auto merge of #18596 : alexcrichton/rust/rollup, r=alexcrichton

Let's see if we can clear out the queue entirely today!
This commit is contained in:
bors 2014-11-04 08:11:53 +00:00
commit 82fb413d37
67 changed files with 1236 additions and 1325 deletions

View file

@ -4467,18 +4467,19 @@ see why consumers matter.
## Iterators
As we've said before, an iterator is something that we can call the `.next()`
method on repeatedly, and it gives us a sequence of things. Because you need
to call the method, this means that iterators are **lazy**. This code, for
example, does not actually generate the numbers `1-100`, and just creates a
value that represents the sequence:
As we've said before, an iterator is something that we can call the
`.next()` method on repeatedly, and it gives us a sequence of things.
Because you need to call the method, this means that iterators
are **lazy** and don't need to generate all of the values upfront.
This code, for example, does not actually generate the numbers
`1-100`, and just creates a value that represents the sequence:
```{rust}
let nums = range(1i, 100i);
```
Since we didn't do anything with the range, it didn't generate the sequence.
Once we add the consumer:
Let's add the consumer:
```{rust}
let nums = range(1i, 100i).collect::<Vec<int>>();
@ -4507,8 +4508,8 @@ std::iter::count(1i, 5i);
```
This iterator counts up from one, adding five each time. It will give
you a new integer every time, forever. Well, technically, until the
maximum number that an `int` can represent. But since iterators are lazy,
you a new integer every time, forever (well, technically, until it reaches the
maximum number representable by an `int`). But since iterators are lazy,
that's okay! You probably don't want to use `collect()` on it, though...
That's enough about iterators. Iterator adapters are the last concept
@ -5251,8 +5252,8 @@ to do something that it can't currently do? You may be able to write a macro
to extend Rust's capabilities.
You've already used one macro extensively: `println!`. When we invoke
a Rust macro, we need to use the exclamation mark (`!`). There's two reasons
that this is true: the first is that it makes it clear when you're using a
a Rust macro, we need to use the exclamation mark (`!`). There are two reasons
why this is so: the first is that it makes it clear when you're using a
macro. The second is that macros allow for flexible syntax, and so Rust must
be able to tell where a macro starts and ends. The `!(...)` helps with this.
@ -5267,7 +5268,7 @@ println!("x is: {}", x);
The `println!` macro does a few things:
1. It parses the string to find any `{}`s
1. It parses the string to find any `{}`s.
2. It checks that the number of `{}`s matches the number of other arguments.
3. It generates a bunch of Rust code, taking this in mind.
@ -5276,8 +5277,8 @@ Rust will generate code that takes all of the types into account. If
`println!` was a function, it could still do this type checking, but it
would happen at run time rather than compile time.
We can check this out using a special flag to `rustc`. This code, in a file
`print.rs`:
We can check this out using a special flag to `rustc`. Put this code in a file
called `print.rs`:
```{rust}
fn main() {
@ -5286,7 +5287,7 @@ fn main() {
}
```
Can have its macros expanded like this: `rustc print.rs --pretty=expanded`, will
You can have the macros expanded like this: `rustc print.rs --pretty=expanded` which will
give us this huge result:
```{rust,ignore}
@ -5325,12 +5326,12 @@ invoke the `println_args` function with the generated arguments.
This is the code that Rust actually compiles. You can see all of the extra
information that's here. We get all of the type safety and options that it
provides, but at compile time, and without needing to type all of this out.
This is how macros are powerful. Without them, you would need to type all of
this by hand to get a type checked `println`.
This is how macros are powerful: without them you would need to type all of
this by hand to get a type-checked `println`.
For more on macros, please consult [the Macros Guide](guide-macros.html).
Macros are a very advanced and still slightly experimental feature, but don't
require a deep understanding to call, since they look just like functions. The
Macros are a very advanced and still slightly experimental feature, but they don't
require a deep understanding to be called, since they look just like functions. The
Guide can help you if you want to write your own.
# Unsafe
@ -5347,8 +5348,8 @@ keyword, which indicates that the function may not behave properly.
Second, if you'd like to create some sort of shared-memory data structure, Rust
won't allow it, because memory must be owned by a single owner. However, if
you're planning on making access to that shared memory safe, such as with a
mutex, _you_ know that it's safe, but Rust can't know. Writing an `unsafe`
you're planning on making access to that shared memory safe such as with a
mutex _you_ know that it's safe, but Rust can't know. Writing an `unsafe`
block allows you to ask the compiler to trust you. In this case, the _internal_
implementation of the mutex is considered unsafe, but the _external_ interface
we present is safe. This allows it to be effectively used in normal Rust, while

View file

@ -831,7 +831,7 @@ mod math {
}
```
Modules and types share the same namespace. Declaring a named type that has
Modules and types share the same namespace. Declaring a named type with
the same name as a module in scope is forbidden: that is, a type definition,
trait, struct, enumeration, or type parameter can't shadow the name of a module
in scope, or vice versa.
@ -870,8 +870,8 @@ view_item : extern_crate_decl | use_decl ;
```
A view item manages the namespace of a module. View items do not define new
items, but rather, simply change other items' visibility. There are several
kinds of view item:
items, but rather, simply change other items' visibility. There are two
kinds of view items:
* [`extern crate` declarations](#extern-crate-declarations)
* [`use` declarations](#use-declarations)
@ -896,7 +896,7 @@ external crate when it was compiled. If no `crateid` is provided, a default
`name` attribute is assumed, equal to the `ident` given in the
`extern_crate_decl`.
Four examples of `extern crate` declarations:
Three examples of `extern crate` declarations:
```{.ignore}
extern crate pcre;

View file

@ -178,14 +178,14 @@ function! s:WithPath(func, ...)
call mkdir(tmpdir)
let save_cwd = getcwd()
silent exe 'lcd' tmpdir
silent exe 'lcd' fnameescape(tmpdir)
let path = 'unnamed.rs'
let save_mod = &mod
set nomod
silent exe 'keepalt write! ' . path
silent exe 'keepalt write! ' . fnameescape(path)
if pathisempty
silent keepalt 0file
endif
@ -195,10 +195,10 @@ function! s:WithPath(func, ...)
call call(a:func, [path] + a:000)
finally
if exists("save_mod") | let &mod = save_mod | endif
if exists("save_write") | let &write = save_write | endif
if exists("save_cwd") | silent exe 'lcd' save_cwd | endif
if exists("tmpdir") | silent call s:RmDir(tmpdir) | endif
if exists("save_mod") | let &mod = save_mod | endif
if exists("save_write") | let &write = save_write | endif
if exists("save_cwd") | silent exe 'lcd' fnameescape(save_cwd) | endif
if exists("tmpdir") | silent call s:RmDir(tmpdir) | endif
endtry
endfunction

View file

@ -276,7 +276,6 @@
#![stable]
use clone::Clone;
use cmp::PartialEq;
use std::fmt::Show;
use slice;

View file

@ -19,7 +19,6 @@
use mem;
use char;
use char::Char;
use clone::Clone;
use cmp;
use cmp::{PartialEq, Eq};
use default::Default;

View file

