mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-24 07:44:10 +00:00
auto merge of #7426 : thestinger/rust/zero-size-noncopyable, r=catamorphism
4885918 r=huonw
42a63fc r=thestinger
7ec5a08 r=catamorphism
fb1e5f1 r=thestinger
659cd55
r=cmr
This commit is contained in:
commit
811e045c60
@ -101,6 +101,7 @@ Version 0.7 (July 2013)
|
||||
dynamic borrowcheck failures for debugging.
|
||||
* rustdoc has a nicer stylesheet.
|
||||
* Various improvements to rustdoc.
|
||||
* Improvements to rustpkg (see the detailed release notes)
|
||||
|
||||
* Other
|
||||
* More and improved library documentation.
|
||||
|
@ -95,12 +95,22 @@ When building a package that is in a `git` repository,
|
||||
When building a package that is not under version control,
|
||||
or that has no tags, `rustpkg` assumes the intended version is 0.1.
|
||||
|
||||
# Dependencies
|
||||
|
||||
rustpkg infers dependencies from `extern mod` directives.
|
||||
Thus, there should be no need to pass a `-L` flag to rustpkg to tell it where to find a library.
|
||||
(In the future, it will also be possible to write an `extern mod` directive referring to a remote package.)
|
||||
|
||||
# Custom build scripts
|
||||
|
||||
A file called `pkg.rs` at the root level in a workspace is called a *package script*.
|
||||
If a package script exists, rustpkg executes it to build the package
|
||||
rather than inferring crates as described previously.
|
||||
|
||||
Inside `pkg.rs`, it's possible to call back into rustpkg to finish up the build.
|
||||
`rustpkg::api` contains functions to build, install, or clean libraries and executables
|
||||
in the way rustpkg normally would without custom build logic.
|
||||
|
||||
# Command reference
|
||||
|
||||
## build
|
||||
|
207
doc/tutorial-container.md
Normal file
207
doc/tutorial-container.md
Normal file
@ -0,0 +1,207 @@
|
||||
% Containers and iterators
|
||||
|
||||
# Containers
|
||||
|
||||
The container traits are defined in the `std::container` module.
|
||||
|
||||
## Unique and managed vectors
|
||||
|
||||
Vectors have `O(1)` indexing and removal from the end, along with `O(1)`
|
||||
amortized insertion. Vectors are the most common container in Rust, and are
|
||||
flexible enough to fit many use cases.
|
||||
|
||||
Vectors can also be sorted and used as efficient lookup tables with the
|
||||
`std::vec::bsearch` function, if all the elements are inserted at one time and
|
||||
deletions are unnecessary.
|
||||
|
||||
## Maps and sets
|
||||
|
||||
Maps are collections of unique keys with corresponding values, and sets are
|
||||
just unique keys without a corresponding value. The `Map` and `Set` traits in
|
||||
`std::container` define the basic interface.
|
||||
|
||||
The standard library provides three owned map/set types:
|
||||
|
||||
* `std::hashmap::HashMap` and `std::hashmap::HashSet`, requiring the keys to
|
||||
implement `Eq` and `Hash`
|
||||
* `std::trie::TrieMap` and `std::trie::TrieSet`, requiring the keys to be `uint`
|
||||
* `extra::treemap::TreeMap` and `extra::treemap::TreeSet`, requiring the keys
|
||||
to implement `TotalOrd`
|
||||
|
||||
These maps do not use managed pointers so they can be sent between tasks as
|
||||
long as the key and value types are sendable. Neither the key or value type has
|
||||
to be copyable.
|
||||
|
||||
The `TrieMap` and `TreeMap` maps are ordered, while `HashMap` uses an arbitrary
|
||||
order.
|
||||
|
||||
Each `HashMap` instance has a random 128-bit key to use with a keyed hash,
|
||||
making the order of a set of keys in a given hash table randomized. Rust
|
||||
provides a [SipHash](https://131002.net/siphash/) implementation for any type
|
||||
implementing the `IterBytes` trait.
|
||||
|
||||
## Double-ended queues
|
||||
|
||||
The `extra::deque` module implements a double-ended queue with `O(1)` amortized
|
||||
inserts and removals from both ends of the container. It also has `O(1)`
|
||||
indexing like a vector. The contained elements are not required to be copyable,
|
||||
and the queue will be sendable if the contained type is sendable.
|
||||
|
||||
## Priority queues
|
||||
|
||||
The `extra::priority_queue` module implements a queue ordered by a key. The
|
||||
contained elements are not required to be copyable, and the queue will be
|
||||
sendable if the contained type is sendable.
|
||||
|
||||
Insertions have `O(log n)` time complexity and checking or popping the largest
|
||||
element is `O(1)`. Converting a vector to a priority queue can be done
|
||||
in-place, and has `O(n)` complexity. A priority queue can also be converted to
|
||||
a sorted vector in-place, allowing it to be used for an `O(n log n)` in-place
|
||||
heapsort.
|
||||
|
||||
# Iterators
|
||||
|
||||
## Iteration protocol
|
||||
|
||||
The iteration protocol is defined by the `Iterator` trait in the
|
||||
`std::iterator` module. The minimal implementation of the trait is a `next`
|
||||
method, yielding the next element from an iterator object:
|
||||
|
||||
~~~
|
||||
/// An infinite stream of zeroes
|
||||
struct ZeroStream;
|
||||
|
||||
impl Iterator<int> for ZeroStream {
|
||||
fn next(&mut self) -> Option<int> {
|
||||
Some(0)
|
||||
}
|
||||
}
|
||||
~~~~
|
||||
|
||||
Reaching the end of the iterator is signalled by returning `None` instead of
|
||||
`Some(item)`:
|
||||
|
||||
~~~
|
||||
/// A stream of N zeroes
|
||||
struct ZeroStream {
|
||||
priv remaining: uint
|
||||
}
|
||||
|
||||
impl ZeroStream {
|
||||
fn new(n: uint) -> ZeroStream {
|
||||
ZeroStream { remaining: n }
|
||||
}
|
||||
}
|
||||
|
||||
impl Iterator<int> for ZeroStream {
|
||||
fn next(&mut self) -> Option<int> {
|
||||
if self.remaining == 0 {
|
||||
None
|
||||
} else {
|
||||
self.remaining -= 1;
|
||||
Some(0)
|
||||
}
|
||||
}
|
||||
}
|
||||
~~~
|
||||
|
||||
## Container iterators
|
||||
|
||||
Containers implement iteration over the contained elements by returning an
|
||||
iterator object. For example, vectors have four iterators available:
|
||||
|
||||
* `vector.iter()`, for immutable references to the elements
|
||||
* `vector.mut_iter()`, for mutable references to the elements
|
||||
* `vector.rev_iter()`, for immutable references to the elements in reverse order
|
||||
* `vector.mut_rev_iter()`, for mutable references to the elements in reverse order
|
||||
|
||||
### Freezing
|
||||
|
||||
Unlike most other languages with external iterators, Rust has no *iterator
|
||||
invalidation*. As long an iterator is still in scope, the compiler will prevent
|
||||
modification of the container through another handle.
|
||||
|
||||
~~~
|
||||
let mut xs = [1, 2, 3];
|
||||
{
|
||||
let _it = xs.iter();
|
||||
|
||||
// the vector is frozen for this scope, the compiler will statically
|
||||
// prevent modification
|
||||
}
|
||||
// the vector becomes unfrozen again at the end of the scope
|
||||
~~~
|
||||
|
||||
These semantics are due to most container iterators being implemented with `&`
|
||||
and `&mut`.
|
||||
|
||||
## Iterator adaptors
|
||||
|
||||
The `IteratorUtil` trait implements common algorithms as methods extending
|
||||
every `Iterator` implementation. For example, the `fold` method will accumulate
|
||||
the items yielded by an `Iterator` into a single value:
|
||||
|
||||
~~~
|
||||
let xs = [1, 9, 2, 3, 14, 12];
|
||||
let result = xs.iter().fold(0, |accumulator, item| accumulator - *item);
|
||||
assert_eq!(result, -41);
|
||||
~~~
|
||||
|
||||
Some adaptors return an adaptor object implementing the `Iterator` trait itself:
|
||||
|
||||
~~~
|
||||
let xs = [1, 9, 2, 3, 14, 12];
|
||||
let ys = [5, 2, 1, 8];
|
||||
let sum = xs.iter().chain_(ys.iter()).fold(0, |a, b| a + *b);
|
||||
assert_eq!(sum, 57);
|
||||
~~~
|
||||
|
||||
Note that some adaptors like the `chain_` method above use a trailing
|
||||
underscore to work around an issue with method resolve. The underscores will be
|
||||
dropped when they become unnecessary.
|
||||
|
||||
## For loops
|
||||
|
||||
The `for` loop syntax is currently in transition, and will switch from the old
|
||||
closure-based iteration protocol to iterator objects. For now, the `advance`
|
||||
adaptor is required as a compatibility shim to use iterators with for loops.
|
||||
|
||||
~~~
|
||||
let xs = [2, 3, 5, 7, 11, 13, 17];
|
||||
|
||||
// print out all the elements in the vector
|
||||
for xs.iter().advance |x| {
|
||||
println(x.to_str())
|
||||
}
|
||||
|
||||
// print out all but the first 3 elements in the vector
|
||||
for xs.iter().skip(3).advance |x| {
|
||||
println(x.to_str())
|
||||
}
|
||||
~~~
|
||||
|
||||
For loops are *often* used with a temporary iterator object, as above. They can
|
||||
also advance the state of an iterator in a mutable location:
|
||||
|
||||
~~~
|
||||
let xs = [1, 2, 3, 4, 5];
|
||||
let ys = ["foo", "bar", "baz", "foobar"];
|
||||
|
||||
// create an iterator yielding tuples of elements from both vectors
|
||||
let mut it = xs.iter().zip(ys.iter());
|
||||
|
||||
// print out the pairs of elements up to (&3, &"baz")
|
||||
for it.advance |(x, y)| {
|
||||
println(fmt!("%d %s", *x, *y));
|
||||
|
||||
if *x == 3 {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// yield and print the last pair from the iterator
|
||||
println(fmt!("last: %?", it.next()));
|
||||
|
||||
// the iterator is now fully consumed
|
||||
assert!(it.next().is_none());
|
||||
~~~
|
127
doc/tutorial.md
127
doc/tutorial.md
@ -1607,132 +1607,6 @@ do spawn {
|
||||
If you want to see the output of `debug!` statements, you will need to turn on `debug!` logging.
|
||||
To enable `debug!` logging, set the RUST_LOG environment variable to the name of your crate, which, for a file named `foo.rs`, will be `foo` (e.g., with bash, `export RUST_LOG=foo`).
|
||||
|
||||
## For loops
|
||||
|
||||
> ***Note:*** The closure-based protocol used `for` loop is on the way out. The `for` loop will
|
||||
> use iterator objects in the future instead.
|
||||
|
||||
The most common way to express iteration in Rust is with a `for`
|
||||
loop. Like `do`, `for` is a nice syntax for describing control flow
|
||||
with closures. Additionally, within a `for` loop, `break`, `loop`,
|
||||
and `return` work just as they do with `while` and `loop`.
|
||||
|
||||
Consider again our `each` function, this time improved to return
|
||||
immediately when the iteratee returns `false`:
|
||||
|
||||
~~~~
|
||||
fn each(v: &[int], op: &fn(v: &int) -> bool) -> bool {
|
||||
let mut n = 0;
|
||||
while n < v.len() {
|
||||
if !op(&v[n]) {
|
||||
return false;
|
||||
}
|
||||
n += 1;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
~~~~
|
||||
|
||||
And using this function to iterate over a vector:
|
||||
|
||||
~~~~
|
||||
# fn each(v: &[int], op: &fn(v: &int) -> bool) -> bool {
|
||||
# let mut n = 0;
|
||||
# while n < v.len() {
|
||||
# if !op(&v[n]) {
|
||||
# return false;
|
||||
# }
|
||||
# n += 1;
|
||||
# }
|
||||
# return true;
|
||||
# }
|
||||
each([2, 4, 8, 5, 16], |n| {
|
||||
if *n % 2 != 0 {
|
||||
println("found odd number!");
|
||||
false
|
||||
} else { true }
|
||||
});
|
||||
~~~~
|
||||
|
||||
With `for`, functions like `each` can be treated more
|
||||
like built-in looping structures. When calling `each`
|
||||
in a `for` loop, instead of returning `false` to break
|
||||
out of the loop, you just write `break`. To skip ahead
|
||||
to the next iteration, write `loop`.
|
||||
|
||||
~~~~
|
||||
# fn each(v: &[int], op: &fn(v: &int) -> bool) -> bool {
|
||||
# let mut n = 0;
|
||||
# while n < v.len() {
|
||||
# if !op(&v[n]) {
|
||||
# return false;
|
||||
# }
|
||||
# n += 1;
|
||||
# }
|
||||
# return true;
|
||||
# }
|
||||
for each([2, 4, 8, 5, 16]) |n| {
|
||||
if *n % 2 != 0 {
|
||||
println("found odd number!");
|
||||
break;
|
||||
}
|
||||
}
|
||||
~~~~
|
||||
|
||||
As an added bonus, you can use the `return` keyword, which is not
|
||||
normally allowed in closures, in a block that appears as the body of a
|
||||
`for` loop: the meaning of `return` in such a block is to return from
|
||||
the enclosing function, not just the loop body.
|
||||
|
||||
~~~~
|
||||
# fn each(v: &[int], op: &fn(v: &int) -> bool) -> bool {
|
||||
# let mut n = 0;
|
||||
# while n < v.len() {
|
||||
# if !op(&v[n]) {
|
||||
# return false;
|
||||
# }
|
||||
# n += 1;
|
||||
# }
|
||||
# return true;
|
||||
# }
|
||||
fn contains(v: &[int], elt: int) -> bool {
|
||||
for each(v) |x| {
|
||||
if (*x == elt) { return true; }
|
||||
}
|
||||
false
|
||||
}
|
||||
~~~~
|
||||
|
||||
Notice that, because `each` passes each value by borrowed pointer,
|
||||
the iteratee needs to dereference it before using it.
|
||||
In these situations it can be convenient to lean on Rust's
|
||||
argument patterns to bind `x` to the actual value, not the pointer.
|
||||
|
||||
~~~~
|
||||
# fn each(v: &[int], op: &fn(v: &int) -> bool) -> bool {
|
||||
# let mut n = 0;
|
||||
# while n < v.len() {
|
||||
# if !op(&v[n]) {
|
||||
# return false;
|
||||
# }
|
||||
# n += 1;
|
||||
# }
|
||||
# return true;
|
||||
# }
|
||||
# fn contains(v: &[int], elt: int) -> bool {
|
||||
for each(v) |&x| {
|
||||
if (x == elt) { return true; }
|
||||
}
|
||||
# false
|
||||
# }
|
||||
~~~~
|
||||
|
||||
`for` syntax only works with stack closures.
|
||||
|
||||
> ***Note:*** This is, essentially, a special loop protocol:
|
||||
> the keywords `break`, `loop`, and `return` work, in varying degree,
|
||||
> with `while`, `loop`, `do`, and `for` constructs.
|
||||
|
||||
# Methods
|
||||
|
||||
Methods are like functions except that they always begin with a special argument,
|
||||
@ -2653,6 +2527,7 @@ tutorials on individual topics.
|
||||
* [Tasks and communication][tasks]
|
||||
* [Macros][macros]
|
||||
* [The foreign function interface][ffi]
|
||||
* [Containers and iterators](tutorial-container.html)
|
||||
|
||||
There is further documentation on the [wiki].
|
||||
|
||||
|
69
man/rustc.1
69
man/rustc.1
@ -1,4 +1,4 @@
|
||||
.TH RUSTC "1" "February 2013" "rustc 0.6" "User Commands"
|
||||
.TH RUSTC "1" "July 2013" "rustc 0.7" "User Commands"
|
||||
.SH NAME
|
||||
rustc \- rust compiler
|
||||
.SH SYNOPSIS
|
||||
@ -33,6 +33,12 @@ Add a directory to the library search path
|
||||
\fB\-\-lib\fR
|
||||
Compile a library crate
|
||||
.TP
|
||||
\fB\-\-linker\fR LINKER
|
||||
Program to use for linking instead of the default
|
||||
.TP
|
||||
\fB\-\-link-args\fR FLAGS
|
||||
A space-separated list of flags passed to the linker
|
||||
.TP
|
||||
\fB\-\-ls\fR
|
||||
List the symbols defined by a library crate
|
||||
.TP
|
||||
@ -48,6 +54,11 @@ Write output to <filename>
|
||||
\fB\-\-opt\-level\fR LEVEL
|
||||
Optimize with possible levels 0-3
|
||||
.TP
|
||||
\fB\-\-passes\fR NAMES
|
||||
Comma- or space-separated list of optimization passes. Overrides
|
||||
the default passes for the optimization level. A value of 'list'
|
||||
will list the available passes.
|
||||
.TP
|
||||
\fB\-\-out\-dir\fR DIR
|
||||
Write output to compiler-chosen filename in <dir>
|
||||
.TP
|
||||
@ -77,6 +88,12 @@ Target triple cpu-manufacturer-kernel[-os] to compile for (see
|
||||
http://sources.redhat.com/autobook/autobook/autobook_17.html
|
||||
for detail)
|
||||
.TP
|
||||
\fB\-\-target-feature\fR TRIPLE
|
||||
Target-specific attributes (see llc -mattr=help for detail)
|
||||
.TP
|
||||
\fB\-\-android-cross-path\fR PATH
|
||||
The path to the Android NDK
|
||||
.TP
|
||||
\fB\-W\fR help
|
||||
Print 'lint' options and default settings
|
||||
.TP
|
||||
@ -94,56 +111,6 @@ Set lint forbidden
|
||||
.TP
|
||||
\fB\-Z\fR FLAG
|
||||
Set internal debugging options. Use "-Z help" to print available options.
|
||||
|
||||
Available debug flags are:
|
||||
.RS
|
||||
.IP \[bu]
|
||||
\fBverbose\fR - in general, enable more debug printouts
|
||||
.IP \[bu]
|
||||
\fBtime\-passes\fR - measure time of each rustc pass
|
||||
.IP \[bu]
|
||||
\fBcount\-llvm\-insns\fR - count where LLVM instrs originate
|
||||
.IP \[bu]
|
||||
\fBtime\-llvm\-passes\fR - measure time of each LLVM pass
|
||||
.IP \[bu]
|
||||
\fBtrans\-stats\fR - gather trans statistics
|
||||
.IP \[bu]
|
||||
\fBno\-asm\-comments\fR - omit comments when using \fI\-S\fR
|
||||
.IP \[bu]
|
||||
\fBno\-verify\fR - skip LLVM verification
|
||||
.IP \[bu]
|
||||
\fBtrace\fR - emit trace logs
|
||||
.IP \[bu]
|
||||
\fBcoherence\fR - perform coherence checking
|
||||
.IP \[bu]
|
||||
\fBborrowck\-stats\fR - gather borrowck statistics
|
||||
.IP \[bu]
|
||||
\fBborrowck\-note\-pure\fR - note where purity is req'd
|
||||
.IP \[bu]
|
||||
\fBborrowck\-note\-loan\fR - note where loans are req'd
|
||||
.IP \[bu]
|
||||
\fBno\-landing\-pads\fR - omit landing pads for unwinding
|
||||
.IP \[bu]
|
||||
\fBdebug\-llvm\fR - enable debug output from LLVM
|
||||
.IP \[bu]
|
||||
\fBcount\-type\-sizes\fR - count the sizes of aggregate types
|
||||
.IP \[bu]
|
||||
\fBmeta\-stats\fR - gather metadata statistics
|
||||
.IP \[bu]
|
||||
\fBno\-opt\fR - do not optimize, even if \fI\-O\fR is passed
|
||||
.IP \[bu]
|
||||
\fBno\-monomorphic\-collapse\fR - do not collapse template instantiations
|
||||
.IP \[bu]
|
||||
\fBgc\fR - Garbage collect shared data (experimental)
|
||||
.IP \[bu]
|
||||
\fBjit\fR - Execute using JIT (experimental)
|
||||
.IP \[bu]
|
||||
\fBextra\-debug\-info\fR - Extra debugging info (experimental)
|
||||
.IP \[bu]
|
||||
\fBdebug\-info\fR - Produce debug info (experimental)
|
||||
.IP \[bu]
|
||||
\fBstatic\fR - Use or produce static libraries or binaries (experimental)
|
||||
.RE
|
||||
.TP
|
||||
\fB\-v\fR, \fB\-\-version\fR
|
||||
Print version info and exit
|
||||
|
10
mk/docs.mk
10
mk/docs.mk
@ -99,6 +99,16 @@ doc/tutorial-macros.html: tutorial-macros.md doc/version_info.html \
|
||||
--include-before-body=doc/version_info.html \
|
||||
--output=$@
|
||||
|
||||
DOCS += doc/tutorial-container.html
|
||||
doc/tutorial-container.html: tutorial-container.md doc/version_info.html doc/rust.css
|
||||
@$(call E, pandoc: $@)
|
||||
$(Q)$(CFG_NODE) $(S)doc/prep.js --highlight $< | \
|
||||
$(CFG_PANDOC) --standalone --toc \
|
||||
--section-divs --number-sections \
|
||||
--from=markdown --to=html --css=rust.css \
|
||||
--include-before-body=doc/version_info.html \
|
||||
--output=$@
|
||||
|
||||
DOCS += doc/tutorial-ffi.html
|
||||
doc/tutorial-ffi.html: tutorial-ffi.md doc/version_info.html doc/rust.css
|
||||
@$(call E, pandoc: $@)
|
||||
|
@ -82,8 +82,14 @@ pub mod reader {
|
||||
use core::cast::transmute;
|
||||
use core::int;
|
||||
use core::io;
|
||||
use core::ptr::offset;
|
||||
use core::str;
|
||||
|
||||
#[cfg(target_arch = "x86")]
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
use core::ptr::offset;
|
||||
|
||||
#[cfg(target_arch = "x86")]
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
use core::unstable::intrinsics::bswap32;
|
||||
|
||||
// ebml reading
|
||||
|
@ -36,6 +36,7 @@ struct RcBox<T> {
|
||||
|
||||
/// Immutable reference counted pointer type
|
||||
#[non_owned]
|
||||
#[unsafe_no_drop_flag]
|
||||
pub struct Rc<T> {
|
||||
priv ptr: *mut RcBox<T>,
|
||||
}
|
||||
@ -168,6 +169,7 @@ struct RcMutBox<T> {
|
||||
/// Mutable reference counted pointer type
|
||||
#[non_owned]
|
||||
#[mutable]
|
||||
#[unsafe_no_drop_flag]
|
||||
pub struct RcMut<T> {
|
||||
priv ptr: *mut RcMutBox<T>,
|
||||
}
|
||||
|
@ -3904,7 +3904,7 @@ impl DtorKind {
|
||||
pub fn ty_dtor(cx: ctxt, struct_id: def_id) -> DtorKind {
|
||||
match cx.destructor_for_type.find(&struct_id) {
|
||||
Some(&method_def_id) => {
|
||||
let flag = !has_attr(cx, struct_id, "no_drop_flag");
|
||||
let flag = !has_attr(cx, struct_id, "unsafe_no_drop_flag");
|
||||
|
||||
TraitDtor(method_def_id, flag)
|
||||
}
|
||||
|
@ -349,7 +349,6 @@ pub mod types {
|
||||
use libc::types::os::arch::c95::{c_uchar, c_uint, c_ulong, time_t};
|
||||
use libc::types::os::arch::c99::{c_longlong, c_ulonglong};
|
||||
use libc::types::os::arch::posix88::{uid_t, gid_t, ino_t};
|
||||
use libc::types::os::arch::posix88::{uid_t};
|
||||
|
||||
pub type nlink_t = u16;
|
||||
pub type blksize_t = u32;
|
||||
|
@ -447,7 +447,7 @@ fn test_option_dance() {
|
||||
}
|
||||
#[test] #[should_fail] #[ignore(cfg(windows))]
|
||||
fn test_option_too_much_dance() {
|
||||
let mut y = Some(util::NonCopyable::new());
|
||||
let mut y = Some(util::NonCopyable);
|
||||
let _y2 = y.swap_unwrap();
|
||||
let _y3 = y.swap_unwrap();
|
||||
}
|
||||
|
@ -62,7 +62,7 @@ pub struct AtomicPtr<T> {
|
||||
/**
|
||||
* An owned atomic pointer. Ensures that only a single reference to the data is held at any time.
|
||||
*/
|
||||
#[no_drop_flag]
|
||||
#[unsafe_no_drop_flag]
|
||||
pub struct AtomicOption<T> {
|
||||
priv p: *mut c_void
|
||||
}
|
||||
|
@ -75,18 +75,14 @@ pub fn replace<T>(dest: &mut T, mut src: T) -> T {
|
||||
}
|
||||
|
||||
/// A non-copyable dummy type.
|
||||
#[deriving(Eq, TotalEq, Ord, TotalOrd)]
|
||||
#[unsafe_no_drop_flag]
|
||||
pub struct NonCopyable;
|
||||
|
||||
impl NonCopyable {
|
||||
/// Creates a dummy non-copyable structure and returns it for use.
|
||||
pub fn new() -> NonCopyable { NonCopyable }
|
||||
}
|
||||
|
||||
impl Drop for NonCopyable {
|
||||
fn drop(&self) { }
|
||||
}
|
||||
|
||||
|
||||
/// A type with no inhabitants
|
||||
pub enum Void { }
|
||||
|
||||
@ -130,39 +126,73 @@ pub fn unreachable() -> ! {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use option::{None, Some};
|
||||
use util::{Void, NonCopyable, id, replace, swap};
|
||||
use either::{Either, Left, Right};
|
||||
use sys::size_of;
|
||||
use kinds::Drop;
|
||||
|
||||
#[test]
|
||||
pub fn identity_crisis() {
|
||||
fn identity_crisis() {
|
||||
// Writing a test for the identity function. How did it come to this?
|
||||
let x = ~[(5, false)];
|
||||
//FIXME #3387 assert!(x.eq(id(copy x)));
|
||||
let y = copy x;
|
||||
assert!(x.eq(&id(y)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_swap() {
|
||||
fn test_swap() {
|
||||
let mut x = 31337;
|
||||
let mut y = 42;
|
||||
swap(&mut x, &mut y);
|
||||
assert_eq!(x, 42);
|
||||
assert_eq!(y, 31337);
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_replace() {
|
||||
let mut x = Some(NonCopyable::new());
|
||||
fn test_replace() {
|
||||
let mut x = Some(NonCopyable);
|
||||
let y = replace(&mut x, None);
|
||||
assert!(x.is_none());
|
||||
assert!(y.is_some());
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_uninhabited() {
|
||||
fn test_uninhabited() {
|
||||
let could_only_be_coin : Either <Void, ()> = Right (());
|
||||
match could_only_be_coin {
|
||||
Right (coin) => coin,
|
||||
Left (is_void) => is_void.uninhabited ()
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_noncopyable() {
|
||||
assert_eq!(size_of::<NonCopyable>(), 0);
|
||||
|
||||
// verify that `#[unsafe_no_drop_flag]` works as intended on a zero-size struct
|
||||
|
||||
// NOTE: uncomment after snapshot, will not parse yet
|
||||
//static mut did_run: bool = false;
|
||||
|
||||
struct Foo { five: int }
|
||||
|
||||
impl Drop for Foo {
|
||||
fn drop(&self) {
|
||||
assert_eq!(self.five, 5);
|
||||
// NOTE: uncomment after snapshot, will not parse yet
|
||||
//unsafe {
|
||||
//did_run = true;
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
let _a = (NonCopyable, Foo { five: 5 }, NonCopyable);
|
||||
}
|
||||
|
||||
// NOTE: uncomment after snapshot, will not parse yet
|
||||
//unsafe { assert_eq!(did_run, true); }
|
||||
}
|
||||
}
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
use std::sys::size_of;
|
||||
|
||||
#[no_drop_flag]
|
||||
#[unsafe_no_drop_flag]
|
||||
struct Test<T> {
|
||||
a: T
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user