Merge tag 'upstream-tar/1.4.0+dfsg1'

Upstream version 1.4.0+dfsg1
This commit is contained in:
Sylvestre Ledru 2015-10-30 09:44:45 +01:00
commit 69c36f97de
1270 changed files with 79085 additions and 47921 deletions

View File

@ -10,6 +10,7 @@ links to the major sections:
* [Writing Documentation](#writing-documentation)
* [Issue Triage](#issue-triage)
* [Out-of-tree Contributions](#out-of-tree-contributions)
* [Helpful Links and Information](#helpful-links-and-information)
If you have questions, please make a post on [internals.rust-lang.org][internals] or
hop on [#rust-internals][pound-rust-internals].
@ -17,8 +18,8 @@ hop on [#rust-internals][pound-rust-internals].
As a reminder, all contributors are expected to follow our [Code of Conduct][coc].
[pound-rust-internals]: http://chat.mibbit.com/?server=irc.mozilla.org&channel=%23rust-internals
[internals]: http://internals.rust-lang.org
[coc]: http://www.rust-lang.org/conduct.html
[internals]: https://internals.rust-lang.org
[coc]: https://www.rust-lang.org/conduct.html
## Feature Requests
@ -207,6 +208,31 @@ it to [Crates.io](http://crates.io). Easier said than done, but very, very
valuable!
[pound-rust]: http://chat.mibbit.com/?server=irc.mozilla.org&channel=%23rust
[users]: http://users.rust-lang.org/
[users]: https://users.rust-lang.org/
[so]: http://stackoverflow.com/questions/tagged/rust
[community-library]: https://github.com/rust-lang/rfcs/labels/A-community-library
## Helpful Links and Information
For people new to Rust, and just starting to contribute, or even for
more seasoned developers, some useful places to look for information
are:
* The [Rust Internals forum][rif], a place to ask questions and
discuss Rust's internals
* The [generated documentation for rust's compiler][gdfrustc]
* The [rust referance][rr], even though it doesn't specifically talk about Rust's internals, its a great reasource nontheless
* Although out of date, [Tom Lee's great blog article][tlgba] is very helpful
* [rustaceans.org][ro] is helpful, but mostly dedicated to IRC
* The [Rust Compiler Testing Docs][rctd]
* For @bors, [this cheetsheat][cheetsheat] is helpful (Remember to replace `@homu` with `@bors` in the commands that you use.)
* **Google**!
* Don't be afraid to ask! The Rust community is friendly and helpful.
[gdfrustc]: http://manishearth.github.io/rust-internals-docs/rustc/
[rif]: http://internals.rust-lang.org
[rr]: https://doc.rust-lang.org/book/README.html
[tlgba]: http://tomlee.co/2014/04/03/a-more-detailed-tour-of-the-rust-compiler/
[ro]: http://www.rustaceans.org/
[rctd]: ./COMPILER_TESTS.md
[cheetsheat]: http://buildbot.rust-lang.org/homu/

View File

@ -22,104 +22,6 @@ The Rust Project includes packages written by third parties.
The following third party packages are included, and carry
their own copyright notices and license terms:
* Two header files that are part of the Valgrind
package. These files are found at src/rt/valgrind/valgrind.h and
src/rt/valgrind/memcheck.h, within this distribution. These files
are redistributed under the following terms, as noted in
them:
for src/rt/valgrind/valgrind.h:
This file is part of Valgrind, a dynamic binary
instrumentation framework.
Copyright (C) 2000-2010 Julian Seward. All rights
reserved.
Redistribution and use in source and binary forms, with
or without modification, are permitted provided that the
following conditions are met:
1. Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
2. The origin of this software must not be
misrepresented; you must not claim that you wrote the
original software. If you use this software in a
product, an acknowledgment in the product
documentation would be appreciated but is not
required.
3. Altered source versions must be plainly marked as
such, and must not be misrepresented as being the
original software.
4. The name of the author may not be used to endorse or
promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
for src/rt/valgrind/memcheck.h:
This file is part of MemCheck, a heavyweight Valgrind
tool for detecting memory errors.
Copyright (C) 2000-2010 Julian Seward. All rights
reserved.
Redistribution and use in source and binary forms, with
or without modification, are permitted provided that the
following conditions are met:
1. Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
2. The origin of this software must not be
misrepresented; you must not claim that you wrote the
original software. If you use this software in a
product, an acknowledgment in the product
documentation would be appreciated but is not
required.
3. Altered source versions must be plainly marked as
such, and must not be misrepresented as being the
original software.
4. The name of the author may not be used to endorse or
promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
* The src/rt/miniz.c file, carrying an implementation of
RFC1950/RFC1951 DEFLATE, by Rich Geldreich
<richgel99@gmail.com>. All uses of this file are

View File

@ -13,8 +13,8 @@ as standard libraries, tools and documentation for Rust.
Read ["Installing Rust"] from [The Book].
["Installing Rust"]: http://doc.rust-lang.org/book/installing-rust.html
[The Book]: http://doc.rust-lang.org/book/index.html
["Installing Rust"]: https://doc.rust-lang.org/book/installing-rust.html
[The Book]: https://doc.rust-lang.org/book/index.html
## Building from Source
@ -65,6 +65,9 @@ Read ["Installing Rust"] from [The Book].
tools.
```sh
# Update package mirrors (may be needed if you have a fresh install of MSYS2)
$ pacman -Sy pacman-mirrors
# Choose one based on platform:
$ pacman -S mingw-w64-i686-toolchain
$ pacman -S mingw-w64-x86_64-toolchain
@ -82,6 +85,28 @@ Read ["Installing Rust"] from [The Book].
$ make && make install
```
## Building Documentation
If youd like to build the documentation, its almost the same:
```sh
./configure
$ make docs
```
Building the documentation requires building the compiler, so the above
details will apply. Once you have the compiler built, you can
```sh
$ make docs NO_REBUILD=1
```
To make sure you dont re-build the compiler because you made a change
to some documentation.
The generated documentation will appear in a top-level `doc` directory,
created by the `make` rule.
## Notes
Since the Rust compiler is written in Rust, it must be built by a
@ -117,7 +142,7 @@ The Rust community congregates in a few places:
[Stack Overflow]: http://stackoverflow.com/questions/tagged/rust
[/r/rust]: http://reddit.com/r/rust
[users.rust-lang.org]: http://users.rust-lang.org/
[users.rust-lang.org]: https://users.rust-lang.org/
## Contributing

View File

@ -1,4 +1,173 @@
Version 1.3.0 (September 2015)
Version 1.4.0 (October 2015)
============================
* ~1200 changes, numerous bugfixes
Highlights
----------
* Windows builds targeting the 64-bit MSVC ABI and linker (instead of
GNU) are now supported and recommended for use.
Breaking Changes
----------------
* [Several changes have been made to fix type soundness and improve
the behavior of associated types][sound]. See [RFC 1214]. Although
we have mostly introduced these changes as warnings this release, to
become errors next release, there are still some scenarios that will
see immediate breakage.
* [The `str::lines` and `BufRead::lines` iterators treat `\r\n` as
line breaks in addition to `\n`][crlf].
* [Loans of `'static` lifetime extend to the end of a function][stat].
Language
--------
* `use` statements that import multiple items [can now rename
them][i], as in `use foo::{bar as kitten, baz as puppy}`.
* [Binops work correctly on fat pointers][binfat].
* `pub extern crate`, which does not behave as expected, [issues a
warning][pec] until a better solution is found.
Libraries
---------
* [Many APIs were stabilized][stab]: `<Box<str>>::into_string`,
[`Arc::downgrade`], [`Arc::get_mut`], [`Arc::make_mut`],
[`Arc::try_unwrap`], [`Box::from_raw`], [`Box::into_raw`], [`CStr::to_str`],
[`CStr::to_string_lossy`], [`CString::from_raw`], [`CString::into_raw`],
[`IntoRawFd::into_raw_fd`], [`IntoRawFd`],
`IntoRawHandle::into_raw_handle`, `IntoRawHandle`,
`IntoRawSocket::into_raw_socket`, `IntoRawSocket`, [`Rc::downgrade`],
[`Rc::get_mut`], [`Rc::make_mut`], [`Rc::try_unwrap`], [`Result::expect`],
[`String::into_boxed_str`], [`TcpStream::read_timeout`],
[`TcpStream::set_read_timeout`], [`TcpStream::set_write_timeout`],
[`TcpStream::write_timeout`], [`UdpSocket::read_timeout`],
[`UdpSocket::set_read_timeout`], [`UdpSocket::set_write_timeout`],
[`UdpSocket::write_timeout`], `Vec::append`, `Vec::split_off`,
[`VecDeque::append`], [`VecDeque::retain`], [`VecDeque::split_off`],
[`rc::Weak::upgrade`], [`rc::Weak`], [`slice::Iter::as_slice`],
[`slice::IterMut::into_slice`], [`str::CharIndices::as_str`],
[`str::Chars::as_str`], [`str::split_at_mut`], [`str::split_at`],
[`sync::Weak::upgrade`], [`sync::Weak`], [`thread::park_timeout`],
[`thread::sleep`].
* [Some APIs were deprecated][dep]: `BTreeMap::with_b`,
`BTreeSet::with_b`, `Option::as_mut_slice`, `Option::as_slice`,
`Result::as_mut_slice`, `Result::as_slice`, `f32::from_str_radix`,
`f64::from_str_radix`.
* [Reverse-searching strings is faster with the 'two-way'
algorithm][s].
* [`std::io::copy` allows `?Sized` arguments][cc].
* The `Windows`, `Chunks`, and `ChunksMut` iterators over slices all
[override `count`, `nth` and `last` with an O(1)
implementation][it].
* [`Default` is implemented for arrays up to `[T; 32]`][d].
* [`IntoRawFd` has been added to the Unix-specific prelude,
`IntoRawSocket` and `IntoRawHandle` to the Windows-specific
prelude][pr].
* [`Extend<String>` and `FromIterator<String` are both implemented for
`String`][es].
* [`IntoIterator` is implemented for `Option<&T>` and
`Result<&T>`][into].
* [`HashMap` and `HashSet` implement `Extend<&T>` where `T:
Copy`][ext] as part of [RFC 839].
* [`BinaryHeap` implements `Debug`][bh2].
* [`Borrow` and `BorrowMut` are implemented for fixed-size
arrays][bm].
* [`extern fn`s of with the "Rust" and "C" ABIs implement common
traits including `Eq`, `Ord`, `Debug`, `Hash`][fp].
* [String comparison is faster][faststr].
* `&mut T` where `T: Write` [also implements `Write`][mutw].
* [A stable regression in `VecDec::push_back` that caused panics for
zero-sized types was fixed][vd].
* [Function pointers implement traits for up to 12 parameters][fp2].
Miscellaneous
-------------
* The compiler [no longer uses the 'morestack' feature to prevent
stack overflow][mm]. Instead it uses guard pages and stack
probes (though stack probes are not yet implemented on any platform
but Windows).
* [The compiler matches traits faster when projections are involved][p].
* The 'improper_ctypes' lint [no longer warns about use of `isize` and
`usize`][ffi].
* [Cargo now displays useful information about what its doing during
`cargo update`][cu].
[`Arc::downgrade`]: http://doc.rust-lang.org/nightly/alloc/arc/struct.Arc.html#method.downgrade
[`Arc::make_mut`]: http://doc.rust-lang.org/nightly/alloc/arc/struct.Arc.html#method.make_mut
[`Arc::get_mut`]: http://doc.rust-lang.org/nightly/alloc/arc/struct.Arc.html#method.get_mut
[`Arc::try_unwrap`]: http://doc.rust-lang.org/nightly/alloc/arc/struct.Arc.html#method.try_unwrap
[`Box::from_raw`]: http://doc.rust-lang.org/nightly/alloc/boxed/struct.Box.html#method.from_raw
[`Box::into_raw`]: http://doc.rust-lang.org/nightly/alloc/boxed/struct.Box.html#method.into_raw
[`CStr::to_str`]: http://doc.rust-lang.org/nightly/std/ffi/struct.CStr.html#method.to_str
[`CStr::to_string_lossy`]: http://doc.rust-lang.org/nightly/std/ffi/struct.CStr.html#method.to_string_lossy
[`CString::from_raw`]: http://doc.rust-lang.org/nightly/std/ffi/struct.CString.html#method.from_raw
[`CString::into_raw`]: http://doc.rust-lang.org/nightly/std/ffi/struct.CString.html#method.into_raw
[`IntoRawFd::into_raw_fd`]: http://doc.rust-lang.org/nightly/std/os/unix/io/trait.IntoRawFd.html#tymethod.into_raw_fd
[`IntoRawFd`]: http://doc.rust-lang.org/nightly/std/os/unix/io/trait.IntoRawFd.html
[`Rc::downgrade`]: http://doc.rust-lang.org/nightly/alloc/rc/struct.Rc.html#method.downgrade
[`Rc::get_mut`]: http://doc.rust-lang.org/nightly/alloc/rc/struct.Rc.html#method.get_mut
[`Rc::make_mut`]: http://doc.rust-lang.org/nightly/alloc/rc/struct.Rc.html#method.make_mut
[`Rc::try_unwrap`]: http://doc.rust-lang.org/nightly/alloc/rc/struct.Rc.html#method.try_unwrap
[`Result::expect`]: http://doc.rust-lang.org/nightly/core/result/enum.Result.html#method.expect
[`String::into_boxed_str`]: http://doc.rust-lang.org/nightly/collections/string/struct.String.html#method.into_boxed_str
[`TcpStream::read_timeout`]: http://doc.rust-lang.org/nightly/std/net/struct.TcpStream.html#method.read_timeout
[`TcpStream::set_read_timeout`]: http://doc.rust-lang.org/nightly/std/net/struct.TcpStream.html#method.set_read_timeout
[`TcpStream::write_timeout`]: http://doc.rust-lang.org/nightly/std/net/struct.TcpStream.html#method.write_timeout
[`TcpStream::set_write_timeout`]: http://doc.rust-lang.org/nightly/std/net/struct.TcpStream.html#method.set_write_timeout
[`UdpSocket::read_timeout`]: http://doc.rust-lang.org/nightly/std/net/struct.TcpStream.html#method.read_timeout
[`UdpSocket::set_read_timeout`]: http://doc.rust-lang.org/nightly/std/net/struct.TcpStream.html#method.set_read_timeout
[`UdpSocket::write_timeout`]: http://doc.rust-lang.org/nightly/std/net/struct.TcpStream.html#method.write_timeout
[`UdpSocket::set_write_timeout`]: http://doc.rust-lang.org/nightly/std/net/struct.TcpStream.html#method.set_write_timeout
[`VecDeque::append`]: http://doc.rust-lang.org/nightly/std/collections/struct.VecDeque.html#method.append
[`VecDeque::retain`]: http://doc.rust-lang.org/nightly/std/collections/struct.VecDeque.html#method.retain
[`VecDeque::split_off`]: http://doc.rust-lang.org/nightly/std/collections/struct.VecDeque.html#method.split_off
[`rc::Weak::upgrade`]: http://doc.rust-lang.org/nightly/std/rc/struct.Weak.html#method.upgrade
[`rc::Weak`]: http://doc.rust-lang.org/nightly/std/rc/struct.Weak.html
[`slice::Iter::as_slice`]: http://doc.rust-lang.org/nightly/std/slice/struct.Iter.html#method.as_slice
[`slice::IterMut::into_slice`]: http://doc.rust-lang.org/nightly/std/slice/struct.IterMut.html#method.into_slice
[`str::CharIndices::as_str`]: http://doc.rust-lang.org/nightly/std/str/struct.CharIndices.html#method.as_str
[`str::Chars::as_str`]: http://doc.rust-lang.org/nightly/std/str/struct.Chars.html#method.as_str
[`str::split_at_mut`]: http://doc.rust-lang.org/nightly/std/primitive.str.html#method.split_at_mut
[`str::split_at`]: http://doc.rust-lang.org/nightly/std/primitive.str.html#method.split_at
[`sync::Weak::upgrade`]: http://doc.rust-lang.org/nightly/std/sync/struct.Weak.html#method.upgrade
[`sync::Weak`]: http://doc.rust-lang.org/nightly/std/sync/struct.Weak.html
[`thread::park_timeout`]: http://doc.rust-lang.org/nightly/std/thread/fn.park_timeout.html
[`thread::sleep`]: http://doc.rust-lang.org/nightly/std/thread/fn.sleep.html
[bh2]: https://github.com/rust-lang/rust/pull/28156
[binfat]: https://github.com/rust-lang/rust/pull/28270
[bm]: https://github.com/rust-lang/rust/pull/28197
[cc]: https://github.com/rust-lang/rust/pull/27531
[crlf]: https://github.com/rust-lang/rust/pull/28034
[cu]: https://github.com/rust-lang/cargo/pull/1931
[d]: https://github.com/rust-lang/rust/pull/27825
[dep]: https://github.com/rust-lang/rust/pull/28339
[es]: https://github.com/rust-lang/rust/pull/27956
[ext]: https://github.com/rust-lang/rust/pull/28094
[faststr]: https://github.com/rust-lang/rust/pull/28338
[ffi]: https://github.com/rust-lang/rust/pull/28779
[fp]: https://github.com/rust-lang/rust/pull/28268
[fp2]: https://github.com/rust-lang/rust/pull/28560
[i]: https://github.com/rust-lang/rust/pull/27451
[into]: https://github.com/rust-lang/rust/pull/28039
[it]: https://github.com/rust-lang/rust/pull/27652
[mm]: https://github.com/rust-lang/rust/pull/27338
[mutw]: https://github.com/rust-lang/rust/pull/28368
[sound]: https://github.com/rust-lang/rust/pull/27641
[p]: https://github.com/rust-lang/rust/pull/27866
[pec]: https://github.com/rust-lang/rust/pull/28486
[pr]: https://github.com/rust-lang/rust/pull/27896
[RFC 839]: https://github.com/rust-lang/rfcs/blob/master/text/0839-embrace-extend-extinguish.md
[RFC 1214]: https://github.com/rust-lang/rfcs/blob/master/text/1214-projections-lifetimes-and-wf.md
[s]: https://github.com/rust-lang/rust/pull/27474
[stab]: https://github.com/rust-lang/rust/pull/28339
[stat]: https://github.com/rust-lang/rust/pull/28321
[vd]: https://github.com/rust-lang/rust/pull/28494
Version 1.3.0 (2015-09-17)
==============================
* ~900 changes, numerous bugfixes
@ -142,7 +311,7 @@ Misc
[`Error`]: http://doc.rust-lang.org/nightly/std/error/trait.Error.html
[`File`]: http://doc.rust-lang.org/nightly/std/fs/struct.File.html
[`Hash`]: http://doc.rust-lang.org/nightly/std/hash/trait.Hash.html
[`Hasher`]: http://doc.rust-lang.org/nightly/std/hash/trait.Hash.html
[`Hasher`]: http://doc.rust-lang.org/nightly/std/hash/trait.Hasher.html
[`Send`]: http://doc.rust-lang.org/nightly/std/marker/trait.Send.html
[`SliceConcatExt`]: http://doc.rust-lang.org/nightly/std/slice/trait.SliceConcatExt.html
[`Stdin`]: http://doc.rust-lang.org/nightly/std/io/struct.Stdin.html
@ -204,8 +373,8 @@ Misc
[win4]: https://github.com/rust-lang/rust/pull/27210
[xp]: https://github.com/rust-lang/rust/pull/26569
Version 1.2.0 (August 2015)
===========================
Version 1.2.0 (2015-08-07)
==========================
* ~1200 changes, numerous bugfixes
@ -308,51 +477,51 @@ Misc
* Fat pointers are now [passed in pairs of immediate arguments][fat],
resulting in faster compile times and smaller code.
[`Extend`]: http://doc.rust-lang.org/nightly/std/iter/trait.Extend.html
[`Extend`]: https://doc.rust-lang.org/nightly/std/iter/trait.Extend.html
[extend-rfc]: https://github.com/rust-lang/rfcs/blob/master/text/0839-embrace-extend-extinguish.md
[`iter::once`]: http://doc.rust-lang.org/nightly/std/iter/fn.once.html
[`iter::empty`]: http://doc.rust-lang.org/nightly/std/iter/fn.empty.html
[`matches`]: http://doc.rust-lang.org/nightly/std/primitive.str.html#method.matches
[`rmatches`]: http://doc.rust-lang.org/nightly/std/primitive.str.html#method.rmatches
[`Cell`]: http://doc.rust-lang.org/nightly/std/cell/struct.Cell.html
[`RefCell`]: http://doc.rust-lang.org/nightly/std/cell/struct.RefCell.html
[`wrapping_add`]: http://doc.rust-lang.org/nightly/std/primitive.i8.html#method.wrapping_add
[`wrapping_sub`]: http://doc.rust-lang.org/nightly/std/primitive.i8.html#method.wrapping_sub
[`wrapping_mul`]: http://doc.rust-lang.org/nightly/std/primitive.i8.html#method.wrapping_mul
[`wrapping_div`]: http://doc.rust-lang.org/nightly/std/primitive.i8.html#method.wrapping_div
[`wrapping_rem`]: http://doc.rust-lang.org/nightly/std/primitive.i8.html#method.wrapping_rem
[`wrapping_neg`]: http://doc.rust-lang.org/nightly/std/primitive.i8.html#method.wrapping_neg
[`wrapping_shl`]: http://doc.rust-lang.org/nightly/std/primitive.i8.html#method.wrapping_shl
[`wrapping_shr`]: http://doc.rust-lang.org/nightly/std/primitive.i8.html#method.wrapping_shr
[`Wrapping`]: http://doc.rust-lang.org/nightly/std/num/struct.Wrapping.html
[`fmt::Formatter`]: http://doc.rust-lang.org/nightly/std/fmt/struct.Formatter.html
[`fmt::Write`]: http://doc.rust-lang.org/nightly/std/fmt/trait.Write.html
[`io::Write`]: http://doc.rust-lang.org/nightly/std/io/trait.Write.html
[`debug_struct`]: http://doc.rust-lang.org/nightly/core/fmt/struct.Formatter.html#method.debug_struct
[`debug_tuple`]: http://doc.rust-lang.org/nightly/core/fmt/struct.Formatter.html#method.debug_tuple
[`debug_list`]: http://doc.rust-lang.org/nightly/core/fmt/struct.Formatter.html#method.debug_list
[`debug_set`]: http://doc.rust-lang.org/nightly/core/fmt/struct.Formatter.html#method.debug_set
[`debug_map`]: http://doc.rust-lang.org/nightly/core/fmt/struct.Formatter.html#method.debug_map
[`Debug`]: http://doc.rust-lang.org/nightly/std/fmt/trait.Debug.html
[strup]: http://doc.rust-lang.org/nightly/std/primitive.str.html#method.to_uppercase
[strlow]: http://doc.rust-lang.org/nightly/std/primitive.str.html#method.to_lowercase
[`to_uppercase`]: http://doc.rust-lang.org/nightly/std/primitive.char.html#method.to_uppercase
[`to_lowercase`]: http://doc.rust-lang.org/nightly/std/primitive.char.html#method.to_lowercase
[`PoisonError`]: http://doc.rust-lang.org/nightly/std/sync/struct.PoisonError.html
[`RwLock`]: http://doc.rust-lang.org/nightly/std/sync/struct.RwLock.html
[`Mutex`]: http://doc.rust-lang.org/nightly/std/sync/struct.Mutex.html
[`FromRawFd`]: http://doc.rust-lang.org/nightly/std/os/unix/io/trait.FromRawFd.html
[`AsRawFd`]: http://doc.rust-lang.org/nightly/std/os/unix/io/trait.AsRawFd.html
[`Stdio`]: http://doc.rust-lang.org/nightly/std/process/struct.Stdio.html
[`ChildStdin`]: http://doc.rust-lang.org/nightly/std/process/struct.ChildStdin.html
[`ChildStdout`]: http://doc.rust-lang.org/nightly/std/process/struct.ChildStdout.html
[`ChildStderr`]: http://doc.rust-lang.org/nightly/std/process/struct.ChildStderr.html
[`io::ErrorKind`]: http://doc.rust-lang.org/nightly/std/io/enum.ErrorKind.html
[`iter::once`]: https://doc.rust-lang.org/nightly/std/iter/fn.once.html
[`iter::empty`]: https://doc.rust-lang.org/nightly/std/iter/fn.empty.html
[`matches`]: https://doc.rust-lang.org/nightly/std/primitive.str.html#method.matches
[`rmatches`]: https://doc.rust-lang.org/nightly/std/primitive.str.html#method.rmatches
[`Cell`]: https://doc.rust-lang.org/nightly/std/cell/struct.Cell.html
[`RefCell`]: https://doc.rust-lang.org/nightly/std/cell/struct.RefCell.html
[`wrapping_add`]: https://doc.rust-lang.org/nightly/std/primitive.i8.html#method.wrapping_add
[`wrapping_sub`]: https://doc.rust-lang.org/nightly/std/primitive.i8.html#method.wrapping_sub
[`wrapping_mul`]: https://doc.rust-lang.org/nightly/std/primitive.i8.html#method.wrapping_mul
[`wrapping_div`]: https://doc.rust-lang.org/nightly/std/primitive.i8.html#method.wrapping_div
[`wrapping_rem`]: https://doc.rust-lang.org/nightly/std/primitive.i8.html#method.wrapping_rem
[`wrapping_neg`]: https://doc.rust-lang.org/nightly/std/primitive.i8.html#method.wrapping_neg
[`wrapping_shl`]: https://doc.rust-lang.org/nightly/std/primitive.i8.html#method.wrapping_shl
[`wrapping_shr`]: https://doc.rust-lang.org/nightly/std/primitive.i8.html#method.wrapping_shr
[`Wrapping`]: https://doc.rust-lang.org/nightly/std/num/struct.Wrapping.html
[`fmt::Formatter`]: https://doc.rust-lang.org/nightly/std/fmt/struct.Formatter.html
[`fmt::Write`]: https://doc.rust-lang.org/nightly/std/fmt/trait.Write.html
[`io::Write`]: https://doc.rust-lang.org/nightly/std/io/trait.Write.html
[`debug_struct`]: https://doc.rust-lang.org/nightly/core/fmt/struct.Formatter.html#method.debug_struct
[`debug_tuple`]: https://doc.rust-lang.org/nightly/core/fmt/struct.Formatter.html#method.debug_tuple
[`debug_list`]: https://doc.rust-lang.org/nightly/core/fmt/struct.Formatter.html#method.debug_list
[`debug_set`]: https://doc.rust-lang.org/nightly/core/fmt/struct.Formatter.html#method.debug_set
[`debug_map`]: https://doc.rust-lang.org/nightly/core/fmt/struct.Formatter.html#method.debug_map
[`Debug`]: https://doc.rust-lang.org/nightly/std/fmt/trait.Debug.html
[strup]: https://doc.rust-lang.org/nightly/std/primitive.str.html#method.to_uppercase
[strlow]: https://doc.rust-lang.org/nightly/std/primitive.str.html#method.to_lowercase
[`to_uppercase`]: https://doc.rust-lang.org/nightly/std/primitive.char.html#method.to_uppercase
[`to_lowercase`]: https://doc.rust-lang.org/nightly/std/primitive.char.html#method.to_lowercase
[`PoisonError`]: https://doc.rust-lang.org/nightly/std/sync/struct.PoisonError.html
[`RwLock`]: https://doc.rust-lang.org/nightly/std/sync/struct.RwLock.html
[`Mutex`]: https://doc.rust-lang.org/nightly/std/sync/struct.Mutex.html
[`FromRawFd`]: https://doc.rust-lang.org/nightly/std/os/unix/io/trait.FromRawFd.html
[`AsRawFd`]: https://doc.rust-lang.org/nightly/std/os/unix/io/trait.AsRawFd.html
[`Stdio`]: https://doc.rust-lang.org/nightly/std/process/struct.Stdio.html
[`ChildStdin`]: https://doc.rust-lang.org/nightly/std/process/struct.ChildStdin.html
[`ChildStdout`]: https://doc.rust-lang.org/nightly/std/process/struct.ChildStdout.html
[`ChildStderr`]: https://doc.rust-lang.org/nightly/std/process/struct.ChildStderr.html
[`io::ErrorKind`]: https://doc.rust-lang.org/nightly/std/io/enum.ErrorKind.html
[debugfmt]: https://www.reddit.com/r/rust/comments/3ceaui/psa_produces_prettyprinted_debug_output/
[`DerefMut`]: http://doc.rust-lang.org/nightly/std/ops/trait.DerefMut.html
[`mem::align_of`]: http://doc.rust-lang.org/nightly/std/mem/fn.align_of.html
[`DerefMut`]: https://doc.rust-lang.org/nightly/std/ops/trait.DerefMut.html
[`mem::align_of`]: https://doc.rust-lang.org/nightly/std/mem/fn.align_of.html
[align]: https://github.com/rust-lang/rust/pull/25646
[`mem::min_align_of`]: http://doc.rust-lang.org/nightly/std/mem/fn.min_align_of.html
[`mem::min_align_of`]: https://doc.rust-lang.org/nightly/std/mem/fn.min_align_of.html
[typos]: https://github.com/rust-lang/rust/pull/26087
[nop]: https://github.com/rust-lang/rust/pull/26336
[fat]: https://github.com/rust-lang/rust/pull/26411
@ -362,7 +531,7 @@ Misc
[ad]: https://github.com/rust-lang/rust/pull/27382
[win]: https://github.com/rust-lang/rust/pull/25350
Version 1.1.0 (June 2015)
Version 1.1.0 (2015-06-25)
=========================
* ~850 changes, numerous bugfixes
@ -443,14 +612,14 @@ Misc
* [The `drop_with_repr_extern` lint warns about mixing `repr(C)`
with `Drop`][drop].
[`str::split_whitespace`]: http://doc.rust-lang.org/nightly/std/primitive.str.html#method.split_whitespace
[`FromRawFd`]: http://doc.rust-lang.org/nightly/std/os/unix/io/trait.FromRawFd.html
[`AsRawFd`]: http://doc.rust-lang.org/nightly/std/os/unix/io/trait.AsRawFd.html
[`std::os::unix::symlink`]: http://doc.rust-lang.org/nightly/std/os/unix/fs/fn.symlink.html
[`IntoIterator`]: http://doc.rust-lang.org/nightly/std/iter/trait.IntoIterator.html
[`From`]: http://doc.rust-lang.org/nightly/std/convert/trait.From.html
[`str::split_whitespace`]: https://doc.rust-lang.org/nightly/std/primitive.str.html#method.split_whitespace
[`FromRawFd`]: https://doc.rust-lang.org/nightly/std/os/unix/io/trait.FromRawFd.html
[`AsRawFd`]: https://doc.rust-lang.org/nightly/std/os/unix/io/trait.AsRawFd.html
[`std::os::unix::symlink`]: https://doc.rust-lang.org/nightly/std/os/unix/fs/fn.symlink.html
[`IntoIterator`]: https://doc.rust-lang.org/nightly/std/iter/trait.IntoIterator.html
[`From`]: https://doc.rust-lang.org/nightly/std/convert/trait.From.html
[rf]: https://github.com/rust-lang/rust/pull/24491
[err-index]: http://doc.rust-lang.org/error-index.html
[err-index]: https://doc.rust-lang.org/error-index.html
[sk]: https://github.com/rust-lang/rust/pull/24615
[pre]: https://github.com/rust-lang/rust/pull/25323
[file]: https://github.com/rust-lang/rust/pull/24598
@ -464,16 +633,16 @@ Misc
[pie]: https://github.com/rust-lang/rust/pull/24953
[abs]: https://github.com/rust-lang/rust/pull/25441
[c]: https://github.com/rust-lang/rust/pull/25496
[`Cloned`]: http://doc.rust-lang.org/nightly/std/iter/struct.Cloned.html
[`Incoming`]: http://doc.rust-lang.org/nightly/std/net/struct.Incoming.html
[`Cloned`]: https://doc.rust-lang.org/nightly/std/iter/struct.Cloned.html
[`Incoming`]: https://doc.rust-lang.org/nightly/std/net/struct.Incoming.html
[inc]: https://github.com/rust-lang/rust/pull/25522
[bh]: https://github.com/rust-lang/rust/pull/25856
[`BinaryHeap`]: http://doc.rust-lang.org/nightly/std/collections/struct.BinaryHeap.html
[`BinaryHeap`]: https://doc.rust-lang.org/nightly/std/collections/struct.BinaryHeap.html
[ll]: https://github.com/rust-lang/rust/pull/26022
[`split_off`]: http://doc.rust-lang.org/nightly/collections/linked_list/struct.LinkedList.html#method.split_off
[`split_off`]: https://doc.rust-lang.org/nightly/collections/linked_list/struct.LinkedList.html#method.split_off
[drop]: https://github.com/rust-lang/rust/pull/24935
Version 1.0.0 (May 2015)
Version 1.0.0 (2015-05-15)
========================
* ~1500 changes, numerous bugfixes
@ -714,7 +883,7 @@ Version 1.0.0-alpha.2 (February 2015)
[drop]: https://github.com/rust-lang/rust/pull/21972
[drop-rfc]: https://github.com/rust-lang/rfcs/blob/master/text/0769-sound-generic-drop.md
[feat]: https://github.com/rust-lang/rust/pull/21248
[feat-forum]: http://users.rust-lang.org/t/psa-important-info-about-rustcs-new-feature-staging/82/5
[feat-forum]: https://users.rust-lang.org/t/psa-important-info-about-rustcs-new-feature-staging/82/5
[feat-rfc]: https://github.com/rust-lang/rfcs/blob/master/text/0507-release-channels.md
[fmt]: https://github.com/rust-lang/rust/pull/21457
[into]: https://github.com/rust-lang/rust/pull/20790
@ -915,7 +1084,7 @@ Version 1.0.0-alpha (January 2015)
[objsafe]: https://github.com/rust-lang/rfcs/blob/master/text/0255-object-safety.md
[assoc]: https://github.com/rust-lang/rfcs/blob/master/text/0195-associated-items.md
[ints]: https://github.com/rust-lang/rfcs/pull/544#issuecomment-68760871
[trpl]: http://doc.rust-lang.org/book/index.html
[trpl]: https://doc.rust-lang.org/book/index.html
[rbe]: http://rustbyexample.com/

82
configure vendored
View File

@ -602,11 +602,16 @@ valopt python "" "set path to python"
valopt jemalloc-root "" "set directory where libjemalloc_pic.a is located"
valopt build "${DEFAULT_BUILD}" "GNUs ./configure syntax LLVM build triple"
valopt android-cross-path "/opt/ndk_standalone" "Android NDK standalone path (deprecated)"
valopt i686-linux-android-ndk "" "i686-linux-android NDK standalone path"
valopt arm-linux-androideabi-ndk "" "arm-linux-androideabi NDK standalone path"
valopt aarch64-linux-android-ndk "" "aarch64-linux-android NDK standalone path"
valopt release-channel "dev" "the name of the release channel to build"
valopt musl-root "/usr/local" "MUSL root installation directory"
# Used on systems where "cc" and "ar" are unavailable
valopt default-linker "cc" "the default linker"
valopt default-ar "ar" "the default ar"
# Many of these are saved below during the "writing configuration" step
# (others are conditionally saved).
opt_nosave manage-submodules 1 "let the build manage the git submodules"
@ -880,6 +885,28 @@ then
CFG_DISABLE_JEMALLOC=1
fi
# default gcc version under OpenBSD maybe too old, try using egcc, which is a
# gcc version from ports
if [ $CFG_OSTYPE = unknown-openbsd ]
then
if [ $("$CFG_GCC" --version 2>&1 | grep -c ' 4\.[0-6]') -ne 0 ]; then
step_msg "older GCC found, try with egcc instead"
# probe again but using egcc
probe CFG_GCC egcc
# and use egcc/eg++ for CC/CXX too if it was found
# (but user setting has priority)
if [ -n "$CFG_GCC" ]; then
CC="${CC:-egcc}"
CXX="${CXX:-eg++}"
fi
fi
step_msg "on OpenBSD, disabling jemalloc"
CFG_DISABLE_JEMALLOC=1
fi
# OS X 10.9, gcc is actually clang. This can cause some confusion in the build
# system, so if we find that gcc is clang, we should just use clang directly.
if [ $CFG_OSTYPE = apple-darwin -a -z "$CFG_ENABLE_CLANG" ]
@ -951,7 +978,7 @@ then
LLVM_VERSION=$($LLVM_CONFIG --version)
case $LLVM_VERSION in
(3.[5-7]*)
(3.[5-8]*)
msg "found ok version of LLVM: $LLVM_VERSION"
;;
(*)
@ -1025,7 +1052,7 @@ then
esac
else
case $CFG_CLANG_VERSION in
(3.2* | 3.3* | 3.4* | 3.5* | 3.6* | 3.7*)
(3.2* | 3.3* | 3.4* | 3.5* | 3.6* | 3.7* | 3.8*)
step_msg "found ok version of CLANG: $CFG_CLANG_VERSION"
;;
(*)
@ -1164,27 +1191,56 @@ do
#
# Consequently here we try to detect when that happens and print an
# error if it does.
if $CFG_PYTHON -c 'import sys; print sys.argv[1]' `pwd` | grep '^/'
if $CFG_PYTHON -c 'import sys; print sys.argv[1]' `pwd` | grep '^/' > /dev/null
then
err "python is silently translating windows paths to MSYS paths \
and the build will fail if this python is used.\n\n \
Either an official python install must be used or an \
alternative python package in MinGW must be used."
err "
python is silently translating windows paths to MSYS paths \
and the build will fail if this python is used.
Either an official python install must be used or an \
alternative python package in MinGW must be used.
If you are building under msys2 try installing the mingw-w64-x86_64-python2 \
package instead of python2:
$ pacman -R python2 && pacman -S mingw-w64-x86_64-python2
"
fi
# MSVC requires cmake because that's how we're going to build LLVM
probe_need CFG_CMAKE cmake
# There are three builds of cmake on windows: MSVC, MinGW and Cygwin
# The Cygwin build does not have generators for Visual Studio, so
# detect that here and error.
if ! "$CFG_CMAKE" --help | sed -n '/^Generators/,$p' | grep 'Visual Studio' > /dev/null
then
err "
cmake does not support Visual Studio generators.
This is likely due to it being an msys/cygwin build of cmake, \
rather than the required windows version, built using MinGW \
or Visual Studio.
If you are building under msys2 try installing the mingw-w64-x86_64-cmake \
package instead of cmake:
$ pacman -R cmake && pacman -S mingw-w64-x86_64-cmake
"
fi
# Use the REG program to figure out where VS is installed
# We need to figure out where cl.exe and link.exe are, so we do some
# munging and some probing here. We also look for the default
# INCLUDE and LIB variables for MSVC so we can set those in the
# build system as well.
install=$(reg QUERY \
install=$(cmd //c reg QUERY \
'HKLM\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\14.0' \
-v InstallDir)
if [ -z "$install" ]; then
install=$(reg QUERY \
install=$(cmd //c reg QUERY \
'HKLM\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\12.0' \
-v InstallDir)
fi
@ -1217,9 +1273,9 @@ do
eval CFG_MSVC_LINK_$bits="\"$bindir/link.exe\""
vcvarsall="${CFG_MSVC_ROOT}/VC/vcvarsall.bat"
include_path=$(cmd /c "\"$vcvarsall\" $msvc_part && cmd /c echo %INCLUDE%")
include_path=$(cmd //V:ON //c "$vcvarsall" $msvc_part \& echo !INCLUDE!)
need_ok "failed to learn about MSVC's INCLUDE"
lib_path=$(cmd /c "\"$vcvarsall\" $msvc_part && cmd /c echo %LIB%")
lib_path=$(cmd //V:ON //c "$vcvarsall" $msvc_part \& echo !LIB!)
need_ok "failed to learn about MSVC's LIB"
eval CFG_MSVC_INCLUDE_PATH_${bits}="\"$include_path\""
@ -1428,9 +1484,10 @@ do
LLVM_BUILD_DIR=
LLVM_INST_DIR=$CFG_LLVM_ROOT
do_reconfigure=0
# Check that LLVm FileCheck is available. Needed for the tests
need_cmd $LLVM_INST_DIR/bin/FileCheck
fi
if [ ${do_reconfigure} -ne 0 ]
then
# because git is hilarious, it might have put the module index
@ -1688,6 +1745,7 @@ putvar CFG_LIBDIR_RELATIVE
putvar CFG_DISABLE_MANAGE_SUBMODULES
putvar CFG_AARCH64_LINUX_ANDROID_NDK
putvar CFG_ARM_LINUX_ANDROIDEABI_NDK
putvar CFG_I686_LINUX_ANDROID_NDK
putvar CFG_MANDIR
# Avoid spurious warnings from clang by feeding it original source on

View File

@ -41,7 +41,7 @@ look for anything here (the default)
.RE
.TP
\fB\-l\fR [\fIKIND\fR=]\fINAME\fR
Link the generated crate(s) to the specified native library \fINAME\fR.
Link the generated crate(s) to the specified library \fINAME\fR.
The optional \fIKIND\fR can be one of \fIstatic\fR, \fIdylib\fR, or
\fIframework\fR.
If omitted, \fIdylib\fR is assumed.
@ -113,7 +113,8 @@ Print version info and exit.
Use verbose output.
.TP
\fB\-\-extern\fR \fINAME\fR=\fIPATH\fR
Specify where an external rust library is located.
Specify where an external rust library is located. These should match
\fIextern\fR declarations in the crate's source code.
.TP
\fB\-\-sysroot\fR \fIPATH\fR
Override the system root.

View File

@ -0,0 +1,25 @@
# i686-linux-android configuration
CC_i686-linux-android=$(CFG_I686_LINUX_ANDROID_NDK)/bin/i686-linux-android-gcc
CXX_i686-linux-android=$(CFG_I686_LINUX_ANDROID_NDK)/bin/i686-linux-android-g++
CPP_i686-linux-android=$(CFG_I686_LINUX_ANDROID_NDK)/bin/i686-linux-android-gcc -E
AR_i686-linux-android=$(CFG_I686_LINUX_ANDROID_NDK)/bin/i686-linux-android-ar
CFG_LIB_NAME_i686-linux-android=lib$(1).so
CFG_STATIC_LIB_NAME_i686-linux-android=lib$(1).a
CFG_LIB_GLOB_i686-linux-android=lib$(1)-*.so
CFG_LIB_DSYM_GLOB_i686-linux-android=lib$(1)-*.dylib.dSYM
CFG_JEMALLOC_CFLAGS_i686-linux-android := -D__i686__ -DANDROID -D__ANDROID__ $(CFLAGS)
CFG_GCCISH_CFLAGS_i686-linux-android := -Wall -g -fPIC -D__i686__ -DANDROID -D__ANDROID__ $(CFLAGS)
CFG_GCCISH_CXXFLAGS_i686-linux-android := -fno-rtti $(CXXFLAGS)
CFG_GCCISH_LINK_FLAGS_i686-linux-android := -shared -fPIC -ldl -g -lm -lsupc++
CFG_GCCISH_DEF_FLAG_i686-linux-android := -Wl,--export-dynamic,--dynamic-list=
CFG_LLC_FLAGS_i686-linux-android :=
CFG_INSTALL_NAME_i686-linux-android =
CFG_EXE_SUFFIX_i686-linux-android :=
CFG_WINDOWSY_i686-linux-android :=
CFG_UNIXY_i686-linux-android := 1
CFG_LDPATH_i686-linux-android :=
CFG_RUN_i686-linux-android=
CFG_RUN_TARG_i686-linux-android=
RUSTC_FLAGS_i686-linux-android :=
RUSTC_CROSS_FLAGS_i686-linux-android :=
CFG_GNU_TRIPLE_i686-linux-android := i686-linux-android

View File

@ -22,8 +22,3 @@ CFG_LDPATH_i686-pc-windows-msvc :=
CFG_RUN_i686-pc-windows-msvc=$(2)
CFG_RUN_TARG_i686-pc-windows-msvc=$(call CFG_RUN_i686-pc-windows-msvc,,$(2))
CFG_GNU_TRIPLE_i686-pc-windows-msvc := i686-pc-win32
# All windows nightiles are currently a GNU triple, so this MSVC triple is not
# bootstrapping from itself. This is relevant during stage0, and other parts of
# the build system take this into account.
BOOTSTRAP_FROM_i686-pc-windows-msvc := i686-pc-windows-gnu

View File

@ -22,8 +22,3 @@ CFG_LDPATH_x86_64-pc-windows-msvc :=
CFG_RUN_x86_64-pc-windows-msvc=$(2)
CFG_RUN_TARG_x86_64-pc-windows-msvc=$(call CFG_RUN_x86_64-pc-windows-msvc,,$(2))
CFG_GNU_TRIPLE_x86_64-pc-windows-msvc := x86_64-pc-win32
# All windows nightiles are currently a GNU triple, so this MSVC triple is not
# bootstrapping from itself. This is relevant during stage0, and other parts of
# the build system take this into account.
BOOTSTRAP_FROM_x86_64-pc-windows-msvc := x86_64-pc-windows-gnu

View File

@ -101,7 +101,6 @@ define CLEAN_TARGET_STAGE_N
clean$(1)_T_$(2)_H_$(3): \
$$(foreach crate,$$(CRATES),clean$(1)_T_$(2)_H_$(3)-lib-$$(crate)) \
$$(foreach tool,$$(TOOLS) $$(DEBUGGER_BIN_SCRIPTS_ALL),clean$(1)_T_$(2)_H_$(3)-tool-$$(tool))
$$(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/libmorestack.a
$$(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/libcompiler-rt.a
$(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/librun_pass_stage* # For unix
$(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/run_pass_stage* # For windows

View File

@ -52,41 +52,44 @@
TARGET_CRATES := libc std flate arena term \
serialize getopts collections test rand \
log graphviz core rbml alloc \
rustc_unicode rustc_bitflags
RUSTC_CRATES := rustc rustc_typeck rustc_borrowck rustc_resolve rustc_driver \
rustc_unicode rustc_bitflags \
alloc_system
RUSTC_CRATES := rustc rustc_typeck rustc_mir rustc_borrowck rustc_resolve rustc_driver \
rustc_trans rustc_back rustc_llvm rustc_privacy rustc_lint \
rustc_data_structures
rustc_data_structures rustc_front rustc_platform_intrinsics
HOST_CRATES := syntax $(RUSTC_CRATES) rustdoc fmt_macros
CRATES := $(TARGET_CRATES) $(HOST_CRATES)
TOOLS := compiletest rustdoc rustc rustbook error-index-generator
DEPS_core :=
DEPS_libc := core
DEPS_rustc_unicode := core
DEPS_alloc := core libc native:jemalloc
DEPS_alloc := core libc alloc_system
DEPS_std := core libc rand alloc collections rustc_unicode \
native:rust_builtin native:backtrace native:rustrt_native \
rustc_bitflags
native:rust_builtin native:backtrace \
alloc_system
DEPS_graphviz := std
DEPS_syntax := std term serialize log fmt_macros arena libc
DEPS_syntax := std term serialize log fmt_macros arena libc rustc_bitflags
DEPS_rustc_driver := arena flate getopts graphviz libc rustc rustc_back rustc_borrowck \
rustc_typeck rustc_resolve log syntax serialize rustc_llvm \
rustc_trans rustc_privacy rustc_lint
rustc_typeck rustc_mir rustc_resolve log syntax serialize rustc_llvm \
rustc_trans rustc_privacy rustc_lint rustc_front
DEPS_rustc_trans := arena flate getopts graphviz libc rustc rustc_back \
log syntax serialize rustc_llvm
DEPS_rustc_typeck := rustc syntax
DEPS_rustc_borrowck := rustc log graphviz syntax
DEPS_rustc_resolve := rustc log syntax
DEPS_rustc_privacy := rustc log syntax
log syntax serialize rustc_llvm rustc_front rustc_platform_intrinsics
DEPS_rustc_mir := rustc rustc_front syntax
DEPS_rustc_typeck := rustc syntax rustc_front rustc_platform_intrinsics
DEPS_rustc_borrowck := rustc rustc_front log graphviz syntax
DEPS_rustc_resolve := rustc rustc_front log syntax
DEPS_rustc_privacy := rustc rustc_front log syntax
DEPS_rustc_lint := rustc log syntax
DEPS_rustc := syntax flate arena serialize getopts rbml \
log graphviz rustc_llvm rustc_back rustc_data_structures
DEPS_rustc_llvm := native:rustllvm libc std
DEPS_rustc_back := std syntax rustc_llvm flate log libc
DEPS_rustc_llvm := native:rustllvm libc std rustc_bitflags
DEPS_rustc_platform_intrinsics := rustc rustc_llvm
DEPS_rustc_back := std syntax rustc_llvm rustc_front flate log libc
DEPS_rustc_front := std syntax log serialize
DEPS_rustc_data_structures := std log serialize
DEPS_rustdoc := rustc rustc_driver native:hoedown serialize getopts \
test rustc_lint
test rustc_lint rustc_front
DEPS_rustc_bitflags := core
DEPS_flate := std native:miniz
DEPS_arena := std
@ -102,6 +105,7 @@ DEPS_test := std getopts serialize rbml term native:rust_test_helpers
DEPS_rand := core
DEPS_log := std
DEPS_fmt_macros = std
DEPS_alloc_system := core libc
TOOL_DEPS_compiletest := test getopts
TOOL_DEPS_rustdoc := rustdoc
@ -121,14 +125,26 @@ ONLY_RLIB_rand := 1
ONLY_RLIB_collections := 1
ONLY_RLIB_rustc_unicode := 1
ONLY_RLIB_rustc_bitflags := 1
ONLY_RLIB_alloc_system := 1
# Documented-by-default crates
DOC_CRATES := std alloc collections core libc rustc_unicode
ifeq ($(CFG_DISABLE_JEMALLOC),)
TARGET_CRATES += alloc_jemalloc
DEPS_std += alloc_jemalloc
DEPS_alloc_jemalloc := core libc native:jemalloc
ONLY_RLIB_alloc_jemalloc := 1
else
RUSTFLAGS_rustc_back := --cfg disable_jemalloc
endif
################################################################################
# You should not need to edit below this line
################################################################################
CRATES := $(TARGET_CRATES) $(HOST_CRATES)
# This macro creates some simple definitions for each crate being built, just
# some munging of all of the parameters above.
#

View File

@ -13,9 +13,6 @@
#
# The DOCS variable is their names (with no file extension).
#
# PDF_DOCS lists the targets for which PDF documentation should be
# build.
#
# RUSTDOC_FLAGS_xyz variables are extra arguments to pass to the
# rustdoc invocation for xyz.
#
@ -35,8 +32,6 @@ DOCS += guide-crates guide-error-handling guide-ffi guide-macros guide \
guide-testing
PDF_DOCS := reference
RUSTDOC_DEPS_reference := doc/full-toc.inc
RUSTDOC_FLAGS_reference := --html-in-header=doc/full-toc.inc
@ -48,17 +43,10 @@ L10N_LANGS := ja
RUSTDOC_HTML_OPTS_NO_CSS = --html-before-content=doc/version_info.html \
--html-in-header=doc/favicon.inc \
--html-after-content=doc/footer.inc \
--markdown-playground-url='http://play.rust-lang.org/'
--markdown-playground-url='https://play.rust-lang.org/'
RUSTDOC_HTML_OPTS = $(RUSTDOC_HTML_OPTS_NO_CSS) --markdown-css rust.css
PANDOC_BASE_OPTS := --standalone --toc --number-sections
PANDOC_TEX_OPTS = $(PANDOC_BASE_OPTS) --from=markdown --to=latex \
--include-before-body=doc/version.tex \
--include-before-body=doc/footer.tex \
--include-in-header=doc/uptack.tex
PANDOC_EPUB_OPTS = $(PANDOC_BASE_OPTS) --to=epub
# The rustdoc executable...
RUSTDOC_EXE = $(HBIN2_H_$(CFG_BUILD))/rustdoc$(X_$(CFG_BUILD))
# ...with rpath included in case --disable-rpath was provided to
@ -89,30 +77,10 @@ else
HTML_DEPS :=
endif
# Check for xelatex
ifneq ($(CFG_XELATEX),)
CFG_LATEX := $(CFG_XELATEX)
XELATEX = 1
else
$(info cfg: no xelatex found, disabling LaTeX docs)
NO_PDF_DOCS = 1
endif
ifeq ($(CFG_PANDOC),)
$(info cfg: no pandoc found, omitting PDF and EPUB docs)
ONLY_HTML_DOCS = 1
endif
######################################################################
# Rust version
######################################################################
doc/version.tex: $(MKFILE_DEPS) $(wildcard $(D)/*.*) | doc/
@$(call E, version-stamp: $@)
$(Q)echo "$(CFG_VERSION)" >$@
HTML_DEPS += doc/version_info.html
doc/version_info.html: $(D)/version_info.html.template $(MKFILE_DEPS) \
$(wildcard $(D)/*.*) | doc/
@ -121,10 +89,10 @@ doc/version_info.html: $(D)/version_info.html.template $(MKFILE_DEPS) \
s/SHORT_HASH/$(CFG_SHORT_VER_HASH)/; \
s/STAMP/$(CFG_VER_HASH)/;" $< >$@
GENERATED += doc/version.tex doc/version_info.html
GENERATED += doc/version_info.html
######################################################################
# Docs, from rustdoc and sometimes pandoc
# Docs from rustdoc
######################################################################
doc/:
@ -150,26 +118,12 @@ doc/footer.inc: $(D)/footer.inc | doc/
$(Q)cp -PRp $< $@ 2> /dev/null
# The (english) documentation for each doc item.
define DEF_SHOULD_BUILD_PDF_DOC
SHOULD_BUILD_PDF_DOC_$(1) = 1
endef
$(foreach docname,$(PDF_DOCS),$(eval $(call DEF_SHOULD_BUILD_PDF_DOC,$(docname))))
doc/footer.tex: $(D)/footer.inc | doc/
@$(call E, pandoc: $@)
$(CFG_PANDOC) --from=html --to=latex $< --output=$@
doc/uptack.tex: $(D)/uptack.tex | doc/
$(Q)cp $< $@
# HTML (rustdoc)
DOC_TARGETS += doc/not_found.html
doc/not_found.html: $(D)/not_found.md $(HTML_DEPS) | doc/
@$(call E, rustdoc: $@)
$(Q)$(RUSTDOC) $(RUSTDOC_HTML_OPTS_NO_CSS) \
--markdown-no-toc \
--markdown-css http://doc.rust-lang.org/rust.css $<
--markdown-css https://doc.rust-lang.org/rust.css $<
define DEF_DOC
@ -179,47 +133,6 @@ doc/$(1).html: $$(D)/$(1).md $$(HTML_DEPS) $$(RUSTDOC_DEPS_$(1)) | doc/
@$$(call E, rustdoc: $$@)
$$(Q)$$(RUSTDOC) $$(RUSTDOC_HTML_OPTS) $$(RUSTDOC_FLAGS_$(1)) $$<
ifneq ($(ONLY_HTML_DOCS),1)
# EPUB (pandoc directly)
DOC_TARGETS += doc/$(1).epub
doc/$(1).epub: $$(D)/$(1).md | doc/
@$$(call E, pandoc: $$@)
$$(CFG_PANDOC) $$(PANDOC_EPUB_OPTS) $$< --output=$$@
# PDF (md =(pandoc)=> tex =(pdflatex)=> pdf)
DOC_TARGETS += doc/$(1).tex
doc/$(1).tex: $$(D)/$(1).md doc/uptack.tex doc/footer.tex doc/version.tex | doc/
@$$(call E, pandoc: $$@)
$$(CFG_PANDOC) $$(PANDOC_TEX_OPTS) $$< --output=$$@
ifneq ($(NO_PDF_DOCS),1)
ifeq ($$(SHOULD_BUILD_PDF_DOC_$(1)),1)
DOC_TARGETS += doc/$(1).pdf
ifneq ($(XELATEX),1)
doc/$(1).pdf: doc/$(1).tex
@$$(call E, latex compiler: $$@)
$$(Q)$$(CFG_LATEX) \
-interaction=batchmode \
-output-directory=doc \
$$<
else
# The version of xelatex on the snap bots seemingly ingores -output-directory
# So we'll output to . and move to the doc directory manually.
# This will leave some intermediate files in the build directory.
doc/$(1).pdf: doc/$(1).tex
@$$(call E, latex compiler: $$@)
$$(Q)$$(CFG_LATEX) \
-interaction=batchmode \
-output-directory=. \
$$<
$$(Q)mv ./$(1).pdf $$@
endif # XELATEX
endif # SHOULD_BUILD_PDF_DOCS_$(1)
endif # NO_PDF_DOCS
endif # ONLY_HTML_DOCS
endef
$(foreach docname,$(DOCS),$(eval $(call DEF_DOC,$(docname))))
@ -278,6 +191,7 @@ ifdef CFG_DISABLE_DOCS
endif
docs: $(DOC_TARGETS)
doc: docs
compiler-docs: $(COMPILER_DOC_TARGETS)
trpl: doc/book/index.html

View File

@ -13,12 +13,12 @@
######################################################################
# The version number
CFG_RELEASE_NUM=1.3.0
CFG_RELEASE_NUM=1.4.0
# An optional number to put after the label, e.g. '.2' -> '-beta.2'
# NB Make sure it starts with a dot to conform to semver pre-release
# versions (section 9)
CFG_PRERELEASE_VERSION=.3
CFG_PRERELEASE_VERSION=.4
# Append a version-dependent hash to each library, so we can install different
# versions in the same place
@ -163,7 +163,7 @@ endif
# that the snapshot will be generated with a statically linked rustc so we only
# have to worry about the distribution of one file (with its native dynamic
# dependencies)
RUSTFLAGS_STAGE0 += -C prefer-dynamic
RUSTFLAGS_STAGE0 += -C prefer-dynamic -C no-stack-check
RUSTFLAGS_STAGE1 += -C prefer-dynamic
RUST_LIB_FLAGS_ST2 += -C prefer-dynamic
RUST_LIB_FLAGS_ST3 += -C prefer-dynamic
@ -172,6 +172,18 @@ RUST_LIB_FLAGS_ST3 += -C prefer-dynamic
# by not emitting them.
RUSTFLAGS_STAGE0 += -Z no-landing-pads
# Enable MIR to "always build" for crates where this works. This is
# just temporary while MIR is being actively built up -- it's just a
# poor man's unit testing infrastructure. Anyway we only want this for
# stage1/stage2.
define ADD_MIR_FLAG
RUSTFLAGS1_$(1) += -Z always-build-mir
RUSTFLAGS2_$(1) += -Z always-build-mir
endef
$(foreach crate,$(TARGET_CRATES),$(eval $(call ADD_MIR_FLAG,$(crate))))
$(foreach crate,$(RUSTC_CRATES),$(eval $(call ADD_MIR_FLAG,$(crate))))
$(foreach crate,$(HOST_CRATES),$(eval $(call ADD_MIR_FLAG,$(crate))))
# platform-specific auto-configuration
include $(CFG_SRC_DIR)mk/platform.mk
@ -294,7 +306,7 @@ LLVM_VERSION_$(1)=$$(shell "$$(LLVM_CONFIG_$(1))" --version)
LLVM_BINDIR_$(1)=$$(shell "$$(LLVM_CONFIG_$(1))" --bindir)
LLVM_INCDIR_$(1)=$$(shell "$$(LLVM_CONFIG_$(1))" --includedir)
LLVM_LIBDIR_$(1)=$$(shell "$$(LLVM_CONFIG_$(1))" --libdir)
LLVM_LIBDIR_RUSTFLAGS_$(1)=-L "$$(LLVM_LIBDIR_$(1))"
LLVM_LIBDIR_RUSTFLAGS_$(1)=-L native="$$(LLVM_LIBDIR_$(1))"
LLVM_LDFLAGS_$(1)=$$(shell "$$(LLVM_CONFIG_$(1))" --ldflags)
ifeq ($$(findstring freebsd,$(1)),freebsd)
# On FreeBSD, it may search wrong headers (that are for pre-installed LLVM),

View File

@ -113,8 +113,7 @@ CFG_RLIB_GLOB=lib$(1)-*.rlib
include $(wildcard $(CFG_SRC_DIR)mk/cfg/*.mk)
define ADD_INSTALLED_OBJECTS
INSTALLED_OBJECTS_$(1) += $$(call CFG_STATIC_LIB_NAME_$(1),morestack) \
$$(call CFG_STATIC_LIB_NAME_$(1),compiler-rt)
INSTALLED_OBJECTS_$(1) += $$(call CFG_STATIC_LIB_NAME_$(1),compiler-rt)
endef
$(foreach target,$(CFG_TARGET), \
@ -238,56 +237,3 @@ endef
$(foreach target,$(CFG_TARGET), \
$(eval $(call CFG_MAKE_TOOLCHAIN,$(target))))
# There are more comments about this available in the target specification for
# Windows MSVC in the compiler, but the gist of it is that we use `llvm-ar.exe`
# instead of `lib.exe` for assembling archives, so we need to inject this custom
# dependency here.
define ADD_LLVM_AR_TO_MSVC_DEPS
ifeq ($$(findstring msvc,$(1)),msvc)
NATIVE_TOOL_DEPS_core_T_$(1) += llvm-ar.exe
INSTALLED_BINS_$(1) += llvm-ar.exe
endif
endef
$(foreach target,$(CFG_TARGET), \
$(eval $(call ADD_LLVM_AR_TO_MSVC_DEPS,$(target))))
# When working with MSVC on windows, each DLL needs to explicitly declare its
# interface to the outside world through some means. The options for doing so
# include:
#
# 1. A custom attribute on each function itself
# 2. A linker argument saying what to export
# 3. A file which lists all symbols that need to be exported
#
# The Rust compiler takes care (1) for us for all Rust code by annotating all
# public-facing functions with dllexport, but we have a few native dependencies
# which need to cross the DLL boundary. The most important of these dependencies
# is LLVM which is linked into `rustc_llvm.dll` but primarily used from
# `rustc_trans.dll`. This means that many of LLVM's C API functions need to be
# exposed from `rustc_llvm.dll` to be forwarded over the boundary.
#
# Unfortunately, at this time, LLVM does not handle this sort of exportation on
# Windows for us, so we're forced to do it ourselves if we want it (which seems
# like the path of least resistance right now). To do this we generate a `.DEF`
# file [1] which we then custom-pass to the linker when building the rustc_llvm
# crate. This DEF file list all symbols that are exported from
# `src/librustc_llvm/lib.rs` and is generated by a small python script.
#
# Fun times!
#
# [1]: https://msdn.microsoft.com/en-us/library/28d6s79h.aspx
define ADD_RUSTC_LLVM_DEF_TO_MSVC
ifeq ($$(findstring msvc,$(1)),msvc)
RUSTFLAGS_rustc_llvm_T_$(1) += -C link-args="-DEF:$(1)/rt/rustc_llvm.def"
CUSTOM_DEPS_rustc_llvm_T_$(1) += $(1)/rt/rustc_llvm.def
$(1)/rt/rustc_llvm.def: $$(S)src/etc/mklldef.py $$(S)src/librustc_llvm/lib.rs
$$(CFG_PYTHON) $$^ $$@ rustc_llvm-$$(CFG_FILENAME_EXTRA)
endif
endef
$(foreach target,$(CFG_TARGET), \
$(eval $(call ADD_RUSTC_LLVM_DEF_TO_MSVC,$(target))))

View File

@ -35,8 +35,7 @@
# that's per-target so you're allowed to conditionally add files based on the
# target.
################################################################################
NATIVE_LIBS := rust_builtin hoedown morestack miniz \
rustrt_native rust_test_helpers
NATIVE_LIBS := rust_builtin hoedown miniz rust_test_helpers
# $(1) is the target triple
define NATIVE_LIBRARIES
@ -53,10 +52,7 @@ NATIVE_DEPS_hoedown_$(1) := hoedown/src/autolink.c \
NATIVE_DEPS_miniz_$(1) = miniz.c
NATIVE_DEPS_rust_builtin_$(1) := rust_builtin.c \
rust_android_dummy.c
NATIVE_DEPS_rustrt_native_$(1) := arch/$$(HOST_$(1))/record_sp.S
NATIVE_DEPS_rust_test_helpers_$(1) := rust_test_helpers.c
NATIVE_DEPS_morestack_$(1) := arch/$$(HOST_$(1))/morestack.S
################################################################################
# You shouldn't find it that necessary to edit anything below this line.
@ -188,8 +184,6 @@ $$(JEMALLOC_LOCAL_$(1)): $$(JEMALLOC_DEPS) $$(MKFILE_DEPS)
EXTRA_CFLAGS="-g1 -ffunction-sections -fdata-sections"
$$(Q)$$(MAKE) -C "$$(JEMALLOC_BUILD_DIR_$(1))" build_lib_static
ifeq ($$(CFG_DISABLE_JEMALLOC),)
RUSTFLAGS_alloc := --cfg jemalloc
ifeq ($(1),$$(CFG_BUILD))
ifneq ($$(CFG_JEMALLOC_ROOT),)
$$(JEMALLOC_LIB_$(1)): $$(CFG_JEMALLOC_ROOT)/libjemalloc_pic.a
@ -203,10 +197,6 @@ else
$$(JEMALLOC_LIB_$(1)): $$(JEMALLOC_LOCAL_$(1))
$$(Q)cp $$< $$@
endif
else
$$(JEMALLOC_LIB_$(1)): $$(MKFILE_DEPS)
$$(Q)touch $$@
endif
################################################################################
# compiler-rt
@ -269,8 +259,10 @@ BACKTRACE_NAME_$(1) := $$(call CFG_STATIC_LIB_NAME_$(1),backtrace)
BACKTRACE_LIB_$(1) := $$(RT_OUTPUT_DIR_$(1))/$$(BACKTRACE_NAME_$(1))
BACKTRACE_BUILD_DIR_$(1) := $$(RT_OUTPUT_DIR_$(1))/libbacktrace
# We don't use this on platforms that aren't linux-based, so just make the file
# available, the compilation of libstd won't actually build it.
# We don't use this on platforms that aren't linux-based (with the exception of
# msys2/mingw builds on windows, which use it to read the dwarf debug
# information) so just make the file available, the compilation of libstd won't
# actually build it.
ifeq ($$(findstring darwin,$$(OSTYPE_$(1))),darwin)
# See comment above
$$(BACKTRACE_LIB_$(1)):
@ -283,7 +275,7 @@ $$(BACKTRACE_LIB_$(1)):
touch $$@
else
ifeq ($$(CFG_WINDOWSY_$(1)),1)
ifeq ($$(findstring msvc,$(1)),msvc)
# See comment above
$$(BACKTRACE_LIB_$(1)):
touch $$@
@ -306,16 +298,25 @@ endif
# ./configure script. This is done to force libbacktrace to *not* use the
# atomic/sync functionality because it pulls in unnecessary dependencies and we
# never use it anyway.
#
# We also use `env PWD=` to clear the PWD environment variable, and then
# execute the command in a new shell. This is necessary to workaround a
# buildbot/msys2 bug: the shell is launched with PWD set to a windows-style path,
# which results in all further uses of `pwd` also printing a windows-style path,
# which breaks libbacktrace's configure script. Clearing PWD within the same
# shell is not sufficient.
$$(BACKTRACE_BUILD_DIR_$(1))/Makefile: $$(BACKTRACE_DEPS) $$(MKFILE_DEPS)
@$$(call E, configure: libbacktrace for $(1))
$$(Q)rm -rf $$(BACKTRACE_BUILD_DIR_$(1))
$$(Q)mkdir -p $$(BACKTRACE_BUILD_DIR_$(1))
$$(Q)(cd $$(BACKTRACE_BUILD_DIR_$(1)) && \
$$(Q)(cd $$(BACKTRACE_BUILD_DIR_$(1)) && env \
PWD= \
CC="$$(CC_$(1))" \
AR="$$(AR_$(1))" \
RANLIB="$$(AR_$(1)) s" \
CFLAGS="$$(CFG_GCCISH_CFLAGS_$(1):-Werror=) -fno-stack-protector" \
$(S)src/libbacktrace/configure --target=$(1) --host=$(CFG_BUILD))
$(S)src/libbacktrace/configure --build=$(CFG_GNU_TRIPLE_$(CFG_BUILD)) --host=$(CFG_GNU_TRIPLE_$(1)))
$$(Q)echo '#undef HAVE_ATOMIC_FUNCTIONS' >> \
$$(BACKTRACE_BUILD_DIR_$(1))/config.h
$$(Q)echo '#undef HAVE_SYNC_FUNCTIONS' >> \
@ -327,7 +328,7 @@ $$(BACKTRACE_LIB_$(1)): $$(BACKTRACE_BUILD_DIR_$(1))/Makefile $$(MKFILE_DEPS)
INCDIR=$(S)src/libbacktrace
$$(Q)cp $$(BACKTRACE_BUILD_DIR_$(1))/.libs/libbacktrace.a $$@
endif # endif for windowsy
endif # endif for msvc
endif # endif for ios
endif # endif for darwin

View File

@ -13,6 +13,10 @@
# this exists can be found on issue #2400
export CFG_COMPILER_HOST_TRIPLE
# Used as defaults for the runtime ar and cc tools
export CFG_DEFAULT_LINKER
export CFG_DEFAULT_AR
# The standard libraries should be held up to a higher standard than any old
# code, make sure that these common warnings are denied by default. These can
# be overridden during development temporarily. For stage0, we allow warnings
@ -37,10 +41,7 @@ CRATE_FULLDEPS_$(1)_T_$(2)_H_$(3)_$(4) := \
$$(foreach dep,$$(NATIVE_DEPS_$(4)), \
$$(RT_OUTPUT_DIR_$(2))/$$(call CFG_STATIC_LIB_NAME_$(2),$$(dep))) \
$$(foreach dep,$$(NATIVE_DEPS_$(4)_T_$(2)), \
$$(RT_OUTPUT_DIR_$(2))/$$(dep)) \
$$(foreach dep,$$(NATIVE_TOOL_DEPS_$(4)_T_$(2)), \
$$(TBIN$(1)_T_$(3)_H_$(3))/$$(dep)) \
$$(CUSTOM_DEPS_$(4)_T_$(2))
$$(RT_OUTPUT_DIR_$(2))/$$(dep))
endef
$(foreach host,$(CFG_HOST), \
@ -56,8 +57,7 @@ $(foreach host,$(CFG_HOST), \
# 1. The immediate dependencies are the rust source files
# 2. Each rust crate dependency is listed (based on their stamp files),
# as well as all native dependencies (listed in RT_OUTPUT_DIR)
# 3. The stage (n-1) compiler is required through the TSREQ dependency, along
# with the morestack library
# 3. The stage (n-1) compiler is required through the TSREQ dependency
# 4. When actually executing the rule, the first thing we do is to clean out
# old libs and rlibs via the REMOVE_ALL_OLD_GLOB_MATCHES macro
# 5. Finally, we get around to building the actual crate. It's just one
@ -93,7 +93,8 @@ $$(TLIB$(1)_T_$(2)_H_$(3))/stamp.$(4): \
$$(LLVM_LIBDIR_RUSTFLAGS_$(2)) \
$$(LLVM_STDCPP_RUSTFLAGS_$(2)) \
$$(RUSTFLAGS_$(4)) \
$$(RUSTFLAGS_$(4)_T_$(2)) \
$$(RUSTFLAGS$(1)_$(4)) \
$$(RUSTFLAGS$(1)_$(4)_T_$(2)) \
--out-dir $$(@D) \
-C extra-filename=-$$(CFG_FILENAME_EXTRA) \
$$<
@ -143,9 +144,6 @@ SNAPSHOT_RUSTC_POST_CLEANUP=$(HBIN0_H_$(CFG_BUILD))/rustc$(X_$(CFG_BUILD))
define TARGET_HOST_RULES
$$(TBIN$(1)_T_$(2)_H_$(3))/:
mkdir -p $$@
$$(TLIB$(1)_T_$(2)_H_$(3))/:
mkdir -p $$@
@ -153,11 +151,6 @@ $$(TLIB$(1)_T_$(2)_H_$(3))/%: $$(RT_OUTPUT_DIR_$(2))/% \
| $$(TLIB$(1)_T_$(2)_H_$(3))/ $$(SNAPSHOT_RUSTC_POST_CLEANUP)
@$$(call E, cp: $$@)
$$(Q)cp $$< $$@
$$(TBIN$(1)_T_$(2)_H_$(3))/%: $$(CFG_LLVM_INST_DIR_$(2))/bin/% \
| $$(TBIN$(1)_T_$(2)_H_$(3))/ $$(SNAPSHOT_RUSTC_POST_CLEANUP)
@$$(call E, cp: $$@)
$$(Q)cp $$< $$@
endef
$(foreach source,$(CFG_HOST), \
@ -181,77 +174,3 @@ $(foreach host,$(CFG_HOST), \
$(foreach stage,$(STAGES), \
$(foreach tool,$(TOOLS), \
$(eval $(call TARGET_TOOL,$(stage),$(target),$(host),$(tool)))))))
# We have some triples which are bootstrapped from other triples, and this means
# that we need to fixup some of the native tools that a triple depends on.
#
# For example, MSVC requires the llvm-ar.exe executable to manage archives, but
# it bootstraps from the GNU Windows triple. This means that the compiler will
# add this directory to PATH when executing new processes:
#
# $SYSROOT/rustlib/x86_64-pc-windows-gnu/bin
#
# Unfortunately, however, the GNU triple is not known about in stage0, so the
# tools are actually located in:
#
# $SYSROOT/rustlib/x86_64-pc-windows-msvc/bin
#
# To remedy this problem, the rules below copy all native tool dependencies into
# the bootstrap triple's location in stage 0 so the bootstrap compiler can find
# the right sets of tools. Later stages (1+) will have the right host triple for
# the compiler, so there's no need to worry there.
#
# $(1) - stage
# $(2) - triple that's being used as host/target
# $(3) - triple snapshot is built for
# $(4) - crate
# $(5) - tool
define MOVE_TOOLS_TO_SNAPSHOT_HOST_DIR
ifneq (,$(3))
$$(TLIB$(1)_T_$(2)_H_$(2))/stamp.$(4): $$(HLIB$(1)_H_$(2))/rustlib/$(3)/bin/$(5)
$$(HLIB$(1)_H_$(2))/rustlib/$(3)/bin/$(5): $$(TBIN$(1)_T_$(2)_H_$(2))/$(5)
mkdir -p $$(@D)
cp $$< $$@
endif
endef
$(foreach target,$(CFG_TARGET), \
$(foreach crate,$(CRATES), \
$(foreach tool,$(NATIVE_TOOL_DEPS_$(crate)_T_$(target)), \
$(eval $(call MOVE_TOOLS_TO_SNAPSHOT_HOST_DIR,0,$(target),$(BOOTSTRAP_FROM_$(target)),$(crate),$(tool))))))
# For MSVC targets we need to set up some environment variables for the linker
# to work correctly when building Rust crates. These two variables are:
#
# - LIB tells the linker the default search path for finding system libraries,
# for example kernel32.dll
# - PATH needs to be modified to ensure that MSVC's link.exe is first in the
# path instead of MinGW's /usr/bin/link.exe (entirely unrelated)
#
# The values for these variables are detected by the configure script.
define SETUP_LIB_MSVC_ENV_VARS
ifeq ($$(findstring msvc,$(2)),msvc)
$$(TLIB$(1)_T_$(2)_H_$(3))/stamp.$(4): \
export LIB := $$(CFG_MSVC_LIB_PATH_$$(HOST_$(2)))
$$(TLIB$(1)_T_$(2)_H_$(3))/stamp.$(4): \
export PATH := $$(CFG_MSVC_BINDIR_$$(HOST_$(2))):$$(PATH)
endif
endef
define SETUP_TOOL_MSVC_ENV_VARS
ifeq ($$(findstring msvc,$(2)),msvc)
$$(TBIN$(1)_T_$(2)_H_$(3))/$(4)$$(X_$(2)): \
export LIB := $$(CFG_MSVC_LIB_PATH_$$(HOST_$(2)))
$$(TBIN$(1)_T_$(2)_H_$(3))/$(4)$$(X_$(2)): \
export PATH := $$(CFG_MSVC_BINDIR_$$(HOST_$(2))):$$(PATH)
endif
endef
$(foreach host,$(CFG_HOST), \
$(foreach target,$(CFG_TARGET), \
$(foreach crate,$(CRATES), \
$(eval $(call SETUP_LIB_MSVC_ENV_VARS,0,$(target),$(host),$(crate))))))
$(foreach host,$(CFG_HOST), \
$(foreach target,$(CFG_TARGET), \
$(foreach tool,$(TOOLS), \
$(eval $(call SETUP_TOOL_MSVC_ENV_VARS,0,$(target),$(host),$(tool))))))

View File

@ -22,7 +22,8 @@ $(eval $(call RUST_CRATE,coretest))
DEPS_collectionstest :=
$(eval $(call RUST_CRATE,collectionstest))
TEST_TARGET_CRATES = $(filter-out core rustc_unicode,$(TARGET_CRATES)) \
TEST_TARGET_CRATES = $(filter-out core rustc_unicode alloc_system \
alloc_jemalloc,$(TARGET_CRATES)) \
collectionstest coretest
TEST_DOC_CRATES = $(DOC_CRATES)
TEST_HOST_CRATES = $(filter-out rustc_typeck rustc_borrowck rustc_resolve \
@ -95,7 +96,8 @@ ifdef CFG_WINDOWSY_$(1)
$$(if $$(findstring stage3,$$(1)), \
stage3/$$(CFG_LIBDIR_RELATIVE), \
)))))/rustlib/$$(CFG_BUILD)/lib
CFG_RUN_TEST_$(1)=$$(call CFG_RUN_$(1),$$(call CFG_TESTLIB_$(1),$$(1),$$(4)),$$(1))
CFG_RUN_TEST_$(1)=$$(TARGET_RPATH_VAR$$(2)_T_$$(3)_H_$$(4)) \
$$(call CFG_RUN_$(1),$$(call CFG_TESTLIB_$(1),$$(1),$$(4)),$$(1))
endif
# Run the compiletest runner itself under valgrind
@ -267,9 +269,10 @@ tidy-basic:
.PHONY: tidy-binaries
tidy-binaries:
@$(call E, check: binaries)
$(Q)find $(S)src -type f -perm +a+x \
$(Q)find $(S)src -type f \
\( -perm -u+x -or -perm -g+x -or -perm -o+x \) \
-not -name '*.rs' -and -not -name '*.py' \
-and -not -name '*.sh' \
-and -not -name '*.sh' -and -not -name '*.pp' \
| grep '^$(S)src/jemalloc' -v \
| grep '^$(S)src/libuv' -v \
| grep '^$(S)src/llvm' -v \
@ -596,6 +599,10 @@ CTEST_DISABLE_debuginfo-gdb =
CTEST_DISABLE_debuginfo-lldb = "lldb tests are disabled on android"
endif
ifeq ($(findstring msvc,$(CFG_TARGET)),msvc)
CTEST_DISABLE_debuginfo-gdb = "gdb tests are disabled on MSVC"
endif
# CTEST_DISABLE_NONSELFHOST_$(TEST_GROUP), if set, will cause that
# test group to be disabled *unless* the target is able to build a
# compiler (i.e. when the target triple is in the set of of host
@ -1049,7 +1056,8 @@ $(3)/test/run-make/%-$(1)-T-$(2)-H-$(3).ok: \
$$(MAKE) \
$$(HBIN$(1)_H_$(3))/rustc$$(X_$(3)) \
$(3)/test/run-make/$$* \
"$$(CC_$(3)) $$(CFG_GCCISH_CFLAGS_$(3))" \
$$(CC_$(3)) \
"$$(CFG_GCCISH_CFLAGS_$(3))" \
$$(HBIN$(1)_H_$(3))/rustdoc$$(X_$(3)) \
"$$(TESTNAME)" \
$$(LD_LIBRARY_PATH_ENV_NAME$(1)_T_$(2)_H_$(3)) \

View File

@ -19,6 +19,7 @@
#![feature(str_char)]
#![feature(test)]
#![feature(vec_push_all)]
#![feature(path_components_peek)]
#![deny(warnings)]
@ -177,7 +178,7 @@ pub fn log_config(config: &Config) {
logv(c, format!("filter: {}",
opt_str(&config.filter
.as_ref()
.map(|re| re.to_string()))));
.map(|re| re.to_owned()))));
logv(c, format!("runtool: {}", opt_str(&config.runtool)));
logv(c, format!("host-rustcflags: {}",
opt_str(&config.host_rustcflags)));
@ -204,19 +205,16 @@ pub fn opt_str<'a>(maybestr: &'a Option<String>) -> &'a str {
pub fn opt_str2(maybestr: Option<String>) -> String {
match maybestr {
None => "(none)".to_string(),
None => "(none)".to_owned(),
Some(s) => s,
}
}
pub fn run_tests(config: &Config) {
if config.target.contains("android") {
match config.mode {
DebugInfoGdb => {
println!("{} debug-info test uses tcp 5039 port.\
please reserve it", config.target);
}
_ =>{}
if let DebugInfoGdb = config.mode {
println!("{} debug-info test uses tcp 5039 port.\
please reserve it", config.target);
}
// android debug-info test uses remote debugger
@ -288,10 +286,10 @@ pub fn is_test(config: &Config, testfile: &Path) -> bool {
// Pretty-printer does not work with .rc files yet
let valid_extensions =
match config.mode {
Pretty => vec!(".rs".to_string()),
_ => vec!(".rc".to_string(), ".rs".to_string())
Pretty => vec!(".rs".to_owned()),
_ => vec!(".rc".to_owned(), ".rs".to_owned())
};
let invalid_prefixes = vec!(".".to_string(), "#".to_string(), "~".to_string());
let invalid_prefixes = vec!(".".to_owned(), "#".to_owned(), "~".to_owned());
let name = testfile.file_name().unwrap().to_str().unwrap();
let mut valid = false;
@ -363,7 +361,7 @@ fn extract_gdb_version(full_version_line: Option<String>) -> Option<String> {
full_version_line.char_at(pos + 3).is_digit(10) {
continue
}
return Some(full_version_line[pos..pos+3].to_string());
return Some(full_version_line[pos..pos+3].to_owned());
}
println!("Could not extract GDB version from line '{}'",
full_version_line);
@ -385,9 +383,8 @@ fn extract_lldb_version(full_version_line: Option<String>) -> Option<String> {
// We are only interested in the major version number, so this function
// will return `Some("179")` and `Some("300")` respectively.
match full_version_line {
Some(ref full_version_line)
if !full_version_line.trim().is_empty() => {
if let Some(ref full_version_line) = full_version_line {
if !full_version_line.trim().is_empty() {
let full_version_line = full_version_line.trim();
for (pos, l) in full_version_line.char_indices() {
@ -409,8 +406,7 @@ fn extract_lldb_version(full_version_line: Option<String>) -> Option<String> {
}
println!("Could not extract LLDB version from line '{}'",
full_version_line);
None
},
_ => None
}
}
None
}

View File

@ -76,7 +76,7 @@ fn parse_expected(last_nonfollow_error: Option<usize>,
let letters = line[kind_start..].chars();
let msg = letters.skip_while(|c| c.is_whitespace())
.skip_while(|c| !c.is_whitespace())
.collect::<String>().trim().to_string();
.collect::<String>().trim().to_owned();
let (which, line) = if follow {
assert!(adjusts == 0, "use either //~| or //~^, not both.");

View File

@ -67,10 +67,9 @@ pub fn load_props(testfile: &Path) -> TestProps {
let mut pretty_compare_only = false;
let mut forbid_output = Vec::new();
iter_header(testfile, &mut |ln| {
match parse_error_pattern(ln) {
Some(ep) => error_patterns.push(ep),
None => ()
};
if let Some(ep) = parse_error_pattern(ln) {
error_patterns.push(ep);
}
if compile_flags.is_none() {
compile_flags = parse_compile_flags(ln);
@ -108,24 +107,20 @@ pub fn load_props(testfile: &Path) -> TestProps {
pretty_compare_only = parse_pretty_compare_only(ln);
}
match parse_aux_build(ln) {
Some(ab) => { aux_builds.push(ab); }
None => {}
if let Some(ab) = parse_aux_build(ln) {
aux_builds.push(ab);
}
match parse_exec_env(ln) {
Some(ee) => { exec_env.push(ee); }
None => {}
if let Some(ee) = parse_exec_env(ln) {
exec_env.push(ee);
}
match parse_check_line(ln) {
Some(cl) => check_lines.push(cl),
None => ()
};
if let Some(cl) = parse_check_line(ln) {
check_lines.push(cl);
}
match parse_forbid_output(ln) {
Some(of) => forbid_output.push(of),
None => (),
if let Some(of) = parse_forbid_output(ln) {
forbid_output.push(of);
}
true
@ -134,8 +129,8 @@ pub fn load_props(testfile: &Path) -> TestProps {
for key in vec!["RUST_TEST_NOCAPTURE", "RUST_TEST_THREADS"] {
match env::var(key) {
Ok(val) =>
if exec_env.iter().find(|&&(ref x, _)| *x == key.to_string()).is_none() {
exec_env.push((key.to_string(), val))
if exec_env.iter().find(|&&(ref x, _)| *x == key).is_none() {
exec_env.push((key.to_owned(), val))
},
Err(..) => {}
}
@ -153,7 +148,7 @@ pub fn load_props(testfile: &Path) -> TestProps {
check_stdout: check_stdout,
no_prefer_dynamic: no_prefer_dynamic,
pretty_expanded: pretty_expanded,
pretty_mode: pretty_mode.unwrap_or("normal".to_string()),
pretty_mode: pretty_mode.unwrap_or("normal".to_owned()),
pretty_compare_only: pretty_compare_only,
forbid_output: forbid_output,
}
@ -182,22 +177,21 @@ pub fn is_test_ignored(config: &Config, testfile: &Path) -> bool {
return true;
}
match config.gdb_version {
Some(ref actual_version) => {
if line.contains("min-gdb-version") {
let min_version = line.trim()
.split(' ')
.last()
.expect("Malformed GDB version directive");
// Ignore if actual version is smaller the minimum required
// version
gdb_version_to_int(actual_version) <
gdb_version_to_int(min_version)
} else {
false
}
if let Some(ref actual_version) = config.gdb_version {
if line.contains("min-gdb-version") {
let min_version = line.trim()
.split(' ')
.last()
.expect("Malformed GDB version directive");
// Ignore if actual version is smaller the minimum required
// version
gdb_version_to_int(actual_version) <
gdb_version_to_int(min_version)
} else {
false
}
None => false
} else {
false
}
}
@ -210,22 +204,21 @@ pub fn is_test_ignored(config: &Config, testfile: &Path) -> bool {
return true;
}
match config.lldb_version {
Some(ref actual_version) => {
if line.contains("min-lldb-version") {
let min_version = line.trim()
.split(' ')
.last()
.expect("Malformed lldb version directive");
// Ignore if actual version is smaller the minimum required
// version
lldb_version_to_int(actual_version) <
lldb_version_to_int(min_version)
} else {
false
}
if let Some(ref actual_version) = config.lldb_version {
if line.contains("min-lldb-version") {
let min_version = line.trim()
.split(' ')
.last()
.expect("Malformed lldb version directive");
// Ignore if actual version is smaller the minimum required
// version
lldb_version_to_int(actual_version) <
lldb_version_to_int(min_version)
} else {
false
}
None => false
} else {
false
}
}
@ -316,11 +309,11 @@ fn parse_exec_env(line: &str) -> Option<(String, String)> {
// nv is either FOO or FOO=BAR
let mut strs: Vec<String> = nv
.splitn(2, '=')
.map(|s| s.to_string())
.map(str::to_owned)
.collect();
match strs.len() {
1 => (strs.pop().unwrap(), "".to_string()),
1 => (strs.pop().unwrap(), "".to_owned()),
2 => {
let end = strs.pop().unwrap();
(strs.pop().unwrap(), end)
@ -331,33 +324,31 @@ fn parse_exec_env(line: &str) -> Option<(String, String)> {
}
fn parse_pp_exact(line: &str, testfile: &Path) -> Option<PathBuf> {
match parse_name_value_directive(line, "pp-exact") {
Some(s) => Some(PathBuf::from(&s)),
None => {
if let Some(s) = parse_name_value_directive(line, "pp-exact") {
Some(PathBuf::from(&s))
} else {
if parse_name_directive(line, "pp-exact") {
testfile.file_name().map(|s| PathBuf::from(s))
testfile.file_name().map(PathBuf::from)
} else {
None
}
}
}
}
fn parse_name_directive(line: &str, directive: &str) -> bool {
// This 'no-' rule is a quick hack to allow pretty-expanded and no-pretty-expanded to coexist
line.contains(directive) && !line.contains(&("no-".to_string() + directive))
line.contains(directive) && !line.contains(&("no-".to_owned() + directive))
}
pub fn parse_name_value_directive(line: &str, directive: &str)
-> Option<String> {
let keycolon = format!("{}:", directive);
match line.find(&keycolon) {
Some(colon) => {
let value = line[(colon + keycolon.len()) .. line.len()].to_string();
debug!("{}: {}", directive, value);
Some(value)
}
None => None
if let Some(colon) = line.find(&keycolon) {
let value = line[(colon + keycolon.len()) .. line.len()].to_owned();
debug!("{}: {}", directive, value);
Some(value)
} else {
None
}
}

View File

@ -17,17 +17,15 @@ fn add_target_env(cmd: &mut Command, lib_path: &str, aux_path: Option<&str>) {
// Need to be sure to put both the lib_path and the aux path in the dylib
// search path for the child.
let mut path = DynamicLibrary::search_path();
match aux_path {
Some(p) => path.insert(0, PathBuf::from(p)),
None => {}
if let Some(p) = aux_path {
path.insert(0, PathBuf::from(p))
}
path.insert(0, PathBuf::from(lib_path));
// Add the new dylib search path var
let var = DynamicLibrary::envvar();
let newpath = DynamicLibrary::create_path(&path);
let newpath = newpath.to_str().unwrap().to_string();
cmd.env(var, &newpath);
cmd.env(var, newpath);
}
pub struct Result {pub status: ExitStatus, pub out: String, pub err: String}

View File

@ -25,7 +25,7 @@ use std::fs::{self, File};
use std::io::BufReader;
use std::io::prelude::*;
use std::net::TcpStream;
use std::path::{Path, PathBuf};
use std::path::{Path, PathBuf, Component};
use std::process::{Command, Output, ExitStatus};
pub fn run(config: Config, testfile: &Path) {
@ -165,9 +165,9 @@ fn run_valgrind_test(config: &Config, props: &TestProps, testfile: &Path) {
fn run_pretty_test(config: &Config, props: &TestProps, testfile: &Path) {
if props.pp_exact.is_some() {
logv(config, "testing for exact pretty-printing".to_string());
logv(config, "testing for exact pretty-printing".to_owned());
} else {
logv(config, "testing for converging pretty-printing".to_string());
logv(config, "testing for converging pretty-printing".to_owned());
}
let rounds =
@ -183,7 +183,7 @@ fn run_pretty_test(config: &Config, props: &TestProps, testfile: &Path) {
let proc_res = print_source(config,
props,
testfile,
srcs[round].to_string(),
srcs[round].to_owned(),
&props.pretty_mode);
if !proc_res.status.success() {
@ -209,9 +209,9 @@ fn run_pretty_test(config: &Config, props: &TestProps, testfile: &Path) {
if props.pp_exact.is_some() {
// Now we have to care about line endings
let cr = "\r".to_string();
actual = actual.replace(&cr, "").to_string();
expected = expected.replace(&cr, "").to_string();
let cr = "\r".to_owned();
actual = actual.replace(&cr, "").to_owned();
expected = expected.replace(&cr, "").to_owned();
}
compare_source(&expected, &actual);
@ -253,7 +253,7 @@ fn run_pretty_test(config: &Config, props: &TestProps, testfile: &Path) {
make_pp_args(config,
props,
testfile,
pretty_type.to_string()),
pretty_type.to_owned()),
props.exec_env.clone(),
&config.compile_lib_path,
Some(aux_dir.to_str().unwrap()),
@ -266,17 +266,17 @@ fn run_pretty_test(config: &Config, props: &TestProps, testfile: &Path) {
pretty_type: String) -> ProcArgs {
let aux_dir = aux_output_dir_name(config, testfile);
// FIXME (#9639): This needs to handle non-utf8 paths
let mut args = vec!("-".to_string(),
"-Zunstable-options".to_string(),
"--pretty".to_string(),
let mut args = vec!("-".to_owned(),
"-Zunstable-options".to_owned(),
"--unpretty".to_owned(),
pretty_type,
format!("--target={}", config.target),
"-L".to_string(),
aux_dir.to_str().unwrap().to_string());
"-L".to_owned(),
aux_dir.to_str().unwrap().to_owned());
args.extend(split_maybe_args(&config.target_rustcflags));
args.extend(split_maybe_args(&props.compile_flags));
return ProcArgs {
prog: config.rustc_path.to_str().unwrap().to_string(),
prog: config.rustc_path.to_str().unwrap().to_owned(),
args: args,
};
}
@ -313,19 +313,18 @@ actual:\n\
&*config.target
};
// FIXME (#9639): This needs to handle non-utf8 paths
let mut args = vec!("-".to_string(),
"-Zno-trans".to_string(),
"--crate-type=lib".to_string(),
let mut args = vec!("-".to_owned(),
"-Zno-trans".to_owned(),
format!("--target={}", target),
"-L".to_string(),
config.build_base.to_str().unwrap().to_string(),
"-L".to_string(),
aux_dir.to_str().unwrap().to_string());
"-L".to_owned(),
config.build_base.to_str().unwrap().to_owned(),
"-L".to_owned(),
aux_dir.to_str().unwrap().to_owned());
args.extend(split_maybe_args(&config.target_rustcflags));
args.extend(split_maybe_args(&props.compile_flags));
// FIXME (#9639): This needs to handle non-utf8 paths
return ProcArgs {
prog: config.rustc_path.to_str().unwrap().to_string(),
prog: config.rustc_path.to_str().unwrap().to_owned(),
args: args,
};
}
@ -388,24 +387,24 @@ fn run_debuginfo_gdb_test(config: &Config, props: &TestProps, testfile: &Path) {
&config.adb_path,
None,
&[
"push".to_string(),
exe_file.to_str().unwrap().to_string(),
"push".to_owned(),
exe_file.to_str().unwrap().to_owned(),
config.adb_test_dir.clone()
],
vec!(("".to_string(), "".to_string())),
Some("".to_string()))
vec!(("".to_owned(), "".to_owned())),
Some("".to_owned()))
.expect(&format!("failed to exec `{:?}`", config.adb_path));
procsrv::run("",
&config.adb_path,
None,
&[
"forward".to_string(),
"tcp:5039".to_string(),
"tcp:5039".to_string()
"forward".to_owned(),
"tcp:5039".to_owned(),
"tcp:5039".to_owned()
],
vec!(("".to_string(), "".to_string())),
Some("".to_string()))
vec!(("".to_owned(), "".to_owned())),
Some("".to_owned()))
.expect(&format!("failed to exec `{:?}`", config.adb_path));
let adb_arg = format!("export LD_LIBRARY_PATH={}; \
@ -422,12 +421,12 @@ fn run_debuginfo_gdb_test(config: &Config, props: &TestProps, testfile: &Path) {
,
None,
&[
"shell".to_string(),
"shell".to_owned(),
adb_arg.clone()
],
vec!(("".to_string(),
"".to_string())),
Some("".to_string()))
vec!(("".to_owned(),
"".to_owned())),
Some("".to_owned()))
.expect(&format!("failed to exec `{:?}`", config.adb_path));
loop {
//waiting 1 second for gdbserver start
@ -438,16 +437,16 @@ fn run_debuginfo_gdb_test(config: &Config, props: &TestProps, testfile: &Path) {
}
let tool_path = match config.android_cross_path.to_str() {
Some(x) => x.to_string(),
Some(x) => x.to_owned(),
None => fatal("cannot find android cross path")
};
let debugger_script = make_out_name(config, testfile, "debugger.script");
// FIXME (#9639): This needs to handle non-utf8 paths
let debugger_opts =
vec!("-quiet".to_string(),
"-batch".to_string(),
"-nx".to_string(),
vec!("-quiet".to_owned(),
"-batch".to_owned(),
"-nx".to_owned(),
format!("-command={}", debugger_script.to_str().unwrap()));
let mut gdb_path = tool_path;
@ -460,7 +459,7 @@ fn run_debuginfo_gdb_test(config: &Config, props: &TestProps, testfile: &Path) {
&gdb_path,
None,
&debugger_opts,
vec!(("".to_string(), "".to_string())),
vec!(("".to_owned(), "".to_owned())),
None)
.expect(&format!("failed to exec `{:?}`", gdb_path));
let cmdline = {
@ -489,7 +488,7 @@ fn run_debuginfo_gdb_test(config: &Config, props: &TestProps, testfile: &Path) {
let rust_pp_module_abs_path = rust_src_root.join(rust_pp_module_rel_path)
.to_str()
.unwrap()
.to_string();
.to_owned();
// write debugger script
let mut script_str = String::with_capacity(2048);
script_str.push_str(&format!("set charset {}\n", charset()));
@ -555,17 +554,17 @@ fn run_debuginfo_gdb_test(config: &Config, props: &TestProps, testfile: &Path) {
// FIXME (#9639): This needs to handle non-utf8 paths
let debugger_opts =
vec!("-quiet".to_string(),
"-batch".to_string(),
"-nx".to_string(),
vec!("-quiet".to_owned(),
"-batch".to_owned(),
"-nx".to_owned(),
format!("-command={}", debugger_script.to_str().unwrap()));
let proc_args = ProcArgs {
prog: debugger().to_string(),
prog: debugger().to_owned(),
args: debugger_opts,
};
let environment = vec![("PYTHONPATH".to_string(), rust_pp_module_abs_path)];
let environment = vec![("PYTHONPATH".to_owned(), rust_pp_module_abs_path)];
debugger_run_result = compose_and_run(config,
testfile,
@ -651,7 +650,7 @@ fn run_debuginfo_lldb_test(config: &Config, props: &TestProps, testfile: &Path)
let rust_pp_module_abs_path = rust_src_root.join(rust_pp_module_rel_path)
.to_str()
.unwrap()
.to_string();
.to_owned();
script_str.push_str(&format!("command script import {}\n",
&rust_pp_module_abs_path[..])[..]);
@ -791,9 +790,9 @@ fn cleanup_debug_info_options(options: &Option<String>) -> Option<String> {
// Remove options that are either unwanted (-O) or may lead to duplicates due to RUSTFLAGS.
let options_to_remove = [
"-O".to_string(),
"-g".to_string(),
"--debuginfo".to_string()
"-O".to_owned(),
"-g".to_owned(),
"--debuginfo".to_owned()
];
let new_options =
split_maybe_args(options).into_iter()
@ -813,7 +812,7 @@ fn check_debugger_output(debugger_run_result: &ProcRes, check_lines: &[String])
s
.trim()
.split("[...]")
.map(|x| x.to_string())
.map(str::to_owned)
.collect()
}).collect();
// check if each line in props.check_lines appears in the
@ -953,6 +952,9 @@ fn check_expected_errors(expected_errors: Vec<errors::ExpectedError>,
// filename:line1:col1: line2:col2: *warning:* msg
// where line1:col1: is the starting point, line2:col2:
// is the ending point, and * represents ANSI color codes.
//
// This pattern is ambiguous on windows, because filename may contain
// a colon, so any path prefix must be detected and removed first.
for line in proc_res.stderr.lines() {
let mut was_expected = false;
let mut prev = 0;
@ -1007,7 +1009,16 @@ fn check_expected_errors(expected_errors: Vec<errors::ExpectedError>,
}
}
fn is_compiler_error_or_warning(line: &str) -> bool {
fn is_compiler_error_or_warning(mut line: &str) -> bool {
// Remove initial prefix which may contain a colon
let mut components = Path::new(line).components();
if let Some(Component::Prefix(_)) = components.peek() {
components.next();
}
// Safe as path was originally constructed from a &str ^
line = components.as_path().to_str().unwrap();
let mut i = 0;
return
scan_until_char(line, ':', &mut i) &&
@ -1128,8 +1139,8 @@ fn compile_test(config: &Config, props: &TestProps,
testfile: &Path) -> ProcRes {
let aux_dir = aux_output_dir_name(config, testfile);
// FIXME (#9639): This needs to handle non-utf8 paths
let link_args = vec!("-L".to_string(),
aux_dir.to_str().unwrap().to_string());
let link_args = vec!("-L".to_owned(),
aux_dir.to_str().unwrap().to_owned());
let args = make_compile_args(config,
props,
link_args,
@ -1143,14 +1154,14 @@ fn document(config: &Config, props: &TestProps,
let out_dir = output_base_name(config, testfile);
let _ = fs::remove_dir_all(&out_dir);
ensure_dir(&out_dir);
let mut args = vec!["-L".to_string(),
aux_dir.to_str().unwrap().to_string(),
"-o".to_string(),
out_dir.to_str().unwrap().to_string(),
testfile.to_str().unwrap().to_string()];
let mut args = vec!["-L".to_owned(),
aux_dir.to_str().unwrap().to_owned(),
"-o".to_owned(),
out_dir.to_str().unwrap().to_owned(),
testfile.to_str().unwrap().to_owned()];
args.extend(split_maybe_args(&props.compile_flags));
let args = ProcArgs {
prog: config.rustdoc_path.to_str().unwrap().to_string(),
prog: config.rustdoc_path.to_str().unwrap().to_owned(),
args: args,
};
(compose_and_run_compiler(config, props, testfile, args, None), out_dir)
@ -1189,8 +1200,8 @@ fn compose_and_run_compiler(config: &Config, props: &TestProps,
let aux_dir = aux_output_dir_name(config, testfile);
// FIXME (#9639): This needs to handle non-utf8 paths
let extra_link_args = vec!["-L".to_string(),
aux_dir.to_str().unwrap().to_string()];
let extra_link_args = vec!["-L".to_owned(),
aux_dir.to_str().unwrap().to_owned()];
for rel_ab in &props.aux_builds {
let abs_ab = config.aux_base.join(rel_ab);
@ -1208,9 +1219,9 @@ fn compose_and_run_compiler(config: &Config, props: &TestProps,
// however, that if the library is built with `force_host` then it's
// ok to be a dylib as the host should always support dylibs.
if config.target.contains("musl") && !aux_props.force_host {
vec!("--crate-type=lib".to_string())
vec!("--crate-type=lib".to_owned())
} else {
vec!("--crate-type=dylib".to_string())
vec!("--crate-type=dylib".to_owned())
}
};
crate_type.extend(extra_link_args.clone());
@ -1290,26 +1301,26 @@ fn make_compile_args<F>(config: &Config,
&*config.target
};
// FIXME (#9639): This needs to handle non-utf8 paths
let mut args = vec!(testfile.to_str().unwrap().to_string(),
"-L".to_string(),
config.build_base.to_str().unwrap().to_string(),
let mut args = vec!(testfile.to_str().unwrap().to_owned(),
"-L".to_owned(),
config.build_base.to_str().unwrap().to_owned(),
format!("--target={}", target));
args.push_all(&extras);
if !props.no_prefer_dynamic {
args.push("-C".to_string());
args.push("prefer-dynamic".to_string());
args.push("-C".to_owned());
args.push("prefer-dynamic".to_owned());
}
let path = match xform_file {
TargetLocation::ThisFile(path) => {
args.push("-o".to_string());
args.push("-o".to_owned());
path
}
TargetLocation::ThisDirectory(path) => {
args.push("--out-dir".to_string());
args.push("--out-dir".to_owned());
path
}
};
args.push(path.to_str().unwrap().to_string());
args.push(path.to_str().unwrap().to_owned());
if props.force_host {
args.extend(split_maybe_args(&config.host_rustcflags));
} else {
@ -1317,7 +1328,7 @@ fn make_compile_args<F>(config: &Config,
}
args.extend(split_maybe_args(&props.compile_flags));
return ProcArgs {
prog: config.rustc_path.to_str().unwrap().to_string(),
prog: config.rustc_path.to_str().unwrap().to_owned(),
args: args,
};
}
@ -1347,7 +1358,7 @@ fn make_run_args(config: &Config, props: &TestProps, testfile: &Path)
let exe_file = make_exe_name(config, testfile);
// FIXME (#9639): This needs to handle non-utf8 paths
args.push(exe_file.to_str().unwrap().to_string());
args.push(exe_file.to_str().unwrap().to_owned());
// Add the arguments in the run_flags directive
args.extend(split_maybe_args(&props.run_flags));
@ -1368,7 +1379,7 @@ fn split_maybe_args(argstr: &Option<String>) -> Vec<String> {
if s.chars().all(|c| c.is_whitespace()) {
None
} else {
Some(s.to_string())
Some(s.to_owned())
}
}).collect()
}
@ -1503,7 +1514,7 @@ fn _arm_exec_compiled_test(config: &Config,
// get bare program string
let mut tvec: Vec<String> = args.prog
.split('/')
.map(|ts| ts.to_string())
.map(str::to_owned)
.collect();
let prog_short = tvec.pop().unwrap();
@ -1512,12 +1523,12 @@ fn _arm_exec_compiled_test(config: &Config,
&config.adb_path,
None,
&[
"push".to_string(),
"push".to_owned(),
args.prog.clone(),
config.adb_test_dir.clone()
],
vec!(("".to_string(), "".to_string())),
Some("".to_string()))
vec!(("".to_owned(), "".to_owned())),
Some("".to_owned()))
.expect(&format!("failed to exec `{}`", config.adb_path));
if config.verbose {
@ -1533,7 +1544,7 @@ fn _arm_exec_compiled_test(config: &Config,
let mut runargs = Vec::new();
// run test via adb_run_wrapper
runargs.push("shell".to_string());
runargs.push("shell".to_owned());
for (key, val) in env {
runargs.push(format!("{}={}", key, val));
}
@ -1542,19 +1553,19 @@ fn _arm_exec_compiled_test(config: &Config,
runargs.push(format!("{}", prog_short));
for tv in &args.args {
runargs.push(tv.to_string());
runargs.push(tv.to_owned());
}
procsrv::run("",
&config.adb_path,
None,
&runargs,
vec!(("".to_string(), "".to_string())), Some("".to_string()))
vec!(("".to_owned(), "".to_owned())), Some("".to_owned()))
.expect(&format!("failed to exec `{}`", config.adb_path));
// get exitcode of result
runargs = Vec::new();
runargs.push("shell".to_string());
runargs.push("cat".to_string());
runargs.push("shell".to_owned());
runargs.push("cat".to_owned());
runargs.push(format!("{}/{}.exitcode", config.adb_test_dir, prog_short));
let procsrv::Result{ out: exitcode_out, err: _, status: _ } =
@ -1562,8 +1573,8 @@ fn _arm_exec_compiled_test(config: &Config,
&config.adb_path,
None,
&runargs,
vec!(("".to_string(), "".to_string())),
Some("".to_string()))
vec!(("".to_owned(), "".to_owned())),
Some("".to_owned()))
.expect(&format!("failed to exec `{}`", config.adb_path));
let mut exitcode: i32 = 0;
@ -1577,8 +1588,8 @@ fn _arm_exec_compiled_test(config: &Config,
// get stdout of result
runargs = Vec::new();
runargs.push("shell".to_string());
runargs.push("cat".to_string());
runargs.push("shell".to_owned());
runargs.push("cat".to_owned());
runargs.push(format!("{}/{}.stdout", config.adb_test_dir, prog_short));
let procsrv::Result{ out: stdout_out, err: _, status: _ } =
@ -1586,14 +1597,14 @@ fn _arm_exec_compiled_test(config: &Config,
&config.adb_path,
None,
&runargs,
vec!(("".to_string(), "".to_string())),
Some("".to_string()))
vec!(("".to_owned(), "".to_owned())),
Some("".to_owned()))
.expect(&format!("failed to exec `{}`", config.adb_path));
// get stderr of result
runargs = Vec::new();
runargs.push("shell".to_string());
runargs.push("cat".to_string());
runargs.push("shell".to_owned());
runargs.push("cat".to_owned());
runargs.push(format!("{}/{}.stderr", config.adb_test_dir, prog_short));
let procsrv::Result{ out: stderr_out, err: _, status: _ } =
@ -1601,8 +1612,8 @@ fn _arm_exec_compiled_test(config: &Config,
&config.adb_path,
None,
&runargs,
vec!(("".to_string(), "".to_string())),
Some("".to_string()))
vec!(("".to_owned(), "".to_owned())),
Some("".to_owned()))
.expect(&format!("failed to exec `{}`", config.adb_path));
dump_output(config,
@ -1630,15 +1641,15 @@ fn _arm_push_aux_shared_library(config: &Config, testfile: &Path) {
&config.adb_path,
None,
&[
"push".to_string(),
"push".to_owned(),
file.to_str()
.unwrap()
.to_string(),
config.adb_test_dir.to_string(),
.to_owned(),
config.adb_test_dir.to_owned(),
],
vec!(("".to_string(),
"".to_string())),
Some("".to_string()))
vec!(("".to_owned(),
"".to_owned())),
Some("".to_owned()))
.expect(&format!("failed to exec `{}`", config.adb_path));
if config.verbose {
@ -1656,10 +1667,10 @@ fn compile_test_and_save_ir(config: &Config, props: &TestProps,
testfile: &Path) -> ProcRes {
let aux_dir = aux_output_dir_name(config, testfile);
// FIXME (#9639): This needs to handle non-utf8 paths
let mut link_args = vec!("-L".to_string(),
aux_dir.to_str().unwrap().to_string());
let llvm_args = vec!("--emit=llvm-ir".to_string(),
"--crate-type=lib".to_string());
let mut link_args = vec!("-L".to_owned(),
aux_dir.to_str().unwrap().to_owned());
let llvm_args = vec!("--emit=llvm-ir".to_owned(),
"--crate-type=lib".to_owned());
link_args.extend(llvm_args);
let args = make_compile_args(config,
props,
@ -1676,9 +1687,9 @@ fn check_ir_with_filecheck(config: &Config, testfile: &Path) -> ProcRes {
let prog = config.llvm_bin_path.as_ref().unwrap().join("FileCheck");
let proc_args = ProcArgs {
// FIXME (#9639): This needs to handle non-utf8 paths
prog: prog.to_str().unwrap().to_string(),
prog: prog.to_str().unwrap().to_owned(),
args: vec!(format!("-input-file={}", irfile.to_str().unwrap()),
testfile.to_str().unwrap().to_string())
testfile.to_str().unwrap().to_owned())
};
compose_and_run(config, testfile, proc_args, Vec::new(), "", None, None)
}

View File

@ -73,7 +73,7 @@ pub fn make_new_path(path: &str) -> String {
Ok(curr) => {
format!("{}{}{}", path, path_div(), curr)
}
Err(..) => path.to_string()
Err(..) => path.to_owned()
}
}

View File

@ -1,11 +1,5 @@
# Rust documentations
## Dependencies
[Pandoc](http://johnmacfarlane.net/pandoc/installing.html), a universal
document converter, is required to generate docs as HTML from Rust's
source code.
## Building
To generate all the docs, just run `make docs` from the root of the repository.
@ -26,15 +20,12 @@ To generate an HTML version of a doc from Markdown manually, you can do
something like:
~~~~
pandoc --from=markdown --to=html5 --number-sections -o reference.html reference.md
rustdoc reference.md
~~~~
(`reference.md` being the Rust Reference Manual.)
The syntax for pandoc flavored markdown can be found at:
An overview of how to use the `rustdoc` command is available [in the docs][1].
Further details are available from the command line by with `rustdoc --help`.
- http://johnmacfarlane.net/pandoc/README.html#pandocs-markdown
A nice quick reference (for non-pandoc markdown) is at:
- http://kramdown.gettalong.org/quickref.html
[1]: https://github.com/rust-lang/rust/blob/master/src/doc/trpl/documentation.md

View File

@ -1 +1 @@
<link rel="shortcut icon" href="http://www.rust-lang.org/favicon.ico">
<link rel="shortcut icon" href="https://www.rust-lang.org/favicon.ico">

View File

@ -281,7 +281,7 @@ type_path_tail : '<' type_expr [ ',' type_expr ] + '>'
## Macros
```antlr
expr_macro_rules : "macro_rules" '!' ident '(' macro_rule * ')' ';'
expr_macro_rules : "macro_rules" '!' ident '(' macro_rule * ')' ';'
| "macro_rules" '!' ident '{' macro_rule * '}' ;
macro_rule : '(' matcher * ')' "=>" '(' transcriber * ')' ';' ;
matcher : '(' matcher * ')' | '[' matcher * ']'
@ -306,7 +306,7 @@ transcriber : '(' transcriber * ')' | '[' transcriber * ']'
```antlr
item : vis ? mod_item | fn_item | type_item | struct_item | enum_item
| const_item | static_item | trait_item | impl_item | extern_block ;
| const_item | static_item | trait_item | impl_item | extern_block_item ;
```
### Type Parameters
@ -636,31 +636,31 @@ lambda_expr : '|' ident_list '|' expr ;
### While loops
```antlr
while_expr : [ lifetime ':' ] "while" no_struct_literal_expr '{' block '}' ;
while_expr : [ lifetime ':' ] ? "while" no_struct_literal_expr '{' block '}' ;
```
### Infinite loops
```antlr
loop_expr : [ lifetime ':' ] "loop" '{' block '}';
loop_expr : [ lifetime ':' ] ? "loop" '{' block '}';
```
### Break expressions
```antlr
break_expr : "break" [ lifetime ];
break_expr : "break" [ lifetime ] ?;
```
### Continue expressions
```antlr
continue_expr : "continue" [ lifetime ];
continue_expr : "continue" [ lifetime ] ?;
```
### For expressions
```antlr
for_expr : [ lifetime ':' ] "for" pat "in" no_struct_literal_expr '{' block '}' ;
for_expr : [ lifetime ':' ] ? "for" pat "in" no_struct_literal_expr '{' block '}' ;
```
### If expressions
@ -688,13 +688,12 @@ match_pat : pat [ '|' pat ] * [ "if" expr ] ? ;
```antlr
if_let_expr : "if" "let" pat '=' expr '{' block '}'
else_tail ? ;
else_tail : "else" [ if_expr | if_let_expr | '{' block '}' ] ;
```
### While let loops
```antlr
while_let_expr : "while" "let" pat '=' expr '{' block '}' ;
while_let_expr : [ lifetime ':' ] ? "while" "let" pat '=' expr '{' block '}' ;
```
### Return expressions
@ -754,8 +753,6 @@ return_expr : "return" expr ? ;
```antlr
closure_type := [ 'unsafe' ] [ '<' lifetime-list '>' ] '|' arg-list '|'
[ ':' bound-list ] [ '->' type ]
procedure_type := 'proc' [ '<' lifetime-list '>' ] '(' arg-list ')'
[ ':' bound-list ] [ '->' type ]
lifetime-list := lifetime | lifetime ',' lifetime-list
arg-list := ident ':' type | ident ':' type ',' arg-list
bound-list := bound | bound '+' bound-list

View File

@ -20,13 +20,30 @@ series of small examples.
[rbe]: http://rustbyexample.com/
# The Standard Library
# Language Reference
Rust does not have an exact specification yet, but an effort to describe as much of
the language in as much detail as possible is in [the reference](reference.html).
# Standard Library Reference
We have [API documentation for the entire standard
library](std/index.html). There's a list of crates on the left with more
specific sections, or you can use the search bar at the top to search for
something if you know its name.
# Tools
[Cargo](https://crates.io) is the Rust's package manager providing access to libraries
beyond the standard one, and its website contains lots of good documentation.
[`rustdoc`](book/documentation.html) is the Rust's documentation generator, a tool converting
annotated source code into HTML docs.
A bunch of non-official tools are available, such as [Racer](https://github.com/phildawes/racer)
(code completion engine), or [rustfmt](https://github.com/nrc/rustfmt) (source code formatter),
or text editor plugins.
# Community & Getting Help
If you need help with something, or just want to talk about Rust with others,
@ -54,25 +71,10 @@ There is an active [subreddit](https://reddit.com/r/rust) with lots of
discussion and news about Rust.
There is also a [user forum](https://users.rust-lang.org), for all
user-oriented discussion, and a [developer
user-oriented discussion, and a [developer
forum](https://internals.rust-lang.org/), where the development of Rust
itself is discussed.
# Specification
Rust does not have an exact specification, but an effort to describe as much of
the language in as much detail as possible is in [the reference](reference.html).
# Tools
Rust is still a young language, so there isn't a ton of tooling yet, but the
tools we have are really nice.
[Cargo](https://crates.io) is Rust's package manager, and its website contains
lots of good documentation.
[`rustdoc`](book/documentation.html) is used to generate documentation for Rust code.
# FAQs
There are questions that are asked quite often, so we've made FAQs for them:
@ -95,5 +97,4 @@ languages:
- [Russian](https://github.com/kgv/rust_book_ru)
- [Korean](https://github.com/rust-kr/doc.rust-kr.org)
- [Chinese](https://github.com/KaiserY/rust-book-chinese)
- [Spanish](https://github.com/goyox86/elpr)
- [Spanish](https://goyox86.github.io/elpr)

View File

@ -127,7 +127,7 @@ fundamentally unsynchronized and compilers are free to aggressively optimize
them. In particular, data accesses are free to be reordered by the compiler on
the assumption that the program is single-threaded. The hardware is also free to
propagate the changes made in data accesses to other threads as lazily and
inconsistently as it wants. Mostly critically, data accesses are how data races
inconsistently as it wants. Most critically, data accesses are how data races
happen. Data accesses are very friendly to the hardware and compiler, but as
we've seen they offer *awful* semantics to try to write synchronized code with.
Actually, that's too weak.
@ -210,18 +210,18 @@ use std::sync::atomic::{AtomicBool, Ordering};
use std::thread;
fn main() {
let lock = Arc::new(AtomicBool::new(true)); // value answers "am I locked?"
let lock = Arc::new(AtomicBool::new(false)); // value answers "am I locked?"
// ... distribute lock to threads somehow ...
// Try to acquire the lock by setting it to false
while !lock.compare_and_swap(true, false, Ordering::Acquire) { }
// Try to acquire the lock by setting it to true
while lock.compare_and_swap(false, true, Ordering::Acquire) { }
// broke out of the loop, so we successfully acquired the lock!
// ... scary data accesses ...
// ok we're done, release the lock
lock.store(true, Ordering::Release);
lock.store(false, Ordering::Release);
}
```

View File

@ -22,7 +22,7 @@ Coercion is allowed between the following types:
for all pointer types (including smart pointers like Box and Rc). Unsize is
only implemented automatically, and enables the following transformations:
* `[T, ..n]` => `[T]`
* `[T; n]` => `[T]`
* `T` => `Trait` where `T: Trait`
* `Foo<..., T, ...>` => `Foo<..., U, ...>` where:
* `T: Unsize<U>`

View File

@ -7,7 +7,7 @@ an abstraction over them in a relatively uncontroversial way. Message passing,
green threads, and async APIs are all diverse enough that any abstraction over
them tends to involve trade-offs that we weren't willing to commit to for 1.0.
However the way Rust models concurrency makes it relatively easy design your own
However the way Rust models concurrency makes it relatively easy to design your own
concurrency paradigm as a library and have everyone else's code Just Work
with yours. Just require the right lifetimes and Send and Sync where appropriate
and you're off to the races. Or rather, off to the... not... having... races.

View File

@ -26,13 +26,16 @@ this is totally fine.
For instance, a custom implementation of `Box` might write `Drop` like this:
```rust
#![feature(heap_api, core_intrinsics, unique)]
#![feature(alloc, heap_api, core_intrinsics, unique)]
extern crate alloc;
use std::rt::heap;
use std::ptr::Unique;
use std::intrinsics::drop_in_place;
use std::mem;
use alloc::heap;
struct Box<T>{ ptr: Unique<T> }
impl<T> Drop for Box<T> {
@ -45,22 +48,26 @@ impl<T> Drop for Box<T> {
}
}
}
# fn main() {}
```
and this works fine because when Rust goes to drop the `ptr` field it just sees
a [Unique][] that has no actual `Drop` implementation. Similarly nothing can
a [Unique] that has no actual `Drop` implementation. Similarly nothing can
use-after-free the `ptr` because when drop exits, it becomes inacessible.
However this wouldn't work:
```rust
#![feature(heap_api, core_intrinsics, unique)]
#![feature(alloc, heap_api, core_intrinsics, unique)]
extern crate alloc;
use std::rt::heap;
use std::ptr::Unique;
use std::intrinsics::drop_in_place;
use std::mem;
use alloc::heap;
struct Box<T>{ ptr: Unique<T> }
impl<T> Drop for Box<T> {
@ -87,6 +94,7 @@ impl<T> Drop for SuperBox<T> {
}
}
}
# fn main() {}
```
After we deallocate the `box`'s ptr in SuperBox's destructor, Rust will
@ -120,7 +128,7 @@ enum Link {
will have its inner Box field dropped if and only if an instance stores the
Next variant.
In general this works really nice because you don't need to worry about
In general this works really nicely because you don't need to worry about
adding/removing drops when you refactor your data layout. Still there's
certainly many valid usecases for needing to do trickier things with
destructors.
@ -129,13 +137,16 @@ The classic safe solution to overriding recursive drop and allowing moving out
of Self during `drop` is to use an Option:
```rust
#![feature(heap_api, core_intrinsics, unique)]
#![feature(alloc, heap_api, core_intrinsics, unique)]
extern crate alloc;
use std::rt::heap;
use std::ptr::Unique;
use std::intrinsics::drop_in_place;
use std::mem;
use alloc::heap;
struct Box<T>{ ptr: Unique<T> }
impl<T> Drop for Box<T> {
@ -165,6 +176,7 @@ impl<T> Drop for SuperBox<T> {
}
}
}
# fn main() {}
```
However this has fairly odd semantics: you're saying that a field that *should*

View File

@ -1,7 +1,7 @@
% Drop Flags
The examples in the previous section introduce an interesting problem for Rust.
We have seen that's possible to conditionally initialize, deinitialize, and
We have seen that it's possible to conditionally initialize, deinitialize, and
reinitialize locations of memory totally safely. For Copy types, this isn't
particularly notable since they're just a random pile of bits. However types
with destructors are a different story: Rust needs to know whether to call a

View File

@ -1,7 +1,7 @@
% Drop Check
We have seen how lifetimes provide us some fairly simple rules for ensuring
that never read dangling references. However up to this point we have only ever
that we never read dangling references. However up to this point we have only ever
interacted with the *outlives* relationship in an inclusive manner. That is,
when we talked about `'a: 'b`, it was ok for `'a` to live *exactly* as long as
`'b`. At first glance, this seems to be a meaningless distinction. Nothing ever

View File

@ -85,8 +85,8 @@ support values.
Safe code need not worry about ZSTs, but *unsafe* code must be careful about the
consequence of types with no size. In particular, pointer offsets are no-ops,
and standard allocators (including jemalloc, the one used by default in Rust)
generally consider passing in `0` for the size of an allocation as Undefined
Behaviour.
may return `nullptr` when a zero-sized allocation is requested, which is
indistinguishable from out of memory.

View File

@ -155,7 +155,6 @@ impl<T> Rc<T> {
impl<T> Drop for Rc<T> {
fn drop(&mut self) {
unsafe {
let inner = &mut ;
(*self.ptr).ref_count -= 1;
if (*self.ptr).ref_count == 0 {
// drop the data and then free it

View File

@ -52,7 +52,7 @@ likely desugar to the following:
}
```
Wow. Thats... awful. Lets all take a moment to thank Rust for making this easier.
Wow. That's... awful. Let's all take a moment to thank Rust for making this easier.
Actually passing references to outer scopes will cause Rust to infer
a larger lifetime:

View File

@ -60,8 +60,8 @@ Unlike C, Undefined Behaviour is pretty limited in scope in Rust. All the core
language cares about is preventing the following things:
* Dereferencing null or dangling pointers
* Reading [uninitialized memory][]
* Breaking the [pointer aliasing rules][]
* Reading [uninitialized memory]
* Breaking the [pointer aliasing rules]
* Producing invalid primitive values:
* dangling/null references
* a `bool` that isn't 0 or 1

View File

@ -26,7 +26,7 @@ still consumes a byte of space.
* DSTs, tuples, and tagged unions are not a concept in C and as such are never
FFI safe.
* **If the type would have any [drop flags][], they will still be added**
* **If the type would have any [drop flags], they will still be added**
* This is equivalent to one of `repr(u*)` (see the next section) for enums. The
chosen size is the default enum size for the target platform's C ABI. Note that

View File

@ -36,9 +36,9 @@ struct A {
}
```
will be 32-bit aligned assuming these primitives are aligned to their size.
It will therefore have a size that is a multiple of 32-bits. It will potentially
*really* become:
will be 32-bit aligned on an architecture that aligns these primitives to their
respective sizes. The whole struct will therefore have a size that is a multiple
of 32-bits. It will potentially become:
```rust
struct A {
@ -50,10 +50,10 @@ struct A {
}
```
There is *no indirection* for these types; all data is stored contiguously as
you would expect in C. However with the exception of arrays (which are densely
packed and in-order), the layout of data is not by default specified in Rust.
Given the two following struct definitions:
There is *no indirection* for these types; all data is stored within the struct,
as you would expect in C. However with the exception of arrays (which are
densely packed and in-order), the layout of data is not by default specified in
Rust. Given the two following struct definitions:
```rust
struct A {
@ -62,18 +62,17 @@ struct A {
}
struct B {
x: i32,
a: i32,
b: u64,
}
```
Rust *does* guarantee that two instances of A have their data laid out in
exactly the same way. However Rust *does not* guarantee that an instance of A
has the same field ordering or padding as an instance of B (in practice there's
no particular reason why they wouldn't, other than that its not currently
guaranteed).
exactly the same way. However Rust *does not* currently guarantee that an
instance of A has the same field ordering or padding as an instance of B, though
in practice there's no reason why they wouldn't.
With A and B as written, this is basically nonsensical, but several other
With A and B as written, this point would seem to be pedantic, but several other
features of Rust make it desirable for the language to play with data layout in
complex ways.
@ -133,18 +132,21 @@ struct FooRepr {
}
```
And indeed this is approximately how it would be laid out in general
(modulo the size and position of `tag`). However there are several cases where
such a representation is inefficient. The classic case of this is Rust's
"null pointer optimization". Given a pointer that is known to not be null
(e.g. `&u32`), an enum can *store* a discriminant bit *inside* the pointer
by using null as a special value. The net result is that
`size_of::<Option<&T>>() == size_of::<&T>()`
And indeed this is approximately how it would be laid out in general (modulo the
size and position of `tag`).
There are many types in Rust that are, or contain, "not null" pointers such as
However there are several cases where such a representation is inefficient. The
classic case of this is Rust's "null pointer optimization": an enum consisting
of a single outer unit variant (e.g. `None`) and a (potentially nested) non-
nullable pointer variant (e.g. `&T`) makes the tag unnecessary, because a null
pointer value can safely be interpreted to mean that the unit variant is chosen
instead. The net result is that, for example, `size_of::<Option<&T>>() ==
size_of::<&T>()`.
There are many types in Rust that are, or contain, non-nullable pointers such as
`Box<T>`, `Vec<T>`, `String`, `&T`, and `&mut T`. Similarly, one can imagine
nested enums pooling their tags into a single discriminant, as they are by
definition known to have a limited range of valid values. In principle enums can
definition known to have a limited range of valid values. In principle enums could
use fairly elaborate algorithms to cache bits throughout nested types with
special constrained representations. As such it is *especially* desirable that
we leave enum layout unspecified today.

View File

@ -35,7 +35,7 @@ unchecked contracts:
There is also `#[unsafe_no_drop_flag]`, which is a special case that exists for
historical reasons and is in the process of being phased out. See the section on
[drop flags][] for details.
[drop flags] for details.
Some examples of unsafe functions:
@ -44,7 +44,7 @@ Some examples of unsafe functions:
* `ptr::offset` is an intrinsic that invokes Undefined Behaviour if it is
not "in bounds" as defined by LLVM.
* `mem::transmute` reinterprets some value as having the given type,
bypassing type safety in arbitrary ways. (see [conversions][] for details)
bypassing type safety in arbitrary ways. (see [conversions] for details)
* All FFI functions are `unsafe` because they can do arbitrary things.
C being an obvious culprit, but generally any language can do something
that Rust isn't happy about.
@ -125,7 +125,7 @@ unsafe impl UnsafeOrd for MyType {
But it's probably not the implementation you want.
Rust has traditionally avoided making traits unsafe because it makes Unsafe
pervasive, which is not desirable. Send and Sync are unsafe is because thread
pervasive, which is not desirable. The reason Send and Sync are unsafe is because thread
safety is a *fundamental property* that unsafe code cannot possibly hope to defend
against in the same way it would defend against a bad Ord implementation. The
only way to possibly defend against thread-unsafety would be to *not use

View File

@ -3,15 +3,15 @@
Not everything obeys inherited mutability, though. Some types allow you to
multiply alias a location in memory while mutating it. Unless these types use
synchronization to manage this access, they are absolutely not thread safe. Rust
captures this with through the `Send` and `Sync` traits.
captures this through the `Send` and `Sync` traits.
* A type is Send if it is safe to send it to another thread.
* A type is Sync if it is safe to share between threads (`&T` is Send).
Send and Sync are fundamental to Rust's concurrency story. As such, a
substantial amount of special tooling exists to make them work right. First and
foremost, they're [unsafe traits][]. This means that they are unsafe to
implement, and other unsafe code can that they are correctly
foremost, they're [unsafe traits]. This means that they are unsafe to
implement, and other unsafe code can assume that they are correctly
implemented. Since they're *marker traits* (they have no associated items like
methods), correctly implemented simply means that they have the intrinsic
properties an implementor should have. Incorrectly implementing Send or Sync can

View File

@ -93,8 +93,8 @@ fn main() {
The signature of `overwrite` is clearly valid: it takes mutable references to
two values of the same type, and overwrites one with the other. If `&mut T` was
variant over T, then `&mut &'a str` would be a subtype of `&mut &'static str`,
since `&'a str` is a subtype of `&'static str`. Therefore the lifetime of
variant over T, then `&mut &'static str` would be a subtype of `&mut &'a str`,
since `&'static str` is a subtype of `&'a str`. Therefore the lifetime of
`forever_str` would successfully be "shrunk" down to the shorter lifetime of
`string`, and `overwrite` would be called successfully. `string` would
subsequently be dropped, and `forever_str` would point to freed memory when we

View File

@ -21,7 +21,7 @@ same size. The ways to cause Undefined Behaviour with this are mind boggling.
* No you can't do it
* No you're not special
* Transmuting to a reference without an explicitly provided lifetime
produces an [unbounded lifetime][]
produces an [unbounded lifetime]
`mem::transmute_copy<T, U>` somehow manages to be *even more* wildly unsafe than
this. It copies `size_of<U>` bytes out of an `&T` and interprets them as a `U`.

View File

@ -77,7 +77,7 @@ contain any `Drop` types.
However when working with uninitialized memory you need to be ever-vigilant for
Rust trying to drop values you make like this before they're fully initialized.
Every control path through that variable's scope must initialize the value
before it ends, if has a destructor.
before it ends, if it has a destructor.
*[This includes code panicking](unwinding.html)*.
And that's about it for working with uninitialized memory! Basically nothing

View File

@ -9,7 +9,7 @@ This is perfectly fine because we already have `cap == 0` as our sentinel for no
allocation. We don't even need to handle it specially in almost any code because
we usually need to check if `cap > len` or `len > 0` anyway. The traditional
Rust value to put here is `0x01`. The standard library actually exposes this
as `std::rt::heap::EMPTY`. There are quite a few places where we'll
as `alloc::heap::EMPTY`. There are quite a few places where we'll
want to use `heap::EMPTY` because there's no real allocation to talk about but
`null` would make the compiler do bad things.
@ -20,11 +20,12 @@ the `heap` API anyway, so let's just get that dependency over with.
So:
```rust,ignore
#![feature(heap_api)]
#![feature(alloc, heap_api)]
use std::rt::heap::EMPTY;
use std::mem;
use alloc::heap::EMPTY;
impl<T> Vec<T> {
fn new() -> Self {
assert!(mem::size_of::<T>() != 0, "We're not ready to handle ZSTs");

View File

@ -129,14 +129,16 @@ impl<'a, T> Drop for Drain<'a, T> {
impl<T> Vec<T> {
pub fn drain(&mut self) -> Drain<T> {
// this is a mem::forget safety thing. If Drain is forgotten, we just
// leak the whole Vec's contents. Also we need to do this eventually
// anyway, so why not do it now?
self.len = 0;
unsafe {
let iter = RawValIter::new(&self);
// this is a mem::forget safety thing. If Drain is forgotten, we just
// leak the whole Vec's contents. Also we need to do this *eventually*
// anyway, so why not do it now?
self.len = 0;
Drain {
iter: RawValIter::new(&self),
iter: iter,
vec: PhantomData,
}
}

View File

@ -2,17 +2,16 @@
```rust
#![feature(unique)]
#![feature(heap_api)]
#![feature(alloc, heap_api)]
extern crate alloc;
use std::ptr::{Unique, self};
use std::rt::heap;
use std::mem;
use std::ops::{Deref, DerefMut};
use std::marker::PhantomData;
use alloc::heap;
struct RawVec<T> {
ptr: Unique<T>,
@ -155,13 +154,16 @@ impl<T> Vec<T> {
}
pub fn drain(&mut self) -> Drain<T> {
// this is a mem::forget safety thing. If this is forgotten, we just
// leak the whole Vec's contents. Also we need to do this *eventually*
// anyway, so why not do it now?
self.len = 0;
unsafe {
let iter = RawValIter::new(&self);
// this is a mem::forget safety thing. If Drain is forgotten, we just
// leak the whole Vec's contents. Also we need to do this *eventually*
// anyway, so why not do it now?
self.len = 0;
Drain {
iter: RawValIter::new(&self),
iter: iter,
vec: PhantomData,
}
}

View File

@ -21,12 +21,12 @@ Some things that might be helpful to you though:
# Reference
* [The Rust official site](http://rust-lang.org)
* [The Rust reference](http://doc.rust-lang.org/reference.html)
* [The Rust official site](https://www.rust-lang.org)
* [The Rust reference](https://doc.rust-lang.org/reference.html)
# Docs
* [The standard library](http://doc.rust-lang.org/std/)
* [The standard library](https://doc.rust-lang.org/std/)
<script>
function get_url_fragments() {
@ -58,7 +58,7 @@ function populate_rust_search() {
// #18540, use a single token
var a = document.createElement("a");
a.href = "http://doc.rust-lang.org/core/?search=" + encodeURIComponent(lt);
a.href = "https://doc.rust-lang.org/core/?search=" + encodeURIComponent(lt);
a.textContent = lt;
var search = document.getElementById('core-search');
search.innerHTML = "";

View File

@ -538,8 +538,9 @@ balanced, but they are otherwise not special.
In the matcher, `$` _name_ `:` _designator_ matches the nonterminal in the Rust
syntax named by _designator_. Valid designators are `item`, `block`, `stmt`,
`pat`, `expr`, `ty` (type), `ident`, `path`, `tt` (either side of the `=>`
in macro rules). In the transcriber, the designator is already known, and so
only the name of a matched nonterminal comes after the dollar sign.
in macro rules), and `meta` (contents of an attribute). In the transcriber, the
designator is already known, and so only the name of a matched nonterminal comes
after the dollar sign.
In both the matcher and transcriber, the Kleene star-like operator indicates
repetition. The Kleene star operator consists of `$` and parentheses, optionally
@ -1094,12 +1095,12 @@ typecheck:
# fn my_err(s: &str) -> ! { panic!() }
fn f(i: i32) -> i32 {
if i == 42 {
return 42;
}
else {
my_err("Bad number!");
}
if i == 42 {
return 42;
}
else {
my_err("Bad number!");
}
}
```
@ -1398,9 +1399,9 @@ functions](#generic-functions).
```
trait Seq<T> {
fn len(&self) -> u32;
fn elt_at(&self, n: u32) -> T;
fn iter<F>(&self, F) where F: Fn(T);
fn len(&self) -> u32;
fn elt_at(&self, n: u32) -> T;
fn iter<F>(&self, F) where F: Fn(T);
}
```
@ -1451,7 +1452,7 @@ fn draw_twice<T: Shape>(surface: Surface, sh: T) {
}
```
Traits also define an [trait object](#trait-objects) with the same
Traits also define a [trait object](#trait-objects) with the same
name as the trait. Values of this type are created by coercing from a
pointer of some specific type to a pointer of trait type. For example,
`&T` could be coerced to `&Shape` if `T: Shape` holds (and similarly
@ -1488,19 +1489,41 @@ impl Num for f64 {
let x: f64 = Num::from_i32(42);
```
Traits may inherit from other traits. For example, in
Traits may inherit from other traits. Consider the following example:
```
trait Shape { fn area(&self) -> f64; }
trait Circle : Shape { fn radius(&self) -> f64; }
```
the syntax `Circle : Shape` means that types that implement `Circle` must also
The syntax `Circle : Shape` means that types that implement `Circle` must also
have an implementation for `Shape`. Multiple supertraits are separated by `+`,
`trait Circle : Shape + PartialEq { }`. In an implementation of `Circle` for a
given type `T`, methods can refer to `Shape` methods, since the typechecker
checks that any type with an implementation of `Circle` also has an
implementation of `Shape`.
implementation of `Shape`:
```rust
struct Foo;
trait Shape { fn area(&self) -> f64; }
trait Circle : Shape { fn radius(&self) -> f64; }
# impl Shape for Foo {
# fn area(&self) -> f64 {
# 0.0
# }
# }
impl Circle for Foo {
fn radius(&self) -> f64 {
println!("calling area: {}", self.area());
0.0
}
}
let c = Foo;
c.radius();
```
In type-parameterized functions, methods of the supertrait may be called on
values of subtrait-bound type parameters. Referring to the previous example of
@ -1556,8 +1579,12 @@ impl Shape for Circle {
fn draw(&self, s: Surface) { do_draw_circle(s, *self); }
fn bounding_box(&self) -> BoundingBox {
let r = self.radius;
BoundingBox{x: self.center.x - r, y: self.center.y - r,
width: 2.0 * r, height: 2.0 * r}
BoundingBox {
x: self.center.x - r,
y: self.center.y - r,
width: 2.0 * r,
height: 2.0 * r,
}
}
}
```
@ -1592,10 +1619,10 @@ are written after the `impl` keyword.
```
# trait Seq<T> { fn dummy(&self, _: T) { } }
impl<T> Seq<T> for Vec<T> {
/* ... */
/* ... */
}
impl Seq<bool> for u32 {
/* Treat the integer as a sequence of bits */
/* Treat the integer as a sequence of bits */
}
```
@ -1827,13 +1854,13 @@ An example of attributes:
// A function marked as a unit test
#[test]
fn test_foo() {
/* ... */
/* ... */
}
// A conditionally-compiled module
#[cfg(target_os="linux")]
mod bar {
/* ... */
/* ... */
}
// A lint attribute used to suppress a warning/error
@ -1858,11 +1885,15 @@ type int8_t = i8;
- `no_start` - disable linking to the `native` crate, which specifies the
"start" language item.
- `no_std` - disable linking to the `std` crate.
- `plugin` load a list of named crates as compiler plugins, e.g.
- `plugin` - load a list of named crates as compiler plugins, e.g.
`#![plugin(foo, bar)]`. Optional arguments for each plugin,
i.e. `#![plugin(foo(... args ...))]`, are provided to the plugin's
registrar function. The `plugin` feature gate is required to use
this attribute.
- `recursion_limit` - Sets the maximum depth for potentially
infinitely-recursive compile-time operations like
auto-dereference or macro expansion. The default is
`#![recursion_limit="64"]`.
### Module-only attributes
@ -1901,10 +1932,16 @@ On an `extern` block, the following attributes are interpreted:
name and type. This is feature gated and the exact behavior is
implementation-defined (due to variety of linker invocation syntax).
- `link` - indicate that a native library should be linked to for the
declarations in this block to be linked correctly. `link` supports an optional `kind`
key with three possible values: `dylib`, `static`, and `framework`. See [external blocks](#external-blocks) for more about external blocks. Two
declarations in this block to be linked correctly. `link` supports an optional
`kind` key with three possible values: `dylib`, `static`, and `framework`. See
[external blocks](#external-blocks) for more about external blocks. Two
examples: `#[link(name = "readline")]` and
`#[link(name = "CoreFoundation", kind = "framework")]`.
- `linked_from` - indicates what native library this block of FFI items is
coming from. This attribute is of the form `#[linked_from = "foo"]` where
`foo` is the name of a library in either `#[link]` or a `-l` flag. This
attribute is currently required to export symbols from a Rust dynamic library
on Windows, and it is feature gated behind the `linked_from` feature.
On declarations inside an `extern` block, the following attributes are
interpreted:
@ -2022,25 +2059,31 @@ arbitrarily complex configurations through nesting.
The following configurations must be defined by the implementation:
* `debug_assertions`. Enabled by default when compiling without optimizations.
* `debug_assertions` - Enabled by default when compiling without optimizations.
This can be used to enable extra debugging code in development but not in
production. For example, it controls the behavior of the standard library's
`debug_assert!` macro.
* `target_arch = "..."`. Target CPU architecture, such as `"x86"`, `"x86_64"`
* `target_arch = "..."` - Target CPU architecture, such as `"x86"`, `"x86_64"`
`"mips"`, `"powerpc"`, `"arm"`, or `"aarch64"`.
* `target_endian = "..."`. Endianness of the target CPU, either `"little"` or
* `target_endian = "..."` - Endianness of the target CPU, either `"little"` or
`"big"`.
* `target_family = "..."`. Operating system family of the target, e. g.
* `target_env = ".."` - An option provided by the compiler by default
describing the runtime environment of the target platform. Some examples of
this are `musl` for builds targeting the MUSL libc implementation, `msvc` for
Windows builds targeting MSVC, and `gnu` frequently the rest of the time. This
option may also be blank on some platforms.
* `target_family = "..."` - Operating system family of the target, e. g.
`"unix"` or `"windows"`. The value of this configuration option is defined
as a configuration itself, like `unix` or `windows`.
* `target_os = "..."`. Operating system of the target, examples include
* `target_os = "..."` - Operating system of the target, examples include
`"windows"`, `"macos"`, `"ios"`, `"linux"`, `"android"`, `"freebsd"`, `"dragonfly"`,
`"bitrig"` , `"openbsd"` or `"netbsd"`.
* `target_pointer_width = "..."`. Target pointer width in bits. This is set
* `target_pointer_width = "..."` - Target pointer width in bits. This is set
to `"32"` for targets with 32-bit pointers, and likewise set to `"64"` for
64-bit pointers.
* `unix`. See `target_family`.
* `windows`. See `target_family`.
* `test` - Enabled when compiling the test harness (using the `--test` flag).
* `unix` - See `target_family`.
* `windows` - See `target_family`.
You can also set another attribute based on a `cfg` variable with `cfg_attr`:
@ -2324,9 +2367,6 @@ The currently implemented features of the reference compiler are:
into a Rust program. This capability, especially the signature for the
annotated function, is subject to change.
* `struct_inherit` - Allows using struct inheritance, which is barely
implemented and will probably be removed. Don't use this.
* `struct_variant` - Structural enum variants (those with named fields). It is
currently unknown whether this style of enum variant is as
fully supported as the tuple-forms, and it's not certain
@ -2860,9 +2900,9 @@ An example of an `as` expression:
# fn len(values: &[f64]) -> i32 { 0 }
fn average(values: &[f64]) -> f64 {
let sum: f64 = sum(values);
let size: f64 = len(values) as f64;
sum / size
let sum: f64 = sum(values);
let size: f64 = len(values) as f64;
sum / size
}
```
@ -3161,16 +3201,6 @@ let z = match x { &0 => "zero", _ => "some" };
assert_eq!(y, z);
```
A pattern that's just an identifier, like `Nil` in the previous example, could
either refer to an enum variant that's in scope, or bind a new variable. The
compiler resolves this ambiguity by forbidding variable bindings that occur in
`match` patterns from shadowing names of variants that are in scope. For
example, wherever `List` is in scope, a `match` pattern would not be able to
bind `Nil` as a new name. The compiler interprets a variable pattern `x` as a
binding _only_ if there is no variant named `x` in scope. A convention you can
use to avoid conflicts is simply to name variants with upper-case letters, and
local variables with lower-case letters.
Multiple match patterns may be joined with the `|` operator. A range of values
may be specified with `...`. For example:
@ -3178,9 +3208,9 @@ may be specified with `...`. For example:
# let x = 2;
let message = match x {
0 | 1 => "not many",
2 ... 9 => "a few",
_ => "lots"
0 | 1 => "not many",
2 ... 9 => "a few",
_ => "lots"
};
```
@ -3199,9 +3229,9 @@ may refer to the variables bound within the pattern they follow.
# fn process_other(i: i32) { }
let message = match maybe_digit {
Some(x) if x < 10 => process_digit(x),
Some(x) => process_other(x),
None => panic!()
Some(x) if x < 10 => process_digit(x),
Some(x) => process_other(x),
None => panic!()
};
```
@ -3245,10 +3275,10 @@ An example of a `return` expression:
```
fn max(a: i32, b: i32) -> i32 {
if a > b {
return a;
}
return b;
if a > b {
return a;
}
return b;
}
```
@ -3492,7 +3522,7 @@ An example of a `fn` type:
```
fn add(x: i32, y: i32) -> i32 {
return x + y;
return x + y;
}
let mut x = add(5,7);
@ -3572,19 +3602,19 @@ An example of a trait object:
```
trait Printable {
fn stringify(&self) -> String;
fn stringify(&self) -> String;
}
impl Printable for i32 {
fn stringify(&self) -> String { self.to_string() }
fn stringify(&self) -> String { self.to_string() }
}
fn print(a: Box<Printable>) {
println!("{}", a.stringify());
println!("{}", a.stringify());
}
fn main() {
print(Box::new(10) as Box<Printable>);
print(Box::new(10) as Box<Printable>);
}
```
@ -3599,7 +3629,7 @@ its type parameters are types:
```ignore
fn to_vec<A: Clone>(xs: &[A]) -> Vec<A> {
if xs.is_empty() {
return vec![];
return vec![];
}
let first: A = xs[0].clone();
let mut rest: Vec<A> = to_vec(&xs[1..]);
@ -3619,7 +3649,7 @@ it is an alias for the implementing type. For example, in:
```
trait Printable {
fn make_string(&self) -> String;
fn make_string(&self) -> String;
}
impl Printable for String {
@ -3687,7 +3717,7 @@ sites are:
fn bar(_: i8) { }
fn main() {
bar(128);
bar(128);
}
```

View File

@ -26,7 +26,7 @@ Every guideline has a status:
One purpose of these guidelines is to reach decisions on a number of
cross-cutting API and stylistic choices. Discussion and development of
the guidelines will happen primarily on http://discuss.rust-lang.org/,
the guidelines will happen primarily on https://internals.rust-lang.org/,
using the Guidelines category. Discussion can also occur on the
[guidelines issue tracker](https://github.com/rust-lang/rust-guidelines).

View File

@ -57,7 +57,7 @@ fn write_info(info: &Info) -> Result<(), IoError> {
```
See
[the `result` module documentation](http://static.rust-lang.org/doc/master/std/result/index.html#the-try!-macro)
[the `result` module documentation](https://doc.rust-lang.org/stable/std/result/index.html#the-try!-macro)
for more details.
### The `Result`-`impl` pattern [FIXME]

View File

@ -94,7 +94,7 @@ aspects of the input that are not covered by the contract.
### For obstructions, use `Result`
The
[`Result<T,E>` type](http://static.rust-lang.org/doc/master/std/result/index.html)
[`Result<T,E>` type](https://doc.rust-lang.org/stable/std/result/index.html)
represents either a success (yielding `T`) or failure (yielding `E`). By
returning a `Result`, a function allows its clients to discover and react to
obstructions in a fine-grained way.

View File

@ -124,7 +124,7 @@ that the caller already owns, for example to re-use a buffer:
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize>
```
(From the [Reader trait](http://static.rust-lang.org/doc/master/std/io/trait.Reader.html#tymethod.read).)
(From the [Read trait](https://doc.rust-lang.org/stable/std/io/trait.Read.html#tymethod.read).)
### Consider validating arguments, statically or dynamically. [FIXME: needs RFC]
@ -132,7 +132,7 @@ _Note: this material is closely related to
[library-level guarantees](../../safety/lib-guarantees.md)._
Rust APIs do _not_ generally follow the
[robustness principle](http://en.wikipedia.org/wiki/Robustness_principle): "be
[robustness principle](https://en.wikipedia.org/wiki/Robustness_principle): "be
conservative in what you send; be liberal in what you accept".
Instead, Rust code should _enforce_ the validity of input whenever practical.
@ -147,24 +147,26 @@ Choose an argument type that rules out bad inputs.
For example, prefer
```rust
fn foo(a: ascii::Ascii) { ... }
enum FooMode {
Mode1,
Mode2,
Mode3,
}
fn foo(mode: FooMode) { ... }
```
over
```rust
fn foo(a: u8) { ... }
fn foo(mode2: bool, mode3: bool) {
assert!(!mode2 || !mode3);
...
}
```
Note that
[`ascii::Ascii`](http://static.rust-lang.org/doc/master/std/ascii/struct.Ascii.html)
is a _wrapper_ around `u8` that guarantees the highest bit is zero; see
[newtype patterns](../types/newtype.md) for more details on creating typesafe wrappers.
Static enforcement usually comes at little run-time cost: it pushes the
costs to the boundaries (e.g. when a `u8` is first converted into an
`Ascii`). It also catches bugs early, during compilation, rather than through
run-time failures.
costs to the boundaries. It also catches bugs early, during compilation,
rather than through run-time failures.
On the other hand, some properties are difficult or impossible to
express using types.
@ -177,7 +179,7 @@ downsides:
1. Runtime overhead (unless checking can be done as part of processing the input).
2. Delayed detection of bugs.
3. Introduces failure cases, either via `fail!` or `Result`/`Option` types (see
3. Introduces failure cases, either via `panic!` or `Result`/`Option` types (see
the [error handling guidelines](../../errors/README.md)), which must then be
dealt with by client code.

View File

@ -58,13 +58,13 @@ For modules that themselves have submodules, place the module in a separate
directory (e.g., `bar/mod.rs` for a module `bar`) rather than the same directory.
Note the structure of
[`std::io`](http://doc.rust-lang.org/std/io/). Many of the submodules lack
[`std::io`](https://doc.rust-lang.org/std/io/). Many of the submodules lack
children, like
[`io::fs`](http://doc.rust-lang.org/std/io/fs/)
[`io::fs`](https://doc.rust-lang.org/std/io/fs/)
and
[`io::stdio`](http://doc.rust-lang.org/std/io/stdio/).
[`io::stdio`](https://doc.rust-lang.org/std/io/stdio/).
On the other hand,
[`io::net`](http://doc.rust-lang.org/std/io/net/)
[`io::net`](https://doc.rust-lang.org/std/io/net/)
contains submodules, so it lives in a separate directory:
```
@ -88,7 +88,7 @@ submodules of `io::net` easier to find.
### Consider top-level definitions or reexports. [FIXME: needs RFC]
For modules with submodules,
define or [reexport](http://doc.rust-lang.org/std/io/#reexports) commonly used
define or [reexport](https://doc.rust-lang.org/std/io/#reexports) commonly used
definitions at the top level:
* Functionality relevant to the module itself or to many of its
@ -98,10 +98,10 @@ definitions at the top level:
common definitions.
For example,
[`IoError`](http://doc.rust-lang.org/std/io/struct.IoError.html)
[`IoError`](https://doc.rust-lang.org/std/io/struct.IoError.html)
is defined in `io/mod.rs`, since it pertains to the entirety of `io`,
while
[`TcpStream`](http://doc.rust-lang.org/std/io/net/tcp/struct.TcpStream.html)
[`TcpStream`](https://doc.rust-lang.org/std/io/net/tcp/struct.TcpStream.html)
is defined in `io/net/tcp.rs` and reexported in the `io` module.
### Use internal module hirearchies for organization. [FIXME: needs RFC]
@ -113,11 +113,11 @@ is defined in `io/net/tcp.rs` and reexported in the `io` module.
Internal module hirearchies (i.e., private submodules) may be used to
hide implementation details that are not part of the module's API.
For example, in [`std::io`](http://doc.rust-lang.org/std/io/), `mod mem`
For example, in [`std::io`](https://doc.rust-lang.org/std/io/), `mod mem`
provides implementations for
[`BufReader`](http://doc.rust-lang.org/std/io/struct.BufReader.html)
[`BufReader`](https://doc.rust-lang.org/std/io/struct.BufReader.html)
and
[`BufWriter`](http://doc.rust-lang.org/std/io/struct.BufWriter.html),
[`BufWriter`](https://doc.rust-lang.org/std/io/struct.BufWriter.html),
but these are re-exported in `io/mod.rs` at the top level of the module:
```rust

View File

@ -32,7 +32,7 @@ treatment of ownership, as described below.
In some cases, constructing the final `T` does not require the builder itself to
be consumed. The follow variant on
[`std::io::process::Command`](http://static.rust-lang.org/doc/master/std/io/process/struct.Command.html)
[`std::process::Command`](https://doc.rust-lang.org/stable/std/process/struct.Command.html)
is one example:
```rust

View File

@ -13,7 +13,7 @@ even though some of these abstractions feel like those of a high-level
language. Even then, Rust still allows precise control like a low-level
language would.
[rust]: http://rust-lang.org
[rust]: https://www.rust-lang.org
“The Rust Programming Language” is split into eight sections. This introduction
is the first. After this:
@ -24,7 +24,7 @@ is the first. After this:
* [Syntax and Semantics][ss] - Each bit of Rust, broken down into small chunks.
* [Nightly Rust][nr] - Cutting-edge features that arent in stable builds yet.
* [Glossary][gl] - A reference of terms used in the book.
* [Academic Research][ar] - Literature that influenced Rust.
* [Bibliography][bi] - Background on Rust's influences, papers about Rust.
[gs]: getting-started.html
[lr]: learn-rust.html
@ -32,7 +32,7 @@ is the first. After this:
[ss]: syntax-and-semantics.html
[nr]: nightly-rust.html
[gl]: glossary.html
[ar]: academic-research.html
[bi]: bibliography.html
After reading this introduction, youll want to dive into either Learn Rust
or Syntax and Semantics, depending on your preference: Learn Rust if you

View File

@ -69,4 +69,4 @@
* [Slice Patterns](slice-patterns.md)
* [Associated Constants](associated-constants.md)
* [Glossary](glossary.md)
* [Academic Research](academic-research.md)
* [Bibliography](bibliography.md)

View File

@ -34,16 +34,16 @@ formal `#[link(...)]` attribute on `extern` blocks instead.
# Static linking
Static linking refers to the process of creating output that contain all
required libraries and so don't need libraries installed on every system where
Static linking refers to the process of creating output that contains all
required libraries and so doesn't need libraries installed on every system where
you want to use your compiled project. Pure-Rust dependencies are statically
linked by default so you can use created binaries and libraries without
installing the Rust everywhere. By contrast, native libraries
(e.g. `libc` and `libm`) usually dynamically linked, but it is possible to
installing Rust everywhere. By contrast, native libraries
(e.g. `libc` and `libm`) are usually dynamically linked, but it is possible to
change this and statically link them as well.
Linking is a very platform dependent topic — on some platforms, static linking
may not be possible at all! This section assumes some basic familiarity with
Linking is a very platform-dependent topic, and static linking may not even be
possible on some platforms! This section assumes some basic familiarity with
linking on your platform of choice.
## Linux
@ -71,8 +71,7 @@ Dynamic linking on Linux can be undesirable if you wish to use new library
features on old systems or target systems which do not have the required
dependencies for your program to run.
Static linking is supported via an alternative `libc`, `musl` - this must be
enabled at Rust compile-time with some prerequisites available. You can compile
Static linking is supported via an alternative `libc`, `musl`. You can compile
your own version of Rust with `musl` enabled and install it into a custom
directory with the instructions below:
@ -81,33 +80,30 @@ $ mkdir musldist
$ PREFIX=$(pwd)/musldist
$
$ # Build musl
$ wget http://www.musl-libc.org/releases/musl-1.1.10.tar.gz
[...]
$ curl -O http://www.musl-libc.org/releases/musl-1.1.10.tar.gz
$ tar xf musl-1.1.10.tar.gz
$ cd musl-1.1.10/
musl-1.1.10 $ ./configure --disable-shared --prefix=$PREFIX
[...]
musl-1.1.10 $ make
[...]
musl-1.1.10 $ make install
[...]
musl-1.1.10 $ cd ..
$ du -h musldist/lib/libc.a
2.2M musldist/lib/libc.a
$
$ # Build libunwind.a
$ wget http://llvm.org/releases/3.6.1/llvm-3.6.1.src.tar.xz
$ tar xf llvm-3.6.1.src.tar.xz
$ cd llvm-3.6.1.src/projects/
llvm-3.6.1.src/projects $ svn co http://llvm.org/svn/llvm-project/libcxxabi/trunk/ libcxxabi
llvm-3.6.1.src/projects $ svn co http://llvm.org/svn/llvm-project/libunwind/trunk/ libunwind
llvm-3.6.1.src/projects $ sed -i 's#^\(include_directories\).*$#\0\n\1(../libcxxabi/include)#' libunwind/CMakeLists.txt
llvm-3.6.1.src/projects $ mkdir libunwind/build
llvm-3.6.1.src/projects $ cd libunwind/build
llvm-3.6.1.src/projects/libunwind/build $ cmake -DLLVM_PATH=../../.. -DLIBUNWIND_ENABLE_SHARED=0 ..
llvm-3.6.1.src/projects/libunwind/build $ make
llvm-3.6.1.src/projects/libunwind/build $ cp lib/libunwind.a $PREFIX/lib/
llvm-3.6.1.src/projects/libunwind/build $ cd cd ../../../../
$ curl -O http://llvm.org/releases/3.7.0/llvm-3.7.0.src.tar.xz
$ tar xf llvm-3.7.0.src.tar.xz
$ cd llvm-3.7.0.src/projects/
llvm-3.7.0.src/projects $ curl http://llvm.org/releases/3.7.0/libcxxabi-3.7.0.src.tar.xz | tar xJf -
llvm-3.7.0.src/projects $ mv libcxxabi-3.7.0.src libcxxabi
llvm-3.7.0.src/projects $ curl http://llvm.org/releases/3.7.0/libunwind-3.7.0.src.tar.xz | tar xJf -
llvm-3.7.0.src/projects $ mv libunwind-3.7.0.src libunwind
llvm-3.7.0.src/projects $ mkdir libunwind/build
llvm-3.7.0.src/projects $ cd libunwind/build
llvm-3.7.0.src/projects/libunwind/build $ cmake -DLLVM_PATH=../../.. -DLIBUNWIND_ENABLE_SHARED=0 ..
llvm-3.7.0.src/projects/libunwind/build $ make
llvm-3.7.0.src/projects/libunwind/build $ cp lib/libunwind.a $PREFIX/lib/
llvm-3.7.0.src/projects/libunwind/build $ cd ../../../../
$ du -h musldist/lib/libunwind.a
164K musldist/lib/libunwind.a
$
@ -123,7 +119,7 @@ $ du -h musldist/bin/rustc
```
You now have a build of a `musl`-enabled Rust! Because we've installed it to a
custom prefix we need to make sure our system can the binaries and appropriate
custom prefix we need to make sure our system can find the binaries and appropriate
libraries when we try and run it:
```text

View File

@ -1,8 +1,8 @@
% Academic Research
% Bibliography
An incomplete list of papers that have had some influence in Rust.
Recommended for inspiration and a better understanding of Rust's background.
This is a reading list of material relevant to Rust. It includes prior
research that has - at one time or another - influenced the design of
Rust, as well as publications about Rust.
### Type system
@ -33,6 +33,7 @@ Recommended for inspiration and a better understanding of Rust's background.
* [Non-blocking steal-half work queues](http://www.cs.bgu.ac.il/%7Ehendlerd/papers/p280-hendler.pdf)
* [Reagents: expressing and composing fine-grained concurrency](http://www.mpi-sws.org/~turon/reagents.pdf)
* [Algorithms for scalable synchronization of shared-memory multiprocessors](https://www.cs.rochester.edu/u/scott/papers/1991_TOCS_synch.pdf)
* [Epoc-based reclamation](https://www.cl.cam.ac.uk/techreports/UCAM-CL-TR-579.pdf).
### Others
@ -71,3 +72,9 @@ Language](http://www.cs.indiana.edu/~eholk/papers/hips2013.pdf). Early GPU work
* [Code Refinement of Stencil
Codes](http://compilers.cs.uni-saarland.de/papers/ppl14_web.pdf). Another
paper using Impala.
* [Parallelization in Rust with fork-join and
friends](http://publications.lib.chalmers.se/records/fulltext/219016/219016.pdf). Linus
Farnstrand's master's thesis.
* [Session Types for
Rust](http://munksgaard.me/papers/laumann-munksgaard-larsen.pdf). Philip
Munksgaard's master's thesis. Research for Servo.

View File

@ -1,6 +1,6 @@
% Choosing your Guarantees
One important feature of Rust as language is that it lets us control the costs and guarantees
One important feature of Rust is that it lets us control the costs and guarantees
of a program.
There are various &ldquo;wrapper type&rdquo; abstractions in the Rust standard library which embody
@ -18,9 +18,9 @@ Before proceeding, it is highly recommended that one reads about [ownership][own
## `Box<T>`
[`Box<T>`][box] is pointer which is &ldquo;owned&rdquo;, or a &ldquo;box&rdquo;. While it can hand
out references to the contained data, it is the only owner of the data. In particular, when
something like the following occurs:
[`Box<T>`][box] is an &ldquo;owned&rdquo; pointer, or a &ldquo;box&rdquo;. While it can hand
out references to the contained data, it is the only owner of the data. In particular, consider
the following:
```rust
let x = Box::new(1);
@ -40,7 +40,7 @@ allowed to share references to this by the regular borrowing rules, checked at c
[box]: ../std/boxed/struct.Box.html
## `&T` and `&mut T`
## `&T` and `&mut T`
These are immutable and mutable references respectively. They follow the &ldquo;read-write lock&rdquo;
pattern, such that one may either have only one mutable reference to some data, or any number of
@ -243,7 +243,7 @@ Many of the types above cannot be used in a threadsafe manner. Particularly, `Rc
`RefCell<T>`, which both use non-atomic reference counts (_atomic_ reference counts are those which
can be incremented from multiple threads without causing a data race), cannot be used this way. This
makes them cheaper to use, but we need thread safe versions of these too. They exist, in the form of
`Arc<T>` and `Mutex<T>`/`RWLock<T>`
`Arc<T>` and `Mutex<T>`/`RwLock<T>`
Note that the non-threadsafe types _cannot_ be sent between threads, and this is checked at compile
time.

View File

@ -316,6 +316,35 @@ assert_eq!(3, answer);
Now we take a trait object, a `&Fn`. And we have to make a reference
to our closure when we pass it to `call_with_one`, so we use `&||`.
# Function pointers and closures
A function pointer is kind of like a closure that has no environment. As such,
you can pass a function pointer to any function expecting a closure argument,
and it will work:
```rust
fn call_with_one(some_closure: &Fn(i32) -> i32) -> i32 {
some_closure(1)
}
fn add_one(i: i32) -> i32 {
i + 1
}
let f = add_one;
let answer = call_with_one(&f);
assert_eq!(2, answer);
```
In this example, we dont strictly need the intermediate variable `f`,
the name of the function works just fine too:
```ignore
let answer = call_with_one(&add_one);
```
# Returning closures
Its very common for functional-style code to return closures in various

View File

@ -115,7 +115,7 @@ In addition to procedural macros, you can define new
extensions. See
[`Registry::register_syntax_extension`](../rustc/plugin/registry/struct.Registry.html#method.register_syntax_extension)
and the [`SyntaxExtension`
enum](http://doc.rust-lang.org/syntax/ext/base/enum.SyntaxExtension.html). For
enum](https://doc.rust-lang.org/syntax/ext/base/enum.SyntaxExtension.html). For
a more involved macro example, see
[`regex_macros`](https://github.com/rust-lang/regex/blob/master/regex_macros/src/lib.rs).
@ -156,7 +156,7 @@ so that the compiler can continue and find further errors.
To print syntax fragments for debugging, you can use
[`span_note`](../syntax/ext/base/struct.ExtCtxt.html#method.span_note) together
with
[`syntax::print::pprust::*_to_string`](http://doc.rust-lang.org/syntax/print/pprust/index.html#functions).
[`syntax::print::pprust::*_to_string`](https://doc.rust-lang.org/syntax/print/pprust/index.html#functions).
The example above produced an integer literal using
[`AstBuilder::expr_usize`](../syntax/ext/build/trait.AstBuilder.html#tymethod.expr_usize).

View File

@ -135,28 +135,34 @@ This gives us an error:
^~~~
```
In this case, we know that our code _should_ be safe, but Rust isn't sure. And
it's actually not safe: if we had a reference to `data` in each thread, and the
thread takes ownership of the reference, we have three owners! That's bad. We
can fix this by using the `Arc<T>` type, which is an atomic reference counted
pointer. The 'atomic' part means that it's safe to share across threads.
Rust knows this wouldn't be safe! If we had a reference to `data` in each
thread, and the thread takes ownership of the reference, we'd have three
owners!
So, we need some type that lets us have more than one reference to a value and
that we can share between threads, that is it must implement `Sync`.
We'll use `Arc<T>`, rust's standard atomic reference count type, which
wraps a value up with some extra runtime bookkeeping which allows us to
share the ownership of the value between multiple references at the same time.
The bookkeeping consists of a count of how many of these references exist to
the value, hence the reference count part of the name.
The Atomic part means `Arc<T>` can safely be accessed from multiple threads.
To do this the compiler guarantees that mutations of the internal count use
indivisible operations which can't have data races.
`Arc<T>` assumes one more property about its contents to ensure that it is safe
to share across threads: it assumes its contents are `Sync`. But in our
case, we want to be able to mutate the value. We need a type that can ensure
only one person at a time can mutate what's inside. For that, we can use the
`Mutex<T>` type. Here's the second version of our code. It still doesn't work,
but for a different reason:
```ignore
use std::thread;
use std::sync::Mutex;
use std::sync::Arc;
fn main() {
let mut data = Mutex::new(vec![1, 2, 3]);
let mut data = Arc::new(vec![1, 2, 3]);
for i in 0..3 {
let data = data.lock().unwrap();
let data = data.clone();
thread::spawn(move || {
data[i] += 1;
});
@ -166,29 +172,29 @@ fn main() {
}
```
Here's the error:
We now call `clone()` on our `Arc<T>`, which increases the internal count.
This handle is then moved into the new thread.
And... still gives us an error.
```text
<anon>:9:9: 9:22 error: the trait `core::marker::Send` is not implemented for the type `std::sync::mutex::MutexGuard<'_, collections::vec::Vec<u32>>` [E0277]
<anon>:11 thread::spawn(move || {
^~~~~~~~~~~~~
<anon>:9:9: 9:22 note: `std::sync::mutex::MutexGuard<'_, collections::vec::Vec<u32>>` cannot be sent between threads safely
<anon>:11 thread::spawn(move || {
^~~~~~~~~~~~~
<anon>:11:24 error: cannot borrow immutable borrowed content as mutable
<anon>:11 data[i] += 1;
^~~~
```
You see, [`Mutex`](../std/sync/struct.Mutex.html) has a
[`lock`](../std/sync/struct.Mutex.html#method.lock)
method which has this signature:
`Arc<T>` assumes one more property about its contents to ensure that it is safe
to share across threads: it assumes its contents are `Sync`. This is true for
our value if it's immutable, but we want to be able to mutate it, so we need
something else to persuade the borrow checker we know what we're doing.
```ignore
fn lock(&self) -> LockResult<MutexGuard<T>>
```
It looks like we need some type that allows us to safely mutate a shared value,
for example a type that that can ensure only one thread at a time is able to
mutate the value inside it at any one time.
Because `Send` is not implemented for `MutexGuard<T>`, we can't transfer the
guard across thread boundaries, which gives us our error.
For that, we can use the `Mutex<T>` type!
We can use `Arc<T>` to fix this. Here's the working version:
Here's the working version:
```rust
use std::sync::{Arc, Mutex};
@ -209,9 +215,31 @@ fn main() {
}
```
We now call `clone()` on our `Arc`, which increases the internal count. This
handle is then moved into the new thread. Let's examine the body of the
thread more closely:
If we'd tried to use `Mutex<T>` without wrapping it in an `Arc<T>` we would have
seen another error like:
```text
error: the trait `core::marker::Send` is not implemented for the type `std::sync::mutex::MutexGuard<'_, collections::vec::Vec<u32>>` [E0277]
thread::spawn(move || {
^~~~~~~~~~~~~
note: `std::sync::mutex::MutexGuard<'_, collections::vec::Vec<u32>>` cannot be sent between threads safely
thread::spawn(move || {
^~~~~~~~~~~~~
```
You see, [`Mutex`](../std/sync/struct.Mutex.html) has a
[`lock`](../std/sync/struct.Mutex.html#method.lock)
method which has this signature:
```ignore
fn lock(&self) -> LockResult<MutexGuard<T>>
```
and because `Send` is not implemented for `MutexGuard<T>`, we couldn't have
transferred the guard across thread boundaries on it's own.
Let's examine the body of the thread more closely:
```rust
# use std::sync::{Arc, Mutex};
@ -315,12 +343,14 @@ threads as a simple isolation mechanism:
```rust
use std::thread;
let result = thread::spawn(move || {
let handle = thread::spawn(move || {
panic!("oops!");
}).join();
});
let result = handle.join();
assert!(result.is_err());
```
Our `Thread` gives us a `Result` back, which allows us to check if the thread
`Thread.join()` gives us a `Result` back, which allows us to check if the thread
has panicked or not.

View File

@ -115,7 +115,7 @@ $ ls target/debug
build deps examples libphrases-a7448e02a0468eaa.rlib native
```
`libphrase-hash.rlib` is the compiled crate. Before we see how to use this
`libphrases-hash.rlib` is the compiled crate. Before we see how to use this
crate from another crate, lets break it up into multiple files.
# Multiple file crates
@ -263,6 +263,10 @@ the `phrases` crate. We can then use `phrases` modules in this one. As we
mentioned earlier, you can use double colons to refer to sub-modules and the
functions inside of them.
(Note: when importing a crate that has dashes in its name "like-this", which is
not a valid Rust identifier, it will be converted by changing the dashes to
underscores, so you would write `extern crate like_this;`.)
Also, Cargo assumes that `src/main.rs` is the crate root of a binary crate,
rather than a library crate. Our package now has two crates: `src/lib.rs` and
`src/main.rs`. This pattern is quite common for executable crates: most
@ -532,3 +536,51 @@ Goodbye in English: Goodbye.
Hello in Japanese: こんにちは
Goodbye in Japanese: さようなら
```
## Complex imports
Rust offers several advanced options that can add compactness and
convenience to your `extern crate` and `use` statements. Here is an example:
```rust,ignore
extern crate phrases as sayings;
use sayings::japanese::greetings as ja_greetings;
use sayings::japanese::farewells::*;
use sayings::english::{self, greetings as en_greetings, farewells as en_farewells};
fn main() {
println!("Hello in English; {}", en_greetings::hello());
println!("And in Japanese: {}", ja_greetings::hello());
println!("Goodbye in English: {}", english::farewells::goodbye());
println!("Again: {}", en_farewells::goodbye());
println!("And in Japanese: {}", goodbye());
}
```
What's going on here?
First, both `extern crate` and `use` allow renaming the thing that is being
imported. So the crate is still called "phrases", but here we will refer
to it as "sayings". Similarly, the first `use` statement pulls in the
`japanese::farewells` module from the crate, but makes it available as
`jp_farewells` as opposed to simply `farewells`. This can help to avoid
ambiguity when importing similarly-named items from different places.
The second `use` statement uses a star glob to bring in _all_ symbols from the
`sayings::japanese::farewells` module. As you can see we can later refer to
the Japanese `goodbye` function with no module qualifiers. This kind of glob
should be used sparingly.
The third `use` statement bears more explanation. It's using "brace expansion"
globbing to compress three `use` statements into one (this sort of syntax
may be familiar if you've written Linux shell scripts before). The
uncompressed form of this statement would be:
```rust,ignore
use sayings::english;
use sayings::english::greetings as en_greetings;
use sayings::english::farewells as en_farewells;
```
As you can see, the curly brackets compress `use` statements for several items
under the same path, and in this context `self` just refers back to that path.
Note: The curly brackets cannot be nested or mixed with star globbing.

View File

@ -89,8 +89,8 @@ Vectors can `Deref` to a slice.
## Deref and method calls
`Deref` will also kick in when calling a method. In other words, these are
the same two things in Rust:
`Deref` will also kick in when calling a method. Consider the following
example.
```rust
struct Foo;
@ -99,13 +99,13 @@ impl Foo {
fn foo(&self) { println!("Foo"); }
}
let f = Foo;
let f = &&Foo;
f.foo();
```
Even though `f` isnt a reference, and `foo` takes `&self`, this works.
Thats because these things are the same:
Even though `f` is a `&&Foo` and `foo` takes `&self`, this works. Thats
because these things are the same:
```rust,ignore
f.foo();

View File

@ -73,10 +73,10 @@ hello.rs:4 }
```
This [unfortunate error](https://github.com/rust-lang/rust/issues/22547) is
correct: documentation comments apply to the thing after them, and there's no
thing after that last comment.
correct: documentation comments apply to the thing after them, and there's
nothing after that last comment.
[rc-new]: http://doc.rust-lang.org/nightly/std/rc/struct.Rc.html#method.new
[rc-new]: https://doc.rust-lang.org/nightly/std/rc/struct.Rc.html#method.new
### Writing documentation comments
@ -196,10 +196,10 @@ This will highlight according to whatever language you're showing off.
If you're just showing plain text, choose `text`.
It's important to choose the correct annotation here, because `rustdoc` uses it
in an interesting way: It can be used to actually test your examples, so that
they don't get out of date. If you have some C code but `rustdoc` thinks it's
Rust because you left off the annotation, `rustdoc` will complain when trying to
generate the documentation.
in an interesting way: It can be used to actually test your examples in a
library crate, so that they don't get out of date. If you have some C code but
`rustdoc` thinks it's Rust because you left off the annotation, `rustdoc` will
complain when trying to generate the documentation.
## Documentation as tests
@ -377,8 +377,8 @@ $ rustdoc --test path/to/my/crate/root.rs
$ cargo test
```
That's right, `cargo test` tests embedded documentation too. However,
`cargo test` will not test binary crates, only library ones. This is
That's right, `cargo test` tests embedded documentation too. **However,
`cargo test` will not test binary crates, only library ones.** This is
due to the way `rustdoc` works: it links against the library to be tested,
but with a binary, theres nothing to link to.
@ -544,9 +544,9 @@ You can control a few aspects of the HTML that `rustdoc` generates through the
`#![doc]` version of the attribute:
```rust
#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
html_root_url = "http://doc.rust-lang.org/")]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
html_favicon_url = "https://www.rust-lang.org/favicon.ico",
html_root_url = "https://doc.rust-lang.org/")]
```
This sets a few different options, with a logo, favicon, and a root URL.

File diff suppressed because it is too large Load Diff

View File

@ -496,9 +496,11 @@ strings are not terminated with `\0`. If you need a NUL-terminated string for
interoperability with C, you should use the `CString` type in the `std::ffi`
module.
The standard library includes type aliases and function definitions for the C
standard library in the `libc` module, and Rust links against `libc` and `libm`
by default.
The [`libc` crate on crates.io][libc] includes type aliases and function
definitions for the C standard library in the `libc` module, and Rust links
against `libc` and `libm` by default.
[libc]: https://crates.io/crates/libc
# The "nullable pointer optimization"
@ -555,3 +557,56 @@ pub extern fn oh_no() -> i32 {
# fn main() {}
```
# Representing opaque structs
Sometimes, a C library wants to provide a pointer to something, but not let you
know the internal details of the thing it wants. The simplest way is to use a
`void *` argument:
```c
void foo(void *arg);
void bar(void *arg);
```
We can represent this in Rust with the `c_void` type:
```rust
# #![feature(libc)]
extern crate libc;
extern "C" {
pub fn foo(arg: *mut libc::c_void);
pub fn bar(arg: *mut libc::c_void);
}
# fn main() {}
```
This is a perfectly valid way of handling the situation. However, we can do a bit
better. To solve this, some C libraries will instead create a `struct`, where
the details and memory layout of the struct are private. This gives some amount
of type safety. These structures are called opaque. Heres an example, in C:
```c
struct Foo; /* Foo is a structure, but its contents are not part of the public interface */
struct Bar;
void foo(struct Foo *arg);
void bar(struct Bar *arg);
```
To do this in Rust, lets create our own opaque types with `enum`:
```rust
pub enum Foo {}
pub enum Bar {}
extern "C" {
pub fn foo(arg: *mut Foo);
pub fn bar(arg: *mut Bar);
}
# fn main() {}
```
By using an `enum` with no variants, we create an opaque type that we cant
instantiate, as it has no variants. But because our `Foo` and `Bar` types are
different, well get type safety between the two of them, so we cannot
accidentally pass a pointer to `Foo` to `bar()`.

View File

@ -214,11 +214,61 @@ fn diverges() -> ! {
`panic!` is a macro, similar to `println!()` that weve already seen. Unlike
`println!()`, `panic!()` causes the current thread of execution to crash with
the given message.
the given message. Because this function will cause a crash, it will never
return, and so it has the type `!`, which is read diverges.
Because this function will cause a crash, it will never return, and so it has
the type `!`, which is read diverges. A diverging function can be used
as any type:
If you add a main function that calls `diverges()` and run it, youll get
some output that looks like this:
```text
thread <main> panicked at This function never returns!, hello.rs:2
```
If you want more information, you can get a backtrace by setting the
`RUST_BACKTRACE` environment variable:
```text
$ RUST_BACKTRACE=1 ./diverges
thread '<main>' panicked at 'This function never returns!', hello.rs:2
stack backtrace:
1: 0x7f402773a829 - sys::backtrace::write::h0942de78b6c02817K8r
2: 0x7f402773d7fc - panicking::on_panic::h3f23f9d0b5f4c91bu9w
3: 0x7f402773960e - rt::unwind::begin_unwind_inner::h2844b8c5e81e79558Bw
4: 0x7f4027738893 - rt::unwind::begin_unwind::h4375279447423903650
5: 0x7f4027738809 - diverges::h2266b4c4b850236beaa
6: 0x7f40277389e5 - main::h19bb1149c2f00ecfBaa
7: 0x7f402773f514 - rt::unwind::try::try_fn::h13186883479104382231
8: 0x7f402773d1d8 - __rust_try
9: 0x7f402773f201 - rt::lang_start::ha172a3ce74bb453aK5w
10: 0x7f4027738a19 - main
11: 0x7f402694ab44 - __libc_start_main
12: 0x7f40277386c8 - <unknown>
13: 0x0 - <unknown>
```
`RUST_BACKTRACE` also works with Cargos `run` command:
```text
$ RUST_BACKTRACE=1 cargo run
Running `target/debug/diverges`
thread '<main>' panicked at 'This function never returns!', hello.rs:2
stack backtrace:
1: 0x7f402773a829 - sys::backtrace::write::h0942de78b6c02817K8r
2: 0x7f402773d7fc - panicking::on_panic::h3f23f9d0b5f4c91bu9w
3: 0x7f402773960e - rt::unwind::begin_unwind_inner::h2844b8c5e81e79558Bw
4: 0x7f4027738893 - rt::unwind::begin_unwind::h4375279447423903650
5: 0x7f4027738809 - diverges::h2266b4c4b850236beaa
6: 0x7f40277389e5 - main::h19bb1149c2f00ecfBaa
7: 0x7f402773f514 - rt::unwind::try::try_fn::h13186883479104382231
8: 0x7f402773d1d8 - __rust_try
9: 0x7f402773f201 - rt::lang_start::ha172a3ce74bb453aK5w
10: 0x7f4027738a19 - main
11: 0x7f402694ab44 - __libc_start_main
12: 0x7f40277386c8 - <unknown>
13: 0x0 - <unknown>
```
A diverging function can be used as any type:
```should_panic
# fn diverges() -> ! {
@ -227,3 +277,34 @@ as any type:
let x: i32 = diverges();
let x: String = diverges();
```
## Function pointers
We can also create variable bindings which point to functions:
```rust
let f: fn(i32) -> i32;
```
`f` is a variable binding which points to a function that takes an `i32` as
an argument and returns an `i32`. For example:
```rust
fn plus_one(i: i32) -> i32 {
i + 1
}
// without type inference
let f: fn(i32) -> i32 = plus_one;
// with type inference
let f = plus_one;
```
We can then use `f` to call the function:
```rust
# fn plus_one(i: i32) -> i32 { i + 1 }
# let f = plus_one;
let six = f(5);
```

View File

@ -6,7 +6,7 @@ Generics are called parametric polymorphism in type theory,
which means that they are types or functions that have multiple forms (poly
is multiple, morph is form) over a given parameter (parametric).
Anyway, enough with type theory, lets check out some generic code. Rusts
Anyway, enough type theory, lets check out some generic code. Rusts
standard library provides a type, `Option<T>`, thats generic:
```rust
@ -17,7 +17,7 @@ enum Option<T> {
```
The `<T>` part, which youve seen a few times before, indicates that this is
a generic data type. Inside the declaration of our enum, wherever we see a `T`,
a generic data type. Inside the declaration of our `enum`, wherever we see a `T`,
we substitute that type for the same type used in the generic. Heres an
example of using `Option<T>`, with some extra type annotations:
@ -27,7 +27,7 @@ let x: Option<i32> = Some(5);
In the type declaration, we say `Option<i32>`. Note how similar this looks to
`Option<T>`. So, in this particular `Option`, `T` has the value of `i32`. On
the right-hand side of the binding, we do make a `Some(T)`, where `T` is `5`.
the right-hand side of the binding, we make a `Some(T)`, where `T` is `5`.
Since thats an `i32`, the two sides match, and Rust is happy. If they didnt
match, wed get an error:
@ -101,11 +101,6 @@ fn takes_two_things<T, U>(x: T, y: U) {
}
```
Generic functions are most useful with trait bounds, which well cover in the
[section on traits][traits].
[traits]: traits.html
## Generic structs
You can store a generic type in a `struct` as well:
@ -120,5 +115,30 @@ let int_origin = Point { x: 0, y: 0 };
let float_origin = Point { x: 0.0, y: 0.0 };
```
Similarly to functions, the `<T>` is where we declare the generic parameters,
Similar to functions, the `<T>` is where we declare the generic parameters,
and we then use `x: T` in the type declaration, too.
When you want to add an implementation for the generic `struct`, you just
declare the type parameter after the `impl`:
```rust
# struct Point<T> {
# x: T,
# y: T,
# }
#
impl<T> Point<T> {
fn swap(&mut self) {
std::mem::swap(&mut self.x, &mut self.y);
}
}
```
So far youve seen generics that take absolutely any type. These are useful in
many cases: youve already seen `Option<T>`, and later youll meet universal
container types like [`Vec<T>`][Vec]. On the other hand, often you want to
trade that flexibility for increased expressive power. Read about [trait
bounds][traits] to see why and how.
[traits]: traits.html
[Vec]: ../std/vec/struct.Vec.html

View File

@ -38,6 +38,12 @@ let z = (8, 2, 6);
In the example above `x` and `y` have arity 2. `z` has arity 3.
### DST (Dynamically Sized Type)
A type without a statically known size or alignment. ([more info][link])
[link]: ../nomicon/exotic-sizes.html#dynamically-sized-types-(dsts)
### Expression
In computer programming, an expression is a combination of values, constants,

View File

@ -533,7 +533,7 @@ Great! Next up: lets compare our guess to the secret guess.
# Comparing guesses
Now that weve got user input, lets compare our guess to the random guess.
Heres our next step, though it doesnt quite work yet:
Heres our next step, though it doesnt quite compile yet:
```rust,ignore
extern crate rand;
@ -617,7 +617,7 @@ match guess.cmp(&secret_number) {
If its `Less`, we print `Too small!`, if its `Greater`, `Too big!`, and if
`Equal`, `You win!`. `match` is really useful, and is used often in Rust.
I did mention that this wont quite work yet, though. Lets try it:
I did mention that this wont quite compile yet, though. Lets try it:
```bash
$ cargo build

View File

@ -32,7 +32,7 @@ install dialog and on the "Product Features" page ensure "Add to PATH" is
installed on the local hard drive.
[install-page]: http://www.rust-lang.org/install.html
[install-page]: https://www.rust-lang.org/install.html
## Uninstalling
@ -85,10 +85,10 @@ $ rustc --version
```
You should see the version number, commit hash, and commit date. If you just
installed version 1.0.0, you should see:
installed version 1.2.0, you should see:
```bash
rustc 1.0.0 (a59de37e9 2015-05-13)
rustc 1.2.0 (082e47636 2015-08-03)
```
If you did, Rust has been installed successfully! Congrats!
@ -112,5 +112,5 @@ resources include [the users forum][users], and
[irc]: irc://irc.mozilla.org/#rust
[mibbit]: http://chat.mibbit.com/?server=irc.mozilla.org&channel=%23rust
[users]: http://users.rust-lang.org/
[users]: https://users.rust-lang.org/
[stackoverflow]: http://stackoverflow.com/questions/tagged/rust

View File

@ -51,7 +51,6 @@ fn main(argc: isize, argv: *const *const u8) -> isize {
0
}
#[lang = "stack_exhausted"] extern fn stack_exhausted() {}
#[lang = "eh_personality"] extern fn eh_personality() {}
#[lang = "panic_fmt"] fn panic_fmt() -> ! { loop {} }
# #[lang = "eh_unwind_resume"] extern fn rust_eh_unwind_resume() {}

View File

@ -77,8 +77,18 @@ Before we get to that, though, lets break the explicit example down:
fn bar<'a>(...)
```
This part declares our lifetimes. This says that `bar` has one lifetime, `'a`.
If we had two reference parameters, it would look like this:
We previously talked a little about [function syntax][functions], but we didnt
discuss the `<>`s after a functions name. A function can have generic
parameters between the `<>`s, of which lifetimes are one kind. Well discuss
other kinds of generics [later in the book][generics], but for now, lets
just focus on the lifetimes aspect.
[functions]: functions.html
[generics]: generics.html
We use `<>` to declare our lifetimes. This says that `bar` has one lifetime,
`'a`. If we had two reference parameters, it would look like this:
```rust,ignore
fn bar<'a, 'b>(...)
@ -98,7 +108,7 @@ If we wanted an `&mut` reference, wed do this:
If you compare `&mut i32` to `&'a mut i32`, theyre the same, its just that
the lifetime `'a` has snuck in between the `&` and the `mut i32`. We read `&mut
i32` as a mutable reference to an i32 and `&'a mut i32` as a mutable
i32` as a mutable reference to an `i32` and `&'a mut i32` as a mutable
reference to an `i32` with the lifetime `'a`.
# In `struct`s

View File

@ -134,7 +134,7 @@ Outputs:
```text
0: Content of line one
1: Content of line two
2: Content of line tree
2: Content of line three
3: Content of line four
```
@ -193,7 +193,7 @@ for x in 0..10 {
You may also encounter situations where you have nested loops and need to
specify which one your `break` or `continue` statement is for. Like most
other languages, by default a `break` or `continue` will apply to innermost
loop. In a sitation where you would like to a `break` or `continue` for one
loop. In a situation where you would like to a `break` or `continue` for one
of the outer loops, you can use labels to specify which loop the `break` or
`continue` statement applies to. This will only print when both `x` and `y` are
odd:

View File

@ -313,7 +313,7 @@ fn main() {
}
```
This works because Rust has a [hygienic macro system][]. Each macro expansion
This works because Rust has a [hygienic macro system]. Each macro expansion
happens in a distinct syntax context, and each variable is tagged with the
syntax context where it was introduced. Its as though the variable `state`
inside `main` is painted a different "color" from the variable `state` inside

View File

@ -7,7 +7,7 @@ can be awkward. Consider this code:
baz(bar(foo));
```
We would read this left-to right, and so we see baz bar foo. But this isnt the
We would read this left-to-right, and so we see baz bar foo. But this isnt the
order that the functions would get called in, thats inside-out: foo bar baz.
Wouldnt it be nice if we could do this instead?
@ -45,17 +45,17 @@ This will print `12.566371`.
Weve made a struct that represents a circle. We then write an `impl` block,
Weve made a `struct` that represents a circle. We then write an `impl` block,
and inside it, define a method, `area`.
Methods take a special first parameter, of which there are three variants:
Methods take a special first parameter, of which there are three variants:
`self`, `&self`, and `&mut self`. You can think of this first parameter as
being the `foo` in `foo.bar()`. The three variants correspond to the three
kinds of things `foo` could be: `self` if its just a value on the stack,
`&self` if its a reference, and `&mut self` if its a mutable reference.
Because we took the `&self` parameter to `area`, we can use it just like any
other parameter. Because we know its a `Circle`, we can access the `radius`
just like we would with any other struct.
just like we would with any other `struct`.
We should default to using `&self`, as you should prefer borrowing over taking
ownership, as well as taking immutable references over mutable ones. Heres an
@ -120,12 +120,12 @@ Check the return type:
```rust
# struct Circle;
# impl Circle {
fn grow(&self) -> Circle {
fn grow(&self, increment: f64) -> Circle {
# Circle } }
```
We just say were returning a `Circle`. With this method, we can grow a new
circle to any arbitrary size.
`Circle` to any arbitrary size.
# Associated functions
@ -161,7 +161,7 @@ methods.
# Builder Pattern
Lets say that we want our users to be able to create Circles, but we will
Lets say that we want our users to be able to create `Circle`s, but we will
allow them to only set the properties they care about. Otherwise, the `x`
and `y` attributes will be `0.0`, and the `radius` will be `1.0`. Rust doesnt
have method overloading, named arguments, or variable arguments. We employ
@ -224,7 +224,7 @@ fn main() {
}
```
What weve done here is make another struct, `CircleBuilder`. Weve defined our
What weve done here is make another `struct`, `CircleBuilder`. Weve defined our
builder methods on it. Weve also defined our `area()` method on `Circle`. We
also made one more method on `CircleBuilder`: `finalize()`. This method creates
our final `Circle` from the builder. Now, weve used the type system to enforce

View File

@ -62,7 +62,7 @@ fn foo(mut x: i32) {
# Interior vs. Exterior Mutability
However, when we say something is immutable in Rust, that doesnt mean that
its not able to be changed: We mean something has exterior mutability. Consider,
its not able to be changed: we mean something has exterior mutability. Consider,
for example, [`Arc<T>`][arc]:
```rust
@ -85,8 +85,8 @@ philosophy, memory safety, and the mechanism by which Rust guarantees it, the
> You may have one or the other of these two kinds of borrows, but not both at
> the same time:
>
> * one or more references (`&T`) to a resource.
> * exactly one mutable reference (`&mut T`)
> * one or more references (`&T`) to a resource,
> * exactly one mutable reference (`&mut T`).
[ownership]: ownership.html
[borrowing]: references-and-borrowing.html#borrowing

View File

@ -50,7 +50,7 @@ documentation on [building Rust from Source][from-source], or [the official
binary downloads][install-page].
[from-source]: https://github.com/rust-lang/rust#building-from-source
[install-page]: http://www.rust-lang.org/install.html
[install-page]: https://www.rust-lang.org/install.html
Oh, we should also mention the officially supported platforms:
@ -95,5 +95,5 @@ resources include [the users forum][users], and [Stack Overflow][stackoverflo
[irc]: irc://irc.mozilla.org/#rust
[mibbit]: http://chat.mibbit.com/?server=irc.mozilla.org&channel=%23rust
[users]: http://users.rust-lang.org/
[users]: https://users.rust-lang.org/
[stackoverflow]: http://stackoverflow.com/questions/tagged/rust

View File

@ -36,7 +36,6 @@ fn start(_argc: isize, _argv: *const *const u8) -> isize {
// These functions and traits are used by the compiler, but not
// for a bare-bones hello world. These are normally
// provided by libstd.
#[lang = "stack_exhausted"] extern fn stack_exhausted() {}
#[lang = "eh_personality"] extern fn eh_personality() {}
#[lang = "panic_fmt"] fn panic_fmt() -> ! { loop {} }
# #[lang = "eh_unwind_resume"] extern fn rust_eh_unwind_resume() {}
@ -61,7 +60,6 @@ pub extern fn main(argc: i32, argv: *const *const u8) -> i32 {
0
}
#[lang = "stack_exhausted"] extern fn stack_exhausted() {}
#[lang = "eh_personality"] extern fn eh_personality() {}
#[lang = "panic_fmt"] fn panic_fmt() -> ! { loop {} }
# #[lang = "eh_unwind_resume"] extern fn rust_eh_unwind_resume() {}
@ -73,18 +71,12 @@ The compiler currently makes a few assumptions about symbols which are available
in the executable to call. Normally these functions are provided by the standard
library, but without it you must define your own.
The first of these three functions, `stack_exhausted`, is invoked whenever stack
overflow is detected. This function has a number of restrictions about how it
can be called and what it must do, but if the stack limit register is not being
maintained then a thread always has an "infinite stack" and this function
shouldn't get triggered.
The second of these three functions, `eh_personality`, is used by the
The first of these two functions, `eh_personality`, is used by the
failure mechanisms of the compiler. This is often mapped to GCC's
personality function (see the
[libstd implementation](../std/rt/unwind/index.html) for more
information), but crates which do not trigger a panic can be assured
that this function is never called. The final function, `panic_fmt`, is
that this function is never called. The second function, `panic_fmt`, is
also used by the failure mechanisms of the compiler.
## Using libcore
@ -150,7 +142,6 @@ extern fn panic_fmt(args: &core::fmt::Arguments,
loop {}
}
#[lang = "stack_exhausted"] extern fn stack_exhausted() {}
#[lang = "eh_personality"] extern fn eh_personality() {}
# #[lang = "eh_unwind_resume"] extern fn rust_eh_unwind_resume() {}
# #[start] fn start(argc: isize, argv: *const *const u8) -> isize { 0 }

View File

@ -81,3 +81,55 @@ will let you do this:
let p: Point = // ...
let x: f64 = p + 2i32;
```
# Using operator traits in generic structs
Now that we know how operator traits are defined, we can define our `HasArea`
trait and `Square` struct from the [traits chapter][traits] more generically:
[traits]: traits.html
```rust
use std::ops::Mul;
trait HasArea<T> {
fn area(&self) -> T;
}
struct Square<T> {
x: T,
y: T,
side: T,
}
impl<T> HasArea<T> for Square<T>
where T: Mul<Output=T> + Copy {
fn area(&self) -> T {
self.side * self.side
}
}
fn main() {
let s = Square {
x: 0.0f64,
y: 0.0f64,
side: 12.0f64,
};
println!("Area of s: {}", s.area());
}
```
For `HasArea` and `Square`, we just declare a type parameter `T` and replace
`f64` with it. The `impl` needs more involved modifications:
```ignore
impl<T> HasArea<T> for Square<T>
where T: Mul<Output=T> + Copy { ... }
```
The `area` method requires that we can multiply the sides, so we declare that
type `T` must implement `std::ops::Mul`. Like `Add`, mentioned above, `Mul`
itself takes an `Output` parameter: since we know that numbers don't change
type when multiplied, we also set it to `T`. `T` must also support copying, so
Rust doesn't try to move `self.side` into the return value.

View File

@ -39,203 +39,6 @@ match x {
This prints `one or two`.
# Ranges
You can match a range of values with `...`:
```rust
let x = 1;
match x {
1 ... 5 => println!("one through five"),
_ => println!("anything"),
}
```
This prints `one through five`.
Ranges are mostly used with integers and `char`s:
```rust
let x = '💅';
match x {
'a' ... 'j' => println!("early letter"),
'k' ... 'z' => println!("late letter"),
_ => println!("something else"),
}
```
This prints `something else`.
# Bindings
You can bind values to names with `@`:
```rust
let x = 1;
match x {
e @ 1 ... 5 => println!("got a range element {}", e),
_ => println!("anything"),
}
```
This prints `got a range element 1`. This is useful when you want to
do a complicated match of part of a data structure:
```rust
#[derive(Debug)]
struct Person {
name: Option<String>,
}
let name = "Steve".to_string();
let mut x: Option<Person> = Some(Person { name: Some(name) });
match x {
Some(Person { name: ref a @ Some(_), .. }) => println!("{:?}", a),
_ => {}
}
```
This prints `Some("Steve")`: Weve bound the inner `name` to `a`.
If you use `@` with `|`, you need to make sure the name is bound in each part
of the pattern:
```rust
let x = 5;
match x {
e @ 1 ... 5 | e @ 8 ... 10 => println!("got a range element {}", e),
_ => println!("anything"),
}
```
# Ignoring bindings
You can use `_` in a pattern to disregard the type and value.
For example, heres a `match` against a `Result<T, E>`:
```rust
# let some_value: Result<i32, &'static str> = Err("There was an error");
match some_value {
Ok(value) => println!("got a value: {}", value),
Err(_) => println!("an error occurred"),
}
```
In the first arm, we bind the value inside the `Ok` variant to `value`. But
in the `Err` arm, we use `_` to disregard the specific error, and just print
a general error message.
`_` is valid in any pattern that creates a binding. This can be useful to
ignore parts of a larger structure:
```rust
fn coordinate() -> (i32, i32, i32) {
// generate and return some sort of triple tuple
# (1, 2, 3)
}
let (x, _, z) = coordinate();
```
Here, we bind the first and last element of the tuple to `x` and `z`, but
ignore the middle element.
Similarly, you can use `..` in a pattern to disregard multiple values.
```rust
enum OptionalTuple {
Value(i32, i32, i32),
Missing,
}
let x = OptionalTuple::Value(5, -2, 3);
match x {
OptionalTuple::Value(..) => println!("Got a tuple!"),
OptionalTuple::Missing => println!("No such luck."),
}
```
This prints `Got a tuple!`.
# Guards
You can introduce match guards with `if`:
```rust
enum OptionalInt {
Value(i32),
Missing,
}
let x = OptionalInt::Value(5);
match x {
OptionalInt::Value(i) if i > 5 => println!("Got an int bigger than five!"),
OptionalInt::Value(..) => println!("Got an int!"),
OptionalInt::Missing => println!("No such luck."),
}
```
This prints `Got an int!`.
If youre using `if` with multiple patterns, the `if` applies to both sides:
```rust
let x = 4;
let y = false;
match x {
4 | 5 if y => println!("yes"),
_ => println!("no"),
}
```
This prints `no`, because the `if` applies to the whole of `4 | 5`, and not to
just the `5`, In other words, the the precedence of `if` behaves like this:
```text
(4 | 5) if y => ...
```
not this:
```text
4 | (5 if y) => ...
```
# ref and ref mut
If you want to get a [reference][ref], use the `ref` keyword:
```rust
let x = 5;
match x {
ref r => println!("Got a reference to {}", r),
}
```
This prints `Got a reference to 5`.
[ref]: references-and-borrowing.html
Here, the `r` inside the `match` has the type `&i32`. In other words, the `ref`
keyword _creates_ a reference, for use in the pattern. If you need a mutable
reference, `ref mut` will work in the same way:
```rust
let mut x = 5;
match x {
ref mut mr => println!("Got a mutable reference to {}", mr),
}
```
# Destructuring
If you have a compound data type, like a [`struct`][struct], you can destructure it
@ -311,6 +114,203 @@ This destructuring behavior works on any compound data type, like
[tuples]: primitive-types.html#tuples
[enums]: enums.html
# Ignoring bindings
You can use `_` in a pattern to disregard the type and value.
For example, heres a `match` against a `Result<T, E>`:
```rust
# let some_value: Result<i32, &'static str> = Err("There was an error");
match some_value {
Ok(value) => println!("got a value: {}", value),
Err(_) => println!("an error occurred"),
}
```
In the first arm, we bind the value inside the `Ok` variant to `value`. But
in the `Err` arm, we use `_` to disregard the specific error, and just print
a general error message.
`_` is valid in any pattern that creates a binding. This can be useful to
ignore parts of a larger structure:
```rust
fn coordinate() -> (i32, i32, i32) {
// generate and return some sort of triple tuple
# (1, 2, 3)
}
let (x, _, z) = coordinate();
```
Here, we bind the first and last element of the tuple to `x` and `z`, but
ignore the middle element.
Similarly, you can use `..` in a pattern to disregard multiple values.
```rust
enum OptionalTuple {
Value(i32, i32, i32),
Missing,
}
let x = OptionalTuple::Value(5, -2, 3);
match x {
OptionalTuple::Value(..) => println!("Got a tuple!"),
OptionalTuple::Missing => println!("No such luck."),
}
```
This prints `Got a tuple!`.
# ref and ref mut
If you want to get a [reference][ref], use the `ref` keyword:
```rust
let x = 5;
match x {
ref r => println!("Got a reference to {}", r),
}
```
This prints `Got a reference to 5`.
[ref]: references-and-borrowing.html
Here, the `r` inside the `match` has the type `&i32`. In other words, the `ref`
keyword _creates_ a reference, for use in the pattern. If you need a mutable
reference, `ref mut` will work in the same way:
```rust
let mut x = 5;
match x {
ref mut mr => println!("Got a mutable reference to {}", mr),
}
```
# Ranges
You can match a range of values with `...`:
```rust
let x = 1;
match x {
1 ... 5 => println!("one through five"),
_ => println!("anything"),
}
```
This prints `one through five`.
Ranges are mostly used with integers and `char`s:
```rust
let x = '💅';
match x {
'a' ... 'j' => println!("early letter"),
'k' ... 'z' => println!("late letter"),
_ => println!("something else"),
}
```
This prints `something else`.
# Bindings
You can bind values to names with `@`:
```rust
let x = 1;
match x {
e @ 1 ... 5 => println!("got a range element {}", e),
_ => println!("anything"),
}
```
This prints `got a range element 1`. This is useful when you want to
do a complicated match of part of a data structure:
```rust
#[derive(Debug)]
struct Person {
name: Option<String>,
}
let name = "Steve".to_string();
let mut x: Option<Person> = Some(Person { name: Some(name) });
match x {
Some(Person { name: ref a @ Some(_), .. }) => println!("{:?}", a),
_ => {}
}
```
This prints `Some("Steve")`: weve bound the inner `name` to `a`.
If you use `@` with `|`, you need to make sure the name is bound in each part
of the pattern:
```rust
let x = 5;
match x {
e @ 1 ... 5 | e @ 8 ... 10 => println!("got a range element {}", e),
_ => println!("anything"),
}
```
# Guards
You can introduce match guards with `if`:
```rust
enum OptionalInt {
Value(i32),
Missing,
}
let x = OptionalInt::Value(5);
match x {
OptionalInt::Value(i) if i > 5 => println!("Got an int bigger than five!"),
OptionalInt::Value(..) => println!("Got an int!"),
OptionalInt::Missing => println!("No such luck."),
}
```
This prints `Got an int!`.
If youre using `if` with multiple patterns, the `if` applies to both sides:
```rust
let x = 4;
let y = false;
match x {
4 | 5 if y => println!("yes"),
_ => println!("no"),
}
```
This prints `no`, because the `if` applies to the whole of `4 | 5`, and not to
just the `5`, In other words, the the precedence of `if` behaves like this:
```text
(4 | 5) if y => ...
```
not this:
```text
4 | (5 if y) => ...
```
# Mix and Match
Whew! Thats a lot of different ways to match things, and they can all be

View File

@ -125,6 +125,10 @@ This will print `6`. We make `y` a mutable reference to `x`, then add one to
the thing `y` points at. Youll notice that `x` had to be marked `mut` as well,
if it wasnt, we couldnt take a mutable borrow to an immutable value.
You'll also notice we added an asterisk (`*`) in front of `y`, making it `*y`,
this is because `y` is an `&mut` reference. You'll also need to use them for
accessing the contents of a reference as well.
Otherwise, `&mut` references are just like references. There _is_ a large
difference between the two, and how they interact, though. You can tell
something is fishy in the above example, because we need that extra scope, with
@ -155,8 +159,8 @@ First, any borrow must last for a scope no greater than that of the owner.
Second, you may have one or the other of these two kinds of borrows, but not
both at the same time:
* one or more references (`&T`) to a resource.
* exactly one mutable reference (`&mut T`)
* one or more references (`&T`) to a resource,
* exactly one mutable reference (`&mut T`).
You may notice that this is very similar, though not exactly the same as,
@ -294,8 +298,8 @@ We cant modify `v` because its borrowed by the loop.
### use after free
References must live as long as the resource they refer to. Rust will check the
scopes of your references to ensure that this is true.
References must not live longer than the resource they refer to. Rust will
check the scopes of your references to ensure that this is true.
If Rust didnt check this property, we could accidentally use a reference
which was invalid. For example:

View File

@ -111,7 +111,7 @@ fn process() {
for _ in (0..5_000_000) {
x += 1
}
x
x
})
}).collect();
@ -217,6 +217,17 @@ And finally, we can try running it:
```bash
$ ruby embed.rb
Thread finished with count=5000000
Thread finished with count=5000000
Thread finished with count=5000000
Thread finished with count=5000000
Thread finished with count=5000000
Thread finished with count=5000000
Thread finished with count=5000000
Thread finished with count=5000000
Thread finished with count=5000000
Thread finished with count=5000000
done!
done!
$
```

View File

@ -115,7 +115,7 @@ You can get something similar to an index like this:
let dog = hachiko.chars().nth(1); // kinda like hachiko[1]
```
This emphasizes that we have to go through the whole list of `chars`.
This emphasizes that we have to walk from the beginning of the list of `chars`.
## Slicing

View File

@ -1,6 +1,6 @@
% Structs
Structs are a way of creating more complex data types. For example, if we were
`struct`s are a way of creating more complex data types. For example, if we were
doing calculations involving coordinates in 2D space, we would need both an `x`
and a `y` value:
@ -9,7 +9,7 @@ let origin_x = 0;
let origin_y = 0;
```
A struct lets us combine these two into a single, unified datatype:
A `struct` lets us combine these two into a single, unified datatype:
```rust
struct Point {
@ -28,14 +28,14 @@ Theres a lot going on here, so lets break it down. We declare a `struct` w
the `struct` keyword, and then with a name. By convention, `struct`s begin with
a capital letter and are camel cased: `PointInSpace`, not `Point_In_Space`.
We can create an instance of our struct via `let`, as usual, but we use a `key:
We can create an instance of our `struct` via `let`, as usual, but we use a `key:
value` style syntax to set each field. The order doesnt need to be the same as
in the original declaration.
Finally, because fields have names, we can access the field through dot
notation: `origin.x`.
The values in structs are immutable by default, like other bindings in Rust.
The values in `struct`s are immutable by default, like other bindings in Rust.
Use `mut` to make them mutable:
```rust
@ -91,7 +91,7 @@ fn main() {
# Update syntax
A `struct` can include `..` to indicate that you want to use a copy of some
other struct for some of the values. For example:
other `struct` for some of the values. For example:
```rust
struct Point3d {
@ -121,7 +121,7 @@ let point = Point3d { z: 1, x: 2, .. origin };
# Tuple structs
Rust has another data type thats like a hybrid between a [tuple][tuple] and a
struct, called a tuple struct. Tuple structs have a name, but
`struct`, called a tuple struct. Tuple structs have a name, but
their fields dont:
```rust
@ -140,7 +140,7 @@ let black = Color(0, 0, 0);
let origin = Point(0, 0, 0);
```
It is almost always better to use a struct than a tuple struct. We would write
It is almost always better to use a `struct` than a tuple struct. We would write
`Color` and `Point` like this instead:
```rust
@ -158,7 +158,7 @@ struct Point {
```
Now, we have actual names, rather than positions. Good names are important,
and with a struct, we have actual names.
and with a `struct`, we have actual names.
There _is_ one case when a tuple struct is very useful, though, and thats a
tuple struct with only one element. We call this the newtype pattern, because
@ -180,13 +180,13 @@ destructuring `let`, just as with regular tuples. In this case, the
# Unit-like structs
You can define a struct with no members at all:
You can define a `struct` with no members at all:
```rust
struct Electron;
```
Such a struct is called unit-like because it resembles the empty
Such a `struct` is called unit-like because it resembles the empty
tuple, `()`, sometimes called unit. Like a tuple struct, it defines a
new type.
@ -195,6 +195,6 @@ marker type), but in combination with other features, it can become
useful. For instance, a library may ask you to create a structure that
implements a certain [trait][trait] to handle events. If you dont have
any data you need to store in the structure, you can just create a
unit-like struct.
unit-like `struct`.
[trait]: traits.html

View File

@ -120,13 +120,26 @@ And that's reflected in the summary line:
test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured
```
We also get a non-zero status code:
We also get a non-zero status code. We can use `$?` on OS X and Linux:
```bash
$ echo $?
101
```
On Windows, if youre using `cmd`:
```bash
> echo %ERRORLEVEL%
```
And if youre using PowerShell:
```bash
> echo $LASTEXITCODE # the code itself
> echo $? # a boolean, fail or succeed
```
This is useful if you want to integrate `cargo test` into other tooling.
We can invert our test's failure with another attribute: `should_panic`:
@ -219,6 +232,66 @@ fn it_works() {
This is a very common use of `assert_eq!`: call some function with
some known arguments and compare it to the expected output.
# The `ignore` attribute
Sometimes a few specific tests can be very time-consuming to execute. These
can be disabled by default by using the `ignore` attribute:
```rust
#[test]
fn it_works() {
assert_eq!(4, add_two(2));
}
#[test]
#[ignore]
fn expensive_test() {
// code that takes an hour to run
}
```
Now we run our tests and see that `it_works` is run, but `expensive_test` is
not:
```bash
$ cargo test
Compiling adder v0.0.1 (file:///home/you/projects/adder)
Running target/adder-91b3e234d4ed382a
running 2 tests
test expensive_test ... ignored
test it_works ... ok
test result: ok. 1 passed; 0 failed; 1 ignored; 0 measured
Doc-tests adder
running 0 tests
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured
```
The expensive tests can be run explicitly using `cargo test -- --ignored`:
```bash
$ cargo test -- --ignored
Running target/adder-91b3e234d4ed382a
running 1 test
test expensive_test ... ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured
Doc-tests adder
running 0 tests
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured
```
The `--ignored` argument is an argument to the test binary, and not to cargo,
which is why the command is `cargo test -- --ignored`.
# The `tests` module
There is one way in which our existing example is not idiomatic: it's
@ -355,8 +428,8 @@ Let's finally check out that third section: documentation tests.
Nothing is better than documentation with examples. Nothing is worse than
examples that don't actually work, because the code has changed since the
documentation has been written. To this end, Rust supports automatically
running examples in your documentation. Here's a fleshed-out `src/lib.rs`
with examples:
running examples in your documentation (**note:** this only works in library
crates, not binary crates). Here's a fleshed-out `src/lib.rs` with examples:
```rust,ignore
//! The `adder` crate provides functions that add numbers to other numbers.

View File

@ -38,7 +38,7 @@ local variables and some other information. This is called a stack frame,
for the purpose of this tutorial, were going to ignore the extra information
and just consider the local variables were allocating. So in this case, when
`main()` is run, well allocate a single 32-bit integer for our stack frame.
This is automatically handled for you, as you can see, we didnt have to write
This is automatically handled for you, as you can see; we didnt have to write
any special Rust code or anything.
When the function is over, its stack frame gets deallocated. This happens
@ -51,7 +51,7 @@ well throw them all away at the same time as well, we can get rid of it very
fast too.
The downside is that we cant keep values around if we need them for longer
than a single function. We also havent talked about what that name, stack
than a single function. We also havent talked about what the word, stack,
means. To do that, we need a slightly more complicated example:
```rust
@ -217,12 +217,12 @@ on the heap. The actual value of the box is a structure which has a pointer to
it allocates some memory for the heap, and puts `5` there. The memory now looks
like this:
| Address | Name | Value |
|-----------------|------|----------------|
| 2<sup>30</sup> | | 5 |
| ... | ... | ... |
| 1 | y | 42 |
| 0 | x | 2<sup>30</sup> |
| Address | Name | Value |
|-----------------|------|------------------|
| 2<sup>30</sup> | | 5 |
| ... | ... | ... |
| 1 | y | 42 |
| 0 | x | 2<sup>30</sup> |
We have 2<sup>30</sup> in our hypothetical computer with 1GB of RAM. And since
our stack grows from zero, the easiest place to allocate memory is from the
@ -242,17 +242,17 @@ freed in any order, it can end up with holes. Heres a diagram of the me
layout of a program which has been running for a while now:
| Address | Name | Value |
|----------------------|------|----------------------|
| 2<sup>30</sup> | | 5 |
| (2<sup>30</sup>) - 1 | | |
| (2<sup>30</sup>) - 2 | | |
| (2<sup>30</sup>) - 3 | | 42 |
| ... | ... | ... |
| 3 | y | (2<sup>30</sup>) - 3 |
| 2 | y | 42 |
| 1 | y | 42 |
| 0 | x | 2<sup>30</sup> |
| Address | Name | Value |
|----------------------|------|------------------------|
| 2<sup>30</sup> | | 5 |
| (2<sup>30</sup>) - 1 | | |
| (2<sup>30</sup>) - 2 | | |
| (2<sup>30</sup>) - 3 | | 42 |
| ... | ... | ... |
| 3 | y | (2<sup>30</sup>) - 3 |
| 2 | y | 42 |
| 1 | y | 42 |
| 0 | x | 2<sup>30</sup> |
In this case, weve allocated four things on the heap, but deallocated two of
them. Theres a gap between 2<sup>30</sup> and (2<sup>30</sup>) - 3 which isnt
@ -304,22 +304,22 @@ fn main() {
When we enter `main()`, memory looks like this:
| Address | Name | Value |
|---------|------|-------|
| 1 | y | 0 |
| 0 | x | 5 |
| Address | Name | Value |
|---------|------|--------|
| 1 | y | 0 |
| 0 | x | 5 |
`x` is a plain old `5`, and `y` is a reference to `x`. So its value is the
memory location that `x` lives at, which in this case is `0`.
What about when we call `foo()`, passing `y` as an argument?
| Address | Name | Value |
|---------|------|-------|
| 3 | z | 42 |
| 2 | i | 0 |
| 1 | y | 0 |
| 0 | x | 5 |
| Address | Name | Value |
|---------|------|--------|
| 3 | z | 42 |
| 2 | i | 0 |
| 1 | y | 0 |
| 0 | x | 5 |
Stack frames arent just for local bindings, theyre for arguments too. So in
this case, we need to have both `i`, our argument, and `z`, our local variable
@ -366,29 +366,29 @@ fn main() {
First, we call `main()`:
| Address | Name | Value |
|-----------------|------|----------------|
| 2<sup>30</sup> | | 20 |
| ... | ... | ... |
| 2 | j | 0 |
| 1 | i | 2<sup>30</sup> |
| 0 | h | 3 |
| Address | Name | Value |
|-----------------|------|------------------|
| 2<sup>30</sup> | | 20 |
| ... | ... | ... |
| 2 | j | 0 |
| 1 | i | 2<sup>30</sup> |
| 0 | h | 3 |
We allocate memory for `j`, `i`, and `h`. `i` is on the heap, and so has a
value pointing there.
Next, at the end of `main()`, `foo()` gets called:
| Address | Name | Value |
|-----------------|------|----------------|
| 2<sup>30</sup> | | 20 |
| ... | ... | ... |
| 5 | z | 4 |
| 4 | y | 10 |
| 3 | x | 0 |
| 2 | j | 0 |
| 1 | i | 2<sup>30</sup> |
| 0 | h | 3 |
| Address | Name | Value |
|-----------------|------|-----------------|
| 2<sup>30</sup> | | 20 |
| ... | ... | ... |
| 5 | z | 4 |
| 4 | y | 10 |
| 3 | x | 0 |
| 2 | j | 0 |
| 1 | i | 2<sup>30</sup>|
| 0 | h | 3 |
Space gets allocated for `x`, `y`, and `z`. The argument `x` has the same value
as `j`, since thats what we passed it in. Its a pointer to the `0` address,
@ -396,51 +396,51 @@ since `j` points at `h`.
Next, `foo()` calls `baz()`, passing `z`:
| Address | Name | Value |
|-----------------|------|----------------|
| 2<sup>30</sup> | | 20 |
| ... | ... | ... |
| 7 | g | 100 |
| 6 | f | 4 |
| 5 | z | 4 |
| 4 | y | 10 |
| 3 | x | 0 |
| 2 | j | 0 |
| 1 | i | 2<sup>30</sup> |
| 0 | h | 3 |
| Address | Name | Value |
|-----------------|------|------------------|
| 2<sup>30</sup> | | 20 |
| ... | ... | ... |
| 7 | g | 100 |
| 6 | f | 4 |
| 5 | z | 4 |
| 4 | y | 10 |
| 3 | x | 0 |
| 2 | j | 0 |
| 1 | i | 2<sup>30</sup> |
| 0 | h | 3 |
Weve allocated memory for `f` and `g`. `baz()` is very short, so when its
over, we get rid of its stack frame:
| Address | Name | Value |
|-----------------|------|----------------|
| 2<sup>30</sup> | | 20 |
| ... | ... | ... |
| 5 | z | 4 |
| 4 | y | 10 |
| 3 | x | 0 |
| 2 | j | 0 |
| 1 | i | 2<sup>30</sup> |
| 0 | h | 3 |
| Address | Name | Value |
|-----------------|------|------------------|
| 2<sup>30</sup> | | 20 |
| ... | ... | ... |
| 5 | z | 4 |
| 4 | y | 10 |
| 3 | x | 0 |
| 2 | j | 0 |
| 1 | i | 2<sup>30</sup> |
| 0 | h | 3 |
Next, `foo()` calls `bar()` with `x` and `z`:
| Address | Name | Value |
|----------------------|------|----------------------|
| 2<sup>30</sup> | | 20 |
| (2<sup>30</sup>) - 1 | | 5 |
| ... | ... | ... |
| 10 | e | 9 |
| 9 | d | (2<sup>30</sup>) - 1 |
| 8 | c | 5 |
| 7 | b | 4 |
| 6 | a | 0 |
| 5 | z | 4 |
| 4 | y | 10 |
| 3 | x | 0 |
| 2 | j | 0 |
| 1 | i | 2<sup>30</sup> |
| 0 | h | 3 |
| Address | Name | Value |
|----------------------|------|------------------------|
| 2<sup>30</sup> | | 20 |
| (2<sup>30</sup>) - 1 | | 5 |
| ... | ... | ... |
| 10 | e | 9 |
| 9 | d | (2<sup>30</sup>) - 1 |
| 8 | c | 5 |
| 7 | b | 4 |
| 6 | a | 0 |
| 5 | z | 4 |
| 4 | y | 10 |
| 3 | x | 0 |
| 2 | j | 0 |
| 1 | i | 2<sup>30</sup> |
| 0 | h | 3 |
We end up allocating another value on the heap, and so we have to subtract one
from 2<sup>30</sup>. Its easier to just write that than `1,073,741,823`. In any
@ -448,70 +448,70 @@ case, we set up the variables as usual.
At the end of `bar()`, it calls `baz()`:
| Address | Name | Value |
|----------------------|------|----------------------|
| 2<sup>30</sup> | | 20 |
| (2<sup>30</sup>) - 1 | | 5 |
| ... | ... | ... |
| 12 | g | 100 |
| 11 | f | 9 |
| 10 | e | 9 |
| 9 | d | (2<sup>30</sup>) - 1 |
| 8 | c | 5 |
| 7 | b | 4 |
| 6 | a | 0 |
| 5 | z | 4 |
| 4 | y | 10 |
| 3 | x | 0 |
| 2 | j | 0 |
| 1 | i | 2<sup>30</sup> |
| 0 | h | 3 |
| Address | Name | Value |
|----------------------|------|------------------------|
| 2<sup>30</sup> | | 20 |
| (2<sup>30</sup>) - 1 | | 5 |
| ... | ... | ... |
| 12 | g | 100 |
| 11 | f | 9 |
| 10 | e | 9 |
| 9 | d | (2<sup>30</sup>) - 1 |
| 8 | c | 5 |
| 7 | b | 4 |
| 6 | a | 0 |
| 5 | z | 4 |
| 4 | y | 10 |
| 3 | x | 0 |
| 2 | j | 0 |
| 1 | i | 2<sup>30</sup> |
| 0 | h | 3 |
With this, were at our deepest point! Whew! Congrats for following along this
far.
After `baz()` is over, we get rid of `f` and `g`:
| Address | Name | Value |
|----------------------|------|----------------------|
| 2<sup>30</sup> | | 20 |
| (2<sup>30</sup>) - 1 | | 5 |
| ... | ... | ... |
| 10 | e | 9 |
| 9 | d | (2<sup>30</sup>) - 1 |
| 8 | c | 5 |
| 7 | b | 4 |
| 6 | a | 0 |
| 5 | z | 4 |
| 4 | y | 10 |
| 3 | x | 0 |
| 2 | j | 0 |
| 1 | i | 2<sup>30</sup> |
| 0 | h | 3 |
| Address | Name | Value |
|----------------------|------|------------------------|
| 2<sup>30</sup> | | 20 |
| (2<sup>30</sup>) - 1 | | 5 |
| ... | ... | ... |
| 10 | e | 9 |
| 9 | d | (2<sup>30</sup>) - 1 |
| 8 | c | 5 |
| 7 | b | 4 |
| 6 | a | 0 |
| 5 | z | 4 |
| 4 | y | 10 |
| 3 | x | 0 |
| 2 | j | 0 |
| 1 | i | 2<sup>30</sup> |
| 0 | h | 3 |
Next, we return from `bar()`. `d` in this case is a `Box<T>`, so it also frees
what it points to: (2<sup>30</sup>) - 1.
| Address | Name | Value |
|-----------------|------|----------------|
| 2<sup>30</sup> | | 20 |
| ... | ... | ... |
| 5 | z | 4 |
| 4 | y | 10 |
| 3 | x | 0 |
| 2 | j | 0 |
| 1 | i | 2<sup>30</sup> |
| 0 | h | 3 |
| Address | Name | Value |
|-----------------|------|------------------|
| 2<sup>30</sup> | | 20 |
| ... | ... | ... |
| 5 | z | 4 |
| 4 | y | 10 |
| 3 | x | 0 |
| 2 | j | 0 |
| 1 | i | 2<sup>30</sup> |
| 0 | h | 3 |
And after that, `foo()` returns:
| Address | Name | Value |
|-----------------|------|----------------|
| 2<sup>30</sup> | | 20 |
| ... | ... | ... |
| 2 | j | 0 |
| 1 | i | 2<sup>30</sup> |
| 0 | h | 3 |
| Address | Name | Value |
|-----------------|------|------------------|
| 2<sup>30</sup> | | 20 |
| ... | ... | ... |
| 2 | j | 0 |
| 1 | i | 2<sup>30</sup> |
| 0 | h | 3 |
And then, finally, `main()`, which cleans the rest up. When `i` is `Drop`ped,
it will clean up the last of the heap too.
@ -549,7 +549,7 @@ reuse.
If youd like to dive into this topic in greater detail, [this paper][wilson]
is a great introduction.
[wilson]: http://www.cs.northwestern.edu/~pdinda/icsclass/doc/dsa.pdf
[wilson]: http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.143.4688
## Semantic impact

View File

@ -300,3 +300,41 @@ let y = TraitObject {
// y.method();
(y.vtable.method)(y.data);
```
## Object Safety
Not every trait can be used to make a trait object. For example, vectors implement
`Clone`, but if we try to make a trait object:
```ignore
let v = vec![1, 2, 3];
let o = &v as &Clone;
```
We get an error:
```text
error: cannot convert to a trait object because trait `core::clone::Clone` is not object-safe [E0038]
let o = &v as &Clone;
^~
note: the trait cannot require that `Self : Sized`
let o = &v as &Clone;
^~
```
The error says that `Clone` is not object-safe. Only traits that are
object-safe can be made into trait objects. A trait is object-safe if both of
these are true:
* the trait does not require that `Self: Sized`
* all of its methods are object-safe
So what makes a method object-safe? Each method must require that `Self: Sized`
or all of the following:
* must not have any type parameters
* must not use `Self`
Whew! As we can see, almost all of these rules talk about `Self`. A good intuition
is “except in special circumstances, if your traits method uses `Self`, it is not
object-safe.”

View File

@ -47,8 +47,11 @@ As you can see, the `trait` block looks very similar to the `impl` block,
but we dont define a body, just a type signature. When we `impl` a trait,
we use `impl Trait for Item`, rather than just `impl Item`.
We can use traits to constrain our generics. Consider this function, which
does not compile:
## Traits bounds for generic functions
Traits are useful because they allow a type to make certain promises about its
behavior. Generic functions can exploit this to constrain the types they
accept. Consider this function, which does not compile:
```rust,ignore
fn print_area<T>(shape: T) {
@ -75,7 +78,7 @@ fn print_area<T: HasArea>(shape: T) {
}
```
The syntax `<T: HasArea>` means `any type that implements the HasArea trait`.
The syntax `<T: HasArea>` means “any type that implements the `HasArea` trait.”
Because traits define function type signatures, we can be sure that any type
which implements `HasArea` will have an `.area()` method.
@ -152,6 +155,63 @@ We get a compile-time error:
error: the trait `HasArea` is not implemented for the type `_` [E0277]
```
## Traits bounds for generic structs
Your generic structs can also benefit from trait constraints. All you need to
do is append the constraint when you declare type parameters. Here is a new
type `Rectangle<T>` and its operation `is_square()`:
```rust
struct Rectangle<T> {
x: T,
y: T,
width: T,
height: T,
}
impl<T: PartialEq> Rectangle<T> {
fn is_square(&self) -> bool {
self.width == self.height
}
}
fn main() {
let mut r = Rectangle {
x: 0,
y: 0,
width: 47,
height: 47,
};
assert!(r.is_square());
r.height = 42;
assert!(!r.is_square());
}
```
`is_square()` needs to check that the sides are equal, so the sides must be of
a type that implements the [`core::cmp::PartialEq`][PartialEq] trait:
```ignore
impl<T: PartialEq> Rectangle<T> { ... }
```
Now, a rectangle can be defined in terms of any type that can be compared for
equality.
[PartialEq]: ../core/cmp/trait.PartialEq.html
Here we defined a new struct `Rectangle` that accepts numbers of any
precision—really, objects of pretty much any type—as long as they can be
compared for equality. Could we do the same for our `HasArea` structs, `Square`
and `Circle`? Yes, but they need multiplication, and to work with that we need
to know more about [operator traits][operators-and-overloading].
[operators-and-overloading]: operators-and-overloading.html
# Rules for implementing traits
So far, weve only added trait implementations to structs, but you can
implement a trait for any type. So technically, we _could_ implement `HasArea`
for `i32`:
@ -175,7 +235,7 @@ impl HasArea for i32 {
It is considered poor style to implement methods on such primitive types, even
though it is possible.
This may seem like the Wild West, but there are two other restrictions around
This may seem like the Wild West, but there are two restrictions around
implementing traits that prevent this from getting out of hand. The first is
that if the trait isnt defined in your scope, it doesnt apply. Heres an
example: the standard library provides a [`Write`][write] trait which adds
@ -330,7 +390,7 @@ fn normal<T: ConvertTo<i64>>(x: &T) -> i64 {
// can be called with T == i64
fn inverse<T>() -> T
// this is using ConvertTo as if it were "ConvertFrom<i32>"
// this is using ConvertTo as if it were "ConvertTo<i64>"
where i32: ConvertTo<T> {
42.convert()
}
@ -340,10 +400,10 @@ This shows off the additional feature of `where` clauses: they allow bounds
where the left-hand side is an arbitrary type (`i32` in this case), not just a
plain type parameter (like `T`).
## Default methods
# Default methods
Theres one last feature of traits we should cover: default methods. Its
easiest just to show an example:
If you already know how a typical implementor will define a method, you can
let your trait supply a default:
```rust
trait Foo {

View File

@ -1,6 +1,6 @@
<div id="versioninfo">
<img src="http://www.rust-lang.org/logos/rust-logo-32x32-blk.png" width="32" height="32" alt><br>
<span class="white-sticker"><a href="http://rust-lang.org">Rust</a> VERSION</span><br>
<a href="http://github.com/rust-lang/rust/commit/STAMP"
<img src="https://www.rust-lang.org/logos/rust-logo-32x32-blk.png" width="32" height="32" alt><br>
<span class="white-sticker"><a href="https://www.rust-lang.org">Rust</a> VERSION</span><br>
<a href="https://github.com/rust-lang/rust/commit/STAMP"
class="hash white-sticker">SHORT_HASH</a>
</div>

134
src/etc/dec2flt_table.py Normal file
View File

@ -0,0 +1,134 @@
#!/usr/bin/env python2.7
#
# 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.
"""
Generate powers of ten using William Clinger's ``AlgorithmM`` for use in
decimal to floating point conversions.
Specifically, computes and outputs (as Rust code) a table of 10^e for some
range of exponents e. The output is one array of 64 bit significands and
another array of corresponding base two exponents. The approximations are
normalized and rounded perfectly, i.e., within 0.5 ULP of the true value.
The representation ([u64], [i16]) instead of the more natural [(u64, i16)]
is used because (u64, i16) has a ton of padding which would make the table
even larger, and it's already uncomfortably large (6 KiB).
"""
from __future__ import print_function
import sys
from fractions import Fraction
from collections import namedtuple
N = 64 # Size of the significand field in bits
MIN_SIG = 2 ** (N - 1)
MAX_SIG = (2 ** N) - 1
# Hand-rolled fp representation without arithmetic or any other operations.
# The significand is normalized and always N bit, but the exponent is
# unrestricted in range.
Fp = namedtuple('Fp', 'sig exp')
def algorithm_m(f, e):
assert f > 0
if e < 0:
u = f
v = 10 ** abs(e)
else:
u = f * 10 ** e
v = 1
k = 0
x = u // v
while True:
if x < MIN_SIG:
u <<= 1
k -= 1
elif x >= MAX_SIG:
v <<= 1
k += 1
else:
break
x = u // v
return ratio_to_float(u, v, k)
def ratio_to_float(u, v, k):
q, r = divmod(u, v)
v_r = v - r
z = Fp(q, k)
if r < v_r:
return z
elif r > v_r:
return next_float(z)
elif q % 2 == 0:
return z
else:
return next_float(z)
def next_float(z):
if z.sig == MAX_SIG:
return Fp(MIN_SIG, z.exp + 1)
else:
return Fp(z.sig + 1, z.exp)
def error(f, e, z):
decimal = f * Fraction(10) ** e
binary = z.sig * Fraction(2) ** z.exp
abs_err = abs(decimal - binary)
# The unit in the last place has value z.exp
ulp_err = abs_err / Fraction(2) ** z.exp
return float(ulp_err)
LICENSE = """
// 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.
"""
def main():
MIN_E = -305
MAX_E = 305
e_range = range(MIN_E, MAX_E+1)
powers = []
for e in e_range:
z = algorithm_m(1, e)
err = error(1, e, z)
assert err < 0.5
powers.append(z)
typ = "([u64; {0}], [i16; {0}])".format(len(e_range))
print(LICENSE.strip())
print("// Table of approximations of powers of ten.")
print("// DO NOT MODIFY: Generated by a src/etc/dec2flt_table.py")
print("pub const MIN_E: i16 = {};".format(MIN_E))
print("pub const MAX_E: i16 = {};".format(MAX_E))
print()
print("pub const POWERS: ", typ, " = ([", sep='')
for z in powers:
print(" 0x{:x},".format(z.sig))
print("], [")
for z in powers:
print(" {},".format(z.exp))
print("]);")
if __name__ == '__main__':
main()

View File

@ -47,20 +47,24 @@ with open(feature_gate_source, 'r') as f:
is_feature_line = True
if is_feature_line:
line = line.replace("(", "").replace("),", "").replace(")", "")
# turn ` ("foo", "1.0.0", Some(10), Active)` into
# `"foo", "1.0.0", Some(10), Active`
line = line.strip(' ,()')
parts = line.split(",")
if len(parts) != 3:
if len(parts) != 4:
print("error: unexpected number of components in line: " + original_line)
sys.exit(1)
feature_name = parts[0].strip().replace('"', "")
since = parts[1].strip().replace('"', "")
status = parts[2].strip()
issue = parts[2].strip()
status = parts[3].strip()
assert len(feature_name) > 0
assert len(since) > 0
assert len(issue) > 0
assert len(status) > 0
language_feature_names += [feature_name]
language_features += [(feature_name, since, status)]
language_features += [(feature_name, since, issue, status)]
assert len(language_features) > 0
@ -158,7 +162,7 @@ for f in language_features:
status = "unstable"
stable_since = None
if f[2] == "Accepted":
if f[3] == "Accepted":
status = "stable"
if status == "stable":
stable_since = f[1]

View File

@ -45,7 +45,7 @@ def make_win_dist(rust_root, gcc_root, target_triple):
elif key == "libraries":
lib_path.extend(val.lstrip(' =').split(';'))
target_tools = ["gcc.exe", "ld.exe", "ar.exe", "dlltool.exe", "windres.exe"]
target_tools = ["gcc.exe", "ld.exe", "ar.exe", "dlltool.exe"]
rustc_dlls = ["libstdc++-6.dll"]
if target_triple.startswith("i686-"):

View File

@ -41,14 +41,14 @@ def convert_path_spec(name, value):
make = sys.argv[2]
putenv('RUSTC', os.path.abspath(sys.argv[3]))
putenv('TMPDIR', os.path.abspath(sys.argv[4]))
putenv('CC', sys.argv[5])
putenv('RUSTDOC', os.path.abspath(sys.argv[6]))
filt = sys.argv[7]
putenv('LD_LIB_PATH_ENVVAR', sys.argv[8])
putenv('HOST_RPATH_DIR', os.path.abspath(sys.argv[9]))
putenv('TARGET_RPATH_DIR', os.path.abspath(sys.argv[10]))
putenv('RUST_BUILD_STAGE', sys.argv[11])
putenv('S', os.path.abspath(sys.argv[12]))
putenv('CC', sys.argv[5] + ' ' + sys.argv[6])
putenv('RUSTDOC', os.path.abspath(sys.argv[7]))
filt = sys.argv[8]
putenv('LD_LIB_PATH_ENVVAR', sys.argv[9])
putenv('HOST_RPATH_DIR', os.path.abspath(sys.argv[10]))
putenv('TARGET_RPATH_DIR', os.path.abspath(sys.argv[11]))
putenv('RUST_BUILD_STAGE', sys.argv[12])
putenv('S', os.path.abspath(sys.argv[13]))
putenv('PYTHON', sys.executable)
if filt not in sys.argv[1]:

View File

@ -0,0 +1,592 @@
{
"platform": "aarch64",
"intrinsic_prefix": "aarch64_v",
"llvm_prefix": "llvm.aarch64.neon.",
"number_info": {
"signed": {
"kind": "s",
"data_type": { "pattern": "s{bitwidth}" }
},
"unsigned": {
"kind": "u",
"data_type": { "pattern": "u{bitwidth}" }
},
"float": {
"kind": "f",
"data_type": { "pattern": "f{bitwidth}" }
}
},
"width_info": {
"64": { "width": "" },
"128": { "width": "q" }
},
"intrinsics": [
{
"intrinsic": "hadd{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "{0.kind}hadd.{0.llvm_name}",
"ret": "i(8-32)",
"args": ["0", "0"]
},
{
"intrinsic": "rhadd{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "{0.kind}rhadd.{0.llvm_name}",
"ret": "i(8-32)",
"args": ["0", "0"]
},
{
"intrinsic": "qadd{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "{0.kind}qadd.{0.llvm_name}",
"ret": "i(8-64)",
"args": ["0", "0"]
},
{
"intrinsic": "uqadd_{0.data_type}",
"width": [128],
"llvm": "suqadd.{0.llvm_name}",
"ret": "s(8-64)",
"args": ["0", "0u"]
},
{
"intrinsic": "sqadd_{0.data_type}",
"width": [128],
"llvm": "usqadd.{0.llvm_name}",
"ret": "u(8-64)",
"args": ["0", "0s"]
},
{
"intrinsic": "raddhn_{1.data_type}",
"width": [64],
"llvm": "raddhn.{0.llvm_name}",
"ret": "i(8-32)",
"args": ["0w", "0w"]
},
{
"intrinsic": "fmulx{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "fmulx.{0.llvm_name}",
"ret": "f(32-64)",
"args": ["0", "0"]
},
{
"intrinsic": "fma{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "!llvm.fma.{0.llvm_name}",
"ret": "f(32-64)",
"args": ["0", "0"]
},
{
"intrinsic": "qdmulh{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "sqdmulh.{0.llvm_name}",
"ret": "s(16-32)",
"args": ["0", "0"]
},
{
"intrinsic": "qrdmulh{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "sqrdmulh.{0.llvm_name}",
"ret": "s(16-32)",
"args": ["0", "0"]
},
{
"intrinsic": "mull_{1.data_type}",
"width": [128],
"llvm": "{0.kind}mull.{0.llvm_name}",
"ret": "i(16-64)",
"args": ["0n", "0n"]
},
{
"intrinsic": "qdmull{0.width}_{1.data_type}",
"width": [128],
"llvm": "sqdmull.{0.llvm_name}",
"ret": "s(16-32)",
"args": ["0n", "0n"]
},
{
"intrinsic": "hsub{0.width}_{1.data_type}",
"width": [64, 128],
"llvm": "{0.kind}hsub.{0.llvm_name}",
"ret": "i(8-32)",
"args": ["0", "0"]
},
{
"intrinsic": "qsub{0.width}_{1.data_type}",
"width": [64, 128],
"llvm": "{0.kind}qsub.{0.llvm_name}",
"ret": "i(8-64)",
"args": ["0", "0"]
},
{
"intrinsic": "rsubhn_{1.data_type}",
"width": [64],
"llvm": "rsubhn.{0.llvm_name}",
"ret": "i(8-32)",
"args": ["0w", "0w"]
},
{
"intrinsic": "abd{0.width}_{1.data_type}",
"width": [64, 128],
"llvm": "{0.kind}abd.{0.llvm_name}",
"ret": ["i(8-32)","f(32-64)"],
"args": ["0", "0"]
},
{
"intrinsic": "max{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "{0.kind}max.{0.llvm_name}",
"ret": ["i(8-32)","f(32-64)"],
"args": ["0", "0"]
},
{
"intrinsic": "min{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "{0.kind}min.{0.llvm_name}",
"ret": ["i(8-32)","f(32-64)"],
"args": ["0", "0"]
},
{
"intrinsic": "maxnm{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "{0.kind}maxnm.{0.llvm_name}",
"ret": "f(32-64)",
"args": ["0", "0"]
},
{
"intrinsic": "minnm{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "{0.kind}minnm.{0.llvm_name}",
"ret": "f(32-64)",
"args": ["0", "0"]
},
{
"intrinsic": "shl{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "{0.kind}shl.{0.llvm_name}",
"ret": "i(8-64)",
"args": ["0", "0s"]
},
{
"intrinsic": "qshl{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "{0.kind}qshl.{0.llvm_name}",
"ret": "i(8-64)",
"args": ["0", "0s"]
},
{
"intrinsic": "rshl{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "{0.kind}rshl.{0.llvm_name}",
"ret": "i(8-64)",
"args": ["0", "0s"]
},
{
"intrinsic": "qrshl{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "{0.kind}qrshl.{0.llvm_name}",
"ret": "i(8-64)",
"args": ["0", "0s"]
},
{
"intrinsic": "qshrun_n_{1.data_type}",
"width": [64],
"llvm": "sqshrun.{0.llvm_name}",
"ret": "s(8-32)",
"args": ["0w", "U32"]
},
{
"intrinsic": "qrshrun_n_{1.data_type}",
"width": [64],
"llvm": "sqrshrun.{0.llvm_name}",
"ret": "s(8-32)",
"args": ["0w", "U32"]
},
{
"intrinsic": "qshrn_n_{1.data_type}",
"width": [64],
"llvm": "{0.kind}qshrn.{0.llvm_name}",
"ret": "i(8-32)",
"args": ["0w", "U32"]
},
{
"intrinsic": "rshrn_n_{1.data_type}",
"width": [64],
"llvm": "rshrn.{0.llvm_name}",
"ret": "i(8-32)",
"args": ["0w", "U32"]
},
{
"intrinsic": "qrshrn_n_{1.data_type}",
"width": [64],
"llvm": "{0.kind}qrshrn.{0.llvm_name}",
"ret": "i(8-32)",
"args": ["0w", "U32"]
},
{
"intrinsic": "sri{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "vsri.{0.llvm_name}",
"ret": "i(8-64)",
"args": ["0", "0"]
},
{
"intrinsic": "sli{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "vsli.{0.llvm_name}",
"ret": "i(8-64)",
"args": ["0", "0"]
},
{
"intrinsic": "vqmovn_{1.data_type}",
"width": [64],
"llvm": "{0.kind}qxtn.{0.llvm_name}",
"ret": "i(8-32)",
"args": ["0w"]
},
{
"intrinsic": "abs{0.width}_{0.data_type}",
"width": [64,128],
"llvm": "abs.{0.llvm_name}",
"ret": "s(8-64)",
"args": ["0"]
},
{
"intrinsic": "abs{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "!llvm.fabs.{0.llvm_name}",
"ret": "f(32-64)",
"args": ["0"]
},
{
"intrinsic": "qabs{0.width}_{0.data_type}",
"width": [64,128],
"llvm": "sqabs.{0.llvm_name}",
"ret": "s(8-64)",
"args": ["0"]
},
{
"intrinsic": "qneg{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "sqneg.{0.llvm_name}",
"ret": "s(8-64)",
"args": ["0"]
},
{
"intrinsic": "clz{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "!llvm.ctlz.{0.llvm_name}",
"ret": "i(8-32)",
"args": ["0"]
},
{
"intrinsic": "cls{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "cls.{0.llvm_name}",
"ret": "i(8-32)",
"args": ["0"]
},
{
"intrinsic": "cnt{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "!llvm.ctpop.{0.llvm_name}",
"ret": "i8",
"args": ["0"]
},
{
"intrinsic": "recpe{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "{0.kind}recpe.{0.llvm_name}",
"ret": ["u32","f(32-64)"],
"args": ["0"]
},
{
"intrinsic": "recps{0.width}_{0.data_type}",
"width": [64,128],
"llvm": "frecps.{0.llvm_name}",
"ret": "f(32-64)",
"args": ["0", "0"]
},
{
"intrinsic": "sqrt{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "!llvm.sqrt.{0.llvm_name}",
"ret": "f(32-64)",
"args": ["0"]
},
{
"intrinsic": "rsqrte{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "{0.kind}rsqrte.{0.llvm_name}",
"ret": ["u32","f(32-64)"],
"args": ["0"]
},
{
"intrinsic": "rsqrts{0.width}_{0.data_type}",
"width": [64,128],
"llvm": "frsqrts.{0.llvm_name}",
"ret": "f(32-64)",
"args": ["0", "0"]
},
{
"intrinsic": "rbit{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "rbit.{0.llvm_name}",
"ret": "i8",
"args": ["0"]
},
{
"intrinsic": "ld2{0[0].width}_{0[0].data_type}",
"width": [64, 128],
"llvm": "ld2.{0[0].llvm_name}.{1.llvm_name}",
"ret": ["[i(8-64);2]","[f(32-64);2]"],
"args": ["0.0SPc/0.0"]
},
{
"intrinsic": "ld3{0[0].width}_{0[0].data_type}",
"width": [64, 128],
"llvm": "ld3.{0[0].llvm_name}.{1.llvm_name}",
"ret": ["[i(8-64);3]","[f(32-64);3]"],
"args": ["0.0SPc/0.0"]
},
{
"intrinsic": "ld4{0[0].width}_{0[0].data_type}",
"width": [64, 128],
"llvm": "ld4.{0[0].llvm_name}.{1.llvm_name}",
"ret": ["[i(8-64);4]","[f(32-64);4]"],
"args": ["0.0SPc/0.0"]
},
{
"intrinsic": "ld2{0[0].width}_dup_{0[0].data_type}",
"width": [64, 128],
"llvm": "ld2.{0[0].llvm_name}.{1.llvm_name}",
"ret": ["[i(8-64);2]","[f(32-64);2]"],
"args": ["0.0SPc"]
},
{
"intrinsic": "ld3{0[0].width}_dup_{0[0].data_type}",
"width": [64, 128],
"llvm": "ld3.{0[0].llvm_name}.{1.llvm_name}",
"ret": ["[i(8-64);3]","[f(32-64);3]"],
"args": ["0.0SPc"]
},
{
"intrinsic": "ld4{0[0].width}_dup_{0[0].data_type}",
"width": [64, 128],
"llvm": "ld4.{0[0].llvm_name}.{1.llvm_name}",
"ret": ["[i(8-64);4]","[f(32-64);4]"],
"args": ["0.0SPc"]
},
{
"intrinsic": "padd{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "addp.{0.llvm_name}",
"ret": ["i(8-32)","f32"],
"args": ["0", "0"]
},
{
"intrinsic": "padd{0.width}_{0.data_type}",
"width": [128],
"llvm": "addp.{0.llvm_name}",
"ret": ["i64","f64"],
"args": ["0", "0"]
},
{
"intrinsic": "paddl{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "{0.kind}addlp.{0.llvm_name}.{1.llvm_name}",
"ret": "i(16-64)",
"args": ["0dn"]
},
{
"intrinsic": "pmax{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "{0.kind}maxp.{0.llvm_name}",
"ret": ["i(8-32)","f32"],
"args": ["0", "0"]
},
{
"intrinsic": "pmax{0.width}_{0.data_type}",
"width": [128],
"llvm": "{0.kind}maxp.{0.llvm_name}",
"ret": ["i64","f64"],
"args": ["0", "0"]
},
{
"intrinsic": "pmin{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "{0.kind}minp.{0.llvm_name}",
"ret": ["i(8-32)","f32"],
"args": ["0", "0"]
},
{
"intrinsic": "pmin{0.width}_{0.data_type}",
"width": [128],
"llvm": "{0.kind}minp.{0.llvm_name}",
"ret": ["i64","f64"],
"args": ["0", "0"]
},
{
"intrinsic": "pmaxnm{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "{0.kind}maxnmp.{0.llvm_name}",
"ret": ["i(8-32)","f32"],
"args": ["0", "0"]
},
{
"intrinsic": "pmaxnm{0.width}_{0.data_type}",
"width": [128],
"llvm": "{0.kind}maxnmp.{0.llvm_name}",
"ret": ["i64","f64"],
"args": ["0", "0"]
},
{
"intrinsic": "pminnm{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "{0.kind}minnmp.{0.llvm_name}",
"ret": "f32",
"args": ["0", "0"]
},
{
"intrinsic": "pminnm{0.width}_{0.data_type}",
"width": [128],
"llvm": "{0.kind}minnmp.{0.llvm_name}",
"ret": "f64",
"args": ["0", "0"]
},
{
"intrinsic": "addv{1.width}_{0.data_type}",
"width": [64, 128],
"llvm": "{0.kind}addv.{0.llvm_name}.{1.llvm_name}",
"ret": ["I(8-32)","F32"],
"args": ["0v"]
},
{
"intrinsic": "addv{1.width}_{0.data_type}",
"width": [128],
"llvm": "{0.kind}addv.{0.llvm_name}.{1.llvm_name}",
"ret": ["I64","F64"],
"args": ["0v"]
},
{
"intrinsic": "addlv{1.width}_{1.data_type}",
"width": [64, 128],
"llvm": "{0.kind}addlv.{0.llvm_name}.{1.llvm_name}",
"ret": "I(16-64)",
"args": ["0vdn"]
},
{
"intrinsic": "maxv{1.width}_{0.data_type}",
"width": [64, 128],
"llvm": "{0.kind}maxv.{0.llvm_name}.{1.llvm_name}",
"ret": ["I(8-32)","F32"],
"args": ["0v"]
},
{
"intrinsic": "maxv{1.width}_{0.data_type}",
"width": [128],
"llvm": "{0.kind}maxv.{0.llvm_name}.{1.llvm_name}",
"ret": "F64",
"args": ["0v"]
},
{
"intrinsic": "minv{1.width}_{0.data_type}",
"width": [64, 128],
"llvm": "{0.kind}minv.{0.llvm_name}.{1.llvm_name}",
"ret": ["I(8-32)","F32"],
"args": ["0v"]
},
{
"intrinsic": "minv{1.width}_{0.data_type}",
"width": [128],
"llvm": "{0.kind}minv.{0.llvm_name}.{1.llvm_name}",
"ret": "F64",
"args": ["0v"]
},
{
"intrinsic": "maxnmv{1.width}_{0.data_type}",
"width": [64, 128],
"llvm": "{0.kind}maxnmv.{0.llvm_name}.{1.llvm_name}",
"ret": "F32",
"args": ["0v"]
},
{
"intrinsic": "maxnmv{1.width}_{0.data_type}",
"width": [128],
"llvm": "{0.kind}maxnmv.{0.llvm_name}.{1.llvm_name}",
"ret": "F64",
"args": ["0v"]
},
{
"intrinsic": "minnmv{1.width}_{0.data_type}",
"width": [64, 128],
"llvm": "{0.kind}minnmv.{0.llvm_name}.{1.llvm_name}",
"ret": "F32",
"args": ["0v"]
},
{
"intrinsic": "minnmv{1.width}_{0.data_type}",
"width": [128],
"llvm": "{0.kind}minnmv.{0.llvm_name}.{1.llvm_name}",
"ret": "F64",
"args": ["0v"]
},
{
"intrinsic": "qtbl1{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "tbl1.{0.llvm_name}",
"ret": "i8",
"args": ["0x128", "0u"]
},
{
"intrinsic": "qtbx1{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "tbx1.{0.llvm_name}",
"ret": "i8",
"args": ["0", "0x128", "0u"]
},
{
"intrinsic": "qtbl2{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "tbl2.{0.llvm_name}",
"ret": "i8",
"args": ["(0x128,0x128)f", "0u"]
},
{
"intrinsic": "qtbx2{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "tbx2.{0.llvm_name}",
"ret": "i8",
"args": ["(0x128,0x128)f", "0u"]
},
{
"intrinsic": "qtbl3{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "tbl3.{0.llvm_name}",
"ret": "i8",
"args": ["(0x128,0x128,0x128)f", "0u"]
},
{
"intrinsic": "qtbx3{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "tbx3.{0.llvm_name}",
"ret": "i8",
"args": ["0", "(0x128,0x128,0x128)f", "0u"]
},
{
"intrinsic": "qtbl4{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "tbl4.{0.llvm_name}",
"ret": "i8",
"args": ["(0x128,0x128,0x128,0x128)f", "0u"]
},
{
"intrinsic": "qtbx4{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "tbx4.{0.llvm_name}",
"ret": "i8",
"args": ["0", "(0x128,0x128,0x128,0x128)f", "0u"]
}
]
}

View File

@ -0,0 +1,396 @@
{
"platform": "arm",
"intrinsic_prefix": "arm_v",
"llvm_prefix": "llvm.neon.v",
"number_info": {
"signed": {
"kind": "s",
"data_type": { "pattern": "s{bitwidth}" }
},
"unsigned": {
"kind": "u",
"data_type": { "pattern": "u{bitwidth}" }
},
"float": {
"kind": "f",
"data_type": { "pattern": "f{bitwidth}" }
}
},
"width_info": {
"64": { "width": "" },
"128": { "width": "q" }
},
"intrinsics": [
{
"intrinsic": "hadd{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "hadd{0.kind}.{0.llvm_name}",
"ret": "i(8-32)",
"args": ["0", "0"]
},
{
"intrinsic": "rhadd{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "rhadd{0.kind}.{0.llvm_name}",
"ret": "i(8-32)",
"args": ["0", "0"]
},
{
"intrinsic": "qadd{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "qadd{0.kind}.{0.llvm_name}",
"ret": "i(8-64)",
"args": ["0", "0"]
},
{
"intrinsic": "raddhn_{1.data_type}",
"width": [64],
"llvm": "raddhn.{0.llvm_name}",
"ret": "i(8-32)",
"args": ["0w", "0w"]
},
{
"intrinsic": "fma{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "!llvm.fma.{0.llvm_name}",
"ret": "f32",
"args": ["0", "0"]
},
{
"intrinsic": "qdmulh{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "sqdmulh.{0.llvm_name}",
"ret": "s(16-32)",
"args": ["0", "0"]
},
{
"intrinsic": "qrdmulh{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "sqrdmulh.{0.llvm_name}",
"ret": "s(16-32)",
"args": ["0", "0"]
},
{
"intrinsic": "mull_{1.data_type}",
"width": [128],
"llvm": "mull{0.kind}.{0.llvm_name}",
"ret": "i(16-64)",
"args": ["0n", "0n"]
},
{
"intrinsic": "qdmull{0.width}_{1.data_type}",
"width": [128],
"llvm": "sqdmull.{0.llvm_name}",
"ret": "s(16-32)",
"args": ["0n", "0n"]
},
{
"intrinsic": "hsub{0.width}_{1.data_type}",
"width": [64, 128],
"llvm": "hsub{0.kind}.{0.llvm_name}",
"ret": "i(8-32)",
"args": ["0", "0"]
},
{
"intrinsic": "qsub{0.width}_{1.data_type}",
"width": [64, 128],
"llvm": "qsub{0.kind}.{0.llvm_name}",
"ret": "i(8-64)",
"args": ["0", "0"]
},
{
"intrinsic": "rsubhn_{1.data_type}",
"width": [64],
"llvm": "rsubhn.{0.llvm_name}",
"ret": "i(8-32)",
"args": ["0w", "0w"]
},
{
"intrinsic": "abd{0.width}_{1.data_type}",
"width": [64, 128],
"llvm": "abd{0.kind}.{0.llvm_name}",
"ret": ["i(8-32)","f32"],
"args": ["0", "0"]
},
{
"intrinsic": "max{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "max{0.kind}.{0.llvm_name}",
"ret": ["i(8-32)","f32"],
"args": ["0", "0"]
},
{
"intrinsic": "min{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "min{0.kind}.{0.llvm_name}",
"ret": ["i(8-32)","f32"],
"args": ["0", "0"]
},
{
"intrinsic": "shl{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "shl{0.kind}.{0.llvm_name}",
"ret": "i(8-64)",
"args": ["0", "0s"]
},
{
"intrinsic": "qshl{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "qshl{0.kind}.{0.llvm_name}",
"ret": "i(8-64)",
"args": ["0", "0s"]
},
{
"intrinsic": "rshl{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "rshl{0.kind}.{0.llvm_name}",
"ret": "i(8-64)",
"args": ["0", "0s"]
},
{
"intrinsic": "qrshl{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "qrshl{0.kind}.{0.llvm_name}",
"ret": "i(8-64)",
"args": ["0", "0s"]
},
{
"intrinsic": "qshrun_n_{1.data_type}",
"width": [64],
"llvm": "sqshrun.{0.llvm_name}",
"ret": "s(8-32)",
"args": ["0w", "U32"]
},
{
"intrinsic": "qrshrun_n_{1.data_type}",
"width": [64],
"llvm": "sqrshrun.{0.llvm_name}",
"ret": "s(8-32)",
"args": ["0w", "U32"]
},
{
"intrinsic": "qshrn_n_{1.data_type}",
"width": [64],
"llvm": "qshrn{0.kind}.{0.llvm_name}",
"ret": "i(8-32)",
"args": ["0w", "U32"]
},
{
"intrinsic": "rshrn_n_{1.data_type}",
"width": [64],
"llvm": "rshrn.{0.llvm_name}",
"ret": "i(8-32)",
"args": ["0w", "U32"]
},
{
"intrinsic": "qrshrn_n_{1.data_type}",
"width": [64],
"llvm": "qrshrn{0.kind}.{0.llvm_name}",
"ret": "i(8-32)",
"args": ["0w", "U32"]
},
{
"intrinsic": "sri{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "vsri.{0.llvm_name}",
"ret": "i(8-64)",
"args": ["0", "0"]
},
{
"intrinsic": "sli{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "vsli.{0.llvm_name}",
"ret": "i(8-64)",
"args": ["0", "0"]
},
{
"intrinsic": "vqmovn_{1.data_type}",
"width": [64],
"llvm": "qxtn{0.kind}.{0.llvm_name}",
"ret": "i(8-32)",
"args": ["0w"]
},
{
"intrinsic": "abs{0.width}_{0.data_type}",
"width": [64,128],
"llvm": "abs.{0.llvm_name}",
"ret": "s(8-32)",
"args": ["0"]
},
{
"intrinsic": "abs{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "!llvm.fabs.{0.llvm_name}",
"ret": "f32",
"args": ["0"]
},
{
"intrinsic": "qabs{0.width}_{0.data_type}",
"width": [64,128],
"llvm": "sqabs.{0.llvm_name}",
"ret": "s(8-32)",
"args": ["0"]
},
{
"intrinsic": "qneg{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "sqneg.{0.llvm_name}",
"ret": "s(8-32)",
"args": ["0"]
},
{
"intrinsic": "clz{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "!llvm.ctlz.{0.llvm_name}",
"ret": "i(8-32)",
"args": ["0"]
},
{
"intrinsic": "cls{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "cls.{0.llvm_name}",
"ret": "i(8-32)",
"args": ["0"]
},
{
"intrinsic": "cnt{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "!llvm.ctpop.{0.llvm_name}",
"ret": "i8",
"args": ["0"]
},
{
"intrinsic": "recpe{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "recpe.{0.llvm_name}",
"ret": ["u32","f32"],
"args": ["0"]
},
{
"intrinsic": "recps{0.width}_{0.data_type}",
"width": [64,128],
"llvm": "frecps.{0.llvm_name}",
"ret": "f32",
"args": ["0", "0"]
},
{
"intrinsic": "sqrt{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "!llvm.sqrt.{0.llvm_name}",
"ret": "f32",
"args": ["0"]
},
{
"intrinsic": "rsqrte{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "rsqrte.{0.llvm_name}",
"ret": ["u32","f32"],
"args": ["0"]
},
{
"intrinsic": "rsqrts{0.width}_{0.data_type}",
"width": [64,128],
"llvm": "rsqrts.{0.llvm_name}",
"ret": "f32",
"args": ["0", "0"]
},
{
"intrinsic": "bsl{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "bsl.{0.llvm_name}",
"ret": "i(8-64)",
"args": ["0u", "0"]
},
{
"intrinsic": "padd{0.width}_{0.data_type}",
"width": [64],
"llvm": "padd.{0.llvm_name}",
"ret": ["i(8-32)","f32"],
"args": ["0", "0"]
},
{
"intrinsic": "paddl{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "paddl{0.kind}.{0.llvm_name}.{1.llvm_name}",
"ret": "i(16-64)",
"args": ["0dn"]
},
{
"intrinsic": "padal{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "padal{0.kind}.{0.llvm_name}.{1.llvm_name}",
"ret": "i(16-64)",
"args": ["0", "0dn"]
},
{
"intrinsic": "pmax{0.width}_{0.data_type}",
"width": [64],
"llvm": "pmax{0.kind}.{0.llvm_name}",
"ret": ["i(8-32)","f32"],
"args": ["0", "0"]
},
{
"intrinsic": "pmin{0.width}_{0.data_type}",
"width": [64, 128],
"llvm": "pmin{0.kind}.{0.llvm_name}",
"ret": ["i(8-32)","f32"],
"args": ["0", "0"]
},
{
"intrinsic": "tbl1_{0.data_type}",
"width": [64],
"llvm": "tbl1",
"ret": "i8",
"args": ["0", "0u"]
},
{
"intrinsic": "tbx1_{0.data_type}",
"width": [64],
"llvm": "tbx1",
"ret": "i8",
"args": ["0", "0", "0u"]
},
{
"intrinsic": "tbl2_{0.data_type}",
"width": [64],
"llvm": "tbl2",
"ret": "i8",
"args": ["(0,0)f", "0u"]
},
{
"intrinsic": "tbx2_{0.data_type}",
"width": [64],
"llvm": "tbx2",
"ret": "i8",
"args": ["(0,0)f", "0u"]
},
{
"intrinsic": "tbl3_{0.data_type}",
"width": [64],
"llvm": "tbl3",
"ret": "i8",
"args": ["(0,0,0)f", "0u"]
},
{
"intrinsic": "tbx3_{0.data_type}",
"width": [64],
"llvm": "tbx3",
"ret": "i8",
"args": ["0", "(0,0,0)f", "0u"]
},
{
"intrinsic": "tbl4_{0.data_type}",
"width": [64],
"llvm": "tbl4",
"ret": "i8",
"args": ["(0,0,0,0)f", "0u"]
},
{
"intrinsic": "tbx4_{0.data_type}",
"width": [64],
"llvm": "tbx4",
"ret": "i8",
"args": ["0", "(0,0,0,0)f", "0u"]
}
]
}

View File

@ -0,0 +1,805 @@
# 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.
from __future__ import division, print_function
import json
import argparse
import sys
import re
import textwrap
import itertools
SPEC = re.compile(
r'^(?:(?P<void>V)|(?P<id>[iusfIUSF])(?:\((?P<start>\d+)-(?P<end>\d+)\)|'
r'(?P<width>\d+)(:?/(?P<llvm_width>\d+))?)'
r'|(?P<reference>\d+))(?P<index>\.\d+)?(?P<modifiers>[vShdnwusfDMC]*)(?P<force_width>x\d+)?'
r'(?:(?P<pointer>Pm|Pc)(?P<llvm_pointer>/.*)?|(?P<bitcast>->.*))?$'
)
class PlatformInfo(object):
def __init__(self, json):
self._platform = json['platform']
self._intrinsic_prefix = json['intrinsic_prefix']
def intrinsic_prefix(self):
return self._intrinsic_prefix
class IntrinsicSet(object):
def __init__(self, platform, json):
self._llvm_prefix = json['llvm_prefix']
self._type_info = json['number_info']
self._intrinsics = json['intrinsics']
self._widths = json['width_info']
self._platform = platform
def intrinsics(self):
for raw in self._intrinsics:
yield GenericIntrinsic(self,
raw['intrinsic'], raw['width'], raw['llvm'],
raw['ret'], raw['args'])
def platform(self):
return self._platform
def llvm_prefix(self):
return self._llvm_prefix
def width_info(self, bitwidth):
return self._widths[str(bitwidth)]
def number_type_info(self, value):
data = self._type_info[value.__class__.__name__.lower()]
bitwidth = value.bitwidth()
def lookup(raw):
if not isinstance(raw, dict):
return raw
try:
return raw[str(bitwidth)]
except KeyError:
return raw['pattern'].format(bitwidth = bitwidth)
return PlatformTypeInfo(value.llvm_name(),
{k: lookup(v) for k, v in data.items()})
class PlatformTypeInfo(object):
def __init__(self, llvm_name, properties, elems = None):
if elems is None:
self.properties = properties
self.llvm_name = llvm_name
else:
assert properties is None and llvm_name is None
self.properties = {}
self.elems = elems
def __repr__(self):
return '<PlatformTypeInfo {}, {}>'.format(self.llvm_name, self.properties)
def __getattr__(self, name):
return self.properties[name]
def __getitem__(self, idx):
return self.elems[idx]
def vectorize(self, length, width_info):
props = self.properties.copy()
props.update(width_info)
return PlatformTypeInfo('v{}{}'.format(length, self.llvm_name), props)
def pointer(self, llvm_elem):
name = self.llvm_name if llvm_elem is None else llvm_elem.llvm_name
return PlatformTypeInfo('p0{}'.format(name), self.properties)
BITWIDTH_POINTER = '<pointer>'
class Type(object):
def __init__(self, bitwidth):
self._bitwidth = bitwidth
def bitwidth(self):
return self._bitwidth
def modify(self, spec, width, previous):
raise NotImplementedError()
def __ne__(self, other):
return not (self == other)
class Void(Type):
def __init__(self):
Type.__init__(self, 0)
def compiler_ctor(self):
return 'void()'
def rust_name(self):
return '()'
def type_info(self, platform_info):
return None
def __eq__(self, other):
return isinstance(other, Void)
class Number(Type):
def __init__(self, bitwidth):
Type.__init__(self, bitwidth)
def modify(self, spec, width, previous):
if spec == 'u':
return Unsigned(self.bitwidth())
elif spec == 's':
return Signed(self.bitwidth())
elif spec == 'f':
return Float(self.bitwidth())
elif spec == 'w':
return self.__class__(self.bitwidth() * 2)
elif spec == 'n':
return self.__class__(self.bitwidth() // 2)
elif spec == 'v':
return Vector(self, width // self.bitwidth())
else:
raise ValueError('unknown modification spec {}', spec)
def type_info(self, platform_info):
return platform_info.number_type_info(self)
def __eq__(self, other):
# print(self, other)
return self.__class__ == other.__class__ and self.bitwidth() == other.bitwidth()
class Signed(Number):
def __init__(self, bitwidth, llvm_bitwidth = None):
Number.__init__(self, bitwidth)
self._llvm_bitwidth = llvm_bitwidth
def compiler_ctor(self):
if self._llvm_bitwidth is None:
return 'i({})'.format(self.bitwidth())
else:
return 'i_({}, {})'.format(self.bitwidth(),
self._llvm_bitwidth)
def llvm_name(self):
bw = self._llvm_bitwidth or self.bitwidth()
return 'i{}'.format(bw)
def rust_name(self):
return 'i{}'.format(self.bitwidth())
class Unsigned(Number):
def __init__(self, bitwidth, llvm_bitwidth = None):
Number.__init__(self, bitwidth)
self._llvm_bitwidth = llvm_bitwidth
def compiler_ctor(self):
if self._llvm_bitwidth is None:
return 'u({})'.format(self.bitwidth())
else:
return 'u_({}, {})'.format(self.bitwidth(),
self._llvm_bitwidth)
def llvm_name(self):
bw = self._llvm_bitwidth or self.bitwidth()
return 'i{}'.format(bw)
def rust_name(self):
return 'u{}'.format(self.bitwidth())
class Float(Number):
def __init__(self, bitwidth):
assert bitwidth in (32, 64)
Number.__init__(self, bitwidth)
def compiler_ctor(self):
return 'f({})'.format(self.bitwidth())
def llvm_name(self):
return 'f{}'.format(self.bitwidth())
def rust_name(self):
return 'f{}'.format(self.bitwidth())
class Vector(Type):
def __init__(self, elem, length, bitcast = None):
assert isinstance(elem, Type) and not isinstance(elem, Vector)
Type.__init__(self,
elem.bitwidth() * length)
self._length = length
self._elem = elem
assert bitcast is None or (isinstance(bitcast, Vector) and
bitcast._bitcast is None and
bitcast._elem.bitwidth() == elem.bitwidth())
if bitcast is not None and bitcast._elem != elem:
self._bitcast = bitcast._elem
else:
self._bitcast = None
def modify(self, spec, width, previous):
if spec == 'S':
return self._elem
elif spec == 'h':
return Vector(self._elem, self._length // 2)
elif spec == 'd':
return Vector(self._elem, self._length * 2)
elif spec.startswith('x'):
new_bitwidth = int(spec[1:])
return Vector(self._elem, new_bitwidth // self._elem.bitwidth())
elif spec.startswith('->'):
bitcast_to = TypeSpec(spec[2:])
choices = list(bitcast_to.enumerate(width, previous))
assert len(choices) == 1
bitcast_to = choices[0]
return Vector(self._elem, self._length, bitcast_to)
else:
return Vector(self._elem.modify(spec, width, previous), self._length)
def compiler_ctor(self):
if self._bitcast is None:
return 'v({}, {})'.format(self._elem.compiler_ctor(),
self._length)
else:
return 'v_({}, {}, {})'.format(self._elem.compiler_ctor(),
self._bitcast.compiler_ctor(),
self._length)
def rust_name(self):
return '{}x{}'.format(self._elem.rust_name(), self._length)
def type_info(self, platform_info):
elem_info = self._elem.type_info(platform_info)
return elem_info.vectorize(self._length,
platform_info.width_info(self.bitwidth()))
def __eq__(self, other):
return isinstance(other, Vector) and self._length == other._length and \
self._elem == other._elem and self._bitcast == other._bitcast
class Pointer(Type):
def __init__(self, elem, llvm_elem, const):
self._elem = elem;
self._llvm_elem = llvm_elem
self._const = const
Type.__init__(self, BITWIDTH_POINTER)
def modify(self, spec, width, previous):
if spec == 'D':
return self._elem
elif spec == 'M':
return Pointer(self._elem, self._llvm_elem, False)
elif spec == 'C':
return Pointer(self._elem, self._llvm_elem, True)
else:
return Pointer(self._elem.modify(spec, width, previous), self._llvm_elem, self._const)
def compiler_ctor(self):
if self._llvm_elem is None:
llvm_elem = 'None'
else:
llvm_elem = 'Some({})'.format(self._llvm_elem.compiler_ctor())
return 'p({}, {}, {})'.format('true' if self._const else 'false',
self._elem.compiler_ctor(),
llvm_elem)
def rust_name(self):
return '*{} {}'.format('const' if self._const else 'mut',
self._elem.rust_name())
def type_info(self, platform_info):
if self._llvm_elem is None:
llvm_elem = None
else:
llvm_elem = self._llvm_elem.type_info(platform_info)
return self._elem.type_info(platform_info).pointer(llvm_elem)
def __eq__(self, other):
return isinstance(other, Pointer) and self._const == other._const \
and self._elem == other._elem and self._llvm_elem == other._llvm_elem
class Aggregate(Type):
def __init__(self, flatten, elems):
self._flatten = flatten
self._elems = elems
Type.__init__(self, sum(elem.bitwidth() for elem in elems))
def __repr__(self):
return '<Aggregate {}>'.format(self._elems)
def modify(self, spec, width, previous):
if spec.startswith('.'):
num = int(spec[1:])
return self._elems[num]
else:
print(spec)
raise NotImplementedError()
def compiler_ctor(self):
return 'agg({}, vec![{}])'.format('true' if self._flatten else 'false',
', '.join(elem.compiler_ctor() for elem in self._elems))
def rust_name(self):
return '({})'.format(', '.join(elem.rust_name() for elem in self._elems))
def type_info(self, platform_info):
return PlatformTypeInfo(None, None, [elem.type_info(platform_info) for elem in self._elems])
def __eq__(self, other):
return isinstance(other, Aggregate) and self._flatten == other._flatten and \
self._elems == other._elems
TYPE_ID_LOOKUP = {'i': [Signed, Unsigned],
's': [Signed],
'u': [Unsigned],
'f': [Float]}
def ptrify(match, elem, width, previous):
ptr = match.group('pointer')
if ptr is None:
return elem
else:
llvm_ptr = match.group('llvm_pointer')
if llvm_ptr is None:
llvm_elem = None
else:
assert llvm_ptr.startswith('/')
options = list(TypeSpec(llvm_ptr[1:]).enumerate(width, previous))
assert len(options) == 1
llvm_elem = options[0]
assert ptr in ('Pc', 'Pm')
return Pointer(elem, llvm_elem, ptr == 'Pc')
class TypeSpec(object):
def __init__(self, spec):
if not isinstance(spec, list):
spec = [spec]
self.spec = spec
def enumerate(self, width, previous):
for spec in self.spec:
match = SPEC.match(spec)
if match is not None:
id = match.group('id')
reference = match.group('reference')
modifiers = []
index = match.group('index')
if index is not None:
modifiers.append(index)
modifiers += list(match.group('modifiers') or '')
force = match.group('force_width')
if force is not None:
modifiers.append(force)
bitcast = match.group('bitcast')
if bitcast is not None:
modifiers.append(bitcast)
if match.group('void') is not None:
assert spec == 'V'
yield Void()
elif id is not None:
is_vector = id.islower()
type_ctors = TYPE_ID_LOOKUP[id.lower()]
start = match.group('start')
if start is not None:
end = match.group('end')
llvm_width = None
else:
start = end = match.group('width')
llvm_width = match.group('llvm_width')
start = int(start)
end = int(end)
bitwidth = start
while bitwidth <= end:
for ctor in type_ctors:
if llvm_width is not None:
assert not is_vector
llvm_width = int(llvm_width)
assert llvm_width < bitwidth
scalar = ctor(bitwidth, llvm_width)
else:
scalar = ctor(bitwidth)
if is_vector:
elem = Vector(scalar, width // bitwidth)
else:
assert bitcast is None
elem = scalar
for x in modifiers:
elem = elem.modify(x, width, previous)
yield ptrify(match, elem, width, previous)
bitwidth *= 2
elif reference is not None:
reference = int(reference)
assert reference < len(previous), \
'referring to argument {}, but only {} are known'.format(reference,
len(previous))
ret = previous[reference]
for x in modifiers:
ret = ret.modify(x, width, previous)
yield ptrify(match, ret, width, previous)
else:
assert False, 'matched `{}`, but didn\'t understand it?'.format(spec)
elif spec.startswith('('):
if spec.endswith(')'):
true_spec = spec[1:-1]
flatten = False
elif spec.endswith(')f'):
true_spec = spec[1:-2]
flatten = True
else:
assert False, 'found unclosed aggregate `{}`'.format(spec)
for elems in itertools.product(*(TypeSpec(subspec).enumerate(width, previous)
for subspec in true_spec.split(','))):
yield Aggregate(flatten, elems)
elif spec.startswith('['):
if spec.endswith(']'):
true_spec = spec[1:-1]
flatten = False
elif spec.endswith(']f'):
true_spec = spec[1:-2]
flatten = True
else:
assert False, 'found unclosed aggregate `{}`'.format(spec)
elem_spec, count = true_spec.split(';')
count = int(count)
for elem in TypeSpec(elem_spec).enumerate(width, previous):
yield Aggregate(flatten, [elem] * count)
else:
assert False, 'Failed to parse `{}`'.format(spec)
class GenericIntrinsic(object):
def __init__(self, platform, intrinsic, widths, llvm_name, ret, args):
self._platform = platform
self.intrinsic = intrinsic
self.widths = map(int, widths)
self.llvm_name = llvm_name
self.ret = TypeSpec(ret)
self.args = list(map(TypeSpec, args))
def monomorphise(self):
for width in self.widths:
# must be a power of two
assert width & (width - 1) == 0
def recur(processed, untouched):
if untouched == []:
ret = processed[0]
args = processed[1:]
yield MonomorphicIntrinsic(self._platform, self.intrinsic, width,
self.llvm_name,
ret, args)
else:
raw_arg = untouched[0]
rest = untouched[1:]
for arg in raw_arg.enumerate(width, processed):
for intr in recur(processed + [arg], rest):
yield intr
for x in recur([], [self.ret] + self.args):
yield x
class MonomorphicIntrinsic(object):
def __init__(self, platform, intrinsic, width, llvm_name, ret, args):
self._platform = platform
self._intrinsic = intrinsic
self._width = '' if width == 64 else 'q'
self._llvm_name = llvm_name
self._ret_raw = ret
self._ret = ret.type_info(platform)
self._args_raw = args
self._args = [arg.type_info(platform) for arg in args]
def llvm_name(self):
if self._llvm_name.startswith('!'):
return self._llvm_name[1:].format(self._ret, *self._args)
else:
return self._platform.llvm_prefix() + self._llvm_name.format(self._ret, *self._args)
def intrinsic_suffix(self):
return self._intrinsic.format(self._ret,
*self._args,
width = self._width)
def intrinsic_name(self):
return self._platform.platform().intrinsic_prefix() + self.intrinsic_suffix()
def compiler_args(self):
return ', '.join(arg.compiler_ctor() for arg in self._args_raw)
def compiler_ret(self):
return self._ret_raw.compiler_ctor()
def compiler_signature(self):
return '({}) -> {}'.format(self.compiler_args(), self.compiler_ret())
def intrinsic_signature(self):
names = 'xyzwabcdef'
return '({}) -> {}'.format(', '.join('{}: {}'.format(name, arg.rust_name())
for name, arg in zip(names, self._args_raw)),
self._ret_raw.rust_name())
def parse_args():
parser = argparse.ArgumentParser(
formatter_class = argparse.RawDescriptionHelpFormatter,
description = 'Render an intrinsic definition JSON to various formats.',
epilog = textwrap.dedent('''\
An intrinsic definition consists of a map with fields:
- intrinsic: pattern for the name(s) of the vendor's C intrinsic(s)
- llvm: pattern for the name(s) of the internal llvm intrinsic(s)
- width: a vector of vector bit-widths the pattern works with
- ret: type specifier for the return value
- arguments: vector of type specifiers for arguments
The width and types describe a range of possible intrinsics,
and these are fed back into the intrinsic and llvm patterns to
create the appropriate definitions.
## Type specifier grammar
```
type := core_type modifier* suffix?
core_type := void | vector | scalar | aggregate | reference
modifier := 'v' | 'h' | 'd' | 'n' | 'w' | 'u' | 's' |
'x' number | '.' number
suffix := pointer | bitcast
pointer := 'Pm' llvm_pointer? | 'Pc' llvm_pointer?
llvm_pointer := '/' type
bitcast := '->' type
void := 'V'
vector := vector_elem width |
vector_elem := 'i' | 'u' | 's' | 'f'
scalar := scalar_type number llvm_width?
scalar_type := 'U' | 'S' | 'F'
llvm_width := '/' number
aggregate := '(' (type),* ')' 'f'? | '[' type ';' number ']' 'f'?
reference := number
width = number | '(' number '-' number ')'
number = [0-9]+
```
## Void
The `V` type corresponds to `void` in LLVM (`()` in
Rust). It's likely to only work in return position.
## Vectors
The vector grammar is a pattern describing many possibilities
for arguments/return value. The `vector_elem` describes the
types of elements to use, and the `width` describes the (range
of) widths for those elements, which are then placed into a
vector with the `width` bitwidth. E.g. if an intrinsic has a
`width` that includes 128, and the return value is `i(8-32)`,
then some instantiation of that intrinsic will be `u8x16`,
`u32x4`, `i32x4`, etc.
### Elements
- i: integer, both signed and unsigned
- u: unsigned integer
- s: signed integer
- f: float
## Scalars
Similar to vectors, but these describe a single concrete type,
not a range. The number is the bitwidth. The optional
`llvm_width` is the bitwidth of the integer that should be
passed to LLVM (by truncating the Rust argument): this only
works with scalar integers and the LLVM width must be smaller
than the Rust width.
### Types
- U: unsigned integer
- S: signed integer
- F: float
## Aggregates
An aggregate is a collection of multiple types; a tuple in
Rust terms, or an unnamed struct in LLVM. The `f` modifiers
forces the tuple to be flattened in the LLVM
intrinsic. E.g. if `llvm.foo` takes `(F32,S32)`:
- no `f` corresponds to `declare ... @llvm.foo({float, i32})`.
- having an `f` corresponds to `declare ... @llvm.foo(float, i32)`.
The `[type;number]` form is a just shorter way to write
`(...)`, except avoids doing a cartesian product of generic
types, e.g. `[S32;2]` is the same as `(S32, S32)`, while
`[I32;2]` is describing just the two types `(S32,S32)` and
`(U32,U32)` (i.e. doesn't include `(S32,U32)`, `(U32,S32)` as
`(I32,I32)` would).
(Currently aggregates can not contain other aggregates.)
## References
A reference uses the type of another argument, with possible
modifications. The number refers to the type to use, starting
with 0 == return value, 1 == first argument, 2 == second
argument, etc.
## Affixes
The `modifier` and `suffix` adaptors change the precise
representation.
### Modifiers
- 'v': put a scalar into a vector of the current width (u32 -> u32x4, when width == 128)
- 'S': get the scalar element of a vector (u32x4 -> u32)
- 'h': half the length of the vector (u32x4 -> u32x2)
- 'd': double the length of the vector (u32x2 -> u32x4)
- 'n': narrow the element of the vector (u32x4 -> u16x4)
- 'w': widen the element of the vector (u16x4 -> u32x4)
- 'u': force a number (vector or scalar) to be unsigned int (f32x4 -> u32x4)
- 's': force a number (vector or scalar) to be signed int (u32x4 -> i32x4)
- 'f': force a number (vector or scalar) to be float (u32x4 -> f32x4)
- 'x' number: force the type to be a vector of bitwidth `number`.
- '.' number: get the `number`th element of an aggregate
- 'D': dereference a pointer (*mut u32 -> u32)
- 'C': make a pointer const (*mut u32 -> *const u32)
- 'M': make a pointer mut (*const u32 -> *mut u32)
### Pointers
Pointers can be created of any type by appending a `P*`
suffix. The `m` vs. `c` chooses mut vs. const. e.g. `S32Pm`
corresponds to `*mut i32`, and `i32Pc` corresponds (with width
128) to `*const i8x16`, `*const u32x4`, etc.
The type after the `/` (optional) represents the type used
internally to LLVM, e.g. `S32pm/S8` is exposed as `*mut i32`
in Rust, but is `i8*` in LLVM. (This defaults to the main
type).
### Bitcast
The `'->' type` bitcast suffix will cause the value to be
bitcast to the right-hand type when calling the intrinsic,
e.g. `s32->f32` will expose the intrinsic as `i32x4` at the
Rust level, but will cast that vector to `f32x4` when calling
the LLVM intrinsic.
'''))
parser.add_argument('--format', choices=FORMATS, required=True,
help = 'Output format.')
parser.add_argument('-o', '--out', type=argparse.FileType('w'), default=sys.stdout,
help = 'File to output to (default stdout).')
parser.add_argument('-i', '--info', type=argparse.FileType('r'),
help = 'File containing platform specific information to merge into'
'the input files\' header.')
parser.add_argument('in_', metavar="FILE", type=argparse.FileType('r'), nargs='+',
help = 'JSON files to load')
return parser.parse_args()
class ExternBlock(object):
def __init__(self):
pass
def open(self, platform):
return 'extern "platform-intrinsic" {'
def render(self, mono):
return ' fn {}{};'.format(mono.intrinsic_name(),
mono.intrinsic_signature())
def close(self):
return '}'
class CompilerDefs(object):
def __init__(self):
pass
def open(self, platform):
return '''\
// 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.
// DO NOT EDIT: autogenerated by etc/platform-intrinsics/generator.py
// ignore-tidy-linelength
#![allow(unused_imports)]
use {{Intrinsic, i, i_, u, u_, f, v, v_, agg, p, void}};
use IntrinsicDef::Named;
use rustc::middle::ty;
// The default inlining settings trigger a pathological behaviour in
// LLVM, which causes makes compilation very slow. See #28273.
#[inline(never)]
pub fn find<'tcx>(_tcx: &ty::ctxt<'tcx>, name: &str) -> Option<Intrinsic> {{
if !name.starts_with("{0}") {{ return None }}
Some(match &name["{0}".len()..] {{'''.format(platform.intrinsic_prefix())
def render(self, mono):
return '''\
"{}" => Intrinsic {{
inputs: vec![{}],
output: {},
definition: Named("{}")
}},'''.format(mono.intrinsic_suffix(),
mono.compiler_args(),
mono.compiler_ret(),
mono.llvm_name())
def close(self):
return '''\
_ => return None,
})
}'''
FORMATS = {
'extern-block': ExternBlock(),
'compiler-defs': CompilerDefs(),
}
def main():
args = parse_args()
ins = args.in_
out = args.out
out_format = FORMATS[args.format]
info = args.info
one_file_no_info = False
if len(ins) > 1 and info is None:
print('error: cannot have multiple inputs without an info header.', file=sys.stderr)
sys.exit(1)
elif info is None:
info = ins[0]
one_file_no_info = True
info_json = json.load(info)
platform = PlatformInfo(info_json)
print(out_format.open(platform), file=out)
for in_ in ins:
if one_file_no_info:
data = info_json
else:
data = json.load(in_)
data.update(info_json)
intrinsics = IntrinsicSet(platform, data)
for intr in intrinsics.intrinsics():
for mono in intr.monomorphise():
print(out_format.render(mono), file=out)
print(out_format.close(), file=out)
if __name__ == '__main__':
main()

View File

@ -0,0 +1,194 @@
{
"llvm_prefix": "llvm.x86.avx.",
"intrinsics": [
{
"intrinsic": "256_addsub_{0.data_type}",
"width": [256],
"llvm": "addsub.{0.data_type}.256",
"ret": "f(32-64)",
"args": ["0", "0"]
},
{
"intrinsic": "256_dp_ps",
"width": [256],
"llvm": "dp.ps.256",
"ret": "f32",
"args": ["0", "0", "S32/8"]
},
{
"intrinsic": "256_hadd_{0.data_type}",
"width": [256],
"llvm": "hadd.{0.data_type}.256",
"ret": "f(32-64)",
"args": ["0", "0"]
},
{
"intrinsic": "256_hsub_{0.data_type}",
"width": [256],
"llvm": "hsub.{0.data_type}.256",
"ret": "f(32-64)",
"args": ["0", "0"]
},
{
"intrinsic": "256_max_{0.data_type}",
"width": [256],
"llvm": "max.{0.data_type}.256",
"ret": "f(32-64)",
"args": ["0", "0"]
},
{
"intrinsic": "{0.width_mm}_maskload_{0.data_type}",
"width": [128, 256],
"llvm": "maskload.{0.data_type_short}{0.width_suffix}",
"ret": ["f(32-64)"],
"args": ["0SPc/S8", "0s->0"]
},
{
"intrinsic": "{3.width_mm}_maskstore_{3.data_type}",
"width": [128, 256],
"llvm": "maskstore.{3.data_type_short}{3.width_suffix}",
"ret": "V",
"args": ["F(32-64)Pm/S8", "1Dsv->1Dv", "1Dv"]
},
{
"intrinsic": "256_min_{0.data_type}",
"width": [256],
"llvm": "min.{0.data_type}.256",
"ret": "f(32-64)",
"args": ["0", "0"]
},
{
"intrinsic": "256_movemask_ps",
"width": [256],
"llvm": "movmsk.ps.256",
"ret": "S32",
"args": ["f32"]
},
{
"intrinsic": "256_movemask_pd",
"width": [256],
"llvm": "movmsk.pd.256",
"ret": "S32",
"args": ["f64"]
},
{
"intrinsic": "{0.width_mm}_permutevar_{0.data_type}",
"width": [128, 256],
"llvm": "vpermilvar.{0.data_type}{0.width_suffix}",
"ret": "f(32-64)",
"args": ["0", "0s"]
},
{
"intrinsic": "256_rcp_ps",
"width": [256],
"llvm": "rcp.ps.256",
"ret": "f32",
"args": ["f32"]
},
{
"intrinsic": "256_rsqrt_ps",
"width": [256],
"llvm": "rsqrt.ps.256",
"ret": "f32",
"args": ["f32"]
},
{
"intrinsic": "256_storeu_{2.data_type}",
"width": [256],
"llvm": "storeu.ps.256",
"ret": "V",
"args": ["f(32-64)Pm/U8", "1D"]
},
{
"intrinsic": "256_storeu_si256",
"width": [256],
"llvm": "storeu.dq.256",
"ret": "V",
"args": ["u8Pm/U8", "1D"]
},
{
"intrinsic": "256_sqrt_{0.data_type}",
"width": [256],
"llvm": "!llvm.sqrt.{0.llvm_name}",
"ret": "f(32-64)",
"args": ["0"]
},
{
"intrinsic": "{1.width_mm}_testc_ps",
"width": [128, 256],
"llvm": "vtestc.ps{1.width_suffix}",
"ret": "S32",
"args": ["f32", "f32"]
},
{
"intrinsic": "{1.width_mm}_testc_pd",
"width": [128, 256],
"llvm": "vtestc.pd{1.width_suffix}",
"ret": "S32",
"args": ["f64", "f64"]
},
{
"intrinsic": "256_testc_si256",
"width": [256],
"llvm": "ptestc.256",
"ret": "S32",
"args": ["u64", "u64"]
},
{
"intrinsic": "{1.width_mm}_testnzc_ps",
"width": [128, 256],
"llvm": "vtestnzc.ps{1.width_suffix}",
"ret": "S32",
"args": ["f32", "f32"]
},
{
"intrinsic": "{1.width_mm}_testnzc_pd",
"width": [128, 256],
"llvm": "vtestnzc.pd{1.width_suffix}",
"ret": "S32",
"args": ["f64", "f64"]
},
{
"intrinsic": "256_testnzc_si256",
"width": [256],
"llvm": "ptestnzc.256",
"ret": "S32",
"args": ["u64", "u64"]
},
{
"intrinsic": "{1.width_mm}_testz_ps",
"width": [128, 256],
"llvm": "vtestz.ps{1.width_suffix}",
"ret": "S32",
"args": ["f32", "f32"]
},
{
"intrinsic": "{1.width_mm}_testz_pd",
"width": [128, 256],
"llvm": "vtestz.pd{1.width_suffix}",
"ret": "S32",
"args": ["f64", "f64"]
},
{
"intrinsic": "256_testz_si256",
"width": [256],
"llvm": "ptestz.256",
"ret": "S32",
"args": ["u64", "u64"]
},
{
"intrinsic": "256_zeroall",
"width": [256],
"llvm": "vzeroall",
"ret": "V",
"args": []
},
{
"intrinsic": "256_zeroupper",
"width": [256],
"llvm": "vzeroupper",
"ret": "V",
"args": []
}
]
}

Some files were not shown because too many files have changed in this diff Show More