@ -227,6 +227,13 @@ fn ziggurat<R:Rng>(
// creating a f64), so we might as well reuse some to save
// generating a whole extra random number. (Seems to be 15%
// faster.)
//
// This unfortunately misses out on the benefits of direct
// floating point generation if an RNG like dSMFT is
// used. (That is, such RNGs create floats directly, highly
// efficiently and overload next_f32/f64, so by not calling it
// this may be slower than it would be otherwise.)
// FIXME: investigate/optimise for the above.
let bits: u64 = rng.gen();
let i = (bits & 0xff) as uint;
let f = (bits >> 11) as f64 / SCALE;

View file

@ -78,6 +78,46 @@ fn next_u64(&mut self) -> u64 {
(self.next_u32() as u64 << 32) | (self.next_u32() as u64)
}
/// Return the next random f32 selected from the half-open
/// interval `[0, 1)`.
///
/// By default this is implemented in terms of `next_u32`, but a
/// random number generator which can generate numbers satisfying
/// the requirements directly can overload this for performance.
/// It is required that the return value lies in `[0, 1)`.
///
/// See `Closed01` for the closed interval `[0,1]`, and
/// `Open01` for the open interval `(0,1)`.
fn next_f32(&mut self) -> f32 {
const MANTISSA_BITS: uint = 24;
const IGNORED_BITS: uint = 8;
const SCALE: f32 = (1u64 << MANTISSA_BITS) as f32;
// using any more than `MANTISSA_BITS` bits will
// cause (e.g.) 0xffff_ffff to correspond to 1
// exactly, so we need to drop some (8 for f32, 11
// for f64) to guarantee the open end.
(self.next_u32() >> IGNORED_BITS) as f32 / SCALE
}
/// Return the next random f64 selected from the half-open
/// interval `[0, 1)`.
///
/// By default this is implemented in terms of `next_u64`, but a
/// random number generator which can generate numbers satisfying
/// the requirements directly can overload this for performance.
/// It is required that the return value lies in `[0, 1)`.
///
/// See `Closed01` for the closed interval `[0,1]`, and
/// `Open01` for the open interval `(0,1)`.
fn next_f64(&mut self) -> f64 {
const MANTISSA_BITS: uint = 53;
const IGNORED_BITS: uint = 11;
const SCALE: f64 = (1u64 << MANTISSA_BITS) as f64;
(self.next_u64() >> IGNORED_BITS) as f64 / SCALE
}
/// Fill `dest` with random data.
///
/// This has a default implementation in terms of `next_u64` and

View file

@ -96,11 +96,11 @@ fn rand<R: Rng>(rng: &mut R) -> u64 {
}
macro_rules! float_impls {
($mod_name:ident, $ty:ty, $mantissa_bits:expr, $method_name:ident, $ignored_bits:expr) => {
($mod_name:ident, $ty:ty, $mantissa_bits:expr, $method_name:ident) => {
mod $mod_name {
use {Rand, Rng, Open01, Closed01};
static SCALE: $ty = (1u64 << $mantissa_bits) as $ty;
const SCALE: $ty = (1u64 << $mantissa_bits) as $ty;
impl Rand for $ty {
/// Generate a floating point number in the half-open
@ -110,11 +110,7 @@ impl Rand for $ty {
/// and `Open01` for the open interval `(0,1)`.
#[inline]
fn rand<R: Rng>(rng: &mut R) -> $ty {
// using any more than `mantissa_bits` bits will
// cause (e.g.) 0xffff_ffff to correspond to 1
// exactly, so we need to drop some (8 for f32, 11
// for f64) to guarantee the open end.
(rng.$method_name() >> $ignored_bits) as $ty / SCALE
rng.$method_name()
}
}
impl Rand for Open01<$ty> {
@ -124,23 +120,22 @@ fn rand<R: Rng>(rng: &mut R) -> Open01<$ty> {
// the precision of f64/f32 at 1.0), so that small
// numbers are larger than 0, but large numbers
// aren't pushed to/above 1.
Open01(((rng.$method_name() >> $ignored_bits) as $ty + 0.25) / SCALE)
Open01(rng.$method_name() + 0.25 / SCALE)
}
}
impl Rand for Closed01<$ty> {
#[inline]
fn rand<R: Rng>(rng: &mut R) -> Closed01<$ty> {
// divide by the maximum value of the numerator to
// get a non-zero probability of getting exactly
// 1.0.
Closed01((rng.$method_name() >> $ignored_bits) as $ty / (SCALE - 1.0))
// rescale so that 1.0 - epsilon becomes 1.0
// precisely.
Closed01(rng.$method_name() * SCALE / (SCALE - 1.0))
}
}
}
}
}
float_impls! { f64_rand_impls, f64, 53, next_u64, 11 }
float_impls! { f32_rand_impls, f32, 24, next_u32, 8 }
float_impls! { f64_rand_impls, f64, 53, next_f64 }
float_impls! { f32_rand_impls, f32, 24, next_f32 }
impl Rand for char {
#[inline]

View file

@ -39,7 +39,7 @@
use std::collections::HashMap;
use std::collections::hash_map::{Occupied, Vacant};
use std::slice;
use std::{int, i8, i16, i32, i64, uint, u8, u16, u32, u64, f32, f64};
use std::{i8, i16, i32, i64, u8, u16, u32, u64, f32, f64};
use syntax::abi;
use syntax::ast_map;
use syntax::ast_util::is_shift_binop;
@ -180,19 +180,19 @@ fn check_expr(&mut self, cx: &Context, e: &ast::Expr) {
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)),
ty::ty_int(t) => Some(int_ty_bits(t, cx.sess().targ_cfg.int_type)),
ty::ty_uint(t) => Some(uint_ty_bits(t, cx.sess().targ_cfg.uint_type)),
_ => 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 }
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 },
Ok(const_int(shift)) => { shift as u64 >= bits },
Ok(const_uint(shift)) => { shift >= bits },
_ => { false }
}
};
@ -312,9 +312,9 @@ fn float_ty_range(float_ty: ast::FloatTy) -> (f64, f64) {
}
}
fn int_ty_bits(int_ty: ast::IntTy) -> u64 {
fn int_ty_bits(int_ty: ast::IntTy, target_int_ty: ast::IntTy) -> u64 {
match int_ty {
ast::TyI => int::BITS as u64,
ast::TyI => 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,
@ -322,9 +322,9 @@ fn int_ty_bits(int_ty: ast::IntTy) -> u64 {
}
}
fn uint_ty_bits(uint_ty: ast::UintTy) -> u64 {
fn uint_ty_bits(uint_ty: ast::UintTy, target_uint_ty: ast::UintTy) -> u64 {
match uint_ty {
ast::TyU => uint::BITS as u64,
ast::TyU => 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,

View file

@ -532,7 +532,7 @@ fn with_lint_attrs(&mut self,
}
}
fn visit_ids(&self, f: |&mut ast_util::IdVisitor<Context>|) {
fn visit_ids(&mut self, f: |&mut ast_util::IdVisitor<Context>|) {
let mut v = ast_util::IdVisitor {
operation: self,
pass_through_items: false,
@ -749,7 +749,7 @@ fn visit_attribute(&mut self, attr: &ast::Attribute) {
// Output any lints that were previously added to the session.
impl<'a, 'tcx> IdVisitingOperation for Context<'a, 'tcx> {
fn visit_id(&self, id: ast::NodeId) {
fn visit_id(&mut self, id: ast::NodeId) {
match self.tcx.sess.lints.borrow_mut().pop(&id) {
None => {}
Some(lints) => {

View file

@ -148,7 +148,7 @@ impl astencode_tag {
pub fn from_uint(value : uint) -> Option<astencode_tag> {
let is_a_tag = first_astencode_tag <= value && value <= last_astencode_tag;
if !is_a_tag { None } else {
Some(unsafe { mem::transmute(value) })
Some(unsafe { mem::transmute::<uint, astencode_tag>(value) })
}
}
}
@ -247,4 +247,3 @@ pub struct LinkMeta {
pub const tag_item_generics: uint = 0xa6;
pub const tag_method_ty_generics: uint = 0xa7;

View file

@ -36,7 +36,7 @@
use std::io;
use std::collections::hash_map::HashMap;
use std::rc::Rc;
use std::u64;
use std::str;
use rbml::reader;
use rbml;
use serialize::Decodable;
@ -215,7 +215,9 @@ fn each_reexport(d: rbml::Doc, f: |rbml::Doc| -> bool) -> bool {
fn variant_disr_val(d: rbml::Doc) -> Option<ty::Disr> {
reader::maybe_get_doc(d, tag_disr_val).and_then(|val_doc| {
reader::with_doc_data(val_doc, |data| u64::parse_bytes(data, 10u))
reader::with_doc_data(val_doc, |data| {
str::from_utf8(data).and_then(from_str)
})
})
}

View file

@ -29,7 +29,6 @@
use std::cell::RefCell;
use std::hash::Hash;
use std::hash;
use std::mem;
use std::collections::HashMap;
use syntax::abi;
use syntax::ast::*;
@ -1508,44 +1507,36 @@ fn my_visit_expr(_e: &Expr) { }
fn my_visit_item(i: &Item,
rbml_w: &mut Encoder,
ecx_ptr: *const int,
ecx: &EncodeContext,
index: &mut Vec<entry<i64>>) {
let mut rbml_w = unsafe { rbml_w.unsafe_clone() };
// See above
let ecx: &EncodeContext = unsafe { mem::transmute(ecx_ptr) };
ecx.tcx.map.with_path(i.id, |path| {
encode_info_for_item(ecx, &mut rbml_w, i, index, path, i.vis);
encode_info_for_item(ecx, rbml_w, i, index, path, i.vis);
});
}
fn my_visit_foreign_item(ni: &ForeignItem,
rbml_w: &mut Encoder,
ecx_ptr:*const int,
ecx: &EncodeContext,
index: &mut Vec<entry<i64>>) {
// See above
let ecx: &EncodeContext = unsafe { mem::transmute(ecx_ptr) };
debug!("writing foreign item {}::{}",
ecx.tcx.map.path_to_string(ni.id),
token::get_ident(ni.ident));
let mut rbml_w = unsafe {
rbml_w.unsafe_clone()
};
let abi = ecx.tcx.map.get_foreign_abi(ni.id);
ecx.tcx.map.with_path(ni.id, |path| {
encode_info_for_foreign_item(ecx, &mut rbml_w,
encode_info_for_foreign_item(ecx, rbml_w,
ni, index,
path, abi);
});
}
struct EncodeVisitor<'a,'b:'a> {
struct EncodeVisitor<'a, 'b:'a, 'c:'a, 'tcx:'c> {
rbml_w_for_visit_item: &'a mut Encoder<'b>,
ecx_ptr:*const int,
ecx: &'a EncodeContext<'c,'tcx>,
index: &'a mut Vec<entry<i64>>,
}
impl<'a, 'b, 'v> Visitor<'v> for EncodeVisitor<'a, 'b> {
impl<'a, 'b, 'c, 'tcx, 'v> Visitor<'v> for EncodeVisitor<'a, 'b, 'c, 'tcx> {
fn visit_expr(&mut self, ex: &Expr) {
visit::walk_expr(self, ex);
my_visit_expr(ex);
@ -1554,14 +1545,14 @@ fn visit_item(&mut self, i: &Item) {
visit::walk_item(self, i);
my_visit_item(i,
self.rbml_w_for_visit_item,
self.ecx_ptr,
self.ecx,
self.index);
}
fn visit_foreign_item(&mut self, ni: &ForeignItem) {
visit::walk_foreign_item(self, ni);
my_visit_foreign_item(ni,
self.rbml_w_for_visit_item,
self.ecx_ptr,
self.ecx,
self.index);
}
}
@ -1585,11 +1576,9 @@ fn encode_info_for_items(ecx: &EncodeContext,
syntax::parse::token::special_idents::invalid,
Public);
// See comment in `encode_side_tables_for_ii` in astencode
let ecx_ptr: *const int = unsafe { mem::transmute(ecx) };
visit::walk_crate(&mut EncodeVisitor {
index: &mut index,
ecx_ptr: ecx_ptr,
ecx: ecx,
rbml_w_for_visit_item: &mut *rbml_w,
}, krate);

View file

@ -231,7 +231,6 @@
use std::cmp;
use std::io::fs::PathExtensions;
use std::io;
use std::mem;
use std::ptr;
use std::slice;
use std::string;
@ -287,8 +286,8 @@ pub struct Library {
pub struct ArchiveMetadata {
_archive: ArchiveRO,
// See comments in ArchiveMetadata::new for why this is static
data: &'static [u8],
// points into self._archive
data: *const [u8],
}
pub struct CratePaths {
@ -709,33 +708,21 @@ pub fn note_crate_name(diag: &SpanHandler, name: &str) {
impl ArchiveMetadata {
fn new(ar: ArchiveRO) -> Option<ArchiveMetadata> {
let data: &'static [u8] = {
let data = match ar.read(METADATA_FILENAME) {
Some(data) => data,
None => {
debug!("didn't find '{}' in the archive", METADATA_FILENAME);
return None;
}
};
// This data is actually a pointer inside of the archive itself, but
// we essentially want to cache it because the lookup inside the
// archive is a fairly expensive operation (and it's queried for
// *very* frequently). For this reason, we transmute it to the
// static lifetime to put into the struct. Note that the buffer is
// never actually handed out with a static lifetime, but rather the
// buffer is loaned with the lifetime of this containing object.
// Hence, we're guaranteed that the buffer will never be used after
// this object is dead, so this is a safe operation to transmute and
// store the data as a static buffer.
unsafe { mem::transmute(data) }
let data = match ar.read(METADATA_FILENAME) {
Some(data) => data as *const [u8],
None => {
debug!("didn't find '{}' in the archive", METADATA_FILENAME);
return None;
}
};
Some(ArchiveMetadata {
_archive: ar,
data: data,
})
}
pub fn as_slice<'a>(&'a self) -> &'a [u8] { self.data }
pub fn as_slice<'a>(&'a self) -> &'a [u8] { unsafe { &*self.data } }
}
// Just a small wrapper to time how long reading metadata takes.
@ -798,7 +785,7 @@ fn get_metadata_section_imp(os: abi::Os, filename: &Path) -> Result<MetadataBlob
let csz = llvm::LLVMGetSectionSize(si.llsi) as uint;
let mut found =
Err(format!("metadata not found: '{}'", filename.display()));
let cvbuf: *const u8 = mem::transmute(cbuf);
let cvbuf: *const u8 = cbuf as *const u8;
let vlen = encoder::metadata_encoding_version.len();
debug!("checking {} bytes of metadata-version stamp",
vlen);

View file

@ -23,7 +23,6 @@
use std::rc::Rc;
use std::str;
use std::string::String;
use std::uint;
use syntax::abi;
use syntax::ast;
use syntax::ast::*;
@ -615,12 +614,12 @@ pub fn parse_def_id(buf: &[u8]) -> ast::DefId {
let crate_part = buf[0u..colon_idx];
let def_part = buf[colon_idx + 1u..len];
let crate_num = match uint::parse_bytes(crate_part, 10u) {
let crate_num = match str::from_utf8(crate_part).and_then(from_str::<uint>) {
Some(cn) => cn as ast::CrateNum,
None => panic!("internal error: parse_def_id: crate number expected, found {}",
crate_part)
};
let def_num = match uint::parse_bytes(def_part, 10u) {
let def_num = match str::from_utf8(def_part).and_then(from_str::<uint>) {
Some(dn) => dn as ast::NodeId,
None => panic!("internal error: parse_def_id: id expected, found {}",
def_part)

View file

@ -38,9 +38,7 @@
use syntax::ptr::P;
use syntax;
use libc;
use std::io::Seek;
use std::mem;
use std::rc::Rc;
use rbml::io::SeekableMemWriter;
@ -81,7 +79,7 @@ pub fn encode_inlined_item(ecx: &e::EncodeContext,
e::IIForeignRef(i) => i.id,
e::IITraitItemRef(_, &ast::ProvidedMethod(ref m)) => m.id,
e::IITraitItemRef(_, &ast::RequiredMethod(ref m)) => m.id,
e::IITraitItemRef(_, &ast::TypeTraitItem(ref ti)) => ti.id,
e::IITraitItemRef(_, &ast::TypeTraitItem(ref ti)) => ti.ty_param.id,
e::IIImplItemRef(_, &ast::MethodImplItem(ref m)) => m.id,
e::IIImplItemRef(_, &ast::TypeImplItem(ref ti)) => ti.id,
};
@ -156,7 +154,7 @@ pub fn decode_inlined_item<'tcx>(cdata: &cstore::crate_metadata,
match *ti {
ast::ProvidedMethod(ref m) => m.pe_ident(),
ast::RequiredMethod(ref ty_m) => ty_m.ident,
ast::TypeTraitItem(ref ti) => ti.ident,
ast::TypeTraitItem(ref ti) => ti.ty_param.ident,
}
},
ast::IIImplItem(_, ref m) => {
@ -711,8 +709,9 @@ fn read_vec_per_param_space<T>(&mut self,
{
let types = self.read_to_vec(|this| Ok(f(this))).unwrap();
let selfs = self.read_to_vec(|this| Ok(f(this))).unwrap();
let assocs = self.read_to_vec(|this| Ok(f(this))).unwrap();
let fns = self.read_to_vec(|this| Ok(f(this))).unwrap();
VecPerParamSpace::new(types, selfs, fns)
VecPerParamSpace::new(types, selfs, assocs, fns)
}
fn read_vtable_res_with_key(&mut self,
@ -1122,27 +1121,15 @@ fn id(&mut self, id: ast::NodeId) {
}
}
struct SideTableEncodingIdVisitor<'a,'b:'a> {
ecx_ptr: *const libc::c_void,
new_rbml_w: &'a mut Encoder<'b>,
struct SideTableEncodingIdVisitor<'a, 'b:'a, 'c:'a, 'tcx:'c> {
ecx: &'a e::EncodeContext<'c, 'tcx>,
rbml_w: &'a mut Encoder<'b>,
}
impl<'a,'b> ast_util::IdVisitingOperation for
SideTableEncodingIdVisitor<'a,'b> {
fn visit_id(&self, id: ast::NodeId) {
// Note: this will cause a copy of rbml_w, which is bad as
// it is mutable. But I believe it's harmless since we generate
// balanced EBML.
//
// FIXME(pcwalton): Don't copy this way.
let mut new_rbml_w = unsafe {
self.new_rbml_w.unsafe_clone()
};
// See above
let ecx: &e::EncodeContext = unsafe {
mem::transmute(self.ecx_ptr)
};
encode_side_tables_for_id(ecx, &mut new_rbml_w, id)
impl<'a, 'b, 'c, 'tcx> ast_util::IdVisitingOperation for
SideTableEncodingIdVisitor<'a, 'b, 'c, 'tcx> {
fn visit_id(&mut self, id: ast::NodeId) {
encode_side_tables_for_id(self.ecx, self.rbml_w, id)
}
}
@ -1150,18 +1137,9 @@ fn encode_side_tables_for_ii(ecx: &e::EncodeContext,
rbml_w: &mut Encoder,
ii: &ast::InlinedItem) {
rbml_w.start_tag(c::tag_table as uint);
let mut new_rbml_w = unsafe {
rbml_w.unsafe_clone()
};
// Because the ast visitor uses @IdVisitingOperation, I can't pass in
// ecx directly, but /I/ know that it'll be fine since the lifetime is
// tied to the CrateContext that lives throughout this entire section.
ast_util::visit_ids_for_inlined_item(ii, &SideTableEncodingIdVisitor {
ecx_ptr: unsafe {
mem::transmute(ecx)
},
new_rbml_w: &mut new_rbml_w,
ast_util::visit_ids_for_inlined_item(ii, &mut SideTableEncodingIdVisitor {
ecx: ecx,
rbml_w: rbml_w
});
rbml_w.end_tag();
}

View file

@ -118,7 +118,6 @@
use std::fmt;
use std::io;
use std::mem::transmute;
use std::rc::Rc;
use std::str;
use std::uint;
@ -380,10 +379,7 @@ fn visit_fn(ir: &mut IrMaps,
// swap in a new set of IR maps for this function body:
let mut fn_maps = IrMaps::new(ir.tcx);
unsafe {
debug!("creating fn_maps: {}",
transmute::<&IrMaps, *const IrMaps>(&fn_maps));
}
debug!("creating fn_maps: {}", &fn_maps as *const IrMaps);
for arg in decl.inputs.iter() {
pat_util::pat_bindings(&ir.tcx.def_map,

View file

@ -296,8 +296,8 @@ fn visit_item(&mut self, item: &ast::Item) {
self.exported_items.insert(m.id);
}
ast::TypeTraitItem(ref t) => {
debug!("typedef {}", t.id);
self.exported_items.insert(t.id);
debug!("typedef {}", t.ty_param.id);
self.exported_items.insert(t.ty_param.id);
}
}
}

View file

@ -627,7 +627,10 @@ fn define_module(&self,
sp: Span) {
// Merges the module with the existing type def or creates a new one.
let modifiers = if is_public { PUBLIC } else { DefModifiers::empty() } | IMPORTABLE;
let module_ = Rc::new(Module::new(parent_link, def_id, kind, external,
let module_ = Rc::new(Module::new(parent_link,
def_id,
kind,
external,
is_public));
let type_def = self.type_def.borrow().clone();
match type_def {
@ -1372,6 +1375,8 @@ fn build_reduced_graph_for_item(&mut self,
// Create the module and add all methods.
match ty.node {
TyPath(ref path, _, _) if path.segments.len() == 1 => {
// FIXME(18446) we should distinguish between the name of
// a trait and the name of an impl of that trait.
let mod_name = path.segments.last().unwrap().identifier.name;
let parent_opt = parent.module().children.borrow()
@ -1380,8 +1385,8 @@ fn build_reduced_graph_for_item(&mut self,
// It already exists
Some(ref child) if child.get_module_if_available()
.is_some() &&
child.get_module().kind.get() ==
ImplModuleKind => {
(child.get_module().kind.get() == ImplModuleKind ||
child.get_module().kind.get() == TraitModuleKind) => {
ModuleReducedGraphParent(child.get_module())
}
Some(ref child) if child.get_module_if_available()
@ -1559,19 +1564,19 @@ fn build_reduced_graph_for_item(&mut self,
}
ast::TypeTraitItem(ref associated_type) => {
let def = DefAssociatedTy(local_def(
associated_type.id));
associated_type.ty_param.id));
let name_bindings =
self.add_child(associated_type.ident.name,
self.add_child(associated_type.ty_param.ident.name,
module_parent.clone(),
ForbidDuplicateTypesAndValues,
associated_type.span);
associated_type.ty_param.span);
// NB: not IMPORTABLE
name_bindings.define_type(def,
associated_type.span,
associated_type.ty_param.span,
PUBLIC);
(associated_type.ident.name, TypeTraitItemKind)
(associated_type.ty_param.ident.name, TypeTraitItemKind)
}
};
@ -4218,7 +4223,7 @@ fn resolve_item(&mut self, item: &Item) {
impl_items.as_slice());
}
ItemTrait(ref generics, ref unbound, ref bounds, ref methods) => {
ItemTrait(ref generics, ref unbound, ref bounds, ref trait_items) => {
// Create a new rib for the self type.
let mut self_type_rib = Rib::new(ItemRibKind);
@ -4246,13 +4251,13 @@ fn resolve_item(&mut self, item: &Item) {
_ => {}
}
for method in (*methods).iter() {
// Create a new rib for the method-specific type
for trait_item in (*trait_items).iter() {
// Create a new rib for the trait_item-specific type
// parameters.
//
// FIXME #4951: Do we need a node ID here?
match *method {
match *trait_item {
ast::RequiredMethod(ref ty_m) => {
this.with_type_parameter_rib
(HasTypeParameters(&ty_m.generics,
@ -4287,8 +4292,9 @@ fn resolve_item(&mut self, item: &Item) {
ProvidedMethod(m.id)),
&**m)
}
ast::TypeTraitItem(_) => {
visit::walk_trait_item(this, method);
ast::TypeTraitItem(ref data) => {
this.resolve_type_parameter(&data.ty_param);
visit::walk_trait_item(this, trait_item);
}
}
}
@ -4477,20 +4483,25 @@ fn resolve_function(&mut self,
fn resolve_type_parameters(&mut self,
type_parameters: &OwnedSlice<TyParam>) {
for type_parameter in type_parameters.iter() {
for bound in type_parameter.bounds.iter() {
self.resolve_type_parameter_bound(type_parameter.id, bound,
TraitBoundingTypeParameter);
}
match &type_parameter.unbound {
&Some(ref unbound) =>
self.resolve_type_parameter_bound(
type_parameter.id, unbound, TraitBoundingTypeParameter),
&None => {}
}
match type_parameter.default {
Some(ref ty) => self.resolve_type(&**ty),
None => {}
}
self.resolve_type_parameter(type_parameter);
}
}
fn resolve_type_parameter(&mut self,
type_parameter: &TyParam) {
for bound in type_parameter.bounds.iter() {
self.resolve_type_parameter_bound(type_parameter.id, bound,
TraitBoundingTypeParameter);
}
match &type_parameter.unbound {
&Some(ref unbound) =>
self.resolve_type_parameter_bound(
type_parameter.id, unbound, TraitBoundingTypeParameter),
&None => {}
}
match type_parameter.default {
Some(ref ty) => self.resolve_type(&**ty),
None => {}
}
}
@ -4577,14 +4588,14 @@ fn resolve_trait_reference(&mut self,
self.resolve_error(trait_reference.path.span,
format!("`{}` is not a trait",
self.path_names_to_string(
&trait_reference.path)));
&trait_reference.path)));
// If it's a typedef, give a note
match def {
DefTy(..) => {
self.session.span_note(
trait_reference.path.span,
format!("`type` aliases cannot \
trait_reference.path.span,
format!("`type` aliases cannot \
be used for traits")
.as_slice());
}

View file

@ -31,13 +31,16 @@ impl<'a> SpanUtils<'a> {
pub fn extent_str(&self, span: Span) -> String {
let lo_loc = self.sess.codemap().lookup_char_pos(span.lo);
let hi_loc = self.sess.codemap().lookup_char_pos(span.hi);
let lo_pos = self.sess.codemap().lookup_byte_offset(span.lo).pos;
let hi_pos = self.sess.codemap().lookup_byte_offset(span.hi).pos;
let lo_pos = self.sess.codemap().bytepos_to_file_charpos(span.lo);
let hi_pos = self.sess.codemap().bytepos_to_file_charpos(span.hi);
let lo_pos_byte = self.sess.codemap().lookup_byte_offset(span.lo).pos;
let hi_pos_byte = self.sess.codemap().lookup_byte_offset(span.hi).pos;
format!("file_name,{},file_line,{},file_col,{},extent_start,{},\
file_line_end,{},file_col_end,{},extent_end,{}",
lo_loc.file.name, lo_loc.line, lo_loc.col.to_uint(), lo_pos.to_uint(),
hi_loc.line, hi_loc.col.to_uint(), hi_pos.to_uint())
format!("file_name,{},file_line,{},file_col,{},extent_start,{},extent_start_bytes,{},\
file_line_end,{},file_col_end,{},extent_end,{},extent_end_bytes,{}",
lo_loc.file.name,
lo_loc.line, lo_loc.col.to_uint(), lo_pos.to_uint(), lo_pos_byte.to_uint(),
hi_loc.line, hi_loc.col.to_uint(), hi_pos.to_uint(), hi_pos_byte.to_uint())
}
// sub_span starts at span.lo, so we need to adjust the positions etc.
@ -92,7 +95,7 @@ pub fn span_for_last_ident(&self, span: Span) -> Option<Span> {
let mut toks = self.retokenise_span(span);
let mut bracket_count = 0u;
loop {
let ts = toks.next_token();
let ts = toks.real_token();
if ts.tok == token::Eof {
return self.make_sub_span(span, result)
}
@ -115,7 +118,7 @@ pub fn span_for_first_ident(&self, span: Span) -> Option<Span> {
let mut toks = self.retokenise_span(span);
let mut bracket_count = 0u;
loop {
let ts = toks.next_token();
let ts = toks.real_token();
if ts.tok == token::Eof {
return None;
}
@ -137,13 +140,13 @@ pub fn span_for_first_ident(&self, span: Span) -> Option<Span> {
// any brackets, or the last span.
pub fn sub_span_for_meth_name(&self, span: Span) -> Option<Span> {
let mut toks = self.retokenise_span(span);
let mut prev = toks.next_token();
let mut prev = toks.real_token();
let mut result = None;
let mut bracket_count = 0u;
let mut last_span = None;
while prev.tok != token::Eof {
last_span = None;
let mut next = toks.next_token();
let mut next = toks.real_token();
if (next.tok == token::OpenDelim(token::Paren) ||
next.tok == token::Lt) &&
@ -156,7 +159,7 @@ pub fn sub_span_for_meth_name(&self, span: Span) -> Option<Span> {
next.tok == token::ModSep {
let old = prev;
prev = next;
next = toks.next_token();
next = toks.real_token();
if next.tok == token::Lt &&
old.tok.is_ident() {
result = Some(old.sp);
@ -185,11 +188,11 @@ pub fn sub_span_for_meth_name(&self, span: Span) -> Option<Span> {
// brackets, or the last span.
pub fn sub_span_for_type_name(&self, span: Span) -> Option<Span> {
let mut toks = self.retokenise_span(span);
let mut prev = toks.next_token();
let mut prev = toks.real_token();
let mut result = None;
let mut bracket_count = 0u;
loop {
let next = toks.next_token();
let next = toks.real_token();
if (next.tok == token::Lt ||
next.tok == token::Colon) &&
@ -234,7 +237,7 @@ pub fn spans_with_brackets(&self, span: Span, nesting: int, limit: int) -> Vec<S
// We keep track of how many brackets we're nested in
let mut bracket_count = 0i;
loop {
let ts = toks.next_token();
let ts = toks.real_token();
if ts.tok == token::Eof {
if bracket_count != 0 {
let loc = self.sess.codemap().lookup_char_pos(span.lo);
@ -263,12 +266,12 @@ pub fn spans_with_brackets(&self, span: Span, nesting: int, limit: int) -> Vec<S
pub fn sub_span_before_token(&self, span: Span, tok: Token) -> Option<Span> {
let mut toks = self.retokenise_span(span);
let mut prev = toks.next_token();
let mut prev = toks.real_token();
loop {
if prev.tok == token::Eof {
return None;
}
let next = toks.next_token();
let next = toks.real_token();
if next.tok == tok {
return self.make_sub_span(span, Some(prev.sp));
}
@ -281,15 +284,16 @@ pub fn sub_span_after_keyword(&self,
keyword: keywords::Keyword) -> Option<Span> {
let mut toks = self.retokenise_span(span);
loop {
let ts = toks.next_token();
let ts = toks.real_token();
if ts.tok == token::Eof {
return None;
}
if ts.tok.is_keyword(keyword) {
let ts = toks.next_token();
let ts = toks.real_token();
if ts.tok == token::Eof {
return None
} else {
println!("found keyword: {} at {}", ts, ts.sp);
return self.make_sub_span(span, Some(ts.sp));
}
}

View file

@ -86,7 +86,7 @@ fn visit_trait_item(&mut self, t: &TraitItem) {
}
}
TypeTraitItem(ref typedef) => (typedef.id, &typedef.attrs),
TypeTraitItem(ref typedef) => (typedef.ty_param.id, &typedef.attrs),
};
self.annotate(id, attrs, |v| visit::walk_trait_item(v, t));
}

View file

@ -16,66 +16,10 @@
use util::ppaux::Repr;
use std::fmt;
use std::mem;
use std::raw;
use std::slice::{Items, MutItems};
use std::slice::Items;
use std::vec::Vec;
use syntax::codemap::{Span, DUMMY_SP};
///////////////////////////////////////////////////////////////////////////
// HomogeneousTuple3 trait
//
// This could be moved into standard library at some point.
trait HomogeneousTuple3<T> {
fn len(&self) -> uint;
fn as_slice<'a>(&'a self) -> &'a [T];
fn as_mut_slice<'a>(&'a mut self) -> &'a mut [T];
fn iter<'a>(&'a self) -> Items<'a, T>;
fn iter_mut<'a>(&'a mut self) -> MutItems<'a, T>;
fn get<'a>(&'a self, index: uint) -> Option<&'a T>;
fn get_mut<'a>(&'a mut self, index: uint) -> Option<&'a mut T>;
}
impl<T> HomogeneousTuple3<T> for (T, T, T) {
fn len(&self) -> uint {
3
}
fn as_slice<'a>(&'a self) -> &'a [T] {
unsafe {
let ptr: *const T = mem::transmute(self);
let slice = raw::Slice { data: ptr, len: 3 };
mem::transmute(slice)
}
}
fn as_mut_slice<'a>(&'a mut self) -> &'a mut [T] {
unsafe {
let ptr: *const T = mem::transmute(self);
let slice = raw::Slice { data: ptr, len: 3 };
mem::transmute(slice)
}
}
fn iter<'a>(&'a self) -> Items<'a, T> {
let slice: &'a [T] = self.as_slice();
slice.iter()
}
fn iter_mut<'a>(&'a mut self) -> MutItems<'a, T> {
self.as_mut_slice().iter_mut()
}
fn get<'a>(&'a self, index: uint) -> Option<&'a T> {
self.as_slice().get(index)
}
fn get_mut<'a>(&'a mut self, index: uint) -> Option<&'a mut T> {
Some(&mut self.as_mut_slice()[index]) // wrong: fallible
}
}
///////////////////////////////////////////////////////////////////////////
/**
@ -112,17 +56,18 @@ pub fn new_type(t: Vec<ty::t>,
r: Vec<ty::Region>)
-> Substs
{
Substs::new(VecPerParamSpace::new(t, Vec::new(), Vec::new()),
VecPerParamSpace::new(r, Vec::new(), Vec::new()))
Substs::new(VecPerParamSpace::new(t, Vec::new(), Vec::new(), Vec::new()),
VecPerParamSpace::new(r, Vec::new(), Vec::new(), Vec::new()))
}
pub fn new_trait(t: Vec<ty::t>,
r: Vec<ty::Region>,
a: Vec<ty::t>,
s: ty::t)
-> Substs
{
Substs::new(VecPerParamSpace::new(t, vec!(s), Vec::new()),
VecPerParamSpace::new(r, Vec::new(), Vec::new()))
Substs::new(VecPerParamSpace::new(t, vec!(s), a, Vec::new()),
VecPerParamSpace::new(r, Vec::new(), Vec::new(), Vec::new()))
}
pub fn erased(t: VecPerParamSpace<ty::t>) -> Substs
@ -226,21 +171,23 @@ fn map<A>(self,
#[deriving(PartialOrd, Ord, PartialEq, Eq,
Clone, Hash, Encodable, Decodable, Show)]
pub enum ParamSpace {
TypeSpace, // Type parameters attached to a type definition, trait, or impl
SelfSpace, // Self parameter on a trait
FnSpace, // Type parameters attached to a method or fn
TypeSpace, // Type parameters attached to a type definition, trait, or impl
SelfSpace, // Self parameter on a trait
AssocSpace, // Assoc types defined in a trait/impl
FnSpace, // Type parameters attached to a method or fn
}
impl ParamSpace {
pub fn all() -> [ParamSpace, ..3] {
[TypeSpace, SelfSpace, FnSpace]
pub fn all() -> [ParamSpace, ..4] {
[TypeSpace, SelfSpace, AssocSpace, FnSpace]
}
pub fn to_uint(self) -> uint {
match self {
TypeSpace => 0,
SelfSpace => 1,
FnSpace => 2,
AssocSpace => 2,
FnSpace => 3,
}
}
@ -248,7 +195,8 @@ pub fn from_uint(u: uint) -> ParamSpace {
match u {
0 => TypeSpace,
1 => SelfSpace,
2 => FnSpace,
2 => AssocSpace,
3 => FnSpace,
_ => panic!("Invalid ParamSpace: {}", u)
}
}
@ -268,14 +216,27 @@ pub struct VecPerParamSpace<T> {
// Here is how the representation corresponds to the abstraction
// i.e. the "abstraction function" AF:
//
// AF(self) = (self.content.slice_to(self.type_limit),
// self.content.slice(self.type_limit, self.self_limit),
// self.content.slice_from(self.self_limit))
// AF(self) = (self.content[..self.type_limit],
// self.content[self.type_limit..self.self_limit],
// self.content[self.self_limit..self.assoc_limit],
// self.content[self.assoc_limit..])
type_limit: uint,
self_limit: uint,
assoc_limit: uint,
content: Vec<T>,
}
/**
* The `split` function converts one `VecPerParamSpace` into this
* `SeparateVecsPerParamSpace` structure.
*/
pub struct SeparateVecsPerParamSpace<T> {
pub types: Vec<T>,
pub selfs: Vec<T>,
pub assocs: Vec<T>,
pub fns: Vec<T>,
}
impl<T:fmt::Show> fmt::Show for VecPerParamSpace<T> {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
try!(write!(fmt, "VecPerParamSpace {{"));
@ -292,7 +253,8 @@ fn limits(&self, space: ParamSpace) -> (uint, uint) {
match space {
TypeSpace => (0, self.type_limit),
SelfSpace => (self.type_limit, self.self_limit),
FnSpace => (self.self_limit, self.content.len()),
AssocSpace => (self.self_limit, self.assoc_limit),
FnSpace => (self.assoc_limit, self.content.len()),
}
}
@ -300,6 +262,7 @@ pub fn empty() -> VecPerParamSpace<T> {
VecPerParamSpace {
type_limit: 0,
self_limit: 0,
assoc_limit: 0,
content: Vec::new()
}
}
@ -310,26 +273,33 @@ pub fn params_from_type(types: Vec<T>) -> VecPerParamSpace<T> {
/// `t` is the type space.
/// `s` is the self space.
/// `a` is the assoc space.
/// `f` is the fn space.
pub fn new(t: Vec<T>, s: Vec<T>, f: Vec<T>) -> VecPerParamSpace<T> {
pub fn new(t: Vec<T>, s: Vec<T>, a: Vec<T>, f: Vec<T>) -> VecPerParamSpace<T> {
let type_limit = t.len();
let self_limit = t.len() + s.len();
let self_limit = type_limit + s.len();
let assoc_limit = self_limit + a.len();
let mut content = t;
content.extend(s.into_iter());
content.extend(a.into_iter());
content.extend(f.into_iter());
VecPerParamSpace {
type_limit: type_limit,
self_limit: self_limit,
assoc_limit: assoc_limit,
content: content,
}
}
fn new_internal(content: Vec<T>, type_limit: uint, self_limit: uint)
fn new_internal(content: Vec<T>, type_limit: uint, self_limit: uint, assoc_limit: uint)
-> VecPerParamSpace<T>
{
VecPerParamSpace {
type_limit: type_limit,
self_limit: self_limit,
assoc_limit: assoc_limit,
content: content,
}
}
@ -341,9 +311,10 @@ fn new_internal(content: Vec<T>, type_limit: uint, self_limit: uint)
pub fn push(&mut self, space: ParamSpace, value: T) {
let (_, limit) = self.limits(space);
match space {
TypeSpace => { self.type_limit += 1; self.self_limit += 1; }
SelfSpace => { self.self_limit += 1; }
FnSpace => {}
TypeSpace => { self.type_limit += 1; self.self_limit += 1; self.assoc_limit += 1; }
SelfSpace => { self.self_limit += 1; self.assoc_limit += 1; }
AssocSpace => { self.assoc_limit += 1; }
FnSpace => { }
}
self.content.insert(limit, value);
}
@ -354,9 +325,10 @@ pub fn pop(&mut self, space: ParamSpace) -> Option<T> {
None
} else {
match space {
TypeSpace => { self.type_limit -= 1; self.self_limit -= 1; }
SelfSpace => { self.self_limit -= 1; }
FnSpace => {}
TypeSpace => { self.type_limit -= 1; self.self_limit -= 1; self.assoc_limit -= 1; }
SelfSpace => { self.self_limit -= 1; self.assoc_limit -= 1; }
AssocSpace => { self.assoc_limit -= 1; }
FnSpace => {}
}
self.content.remove(limit - 1)
}
@ -442,35 +414,35 @@ pub fn map<U>(&self, pred: |&T| -> U) -> VecPerParamSpace<U> {
let result = self.iter().map(pred).collect();
VecPerParamSpace::new_internal(result,
self.type_limit,
self.self_limit)
self.self_limit,
self.assoc_limit)
}
pub fn map_move<U>(self, pred: |T| -> U) -> VecPerParamSpace<U> {
let (t, s, f) = self.split();
let SeparateVecsPerParamSpace {
types: t,
selfs: s,
assocs: a,
fns: f
} = self.split();
VecPerParamSpace::new(t.into_iter().map(|p| pred(p)).collect(),
s.into_iter().map(|p| pred(p)).collect(),
a.into_iter().map(|p| pred(p)).collect(),
f.into_iter().map(|p| pred(p)).collect())
}
pub fn split(self) -> (Vec<T>, Vec<T>, Vec<T>) {
// FIXME (#15418): this does two traversals when in principle
// one would suffice. i.e. change to use `move_iter`.
let VecPerParamSpace { type_limit, self_limit, content } = self;
let mut i = 0;
let (prefix, fn_vec) = content.partition(|_| {
let on_left = i < self_limit;
i += 1;
on_left
});
pub fn split(self) -> SeparateVecsPerParamSpace<T> {
let VecPerParamSpace { type_limit, self_limit, assoc_limit, content } = self;
let mut i = 0;
let (type_vec, self_vec) = prefix.partition(|_| {
let on_left = i < type_limit;
i += 1;
on_left
});
let mut content_iter = content.into_iter();
(type_vec, self_vec, fn_vec)
SeparateVecsPerParamSpace {
types: content_iter.by_ref().take(type_limit).collect(),
selfs: content_iter.by_ref().take(self_limit - type_limit).collect(),
assocs: content_iter.by_ref().take(assoc_limit - self_limit).collect(),
fns: content_iter.collect()
}
}
pub fn with_vec(mut self, space: ParamSpace, vec: Vec<T>)
@ -616,12 +588,13 @@ fn check(this: &SubstFolder,
this.tcx().sess.span_bug(
span,
format!("Type parameter `{}` ({}/{}/{}) out of range \
when substituting (root type={})",
when substituting (root type={}) substs={}",
p.repr(this.tcx()),
source_ty.repr(this.tcx()),
space,
index,
this.root_ty.repr(this.tcx())).as_slice());
this.root_ty.repr(this.tcx()),
this.substs.repr(this.tcx())).as_slice());
}
}
}

View file

@ -514,7 +514,7 @@ pub fn evaluate_method_obligation(&mut self,
// and `Rc<Baz>`. (Note that it is not a *coherence violation*
// to have impls for both `Bar` and `Baz`, despite this
// ambiguity). In this case, we report an error, listing all
// the applicable impls. The use can explicitly "up-coerce"
// the applicable impls. The user can explicitly "up-coerce"
// to the type they want.
//
// Note that this coercion step only considers actual impls
@ -1618,7 +1618,8 @@ fn vtable_builtin_data(&mut self,
Ok(o) => o,
Err(ErrorReported) => Vec::new()
};
let obligations = VecPerParamSpace::new(obligations, Vec::new(), Vec::new());
let obligations = VecPerParamSpace::new(obligations, Vec::new(),
Vec::new(), Vec::new());
VtableBuiltinData { nested: obligations }
}
@ -1693,6 +1694,7 @@ fn confirm_unboxed_closure_candidate(&mut self,
vec![arguments_tuple.subst(self.tcx(), substs),
new_signature.output.unwrap().subst(self.tcx(), substs)],
vec![],
vec![],
obligation.self_ty())
});
@ -1942,7 +1944,7 @@ fn push_stack<'o,'s:'o>(&mut self,
fn all_impls(&self, trait_def_id: ast::DefId) -> Vec<ast::DefId> {
/*!
* Returns se tof all impls for a given trait.
* Returns set of all impls for a given trait.
*/
ty::populate_implementations_for_trait_if_necessary(self.tcx(),

View file

@ -205,7 +205,12 @@ pub fn trans_static_method_callee(bcx: Block,
// type parameters that belong to the trait but also some that
// belong to the method:
let rcvr_substs = node_id_substs(bcx, ExprId(expr_id));
let (rcvr_type, rcvr_self, rcvr_method) = rcvr_substs.types.split();
let subst::SeparateVecsPerParamSpace {
types: rcvr_type,
selfs: rcvr_self,
assocs: rcvr_assoc,
fns: rcvr_method
} = rcvr_substs.types.split();
// Lookup the precise impl being called. To do that, we need to
// create a trait reference identifying the self type and other
@ -232,6 +237,7 @@ pub fn trans_static_method_callee(bcx: Block,
let trait_substs =
Substs::erased(VecPerParamSpace::new(rcvr_type,
rcvr_self,
rcvr_assoc,
Vec::new()));
debug!("trait_substs={}", trait_substs.repr(bcx.tcx()));
let trait_ref = Rc::new(ty::TraitRef { def_id: trait_id,
@ -265,10 +271,16 @@ pub fn trans_static_method_callee(bcx: Block,
// that with the `rcvr_method` from before, which tells us
// the type parameters from the *method*, to yield
// `callee_substs=[[T=int],[],[U=String]]`.
let (impl_type, impl_self, _) = impl_substs.types.split();
let subst::SeparateVecsPerParamSpace {
types: impl_type,
selfs: impl_self,
assocs: impl_assoc,
fns: _
} = impl_substs.types.split();
let callee_substs =
Substs::erased(VecPerParamSpace::new(impl_type,
impl_self,
impl_assoc,
rcvr_method));
let mth_id = method_with_name(ccx, impl_did, mname);
@ -397,12 +409,17 @@ fn combine_impl_and_methods_tps(bcx: Block,
// Break apart the type parameters from the node and type
// parameters from the receiver.
let (_, _, node_method) = node_substs.types.split();
let (rcvr_type, rcvr_self, rcvr_method) = rcvr_substs.types.clone().split();
let node_method = node_substs.types.split().fns;
let subst::SeparateVecsPerParamSpace {
types: rcvr_type,
selfs: rcvr_self,
assocs: rcvr_assoc,
fns: rcvr_method
} = rcvr_substs.types.clone().split();
assert!(rcvr_method.is_empty());
subst::Substs {
regions: subst::ErasedRegions,
types: subst::VecPerParamSpace::new(rcvr_type, rcvr_self, node_method)
types: subst::VecPerParamSpace::new(rcvr_type, rcvr_self, rcvr_assoc, node_method)
}
}

View file

@ -27,6 +27,7 @@
use libc::c_uint;
#[deriving(Clone, PartialEq, Show)]
#[repr(C)]
pub struct Type {
rf: TypeRef
}
@ -283,9 +284,10 @@ pub fn field_types(&self) -> Vec<Type> {
if n_elts == 0 {
return Vec::new();
}
let mut elts = Vec::from_elem(n_elts, 0 as TypeRef);
llvm::LLVMGetStructElementTypes(self.to_ref(), &mut elts[0]);
mem::transmute(elts)
let mut elts = Vec::from_elem(n_elts, Type { rf: 0 as TypeRef });
llvm::LLVMGetStructElementTypes(self.to_ref(),
elts.as_mut_ptr() as *mut TypeRef);
elts
}
}
@ -296,9 +298,10 @@ pub fn return_type(&self) -> Type {
pub fn func_params(&self) -> Vec<Type> {
unsafe {
let n_args = llvm::LLVMCountParamTypes(self.to_ref()) as uint;
let args = Vec::from_elem(n_args, 0 as TypeRef);
llvm::LLVMGetParamTypes(self.to_ref(), args.as_ptr());
mem::transmute(args)
let mut args = Vec::from_elem(n_args, Type { rf: 0 as TypeRef });
llvm::LLVMGetParamTypes(self.to_ref(),
args.as_mut_ptr() as *mut TypeRef);
args
}
}

View file

@ -573,10 +573,6 @@ pub struct ctxt<'tcx> {
/// Maps def IDs to true if and only if they're associated types.
pub associated_types: RefCell<DefIdMap<bool>>,
/// Maps def IDs of traits to information about their associated types.
pub trait_associated_types:
RefCell<DefIdMap<Rc<Vec<AssociatedTypeInfo>>>>,
/// Caches the results of trait selection. This cache is used
/// for things that do not have to do with the parameters in scope.
pub selection_cache: traits::SelectionCache,
@ -1564,7 +1560,6 @@ pub fn mk_ctxt<'tcx>(s: Session,
stability: RefCell::new(stability),
capture_modes: capture_modes,
associated_types: RefCell::new(DefIdMap::new()),
trait_associated_types: RefCell::new(DefIdMap::new()),
selection_cache: traits::SelectionCache::new(),
repr_hint_cache: RefCell::new(DefIdMap::new()),
}
@ -1994,6 +1989,16 @@ pub fn is_noop(&self) -> bool {
}
}
impl ParamBounds {
pub fn empty() -> ParamBounds {
ParamBounds {
builtin_bounds: empty_builtin_bounds(),
trait_bounds: Vec::new(),
region_bounds: Vec::new(),
}
}
}
// Type utilities
pub fn type_is_nil(ty: t) -> bool {
@ -4155,18 +4160,6 @@ fn cmp(&self, other: &AssociatedTypeInfo) -> Ordering {
}
}
/// Returns the associated types belonging to the given trait, in parameter
/// order.
pub fn associated_types_for_trait(cx: &ctxt, trait_id: ast::DefId)
-> Rc<Vec<AssociatedTypeInfo>> {
cx.trait_associated_types
.borrow()
.find(&trait_id)
.expect("associated_types_for_trait(): trait not found, try calling \
ensure_associated_types()")
.clone()
}
pub fn trait_item_def_ids(cx: &ctxt, id: ast::DefId)
-> Rc<Vec<ImplOrTraitItemId>> {
lookup_locally_or_in_crate_store("trait_item_def_ids",

View file

@ -54,7 +54,7 @@
use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem};
use middle::lang_items::{FnOnceTraitLangItem};
use middle::resolve_lifetime as rl;
use middle::subst::{FnSpace, TypeSpace, SelfSpace, Subst, Substs};
use middle::subst::{FnSpace, TypeSpace, AssocSpace, SelfSpace, Subst, Substs};
use middle::subst::{VecPerParamSpace};
use middle::ty;
use middle::typeck::lookup_def_tcx;
@ -215,7 +215,8 @@ fn ast_path_substs<'tcx,AC,RS>(
associated_ty: Option<ty::t>,
path: &ast::Path)
-> Substs
where AC: AstConv<'tcx>, RS: RegionScope {
where AC: AstConv<'tcx>, RS: RegionScope
{
/*!
* Given a path `path` that refers to an item `I` with the
* declared generics `decl_generics`, returns an appropriate
@ -338,17 +339,21 @@ fn ast_path_substs<'tcx,AC,RS>(
substs.types.push(TypeSpace, default);
}
None => {
// This is an associated type.
substs.types.push(
TypeSpace,
this.associated_type_binding(path.span,
associated_ty,
decl_def_id,
param.def_id))
tcx.sess.span_bug(path.span,
"extra parameter without default");
}
}
}
for param in decl_generics.types.get_slice(AssocSpace).iter() {
substs.types.push(
AssocSpace,
this.associated_type_binding(path.span,
associated_ty,
decl_def_id,
param.def_id))
}
substs
}
@ -628,9 +633,13 @@ fn mk_pointer<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
a_seq_ty: &ast::Ty,
ptr_ty: PointerTy,
constr: |ty::t| -> ty::t)
-> ty::t {
-> ty::t
{
let tcx = this.tcx();
debug!("mk_pointer(ptr_ty={})", ptr_ty);
debug!("mk_pointer(ptr_ty={}, a_seq_ty={})",
ptr_ty,
a_seq_ty.repr(tcx));
match a_seq_ty.node {
ast::TyVec(ref ty) => {
@ -730,7 +739,13 @@ fn associated_ty_to_ty<'tcx,AC,RS>(this: &AC,
trait_type_id: ast::DefId,
span: Span)
-> ty::t
where AC: AstConv<'tcx>, RS: RegionScope {
where AC: AstConv<'tcx>, RS: RegionScope
{
debug!("associated_ty_to_ty(trait_path={}, for_ast_type={}, trait_type_id={})",
trait_path.repr(this.tcx()),
for_ast_type.repr(this.tcx()),
trait_type_id.repr(this.tcx()));
// Find the trait that this associated type belongs to.
let trait_did = match ty::impl_or_trait_item(this.tcx(),
trait_type_id).container() {
@ -757,9 +772,16 @@ fn associated_ty_to_ty<'tcx,AC,RS>(this: &AC,
None,
Some(for_type),
trait_path);
debug!("associated_ty_to_ty(trait_ref={})",
trait_ref.repr(this.tcx()));
let trait_def = this.get_trait_def(trait_did);
for type_parameter in trait_def.generics.types.iter() {
if type_parameter.def_id == trait_type_id {
debug!("associated_ty_to_ty(type_parameter={} substs={})",
type_parameter.repr(this.tcx()),
trait_ref.substs.repr(this.tcx()));
return *trait_ref.substs.types.get(type_parameter.space,
type_parameter.index)
}
@ -772,7 +794,10 @@ fn associated_ty_to_ty<'tcx,AC,RS>(this: &AC,
// Parses the programmer's textual representation of a type into our
// internal notion of a type.
pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
this: &AC, rscope: &RS, ast_ty: &ast::Ty) -> ty::t {
this: &AC, rscope: &RS, ast_ty: &ast::Ty) -> ty::t
{
debug!("ast_ty_to_ty(ast_ty={})",
ast_ty.repr(this.tcx()));
let tcx = this.tcx();

View file

@ -2536,7 +2536,7 @@ fn check_argument_types<'a>(fcx: &FnCtxt,
span_err!(tcx.sess, sp, E0059,
"cannot use call notation; the first type parameter \
for the function trait is neither a tuple nor unit");
err_args(supplied_arg_count)
err_args(args.len())
}
}
} else if expected_arg_count == supplied_arg_count {

View file

@ -207,8 +207,8 @@ fn check_implementation(&self,
let impl_items = self.create_impl_from_item(item);
for associated_trait in associated_traits.iter() {
let trait_ref = ty::node_id_to_trait_ref(
self.crate_context.tcx, associated_trait.ref_id);
let trait_ref = ty::node_id_to_trait_ref(self.crate_context.tcx,
associated_trait.ref_id);
debug!("(checking implementation) adding impl for trait '{}', item '{}'",
trait_ref.repr(self.crate_context.tcx),
token::get_ident(item.ident));

View file

@ -41,7 +41,8 @@ fn visit_item(&mut self, item: &'v ast::Item) {
let self_ty = ty::lookup_item_type(self.tcx, def_id).ty;
match ty::get(self_ty).sty {
ty::ty_enum(def_id, _) |
ty::ty_struct(def_id, _) => {
ty::ty_struct(def_id, _) |
ty::ty_trait(box ty::TyTrait{ def_id, ..}) => {
if def_id.krate != ast::LOCAL_CRATE {
span_err!(self.tcx.sess, item.span, E0116,
"cannot associate methods with a type outside the \

View file

@ -298,13 +298,19 @@ fn collect_trait_methods(ccx: &CrateCtxt,
&*m.pe_fn_decl())
}
ast::TypeTraitItem(ref at) => {
tcx.sess.span_bug(at.span,
tcx.sess.span_bug(at.ty_param.span,
"there shouldn't \
be a type trait \
item here")
}
});
debug!("ty_method_of_trait_method yielded {} \
for method {} of trait {}",
ty_method.repr(ccx.tcx),
trait_item.repr(ccx.tcx),
local_def(trait_id).repr(ccx.tcx));
make_method_ty(ccx, &*ty_method);
tcx.impl_or_trait_items
@ -315,9 +321,9 @@ fn collect_trait_methods(ccx: &CrateCtxt,
ast::TypeTraitItem(ref ast_associated_type) => {
let trait_did = local_def(trait_id);
let associated_type = ty::AssociatedType {
name: ast_associated_type.ident.name,
name: ast_associated_type.ty_param.ident.name,
vis: ast::Public,
def_id: local_def(ast_associated_type.id),
def_id: local_def(ast_associated_type.ty_param.id),
container: TraitContainer(trait_did),
};
@ -345,7 +351,7 @@ fn collect_trait_methods(ccx: &CrateCtxt,
method.id))
}
ast::TypeTraitItem(ref typedef) => {
ty::TypeTraitItemId(local_def(typedef.id))
ty::TypeTraitItemId(local_def(typedef.ty_param.id))
}
}
}).collect());
@ -460,35 +466,35 @@ fn convert_associated_type(ccx: &CrateCtxt,
// associated type.
let type_parameter_def = trait_def.generics
.types
.get_slice(subst::TypeSpace)
.get_slice(subst::AssocSpace)
.iter()
.find(|def| {
def.def_id == local_def(associated_type.id)
def.def_id == local_def(associated_type.ty_param.id)
});
let type_parameter_def = match type_parameter_def {
Some(type_parameter_def) => type_parameter_def,
None => {
ccx.tcx().sess.span_bug(associated_type.span,
ccx.tcx().sess.span_bug(associated_type.ty_param.span,
"`convert_associated_type()` didn't find \
a type parameter ID corresponding to \
this type")
}
};
let param_type = ty::mk_param(ccx.tcx,
subst::TypeSpace,
type_parameter_def.space,
type_parameter_def.index,
local_def(associated_type.id));
ccx.tcx.tcache.borrow_mut().insert(local_def(associated_type.id),
local_def(associated_type.ty_param.id));
ccx.tcx.tcache.borrow_mut().insert(local_def(associated_type.ty_param.id),
Polytype {
generics: ty::Generics::empty(),
ty: param_type,
});
write_ty_to_tcx(ccx.tcx, associated_type.id, param_type);
write_ty_to_tcx(ccx.tcx, associated_type.ty_param.id, param_type);
let associated_type = Rc::new(ty::AssociatedType {
name: associated_type.ident.name,
name: associated_type.ty_param.ident.name,
vis: ast::Public,
def_id: local_def(associated_type.id),
def_id: local_def(associated_type.ty_param.id),
container: TraitContainer(trait_def.trait_ref.def_id),
});
ccx.tcx
@ -780,25 +786,18 @@ fn associated_type_binding(&self,
ty: Option<ty::t>,
trait_id: ast::DefId,
associated_type_id: ast::DefId)
-> ty::t {
ensure_associated_types(self, trait_id);
let associated_type_ids = ty::associated_types_for_trait(self.ccx.tcx,
trait_id);
-> ty::t
{
let trait_def = ty::lookup_trait_def(self.tcx(), trait_id);
match self.opt_trait_ref_id {
Some(trait_ref_id) if trait_ref_id == trait_id => {
// It's an associated type on the trait that we're
// implementing.
let associated_type_id =
associated_type_ids.iter()
.find(|id| {
id.def_id == associated_type_id
})
.expect("associated_type_binding(): \
expected associated type ID \
in trait");
let associated_type =
ty::impl_or_trait_item(self.ccx.tcx,
associated_type_id.def_id);
assert!(trait_def.generics.types
.get_slice(subst::AssocSpace)
.iter()
.any(|type_param_def| type_param_def.def_id == associated_type_id));
let associated_type = ty::impl_or_trait_item(self.ccx.tcx, associated_type_id);
for impl_item in self.impl_items.iter() {
match *impl_item {
ast::MethodImplItem(_) => {}
@ -978,9 +977,9 @@ fn associated_type_binding(&self,
match *item {
ast::RequiredMethod(_) | ast::ProvidedMethod(_) => {}
ast::TypeTraitItem(ref item) => {
if local_def(item.id) == associated_type_id {
if local_def(item.ty_param.id) == associated_type_id {
return ty::mk_param(self.tcx(),
subst::TypeSpace,
subst::AssocSpace,
index,
associated_type_id)
}
@ -1451,7 +1450,8 @@ fn mk_trait_substs(ccx: &CrateCtxt,
trait_id: ast::NodeId,
generics: &ast::Generics,
items: &[ast::TraitItem])
-> subst::Substs {
-> subst::Substs
{
// Creates a no-op substitution for the trait's type parameters.
let regions =
generics.lifetimes
@ -1464,7 +1464,7 @@ fn mk_trait_substs(ccx: &CrateCtxt,
.collect();
// Start with the generics in the type parameters...
let mut types: Vec<_> =
let types: Vec<_> =
generics.ty_params
.iter()
.enumerate()
@ -1472,24 +1472,27 @@ fn mk_trait_substs(ccx: &CrateCtxt,
i, local_def(def.id)))
.collect();
// ...and add generics synthesized from the associated types.
for item in items.iter() {
match *item {
// ...and also create generics synthesized from the associated types.
let assoc_types: Vec<_> =
items.iter()
.flat_map(|item| match *item {
ast::TypeTraitItem(ref trait_item) => {
let index = types.len();
types.push(ty::mk_param(ccx.tcx,
subst::TypeSpace,
index,
local_def(trait_item.id)))
Some(ty::mk_param(ccx.tcx,
subst::AssocSpace,
index,
local_def(trait_item.ty_param.id))).into_iter()
}
ast::RequiredMethod(_) | ast::ProvidedMethod(_) => {}
}
}
ast::RequiredMethod(_) | ast::ProvidedMethod(_) => {
None.into_iter()
}
})
.collect();
let self_ty =
ty::mk_param(ccx.tcx, subst::SelfSpace, 0, local_def(trait_id));
subst::Substs::new_trait(types, regions, self_ty)
subst::Substs::new_trait(types, regions, assoc_types, self_ty)
}
}
@ -1630,11 +1633,11 @@ fn ty_of_trait_item(ccx: &CrateCtxt, trait_item: &ast::TraitItem)
"ty_of_trait_item() on provided method")
}
ast::TypeTraitItem(ref associated_type) => {
let parent = ccx.tcx.map.get_parent(associated_type.id);
let parent = ccx.tcx.map.get_parent(associated_type.ty_param.id);
let trait_def = match ccx.tcx.map.get(parent) {
ast_map::NodeItem(item) => trait_def_of_item(ccx, &*item),
_ => {
ccx.tcx.sess.span_bug(associated_type.span,
ccx.tcx.sess.span_bug(associated_type.ty_param.span,
"associated type's parent wasn't \
an item?!")
}
@ -1661,38 +1664,33 @@ fn ty_generics_for_type(ccx: &CrateCtxt,
fn ty_generics_for_trait(ccx: &CrateCtxt,
trait_id: ast::NodeId,
substs: &subst::Substs,
generics: &ast::Generics,
ast_generics: &ast::Generics,
items: &[ast::TraitItem])
-> ty::Generics {
let mut generics =
ty_generics(ccx,
subst::TypeSpace,
generics.lifetimes.as_slice(),
generics.ty_params.as_slice(),
ast_generics.lifetimes.as_slice(),
ast_generics.ty_params.as_slice(),
ty::Generics::empty(),
&generics.where_clause,
&ast_generics.where_clause,
DontCreateTypeParametersForAssociatedTypes);
// Add in type parameters for any associated types.
for item in items.iter() {
match *item {
ast::TypeTraitItem(ref associated_type) => {
let def = ty::TypeParameterDef {
space: subst::TypeSpace,
index: generics.types.len(subst::TypeSpace),
name: associated_type.ident.name,
def_id: local_def(associated_type.id),
bounds: ty::ParamBounds {
builtin_bounds: ty::empty_builtin_bounds(),
trait_bounds: Vec::new(),
region_bounds: Vec::new(),
},
associated_with: Some(local_def(trait_id)),
default: None,
};
ccx.tcx.ty_param_defs.borrow_mut().insert(associated_type.id,
let def =
get_or_create_type_parameter_def(
ccx,
subst::AssocSpace,
&associated_type.ty_param,
generics.types.len(subst::TypeSpace),
&ast_generics.where_clause,
Some(local_def(trait_id)));
ccx.tcx.ty_param_defs.borrow_mut().insert(associated_type.ty_param.id,
def.clone());
generics.types.push(subst::TypeSpace, def);
generics.types.push(subst::AssocSpace, def);
}
ast::ProvidedMethod(_) | ast::RequiredMethod(_) => {}
}
@ -1791,86 +1789,17 @@ enum CreateTypeParametersForAssociatedTypesFlag {
CreateTypeParametersForAssociatedTypes,
}
fn ensure_associated_types<'tcx,AC>(this: &AC, trait_id: ast::DefId)
where AC: AstConv<'tcx> {
if this.tcx().trait_associated_types.borrow().contains_key(&trait_id) {
return
}
if trait_id.krate == ast::LOCAL_CRATE {
match this.tcx().map.find(trait_id.node) {
Some(ast_map::NodeItem(item)) => {
match item.node {
ast::ItemTrait(_, _, _, ref trait_items) => {
let mut result = Vec::new();
let mut index = 0;
for trait_item in trait_items.iter() {
match *trait_item {
ast::RequiredMethod(_) |
ast::ProvidedMethod(_) => {}
ast::TypeTraitItem(ref associated_type) => {
let info = ty::AssociatedTypeInfo {
def_id: local_def(associated_type.id),
index: index,
name: associated_type.ident.name,
};
result.push(info);
index += 1;
}
}
}
this.tcx()
.trait_associated_types
.borrow_mut()
.insert(trait_id, Rc::new(result));
return
}
_ => {
this.tcx().sess.bug("ensure_associated_types() \
called on non-trait")
}
}
}
_ => {
this.tcx().sess.bug("ensure_associated_types() called on \
non-trait")
}
}
}
// Cross-crate case.
let mut result = Vec::new();
let mut index = 0;
let trait_items = ty::trait_items(this.tcx(), trait_id);
for trait_item in trait_items.iter() {
match *trait_item {
ty::MethodTraitItem(_) => {}
ty::TypeTraitItem(ref associated_type) => {
let info = ty::AssociatedTypeInfo {
def_id: associated_type.def_id,
index: index,
name: associated_type.name
};
result.push(info);
index += 1;
}
}
}
this.tcx().trait_associated_types.borrow_mut().insert(trait_id,
Rc::new(result));
}
fn ty_generics<'tcx,AC>(this: &AC,
space: subst::ParamSpace,
lifetime_defs: &[ast::LifetimeDef],
types: &[ast::TyParam],
base_generics: ty::Generics,
where_clause: &ast::WhereClause,
create_type_parameters_for_associated_types:
create_type_parameters_for_associated_types_flag:
CreateTypeParametersForAssociatedTypesFlag)
-> ty::Generics
where AC: AstConv<'tcx> {
where AC: AstConv<'tcx>
{
let mut result = base_generics;
for (i, l) in lifetime_defs.iter().enumerate() {
@ -1891,62 +1820,11 @@ fn ty_generics<'tcx,AC>(this: &AC,
// First, create the virtual type parameters for associated types if
// necessary.
let mut associated_types_generics = ty::Generics::empty();
match create_type_parameters_for_associated_types {
match create_type_parameters_for_associated_types_flag {
DontCreateTypeParametersForAssociatedTypes => {}
CreateTypeParametersForAssociatedTypes => {
let mut index = 0;
for param in types.iter() {
for bound in param.bounds.iter() {
match *bound {
ast::TraitTyParamBound(ref trait_bound) => {
match lookup_def_tcx(this.tcx(),
trait_bound.path.span,
trait_bound.ref_id) {
def::DefTrait(trait_did) => {
ensure_associated_types(this, trait_did);
let associated_types =
ty::associated_types_for_trait(
this.tcx(),
trait_did);
for associated_type_info in
associated_types.iter() {
let associated_type_trait_item =
ty::impl_or_trait_item(
this.tcx(),
associated_type_info.def_id);
let def = ty::TypeParameterDef {
name: associated_type_trait_item.name(),
def_id: associated_type_info.def_id,
space: space,
index: types.len() + index,
bounds: ty::ParamBounds {
builtin_bounds:
ty::empty_builtin_bounds(),
trait_bounds: Vec::new(),
region_bounds: Vec::new(),
},
associated_with: {
Some(local_def(param.id))
},
default: None,
};
associated_types_generics.types
.push(space,
def);
index += 1;
}
}
_ => {
this.tcx().sess.span_bug(trait_bound.path
.span,
"not a trait?!")
}
}
}
_ => {}
}
}
}
create_type_parameters_for_associated_types(this, space, types,
&mut associated_types_generics);
}
}
@ -1960,7 +1838,8 @@ fn ty_generics<'tcx,AC>(this: &AC,
space,
param,
i,
where_clause);
where_clause,
None);
debug!("ty_generics: def for type param: {}, {}",
def.repr(this.tcx()),
space);
@ -1981,62 +1860,140 @@ fn ty_generics<'tcx,AC>(this: &AC,
return result;
fn get_or_create_type_parameter_def<'tcx,AC>(
this: &AC,
space: subst::ParamSpace,
param: &ast::TyParam,
index: uint,
where_clause: &ast::WhereClause)
-> ty::TypeParameterDef
where AC: AstConv<'tcx> {
match this.tcx().ty_param_defs.borrow().find(&param.id) {
Some(d) => { return (*d).clone(); }
None => { }
fn create_type_parameters_for_associated_types<'tcx,AC>(
this: &AC,
space: subst::ParamSpace,
types: &[ast::TyParam],
associated_types_generics: &mut ty::Generics)
where AC: AstConv<'tcx>
{
// The idea here is roughly as follows. We start with
// an item that is paramerized by various type parameters
// with bounds:
//
// fn foo<T:Iterator>(t: T) { ... }
//
// The traits in those bounds declare associated types:
//
// trait Iterator { type Elem; ... }
//
// And we rewrite the original function so that every associated
// type is bound to some fresh type parameter:
//
// fn foo<A,T:Iterator<Elem=A>>(t: T) { ... }
// Number of synthetic type parameters created thus far
let mut index = 0;
// Iterate over the each type parameter `T` (from the example)
for param in types.iter() {
// Iterate over the bound `Iterator`
for bound in param.bounds.iter() {
// In the above example, `ast_trait_ref` is `Iterator`.
let ast_trait_ref = match *bound {
ast::TraitTyParamBound(ref r) => r,
ast::UnboxedFnTyParamBound(..) => { continue; }
ast::RegionTyParamBound(..) => { continue; }
};
let trait_def_id =
match lookup_def_tcx(this.tcx(),
ast_trait_ref.path.span,
ast_trait_ref.ref_id) {
def::DefTrait(trait_def_id) => trait_def_id,
_ => {
this.tcx().sess.span_bug(ast_trait_ref.path.span,
"not a trait?!")
}
};
// trait_def_id is def-id of `Iterator`
let trait_def = ty::lookup_trait_def(this.tcx(), trait_def_id);
let associated_type_defs = trait_def.generics.types.get_slice(subst::AssocSpace);
// Iterate over each associated type `Elem`
for associated_type_def in associated_type_defs.iter() {
// Create the fresh type parameter `A`
let def = ty::TypeParameterDef {
name: associated_type_def.name,
def_id: associated_type_def.def_id,
space: space,
index: types.len() + index,
bounds: ty::ParamBounds {
builtin_bounds: associated_type_def.bounds.builtin_bounds,
// FIXME(#18178) -- we should add the other bounds, but
// that requires subst and more logic
trait_bounds: Vec::new(),
region_bounds: Vec::new(),
},
associated_with: Some(local_def(param.id)),
default: None,
};
associated_types_generics.types.push(space, def);
index += 1;
}
}
}
}
}
let param_ty = ty::ParamTy::new(space, index, local_def(param.id));
let bounds = compute_bounds(this,
param.ident.name,
param_ty,
param.bounds.as_slice(),
&param.unbound,
param.span,
where_clause);
let default = match param.default {
None => None,
Some(ref path) => {
let ty = ast_ty_to_ty(this, &ExplicitRscope, &**path);
let cur_idx = index;
fn get_or_create_type_parameter_def<'tcx,AC>(this: &AC,
space: subst::ParamSpace,
param: &ast::TyParam,
index: uint,
where_clause: &ast::WhereClause,
associated_with: Option<ast::DefId>)
-> ty::TypeParameterDef
where AC: AstConv<'tcx>
{
match this.tcx().ty_param_defs.borrow().find(&param.id) {
Some(d) => { return (*d).clone(); }
None => { }
}
ty::walk_ty(ty, |t| {
match ty::get(t).sty {
ty::ty_param(p) => if p.idx > cur_idx {
let param_ty = ty::ParamTy::new(space, index, local_def(param.id));
let bounds = compute_bounds(this,
param.ident.name,
param_ty,
param.bounds.as_slice(),
&param.unbound,
param.span,
where_clause);
let default = match param.default {
None => None,
Some(ref path) => {
let ty = ast_ty_to_ty(this, &ExplicitRscope, &**path);
let cur_idx = index;
ty::walk_ty(ty, |t| {
match ty::get(t).sty {
ty::ty_param(p) => if p.idx > cur_idx {
span_err!(this.tcx().sess, path.span, E0128,
"type parameters with a default cannot use \
forward declared identifiers");
},
_ => {}
}
});
});
Some(ty)
}
};
Some(ty)
}
};
let def = ty::TypeParameterDef {
space: space,
index: index,
name: param.ident.name,
def_id: local_def(param.id),
associated_with: None,
bounds: bounds,
default: default
};
let def = ty::TypeParameterDef {
space: space,
index: index,
name: param.ident.name,
def_id: local_def(param.id),
associated_with: associated_with,
bounds: bounds,
default: default
};
this.tcx().ty_param_defs.borrow_mut().insert(param.id, def.clone());
this.tcx().ty_param_defs.borrow_mut().insert(param.id, def.clone());
def
}
def
}
fn compute_bounds<'tcx,AC>(this: &AC,

View file

@ -774,10 +774,15 @@ pub fn fresh_substs_for_trait(&self,
assert!(generics.regions.len(subst::FnSpace) == 0);
let type_parameter_count = generics.types.len(subst::TypeSpace);
let type_parameters = self.next_ty_vars(type_parameter_count);
let region_param_defs = generics.regions.get_slice(subst::TypeSpace);
let regions = self.region_vars_for_defs(span, region_param_defs);
let type_parameters = self.next_ty_vars(type_parameter_count);
subst::Substs::new_trait(type_parameters, regions, self_ty)
let assoc_type_parameter_count = generics.types.len(subst::AssocSpace);
let assoc_type_parameters = self.next_ty_vars(assoc_type_parameter_count);
subst::Substs::new_trait(type_parameters, regions, assoc_type_parameters, self_ty)
}
pub fn fresh_bound_region(&self, binder_id: ast::NodeId) -> ty::Region {
@ -791,7 +796,7 @@ pub fn resolve_regions_and_report_errors(&self) {
pub fn ty_to_string(&self, t: ty::t) -> String {
ty_to_string(self.tcx,
self.resolve_type_vars_if_possible(t))
self.resolve_type_vars_if_possible(t))
}
pub fn tys_to_string(&self, ts: &[ty::t]) -> String {

View file

@ -425,7 +425,13 @@ fn infer_ty_to_string(cx: &ctxt, ty: ty::InferTy) -> String {
}
ty_infer(infer_ty) => infer_ty_to_string(cx, infer_ty),
ty_err => "[type error]".to_string(),
ty_param(ref param_ty) => param_ty.repr(cx),
ty_param(ref param_ty) => {
if cx.sess.verbose() {
param_ty.repr(cx)
} else {
param_ty.user_string(cx)
}
}
ty_enum(did, ref substs) | ty_struct(did, ref substs) => {
let base = ty::item_path_str(cx, did);
let generics = ty::lookup_item_type(cx, did).generics;
@ -481,6 +487,17 @@ pub fn parameterized(cx: &ctxt,
generics: &ty::Generics)
-> String
{
if cx.sess.verbose() {
if substs.is_noop() {
return format!("{}", base);
} else {
return format!("{}<{},{}>",
base,
substs.regions.repr(cx),
substs.types.repr(cx));
}
}
let mut strs = Vec::new();
match substs.regions {
@ -505,7 +522,7 @@ pub fn parameterized(cx: &ctxt,
let tps = substs.types.get_slice(subst::TypeSpace);
let ty_params = generics.types.get_slice(subst::TypeSpace);
let has_defaults = ty_params.last().map_or(false, |def| def.default.is_some());
let num_defaults = if has_defaults && !cx.sess.verbose() {
let num_defaults = if has_defaults {
ty_params.iter().zip(tps.iter()).rev().take_while(|&(def, &actual)| {
match def.default {
Some(default) => default.subst(cx, substs) == actual,
@ -520,18 +537,6 @@ pub fn parameterized(cx: &ctxt,
strs.push(ty_to_string(cx, *t))
}
if cx.sess.verbose() {
for t in substs.types.get_slice(subst::SelfSpace).iter() {
strs.push(format!("self {}", t.repr(cx)));
}
// generally there shouldn't be any substs in the fn param
// space, but in verbose mode, print them out.
for t in substs.types.get_slice(subst::FnSpace).iter() {
strs.push(format!("fn {}", t.repr(cx)));
}
}
if strs.len() > 0u {
format!("{}<{}>", base, strs.connect(", "))
} else {
@ -668,10 +673,11 @@ fn repr(&self, tcx: &ctxt) -> String {
impl<T:Repr> Repr for subst::VecPerParamSpace<T> {
fn repr(&self, tcx: &ctxt) -> String {
format!("[{};{};{}]",
self.get_slice(subst::TypeSpace).repr(tcx),
self.get_slice(subst::SelfSpace).repr(tcx),
self.get_slice(subst::FnSpace).repr(tcx))
format!("[{};{};{};{}]",
self.get_slice(subst::TypeSpace).repr(tcx),
self.get_slice(subst::SelfSpace).repr(tcx),
self.get_slice(subst::AssocSpace).repr(tcx),
self.get_slice(subst::FnSpace).repr(tcx))
}
}
@ -726,7 +732,7 @@ impl Repr for ty::TraitRef {
fn repr(&self, tcx: &ctxt) -> String {
let base = ty::item_path_str(tcx, self.def_id);
let trait_def = ty::lookup_trait_def(tcx, self.def_id);
format!("<{} as {}>",
format!("<{} : {}>",
self.substs.self_ty().repr(tcx),
parameterized(tcx, base.as_slice(), &self.substs, &trait_def.generics))
}
@ -741,6 +747,19 @@ fn repr(&self, tcx: &ctxt) -> String {
}
}
impl Repr for ast::TraitItem {
fn repr(&self, _tcx: &ctxt) -> String {
match *self {
ast::RequiredMethod(ref data) => format!("RequiredMethod({}, id={})",
data.ident, data.id),
ast::ProvidedMethod(ref data) => format!("ProvidedMethod(id={})",
data.id),
ast::TypeTraitItem(ref data) => format!("TypeTraitItem({}, id={})",
data.ty_param.ident, data.ty_param.id),
}
}
}
impl Repr for ast::Expr {
fn repr(&self, _tcx: &ctxt) -> String {
format!("expr({}: {})", self.id, pprust::expr_to_string(self))
@ -759,6 +778,12 @@ fn user_string(&self, _tcx: &ctxt) -> String {
}
}
impl Repr for ast::Ty {
fn repr(&self, _tcx: &ctxt) -> String {
format!("type({})", pprust::ty_to_string(self))
}
}
impl Repr for ast::Item {
fn repr(&self, tcx: &ctxt) -> String {
format!("item({})", tcx.map.node_to_string(self.id))
@ -1262,7 +1287,8 @@ fn user_string(&self, tcx: &ctxt) -> String {
impl Repr for ParamTy {
fn repr(&self, tcx: &ctxt) -> String {
self.user_string(tcx)
let ident = self.user_string(tcx);
format!("{}/{}.{}", ident, self.space, self.idx)
}
}

View file

@ -547,7 +547,7 @@ pub fn LLVMFunctionType(ReturnType: TypeRef,
pub fn LLVMIsFunctionVarArg(FunctionTy: TypeRef) -> Bool;
pub fn LLVMGetReturnType(FunctionTy: TypeRef) -> TypeRef;
pub fn LLVMCountParamTypes(FunctionTy: TypeRef) -> c_uint;
pub fn LLVMGetParamTypes(FunctionTy: TypeRef, Dest: *const TypeRef);
pub fn LLVMGetParamTypes(FunctionTy: TypeRef, Dest: *mut TypeRef);
/* Operations on struct types */
pub fn LLVMStructTypeInContext(C: ContextRef,
@ -2195,4 +2195,3 @@ pub unsafe fn static_link_hack_this_sucks() {
// Works to the above fix for #15460 to ensure LLVM dependencies that
// are only used by rustllvm don't get stripped by the linker.
mod llvmdeps;

View file

@ -2203,12 +2203,12 @@ fn clean(&self, _: &DocContext) -> Stability {
impl Clean<Item> for ast::AssociatedType {
fn clean(&self, cx: &DocContext) -> Item {
Item {
source: self.span.clean(cx),
name: Some(self.ident.clean(cx)),
source: self.ty_param.span.clean(cx),
name: Some(self.ty_param.ident.clean(cx)),
attrs: self.attrs.clean(cx),
inner: AssociatedTypeItem,
visibility: None,
def_id: ast_util::local_def(self.id),
def_id: ast_util::local_def(self.ty_param.id),
stability: None,
}
}

View file

@ -203,6 +203,7 @@ fn main() {
use std::str::ScalarValue;
use std::string;
use std::vec::Vec;
use std::ops;
use Encodable;
@ -889,9 +890,9 @@ pub fn to_pretty_str(&self) -> string::String {
/// If the Json value is an Object, returns the value associated with the provided key.
/// Otherwise, returns None.
pub fn find<'a>(&'a self, key: &string::String) -> Option<&'a Json>{
pub fn find<'a>(&'a self, key: &str) -> Option<&'a Json>{
match self {
&Object(ref map) => map.find(key),
&Object(ref map) => map.find_with(|s| key.cmp(&s.as_slice())),
_ => None
}
}
@ -899,7 +900,7 @@ pub fn find<'a>(&'a self, key: &string::String) -> Option<&'a Json>{
/// Attempts to get a nested Json Object for each key in `keys`.
/// If any key is found not to exist, find_path will return None.
/// Otherwise, it will return the Json value associated with the final key.
pub fn find_path<'a>(&'a self, keys: &[&string::String]) -> Option<&'a Json>{
pub fn find_path<'a>(&'a self, keys: &[&str]) -> Option<&'a Json>{
let mut target = self;
for key in keys.iter() {
match target.find(*key) {
@ -913,20 +914,19 @@ pub fn find_path<'a>(&'a self, keys: &[&string::String]) -> Option<&'a Json>{
/// If the Json value is an Object, performs a depth-first search until
/// a value associated with the provided key is found. If no value is found
/// or the Json value is not an Object, returns None.
pub fn search<'a>(&'a self, key: &string::String) -> Option<&'a Json> {
pub fn search<'a>(&'a self, key: &str) -> Option<&'a Json> {
match self {
&Object(ref map) => {
match map.find(key) {
match map.find_with(|s| key.cmp(&s.as_slice())) {
Some(json_value) => Some(json_value),
None => {
let mut value : Option<&'a Json> = None;
for (_, v) in map.iter() {
value = v.search(key);
if value.is_some() {
break;
match v.search(key) {
x if x.is_some() => return x,
_ => ()
}
}
value
None
}
}
},
@ -1068,6 +1068,21 @@ pub fn as_null(&self) -> Option<()> {
}
}
impl<'a> ops::Index<&'a str, Json> for Json {
fn index<'a>(&'a self, idx: & &str) -> &'a Json {
self.find(*idx).unwrap()
}
}
impl ops::Index<uint, Json> for Json {
fn index<'a>(&'a self, idx: &uint) -> &'a Json {
match self {
&List(ref v) => v.index(idx),
_ => panic!("can only index Json with uint if it is a list")
}
}
}
/// The output of the streaming parser.
#[deriving(PartialEq, Clone, Show)]
pub enum JsonEvent {
@ -3089,26 +3104,33 @@ fn test_decode_errors_enum() {
#[test]
fn test_find(){
let json_value = from_str("{\"dog\" : \"cat\"}").unwrap();
let found_str = json_value.find(&"dog".to_string());
assert!(found_str.is_some() && found_str.unwrap().as_string().unwrap() == "cat");
let found_str = json_value.find("dog");
assert!(found_str.unwrap().as_string().unwrap() == "cat");
}
#[test]
fn test_find_path(){
let json_value = from_str("{\"dog\":{\"cat\": {\"mouse\" : \"cheese\"}}}").unwrap();
let found_str = json_value.find_path(&[&"dog".to_string(),
&"cat".to_string(), &"mouse".to_string()]);
assert!(found_str.is_some() && found_str.unwrap().as_string().unwrap() == "cheese");
let found_str = json_value.find_path(&["dog", "cat", "mouse"]);
assert!(found_str.unwrap().as_string().unwrap() == "cheese");
}
#[test]
fn test_search(){
let json_value = from_str("{\"dog\":{\"cat\": {\"mouse\" : \"cheese\"}}}").unwrap();
let found_str = json_value.search(&"mouse".to_string()).and_then(|j| j.as_string());
assert!(found_str.is_some());
let found_str = json_value.search("mouse").and_then(|j| j.as_string());
assert!(found_str.unwrap() == "cheese");
}
#[test]
fn test_index(){
let json_value = from_str("{\"animals\":[\"dog\",\"cat\",\"mouse\"]}").unwrap();
let ref list = json_value["animals"];
assert_eq!(list[0].as_string().unwrap(), "dog");
assert_eq!(list[1].as_string().unwrap(), "cat");
assert_eq!(list[2].as_string().unwrap(), "mouse");
}
#[test]
fn test_is_object(){
let json_value = from_str("{}").unwrap();

View file

@ -10,7 +10,6 @@
//
// ignore-lexer-test FIXME #15883
use clone::Clone;
use cmp::{Eq, Equiv, PartialEq};
use core::kinds::Sized;
use default::Default;

View file

@ -26,7 +26,6 @@
use c_str::CString;
use collections::HashMap;
use hash::Hash;
use clone::Clone;
#[cfg(windows)]
use std::hash::sip::SipState;

View file

@ -333,35 +333,10 @@ pub fn to_str_exp_digits(num: f32, dig: uint, upper: bool) -> String {
r
}
/// Convert a string in base 16 to a float.
/// Accepts an optional binary exponent.
///
/// This function accepts strings such as
///
/// * 'a4.fe'
/// * '+a4.fe', equivalent to 'a4.fe'
/// * '-a4.fe'
/// * '2b.aP128', or equivalently, '2b.ap128'
/// * '2b.aP-128'
/// * '.' (understood as 0)
/// * 'c.'
/// * '.c', or, equivalently, '0.c'
/// * '+inf', 'inf', '-inf', 'NaN'
///
/// Leading and trailing whitespace represent an error.
///
/// # Arguments
///
/// * num - A string
///
/// # Return value
///
/// `None` if the string did not represent a valid number. Otherwise,
/// `Some(n)` where `n` is the floating-point number represented by `[num]`.
#[inline]
pub fn from_str_hex(num: &str) -> Option<f32> {
strconv::from_str_common(num, 16u, true, true, true,
strconv::ExpBin, false, false)
#[deprecated="Use `FromStrRadix::from_str_radix(src, 16)`"]
pub fn from_str_hex(src: &str) -> Option<f32> {
strconv::from_str_radix_float(src, 16)
}
impl FromStr for f32 {
@ -384,16 +359,15 @@ impl FromStr for f32 {
///
/// # Arguments
///
/// * num - A string
/// * src - A string
///
/// # Return value
///
/// `None` if the string did not represent a valid number. Otherwise,
/// `Some(n)` where `n` is the floating-point number represented by `num`.
/// `Some(n)` where `n` is the floating-point number represented by `src`.
#[inline]
fn from_str(val: &str) -> Option<f32> {
strconv::from_str_common(val, 10u, true, true, true,
strconv::ExpDec, false, false)
fn from_str(src: &str) -> Option<f32> {
strconv::from_str_radix_float(src, 10u)
}
}
@ -408,17 +382,16 @@ impl num::FromStrRadix for f32 {
///
/// # Arguments
///
/// * num - A string
/// * src - A string
/// * radix - The base to use. Must lie in the range [2 .. 36]
///
/// # Return value
///
/// `None` if the string did not represent a valid number. Otherwise,
/// `Some(n)` where `n` is the floating-point number represented by `num`.
/// `Some(n)` where `n` is the floating-point number represented by `src`.
#[inline]
fn from_str_radix(val: &str, rdx: uint) -> Option<f32> {
strconv::from_str_common(val, rdx, true, true, false,
strconv::ExpNone, false, false)
fn from_str_radix(src: &str, radix: uint) -> Option<f32> {
strconv::from_str_radix_float(src, radix)
}
}
@ -710,8 +683,8 @@ fn test_classify() {
fn test_ldexp() {
// We have to use from_str until base-2 exponents
// are supported in floating-point literals
let f1: f32 = from_str_hex("1p-123").unwrap();
let f2: f32 = from_str_hex("1p-111").unwrap();
let f1: f32 = FromStrRadix::from_str_radix("1p-123", 16).unwrap();
let f2: f32 = FromStrRadix::from_str_radix("1p-111", 16).unwrap();
assert_eq!(FloatMath::ldexp(1f32, -123), f1);
assert_eq!(FloatMath::ldexp(1f32, -111), f2);
@ -730,8 +703,8 @@ fn test_ldexp() {
fn test_frexp() {
// We have to use from_str until base-2 exponents
// are supported in floating-point literals
let f1: f32 = from_str_hex("1p-123").unwrap();
let f2: f32 = from_str_hex("1p-111").unwrap();
let f1: f32 = FromStrRadix::from_str_radix("1p-123", 16).unwrap();
let f2: f32 = FromStrRadix::from_str_radix("1p-111", 16).unwrap();
let (x1, exp1) = f1.frexp();
let (x2, exp2) = f2.frexp();
assert_eq!((x1, exp1), (0.5f32, -122));

View file

@ -341,92 +341,60 @@ pub fn to_str_exp_digits(num: f64, dig: uint, upper: bool) -> String {
r
}
/// Convert a string in base 16 to a float.
/// Accepts an optional binary exponent.
///
/// This function accepts strings such as
///
/// * 'a4.fe'
/// * '+a4.fe', equivalent to 'a4.fe'
/// * '-a4.fe'
/// * '2b.aP128', or equivalently, '2b.ap128'
/// * '2b.aP-128'
/// * '.' (understood as 0)
/// * 'c.'
/// * '.c', or, equivalently, '0.c'
/// * '+inf', 'inf', '-inf', 'NaN'
///
/// Leading and trailing whitespace represent an error.
///
/// # Arguments
///
/// * num - A string
///
/// # Return value
///
/// `None` if the string did not represent a valid number. Otherwise,
/// `Some(n)` where `n` is the floating-point number represented by `[num]`.
#[inline]
pub fn from_str_hex(num: &str) -> Option<f64> {
strconv::from_str_common(num, 16u, true, true, true,
strconv::ExpBin, false, false)
#[deprecated="Use `FromStrRadix::from_str_radix(src, 16)`"]
pub fn from_str_hex(src: &str) -> Option<f64> {
strconv::from_str_radix_float(src, 16)
}
impl FromStr for f64 {
/// Convert a string in base 10 to a float.
/// Accepts an optional decimal exponent.
///
/// This function accepts strings such as
/// This function accepts strings such as:
///
/// * '3.14'
/// * '+3.14', equivalent to '3.14'
/// * '-3.14'
/// * '2.5E10', or equivalently, '2.5e10'
/// * '2.5E-10'
/// * '.' (understood as 0)
/// * '5.'
/// * '.5', or, equivalently, '0.5'
/// * '+inf', 'inf', '-inf', 'NaN'
/// * inf', '-inf', 'NaN'
///
/// Leading and trailing whitespace represent an error.
///
/// # Arguments
///
/// * num - A string
/// * src - A string
///
/// # Return value
///
/// `none` if the string did not represent a valid number. Otherwise,
/// `Some(n)` where `n` is the floating-point number represented by `num`.
/// `Some(n)` where `n` is the floating-point number represented by `src`.
#[inline]
fn from_str(val: &str) -> Option<f64> {
strconv::from_str_common(val, 10u, true, true, true,
strconv::ExpDec, false, false)
fn from_str(src: &str) -> Option<f64> {
strconv::from_str_radix_float(src, 10u)
}
}
impl num::FromStrRadix for f64 {
/// Convert a string in a given base to a float.
///
/// Due to possible conflicts, this function does **not** accept
/// the special values `inf`, `-inf`, `+inf` and `NaN`, **nor**
/// does it recognize exponents of any kind.
///
/// Leading and trailing whitespace represent an error.
///
/// # Arguments
///
/// * num - A string
/// * src - A string
/// * radix - The base to use. Must lie in the range [2 .. 36]
///
/// # Return value
///
/// `None` if the string did not represent a valid number. Otherwise,
/// `Some(n)` where `n` is the floating-point number represented by `num`.
/// `Some(n)` where `n` is the floating-point number represented by `src`.
#[inline]
fn from_str_radix(val: &str, rdx: uint) -> Option<f64> {
strconv::from_str_common(val, rdx, true, true, false,
strconv::ExpNone, false, false)
fn from_str_radix(src: &str, radix: uint) -> Option<f64> {
strconv::from_str_radix_float(src, radix)
}
}
@ -712,8 +680,8 @@ fn test_classify() {
fn test_ldexp() {
// We have to use from_str until base-2 exponents
// are supported in floating-point literals
let f1: f64 = from_str_hex("1p-123").unwrap();
let f2: f64 = from_str_hex("1p-111").unwrap();
let f1: f64 = FromStrRadix::from_str_radix("1p-123", 16).unwrap();
let f2: f64 = FromStrRadix::from_str_radix("1p-111", 16).unwrap();
assert_eq!(FloatMath::ldexp(1f64, -123), f1);
assert_eq!(FloatMath::ldexp(1f64, -111), f2);
@ -732,8 +700,8 @@ fn test_ldexp() {
fn test_frexp() {
// We have to use from_str until base-2 exponents
// are supported in floating-point literals
let f1: f64 = from_str_hex("1p-123").unwrap();
let f2: f64 = from_str_hex("1p-111").unwrap();
let f1: f64 = FromStrRadix::from_str_radix("1p-123", 16).unwrap();
let f2: f64 = FromStrRadix::from_str_radix("1p-111", 16).unwrap();
let (x1, exp1) = f1.frexp();
let (x2, exp2) = f2.frexp();
assert_eq!((x1, exp1), (0.5f64, -122));

View file

@ -14,31 +14,11 @@
macro_rules! int_module (($T:ty) => (
// String conversion functions and impl str -> num
/// Parse a byte slice as a number in the given base
///
/// Yields an `Option` because `buf` may or may not actually be parseable.
///
/// # Examples
///
/// ```
/// let num = std::i64::parse_bytes([49,50,51,52,53,54,55,56,57], 10);
/// assert!(num == Some(123456789));
/// ```
#[inline]
#[experimental = "might need to return Result"]
pub fn parse_bytes(buf: &[u8], radix: uint) -> Option<$T> {
strconv::from_str_bytes_common(buf, radix, true, false, false,
strconv::ExpNone, false, false)
}
#[experimental = "might need to return Result"]
impl FromStr for $T {
#[inline]
fn from_str(s: &str) -> Option<$T> {
strconv::from_str_common(s, 10u, true, false, false,
strconv::ExpNone, false, false)
strconv::from_str_radix_int(s, 10)
}
}
@ -46,18 +26,14 @@ fn from_str(s: &str) -> Option<$T> {
impl FromStrRadix for $T {
#[inline]
fn from_str_radix(s: &str, radix: uint) -> Option<$T> {
strconv::from_str_common(s, radix, true, false, false,
strconv::ExpNone, false, false)
strconv::from_str_radix_int(s, radix)
}
}
#[cfg(test)]
mod tests {
use prelude::*;
use super::*;
use i32;
use str::StrSlice;
use num::FromStrRadix;
#[test]
fn test_from_str() {
@ -73,33 +49,33 @@ fn test_from_str() {
assert_eq!(from_str::<i32>("-123456789"), Some(-123456789 as i32));
assert_eq!(from_str::<$T>("-00100"), Some(-100 as $T));
assert!(from_str::<$T>(" ").is_none());
assert!(from_str::<$T>("x").is_none());
assert_eq!(from_str::<$T>(""), None);
assert_eq!(from_str::<$T>(" "), None);
assert_eq!(from_str::<$T>("x"), None);
}
#[test]
fn test_parse_bytes() {
use str::StrSlice;
assert_eq!(parse_bytes("123".as_bytes(), 10u), Some(123 as $T));
assert_eq!(parse_bytes("1001".as_bytes(), 2u), Some(9 as $T));
assert_eq!(parse_bytes("123".as_bytes(), 8u), Some(83 as $T));
assert_eq!(i32::parse_bytes("123".as_bytes(), 16u), Some(291 as i32));
assert_eq!(i32::parse_bytes("ffff".as_bytes(), 16u), Some(65535 as i32));
assert_eq!(i32::parse_bytes("FFFF".as_bytes(), 16u), Some(65535 as i32));
assert_eq!(parse_bytes("z".as_bytes(), 36u), Some(35 as $T));
assert_eq!(parse_bytes("Z".as_bytes(), 36u), Some(35 as $T));
fn test_from_str_radix() {
assert_eq!(FromStrRadix::from_str_radix("123", 10), Some(123 as $T));
assert_eq!(FromStrRadix::from_str_radix("1001", 2), Some(9 as $T));
assert_eq!(FromStrRadix::from_str_radix("123", 8), Some(83 as $T));
assert_eq!(FromStrRadix::from_str_radix("123", 16), Some(291 as i32));
assert_eq!(FromStrRadix::from_str_radix("ffff", 16), Some(65535 as i32));
assert_eq!(FromStrRadix::from_str_radix("FFFF", 16), Some(65535 as i32));
assert_eq!(FromStrRadix::from_str_radix("z", 36), Some(35 as $T));
assert_eq!(FromStrRadix::from_str_radix("Z", 36), Some(35 as $T));
assert_eq!(parse_bytes("-123".as_bytes(), 10u), Some(-123 as $T));
assert_eq!(parse_bytes("-1001".as_bytes(), 2u), Some(-9 as $T));
assert_eq!(parse_bytes("-123".as_bytes(), 8u), Some(-83 as $T));
assert_eq!(i32::parse_bytes("-123".as_bytes(), 16u), Some(-291 as i32));
assert_eq!(i32::parse_bytes("-ffff".as_bytes(), 16u), Some(-65535 as i32));
assert_eq!(i32::parse_bytes("-FFFF".as_bytes(), 16u), Some(-65535 as i32));
assert_eq!(parse_bytes("-z".as_bytes(), 36u), Some(-35 as $T));
assert_eq!(parse_bytes("-Z".as_bytes(), 36u), Some(-35 as $T));
assert_eq!(FromStrRadix::from_str_radix("-123", 10), Some(-123 as $T));
assert_eq!(FromStrRadix::from_str_radix("-1001", 2), Some(-9 as $T));
assert_eq!(FromStrRadix::from_str_radix("-123", 8), Some(-83 as $T));
assert_eq!(FromStrRadix::from_str_radix("-123", 16), Some(-291 as i32));
assert_eq!(FromStrRadix::from_str_radix("-ffff", 16), Some(-65535 as i32));
assert_eq!(FromStrRadix::from_str_radix("-FFFF", 16), Some(-65535 as i32));
assert_eq!(FromStrRadix::from_str_radix("-z", 36), Some(-35 as $T));
assert_eq!(FromStrRadix::from_str_radix("-Z", 36), Some(-35 as $T));
assert!(parse_bytes("Z".as_bytes(), 35u).is_none());
assert!(parse_bytes("-9".as_bytes(), 2u).is_none());
assert_eq!(FromStrRadix::from_str_radix("Z", 35), None::<$T>);
assert_eq!(FromStrRadix::from_str_radix("-9", 2), None::<$T>);
}
#[test]
@ -133,35 +109,35 @@ fn test_int_to_str_overflow() {
fn test_int_from_str_overflow() {
let mut i8_val: i8 = 127_i8;
assert_eq!(from_str::<i8>("127"), Some(i8_val));
assert!(from_str::<i8>("128").is_none());
assert_eq!(from_str::<i8>("128"), None);
i8_val += 1 as i8;
assert_eq!(from_str::<i8>("-128"), Some(i8_val));
assert!(from_str::<i8>("-129").is_none());
assert_eq!(from_str::<i8>("-129"), None);
let mut i16_val: i16 = 32_767_i16;
assert_eq!(from_str::<i16>("32767"), Some(i16_val));
assert!(from_str::<i16>("32768").is_none());
assert_eq!(from_str::<i16>("32768"), None);
i16_val += 1 as i16;
assert_eq!(from_str::<i16>("-32768"), Some(i16_val));
assert!(from_str::<i16>("-32769").is_none());
assert_eq!(from_str::<i16>("-32769"), None);
let mut i32_val: i32 = 2_147_483_647_i32;
assert_eq!(from_str::<i32>("2147483647"), Some(i32_val));
assert!(from_str::<i32>("2147483648").is_none());
assert_eq!(from_str::<i32>("2147483648"), None);
i32_val += 1 as i32;
assert_eq!(from_str::<i32>("-2147483648"), Some(i32_val));
assert!(from_str::<i32>("-2147483649").is_none());
assert_eq!(from_str::<i32>("-2147483649"), None);
let mut i64_val: i64 = 9_223_372_036_854_775_807_i64;
assert_eq!(from_str::<i64>("9223372036854775807"), Some(i64_val));
assert!(from_str::<i64>("9223372036854775808").is_none());
assert_eq!(from_str::<i64>("9223372036854775808"), None);
i64_val += 1 as i64;
assert_eq!(from_str::<i64>("-9223372036854775808"), Some(i64_val));
assert!(from_str::<i64>("-9223372036854775809").is_none());
assert_eq!(from_str::<i64>("-9223372036854775809"), None);
}
}

View file

@ -13,14 +13,14 @@
#![allow(missing_docs)]
use char;
use clone::Clone;
use num::{NumCast, Zero, One, cast, Int};
use num::{Float, FPNaN, FPInfinite, ToPrimitive};
use char::Char;
use from_str::from_str;
use iter::Iterator;
use num;
use ops::{Add, Sub, Mul, Div, Rem, Neg};
use num::{Int, Bounded};
use num::{Float, FPNaN, FPInfinite, ToPrimitive};
use option::{None, Option, Some};
use slice::{ImmutableSlice, MutableSlice, CloneableVector};
use std::cmp::{PartialOrd, PartialEq};
use str::StrSlice;
use string::String;
use vec::Vec;
@ -67,81 +67,6 @@ pub enum SignFormat {
SignAll,
}
/// Encompasses functions used by the string converter.
pub trait NumStrConv {
/// Returns the NaN value.
fn nan() -> Option<Self>;
/// Returns the infinite value.
fn inf() -> Option<Self>;
/// Returns the negative infinite value.
fn neg_inf() -> Option<Self>;
/// Returns -0.0.
fn neg_zero() -> Option<Self>;
/// Rounds the number toward zero.
fn round_to_zero(&self) -> Self;
/// Returns the fractional part of the number.
fn fractional_part(&self) -> Self;
}
macro_rules! impl_NumStrConv_Floating (($t:ty) => (
impl NumStrConv for $t {
#[inline]
fn nan() -> Option<$t> { Some( 0.0 / 0.0) }
#[inline]
fn inf() -> Option<$t> { Some( 1.0 / 0.0) }
#[inline]
fn neg_inf() -> Option<$t> { Some(-1.0 / 0.0) }
#[inline]
fn neg_zero() -> Option<$t> { Some(-0.0 ) }
#[inline]
fn round_to_zero(&self) -> $t { self.trunc() }
#[inline]
fn fractional_part(&self) -> $t { self.fract() }
}
))
macro_rules! impl_NumStrConv_Integer (($t:ty) => (
impl NumStrConv for $t {
#[inline] fn nan() -> Option<$t> { None }
#[inline] fn inf() -> Option<$t> { None }
#[inline] fn neg_inf() -> Option<$t> { None }
#[inline] fn neg_zero() -> Option<$t> { None }
#[inline] fn round_to_zero(&self) -> $t { *self }
#[inline] fn fractional_part(&self) -> $t { 0 }
}
))
// FIXME: #4955
// Replace by two generic impls for traits 'Integral' and 'Floating'
impl_NumStrConv_Floating!(f32)
impl_NumStrConv_Floating!(f64)
impl_NumStrConv_Integer!(int)
impl_NumStrConv_Integer!(i8)
impl_NumStrConv_Integer!(i16)
impl_NumStrConv_Integer!(i32)
impl_NumStrConv_Integer!(i64)
impl_NumStrConv_Integer!(uint)
impl_NumStrConv_Integer!(u8)
impl_NumStrConv_Integer!(u16)
impl_NumStrConv_Integer!(u32)
impl_NumStrConv_Integer!(u64)
// Special value strings as [u8] consts.
static INF_BUF: [u8, ..3] = [b'i', b'n', b'f'];
static POS_INF_BUF: [u8, ..4] = [b'+', b'i', b'n', b'f'];
static NEG_INF_BUF: [u8, ..4] = [b'-', b'i', b'n', b'f'];
static NAN_BUF: [u8, ..3] = [b'N', b'a', b'N'];
/**
* Converts an integral number to its string representation as a byte vector.
* This is meant to be a common base implementation for all integral string
@ -170,10 +95,10 @@ impl NumStrConv for $t {
fn int_to_str_bytes_common<T: Int>(num: T, radix: uint, sign: SignFormat, f: |u8|) {
assert!(2 <= radix && radix <= 36);
let _0: T = Zero::zero();
let _0: T = num::zero();
let neg = num < _0;
let radix_gen: T = cast(radix).unwrap();
let radix_gen: T = num::cast(radix).unwrap();
let mut deccum = num;
// This is just for integral types, the largest of which is a u64. The
@ -255,8 +180,7 @@ fn int_to_str_bytes_common<T: Int>(num: T, radix: uint, sign: SignFormat, f: |u8
* - Fails if `radix` > 25 and `exp_format` is `ExpBin` due to conflict
* between digit and exponent sign `'p'`.
*/
pub fn float_to_str_bytes_common<T:NumCast+Zero+One+PartialEq+PartialOrd+Float+
Div<T,T>+Neg<T>+Rem<T,T>+Mul<T,T>>(
pub fn float_to_str_bytes_common<T: Float>(
num: T, radix: uint, negative_zero: bool,
sign: SignFormat, digits: SignificantDigits, exp_format: ExponentFormat, exp_upper: bool
) -> (Vec<u8>, bool) {
@ -271,8 +195,8 @@ pub fn float_to_str_bytes_common<T:NumCast+Zero+One+PartialEq+PartialOrd+Float+
_ => ()
}
let _0: T = Zero::zero();
let _1: T = One::one();
let _0: T = num::zero();
let _1: T = num::one();
match num.classify() {
FPNaN => { return (b"NaN".to_vec(), true); }
@ -293,7 +217,7 @@ pub fn float_to_str_bytes_common<T:NumCast+Zero+One+PartialEq+PartialOrd+Float+
let neg = num < _0 || (negative_zero && _1 / num == Float::neg_infinity());
let mut buf = Vec::new();
let radix_gen: T = cast(radix as int).unwrap();
let radix_gen: T = num::cast(radix as int).unwrap();
let (num, exp) = match exp_format {
ExpNone => (num, 0i32),
@ -302,12 +226,12 @@ pub fn float_to_str_bytes_common<T:NumCast+Zero+One+PartialEq+PartialOrd+Float+
(num, 0i32)
} else {
let (exp, exp_base) = match exp_format {
ExpDec => (num.abs().log10().floor(), cast::<f64, T>(10.0f64).unwrap()),
ExpBin => (num.abs().log2().floor(), cast::<f64, T>(2.0f64).unwrap()),
ExpDec => (num.abs().log10().floor(), num::cast::<f64, T>(10.0f64).unwrap()),
ExpBin => (num.abs().log2().floor(), num::cast::<f64, T>(2.0f64).unwrap()),
ExpNone => unreachable!()
};
(num / exp_base.powf(exp), cast::<T, i32>(exp).unwrap())
(num / exp_base.powf(exp), num::cast::<T, i32>(exp).unwrap())
}
}
};
@ -488,8 +412,7 @@ pub fn float_to_str_bytes_common<T:NumCast+Zero+One+PartialEq+PartialOrd+Float+
* `to_str_bytes_common()`, for details see there.
*/
#[inline]
pub fn float_to_str_common<T:NumCast+Zero+One+PartialEq+PartialOrd+NumStrConv+Float+
Div<T,T>+Neg<T>+Rem<T,T>+Mul<T,T>>(
pub fn float_to_str_common<T: Float>(
num: T, radix: uint, negative_zero: bool,
sign: SignFormat, digits: SignificantDigits, exp_format: ExponentFormat, exp_capital: bool
) -> (String, bool) {
@ -501,311 +424,228 @@ pub fn float_to_str_common<T:NumCast+Zero+One+PartialEq+PartialOrd+NumStrConv+Fl
// Some constants for from_str_bytes_common's input validation,
// they define minimum radix values for which the character is a valid digit.
static DIGIT_P_RADIX: uint = ('p' as uint) - ('a' as uint) + 11u;
static DIGIT_I_RADIX: uint = ('i' as uint) - ('a' as uint) + 11u;
static DIGIT_E_RADIX: uint = ('e' as uint) - ('a' as uint) + 11u;
/**
* Parses a byte slice as a number. This is meant to
* be a common base implementation for all numeric string conversion
* functions like `from_str()` or `from_str_radix()`.
*
* # Arguments
* - `buf` - The byte slice to parse.
* - `radix` - Which base to parse the number as. Accepts 2-36.
* - `negative` - Whether to accept negative numbers.
* - `fractional` - Whether to accept numbers with fractional parts.
* - `special` - Whether to accept special values like `inf`
* and `NaN`. Can conflict with `radix`, see Failure.
* - `exponent` - Which exponent format to accept. Options are:
* - `ExpNone`: No Exponent, accepts just plain numbers like `42` or
* `-8.2`.
* - `ExpDec`: Accepts numbers with a decimal exponent like `42e5` or
* `8.2E-2`. The exponent string itself is always base 10.
* Can conflict with `radix`, see Failure.
* - `ExpBin`: Accepts numbers with a binary exponent like `42P-8` or
* `FFp128`. The exponent string itself is always base 10.
* Can conflict with `radix`, see Failure.
* - `empty_zero` - Whether to accept an empty `buf` as a 0 or not.
* - `ignore_underscores` - Whether all underscores within the string should
* be ignored.
*
* # Return value
* Returns `Some(n)` if `buf` parses to a number n without overflowing, and
* `None` otherwise, depending on the constraints set by the remaining
* arguments.
*
* # Failure
* - Fails if `radix` < 2 or `radix` > 36.
* - Fails if `radix` > 14 and `exponent` is `ExpDec` due to conflict
* between digit and exponent sign `'e'`.
* - Fails if `radix` > 25 and `exponent` is `ExpBin` due to conflict
* between digit and exponent sign `'p'`.
* - Fails if `radix` > 18 and `special == true` due to conflict
* between digit and lowest first character in `inf` and `NaN`, the `'i'`.
*/
pub fn from_str_bytes_common<T:NumCast+Zero+One+PartialEq+PartialOrd+Div<T,T>+
Mul<T,T>+Sub<T,T>+Neg<T>+Add<T,T>+
NumStrConv+Clone>(
buf: &[u8], radix: uint, negative: bool, fractional: bool,
special: bool, exponent: ExponentFormat, empty_zero: bool,
ignore_underscores: bool
) -> Option<T> {
match exponent {
ExpDec if radix >= DIGIT_E_RADIX // decimal exponent 'e'
=> panic!("from_str_bytes_common: radix {} incompatible with \
use of 'e' as decimal exponent", radix),
ExpBin if radix >= DIGIT_P_RADIX // binary exponent 'p'
=> panic!("from_str_bytes_common: radix {} incompatible with \
use of 'p' as binary exponent", radix),
_ if special && radix >= DIGIT_I_RADIX // first digit of 'inf'
=> panic!("from_str_bytes_common: radix {} incompatible with \
special values 'inf' and 'NaN'", radix),
_ if (radix as int) < 2
=> panic!("from_str_bytes_common: radix {} to low, \
must lie in the range [2, 36]", radix),
_ if (radix as int) > 36
=> panic!("from_str_bytes_common: radix {} to high, \
must lie in the range [2, 36]", radix),
_ => ()
pub fn from_str_radix_float<T: Float>(src: &str, radix: uint) -> Option<T> {
assert!(radix >= 2 && radix <= 36,
"from_str_radix_float: must lie in the range `[2, 36]` - found {}",
radix);
let _0: T = num::zero();
let _1: T = num::one();
let radix_t: T = num::cast(radix as int).unwrap();
// Special values
match src {
"inf" => return Some(Float::infinity()),
"-inf" => return Some(Float::neg_infinity()),
"NaN" => return Some(Float::nan()),
_ => {},
}
let _0: T = Zero::zero();
let _1: T = One::one();
let radix_gen: T = cast(radix as int).unwrap();
let len = buf.len();
if len == 0 {
if empty_zero {
return Some(_0);
} else {
return None;
}
}
if special {
if buf == INF_BUF || buf == POS_INF_BUF {
return NumStrConv::inf();
} else if buf == NEG_INF_BUF {
if negative {
return NumStrConv::neg_inf();
} else {
return None;
}
} else if buf == NAN_BUF {
return NumStrConv::nan();
}
}
let (start, accum_positive) = match buf[0] as char {
'-' if !negative => return None,
'-' => (1u, false),
'+' => (1u, true),
_ => (0u, true)
let (is_positive, src) = match src.slice_shift_char() {
(None, _) => return None,
(Some('-'), "") => return None,
(Some('-'), src) => (false, src),
(Some(_), _) => (true, src),
};
// Initialize accumulator with signed zero for floating point parsing to
// work
let mut accum = if accum_positive { _0.clone() } else { -_1 * _0};
let mut last_accum = accum.clone(); // Necessary to detect overflow
let mut i = start;
let mut exp_found = false;
// The significand to accumulate
let mut sig = if is_positive { _0 } else { -_1 };
// Necessary to detect overflow
let mut prev_sig = sig;
let mut cs = src.chars().enumerate();
// Exponent prefix and exponent index offset
let mut exp_info = None::<(char, uint)>;
// Parse integer part of number
while i < len {
let c = buf[i] as char;
match char::to_digit(c, radix) {
// Parse the integer part of the significand
for (i, c) in cs {
match c.to_digit(radix) {
Some(digit) => {
// shift accum one digit left
accum = accum * radix_gen.clone();
// shift significand one digit left
sig = sig * radix_t;
// add/subtract current digit depending on sign
if accum_positive {
accum = accum + cast(digit as int).unwrap();
if is_positive {
sig = sig + num::cast(digit as int).unwrap();
} else {
accum = accum - cast(digit as int).unwrap();
sig = sig - num::cast(digit as int).unwrap();
}
// Detect overflow by comparing to last value, except
// if we've not seen any non-zero digits.
if last_accum != _0 {
if accum_positive && accum <= last_accum { return NumStrConv::inf(); }
if !accum_positive && accum >= last_accum { return NumStrConv::neg_inf(); }
if prev_sig != _0 {
if is_positive && sig <= prev_sig
{ return Some(Float::infinity()); }
if !is_positive && sig >= prev_sig
{ return Some(Float::neg_infinity()); }
// Detect overflow by reversing the shift-and-add process
if accum_positive &&
(last_accum != ((accum - cast(digit as int).unwrap())/radix_gen.clone())) {
return NumStrConv::inf();
}
if !accum_positive &&
(last_accum != ((accum + cast(digit as int).unwrap())/radix_gen.clone())) {
return NumStrConv::neg_inf();
}
let digit: T = num::cast(digit as int).unwrap();
if is_positive && (prev_sig != ((sig - digit) / radix_t))
{ return Some(Float::infinity()); }
if !is_positive && (prev_sig != ((sig + digit) / radix_t))
{ return Some(Float::neg_infinity()); }
}
last_accum = accum.clone();
}
prev_sig = sig;
},
None => match c {
'_' if ignore_underscores => {}
'e' | 'E' | 'p' | 'P' => {
exp_found = true;
break; // start of exponent
}
'.' if fractional => {
i += 1u; // skip the '.'
break; // start of fractional part
}
_ => return None // invalid number
}
exp_info = Some((c, i + 1));
break; // start of exponent
},
'.' => {
break; // start of fractional part
},
_ => {
return None;
},
},
}
i += 1u;
}
// Parse fractional part of number
// Skip if already reached start of exponent
if !exp_found {
let mut power = _1.clone();
while i < len {
let c = buf[i] as char;
match char::to_digit(c, radix) {
// If we are not yet at the exponent parse the fractional
// part of the significand
if exp_info.is_none() {
let mut power = _1;
for (i, c) in cs {
match c.to_digit(radix) {
Some(digit) => {
let digit: T = num::cast(digit).unwrap();
// Decrease power one order of magnitude
power = power / radix_gen;
let digit_t: T = cast(digit).unwrap();
power = power / radix_t;
// add/subtract current digit depending on sign
if accum_positive {
accum = accum + digit_t * power;
sig = if is_positive {
sig + digit * power
} else {
accum = accum - digit_t * power;
}
sig - digit * power
};
// Detect overflow by comparing to last value
if accum_positive && accum < last_accum { return NumStrConv::inf(); }
if !accum_positive && accum > last_accum { return NumStrConv::neg_inf(); }
last_accum = accum.clone();
}
if is_positive && sig < prev_sig
{ return Some(Float::infinity()); }
if !is_positive && sig > prev_sig
{ return Some(Float::neg_infinity()); }
prev_sig = sig;
},
None => match c {
'_' if ignore_underscores => {}
'e' | 'E' | 'p' | 'P' => {
exp_found = true;
break; // start of exponent
}
_ => return None // invalid number
}
exp_info = Some((c, i + 1));
break; // start of exponent
},
_ => {
return None; // invalid number
},
},
}
i += 1u;
}
}
// Special case: buf not empty, but does not contain any digit in front
// of the exponent sign -> number is empty string
if i == start {
if empty_zero {
return Some(_0);
} else {
return None;
}
}
// Parse and calculate the exponent
let exp = match exp_info {
Some((c, offset)) => {
let base: T = match c {
'E' | 'e' if radix == 10 => num::cast(10u).unwrap(),
'P' | 'p' if radix == 16 => num::cast(2u).unwrap(),
_ => return None,
};
let mut multiplier = _1.clone();
// Parse the exponent as decimal integer
let src = src[offset..];
let (is_positive, exp) = match src.slice_shift_char() {
(Some('-'), src) => (false, from_str::<uint>(src)),
(Some('+'), src) => (true, from_str::<uint>(src)),
(Some(_), _) => (true, from_str::<uint>(src)),
(None, _) => return None,
};
if exp_found {
let c = buf[i] as char;
let base: T = match (c, exponent) {
// c is never _ so don't need to handle specially
('e', ExpDec) | ('E', ExpDec) => cast(10u).unwrap(),
('p', ExpBin) | ('P', ExpBin) => cast(2u).unwrap(),
_ => return None // char doesn't fit given exponent format
};
// parse remaining bytes as decimal integer,
// skipping the exponent char
let exp: Option<int> = from_str_bytes_common(
buf[i+1..len], 10, true, false, false, ExpNone, false,
ignore_underscores);
match exp {
Some(exp_pow) => {
multiplier = if exp_pow < 0 {
_1 / num::pow(base, (-exp_pow.to_int().unwrap()) as uint)
} else {
num::pow(base, exp_pow.to_int().unwrap() as uint)
}
match (is_positive, exp) {
(true, Some(exp)) => num::pow(base, exp),
(false, Some(exp)) => _1 / num::pow(base, exp),
(_, None) => return None,
}
None => return None // invalid exponent -> invalid number
}
}
},
None => _1, // no exponent
};
Some(accum * multiplier)
Some(sig * exp)
}
/**
* Parses a string as a number. This is a wrapper for
* `from_str_bytes_common()`, for details see there.
*/
#[inline]
pub fn from_str_common<T:NumCast+Zero+One+PartialEq+PartialOrd+Div<T,T>+Mul<T,T>+
Sub<T,T>+Neg<T>+Add<T,T>+NumStrConv+Clone>(
buf: &str, radix: uint, negative: bool, fractional: bool,
special: bool, exponent: ExponentFormat, empty_zero: bool,
ignore_underscores: bool
) -> Option<T> {
from_str_bytes_common(buf.as_bytes(), radix, negative,
fractional, special, exponent, empty_zero,
ignore_underscores)
pub fn from_str_radix_int<T: Int>(src: &str, radix: uint) -> Option<T> {
assert!(radix >= 2 && radix <= 36,
"from_str_radix_int: must lie in the range `[2, 36]` - found {}",
radix);
fn cast<T: Int>(x: uint) -> T {
num::cast(x).unwrap()
}
let _0: T = num::zero();
let _1: T = num::one();
let is_signed = _0 > Bounded::min_value();
let (is_positive, src) = match src.slice_shift_char() {
(Some('-'), src) if is_signed => (false, src),
(Some(_), _) => (true, src),
(None, _) => return None,
};
let mut xs = src.chars().map(|c| {
c.to_digit(radix).map(cast)
});
let radix = cast(radix);
let mut result = _0;
if is_positive {
for x in xs {
let x = match x {
Some(x) => x,
None => return None,
};
result = match result.checked_mul(&radix) {
Some(result) => result,
None => return None,
};
result = match result.checked_add(&x) {
Some(result) => result,
None => return None,
};
}
} else {
for x in xs {
let x = match x {
Some(x) => x,
None => return None,
};
result = match result.checked_mul(&radix) {
Some(result) => result,
None => return None,
};
result = match result.checked_sub(&x) {
Some(result) => result,
None => return None,
};
}
}
Some(result)
}
#[cfg(test)]
mod test {
use super::*;
use option::*;
#[test]
fn from_str_ignore_underscores() {
let s : Option<u8> = from_str_common("__1__", 2, false, false, false,
ExpNone, false, true);
assert_eq!(s, Some(1u8));
let n : Option<u8> = from_str_common("__1__", 2, false, false, false,
ExpNone, false, false);
assert_eq!(n, None);
let f : Option<f32> = from_str_common("_1_._5_e_1_", 10, false, true, false,
ExpDec, false, true);
assert_eq!(f, Some(1.5e1f32));
}
#[test]
fn from_str_issue5770() {
// try to parse 0b1_1111_1111 = 511 as a u8. Caused problems
// since 255*2+1 == 255 (mod 256) so the overflow wasn't
// detected.
let n : Option<u8> = from_str_common("111111111", 2, false, false, false,
ExpNone, false, false);
assert_eq!(n, None);
}
use num::Float;
#[test]
fn from_str_issue7588() {
let u : Option<u8> = from_str_common("1000", 10, false, false, false,
ExpNone, false, false);
let u : Option<u8> = from_str_radix_int("1000", 10);
assert_eq!(u, None);
let s : Option<i16> = from_str_common("80000", 10, false, false, false,
ExpNone, false, false);
let s : Option<i16> = from_str_radix_int("80000", 10);
assert_eq!(s, None);
let f : Option<f32> = from_str_common(
"10000000000000000000000000000000000000000", 10, false, false, false,
ExpNone, false, false);
assert_eq!(f, NumStrConv::inf())
let fe : Option<f32> = from_str_common("1e40", 10, false, false, false,
ExpDec, false, false);
assert_eq!(fe, NumStrConv::inf())
let f : Option<f32> = from_str_radix_float("10000000000000000000000000000000000000000", 10);
assert_eq!(f, Some(Float::infinity()))
let fe : Option<f32> = from_str_radix_float("1e40", 10);
assert_eq!(fe, Some(Float::infinity()))
}
}

View file

@ -15,31 +15,11 @@
macro_rules! uint_module (($T:ty) => (
// String conversion functions and impl str -> num
/// Parse a byte slice as a number in the given base
///
/// Yields an `Option` because `buf` may or may not actually be parseable.
///
/// # Examples
///
/// ```
/// let num = std::uint::parse_bytes([49,50,51,52,53,54,55,56,57], 10);
/// assert!(num == Some(123456789));
/// ```
#[inline]
#[experimental = "might need to return Result"]
pub fn parse_bytes(buf: &[u8], radix: uint) -> Option<$T> {
strconv::from_str_bytes_common(buf, radix, false, false, false,
strconv::ExpNone, false, false)
}
#[experimental = "might need to return Result"]
impl FromStr for $T {
#[inline]
fn from_str(s: &str) -> Option<$T> {
strconv::from_str_common(s, 10u, false, false, false,
strconv::ExpNone, false, false)
strconv::from_str_radix_int(s, 10)
}
}
@ -47,8 +27,7 @@ fn from_str(s: &str) -> Option<$T> {
impl FromStrRadix for $T {
#[inline]
fn from_str_radix(s: &str, radix: uint) -> Option<$T> {
strconv::from_str_common(s, radix, false, false, false,
strconv::ExpNone, false, false)
strconv::from_str_radix_int(s, radix)
}
}
@ -85,10 +64,7 @@ pub fn to_str_bytes<U>(n: $T, radix: uint, f: |v: &[u8]| -> U) -> U {
#[cfg(test)]
mod tests {
use prelude::*;
use super::*;
use str::StrSlice;
use u16;
use num::FromStrRadix;
#[test]
pub fn test_from_str() {
@ -98,23 +74,22 @@ pub fn test_from_str() {
assert_eq!(from_str::<u32>("123456789"), Some(123456789 as u32));
assert_eq!(from_str::<$T>("00100"), Some(100u as $T));
assert!(from_str::<$T>("").is_none());
assert!(from_str::<$T>(" ").is_none());
assert!(from_str::<$T>("x").is_none());
assert_eq!(from_str::<$T>(""), None);
assert_eq!(from_str::<$T>(" "), None);
assert_eq!(from_str::<$T>("x"), None);
}
#[test]
pub fn test_parse_bytes() {
use str::StrSlice;
assert_eq!(parse_bytes("123".as_bytes(), 10u), Some(123u as $T));
assert_eq!(parse_bytes("1001".as_bytes(), 2u), Some(9u as $T));
assert_eq!(parse_bytes("123".as_bytes(), 8u), Some(83u as $T));
assert_eq!(u16::parse_bytes("123".as_bytes(), 16u), Some(291u as u16));
assert_eq!(u16::parse_bytes("ffff".as_bytes(), 16u), Some(65535u as u16));
assert_eq!(parse_bytes("z".as_bytes(), 36u), Some(35u as $T));
assert_eq!(FromStrRadix::from_str_radix("123", 10), Some(123u as $T));
assert_eq!(FromStrRadix::from_str_radix("1001", 2), Some(9u as $T));
assert_eq!(FromStrRadix::from_str_radix("123", 8), Some(83u as $T));
assert_eq!(FromStrRadix::from_str_radix("123", 16), Some(291u as u16));
assert_eq!(FromStrRadix::from_str_radix("ffff", 16), Some(65535u as u16));
assert_eq!(FromStrRadix::from_str_radix("z", 36), Some(35u as $T));
assert!(parse_bytes("Z".as_bytes(), 10u).is_none());
assert!(parse_bytes("_".as_bytes(), 2u).is_none());
assert_eq!(FromStrRadix::from_str_radix("Z", 10), None::<$T>);
assert_eq!(FromStrRadix::from_str_radix("_", 2), None::<$T>);
}
#[test]
@ -148,35 +123,35 @@ fn test_uint_to_str_overflow() {
fn test_uint_from_str_overflow() {
let mut u8_val: u8 = 255_u8;
assert_eq!(from_str::<u8>("255"), Some(u8_val));
assert!(from_str::<u8>("256").is_none());
assert_eq!(from_str::<u8>("256"), None);
u8_val += 1 as u8;
assert_eq!(from_str::<u8>("0"), Some(u8_val));
assert!(from_str::<u8>("-1").is_none());
assert_eq!(from_str::<u8>("-1"), None);
let mut u16_val: u16 = 65_535_u16;
assert_eq!(from_str::<u16>("65535"), Some(u16_val));
assert!(from_str::<u16>("65536").is_none());
assert_eq!(from_str::<u16>("65536"), None);
u16_val += 1 as u16;
assert_eq!(from_str::<u16>("0"), Some(u16_val));
assert!(from_str::<u16>("-1").is_none());
assert_eq!(from_str::<u16>("-1"), None);
let mut u32_val: u32 = 4_294_967_295_u32;
assert_eq!(from_str::<u32>("4294967295"), Some(u32_val));
assert!(from_str::<u32>("4294967296").is_none());
assert_eq!(from_str::<u32>("4294967296"), None);
u32_val += 1 as u32;
assert_eq!(from_str::<u32>("0"), Some(u32_val));
assert!(from_str::<u32>("-1").is_none());
assert_eq!(from_str::<u32>("-1"), None);
let mut u64_val: u64 = 18_446_744_073_709_551_615_u64;
assert_eq!(from_str::<u64>("18446744073709551615"), Some(u64_val));
assert!(from_str::<u64>("18446744073709551616").is_none());
assert_eq!(from_str::<u64>("18446744073709551616"), None);
u64_val += 1 as u64;
assert_eq!(from_str::<u64>("0"), Some(u64_val));
assert!(from_str::<u64>("-1").is_none());
assert_eq!(from_str::<u64>("-1"), None);
}
}

View file

@ -119,7 +119,7 @@ impl Name {
pub fn as_str<'a>(&'a self) -> &'a str {
unsafe {
// FIXME #12938: can't use copy_lifetime since &str isn't a &T
::std::mem::transmute(token::get_name(*self).get())
::std::mem::transmute::<&str,&str>(token::get_name(*self).get())
}
}
@ -385,7 +385,7 @@ pub enum Pat_ {
PatLit(P<Expr>),
PatRange(P<Expr>, P<Expr>),
/// [a, b, ..i, y, z] is represented as:
/// PatVec(~[a, b], Some(i), ~[y, z])
/// PatVec(box [a, b], Some(i), box [y, z])
PatVec(Vec<P<Pat>>, Option<P<Pat>>, Vec<P<Pat>>),
PatMac(Mac),
}
@ -861,10 +861,8 @@ pub enum ImplItem {
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
pub struct AssociatedType {
pub id: NodeId,
pub span: Span,
pub ident: Ident,
pub attrs: Vec<Attribute>,
pub ty_param: TyParam,
}
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]

View file

@ -405,7 +405,9 @@ pub fn get_path_elem(&self, id: NodeId) -> PathElem {
MethMac(_) => panic!("no path elem for {}", node),
}
}
TypeTraitItem(ref m) => PathName(m.ident.name),
TypeTraitItem(ref m) => {
PathName(m.ty_param.ident.name)
}
},
NodeVariant(v) => PathName(v.node.name.name),
_ => panic!("no path elem for {}", node)
@ -510,7 +512,7 @@ pub fn opt_span(&self, id: NodeId) -> Option<Span> {
match *trait_method {
RequiredMethod(ref type_method) => type_method.span,
ProvidedMethod(ref method) => method.span,
TypeTraitItem(ref typedef) => typedef.span,
TypeTraitItem(ref typedef) => typedef.ty_param.span,
}
}
Some(NodeImplItem(ref impl_item)) => {
@ -650,7 +652,7 @@ fn name(&self) -> Name {
match *self {
RequiredMethod(ref tm) => tm.ident.name,
ProvidedMethod(ref m) => m.name(),
TypeTraitItem(ref at) => at.ident.name,
TypeTraitItem(ref at) => at.ty_param.ident.name,
}
}
}
@ -783,7 +785,7 @@ fn visit_item(&mut self, i: &'ast Item) {
self.insert(m.id, NodeTraitItem(tm));
}
TypeTraitItem(ref typ) => {
self.insert(typ.id, NodeTraitItem(tm));
self.insert(typ.ty_param.id, NodeTraitItem(tm));
}
}
}
@ -976,7 +978,7 @@ pub fn map_decoded_item<'ast, F: FoldOps>(map: &Map<'ast>,
let trait_item_id = match *trait_item {
ProvidedMethod(ref m) => m.id,
RequiredMethod(ref m) => m.id,
TypeTraitItem(ref ty) => ty.id,
TypeTraitItem(ref ty) => ty.ty_param.id,
};
collector.insert(trait_item_id, NodeTraitItem(trait_item));
@ -1080,7 +1082,7 @@ fn node_id_to_string(map: &Map, id: NodeId) -> String {
}
TypeTraitItem(ref t) => {
format!("type item {} in {} (id={})",
token::get_ident(t.ident),
token::get_ident(t.ty_param.ident),
map.path_to_string(id),
id)
}

View file

@ -21,7 +21,6 @@
use visit::Visitor;
use visit;
use std::cell::Cell;
use std::cmp;
use std::u32;
@ -333,20 +332,20 @@ pub fn add(&mut self, id: NodeId) {
}
pub trait IdVisitingOperation {
fn visit_id(&self, node_id: NodeId);
fn visit_id(&mut self, node_id: NodeId);
}
/// A visitor that applies its operation to all of the node IDs
/// in a visitable thing.
pub struct IdVisitor<'a, O:'a> {
pub operation: &'a O,
pub operation: &'a mut O,
pub pass_through_items: bool,
pub visited_outermost: bool,
}
impl<'a, O: IdVisitingOperation> IdVisitor<'a, O> {
fn visit_generics_helper(&self, generics: &Generics) {
fn visit_generics_helper(&mut self, generics: &Generics) {
for type_parameter in generics.ty_params.iter() {
self.operation.visit_id(type_parameter.id)
}
@ -525,7 +524,7 @@ fn visit_trait_item(&mut self, tm: &ast::TraitItem) {
match *tm {
ast::RequiredMethod(ref m) => self.operation.visit_id(m.id),
ast::ProvidedMethod(ref m) => self.operation.visit_id(m.id),
ast::TypeTraitItem(ref typ) => self.operation.visit_id(typ.id),
ast::TypeTraitItem(ref typ) => self.operation.visit_id(typ.ty_param.id),
}
visit::walk_trait_item(self, tm);
}
@ -540,7 +539,7 @@ fn visit_lifetime_decl(&mut self, def: &'v LifetimeDef) {
}
pub fn visit_ids_for_inlined_item<O: IdVisitingOperation>(item: &InlinedItem,
operation: &O) {
operation: &mut O) {
let mut id_visitor = IdVisitor {
operation: operation,
pass_through_items: true,
@ -551,23 +550,21 @@ pub fn visit_ids_for_inlined_item<O: IdVisitingOperation>(item: &InlinedItem,
}
struct IdRangeComputingVisitor {
result: Cell<IdRange>,
result: IdRange,
}
impl IdVisitingOperation for IdRangeComputingVisitor {
fn visit_id(&self, id: NodeId) {
let mut id_range = self.result.get();
id_range.add(id);
self.result.set(id_range)
fn visit_id(&mut self, id: NodeId) {
self.result.add(id);
}
}
pub fn compute_id_range_for_inlined_item(item: &InlinedItem) -> IdRange {
let visitor = IdRangeComputingVisitor {
result: Cell::new(IdRange::max())
let mut visitor = IdRangeComputingVisitor {
result: IdRange::max()
};
visit_ids_for_inlined_item(item, &visitor);
visitor.result.get()
visit_ids_for_inlined_item(item, &mut visitor);
visitor.result
}
pub fn compute_id_range_for_fn_body(fk: visit::FnKind,
@ -582,16 +579,16 @@ pub fn compute_id_range_for_fn_body(fk: visit::FnKind,
* ignoring nested items.
*/
let visitor = IdRangeComputingVisitor {
result: Cell::new(IdRange::max())
let mut visitor = IdRangeComputingVisitor {
result: IdRange::max()
};
let mut id_visitor = IdVisitor {
operation: &visitor,
operation: &mut visitor,
pass_through_items: false,
visited_outermost: false,
};
id_visitor.visit_fn(fk, decl, body, sp, id);
visitor.result.get()
id_visitor.operation.result
}
pub fn walk_pat(pat: &Pat, it: |&Pat| -> bool) -> bool {

View file

@ -52,11 +52,19 @@ fn cs_clone(
name: &str,
cx: &mut ExtCtxt, trait_span: Span,
substr: &Substructure) -> P<Expr> {
let clone_ident = substr.method_ident;
let ctor_ident;
let all_fields;
let subcall = |field: &FieldInfo|
cx.expr_method_call(field.span, field.self_.clone(), clone_ident, Vec::new());
let fn_path = vec![
cx.ident_of("std"),
cx.ident_of("clone"),
cx.ident_of("Clone"),
cx.ident_of("clone"),
];
let subcall = |field: &FieldInfo| {
let args = vec![cx.expr_addr_of(field.span, field.self_.clone())];
cx.expr_call_global(field.span, fn_path.clone(), args)
};
match *substr.fields {
Struct(ref af) => {

View file

@ -260,7 +260,7 @@ fn visit_trait_item(&mut self, trait_item: &ast::TraitItem) {
ast::RequiredMethod(_) | ast::ProvidedMethod(_) => {}
ast::TypeTraitItem(ref ti) => {
self.gate_feature("associated_types",
ti.span,
ti.ty_param.span,
"associated types are experimental")
}
}

View file

@ -793,19 +793,16 @@ pub fn noop_fold_typedef<T>(t: Typedef, folder: &mut T)
pub fn noop_fold_associated_type<T>(at: AssociatedType, folder: &mut T)
-> AssociatedType
where T: Folder {
let new_id = folder.new_id(at.id);
let new_span = folder.new_span(at.span);
let new_ident = folder.fold_ident(at.ident);
where T: Folder
{
let new_attrs = at.attrs
.iter()
.map(|attr| folder.fold_attribute((*attr).clone()))
.collect();
let new_param = folder.fold_ty_param(at.ty_param);
ast::AssociatedType {
ident: new_ident,
attrs: new_attrs,
id: new_id,
span: new_span,
ty_param: new_param,
}
}

View file

@ -35,6 +35,19 @@ pub trait Reader {
/// Report a non-fatal error with the current span.
fn err(&self, &str);
fn peek(&self) -> TokenAndSpan;
/// Get a token the parser cares about.
fn real_token(&mut self) -> TokenAndSpan {
let mut t = self.next_token();
loop {
match t.tok {
token::Whitespace | token::Comment | token::Shebang(_) => {
t = self.next_token();
},
_ => break
}
}
t
}
}
#[deriving(Clone, PartialEq, Eq, Show)]

View file

@ -338,27 +338,13 @@ fn is_plain_ident_or_underscore(t: &token::Token) -> bool {
t.is_plain_ident() || *t == token::Underscore
}
/// Get a token the parser cares about
fn real_token(rdr: &mut Reader) -> TokenAndSpan {
let mut t = rdr.next_token();
loop {
match t.tok {
token::Whitespace | token::Comment | token::Shebang(_) => {
t = rdr.next_token();
},
_ => break
}
}
t
}
impl<'a> Parser<'a> {
pub fn new(sess: &'a ParseSess,
cfg: ast::CrateConfig,
mut rdr: Box<Reader+'a>)
-> Parser<'a>
{
let tok0 = real_token(&mut *rdr);
let tok0 = rdr.real_token();
let span = tok0.sp;
let placeholder = TokenAndSpan {
tok: token::Underscore,
@ -898,7 +884,7 @@ pub fn bump(&mut self) {
None
};
let next = if self.buffer_start == self.buffer_end {
real_token(&mut *self.reader)
self.reader.real_token()
} else {
// Avoid token copies with `replace`.
let buffer_start = self.buffer_start as uint;
@ -942,7 +928,7 @@ pub fn look_ahead<R>(&mut self, distance: uint, f: |&token::Token| -> R)
-> R {
let dist = distance as int;
while self.buffer_length() < dist {
self.buffer[self.buffer_end as uint] = real_token(&mut *self.reader);
self.buffer[self.buffer_end as uint] = self.reader.real_token();
self.buffer_end = (self.buffer_end + 1) & 3;
}
f(&self.buffer[((self.buffer_start + dist - 1) & 3) as uint].tok)
@ -1229,16 +1215,13 @@ pub fn parse_ty_fn_decl(&mut self, allow_variadic: bool)
/// Parses `type Foo;` in a trait declaration only. The `type` keyword has
/// already been parsed.
fn parse_associated_type(&mut self, attrs: Vec<Attribute>)
-> AssociatedType {
let lo = self.span.lo;
let ident = self.parse_ident();
let hi = self.span.hi;
-> AssociatedType
{
let ty_param = self.parse_ty_param();
self.expect(&token::Semi);
AssociatedType {
id: ast::DUMMY_NODE_ID,
span: mk_sp(lo, hi),
ident: ident,
attrs: attrs,
ty_param: ty_param,
}
}

View file

@ -668,12 +668,12 @@ pub fn get<'a>(&'a self) -> &'a str {
impl BytesContainer for InternedString {
fn container_as_bytes<'a>(&'a self) -> &'a [u8] {
// FIXME(pcwalton): This is a workaround for the incorrect signature
// FIXME #12938: This is a workaround for the incorrect signature
// of `BytesContainer`, which is itself a workaround for the lack of
// DST.
unsafe {
let this = self.get();
mem::transmute(this.container_as_bytes())
mem::transmute::<&[u8],&[u8]>(this.container_as_bytes())
}
}
}

View file

@ -169,17 +169,14 @@ pub fn to_string(f: |&mut State| -> IoResult<()>) -> String {
let mut s = rust_printer(box MemWriter::new());
f(&mut s).unwrap();
eof(&mut s.s).unwrap();
unsafe {
let wr = unsafe {
// FIXME(pcwalton): A nasty function to extract the string from an `io::Writer`
// that we "know" to be a `MemWriter` that works around the lack of checked
// downcasts.
let obj: TraitObject = mem::transmute_copy(&s.s.out);
let wr: Box<MemWriter> = mem::transmute(obj.data);
let result =
String::from_utf8(wr.get_ref().as_slice().to_vec()).unwrap();
mem::forget(wr);
result.to_string()
}
let obj: &TraitObject = mem::transmute(&s.s.out);
mem::transmute::<*mut (), &MemWriter>(obj.data)
};
String::from_utf8(wr.get_ref().to_vec()).unwrap()
}
pub fn binop_to_string(op: BinOpToken) -> &'static str {
@ -818,9 +815,11 @@ pub fn print_foreign_item(&mut self,
}
fn print_associated_type(&mut self, typedef: &ast::AssociatedType)
-> IoResult<()> {
-> IoResult<()>
{
try!(self.print_outer_attributes(typedef.attrs[]));
try!(self.word_space("type"));
try!(self.print_ident(typedef.ident));
try!(self.print_ty_param(&typedef.ty_param));
word(&mut self.s, ";")
}
@ -2434,23 +2433,7 @@ pub fn print_generics(&mut self,
} else {
let idx = idx - generics.lifetimes.len();
let param = generics.ty_params.get(idx);
match param.unbound {
Some(TraitTyParamBound(ref tref)) => {
try!(s.print_trait_ref(tref));
try!(s.word_space("?"));
}
_ => {}
}
try!(s.print_ident(param.ident));
try!(s.print_bounds(":", &param.bounds));
match param.default {
Some(ref default) => {
try!(space(&mut s.s));
try!(s.word_space("="));
s.print_type(&**default)
}
_ => Ok(())
}
s.print_ty_param(param)
}
}));
@ -2458,6 +2441,26 @@ pub fn print_generics(&mut self,
Ok(())
}
pub fn print_ty_param(&mut self, param: &ast::TyParam) -> IoResult<()> {
match param.unbound {
Some(TraitTyParamBound(ref tref)) => {
try!(self.print_trait_ref(tref));
try!(self.word_space("?"));
}
_ => {}
}
try!(self.print_ident(param.ident));
try!(self.print_bounds(":", &param.bounds));
match param.default {
Some(ref default) => {
try!(space(&mut self.s));
try!(self.word_space("="));
self.print_type(&**default)
}
_ => Ok(())
}
}
pub fn print_where_clause(&mut self, generics: &ast::Generics)
-> IoResult<()> {
if generics.where_clause.predicates.len() == 0 {

View file

@ -596,7 +596,8 @@ pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_method: &'v Tr
RequiredMethod(ref method_type) => visitor.visit_ty_method(method_type),
ProvidedMethod(ref method) => walk_method_helper(visitor, &**method),
TypeTraitItem(ref associated_type) => {
visitor.visit_ident(associated_type.span, associated_type.ident)
visitor.visit_ident(associated_type.ty_param.span,
associated_type.ty_param.ident)
}
}
}

View file

@ -17,7 +17,6 @@
* methods provided by the UnicodeChar trait.
*/
use core::clone::Clone;
use core::cmp;
use core::slice::ImmutableSlice;
use core::iter::{Filter, AdditiveIterator, Iterator, DoubleEndedIterator};

View file

@ -24,7 +24,6 @@
use std::os;
use std::result::{Ok, Err};
use std::task;
use std::uint;
fn fib(n: int) -> int {
fn pfib(tx: &Sender<int>, n: int) {
@ -102,8 +101,7 @@ fn main() {
if opts.stress {
stress(2);
} else {
let max = uint::parse_bytes(args[1].as_bytes(), 10u).unwrap() as
int;
let max = from_str::<uint>(args[1].as_slice()).unwrap() as int;
let num_trials = 10;

View file

@ -0,0 +1,24 @@
// 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.
#![feature(associated_types)]
trait Get {
type Sized? Value;
fn get(&self) -> <Self as Get>::Value;
}
fn foo<T:Get>(t: T) {
let x = t.get(); //~ ERROR the trait `core::kinds::Sized` is not implemented
}
fn main() {
}

View file

@ -17,7 +17,8 @@ struct E {
}
#[deriving(Clone)]
struct C {
x: NoCloneOrEq //~ ERROR does not implement any method in scope named `clone`
x: NoCloneOrEq
//~^ ERROR the trait `core::clone::Clone` is not implemented for the type `NoCloneOrEq`
}

View file

@ -0,0 +1,22 @@
// 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.
// Test that overloaded call parameter checking does not ICE
// when a type error or unconstrained type variable propagates
// into it.
#![feature(overloaded_calls)]
fn main() {
(return)((),());
//~^ ERROR the type of this value must be known
//~^^ ERROR the type of this value must be known
//~^^^ ERROR cannot use call notation
}

View file

@ -10,49 +10,53 @@
#![deny(exceeding_bitshifts)]
#![allow(unused_variables)]
#![allow(dead_code)]
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 << 7;
let n = 1u8 << 8; //~ ERROR: bitshift exceeds the type's number of bits
let n = 1u16 << 15;
let n = 1u16 << 16; //~ ERROR: bitshift exceeds the type's number of bits
let n = 1u32 << 31;
let n = 1u32 << 32; //~ ERROR: bitshift exceeds the type's number of bits
let n = 1u64 << 63;
let n = 1u64 << 64; //~ ERROR: bitshift exceeds the type's number of bits
let n = 1i8 << 7;
let n = 1i8 << 8; //~ ERROR: bitshift exceeds the type's number of bits
let n = 1i16 << 15;
let n = 1i16 << 16; //~ ERROR: bitshift exceeds the type's number of bits
let n = 1i32 << 31;
let n = 1i32 << 32; //~ ERROR: bitshift exceeds the type's number of bits
let n = 1i64 << 63;
let n = 1i64 << 64; //~ 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 >> 7;
let n = 1u8 >> 8; //~ ERROR: bitshift exceeds the type's number of bits
let n = 1u16 >> 15;
let n = 1u16 >> 16; //~ ERROR: bitshift exceeds the type's number of bits
let n = 1u32 >> 31;
let n = 1u32 >> 32; //~ ERROR: bitshift exceeds the type's number of bits
let n = 1u64 >> 63;
let n = 1u64 >> 64; //~ ERROR: bitshift exceeds the type's number of bits
let n = 1i8 >> 7;
let n = 1i8 >> 8; //~ ERROR: bitshift exceeds the type's number of bits
let n = 1i16 >> 15;
let n = 1i16 >> 16; //~ ERROR: bitshift exceeds the type's number of bits
let n = 1i32 >> 31;
let n = 1i32 >> 32; //~ ERROR: bitshift exceeds the type's number of bits
let n = 1i64 >> 63;
let n = 1i64 >> 64; //~ 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 = n << 7;
let n = n << 8; //~ 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 << -8; //~ 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
let n = 1u8 << (4+3);
let n = 1u8 << (4+4); //~ ERROR: bitshift exceeds the type's number of bits
let n = 1i << std::int::BITS; //~ ERROR: bitshift exceeds the type's number of bits
let n = 1u << std::uint::BITS; //~ ERROR: bitshift exceeds the type's number of bits
}

View file

@ -0,0 +1,26 @@
// 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.
// Test calling methods on an impl for a bare trait. This test checks that the
// trait impl is only applied to a trait object, not concrete types which implement
// the trait.
trait T {}
impl<'a> T+'a {
fn foo(&self) {}
}
impl T for int {}
fn main() {
let x = &42i;
x.foo(); //~ERROR: type `&int` does not implement any method in scope named `foo`
}

View file

@ -0,0 +1,24 @@
// 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.
// Test calling methods on an impl for a bare trait. This test checks trait impls
// must be in the same module as the trait.
mod Foo {
trait T {}
}
mod Bar {
impl<'a> ::Foo::T+'a { //~ERROR: inherent implementations may only be implemented in the same
fn foo(&self) {}
}
}
fn main() {}

View file

@ -14,7 +14,7 @@
// Regions that just appear in normal spots are contravariant:
#[rustc_variance]
struct Test2<'a, 'b, 'c> { //~ ERROR regions=[[-, -, -];[];[]]
struct Test2<'a, 'b, 'c> { //~ ERROR regions=[[-, -, -];[];[];[]]
x: &'a int,
y: &'b [int],
c: &'c str
@ -23,7 +23,7 @@
// Those same annotations in function arguments become covariant:
#[rustc_variance]
struct Test3<'a, 'b, 'c> { //~ ERROR regions=[[+, +, +];[];[]]
struct Test3<'a, 'b, 'c> { //~ ERROR regions=[[+, +, +];[];[];[]]
x: extern "Rust" fn(&'a int),
y: extern "Rust" fn(&'b [int]),
c: extern "Rust" fn(&'c str),
@ -32,7 +32,7 @@
// Mutability induces invariance:
#[rustc_variance]
struct Test4<'a, 'b:'a> { //~ ERROR regions=[[-, o];[];[]]
struct Test4<'a, 'b:'a> { //~ ERROR regions=[[-, o];[];[];[]]
x: &'a mut &'b int,
}
@ -40,7 +40,7 @@
// contravariant context:
#[rustc_variance]
struct Test5<'a, 'b> { //~ ERROR regions=[[+, o];[];[]]
struct Test5<'a, 'b> { //~ ERROR regions=[[+, o];[];[];[]]
x: extern "Rust" fn(&'a mut &'b int),
}
@ -50,21 +50,21 @@
// argument list occurs in an invariant context.
#[rustc_variance]
struct Test6<'a, 'b> { //~ ERROR regions=[[-, o];[];[]]
struct Test6<'a, 'b> { //~ ERROR regions=[[-, o];[];[];[]]
x: &'a mut extern "Rust" fn(&'b int),
}
// No uses at all is bivariant:
#[rustc_variance]
struct Test7<'a> { //~ ERROR regions=[[*];[];[]]
struct Test7<'a> { //~ ERROR regions=[[*];[];[];[]]
x: int
}
// Try enums too.
#[rustc_variance]
enum Test8<'a, 'b, 'c:'b> { //~ ERROR regions=[[+, -, o];[];[]]
enum Test8<'a, 'b, 'c:'b> { //~ ERROR regions=[[+, -, o];[];[];[]]
Test8A(extern "Rust" fn(&'a int)),
Test8B(&'b [int]),
Test8C(&'b mut &'c str),

View file

@ -13,29 +13,29 @@
// Try enums too.
#[rustc_variance]
enum Base<'a, 'b, 'c:'b, 'd> { //~ ERROR regions=[[+, -, o, *];[];[]]
enum Base<'a, 'b, 'c:'b, 'd> { //~ ERROR regions=[[+, -, o, *];[];[];[]]
Test8A(extern "Rust" fn(&'a int)),
Test8B(&'b [int]),
Test8C(&'b mut &'c str),
}
#[rustc_variance]
struct Derived1<'w, 'x:'y, 'y, 'z> { //~ ERROR regions=[[*, o, -, +];[];[]]
struct Derived1<'w, 'x:'y, 'y, 'z> { //~ ERROR regions=[[*, o, -, +];[];[];[]]
f: Base<'z, 'y, 'x, 'w>
}
#[rustc_variance] // Combine - and + to yield o
struct Derived2<'a, 'b:'a, 'c> { //~ ERROR regions=[[o, o, *];[];[]]
struct Derived2<'a, 'b:'a, 'c> { //~ ERROR regions=[[o, o, *];[];[];[]]
f: Base<'a, 'a, 'b, 'c>
}
#[rustc_variance] // Combine + and o to yield o (just pay attention to 'a here)
struct Derived3<'a:'b, 'b, 'c> { //~ ERROR regions=[[o, -, *];[];[]]
struct Derived3<'a:'b, 'b, 'c> { //~ ERROR regions=[[o, -, *];[];[];[]]
f: Base<'a, 'b, 'a, 'c>
}
#[rustc_variance] // Combine + and * to yield + (just pay attention to 'a here)
struct Derived4<'a, 'b, 'c:'b> { //~ ERROR regions=[[+, -, o];[];[]]
struct Derived4<'a, 'b, 'c:'b> { //~ ERROR regions=[[+, -, o];[];[];[]]
f: Base<'a, 'b, 'c, 'a>
}

View file

@ -19,7 +19,7 @@
trait T { fn foo(); }
#[rustc_variance]
struct TOption<'a> { //~ ERROR regions=[[-];[];[]]
struct TOption<'a> { //~ ERROR regions=[[-];[];[];[]]
v: Option<Box<T + 'a>>,
}

View file

@ -0,0 +1,16 @@
// 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.
#[deriving(Clone)]
enum Test<'a> {
Slice(&'a int)
}
fn main() {}

View file

@ -0,0 +1,36 @@
// 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.
// Test calling methods on an impl for a bare trait.
static mut COUNT: uint = 1;
trait T {}
impl<'a> T+'a {
fn foo(&self) {
unsafe { COUNT *= 2; }
}
fn bar() {
unsafe { COUNT *= 3; }
}
}
impl T for int {}
fn main() {
let x: &T = &42i;
x.foo();
T::foo(x);
T::bar();
unsafe { assert!(COUNT == 12); }
}