Auto merge of #22153 - alexcrichton:rollup, r=alexcrichton
This commit is contained in:
commit
bc87efef2c
configure
src
compiletest
doc
liballoc
libarena
libcollections
libcore
libcoretest
libgetopts
liblibc
librustc
librustc_borrowck/borrowck/gather_loans
librustc_privacy
librustc_typeck/check
librustdoc
libserialize
libstd
libsyntax
libterm
test
compile-fail
cfg-attr-cfg-2.rscfg-attr-crate-2.rsfunctional-struct-update-respects-privacy.rsissue-17551.rsissue-17999.rsissue-20801.rsissue-2150.rsliveness-unused.rsreserved-become.rs
run-make
c-link-to-rust-staticlib
duplicate-output-flavors
empty-file
issue-22131
no-stack-check
symbols-are-reasonable
target-specs
use-extern-for-plugins
run-pass
3
configure
vendored
3
configure
vendored
@ -525,6 +525,7 @@ opt verify-install 1 "verify installed binaries work"
|
||||
opt dist-host-only 0 "only install bins for the host architecture"
|
||||
opt inject-std-version 1 "inject the current compiler version of libstd into programs"
|
||||
opt jemalloc 1 "build liballoc with jemalloc"
|
||||
opt llvm-version-check 1 "don't check if the LLVM version is supported, build anyway"
|
||||
|
||||
valopt localstatedir "/var/lib" "local state directory"
|
||||
valopt sysconfdir "/etc" "install system configuration files"
|
||||
@ -796,7 +797,7 @@ then
|
||||
putvar CFG_ENABLE_CLANG
|
||||
fi
|
||||
|
||||
if [ ! -z "$CFG_LLVM_ROOT" -a -e "$CFG_LLVM_ROOT/bin/llvm-config" ]
|
||||
if [ ! -z "$CFG_LLVM_ROOT" -a -z "$CFG_DISABLE_LLVM_VERSION_CHECK" -a -e "$CFG_LLVM_ROOT/bin/llvm-config" ]
|
||||
then
|
||||
step_msg "using custom LLVM at $CFG_LLVM_ROOT"
|
||||
|
||||
|
@ -12,7 +12,6 @@
|
||||
|
||||
#![feature(box_syntax)]
|
||||
#![feature(collections)]
|
||||
#![feature(core)]
|
||||
#![feature(int_uint)]
|
||||
#![feature(io)]
|
||||
#![feature(os)]
|
||||
|
@ -157,7 +157,7 @@ token : simple_token | ident | literal | symbol | whitespace token ;
|
||||
|
||||
| | | | | |
|
||||
|----------|----------|----------|----------|--------|
|
||||
| abstract | alignof | as | be | box |
|
||||
| abstract | alignof | as | become | box |
|
||||
| break | const | continue | crate | do |
|
||||
| else | enum | extern | false | final |
|
||||
| fn | for | if | impl | in |
|
||||
|
@ -59,8 +59,7 @@ tools we have are really nice.
|
||||
[Cargo](http://crates.io) is Rust's package manager, and its website contains
|
||||
lots of good documentation.
|
||||
|
||||
[The `rustdoc` manual](rustdoc.html) contains information about Rust's
|
||||
documentation tool.
|
||||
[`rustdoc`](book/documentation.html) is used to generate documentation for Rust code.
|
||||
|
||||
# FAQs
|
||||
|
||||
|
@ -189,7 +189,7 @@ grammar as double-quoted strings. Other tokens have exact rules given.
|
||||
|
||||
| | | | | |
|
||||
|----------|----------|----------|----------|---------|
|
||||
| abstract | alignof | as | be | box |
|
||||
| abstract | alignof | as | become | box |
|
||||
| break | const | continue | crate | do |
|
||||
| else | enum | extern | false | final |
|
||||
| fn | for | if | impl | in |
|
||||
@ -381,11 +381,13 @@ character (`\`), or a single _escape_. It is equivalent to a `u8` unsigned
|
||||
|
||||
##### Byte string literals
|
||||
|
||||
A _byte string literal_ is a sequence of ASCII characters and _escapes_
|
||||
enclosed within two `U+0022` (double-quote) characters, with the exception of
|
||||
`U+0022` itself, which must be _escaped_ by a preceding `U+005C` character
|
||||
(`\`), or a _raw byte string literal_. It is equivalent to a `&'static [u8]`
|
||||
borrowed array of unsigned 8-bit integers.
|
||||
A non-raw _byte string literal_ is a sequence of ASCII characters and _escapes_,
|
||||
preceded by the characters `U+0062` (`b`) and `U+0022` (double-quote), and
|
||||
followed by the character `U+0022`. If the character `U+0022` is present within
|
||||
the literal, it must be _escaped_ by a preceding `U+005C` (`\`) character.
|
||||
Alternatively, a byte string literal can be a _raw byte string literal_, defined
|
||||
below. A byte string literal is equivalent to a `&'static [u8]` borrowed array
|
||||
of unsigned 8-bit integers.
|
||||
|
||||
Some additional _escapes_ are available in either byte or non-raw byte string
|
||||
literals. An escape starts with a `U+005C` (`\`) and continues with one of the
|
||||
@ -1253,9 +1255,7 @@ fn my_err(s: &str) -> ! {
|
||||
We call such functions "diverging" because they never return a value to the
|
||||
caller. Every control path in a diverging function must end with a `panic!()` or
|
||||
a call to another diverging function on every control path. The `!` annotation
|
||||
does *not* denote a type. Rather, the result type of a diverging function is a
|
||||
special type called ⊥ ("bottom") that unifies with any type. Rust has no
|
||||
syntax for ⊥.
|
||||
does *not* denote a type.
|
||||
|
||||
It might be necessary to declare a diverging function because as mentioned
|
||||
previously, the typechecker checks that every control path in a function ends
|
||||
@ -2354,8 +2354,8 @@ Supported traits for `derive` are:
|
||||
* `FromPrimitive`, to create an instance from a numeric primitive.
|
||||
* `Hash`, to iterate over the bytes in a data type.
|
||||
* `Rand`, to create a random instance of a data type.
|
||||
* `Show`, to format a value using the `{}` formatter.
|
||||
* `Zero`, to create a zero instance of a numeric data type.
|
||||
* `Debug`, to format a value using the `{:?}` formatter.
|
||||
* `Copy`, for "Plain Old Data" types which can be copied by simply moving bits.
|
||||
|
||||
### Compiler Features
|
||||
|
||||
|
@ -58,7 +58,7 @@
|
||||
body {
|
||||
margin: 0 auto;
|
||||
padding: 0 15px;
|
||||
font-family: "Source Serif Pro", "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
font-family: "Source Serif Pro", Georgia, Times, "Times New Roman", serif;
|
||||
font-size: 18px;
|
||||
color: #333;
|
||||
line-height: 1.428571429;
|
||||
|
@ -27,6 +27,7 @@
|
||||
* [Iterators](iterators.md)
|
||||
* [Generics](generics.md)
|
||||
* [Traits](traits.md)
|
||||
* [Static and Dynamic Dispatch](static-and-dynamic-dispatch.md)
|
||||
* [Concurrency](concurrency.md)
|
||||
* [Error Handling](error-handling.md)
|
||||
* [Documentation](documentation.md)
|
||||
|
@ -9,7 +9,7 @@ arguments, really powerful things are possible.
|
||||
Let's make a closure:
|
||||
|
||||
```{rust}
|
||||
let add_one = |&: x| { 1 + x };
|
||||
let add_one = |x| { 1 + x };
|
||||
|
||||
println!("The sum of 5 plus 1 is {}.", add_one(5));
|
||||
```
|
||||
@ -21,8 +21,8 @@ binding name and two parentheses, just like we would for a named function.
|
||||
Let's compare syntax. The two are pretty close:
|
||||
|
||||
```{rust}
|
||||
let add_one = |&: x: i32| -> i32 { 1 + x };
|
||||
fn add_one (x: i32) -> i32 { 1 + x }
|
||||
let add_one = |x: i32| -> i32 { 1 + x };
|
||||
fn add_one (x: i32) -> i32 { 1 + x }
|
||||
```
|
||||
|
||||
As you may have noticed, closures infer their argument and return types, so you
|
||||
@ -37,7 +37,7 @@ this:
|
||||
fn main() {
|
||||
let x: i32 = 5;
|
||||
|
||||
let printer = |&:| { println!("x is: {}", x); };
|
||||
let printer = || { println!("x is: {}", x); };
|
||||
|
||||
printer(); // prints "x is: 5"
|
||||
}
|
||||
@ -53,7 +53,7 @@ defined. The closure borrows any variables it uses, so this will error:
|
||||
fn main() {
|
||||
let mut x: i32 = 5;
|
||||
|
||||
let printer = |&:| { println!("x is: {}", x); };
|
||||
let printer = || { println!("x is: {}", x); };
|
||||
|
||||
x = 6; // error: cannot assign to `x` because it is borrowed
|
||||
}
|
||||
@ -80,7 +80,7 @@ fn twice<F: Fn(i32) -> i32>(x: i32, f: F) -> i32 {
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let square = |&: x: i32| { x * x };
|
||||
let square = |x: i32| { x * x };
|
||||
|
||||
twice(5, square); // evaluates to 50
|
||||
}
|
||||
@ -89,7 +89,7 @@ fn main() {
|
||||
Let's break the example down, starting with `main`:
|
||||
|
||||
```{rust}
|
||||
let square = |&: x: i32| { x * x };
|
||||
let square = |x: i32| { x * x };
|
||||
```
|
||||
|
||||
We've seen this before. We make a closure that takes an integer, and returns
|
||||
@ -97,7 +97,7 @@ its square.
|
||||
|
||||
```{rust}
|
||||
# fn twice<F: Fn(i32) -> i32>(x: i32, f: F) -> i32 { f(x) + f(x) }
|
||||
# let square = |&: x: i32| { x * x };
|
||||
# let square = |x: i32| { x * x };
|
||||
twice(5, square); // evaluates to 50
|
||||
```
|
||||
|
||||
@ -184,8 +184,8 @@ fn compose<F, G>(x: i32, f: F, g: G) -> i32
|
||||
|
||||
fn main() {
|
||||
compose(5,
|
||||
|&: n: i32| { n + 42 },
|
||||
|&: n: i32| { n * 2 }); // evaluates to 94
|
||||
|n: i32| { n + 42 },
|
||||
|n: i32| { n * 2 }); // evaluates to 94
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -72,6 +72,20 @@ if x == y {
|
||||
|
||||
This will print `no`, because some of the values aren't equal.
|
||||
|
||||
Note that the order of the values is considered when checking for equality,
|
||||
so the following example will also print `no`.
|
||||
|
||||
```rust
|
||||
let x = (1, 2, 3);
|
||||
let y = (2, 1, 3);
|
||||
|
||||
if x == y {
|
||||
println!("yes");
|
||||
} else {
|
||||
println!("no");
|
||||
}
|
||||
```
|
||||
|
||||
One other use of tuples is to return multiple values from a function:
|
||||
|
||||
```rust
|
||||
|
286
src/doc/trpl/static-and-dynamic-dispatch.md
Normal file
286
src/doc/trpl/static-and-dynamic-dispatch.md
Normal file
@ -0,0 +1,286 @@
|
||||
% Static and Dynamic Dispatch
|
||||
|
||||
When code involves polymorphism, there needs to be a mechanism to determine
|
||||
which specific version is actually run. This is called 'dispatch.' There are
|
||||
two major forms of dispatch: static dispatch and dynamic dispatch. While Rust
|
||||
favors static dispatch, it also supports dynamic dispatch through a mechanism
|
||||
called 'trait objects.'
|
||||
|
||||
## Background
|
||||
|
||||
For the rest of this chapter, we'll need a trait and some implementations.
|
||||
Let's make a simple one, `Foo`. It has one method that is expected to return a
|
||||
`String`.
|
||||
|
||||
```rust
|
||||
trait Foo {
|
||||
fn method(&self) -> String;
|
||||
}
|
||||
```
|
||||
|
||||
We'll also implement this trait for `u8` and `String`:
|
||||
|
||||
```rust
|
||||
# trait Foo { fn method(&self) -> String; }
|
||||
impl Foo for u8 {
|
||||
fn method(&self) -> String { format!("u8: {}", *self) }
|
||||
}
|
||||
|
||||
impl Foo for String {
|
||||
fn method(&self) -> String { format!("string: {}", *self) }
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## Static dispatch
|
||||
|
||||
We can use this trait to perform static dispatch with trait bounds:
|
||||
|
||||
```rust
|
||||
# trait Foo { fn method(&self) -> String; }
|
||||
# impl Foo for u8 { fn method(&self) -> String { format!("u8: {}", *self) } }
|
||||
# impl Foo for String { fn method(&self) -> String { format!("string: {}", *self) } }
|
||||
fn do_something<T: Foo>(x: T) {
|
||||
x.method();
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let x = 5u8;
|
||||
let y = "Hello".to_string();
|
||||
|
||||
do_something(x);
|
||||
do_something(y);
|
||||
}
|
||||
```
|
||||
|
||||
Rust uses 'monomorphization' to perform static dispatch here. This means that
|
||||
Rust will create a special version of `do_something()` for both `u8` and
|
||||
`String`, and then replace the call sites with calls to these specialized
|
||||
functions. In other words, Rust generates something like this:
|
||||
|
||||
```rust
|
||||
# trait Foo { fn method(&self) -> String; }
|
||||
# impl Foo for u8 { fn method(&self) -> String { format!("u8: {}", *self) } }
|
||||
# impl Foo for String { fn method(&self) -> String { format!("string: {}", *self) } }
|
||||
fn do_something_u8(x: u8) {
|
||||
x.method();
|
||||
}
|
||||
|
||||
fn do_something_string(x: String) {
|
||||
x.method();
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let x = 5u8;
|
||||
let y = "Hello".to_string();
|
||||
|
||||
do_something_u8(x);
|
||||
do_something_string(y);
|
||||
}
|
||||
```
|
||||
|
||||
This has some upsides: static dispatching of any method calls, allowing for
|
||||
inlining and hence usually higher performance. It also has some downsides:
|
||||
causing code bloat due to many copies of the same function existing in the
|
||||
binary, one for each type.
|
||||
|
||||
Furthermore, compilers aren’t perfect and may “optimise” code to become slower.
|
||||
For example, functions inlined too eagerly will bloat the instruction cache
|
||||
(cache rules everything around us). This is part of the reason that `#[inline]`
|
||||
and `#[inline(always)]` should be used carefully, and one reason why using a
|
||||
dynamic dispatch is sometimes more efficient.
|
||||
|
||||
However, the common case is that it is more efficient to use static dispatch,
|
||||
and one can always have a thin statically-dispatched wrapper function that does
|
||||
a dynamic, but not vice versa, meaning static calls are more flexible. The
|
||||
standard library tries to be statically dispatched where possible for this
|
||||
reason.
|
||||
|
||||
## Dynamic dispatch
|
||||
|
||||
Rust provides dynamic dispatch through a feature called 'trait objects.' Trait
|
||||
objects, like `&Foo` or `Box<Foo>`, are normal values that store a value of
|
||||
*any* type that implements the given trait, where the precise type can only be
|
||||
known at runtime. The methods of the trait can be called on a trait object via
|
||||
a special record of function pointers (created and managed by the compiler).
|
||||
|
||||
A function that takes a trait object is not specialised to each of the types
|
||||
that implements `Foo`: only one copy is generated, often (but not always)
|
||||
resulting in less code bloat. However, this comes at the cost of requiring
|
||||
slower virtual function calls, and effectively inhibiting any chance of
|
||||
inlining and related optimisations from occurring.
|
||||
|
||||
Trait objects are both simple and complicated: their core representation and
|
||||
layout is quite straight-forward, but there are some curly error messages and
|
||||
surprising behaviours to discover.
|
||||
|
||||
### Obtaining a trait object
|
||||
|
||||
There's two similar ways to get a trait object value: casts and coercions. If
|
||||
`T` is a type that implements a trait `Foo` (e.g. `u8` for the `Foo` above),
|
||||
then the two ways to get a `Foo` trait object out of a pointer to `T` look
|
||||
like:
|
||||
|
||||
```{rust,ignore}
|
||||
let ref_to_t: &T = ...;
|
||||
|
||||
// `as` keyword for casting
|
||||
let cast = ref_to_t as &Foo;
|
||||
|
||||
// using a `&T` in a place that has a known type of `&Foo` will implicitly coerce:
|
||||
let coerce: &Foo = ref_to_t;
|
||||
|
||||
fn also_coerce(_unused: &Foo) {}
|
||||
also_coerce(ref_to_t);
|
||||
```
|
||||
|
||||
These trait object coercions and casts also work for pointers like `&mut T` to
|
||||
`&mut Foo` and `Box<T>` to `Box<Foo>`, but that's all at the moment. Coercions
|
||||
and casts are identical.
|
||||
|
||||
This operation can be seen as "erasing" the compiler's knowledge about the
|
||||
specific type of the pointer, and hence trait objects are sometimes referred to
|
||||
"type erasure".
|
||||
|
||||
### Representation
|
||||
|
||||
Let's start simple, with the runtime representation of a trait object. The
|
||||
`std::raw` module contains structs with layouts that are the same as the
|
||||
complicated build-in types, [including trait objects][stdraw]:
|
||||
|
||||
```rust
|
||||
# mod foo {
|
||||
pub struct TraitObject {
|
||||
pub data: *mut (),
|
||||
pub vtable: *mut (),
|
||||
}
|
||||
# }
|
||||
```
|
||||
|
||||
[stdraw]: ../std/raw/struct.TraitObject.html
|
||||
|
||||
That is, a trait object like `&Foo` consists of a "data" pointer and a "vtable"
|
||||
pointer.
|
||||
|
||||
The data pointer addresses the data (of some unknown type `T`) that the trait
|
||||
object is storing, and the vtable pointer points to the vtable ("virtual method
|
||||
table") corresponding to the implementation of `Foo` for `T`.
|
||||
|
||||
|
||||
A vtable is essentially a struct of function pointers, pointing to the concrete
|
||||
piece of machine code for each method in the implementation. A method call like
|
||||
`trait_object.method()` will retrieve the correct pointer out of the vtable and
|
||||
then do a dynamic call of it. For example:
|
||||
|
||||
```{rust,ignore}
|
||||
struct FooVtable {
|
||||
destructor: fn(*mut ()),
|
||||
size: usize,
|
||||
align: usize,
|
||||
method: fn(*const ()) -> String,
|
||||
}
|
||||
|
||||
// u8:
|
||||
|
||||
fn call_method_on_u8(x: *const ()) -> String {
|
||||
// the compiler guarantees that this function is only called
|
||||
// with `x` pointing to a u8
|
||||
let byte: &u8 = unsafe { &*(x as *const u8) };
|
||||
|
||||
byte.method()
|
||||
}
|
||||
|
||||
static Foo_for_u8_vtable: FooVtable = FooVtable {
|
||||
destructor: /* compiler magic */,
|
||||
size: 1,
|
||||
align: 1,
|
||||
|
||||
// cast to a function pointer
|
||||
method: call_method_on_u8 as fn(*const ()) -> String,
|
||||
};
|
||||
|
||||
|
||||
// String:
|
||||
|
||||
fn call_method_on_String(x: *const ()) -> String {
|
||||
// the compiler guarantees that this function is only called
|
||||
// with `x` pointing to a String
|
||||
let string: &String = unsafe { &*(x as *const String) };
|
||||
|
||||
string.method()
|
||||
}
|
||||
|
||||
static Foo_for_String_vtable: FooVtable = FooVtable {
|
||||
destructor: /* compiler magic */,
|
||||
// values for a 64-bit computer, halve them for 32-bit ones
|
||||
size: 24,
|
||||
align: 8,
|
||||
|
||||
method: call_method_on_String as fn(*const ()) -> String,
|
||||
};
|
||||
```
|
||||
|
||||
The `destructor` field in each vtable points to a function that will clean up
|
||||
any resources of the vtable's type, for `u8` it is trivial, but for `String` it
|
||||
will free the memory. This is necessary for owning trait objects like
|
||||
`Box<Foo>`, which need to clean-up both the `Box` allocation and as well as the
|
||||
internal type when they go out of scope. The `size` and `align` fields store
|
||||
the size of the erased type, and its alignment requirements; these are
|
||||
essentially unused at the moment since the information is embedded in the
|
||||
destructor, but will be used in future, as trait objects are progressively made
|
||||
more flexible.
|
||||
|
||||
Suppose we've got some values that implement `Foo`, the explicit form of
|
||||
construction and use of `Foo` trait objects might look a bit like (ignoring the
|
||||
type mismatches: they're all just pointers anyway):
|
||||
|
||||
```{rust,ignore}
|
||||
let a: String = "foo".to_string();
|
||||
let x: u8 = 1;
|
||||
|
||||
// let b: &Foo = &a;
|
||||
let b = TraitObject {
|
||||
// store the data
|
||||
data: &a,
|
||||
// store the methods
|
||||
vtable: &Foo_for_String_vtable
|
||||
};
|
||||
|
||||
// let y: &Foo = x;
|
||||
let y = TraitObject {
|
||||
// store the data
|
||||
data: &x,
|
||||
// store the methods
|
||||
vtable: &Foo_for_u8_vtable
|
||||
};
|
||||
|
||||
// b.method();
|
||||
(b.vtable.method)(b.data);
|
||||
|
||||
// y.method();
|
||||
(y.vtable.method)(y.data);
|
||||
```
|
||||
|
||||
If `b` or `y` were owning trait objects (`Box<Foo>`), there would be a
|
||||
`(b.vtable.destructor)(b.data)` (respectively `y`) call when they went out of
|
||||
scope.
|
||||
|
||||
### Why pointers?
|
||||
|
||||
The use of language like "fat pointer" implies that a trait object is
|
||||
always a pointer of some form, but why?
|
||||
|
||||
Rust does not put things behind a pointer by default, unlike many managed
|
||||
languages, so types can have different sizes. Knowing the size of the value at
|
||||
compile time is important for things like passing it as an argument to a
|
||||
function, moving it about on the stack and allocating (and deallocating) space
|
||||
on the heap to store it.
|
||||
|
||||
For `Foo`, we would need to have a value that could be at least either a
|
||||
`String` (24 bytes) or a `u8` (1 byte), as well as any other type for which
|
||||
dependent crates may implement `Foo` (any number of bytes at all). There's no
|
||||
way to guarantee that this last point can work if the values are stored without
|
||||
a pointer, because those other types can be arbitrarily large.
|
||||
|
||||
Putting the value behind a pointer means the size of the value is not relevant
|
||||
when we are tossing a trait object around, only the size of the pointer itself.
|
@ -270,51 +270,8 @@ not, because both the trait and the type aren't in our crate.
|
||||
|
||||
One last thing about traits: generic functions with a trait bound use
|
||||
*monomorphization* (*mono*: one, *morph*: form), so they are statically
|
||||
dispatched. What's that mean? Well, let's take a look at `print_area` again:
|
||||
|
||||
```{rust,ignore}
|
||||
fn print_area<T: HasArea>(shape: T) {
|
||||
println!("This shape has an area of {}", shape.area());
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let c = Circle { ... };
|
||||
|
||||
let s = Square { ... };
|
||||
|
||||
print_area(c);
|
||||
print_area(s);
|
||||
}
|
||||
```
|
||||
|
||||
When we use this trait with `Circle` and `Square`, Rust ends up generating
|
||||
two different functions with the concrete type, and replacing the call sites with
|
||||
calls to the concrete implementations. In other words, you get something like
|
||||
this:
|
||||
|
||||
```{rust,ignore}
|
||||
fn __print_area_circle(shape: Circle) {
|
||||
println!("This shape has an area of {}", shape.area());
|
||||
}
|
||||
|
||||
fn __print_area_square(shape: Square) {
|
||||
println!("This shape has an area of {}", shape.area());
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let c = Circle { ... };
|
||||
|
||||
let s = Square { ... };
|
||||
|
||||
__print_area_circle(c);
|
||||
__print_area_square(s);
|
||||
}
|
||||
```
|
||||
|
||||
The names don't actually change to this, it's just for illustration. But
|
||||
as you can see, there's no overhead of deciding which version to call here,
|
||||
hence *statically dispatched*. The downside is that we have two copies of
|
||||
the same function, so our binary is a little bit larger.
|
||||
dispatched. What's that mean? Check out the chapter on [static and dynamic
|
||||
dispatch](static-and-dynamic-dispatch.html) for more.
|
||||
|
||||
## Our `inverse` Example
|
||||
|
||||
|
@ -206,12 +206,12 @@ impl<T> Arc<T> {
|
||||
/// Get the number of weak references to this value.
|
||||
#[inline]
|
||||
#[unstable(feature = "alloc")]
|
||||
pub fn weak_count<T>(this: &Arc<T>) -> uint { this.inner().weak.load(SeqCst) - 1 }
|
||||
pub fn weak_count<T>(this: &Arc<T>) -> usize { this.inner().weak.load(SeqCst) - 1 }
|
||||
|
||||
/// Get the number of strong references to this value.
|
||||
#[inline]
|
||||
#[unstable(feature = "alloc")]
|
||||
pub fn strong_count<T>(this: &Arc<T>) -> uint { this.inner().strong.load(SeqCst) }
|
||||
pub fn strong_count<T>(this: &Arc<T>) -> usize { this.inner().strong.load(SeqCst) }
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T> Clone for Arc<T> {
|
||||
@ -649,7 +649,7 @@ mod tests {
|
||||
let (tx, rx) = channel();
|
||||
|
||||
let _t = Thread::spawn(move || {
|
||||
let arc_v: Arc<Vec<int>> = rx.recv().unwrap();
|
||||
let arc_v: Arc<Vec<i32>> = rx.recv().unwrap();
|
||||
assert_eq!((*arc_v)[3], 4);
|
||||
});
|
||||
|
||||
@ -818,5 +818,5 @@ mod tests {
|
||||
|
||||
// Make sure deriving works with Arc<T>
|
||||
#[derive(Eq, Ord, PartialEq, PartialOrd, Clone, Debug, Default)]
|
||||
struct Foo { inner: Arc<int> }
|
||||
struct Foo { inner: Arc<i32> }
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ use std::boxed::BoxAny;
|
||||
#[test]
|
||||
fn test_owned_clone() {
|
||||
let a = Box::new(5);
|
||||
let b: Box<int> = a.clone();
|
||||
let b: Box<i32> = a.clone();
|
||||
assert!(a == b);
|
||||
}
|
||||
|
||||
@ -31,11 +31,11 @@ struct Test;
|
||||
|
||||
#[test]
|
||||
fn any_move() {
|
||||
let a = Box::new(8us) as Box<Any>;
|
||||
let a = Box::new(8) as Box<Any>;
|
||||
let b = Box::new(Test) as Box<Any>;
|
||||
|
||||
match a.downcast::<uint>() {
|
||||
Ok(a) => { assert!(a == Box::new(8us)); }
|
||||
match a.downcast::<i32>() {
|
||||
Ok(a) => { assert!(a == Box::new(8)); }
|
||||
Err(..) => panic!()
|
||||
}
|
||||
match b.downcast::<Test>() {
|
||||
@ -47,7 +47,7 @@ fn any_move() {
|
||||
let b = Box::new(Test) as Box<Any>;
|
||||
|
||||
assert!(a.downcast::<Box<Test>>().is_err());
|
||||
assert!(b.downcast::<Box<uint>>().is_err());
|
||||
assert!(b.downcast::<Box<i32>>().is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -21,7 +21,7 @@ use core::ptr::PtrExt;
|
||||
/// power of 2. The alignment must be no larger than the largest supported page
|
||||
/// size on the platform.
|
||||
#[inline]
|
||||
pub unsafe fn allocate(size: uint, align: uint) -> *mut u8 {
|
||||
pub unsafe fn allocate(size: usize, align: usize) -> *mut u8 {
|
||||
imp::allocate(size, align)
|
||||
}
|
||||
|
||||
@ -37,7 +37,7 @@ pub unsafe fn allocate(size: uint, align: uint) -> *mut u8 {
|
||||
/// create the allocation referenced by `ptr`. The `old_size` parameter may be
|
||||
/// any value in range_inclusive(requested_size, usable_size).
|
||||
#[inline]
|
||||
pub unsafe fn reallocate(ptr: *mut u8, old_size: uint, size: uint, align: uint) -> *mut u8 {
|
||||
pub unsafe fn reallocate(ptr: *mut u8, old_size: usize, size: usize, align: usize) -> *mut u8 {
|
||||
imp::reallocate(ptr, old_size, size, align)
|
||||
}
|
||||
|
||||
@ -54,7 +54,8 @@ pub unsafe fn reallocate(ptr: *mut u8, old_size: uint, size: uint, align: uint)
|
||||
/// create the allocation referenced by `ptr`. The `old_size` parameter may be
|
||||
/// any value in range_inclusive(requested_size, usable_size).
|
||||
#[inline]
|
||||
pub unsafe fn reallocate_inplace(ptr: *mut u8, old_size: uint, size: uint, align: uint) -> uint {
|
||||
pub unsafe fn reallocate_inplace(ptr: *mut u8, old_size: usize, size: usize,
|
||||
align: usize) -> usize {
|
||||
imp::reallocate_inplace(ptr, old_size, size, align)
|
||||
}
|
||||
|
||||
@ -66,14 +67,14 @@ pub unsafe fn reallocate_inplace(ptr: *mut u8, old_size: uint, size: uint, align
|
||||
/// create the allocation referenced by `ptr`. The `old_size` parameter may be
|
||||
/// any value in range_inclusive(requested_size, usable_size).
|
||||
#[inline]
|
||||
pub unsafe fn deallocate(ptr: *mut u8, old_size: uint, align: uint) {
|
||||
pub unsafe fn deallocate(ptr: *mut u8, old_size: usize, align: usize) {
|
||||
imp::deallocate(ptr, old_size, align)
|
||||
}
|
||||
|
||||
/// Returns the usable size of an allocation created with the specified the
|
||||
/// `size` and `align`.
|
||||
#[inline]
|
||||
pub fn usable_size(size: uint, align: uint) -> uint {
|
||||
pub fn usable_size(size: usize, align: usize) -> usize {
|
||||
imp::usable_size(size, align)
|
||||
}
|
||||
|
||||
@ -96,7 +97,7 @@ pub const EMPTY: *mut () = 0x1 as *mut ();
|
||||
#[cfg(not(test))]
|
||||
#[lang="exchange_malloc"]
|
||||
#[inline]
|
||||
unsafe fn exchange_malloc(size: uint, align: uint) -> *mut u8 {
|
||||
unsafe fn exchange_malloc(size: usize, align: usize) -> *mut u8 {
|
||||
if size == 0 {
|
||||
EMPTY as *mut u8
|
||||
} else {
|
||||
@ -109,7 +110,7 @@ unsafe fn exchange_malloc(size: uint, align: uint) -> *mut u8 {
|
||||
#[cfg(not(test))]
|
||||
#[lang="exchange_free"]
|
||||
#[inline]
|
||||
unsafe fn exchange_free(ptr: *mut u8, old_size: uint, align: uint) {
|
||||
unsafe fn exchange_free(ptr: *mut u8, old_size: usize, align: usize) {
|
||||
deallocate(ptr, old_size, align);
|
||||
}
|
||||
|
||||
@ -122,49 +123,49 @@ unsafe fn exchange_free(ptr: *mut u8, old_size: uint, align: uint) {
|
||||
target_arch = "mips",
|
||||
target_arch = "mipsel",
|
||||
target_arch = "powerpc")))]
|
||||
const MIN_ALIGN: uint = 8;
|
||||
const MIN_ALIGN: usize = 8;
|
||||
#[cfg(all(not(feature = "external_funcs"),
|
||||
not(feature = "external_crate"),
|
||||
any(target_arch = "x86",
|
||||
target_arch = "x86_64",
|
||||
target_arch = "aarch64")))]
|
||||
const MIN_ALIGN: uint = 16;
|
||||
const MIN_ALIGN: usize = 16;
|
||||
|
||||
#[cfg(feature = "external_funcs")]
|
||||
mod imp {
|
||||
extern {
|
||||
fn rust_allocate(size: uint, align: uint) -> *mut u8;
|
||||
fn rust_deallocate(ptr: *mut u8, old_size: uint, align: uint);
|
||||
fn rust_reallocate(ptr: *mut u8, old_size: uint, size: uint, align: uint) -> *mut u8;
|
||||
fn rust_reallocate_inplace(ptr: *mut u8, old_size: uint, size: uint,
|
||||
align: uint) -> uint;
|
||||
fn rust_usable_size(size: uint, align: uint) -> uint;
|
||||
fn rust_allocate(size: usize, align: usize) -> *mut u8;
|
||||
fn rust_deallocate(ptr: *mut u8, old_size: usize, align: usize);
|
||||
fn rust_reallocate(ptr: *mut u8, old_size: usize, size: usize, align: usize) -> *mut u8;
|
||||
fn rust_reallocate_inplace(ptr: *mut u8, old_size: usize, size: usize,
|
||||
align: usize) -> usize;
|
||||
fn rust_usable_size(size: usize, align: usize) -> usize;
|
||||
fn rust_stats_print();
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn allocate(size: uint, align: uint) -> *mut u8 {
|
||||
pub unsafe fn allocate(size: usize, align: usize) -> *mut u8 {
|
||||
rust_allocate(size, align)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn deallocate(ptr: *mut u8, old_size: uint, align: uint) {
|
||||
pub unsafe fn deallocate(ptr: *mut u8, old_size: usize, align: usize) {
|
||||
rust_deallocate(ptr, old_size, align)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn reallocate(ptr: *mut u8, old_size: uint, size: uint, align: uint) -> *mut u8 {
|
||||
pub unsafe fn reallocate(ptr: *mut u8, old_size: usize, size: usize, align: usize) -> *mut u8 {
|
||||
rust_reallocate(ptr, old_size, size, align)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn reallocate_inplace(ptr: *mut u8, old_size: uint, size: uint,
|
||||
align: uint) -> uint {
|
||||
pub unsafe fn reallocate_inplace(ptr: *mut u8, old_size: usize, size: usize,
|
||||
align: usize) -> usize {
|
||||
rust_reallocate_inplace(ptr, old_size, size, align)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn usable_size(size: uint, align: uint) -> uint {
|
||||
pub fn usable_size(size: usize, align: usize) -> usize {
|
||||
unsafe { rust_usable_size(size, align) }
|
||||
}
|
||||
|
||||
@ -215,42 +216,42 @@ mod imp {
|
||||
|
||||
// MALLOCX_ALIGN(a) macro
|
||||
#[inline(always)]
|
||||
fn mallocx_align(a: uint) -> c_int { a.trailing_zeros() as c_int }
|
||||
fn mallocx_align(a: usize) -> c_int { a.trailing_zeros() as c_int }
|
||||
|
||||
#[inline(always)]
|
||||
fn align_to_flags(align: uint) -> c_int {
|
||||
fn align_to_flags(align: usize) -> c_int {
|
||||
if align <= MIN_ALIGN { 0 } else { mallocx_align(align) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn allocate(size: uint, align: uint) -> *mut u8 {
|
||||
pub unsafe fn allocate(size: usize, align: usize) -> *mut u8 {
|
||||
let flags = align_to_flags(align);
|
||||
je_mallocx(size as size_t, flags) as *mut u8
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn reallocate(ptr: *mut u8, _old_size: uint, size: uint, align: uint) -> *mut u8 {
|
||||
pub unsafe fn reallocate(ptr: *mut u8, _old_size: usize, size: usize, align: usize) -> *mut u8 {
|
||||
let flags = align_to_flags(align);
|
||||
je_rallocx(ptr as *mut c_void, size as size_t, flags) as *mut u8
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn reallocate_inplace(ptr: *mut u8, _old_size: uint, size: uint,
|
||||
align: uint) -> uint {
|
||||
pub unsafe fn reallocate_inplace(ptr: *mut u8, _old_size: usize, size: usize,
|
||||
align: usize) -> usize {
|
||||
let flags = align_to_flags(align);
|
||||
je_xallocx(ptr as *mut c_void, size as size_t, 0, flags) as uint
|
||||
je_xallocx(ptr as *mut c_void, size as size_t, 0, flags) as usize
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn deallocate(ptr: *mut u8, old_size: uint, align: uint) {
|
||||
pub unsafe fn deallocate(ptr: *mut u8, old_size: usize, align: usize) {
|
||||
let flags = align_to_flags(align);
|
||||
je_sdallocx(ptr as *mut c_void, old_size as size_t, flags)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn usable_size(size: uint, align: uint) -> uint {
|
||||
pub fn usable_size(size: usize, align: usize) -> usize {
|
||||
let flags = align_to_flags(align);
|
||||
unsafe { je_nallocx(size as size_t, flags) as uint }
|
||||
unsafe { je_nallocx(size as size_t, flags) as usize }
|
||||
}
|
||||
|
||||
pub fn stats_print() {
|
||||
@ -277,7 +278,7 @@ mod imp {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn allocate(size: uint, align: uint) -> *mut u8 {
|
||||
pub unsafe fn allocate(size: usize, align: usize) -> *mut u8 {
|
||||
if align <= MIN_ALIGN {
|
||||
libc::malloc(size as libc::size_t) as *mut u8
|
||||
} else {
|
||||
@ -294,7 +295,7 @@ mod imp {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn reallocate(ptr: *mut u8, old_size: uint, size: uint, align: uint) -> *mut u8 {
|
||||
pub unsafe fn reallocate(ptr: *mut u8, old_size: usize, size: usize, align: usize) -> *mut u8 {
|
||||
if align <= MIN_ALIGN {
|
||||
libc::realloc(ptr as *mut libc::c_void, size as libc::size_t) as *mut u8
|
||||
} else {
|
||||
@ -306,18 +307,18 @@ mod imp {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn reallocate_inplace(_ptr: *mut u8, old_size: uint, _size: uint,
|
||||
_align: uint) -> uint {
|
||||
pub unsafe fn reallocate_inplace(_ptr: *mut u8, old_size: usize, _size: usize,
|
||||
_align: usize) -> usize {
|
||||
old_size
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn deallocate(ptr: *mut u8, _old_size: uint, _align: uint) {
|
||||
pub unsafe fn deallocate(ptr: *mut u8, _old_size: usize, _align: usize) {
|
||||
libc::free(ptr as *mut libc::c_void)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn usable_size(size: uint, _align: uint) -> uint {
|
||||
pub fn usable_size(size: usize, _align: usize) -> usize {
|
||||
size
|
||||
}
|
||||
|
||||
@ -341,7 +342,7 @@ mod imp {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn allocate(size: uint, align: uint) -> *mut u8 {
|
||||
pub unsafe fn allocate(size: usize, align: usize) -> *mut u8 {
|
||||
if align <= MIN_ALIGN {
|
||||
libc::malloc(size as size_t) as *mut u8
|
||||
} else {
|
||||
@ -350,7 +351,7 @@ mod imp {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn reallocate(ptr: *mut u8, _old_size: uint, size: uint, align: uint) -> *mut u8 {
|
||||
pub unsafe fn reallocate(ptr: *mut u8, _old_size: usize, size: usize, align: usize) -> *mut u8 {
|
||||
if align <= MIN_ALIGN {
|
||||
libc::realloc(ptr as *mut c_void, size as size_t) as *mut u8
|
||||
} else {
|
||||
@ -359,13 +360,13 @@ mod imp {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn reallocate_inplace(_ptr: *mut u8, old_size: uint, _size: uint,
|
||||
_align: uint) -> uint {
|
||||
pub unsafe fn reallocate_inplace(_ptr: *mut u8, old_size: usize, _size: usize,
|
||||
_align: usize) -> usize {
|
||||
old_size
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn deallocate(ptr: *mut u8, _old_size: uint, align: uint) {
|
||||
pub unsafe fn deallocate(ptr: *mut u8, _old_size: usize, align: usize) {
|
||||
if align <= MIN_ALIGN {
|
||||
libc::free(ptr as *mut libc::c_void)
|
||||
} else {
|
||||
@ -374,7 +375,7 @@ mod imp {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn usable_size(size: uint, _align: uint) -> uint {
|
||||
pub fn usable_size(size: usize, _align: usize) -> usize {
|
||||
size
|
||||
}
|
||||
|
||||
|
@ -70,7 +70,6 @@
|
||||
#![feature(lang_items, unsafe_destructor)]
|
||||
#![feature(box_syntax)]
|
||||
#![feature(optin_builtin_traits)]
|
||||
#![feature(int_uint)]
|
||||
#![feature(unboxed_closures)]
|
||||
#![feature(core)]
|
||||
#![feature(hash)]
|
||||
|
@ -40,7 +40,7 @@
|
||||
//! }
|
||||
//!
|
||||
//! struct Gadget {
|
||||
//! id: int,
|
||||
//! id: i32,
|
||||
//! owner: Rc<Owner>
|
||||
//! // ...other fields
|
||||
//! }
|
||||
@ -99,7 +99,7 @@
|
||||
//! }
|
||||
//!
|
||||
//! struct Gadget {
|
||||
//! id: int,
|
||||
//! id: i32,
|
||||
//! owner: Rc<Owner>
|
||||
//! // ...other fields
|
||||
//! }
|
||||
@ -166,8 +166,8 @@ use heap::deallocate;
|
||||
|
||||
struct RcBox<T> {
|
||||
value: T,
|
||||
strong: Cell<uint>,
|
||||
weak: Cell<uint>
|
||||
strong: Cell<usize>,
|
||||
weak: Cell<usize>
|
||||
}
|
||||
|
||||
/// An immutable reference-counted pointer type.
|
||||
@ -233,12 +233,12 @@ impl<T> Rc<T> {
|
||||
/// Get the number of weak references to this value.
|
||||
#[inline]
|
||||
#[unstable(feature = "alloc")]
|
||||
pub fn weak_count<T>(this: &Rc<T>) -> uint { this.weak() - 1 }
|
||||
pub fn weak_count<T>(this: &Rc<T>) -> usize { this.weak() - 1 }
|
||||
|
||||
/// Get the number of strong references to this value.
|
||||
#[inline]
|
||||
#[unstable(feature = "alloc")]
|
||||
pub fn strong_count<T>(this: &Rc<T>) -> uint { this.strong() }
|
||||
pub fn strong_count<T>(this: &Rc<T>) -> usize { this.strong() }
|
||||
|
||||
/// Returns true if there are no other `Rc` or `Weak<T>` values that share the same inner value.
|
||||
///
|
||||
@ -447,7 +447,7 @@ impl<T: Default> Default for Rc<T> {
|
||||
/// use std::rc::Rc;
|
||||
/// use std::default::Default;
|
||||
///
|
||||
/// let x: Rc<int> = Default::default();
|
||||
/// let x: Rc<i32> = Default::default();
|
||||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
@ -750,7 +750,7 @@ trait RcBoxPtr<T> {
|
||||
fn inner(&self) -> &RcBox<T>;
|
||||
|
||||
#[inline]
|
||||
fn strong(&self) -> uint { self.inner().strong.get() }
|
||||
fn strong(&self) -> usize { self.inner().strong.get() }
|
||||
|
||||
#[inline]
|
||||
fn inc_strong(&self) { self.inner().strong.set(self.strong() + 1); }
|
||||
@ -759,7 +759,7 @@ trait RcBoxPtr<T> {
|
||||
fn dec_strong(&self) { self.inner().strong.set(self.strong() - 1); }
|
||||
|
||||
#[inline]
|
||||
fn weak(&self) -> uint { self.inner().weak.get() }
|
||||
fn weak(&self) -> usize { self.inner().weak.get() }
|
||||
|
||||
#[inline]
|
||||
fn inc_weak(&self) { self.inner().weak.set(self.weak() + 1); }
|
||||
|
@ -31,7 +31,6 @@
|
||||
#![feature(alloc)]
|
||||
#![feature(box_syntax)]
|
||||
#![feature(core)]
|
||||
#![feature(int_uint)]
|
||||
#![feature(staged_api)]
|
||||
#![feature(unboxed_closures)]
|
||||
#![feature(unsafe_destructor)]
|
||||
@ -55,12 +54,12 @@ use std::rt::heap::{allocate, deallocate};
|
||||
#[derive(Clone, PartialEq)]
|
||||
struct Chunk {
|
||||
data: Rc<RefCell<Vec<u8>>>,
|
||||
fill: Cell<uint>,
|
||||
fill: Cell<usize>,
|
||||
is_copy: Cell<bool>,
|
||||
}
|
||||
|
||||
impl Chunk {
|
||||
fn capacity(&self) -> uint {
|
||||
fn capacity(&self) -> usize {
|
||||
self.data.borrow().capacity()
|
||||
}
|
||||
|
||||
@ -105,7 +104,7 @@ impl Arena {
|
||||
}
|
||||
|
||||
/// Allocates a new Arena with `initial_size` bytes preallocated.
|
||||
pub fn new_with_size(initial_size: uint) -> Arena {
|
||||
pub fn new_with_size(initial_size: usize) -> Arena {
|
||||
Arena {
|
||||
head: RefCell::new(chunk(initial_size, false)),
|
||||
copy_head: RefCell::new(chunk(initial_size, true)),
|
||||
@ -114,7 +113,7 @@ impl Arena {
|
||||
}
|
||||
}
|
||||
|
||||
fn chunk(size: uint, is_copy: bool) -> Chunk {
|
||||
fn chunk(size: usize, is_copy: bool) -> Chunk {
|
||||
Chunk {
|
||||
data: Rc::new(RefCell::new(Vec::with_capacity(size))),
|
||||
fill: Cell::new(0),
|
||||
@ -137,7 +136,7 @@ impl Drop for Arena {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn round_up(base: uint, align: uint) -> uint {
|
||||
fn round_up(base: usize, align: usize) -> usize {
|
||||
(base.checked_add(align - 1)).unwrap() & !(align - 1)
|
||||
}
|
||||
|
||||
@ -149,7 +148,7 @@ unsafe fn destroy_chunk(chunk: &Chunk) {
|
||||
let fill = chunk.fill.get();
|
||||
|
||||
while idx < fill {
|
||||
let tydesc_data: *const uint = mem::transmute(buf.offset(idx as int));
|
||||
let tydesc_data: *const usize = mem::transmute(buf.offset(idx as isize));
|
||||
let (tydesc, is_done) = un_bitpack_tydesc_ptr(*tydesc_data);
|
||||
let (size, align) = ((*tydesc).size, (*tydesc).align);
|
||||
|
||||
@ -160,7 +159,7 @@ unsafe fn destroy_chunk(chunk: &Chunk) {
|
||||
//debug!("freeing object: idx = {}, size = {}, align = {}, done = {}",
|
||||
// start, size, align, is_done);
|
||||
if is_done {
|
||||
((*tydesc).drop_glue)(buf.offset(start as int) as *const i8);
|
||||
((*tydesc).drop_glue)(buf.offset(start as isize) as *const i8);
|
||||
}
|
||||
|
||||
// Find where the next tydesc lives
|
||||
@ -173,21 +172,21 @@ unsafe fn destroy_chunk(chunk: &Chunk) {
|
||||
// is necessary in order to properly do cleanup if a panic occurs
|
||||
// during an initializer.
|
||||
#[inline]
|
||||
fn bitpack_tydesc_ptr(p: *const TyDesc, is_done: bool) -> uint {
|
||||
p as uint | (is_done as uint)
|
||||
fn bitpack_tydesc_ptr(p: *const TyDesc, is_done: bool) -> usize {
|
||||
p as usize | (is_done as usize)
|
||||
}
|
||||
#[inline]
|
||||
fn un_bitpack_tydesc_ptr(p: uint) -> (*const TyDesc, bool) {
|
||||
fn un_bitpack_tydesc_ptr(p: usize) -> (*const TyDesc, bool) {
|
||||
((p & !1) as *const TyDesc, p & 1 == 1)
|
||||
}
|
||||
|
||||
impl Arena {
|
||||
fn chunk_size(&self) -> uint {
|
||||
fn chunk_size(&self) -> usize {
|
||||
self.copy_head.borrow().capacity()
|
||||
}
|
||||
|
||||
// Functions for the POD part of the arena
|
||||
fn alloc_copy_grow(&self, n_bytes: uint, align: uint) -> *const u8 {
|
||||
fn alloc_copy_grow(&self, n_bytes: usize, align: usize) -> *const u8 {
|
||||
// Allocate a new chunk.
|
||||
let new_min_chunk_size = cmp::max(n_bytes, self.chunk_size());
|
||||
self.chunks.borrow_mut().push(self.copy_head.borrow().clone());
|
||||
@ -199,7 +198,7 @@ impl Arena {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn alloc_copy_inner(&self, n_bytes: uint, align: uint) -> *const u8 {
|
||||
fn alloc_copy_inner(&self, n_bytes: usize, align: usize) -> *const u8 {
|
||||
let start = round_up(self.copy_head.borrow().fill.get(), align);
|
||||
|
||||
let end = start + n_bytes;
|
||||
@ -211,7 +210,7 @@ impl Arena {
|
||||
copy_head.fill.set(end);
|
||||
|
||||
unsafe {
|
||||
copy_head.as_ptr().offset(start as int)
|
||||
copy_head.as_ptr().offset(start as isize)
|
||||
}
|
||||
}
|
||||
|
||||
@ -227,8 +226,8 @@ impl Arena {
|
||||
}
|
||||
|
||||
// Functions for the non-POD part of the arena
|
||||
fn alloc_noncopy_grow(&self, n_bytes: uint,
|
||||
align: uint) -> (*const u8, *const u8) {
|
||||
fn alloc_noncopy_grow(&self, n_bytes: usize,
|
||||
align: usize) -> (*const u8, *const u8) {
|
||||
// Allocate a new chunk.
|
||||
let new_min_chunk_size = cmp::max(n_bytes, self.chunk_size());
|
||||
self.chunks.borrow_mut().push(self.head.borrow().clone());
|
||||
@ -240,8 +239,8 @@ impl Arena {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn alloc_noncopy_inner(&self, n_bytes: uint,
|
||||
align: uint) -> (*const u8, *const u8) {
|
||||
fn alloc_noncopy_inner(&self, n_bytes: usize,
|
||||
align: usize) -> (*const u8, *const u8) {
|
||||
// Be careful to not maintain any `head` borrows active, because
|
||||
// `alloc_noncopy_grow` borrows it mutably.
|
||||
let (start, end, tydesc_start, head_capacity) = {
|
||||
@ -265,7 +264,7 @@ impl Arena {
|
||||
|
||||
unsafe {
|
||||
let buf = head.as_ptr();
|
||||
return (buf.offset(tydesc_start as int), buf.offset(start as int));
|
||||
return (buf.offset(tydesc_start as isize), buf.offset(start as isize));
|
||||
}
|
||||
}
|
||||
|
||||
@ -276,7 +275,7 @@ impl Arena {
|
||||
let (ty_ptr, ptr) =
|
||||
self.alloc_noncopy_inner(mem::size_of::<T>(),
|
||||
mem::min_align_of::<T>());
|
||||
let ty_ptr = ty_ptr as *mut uint;
|
||||
let ty_ptr = ty_ptr as *mut usize;
|
||||
let ptr = ptr as *mut T;
|
||||
// Write in our tydesc along with a bit indicating that it
|
||||
// has *not* been initialized yet.
|
||||
@ -320,7 +319,7 @@ fn test_arena_destructors() {
|
||||
|
||||
#[test]
|
||||
fn test_arena_alloc_nested() {
|
||||
struct Inner { value: uint }
|
||||
struct Inner { value: usize }
|
||||
struct Outer<'a> { inner: &'a Inner }
|
||||
|
||||
let arena = Arena::new();
|
||||
@ -343,10 +342,10 @@ fn test_arena_destructors_fail() {
|
||||
arena.alloc(|| { Rc::new(i) });
|
||||
// Allocate something with funny size and alignment, to keep
|
||||
// things interesting.
|
||||
arena.alloc(|| { [0u8, 1u8, 2u8] });
|
||||
arena.alloc(|| { [0u8, 1, 2] });
|
||||
}
|
||||
// Now, panic while allocating
|
||||
arena.alloc::<Rc<int>, _>(|| {
|
||||
arena.alloc::<Rc<i32>, _>(|| {
|
||||
panic!();
|
||||
});
|
||||
}
|
||||
@ -373,12 +372,12 @@ struct TypedArenaChunk<T> {
|
||||
next: *mut TypedArenaChunk<T>,
|
||||
|
||||
/// The number of elements that this chunk can hold.
|
||||
capacity: uint,
|
||||
capacity: usize,
|
||||
|
||||
// Objects follow here, suitably aligned.
|
||||
}
|
||||
|
||||
fn calculate_size<T>(capacity: uint) -> uint {
|
||||
fn calculate_size<T>(capacity: usize) -> usize {
|
||||
let mut size = mem::size_of::<TypedArenaChunk<T>>();
|
||||
size = round_up(size, mem::min_align_of::<T>());
|
||||
let elem_size = mem::size_of::<T>();
|
||||
@ -389,7 +388,7 @@ fn calculate_size<T>(capacity: uint) -> uint {
|
||||
|
||||
impl<T> TypedArenaChunk<T> {
|
||||
#[inline]
|
||||
unsafe fn new(next: *mut TypedArenaChunk<T>, capacity: uint)
|
||||
unsafe fn new(next: *mut TypedArenaChunk<T>, capacity: usize)
|
||||
-> *mut TypedArenaChunk<T> {
|
||||
let size = calculate_size::<T>(capacity);
|
||||
let chunk = allocate(size, mem::min_align_of::<TypedArenaChunk<T>>())
|
||||
@ -403,13 +402,13 @@ impl<T> TypedArenaChunk<T> {
|
||||
/// Destroys this arena chunk. If the type descriptor is supplied, the
|
||||
/// drop glue is called; otherwise, drop glue is not called.
|
||||
#[inline]
|
||||
unsafe fn destroy(&mut self, len: uint) {
|
||||
unsafe fn destroy(&mut self, len: usize) {
|
||||
// Destroy all the allocated objects.
|
||||
if intrinsics::needs_drop::<T>() {
|
||||
let mut start = self.start();
|
||||
for _ in 0..len {
|
||||
ptr::read(start as *const T); // run the destructor on the pointer
|
||||
start = start.offset(mem::size_of::<T>() as int)
|
||||
start = start.offset(mem::size_of::<T>() as isize)
|
||||
}
|
||||
}
|
||||
|
||||
@ -429,7 +428,7 @@ impl<T> TypedArenaChunk<T> {
|
||||
fn start(&self) -> *const u8 {
|
||||
let this: *const TypedArenaChunk<T> = self;
|
||||
unsafe {
|
||||
mem::transmute(round_up(this.offset(1) as uint,
|
||||
mem::transmute(round_up(this.offset(1) as usize,
|
||||
mem::min_align_of::<T>()))
|
||||
}
|
||||
}
|
||||
@ -439,7 +438,7 @@ impl<T> TypedArenaChunk<T> {
|
||||
fn end(&self) -> *const u8 {
|
||||
unsafe {
|
||||
let size = mem::size_of::<T>().checked_mul(self.capacity).unwrap();
|
||||
self.start().offset(size as int)
|
||||
self.start().offset(size as isize)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -454,7 +453,7 @@ impl<T> TypedArena<T> {
|
||||
/// Creates a new `TypedArena` with preallocated space for the given number of
|
||||
/// objects.
|
||||
#[inline]
|
||||
pub fn with_capacity(capacity: uint) -> TypedArena<T> {
|
||||
pub fn with_capacity(capacity: usize) -> TypedArena<T> {
|
||||
unsafe {
|
||||
let chunk = TypedArenaChunk::<T>::new(ptr::null_mut(), capacity);
|
||||
TypedArena {
|
||||
@ -501,8 +500,8 @@ impl<T> Drop for TypedArena<T> {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
// Determine how much was filled.
|
||||
let start = self.first.borrow().as_ref().unwrap().start() as uint;
|
||||
let end = self.ptr.get() as uint;
|
||||
let start = self.first.borrow().as_ref().unwrap().start() as usize;
|
||||
let end = self.ptr.get() as usize;
|
||||
let diff = (end - start) / mem::size_of::<T>();
|
||||
|
||||
// Pass that to the `destroy` method.
|
||||
@ -519,9 +518,9 @@ mod tests {
|
||||
|
||||
#[allow(dead_code)]
|
||||
struct Point {
|
||||
x: int,
|
||||
y: int,
|
||||
z: int,
|
||||
x: i32,
|
||||
y: i32,
|
||||
z: i32,
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -576,7 +575,7 @@ mod tests {
|
||||
#[allow(dead_code)]
|
||||
struct Noncopy {
|
||||
string: String,
|
||||
array: Vec<int>,
|
||||
array: Vec<i32>,
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -656,7 +656,7 @@ impl<T: Ord> FromIterator<T> for BinaryHeap<T> {
|
||||
}
|
||||
|
||||
impl<T: Ord> IntoIterator for BinaryHeap<T> {
|
||||
type Iter = IntoIter<T>;
|
||||
type IntoIter = IntoIter<T>;
|
||||
|
||||
fn into_iter(self) -> IntoIter<T> {
|
||||
self.into_iter()
|
||||
@ -664,7 +664,7 @@ impl<T: Ord> IntoIterator for BinaryHeap<T> {
|
||||
}
|
||||
|
||||
impl<'a, T> IntoIterator for &'a BinaryHeap<T> where T: Ord {
|
||||
type Iter = Iter<'a, T>;
|
||||
type IntoIter = Iter<'a, T>;
|
||||
|
||||
fn into_iter(self) -> Iter<'a, T> {
|
||||
self.iter()
|
||||
|
@ -1071,7 +1071,7 @@ impl<'a> RandomAccessIterator for Iter<'a> {
|
||||
}
|
||||
|
||||
impl<'a> IntoIterator for &'a Bitv {
|
||||
type Iter = Iter<'a>;
|
||||
type IntoIter = Iter<'a>;
|
||||
|
||||
fn into_iter(self) -> Iter<'a> {
|
||||
self.iter()
|
||||
@ -1883,7 +1883,7 @@ impl<'a> Iterator for SymmetricDifference<'a> {
|
||||
}
|
||||
|
||||
impl<'a> IntoIterator for &'a BitvSet {
|
||||
type Iter = SetIter<'a>;
|
||||
type IntoIter = SetIter<'a>;
|
||||
|
||||
fn into_iter(self) -> SetIter<'a> {
|
||||
self.iter()
|
||||
|
@ -463,7 +463,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
|
||||
}
|
||||
|
||||
impl<K, V> IntoIterator for BTreeMap<K, V> {
|
||||
type Iter = IntoIter<K, V>;
|
||||
type IntoIter = IntoIter<K, V>;
|
||||
|
||||
fn into_iter(self) -> IntoIter<K, V> {
|
||||
self.into_iter()
|
||||
@ -471,7 +471,7 @@ impl<K, V> IntoIterator for BTreeMap<K, V> {
|
||||
}
|
||||
|
||||
impl<'a, K, V> IntoIterator for &'a BTreeMap<K, V> {
|
||||
type Iter = Iter<'a, K, V>;
|
||||
type IntoIter = Iter<'a, K, V>;
|
||||
|
||||
fn into_iter(self) -> Iter<'a, K, V> {
|
||||
self.iter()
|
||||
@ -479,7 +479,7 @@ impl<'a, K, V> IntoIterator for &'a BTreeMap<K, V> {
|
||||
}
|
||||
|
||||
impl<'a, K, V> IntoIterator for &'a mut BTreeMap<K, V> {
|
||||
type Iter = IterMut<'a, K, V>;
|
||||
type IntoIter = IterMut<'a, K, V>;
|
||||
|
||||
fn into_iter(mut self) -> IterMut<'a, K, V> {
|
||||
self.iter_mut()
|
||||
|
@ -481,7 +481,7 @@ impl<T: Ord> FromIterator<T> for BTreeSet<T> {
|
||||
}
|
||||
|
||||
impl<T> IntoIterator for BTreeSet<T> {
|
||||
type Iter = IntoIter<T>;
|
||||
type IntoIter = IntoIter<T>;
|
||||
|
||||
fn into_iter(self) -> IntoIter<T> {
|
||||
self.into_iter()
|
||||
@ -489,7 +489,7 @@ impl<T> IntoIterator for BTreeSet<T> {
|
||||
}
|
||||
|
||||
impl<'a, T> IntoIterator for &'a BTreeSet<T> {
|
||||
type Iter = Iter<'a, T>;
|
||||
type IntoIter = Iter<'a, T>;
|
||||
|
||||
fn into_iter(self) -> Iter<'a, T> {
|
||||
self.iter()
|
||||
|
@ -831,7 +831,7 @@ impl<A> FromIterator<A> for DList<A> {
|
||||
}
|
||||
|
||||
impl<T> IntoIterator for DList<T> {
|
||||
type Iter = IntoIter<T>;
|
||||
type IntoIter = IntoIter<T>;
|
||||
|
||||
fn into_iter(self) -> IntoIter<T> {
|
||||
self.into_iter()
|
||||
@ -839,7 +839,7 @@ impl<T> IntoIterator for DList<T> {
|
||||
}
|
||||
|
||||
impl<'a, T> IntoIterator for &'a DList<T> {
|
||||
type Iter = Iter<'a, T>;
|
||||
type IntoIter = Iter<'a, T>;
|
||||
|
||||
fn into_iter(self) -> Iter<'a, T> {
|
||||
self.iter()
|
||||
@ -847,7 +847,7 @@ impl<'a, T> IntoIterator for &'a DList<T> {
|
||||
}
|
||||
|
||||
impl<'a, T> IntoIterator for &'a mut DList<T> {
|
||||
type Iter = IterMut<'a, T>;
|
||||
type IntoIter = IterMut<'a, T>;
|
||||
|
||||
fn into_iter(mut self) -> IterMut<'a, T> {
|
||||
self.iter_mut()
|
||||
|
@ -258,7 +258,7 @@ impl<E:CLike> FromIterator<E> for EnumSet<E> {
|
||||
}
|
||||
|
||||
impl<'a, E> IntoIterator for &'a EnumSet<E> where E: CLike {
|
||||
type Iter = Iter<E>;
|
||||
type IntoIter = Iter<E>;
|
||||
|
||||
fn into_iter(self) -> Iter<E> {
|
||||
self.iter()
|
||||
|
@ -30,7 +30,7 @@
|
||||
#![feature(unboxed_closures)]
|
||||
#![feature(unicode)]
|
||||
#![feature(unsafe_destructor, slicing_syntax)]
|
||||
#![cfg_attr(test, feature(test))]
|
||||
#![cfg_attr(test, feature(rand, rustc_private, test))]
|
||||
#![cfg_attr(test, allow(deprecated))] // rand
|
||||
|
||||
#![feature(no_std)]
|
||||
|
@ -1608,7 +1608,7 @@ impl<A> FromIterator<A> for RingBuf<A> {
|
||||
}
|
||||
|
||||
impl<T> IntoIterator for RingBuf<T> {
|
||||
type Iter = IntoIter<T>;
|
||||
type IntoIter = IntoIter<T>;
|
||||
|
||||
fn into_iter(self) -> IntoIter<T> {
|
||||
self.into_iter()
|
||||
@ -1616,7 +1616,7 @@ impl<T> IntoIterator for RingBuf<T> {
|
||||
}
|
||||
|
||||
impl<'a, T> IntoIterator for &'a RingBuf<T> {
|
||||
type Iter = Iter<'a, T>;
|
||||
type IntoIter = Iter<'a, T>;
|
||||
|
||||
fn into_iter(self) -> Iter<'a, T> {
|
||||
self.iter()
|
||||
@ -1624,7 +1624,7 @@ impl<'a, T> IntoIterator for &'a RingBuf<T> {
|
||||
}
|
||||
|
||||
impl<'a, T> IntoIterator for &'a mut RingBuf<T> {
|
||||
type Iter = IterMut<'a, T>;
|
||||
type IntoIter = IterMut<'a, T>;
|
||||
|
||||
fn into_iter(mut self) -> IterMut<'a, T> {
|
||||
self.iter_mut()
|
||||
|
@ -1388,7 +1388,7 @@ impl<T> FromIterator<T> for Vec<T> {
|
||||
}
|
||||
|
||||
impl<T> IntoIterator for Vec<T> {
|
||||
type Iter = IntoIter<T>;
|
||||
type IntoIter = IntoIter<T>;
|
||||
|
||||
fn into_iter(self) -> IntoIter<T> {
|
||||
self.into_iter()
|
||||
@ -1396,7 +1396,7 @@ impl<T> IntoIterator for Vec<T> {
|
||||
}
|
||||
|
||||
impl<'a, T> IntoIterator for &'a Vec<T> {
|
||||
type Iter = slice::Iter<'a, T>;
|
||||
type IntoIter = slice::Iter<'a, T>;
|
||||
|
||||
fn into_iter(self) -> slice::Iter<'a, T> {
|
||||
self.iter()
|
||||
@ -1404,7 +1404,7 @@ impl<'a, T> IntoIterator for &'a Vec<T> {
|
||||
}
|
||||
|
||||
impl<'a, T> IntoIterator for &'a mut Vec<T> {
|
||||
type Iter = slice::IterMut<'a, T>;
|
||||
type IntoIter = slice::IterMut<'a, T>;
|
||||
|
||||
fn into_iter(mut self) -> slice::IterMut<'a, T> {
|
||||
self.iter_mut()
|
||||
|
@ -669,7 +669,7 @@ impl<V> FromIterator<(usize, V)> for VecMap<V> {
|
||||
}
|
||||
|
||||
impl<T> IntoIterator for VecMap<T> {
|
||||
type Iter = IntoIter<T>;
|
||||
type IntoIter = IntoIter<T>;
|
||||
|
||||
fn into_iter(self) -> IntoIter<T> {
|
||||
self.into_iter()
|
||||
@ -677,7 +677,7 @@ impl<T> IntoIterator for VecMap<T> {
|
||||
}
|
||||
|
||||
impl<'a, T> IntoIterator for &'a VecMap<T> {
|
||||
type Iter = Iter<'a, T>;
|
||||
type IntoIter = Iter<'a, T>;
|
||||
|
||||
fn into_iter(self) -> Iter<'a, T> {
|
||||
self.iter()
|
||||
@ -685,7 +685,7 @@ impl<'a, T> IntoIterator for &'a VecMap<T> {
|
||||
}
|
||||
|
||||
impl<'a, T> IntoIterator for &'a mut VecMap<T> {
|
||||
type Iter = IterMut<'a, T>;
|
||||
type IntoIter = IterMut<'a, T>;
|
||||
|
||||
fn into_iter(mut self) -> IterMut<'a, T> {
|
||||
self.iter_mut()
|
||||
|
@ -27,7 +27,7 @@
|
||||
//! # Examples
|
||||
//!
|
||||
//! Consider a situation where we want to log out a value passed to a function.
|
||||
//! We know the value we're working on implements Show, but we don't know its
|
||||
//! We know the value we're working on implements Debug, but we don't know its
|
||||
//! concrete type. We want to give special treatment to certain types: in this
|
||||
//! case printing out the length of String values prior to their value.
|
||||
//! We don't know the concrete type of our value at compile time, so we need to
|
||||
|
@ -49,7 +49,7 @@ macro_rules! array_impls {
|
||||
}
|
||||
|
||||
impl<'a, T> IntoIterator for &'a [T; $N] {
|
||||
type Iter = Iter<'a, T>;
|
||||
type IntoIter = Iter<'a, T>;
|
||||
|
||||
fn into_iter(self) -> Iter<'a, T> {
|
||||
self.iter()
|
||||
@ -57,7 +57,7 @@ macro_rules! array_impls {
|
||||
}
|
||||
|
||||
impl<'a, T> IntoIterator for &'a mut [T; $N] {
|
||||
type Iter = IterMut<'a, T>;
|
||||
type IntoIter = IterMut<'a, T>;
|
||||
|
||||
fn into_iter(self) -> IterMut<'a, T> {
|
||||
self.iter_mut()
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
|
||||
// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
@ -151,7 +151,7 @@ use option::Option::{None, Some};
|
||||
|
||||
/// A mutable memory location that admits only `Copy` data.
|
||||
///
|
||||
/// See the [module-level documentation](../index.html) for more.
|
||||
/// See the [module-level documentation](index.html) for more.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct Cell<T> {
|
||||
value: UnsafeCell<T>,
|
||||
@ -259,7 +259,7 @@ impl<T:PartialEq + Copy> PartialEq for Cell<T> {
|
||||
|
||||
/// A mutable memory location with dynamically checked borrow rules
|
||||
///
|
||||
/// See the [module-level documentation](../index.html) for more.
|
||||
/// See the [module-level documentation](index.html) for more.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct RefCell<T> {
|
||||
value: UnsafeCell<T>,
|
||||
@ -534,7 +534,7 @@ impl<'b> Clone for BorrowRef<'b> {
|
||||
/// Wraps a borrowed reference to a value in a `RefCell` box.
|
||||
/// A wrapper type for an immutably borrowed value from a `RefCell<T>`.
|
||||
///
|
||||
/// See the [module-level documentation](../index.html) for more.
|
||||
/// See the [module-level documentation](index.html) for more.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct Ref<'b, T:'b> {
|
||||
// FIXME #12808: strange name to try to avoid interfering with
|
||||
@ -595,7 +595,7 @@ impl<'b> BorrowRefMut<'b> {
|
||||
|
||||
/// A wrapper type for a mutably borrowed value from a `RefCell<T>`.
|
||||
///
|
||||
/// See the [module-level documentation](../index.html) for more.
|
||||
/// See the [module-level documentation](index.html) for more.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct RefMut<'b, T:'b> {
|
||||
// FIXME #12808: strange name to try to avoid interfering with
|
||||
|
@ -222,12 +222,11 @@ extern "rust-intrinsic" {
|
||||
|
||||
/// Unsafely transforms a value of one type into a value of another type.
|
||||
///
|
||||
/// Both types must have the same size and alignment, and this guarantee
|
||||
/// is enforced at compile-time.
|
||||
/// Both types must have the same size.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// ```
|
||||
/// use std::mem;
|
||||
///
|
||||
/// let v: &[u8] = unsafe { mem::transmute("L") };
|
||||
|
@ -120,14 +120,15 @@ pub trait FromIterator<A> {
|
||||
|
||||
/// Conversion into an `Iterator`
|
||||
pub trait IntoIterator {
|
||||
type Iter: Iterator;
|
||||
type IntoIter: Iterator;
|
||||
|
||||
/// Consumes `Self` and returns an iterator over it
|
||||
fn into_iter(self) -> Self::Iter;
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
fn into_iter(self) -> Self::IntoIter;
|
||||
}
|
||||
|
||||
impl<I> IntoIterator for I where I: Iterator {
|
||||
type Iter = I;
|
||||
type IntoIter = I;
|
||||
|
||||
fn into_iter(self) -> I {
|
||||
self
|
||||
@ -967,10 +968,9 @@ pub trait IteratorExt: Iterator + Sized {
|
||||
/// Creates an iterator that clones the elements it yields. Useful for converting an
|
||||
/// Iterator<&T> to an Iterator<T>.
|
||||
#[unstable(feature = "core", reason = "recent addition")]
|
||||
fn cloned<T, D>(self) -> Cloned<Self> where
|
||||
Self: Iterator<Item=D>,
|
||||
D: Deref<Target=T>,
|
||||
T: Clone,
|
||||
fn cloned(self) -> Cloned<Self> where
|
||||
Self::Item: Deref,
|
||||
<Self::Item as Deref>::Output: Clone,
|
||||
{
|
||||
Cloned { it: self }
|
||||
}
|
||||
@ -2646,13 +2646,7 @@ impl<A: Int> Iterator for RangeStepInclusive<A> {
|
||||
macro_rules! range_exact_iter_impl {
|
||||
($($t:ty)*) => ($(
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl ExactSizeIterator for ::ops::Range<$t> {
|
||||
#[inline]
|
||||
fn len(&self) -> usize {
|
||||
debug_assert!(self.end >= self.start);
|
||||
(self.end - self.start) as usize
|
||||
}
|
||||
}
|
||||
impl ExactSizeIterator for ::ops::Range<$t> { }
|
||||
)*)
|
||||
}
|
||||
|
||||
@ -2673,9 +2667,12 @@ impl<A: Int> Iterator for ::ops::Range<A> {
|
||||
|
||||
#[inline]
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
debug_assert!(self.end >= self.start);
|
||||
let hint = (self.end - self.start).to_uint();
|
||||
(hint.unwrap_or(0), hint)
|
||||
if self.start >= self.end {
|
||||
(0, Some(0))
|
||||
} else {
|
||||
let length = (self.end - self.start).to_uint();
|
||||
(length.unwrap_or(0), length)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -141,6 +141,10 @@ pub mod hash;
|
||||
pub mod fmt;
|
||||
pub mod error;
|
||||
|
||||
#[doc(primitive = "bool")]
|
||||
mod bool {
|
||||
}
|
||||
|
||||
// note: does not need to be public
|
||||
mod tuple;
|
||||
mod array;
|
||||
|
@ -522,21 +522,21 @@ impl<T> PartialOrd for *mut T {
|
||||
/// Useful for building abstractions like `Vec<T>` or `Box<T>`, which
|
||||
/// internally use raw pointers to manage the memory that they own.
|
||||
#[unstable(feature = "core", reason = "recently added to this module")]
|
||||
pub struct Unique<T>(pub *mut T);
|
||||
pub struct Unique<T: ?Sized>(pub *mut T);
|
||||
|
||||
/// `Unique` pointers are `Send` if `T` is `Send` because the data they
|
||||
/// reference is unaliased. Note that this aliasing invariant is
|
||||
/// unenforced by the type system; the abstraction using the
|
||||
/// `Unique` must enforce it.
|
||||
#[unstable(feature = "core", reason = "recently added to this module")]
|
||||
unsafe impl<T:Send> Send for Unique<T> { }
|
||||
unsafe impl<T: Send + ?Sized> Send for Unique<T> { }
|
||||
|
||||
/// `Unique` pointers are `Sync` if `T` is `Sync` because the data they
|
||||
/// reference is unaliased. Note that this aliasing invariant is
|
||||
/// unenforced by the type system; the abstraction using the
|
||||
/// `Unique` must enforce it.
|
||||
#[unstable(feature = "core", reason = "recently added to this module")]
|
||||
unsafe impl<T:Sync> Sync for Unique<T> { }
|
||||
unsafe impl<T: Sync + ?Sized> Sync for Unique<T> { }
|
||||
|
||||
impl<T> Unique<T> {
|
||||
/// Returns a null Unique.
|
||||
|
@ -628,7 +628,7 @@ impl<'a, T> Default for &'a [T] {
|
||||
//
|
||||
|
||||
impl<'a, T> IntoIterator for &'a [T] {
|
||||
type Iter = Iter<'a, T>;
|
||||
type IntoIter = Iter<'a, T>;
|
||||
|
||||
fn into_iter(self) -> Iter<'a, T> {
|
||||
self.iter()
|
||||
@ -636,7 +636,7 @@ impl<'a, T> IntoIterator for &'a [T] {
|
||||
}
|
||||
|
||||
impl<'a, T> IntoIterator for &'a mut [T] {
|
||||
type Iter = IterMut<'a, T>;
|
||||
type IntoIter = IterMut<'a, T>;
|
||||
|
||||
fn into_iter(self) -> IterMut<'a, T> {
|
||||
self.iter_mut()
|
||||
|
@ -34,6 +34,7 @@
|
||||
//! * `Default`
|
||||
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
#![doc(primitive = "tuple")]
|
||||
|
||||
use clone::Clone;
|
||||
use cmp::*;
|
||||
|
@ -756,6 +756,7 @@ fn test_range() {
|
||||
// this test is only meaningful when sizeof uint < sizeof u64
|
||||
assert_eq!((uint::MAX - 1..uint::MAX).size_hint(), (1, Some(1)));
|
||||
assert_eq!((-10..-1).size_hint(), (9, Some(9)));
|
||||
assert_eq!((-1..-10).size_hint(), (0, Some(0)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -167,3 +167,12 @@ fn test_set_memory() {
|
||||
unsafe { set_memory(ptr, 5u8, xs.len()); }
|
||||
assert!(xs == [5u8; 20]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_unsized_unique() {
|
||||
let xs: &mut [_] = &mut [1, 2, 3];
|
||||
let ptr = Unique(xs as *mut [_]);
|
||||
let ys = unsafe { &mut *ptr.0 };
|
||||
let zs: &mut [_] = &mut [1, 2, 3];
|
||||
assert!(ys == zs);
|
||||
}
|
||||
|
@ -90,7 +90,6 @@
|
||||
|
||||
#![deny(missing_docs)]
|
||||
#![feature(collections)]
|
||||
#![feature(core)]
|
||||
#![feature(int_uint)]
|
||||
#![feature(slicing_syntax)]
|
||||
#![feature(staged_api)]
|
||||
@ -195,7 +194,7 @@ pub struct Matches {
|
||||
}
|
||||
|
||||
/// The type returned when the command line does not conform to the
|
||||
/// expected format. Use the `Show` implementation to output detailed
|
||||
/// expected format. Use the `Debug` implementation to output detailed
|
||||
/// information.
|
||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||
pub enum Fail {
|
||||
@ -545,7 +544,7 @@ impl Fail {
|
||||
/// Convert a `Fail` enum into an error string.
|
||||
#[unstable(feature = "rustc_private")]
|
||||
#[deprecated(since = "1.0.0",
|
||||
reason = "use `fmt::String` (`{}` format specifier)")]
|
||||
reason = "use `fmt::Display` (`{}` format specifier)")]
|
||||
pub fn to_err_msg(self) -> String {
|
||||
self.to_string()
|
||||
}
|
||||
@ -579,7 +578,7 @@ impl fmt::Display for Fail {
|
||||
/// `opt_str`, etc. to interrogate results.
|
||||
/// # Panics
|
||||
///
|
||||
/// Returns `Err(Fail)` on failure: use the `Show` implementation of `Fail` to display
|
||||
/// Returns `Err(Fail)` on failure: use the `Debug` implementation of `Fail` to display
|
||||
/// information about it.
|
||||
pub fn getopts(args: &[String], optgrps: &[OptGroup]) -> Result {
|
||||
let opts: Vec<Opt> = optgrps.iter().map(|x| x.long_to_short()).collect();
|
||||
|
@ -15,7 +15,6 @@
|
||||
#![cfg_attr(not(feature = "cargo-build"), feature(staged_api))]
|
||||
#![cfg_attr(not(feature = "cargo-build"), staged_api)]
|
||||
#![cfg_attr(not(feature = "cargo-build"), feature(core))]
|
||||
#![feature(int_uint)]
|
||||
#![feature(no_std)]
|
||||
#![no_std]
|
||||
#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
|
||||
@ -1905,7 +1904,7 @@ pub mod types {
|
||||
#[repr(C)]
|
||||
#[derive(Copy)] pub struct WSAPROTOCOLCHAIN {
|
||||
pub ChainLen: c_int,
|
||||
pub ChainEntries: [DWORD; MAX_PROTOCOL_CHAIN as uint],
|
||||
pub ChainEntries: [DWORD; MAX_PROTOCOL_CHAIN as usize],
|
||||
}
|
||||
|
||||
pub type LPWSAPROTOCOLCHAIN = *mut WSAPROTOCOLCHAIN;
|
||||
@ -1931,7 +1930,7 @@ pub mod types {
|
||||
pub iSecurityScheme: c_int,
|
||||
pub dwMessageSize: DWORD,
|
||||
pub dwProviderReserved: DWORD,
|
||||
pub szProtocol: [u8; (WSAPROTOCOL_LEN as uint) + 1us],
|
||||
pub szProtocol: [u8; WSAPROTOCOL_LEN as usize + 1us],
|
||||
}
|
||||
|
||||
pub type LPWSAPROTOCOL_INFO = *mut WSAPROTOCOL_INFO;
|
||||
|
@ -50,7 +50,10 @@ pub fn find_entry_point(session: &Session, ast_map: &ast_map::Map) {
|
||||
let any_exe = session.crate_types.borrow().iter().any(|ty| {
|
||||
*ty == config::CrateTypeExecutable
|
||||
});
|
||||
if !any_exe {
|
||||
let emit_link = session.opts.output_types.iter().any(|ty| {
|
||||
*ty == config::OutputTypeExe
|
||||
});
|
||||
if !any_exe || !emit_link {
|
||||
// No need to find a main function
|
||||
return
|
||||
}
|
||||
|
@ -1549,6 +1549,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
return Ok(ParameterBuiltin);
|
||||
}
|
||||
|
||||
// Upvars are always local variables or references to
|
||||
// local variables, and local variables cannot be
|
||||
// unsized, so the closure struct as a whole must be
|
||||
// Sized.
|
||||
if bound == ty::BoundSized {
|
||||
return Ok(If(Vec::new()));
|
||||
}
|
||||
|
||||
match self.closure_typer.closure_upvars(def_id, substs) {
|
||||
Some(upvars) => {
|
||||
Ok(If(upvars.iter().map(|c| c.ty).collect()))
|
||||
|
@ -70,7 +70,7 @@ use arena::TypedArena;
|
||||
use std::borrow::{BorrowFrom, Cow};
|
||||
use std::cell::{Cell, RefCell};
|
||||
use std::cmp;
|
||||
use std::fmt::{self, Show};
|
||||
use std::fmt;
|
||||
use std::hash::{Hash, Writer, SipHasher, Hasher};
|
||||
use std::mem;
|
||||
use std::ops;
|
||||
|
@ -83,7 +83,7 @@ pub struct Options {
|
||||
pub debuginfo: DebugInfoLevel,
|
||||
pub lint_opts: Vec<(String, lint::Level)>,
|
||||
pub describe_lints: bool,
|
||||
pub output_types: Vec<OutputType> ,
|
||||
pub output_types: Vec<OutputType>,
|
||||
// This was mutable for rustpkg, which updates search paths based on the
|
||||
// parsed code. It remains mutable in case its replacements wants to use
|
||||
// this.
|
||||
@ -1076,7 +1076,9 @@ pub fn parse_crate_types_from_list(list_list: Vec<String>) -> Result<Vec<CrateTy
|
||||
part));
|
||||
}
|
||||
};
|
||||
crate_types.push(new_part)
|
||||
if !crate_types.contains(&new_part) {
|
||||
crate_types.push(new_part)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -118,6 +118,7 @@ fn report_cannot_move_out_of<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
|
||||
match move_from.cat {
|
||||
mc::cat_deref(_, _, mc::BorrowedPtr(..)) |
|
||||
mc::cat_deref(_, _, mc::Implicit(..)) |
|
||||
mc::cat_deref(_, _, mc::UnsafePtr(..)) |
|
||||
mc::cat_static_item => {
|
||||
bccx.span_err(move_from.span,
|
||||
&format!("cannot move out of {}",
|
||||
|
@ -390,8 +390,8 @@ enum PrivacyResult {
|
||||
|
||||
enum FieldName {
|
||||
UnnamedField(uint), // index
|
||||
// FIXME #6993: change type (and name) from Ident to Name
|
||||
NamedField(ast::Ident),
|
||||
// (Name, not Ident, because struct fields are not macro-hygienic)
|
||||
NamedField(ast::Name),
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> {
|
||||
@ -665,9 +665,9 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> {
|
||||
name: FieldName) {
|
||||
let fields = ty::lookup_struct_fields(self.tcx, id);
|
||||
let field = match name {
|
||||
NamedField(ident) => {
|
||||
debug!("privacy - check named field {} in struct {:?}", ident.name, id);
|
||||
fields.iter().find(|f| f.name == ident.name).unwrap()
|
||||
NamedField(f_name) => {
|
||||
debug!("privacy - check named field {} in struct {:?}", f_name, id);
|
||||
fields.iter().find(|f| f.name == f_name).unwrap()
|
||||
}
|
||||
UnnamedField(idx) => &fields[idx]
|
||||
};
|
||||
@ -686,7 +686,7 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> {
|
||||
};
|
||||
let msg = match name {
|
||||
NamedField(name) => format!("field `{}` of {} is private",
|
||||
token::get_ident(name), struct_desc),
|
||||
token::get_name(name), struct_desc),
|
||||
UnnamedField(idx) => format!("field #{} of {} is private",
|
||||
idx + 1, struct_desc),
|
||||
};
|
||||
@ -873,7 +873,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> {
|
||||
match expr.node {
|
||||
ast::ExprField(ref base, ident) => {
|
||||
if let ty::ty_struct(id, _) = ty::expr_ty_adjusted(self.tcx, &**base).sty {
|
||||
self.check_field(expr.span, id, NamedField(ident.node));
|
||||
self.check_field(expr.span, id, NamedField(ident.node.name));
|
||||
}
|
||||
}
|
||||
ast::ExprTupField(ref base, idx) => {
|
||||
@ -897,10 +897,14 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> {
|
||||
}
|
||||
ast::ExprStruct(_, ref fields, _) => {
|
||||
match ty::expr_ty(self.tcx, expr).sty {
|
||||
ty::ty_struct(id, _) => {
|
||||
for field in &(*fields) {
|
||||
self.check_field(expr.span, id,
|
||||
NamedField(field.ident.node));
|
||||
ty::ty_struct(ctor_id, _) => {
|
||||
// RFC 736: ensure all unmentioned fields are visible.
|
||||
// Rather than computing the set of unmentioned fields
|
||||
// (i.e. `all_fields - fields`), just check them all.
|
||||
let all_fields = ty::lookup_struct_fields(self.tcx, ctor_id);
|
||||
for field in all_fields {
|
||||
self.check_field(expr.span, ctor_id,
|
||||
NamedField(field.name));
|
||||
}
|
||||
}
|
||||
ty::ty_enum(_, _) => {
|
||||
@ -908,7 +912,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> {
|
||||
def::DefVariant(_, variant_id, _) => {
|
||||
for field in fields {
|
||||
self.check_field(expr.span, variant_id,
|
||||
NamedField(field.ident.node));
|
||||
NamedField(field.ident.node.name));
|
||||
}
|
||||
}
|
||||
_ => self.tcx.sess.span_bug(expr.span,
|
||||
@ -973,7 +977,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> {
|
||||
ty::ty_struct(id, _) => {
|
||||
for field in fields {
|
||||
self.check_field(pattern.span, id,
|
||||
NamedField(field.node.ident));
|
||||
NamedField(field.node.ident.name));
|
||||
}
|
||||
}
|
||||
ty::ty_enum(_, _) => {
|
||||
@ -981,7 +985,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> {
|
||||
Some(&def::DefVariant(_, variant_id, _)) => {
|
||||
for field in fields {
|
||||
self.check_field(pattern.span, variant_id,
|
||||
NamedField(field.node.ident));
|
||||
NamedField(field.node.ident.name));
|
||||
}
|
||||
}
|
||||
_ => self.tcx.sess.span_bug(pattern.span,
|
||||
|
@ -9,11 +9,11 @@
|
||||
// except according to those terms.
|
||||
|
||||
use check::{FnCtxt, structurally_resolved_type};
|
||||
use check::demand;
|
||||
use middle::traits::{self, ObjectSafetyViolation, MethodViolationCode};
|
||||
use middle::traits::{Obligation, ObligationCause};
|
||||
use middle::traits::report_fulfillment_errors;
|
||||
use middle::ty::{self, Ty, AsPredicate};
|
||||
use middle::infer;
|
||||
use syntax::ast;
|
||||
use syntax::codemap::Span;
|
||||
use util::nodemap::FnvHashSet;
|
||||
@ -24,71 +24,63 @@ pub fn check_object_cast<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
|
||||
source_expr: &ast::Expr,
|
||||
target_object_ty: Ty<'tcx>)
|
||||
{
|
||||
let tcx = fcx.tcx();
|
||||
debug!("check_object_cast(cast_expr={}, target_object_ty={})",
|
||||
cast_expr.repr(fcx.tcx()),
|
||||
target_object_ty.repr(fcx.tcx()));
|
||||
cast_expr.repr(tcx),
|
||||
target_object_ty.repr(tcx));
|
||||
|
||||
// Look up vtables for the type we're casting to,
|
||||
// passing in the source and target type. The source
|
||||
// must be a pointer type suitable to the object sigil,
|
||||
// e.g.: `&x as &Trait` or `box x as Box<Trait>`
|
||||
let source_ty = fcx.expr_ty(source_expr);
|
||||
let source_ty = structurally_resolved_type(fcx, source_expr.span, source_ty);
|
||||
debug!("source_ty={}", source_ty.repr(fcx.tcx()));
|
||||
match (&source_ty.sty, &target_object_ty.sty) {
|
||||
(&ty::ty_uniq(referent_ty), &ty::ty_uniq(object_trait_ty)) => {
|
||||
let object_trait = object_trait(&object_trait_ty);
|
||||
|
||||
// Ensure that if ~T is cast to ~Trait, then T : Trait
|
||||
push_cast_obligation(fcx, cast_expr, object_trait, referent_ty);
|
||||
check_object_safety(fcx.tcx(), object_trait, source_expr.span);
|
||||
// First, construct a fresh type that we can feed into `<expr>`
|
||||
// within `<expr> as <type>` to inform type inference (e.g. to
|
||||
// tell it that we are expecting a `Box<_>` or an `&_`).
|
||||
let fresh_ty = fcx.infcx().next_ty_var();
|
||||
let (object_trait_ty, source_expected_ty) = match target_object_ty.sty {
|
||||
ty::ty_uniq(object_trait_ty) => {
|
||||
(object_trait_ty, ty::mk_uniq(fcx.tcx(), fresh_ty))
|
||||
}
|
||||
|
||||
(&ty::ty_rptr(referent_region, ty::mt { ty: referent_ty,
|
||||
mutbl: referent_mutbl }),
|
||||
&ty::ty_rptr(target_region, ty::mt { ty: object_trait_ty,
|
||||
mutbl: target_mutbl })) =>
|
||||
{
|
||||
let object_trait = object_trait(&object_trait_ty);
|
||||
if !mutability_allowed(referent_mutbl, target_mutbl) {
|
||||
span_err!(fcx.tcx().sess, source_expr.span, E0188,
|
||||
"types differ in mutability");
|
||||
} else {
|
||||
// Ensure that if &'a T is cast to &'b Trait, then T : Trait
|
||||
push_cast_obligation(fcx, cast_expr,
|
||||
object_trait,
|
||||
referent_ty);
|
||||
|
||||
// Ensure that if &'a T is cast to &'b Trait, then 'b <= 'a
|
||||
infer::mk_subr(fcx.infcx(),
|
||||
infer::RelateObjectBound(source_expr.span),
|
||||
*target_region,
|
||||
*referent_region);
|
||||
|
||||
check_object_safety(fcx.tcx(), object_trait, source_expr.span);
|
||||
}
|
||||
ty::ty_rptr(target_region, ty::mt { ty: object_trait_ty,
|
||||
mutbl: target_mutbl }) => {
|
||||
(object_trait_ty,
|
||||
ty::mk_rptr(fcx.tcx(),
|
||||
target_region, ty::mt { ty: fresh_ty,
|
||||
mutbl: target_mutbl }))
|
||||
}
|
||||
|
||||
(_, &ty::ty_uniq(..)) => {
|
||||
span_err!(fcx.ccx.tcx.sess, source_expr.span, E0189,
|
||||
"can only cast a boxed pointer \
|
||||
to a boxed object, not a {}",
|
||||
ty::ty_sort_string(fcx.tcx(), source_ty));
|
||||
}
|
||||
|
||||
(_, &ty::ty_rptr(..)) => {
|
||||
span_err!(fcx.ccx.tcx.sess, source_expr.span, E0190,
|
||||
"can only cast a &-pointer \
|
||||
to an &-object, not a {}",
|
||||
ty::ty_sort_string(fcx.tcx(), source_ty));
|
||||
}
|
||||
|
||||
_ => {
|
||||
fcx.tcx().sess.span_bug(
|
||||
source_expr.span,
|
||||
"expected object type");
|
||||
fcx.tcx().sess.span_bug(source_expr.span, "expected object type");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let source_ty = fcx.expr_ty(source_expr);
|
||||
debug!("check_object_cast pre unify source_ty={}", source_ty.repr(tcx));
|
||||
|
||||
// This ensures that the source_ty <: source_expected_ty, which
|
||||
// will ensure e.g. that &'a T <: &'b T when doing `&'a T as &'b Trait`
|
||||
//
|
||||
// FIXME (pnkfelix): do we need to use suptype_with_fn in order to
|
||||
// override the error message emitted when the types do not work
|
||||
// out in the manner desired?
|
||||
demand::suptype(fcx, source_expr.span, source_expected_ty, source_ty);
|
||||
|
||||
debug!("check_object_cast postunify source_ty={}", source_ty.repr(tcx));
|
||||
let source_ty = structurally_resolved_type(fcx, source_expr.span, source_ty);
|
||||
debug!("check_object_cast resolveto source_ty={}", source_ty.repr(tcx));
|
||||
|
||||
let object_trait = object_trait(&object_trait_ty);
|
||||
|
||||
let referent_ty = match source_ty.sty {
|
||||
ty::ty_uniq(ty) => ty,
|
||||
ty::ty_rptr(_, ty::mt { ty, mutbl: _ }) => ty,
|
||||
_ => fcx.tcx().sess.span_bug(source_expr.span,
|
||||
"expected appropriate reference type"),
|
||||
};
|
||||
|
||||
// Ensure that if Ptr<T> is cast to Ptr<Trait>, then T : Trait.
|
||||
push_cast_obligation(fcx, cast_expr, object_trait, referent_ty);
|
||||
check_object_safety(tcx, object_trait, source_expr.span);
|
||||
|
||||
fn object_trait<'a, 'tcx>(t: &'a Ty<'tcx>) -> &'a ty::TyTrait<'tcx> {
|
||||
match t.sty {
|
||||
@ -97,13 +89,6 @@ pub fn check_object_cast<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
|
||||
}
|
||||
}
|
||||
|
||||
fn mutability_allowed(a_mutbl: ast::Mutability,
|
||||
b_mutbl: ast::Mutability)
|
||||
-> bool {
|
||||
a_mutbl == b_mutbl ||
|
||||
(a_mutbl == ast::MutMutable && b_mutbl == ast::MutImmutable)
|
||||
}
|
||||
|
||||
fn push_cast_obligation<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
|
||||
cast_expr: &ast::Expr,
|
||||
object_trait: &ty::TyTrait<'tcx>,
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
//! HTML formatting module
|
||||
//!
|
||||
//! This module contains a large number of `fmt::String` implementations for
|
||||
//! This module contains a large number of `fmt::Display` implementations for
|
||||
//! various types in `rustdoc::clean`. These implementations all currently
|
||||
//! assume that HTML output is desired, although it may be possible to redesign
|
||||
//! them in the future to instead emit any format desired.
|
||||
|
@ -64,7 +64,7 @@
|
||||
|
||||
body {
|
||||
color: #333;
|
||||
font: 16px/1.4 "Source Serif Pro", "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
font: 16px/1.4 "Source Serif Pro", Georgia, Times, "Times New Roman", serif;
|
||||
margin: 0;
|
||||
position: relative;
|
||||
padding: 10px 15px 20px 15px;
|
||||
|
@ -24,11 +24,8 @@ use rustc::session::{self, config};
|
||||
use rustc::session::config::get_unstable_features_setting;
|
||||
use rustc::session::search_paths::{SearchPaths, PathKind};
|
||||
use rustc_driver::{driver, Compilation};
|
||||
use syntax::ast;
|
||||
use syntax::codemap::{CodeMap, dummy_spanned};
|
||||
use syntax::codemap::CodeMap;
|
||||
use syntax::diagnostic;
|
||||
use syntax::parse::token;
|
||||
use syntax::ptr::P;
|
||||
|
||||
use core;
|
||||
use clean;
|
||||
@ -67,10 +64,7 @@ pub fn run(input: &str,
|
||||
span_diagnostic_handler);
|
||||
|
||||
let mut cfg = config::build_configuration(&sess);
|
||||
cfg.extend(cfgs.into_iter().map(|cfg_| {
|
||||
let cfg_ = token::intern_and_get_ident(&cfg_);
|
||||
P(dummy_spanned(ast::MetaWord(cfg_)))
|
||||
}));
|
||||
cfg.extend(config::parse_cfgspecs(cfgs).into_iter());
|
||||
let krate = driver::phase_1_parse_input(&sess, cfg, &input);
|
||||
let krate = driver::phase_2_configure_and_expand(&sess, krate,
|
||||
"rustdoc-test", None)
|
||||
|
@ -1032,7 +1032,7 @@ pub fn as_pretty_json<T>(t: &T) -> AsPrettyJson<T> {
|
||||
|
||||
impl Json {
|
||||
/// Borrow this json object as a pretty object to generate a pretty
|
||||
/// representation for it via `Show`.
|
||||
/// representation for it via `Display`.
|
||||
pub fn pretty(&self) -> PrettyJson {
|
||||
PrettyJson { inner: self }
|
||||
}
|
||||
@ -3540,7 +3540,7 @@ mod tests {
|
||||
fn test_hashmap_with_enum_key() {
|
||||
use std::collections::HashMap;
|
||||
use json;
|
||||
#[derive(RustcEncodable, Eq, Hash, PartialEq, RustcDecodable, Show)]
|
||||
#[derive(RustcEncodable, Eq, Hash, PartialEq, RustcDecodable, Debug)]
|
||||
enum Enum {
|
||||
Foo,
|
||||
#[allow(dead_code)]
|
||||
|
@ -338,7 +338,6 @@ mod tests {
|
||||
assert!("".is_ascii());
|
||||
assert!("a".is_ascii());
|
||||
assert!(!"\u{2009}".is_ascii());
|
||||
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -346,13 +345,11 @@ mod tests {
|
||||
assert_eq!("url()URL()uRl()ürl".to_ascii_uppercase(), "URL()URL()URL()üRL");
|
||||
assert_eq!("hıKß".to_ascii_uppercase(), "HıKß");
|
||||
|
||||
let mut i = 0;
|
||||
while i <= 500 {
|
||||
for i in 0u32..501 {
|
||||
let upper = if 'a' as u32 <= i && i <= 'z' as u32 { i + 'A' as u32 - 'a' as u32 }
|
||||
else { i };
|
||||
assert_eq!((from_u32(i).unwrap()).to_string().to_ascii_uppercase(),
|
||||
(from_u32(upper).unwrap()).to_string());
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
|
||||
@ -362,13 +359,11 @@ mod tests {
|
||||
// Dotted capital I, Kelvin sign, Sharp S.
|
||||
assert_eq!("HİKß".to_ascii_lowercase(), "hİKß");
|
||||
|
||||
let mut i = 0;
|
||||
while i <= 500 {
|
||||
for i in 0u32..501 {
|
||||
let lower = if 'A' as u32 <= i && i <= 'Z' as u32 { i + 'a' as u32 - 'A' as u32 }
|
||||
else { i };
|
||||
assert_eq!((from_u32(i).unwrap()).to_string().to_ascii_lowercase(),
|
||||
(from_u32(lower).unwrap()).to_string());
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
|
||||
@ -378,13 +373,11 @@ mod tests {
|
||||
"URL()URL()URL()üRL".to_string());
|
||||
assert_eq!(("hıKß".to_string()).into_ascii_uppercase(), "HıKß");
|
||||
|
||||
let mut i = 0;
|
||||
while i <= 500 {
|
||||
for i in 0u32..501 {
|
||||
let upper = if 'a' as u32 <= i && i <= 'z' as u32 { i + 'A' as u32 - 'a' as u32 }
|
||||
else { i };
|
||||
assert_eq!((from_u32(i).unwrap()).to_string().into_ascii_uppercase(),
|
||||
(from_u32(upper).unwrap()).to_string());
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
|
||||
@ -395,13 +388,11 @@ mod tests {
|
||||
// Dotted capital I, Kelvin sign, Sharp S.
|
||||
assert_eq!(("HİKß".to_string()).into_ascii_lowercase(), "hİKß");
|
||||
|
||||
let mut i = 0;
|
||||
while i <= 500 {
|
||||
for i in 0u32..501 {
|
||||
let lower = if 'A' as u32 <= i && i <= 'Z' as u32 { i + 'a' as u32 - 'A' as u32 }
|
||||
else { i };
|
||||
assert_eq!((from_u32(i).unwrap()).to_string().into_ascii_lowercase(),
|
||||
(from_u32(lower).unwrap()).to_string());
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
|
||||
@ -415,14 +406,11 @@ mod tests {
|
||||
assert!(!"K".eq_ignore_ascii_case("k"));
|
||||
assert!(!"ß".eq_ignore_ascii_case("s"));
|
||||
|
||||
let mut i = 0;
|
||||
while i <= 500 {
|
||||
let c = i;
|
||||
let lower = if 'A' as u32 <= c && c <= 'Z' as u32 { c + 'a' as u32 - 'A' as u32 }
|
||||
else { c };
|
||||
for i in 0u32..501 {
|
||||
let lower = if 'A' as u32 <= i && i <= 'Z' as u32 { i + 'a' as u32 - 'A' as u32 }
|
||||
else { i };
|
||||
assert!((from_u32(i).unwrap()).to_string().eq_ignore_ascii_case(
|
||||
&from_u32(lower).unwrap().to_string()));
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1377,7 +1377,7 @@ impl<'a, K, V, S, H> IntoIterator for &'a HashMap<K, V, S>
|
||||
S: HashState<Hasher=H>,
|
||||
H: hash::Hasher<Output=u64>
|
||||
{
|
||||
type Iter = Iter<'a, K, V>;
|
||||
type IntoIter = Iter<'a, K, V>;
|
||||
|
||||
fn into_iter(self) -> Iter<'a, K, V> {
|
||||
self.iter()
|
||||
@ -1389,7 +1389,7 @@ impl<'a, K, V, S, H> IntoIterator for &'a mut HashMap<K, V, S>
|
||||
S: HashState<Hasher=H>,
|
||||
H: hash::Hasher<Output=u64>
|
||||
{
|
||||
type Iter = IterMut<'a, K, V>;
|
||||
type IntoIter = IterMut<'a, K, V>;
|
||||
|
||||
fn into_iter(mut self) -> IterMut<'a, K, V> {
|
||||
self.iter_mut()
|
||||
@ -1401,7 +1401,7 @@ impl<K, V, S, H> IntoIterator for HashMap<K, V, S>
|
||||
S: HashState<Hasher=H>,
|
||||
H: hash::Hasher<Output=u64>
|
||||
{
|
||||
type Iter = IntoIter<K, V>;
|
||||
type IntoIter = IntoIter<K, V>;
|
||||
|
||||
fn into_iter(self) -> IntoIter<K, V> {
|
||||
self.into_iter()
|
||||
|
@ -840,7 +840,7 @@ impl<'a, T, S, H> IntoIterator for &'a HashSet<T, S>
|
||||
S: HashState<Hasher=H>,
|
||||
H: hash::Hasher<Output=u64>
|
||||
{
|
||||
type Iter = Iter<'a, T>;
|
||||
type IntoIter = Iter<'a, T>;
|
||||
|
||||
fn into_iter(self) -> Iter<'a, T> {
|
||||
self.iter()
|
||||
@ -852,7 +852,7 @@ impl<T, S, H> IntoIterator for HashSet<T, S>
|
||||
S: HashState<Hasher=H>,
|
||||
H: hash::Hasher<Output=u64>
|
||||
{
|
||||
type Iter = IntoIter<T>;
|
||||
type IntoIter = IntoIter<T>;
|
||||
|
||||
fn into_iter(self) -> IntoIter<T> {
|
||||
self.into_iter()
|
||||
|
@ -228,7 +228,7 @@ pub trait GenericPath: Clone + GenericPathUnsafe {
|
||||
/// ```
|
||||
fn into_vec(self) -> Vec<u8>;
|
||||
|
||||
/// Returns an object that implements `Show` for printing paths
|
||||
/// Returns an object that implements `Display` for printing paths
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
@ -244,7 +244,7 @@ pub trait GenericPath: Clone + GenericPathUnsafe {
|
||||
Display{ path: self, filename: false }
|
||||
}
|
||||
|
||||
/// Returns an object that implements `Show` for printing filenames
|
||||
/// Returns an object that implements `Display` for printing filenames
|
||||
///
|
||||
/// If there is no filename, nothing will be printed.
|
||||
///
|
||||
|
@ -723,7 +723,7 @@ extern "system" {
|
||||
/// println!("{}", argument);
|
||||
/// }
|
||||
/// ```
|
||||
#[deprecated(since = "1.0.0", reason = "use env::args instead")]
|
||||
#[deprecated(since = "1.0.0", reason = "use std::env::args() instead")]
|
||||
#[unstable(feature = "os")]
|
||||
pub fn args() -> Vec<String> {
|
||||
real_args()
|
||||
|
@ -56,10 +56,6 @@ pub fn stack_guard() -> uint {
|
||||
|
||||
pub fn set(stack_bounds: (uint, uint), stack_guard: uint, thread: Thread) {
|
||||
THREAD_INFO.with(|c| assert!(c.borrow().is_none()));
|
||||
match thread.name() {
|
||||
Some(name) => unsafe { ::sys::thread::set_name(name); },
|
||||
None => {}
|
||||
}
|
||||
THREAD_INFO.with(move |c| *c.borrow_mut() = Some(ThreadInfo{
|
||||
stack_bounds: stack_bounds,
|
||||
stack_guard: stack_guard,
|
||||
|
@ -156,6 +156,7 @@ use ops::{Drop, FnOnce};
|
||||
use option::Option::{self, Some, None};
|
||||
use result::Result::{Err, Ok};
|
||||
use sync::{Mutex, Condvar, Arc};
|
||||
use str::Str;
|
||||
use string::String;
|
||||
use rt::{self, unwind};
|
||||
use old_io::{Writer, stdio};
|
||||
@ -280,6 +281,10 @@ impl Builder {
|
||||
unsafe {
|
||||
stack::record_os_managed_stack_bounds(my_stack_bottom, my_stack_top);
|
||||
}
|
||||
match their_thread.name() {
|
||||
Some(name) => unsafe { imp::set_name(name.as_slice()); },
|
||||
None => {}
|
||||
}
|
||||
thread_info::set(
|
||||
(my_stack_bottom, my_stack_top),
|
||||
unsafe { imp::guard::current() },
|
||||
|
@ -64,7 +64,6 @@ use parse::token;
|
||||
use ptr::P;
|
||||
|
||||
use std::fmt;
|
||||
use std::fmt::Show;
|
||||
use std::num::Int;
|
||||
use std::rc::Rc;
|
||||
use serialize::{Encodable, Decodable, Encoder, Decoder};
|
||||
|
@ -12,7 +12,7 @@ use attr::AttrMetaMethods;
|
||||
use diagnostic::SpanHandler;
|
||||
use fold::Folder;
|
||||
use {ast, fold, attr};
|
||||
use codemap::Spanned;
|
||||
use codemap::{Spanned, respan};
|
||||
use ptr::P;
|
||||
|
||||
use util::small_vector::SmallVector;
|
||||
@ -26,6 +26,7 @@ struct Context<F> where F: FnMut(&[ast::Attribute]) -> bool {
|
||||
// Support conditional compilation by transforming the AST, stripping out
|
||||
// any items that do not belong in the current configuration
|
||||
pub fn strip_unconfigured_items(diagnostic: &SpanHandler, krate: ast::Crate) -> ast::Crate {
|
||||
let krate = process_cfg_attr(diagnostic, krate);
|
||||
let config = krate.config.clone();
|
||||
strip_items(krate, |attrs| in_cfg(diagnostic, &config, attrs))
|
||||
}
|
||||
@ -281,3 +282,49 @@ fn in_cfg(diagnostic: &SpanHandler, cfg: &[P<ast::MetaItem>], attrs: &[ast::Attr
|
||||
attr::cfg_matches(diagnostic, cfg, &*mis[0])
|
||||
})
|
||||
}
|
||||
|
||||
struct CfgAttrFolder<'a> {
|
||||
diag: &'a SpanHandler,
|
||||
config: ast::CrateConfig,
|
||||
}
|
||||
|
||||
// Process `#[cfg_attr]`.
|
||||
fn process_cfg_attr(diagnostic: &SpanHandler, krate: ast::Crate) -> ast::Crate {
|
||||
let mut fld = CfgAttrFolder {
|
||||
diag: diagnostic,
|
||||
config: krate.config.clone(),
|
||||
};
|
||||
fld.fold_crate(krate)
|
||||
}
|
||||
|
||||
impl<'a> fold::Folder for CfgAttrFolder<'a> {
|
||||
fn fold_attribute(&mut self, attr: ast::Attribute) -> Option<ast::Attribute> {
|
||||
if !attr.check_name("cfg_attr") {
|
||||
return fold::noop_fold_attribute(attr, self);
|
||||
}
|
||||
|
||||
let (cfg, mi) = match attr.meta_item_list() {
|
||||
Some([ref cfg, ref mi]) => (cfg, mi),
|
||||
_ => {
|
||||
self.diag.span_err(attr.span, "expected `#[cfg_attr(<cfg pattern>, <attr>)]`");
|
||||
return None;
|
||||
}
|
||||
};
|
||||
|
||||
if attr::cfg_matches(self.diag, &self.config[], &cfg) {
|
||||
Some(respan(mi.span, ast::Attribute_ {
|
||||
id: attr::mk_attr_id(),
|
||||
style: attr.node.style,
|
||||
value: mi.clone(),
|
||||
is_sugared_doc: false,
|
||||
}))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
// Need the ability to run pre-expansion.
|
||||
fn fold_mac(&mut self, mac: ast::Mac) -> ast::Mac {
|
||||
fold::noop_fold_mac(mac, self)
|
||||
}
|
||||
}
|
||||
|
@ -518,10 +518,11 @@ fn highlight_lines(err: &mut EmitterWriter,
|
||||
let count = match lastc {
|
||||
// Most terminals have a tab stop every eight columns by default
|
||||
'\t' => 8 - col%8,
|
||||
_ => lastc.width(false).unwrap_or(1),
|
||||
_ => lastc.width(false).unwrap_or(0),
|
||||
};
|
||||
col += count;
|
||||
s.extend(::std::iter::repeat('~').take(count - 1));
|
||||
s.extend(::std::iter::repeat('~').take(count));
|
||||
|
||||
let hi = cm.lookup_char_pos(sp.hi);
|
||||
if hi.col != lo.col {
|
||||
for (pos, ch) in iter {
|
||||
@ -534,6 +535,12 @@ fn highlight_lines(err: &mut EmitterWriter,
|
||||
s.extend(::std::iter::repeat('~').take(count));
|
||||
}
|
||||
}
|
||||
|
||||
if s.len() > 1 {
|
||||
// One extra squiggly is replaced by a "^"
|
||||
s.pop();
|
||||
}
|
||||
|
||||
try!(print_maybe_styled(err,
|
||||
&format!("{}\n", s)[],
|
||||
term::attr::ForegroundColor(lvl.color())));
|
||||
|
@ -528,8 +528,6 @@ fn initial_syntax_expander_table(ecfg: &expand::ExpansionConfig) -> SyntaxEnv {
|
||||
syntax_expanders.insert(intern("cfg"),
|
||||
builtin_normal_expander(
|
||||
ext::cfg::expand_cfg));
|
||||
syntax_expanders.insert(intern("cfg_attr"),
|
||||
Modifier(box ext::cfg_attr::expand));
|
||||
syntax_expanders.insert(intern("trace_macros"),
|
||||
builtin_normal_expander(
|
||||
ext::trace_macros::expand_trace_macros));
|
||||
|
@ -40,6 +40,18 @@ pub trait AstBuilder {
|
||||
bindings: Vec<P<ast::TypeBinding>> )
|
||||
-> ast::Path;
|
||||
|
||||
fn qpath(&self, self_type: P<ast::Ty>,
|
||||
trait_ref: P<ast::TraitRef>,
|
||||
ident: ast::Ident )
|
||||
-> P<ast::QPath>;
|
||||
fn qpath_all(&self, self_type: P<ast::Ty>,
|
||||
trait_ref: P<ast::TraitRef>,
|
||||
ident: ast::Ident,
|
||||
lifetimes: Vec<ast::Lifetime>,
|
||||
types: Vec<P<ast::Ty>>,
|
||||
bindings: Vec<P<ast::TypeBinding>> )
|
||||
-> P<ast::QPath>;
|
||||
|
||||
// types
|
||||
fn ty_mt(&self, ty: P<ast::Ty>, mutbl: ast::Mutability) -> ast::MutTy;
|
||||
|
||||
@ -102,6 +114,7 @@ pub trait AstBuilder {
|
||||
// expressions
|
||||
fn expr(&self, span: Span, node: ast::Expr_) -> P<ast::Expr>;
|
||||
fn expr_path(&self, path: ast::Path) -> P<ast::Expr>;
|
||||
fn expr_qpath(&self, span: Span, qpath: P<ast::QPath>) -> P<ast::Expr>;
|
||||
fn expr_ident(&self, span: Span, id: ast::Ident) -> P<ast::Expr>;
|
||||
|
||||
fn expr_self(&self, span: Span) -> P<ast::Expr>;
|
||||
@ -330,6 +343,44 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Constructs a qualified path.
|
||||
///
|
||||
/// Constructs a path like `<self_type as trait_ref>::ident`.
|
||||
fn qpath(&self,
|
||||
self_type: P<ast::Ty>,
|
||||
trait_ref: P<ast::TraitRef>,
|
||||
ident: ast::Ident)
|
||||
-> P<ast::QPath> {
|
||||
self.qpath_all(self_type, trait_ref, ident, Vec::new(), Vec::new(), Vec::new())
|
||||
}
|
||||
|
||||
/// Constructs a qualified path.
|
||||
///
|
||||
/// Constructs a path like `<self_type as trait_ref>::ident<a, T, A=Bar>`.
|
||||
fn qpath_all(&self,
|
||||
self_type: P<ast::Ty>,
|
||||
trait_ref: P<ast::TraitRef>,
|
||||
ident: ast::Ident,
|
||||
lifetimes: Vec<ast::Lifetime>,
|
||||
types: Vec<P<ast::Ty>>,
|
||||
bindings: Vec<P<ast::TypeBinding>> )
|
||||
-> P<ast::QPath> {
|
||||
let segment = ast::PathSegment {
|
||||
identifier: ident,
|
||||
parameters: ast::AngleBracketedParameters(ast::AngleBracketedParameterData {
|
||||
lifetimes: lifetimes,
|
||||
types: OwnedSlice::from_vec(types),
|
||||
bindings: OwnedSlice::from_vec(bindings),
|
||||
})
|
||||
};
|
||||
|
||||
P(ast::QPath {
|
||||
self_type: self_type,
|
||||
trait_ref: trait_ref,
|
||||
item_path: segment,
|
||||
})
|
||||
}
|
||||
|
||||
fn ty_mt(&self, ty: P<ast::Ty>, mutbl: ast::Mutability) -> ast::MutTy {
|
||||
ast::MutTy {
|
||||
ty: ty,
|
||||
@ -554,6 +605,11 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
|
||||
self.expr(path.span, ast::ExprPath(path))
|
||||
}
|
||||
|
||||
/// Constructs a QPath expression.
|
||||
fn expr_qpath(&self, span: Span, qpath: P<ast::QPath>) -> P<ast::Expr> {
|
||||
self.expr(span, ast::ExprQPath(qpath))
|
||||
}
|
||||
|
||||
fn expr_ident(&self, span: Span, id: ast::Ident) -> P<ast::Expr> {
|
||||
self.expr_path(self.path_ident(span, id))
|
||||
}
|
||||
|
@ -1,34 +0,0 @@
|
||||
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use ast;
|
||||
use attr;
|
||||
use codemap::Span;
|
||||
use ext::base::ExtCtxt;
|
||||
use ext::build::AstBuilder;
|
||||
use ptr::P;
|
||||
|
||||
pub fn expand(cx: &mut ExtCtxt, sp: Span, mi: &ast::MetaItem, it: P<ast::Item>) -> P<ast::Item> {
|
||||
let (cfg, attr) = match mi.node {
|
||||
ast::MetaList(_, ref mis) if mis.len() == 2 => (&mis[0], &mis[1]),
|
||||
_ => {
|
||||
cx.span_err(sp, "expected `#[cfg_attr(<cfg pattern>, <attr>)]`");
|
||||
return it;
|
||||
}
|
||||
};
|
||||
|
||||
let mut out = (*it).clone();
|
||||
if attr::cfg_matches(&cx.parse_sess.span_diagnostic, &cx.cfg, &**cfg) {
|
||||
out.attrs.push(cx.attribute(attr.span, attr.clone()));
|
||||
}
|
||||
|
||||
P(out)
|
||||
}
|
||||
|
@ -844,7 +844,7 @@ fn expand_arm(arm: ast::Arm, fld: &mut MacroExpander) -> ast::Arm {
|
||||
arm.guard.map(|g| fld.fold_expr(rename_fld.fold_expr(g)));
|
||||
let rewritten_body = fld.fold_expr(rename_fld.fold_expr(arm.body));
|
||||
ast::Arm {
|
||||
attrs: arm.attrs.move_map(|x| fld.fold_attribute(x)),
|
||||
attrs: fold::fold_attrs(arm.attrs, fld),
|
||||
pats: rewritten_pats,
|
||||
guard: rewritten_guard,
|
||||
body: rewritten_body,
|
||||
@ -1273,7 +1273,7 @@ fn expand_method(m: P<ast::Method>, fld: &mut MacroExpander) -> SmallVector<P<as
|
||||
let (rewritten_fn_decl, rewritten_body)
|
||||
= expand_and_rename_fn_decl_and_block(decl, body, fld);
|
||||
SmallVector::one(P(ast::Method {
|
||||
attrs: m.attrs.move_map(|a| fld.fold_attribute(a)),
|
||||
attrs: fold::fold_attrs(m.attrs, fld),
|
||||
id: id,
|
||||
span: fld.new_span(m.span),
|
||||
node: ast::MethDecl(fld.fold_ident(ident),
|
||||
|
@ -223,7 +223,7 @@ pub trait Folder : Sized {
|
||||
noop_fold_lifetime_def(l, self)
|
||||
}
|
||||
|
||||
fn fold_attribute(&mut self, at: Attribute) -> Attribute {
|
||||
fn fold_attribute(&mut self, at: Attribute) -> Option<Attribute> {
|
||||
noop_fold_attribute(at, self)
|
||||
}
|
||||
|
||||
@ -373,9 +373,13 @@ pub fn noop_fold_view_path<T: Folder>(view_path: P<ViewPath>, fld: &mut T) -> P<
|
||||
})
|
||||
}
|
||||
|
||||
pub fn fold_attrs<T: Folder>(attrs: Vec<Attribute>, fld: &mut T) -> Vec<Attribute> {
|
||||
attrs.into_iter().flat_map(|x| fld.fold_attribute(x).into_iter()).collect()
|
||||
}
|
||||
|
||||
pub fn noop_fold_arm<T: Folder>(Arm {attrs, pats, guard, body}: Arm, fld: &mut T) -> Arm {
|
||||
Arm {
|
||||
attrs: attrs.move_map(|x| fld.fold_attribute(x)),
|
||||
attrs: fold_attrs(attrs, fld),
|
||||
pats: pats.move_map(|x| fld.fold_pat(x)),
|
||||
guard: guard.map(|x| fld.fold_expr(x)),
|
||||
body: fld.fold_expr(body),
|
||||
@ -475,7 +479,7 @@ pub fn noop_fold_variant<T: Folder>(v: P<Variant>, fld: &mut T) -> P<Variant> {
|
||||
node: Variant_ {
|
||||
id: fld.new_id(id),
|
||||
name: name,
|
||||
attrs: attrs.move_map(|x| fld.fold_attribute(x)),
|
||||
attrs: fold_attrs(attrs, fld),
|
||||
kind: match kind {
|
||||
TupleVariantKind(variant_args) => {
|
||||
TupleVariantKind(variant_args.move_map(|x|
|
||||
@ -553,9 +557,9 @@ pub fn noop_fold_local<T: Folder>(l: P<Local>, fld: &mut T) -> P<Local> {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn noop_fold_attribute<T: Folder>(at: Attribute, fld: &mut T) -> Attribute {
|
||||
pub fn noop_fold_attribute<T: Folder>(at: Attribute, fld: &mut T) -> Option<Attribute> {
|
||||
let Spanned {node: Attribute_ {id, style, value, is_sugared_doc}, span} = at;
|
||||
Spanned {
|
||||
Some(Spanned {
|
||||
node: Attribute_ {
|
||||
id: id,
|
||||
style: style,
|
||||
@ -563,7 +567,7 @@ pub fn noop_fold_attribute<T: Folder>(at: Attribute, fld: &mut T) -> Attribute {
|
||||
is_sugared_doc: is_sugared_doc
|
||||
},
|
||||
span: fld.new_span(span)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn noop_fold_explicit_self_underscore<T: Folder>(es: ExplicitSelf_, fld: &mut T)
|
||||
@ -845,8 +849,8 @@ pub fn noop_fold_typedef<T>(t: Typedef, folder: &mut T)
|
||||
where T: Folder {
|
||||
let new_id = folder.new_id(t.id);
|
||||
let new_span = folder.new_span(t.span);
|
||||
let new_attrs = t.attrs.iter().map(|attr| {
|
||||
folder.fold_attribute((*attr).clone())
|
||||
let new_attrs = t.attrs.iter().flat_map(|attr| {
|
||||
folder.fold_attribute((*attr).clone()).into_iter()
|
||||
}).collect();
|
||||
let new_ident = folder.fold_ident(t.ident);
|
||||
let new_type = folder.fold_ty(t.typ);
|
||||
@ -866,7 +870,7 @@ pub fn noop_fold_associated_type<T>(at: AssociatedType, folder: &mut T)
|
||||
{
|
||||
let new_attrs = at.attrs
|
||||
.iter()
|
||||
.map(|attr| folder.fold_attribute((*attr).clone()))
|
||||
.flat_map(|attr| folder.fold_attribute((*attr).clone()).into_iter())
|
||||
.collect();
|
||||
let new_param = folder.fold_ty_param(at.ty_param);
|
||||
ast::AssociatedType {
|
||||
@ -909,7 +913,7 @@ pub fn noop_fold_struct_field<T: Folder>(f: StructField, fld: &mut T) -> StructF
|
||||
id: fld.new_id(id),
|
||||
kind: kind,
|
||||
ty: fld.fold_ty(ty),
|
||||
attrs: attrs.move_map(|a| fld.fold_attribute(a))
|
||||
attrs: fold_attrs(attrs, fld),
|
||||
},
|
||||
span: fld.new_span(span)
|
||||
}
|
||||
@ -1072,7 +1076,7 @@ pub fn noop_fold_type_method<T: Folder>(m: TypeMethod, fld: &mut T) -> TypeMetho
|
||||
TypeMethod {
|
||||
id: fld.new_id(id),
|
||||
ident: fld.fold_ident(ident),
|
||||
attrs: attrs.move_map(|a| fld.fold_attribute(a)),
|
||||
attrs: fold_attrs(attrs, fld),
|
||||
unsafety: unsafety,
|
||||
abi: abi,
|
||||
decl: fld.fold_fn_decl(decl),
|
||||
@ -1154,7 +1158,7 @@ pub fn noop_fold_item_simple<T: Folder>(Item {id, ident, attrs, node, vis, span}
|
||||
Item {
|
||||
id: id,
|
||||
ident: folder.fold_ident(ident),
|
||||
attrs: attrs.move_map(|e| folder.fold_attribute(e)),
|
||||
attrs: fold_attrs(attrs, folder),
|
||||
node: node,
|
||||
vis: vis,
|
||||
span: folder.new_span(span)
|
||||
@ -1165,7 +1169,7 @@ pub fn noop_fold_foreign_item<T: Folder>(ni: P<ForeignItem>, folder: &mut T) ->
|
||||
ni.map(|ForeignItem {id, ident, attrs, node, span, vis}| ForeignItem {
|
||||
id: folder.new_id(id),
|
||||
ident: folder.fold_ident(ident),
|
||||
attrs: attrs.move_map(|x| folder.fold_attribute(x)),
|
||||
attrs: fold_attrs(attrs, folder),
|
||||
node: match node {
|
||||
ForeignItemFn(fdec, generics) => {
|
||||
ForeignItemFn(folder.fold_fn_decl(fdec), folder.fold_generics(generics))
|
||||
@ -1184,7 +1188,7 @@ pub fn noop_fold_foreign_item<T: Folder>(ni: P<ForeignItem>, folder: &mut T) ->
|
||||
pub fn noop_fold_method<T: Folder>(m: P<Method>, folder: &mut T) -> SmallVector<P<Method>> {
|
||||
SmallVector::one(m.map(|Method {id, attrs, node, span}| Method {
|
||||
id: folder.new_id(id),
|
||||
attrs: attrs.move_map(|a| folder.fold_attribute(a)),
|
||||
attrs: fold_attrs(attrs, folder),
|
||||
node: match node {
|
||||
MethDecl(ident,
|
||||
generics,
|
||||
|
@ -96,7 +96,6 @@ pub mod ext {
|
||||
pub mod base;
|
||||
pub mod build;
|
||||
pub mod cfg;
|
||||
pub mod cfg_attr;
|
||||
pub mod concat;
|
||||
pub mod concat_idents;
|
||||
pub mod deriving;
|
||||
|
@ -562,7 +562,7 @@ declare_special_idents_and_keywords! {
|
||||
(45, Where, "where");
|
||||
'reserved:
|
||||
(46, Alignof, "alignof");
|
||||
(47, Be, "be");
|
||||
(47, Become, "become");
|
||||
(48, Offsetof, "offsetof");
|
||||
(49, Priv, "priv");
|
||||
(50, Pure, "pure");
|
||||
|
@ -52,7 +52,6 @@
|
||||
|
||||
#![feature(box_syntax)]
|
||||
#![feature(collections)]
|
||||
#![feature(core)]
|
||||
#![feature(int_uint)]
|
||||
#![feature(io)]
|
||||
#![feature(path)]
|
||||
|
18
src/test/compile-fail/cfg-attr-cfg-2.rs
Normal file
18
src/test/compile-fail/cfg-attr-cfg-2.rs
Normal file
@ -0,0 +1,18 @@
|
||||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
//
|
||||
// error-pattern: main function not found
|
||||
// compile-flags: --cfg foo
|
||||
|
||||
// main is conditionally compiled, but the conditional compilation
|
||||
// is conditional too!
|
||||
|
||||
#[cfg_attr(foo, cfg(bar))]
|
||||
fn main() { }
|
17
src/test/compile-fail/cfg-attr-crate-2.rs
Normal file
17
src/test/compile-fail/cfg-attr-crate-2.rs
Normal file
@ -0,0 +1,17 @@
|
||||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
//
|
||||
// compile-flags: --cfg broken
|
||||
|
||||
// https://github.com/rust-lang/rust/issues/21833#issuecomment-72353044
|
||||
|
||||
#![cfg_attr(broken, no_std)] //~ ERROR no_std is experimental
|
||||
|
||||
fn main() { }
|
@ -0,0 +1,42 @@
|
||||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// RFC 736 (and Issue 21407): functional struct update should respect privacy.
|
||||
|
||||
// The `foo` module attempts to maintains an invariant that each `S`
|
||||
// has a unique `u64` id.
|
||||
use self::foo::S;
|
||||
mod foo {
|
||||
use std::cell::{UnsafeCell};
|
||||
|
||||
static mut count : UnsafeCell<u64> = UnsafeCell { value: 1 };
|
||||
|
||||
pub struct S { pub a: u8, pub b: String, secret_uid: u64 }
|
||||
|
||||
pub fn make_secrets(a: u8, b: String) -> S {
|
||||
let val = unsafe { let p = count.get(); let val = *p; *p = val + 1; val };
|
||||
println!("creating {}, uid {}", b, val);
|
||||
S { a: a, b: b, secret_uid: val }
|
||||
}
|
||||
|
||||
impl Drop for S {
|
||||
fn drop(&mut self) {
|
||||
println!("dropping {}, uid {}", self.b, self.secret_uid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let s_1 = foo::make_secrets(3, format!("ess one"));
|
||||
let s_2 = foo::S { b: format!("ess two"), ..s_1 }; // FRU ...
|
||||
//~^ ERROR field `secret_uid` of struct `foo::S` is private
|
||||
println!("main forged an S named: {}", s_2.b);
|
||||
// at end of scope, ... both s_1 *and* s_2 get dropped. Boom!
|
||||
}
|
@ -13,6 +13,6 @@
|
||||
struct B<T>;
|
||||
|
||||
fn main() {
|
||||
let foo = B;
|
||||
let closure = || foo; //~ ERROR unable to infer enough type information
|
||||
let foo = B; //~ ERROR: unable to infer enough type information
|
||||
let closure = || foo;
|
||||
}
|
||||
|
@ -9,7 +9,6 @@
|
||||
// except according to those terms.
|
||||
|
||||
#![deny(unused_variables)]
|
||||
#![feature(core)]
|
||||
|
||||
fn main() {
|
||||
for _ in 1..101 {
|
||||
|
47
src/test/compile-fail/issue-20801.rs
Normal file
47
src/test/compile-fail/issue-20801.rs
Normal file
@ -0,0 +1,47 @@
|
||||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// We used to ICE when moving out of a `*mut T` or `*const T`.
|
||||
|
||||
struct T(u8);
|
||||
|
||||
static mut GLOBAL_MUT_T: T = T(0);
|
||||
|
||||
static GLOBAL_T: T = T(0);
|
||||
|
||||
fn imm_ref() -> &'static T {
|
||||
unsafe { &GLOBAL_T }
|
||||
}
|
||||
|
||||
fn mut_ref() -> &'static mut T {
|
||||
unsafe { &mut GLOBAL_MUT_T }
|
||||
}
|
||||
|
||||
fn mut_ptr() -> *mut T {
|
||||
unsafe { 0u8 as *mut T }
|
||||
}
|
||||
|
||||
fn const_ptr() -> *const T {
|
||||
unsafe { 0u8 as *const T }
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
let a = unsafe { *mut_ref() };
|
||||
//~^ ERROR cannot move out of borrowed content
|
||||
|
||||
let b = unsafe { *imm_ref() };
|
||||
//~^ ERROR cannot move out of borrowed content
|
||||
|
||||
let c = unsafe { *mut_ptr() };
|
||||
//~^ ERROR cannot move out of dereference of unsafe pointer
|
||||
|
||||
let d = unsafe { *const_ptr() };
|
||||
//~^ ERROR cannot move out of dereference of unsafe pointer
|
||||
}
|
@ -11,7 +11,6 @@
|
||||
#![deny(unreachable_code)]
|
||||
#![allow(unused_variables)]
|
||||
#![allow(dead_code)]
|
||||
#![feature(core)]
|
||||
|
||||
fn fail_len(v: Vec<isize> ) -> usize {
|
||||
let mut i = 3;
|
||||
|
@ -11,7 +11,6 @@
|
||||
#![deny(unused_variables)]
|
||||
#![deny(unused_assignments)]
|
||||
#![allow(dead_code, non_camel_case_types)]
|
||||
#![feature(core)]
|
||||
|
||||
fn f1(x: isize) {
|
||||
//~^ ERROR unused variable: `x`
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
|
||||
// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
@ -9,6 +9,6 @@
|
||||
// except according to those terms.
|
||||
|
||||
fn main() {
|
||||
let be = 0;
|
||||
//~^ ERROR `be` is a reserved keyword
|
||||
let become = 0;
|
||||
//~^ ERROR `become` is a reserved keyword
|
||||
}
|
@ -1,9 +1,7 @@
|
||||
-include ../tools.mk
|
||||
|
||||
ifndef IS_WINDOWS
|
||||
ifneq ($(shell uname),Darwin)
|
||||
EXTRAFLAGS := -lm -lrt -ldl -lpthread
|
||||
endif
|
||||
EXTRAFLAGS := $(EXTRACFLAGS)
|
||||
endif
|
||||
|
||||
# FIXME: ignore freebsd
|
||||
|
@ -2,3 +2,4 @@ include ../tools.mk
|
||||
|
||||
all:
|
||||
$(RUSTC) --crate-type=rlib foo.rs
|
||||
$(RUSTC) --crate-type=rlib,rlib foo.rs
|
||||
|
5
src/test/run-make/empty-file/Makefile
Normal file
5
src/test/run-make/empty-file/Makefile
Normal file
@ -0,0 +1,5 @@
|
||||
-include ../tools.mk
|
||||
|
||||
all:
|
||||
$(RUSTC) --emit=asm,llvm-bc,llvm-ir,obj,dep-info empty.rs
|
||||
$(RUSTC) --emit=link --crate-type=rlib,dylib,staticlib empty.rs
|
0
src/test/run-make/empty-file/empty.rs
Normal file
0
src/test/run-make/empty-file/empty.rs
Normal file
7
src/test/run-make/issue-22131/Makefile
Normal file
7
src/test/run-make/issue-22131/Makefile
Normal file
@ -0,0 +1,7 @@
|
||||
-include ../tools.mk
|
||||
|
||||
all: foo.rs
|
||||
$(RUSTC) --cfg 'feature="bar"' --crate-type lib foo.rs
|
||||
$(HOST_RPATH_ENV) $(RUSTDOC) --test --cfg 'feature="bar"' \
|
||||
-L $(TMPDIR) foo.rs |\
|
||||
grep --quiet 'test foo_0 ... ok'
|
17
src/test/run-make/issue-22131/foo.rs
Normal file
17
src/test/run-make/issue-22131/foo.rs
Normal file
@ -0,0 +1,17 @@
|
||||
// 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.
|
||||
|
||||
#![crate_name="foo"]
|
||||
|
||||
/// ```rust
|
||||
/// assert_eq!(foo::foo(), 1);
|
||||
/// ```
|
||||
#[cfg(feature = "bar")]
|
||||
pub fn foo() -> i32 { 1 }
|
@ -1,6 +1,7 @@
|
||||
-include ../tools.mk
|
||||
|
||||
ifndef IS_WINDOWS
|
||||
ifneq ($(UNAME),OpenBSD)
|
||||
all:
|
||||
$(RUSTC) -O --emit asm attr.rs
|
||||
! grep -q morestack $(TMPDIR)/attr.s
|
||||
@ -9,6 +10,10 @@ all:
|
||||
$(RUSTC) -O --emit asm -C no-stack-check flag.rs
|
||||
! grep -q morestack $(TMPDIR)/flag.s
|
||||
else
|
||||
# On OpenBSD, morestack isn't used as the segmented stacks are disabled
|
||||
all:
|
||||
endif
|
||||
else
|
||||
# On Windows we use __chkstk and it only appears in functions with large allocations,
|
||||
# so this test wouldn't be reliable.
|
||||
all:
|
||||
|
@ -10,6 +10,6 @@ OUT=$(TMPDIR)/lib.s
|
||||
all:
|
||||
$(RUSTC) lib.rs --emit=asm --crate-type=staticlib
|
||||
# just check for symbol declarations with the names we're expecting.
|
||||
grep 'str[0-9]\+:' $(OUT)
|
||||
grep 'binary[0-9]\+:' $(OUT)
|
||||
grep 'vtable[0-9]\+' $(OUT)
|
||||
grep 'str[0-9][0-9]*:' $(OUT)
|
||||
grep 'binary[0-9][0-9]*:' $(OUT)
|
||||
grep 'vtable[0-9][0-9]*' $(OUT)
|
||||
|
@ -1,11 +1,11 @@
|
||||
-include ../tools.mk
|
||||
all:
|
||||
$(RUSTC) foo.rs --target=my-awesome-platform.json --crate-type=lib --emit=asm
|
||||
grep --quiet --invert-match morestack < $(TMPDIR)/foo.s
|
||||
grep -q -v morestack < $(TMPDIR)/foo.s
|
||||
$(RUSTC) foo.rs --target=my-invalid-platform.json 2>&1 | grep --quiet "Error loading target specification"
|
||||
$(RUSTC) foo.rs --target=my-incomplete-platform.json 2>&1 | grep 'Field llvm-target'
|
||||
RUST_TARGET_PATH=. $(RUSTC) foo.rs --target=my-awesome-platform --crate-type=lib --emit=asm
|
||||
RUST_TARGET_PATH=. $(RUSTC) foo.rs --target=x86_64-unknown-linux-gnu --crate-type=lib --emit=asm
|
||||
# The built-in target *should* override the one we have here, and thus we
|
||||
# should have morestack
|
||||
grep --quiet morestack < $(TMPDIR)/foo.s
|
||||
grep -q morestack < $(TMPDIR)/foo.s
|
||||
|
@ -1,5 +1,6 @@
|
||||
-include ../tools.mk
|
||||
|
||||
ifneq ($(UNAME),OpenBSD)
|
||||
HOST := $(shell $(RUSTC) -vV | grep 'host:' | sed 's/host: //')
|
||||
ifeq ($(findstring i686,$(HOST)),i686)
|
||||
TARGET := $(subst i686,x86_64,$(HOST))
|
||||
@ -11,3 +12,7 @@ all:
|
||||
$(RUSTC) foo.rs -C extra-filename=-host
|
||||
$(RUSTC) bar.rs -C extra-filename=-targ --target $(TARGET)
|
||||
$(RUSTC) baz.rs --extern a=$(TMPDIR)/liba-targ.rlib --target $(TARGET)
|
||||
else
|
||||
# OpenBSD support only x86_64 architecture for now
|
||||
all:
|
||||
endif
|
||||
|
15
src/test/run-pass/cfg-attr-cfg.rs
Normal file
15
src/test/run-pass/cfg-attr-cfg.rs
Normal file
@ -0,0 +1,15 @@
|
||||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// main is conditionally compiled, but the conditional compilation
|
||||
// is conditional too!
|
||||
|
||||
#[cfg_attr(foo, cfg(bar))]
|
||||
fn main() { }
|
15
src/test/run-pass/cfg-attr-crate.rs
Normal file
15
src/test/run-pass/cfg-attr-crate.rs
Normal file
@ -0,0 +1,15 @@
|
||||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// https://github.com/rust-lang/rust/issues/21833#issuecomment-72353044
|
||||
|
||||
#![cfg_attr(not_used, no_std)]
|
||||
|
||||
fn main() { }
|
59
src/test/run-pass/infer-container-across-object-cast.rs
Normal file
59
src/test/run-pass/infer-container-across-object-cast.rs
Normal file
@ -0,0 +1,59 @@
|
||||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// Given `<expr> as Box<Trait>`, we should be able to infer that a
|
||||
// `Box<_>` is the expected type.
|
||||
|
||||
trait Foo { fn foo(&self) -> u32; }
|
||||
impl Foo for u32 { fn foo(&self) -> u32 { *self } }
|
||||
|
||||
// (another impl to ensure trait-matching cannot just choose from a singleton set)
|
||||
impl Foo for () { fn foo(&self) -> u32 { -176 } }
|
||||
|
||||
trait Boxed { fn make() -> Self; }
|
||||
impl Boxed for Box<u32> { fn make() -> Self { Box::new(7) } }
|
||||
|
||||
// (another impl to ensure trait-matching cannot just choose from a singleton set)
|
||||
impl Boxed for () { fn make() -> Self { () } }
|
||||
|
||||
fn boxed_foo() {
|
||||
let b7 = Boxed::make() as Box<Foo>;
|
||||
assert_eq!(b7.foo(), 7);
|
||||
}
|
||||
|
||||
trait Refed<'a,T> { fn make(&'a T) -> Self; }
|
||||
impl<'a> Refed<'a, u32> for &'a u32 { fn make(x: &'a u32) -> Self { x } }
|
||||
|
||||
// (another impl to ensure trait-matching cannot just choose from a singleton set)
|
||||
impl<'a,'b> Refed<'a, ()> for &'b () { fn make(_: &'a ()) -> Self { static U: () = (); &U } }
|
||||
|
||||
fn refed_foo() {
|
||||
let a = 8;
|
||||
let b7 = Refed::make(&a) as &Foo;
|
||||
assert_eq!(b7.foo(), 8);
|
||||
}
|
||||
|
||||
fn check_subtyping_works() {
|
||||
fn inner<'short, 'long:'short>(_s: &'short u32,
|
||||
l: &'long u32) -> &'short (Foo+'short) {
|
||||
Refed::make(l) as &Foo
|
||||
}
|
||||
|
||||
let a = 9;
|
||||
let b = 10;
|
||||
let r = inner(&b, &a);
|
||||
assert_eq!(r.foo(), 9);
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
boxed_foo();
|
||||
refed_foo();
|
||||
check_subtyping_works();
|
||||
}
|
22
src/test/run-pass/unboxed-closures-infer-upvar.rs
Normal file
22
src/test/run-pass/unboxed-closures-infer-upvar.rs
Normal file
@ -0,0 +1,22 @@
|
||||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// Test that the type variable in the type(`Vec<_>`) of a closed over
|
||||
// variable does not interfere with type inference.
|
||||
|
||||
fn f<F: FnMut()>(mut f: F) {
|
||||
f();
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut v: Vec<_> = vec![];
|
||||
f(|| v.push(0));
|
||||
assert_eq!(v, vec![0]);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user