diff --git a/.gitmodules b/.gitmodules index 6cd704b370376..83be070b3854a 100644 --- a/.gitmodules +++ b/.gitmodules @@ -14,3 +14,6 @@ [submodule "src/rust-installer"] path = src/rust-installer url = https://github.com/rust-lang/rust-installer +[submodule "src/liblibc"] + path = src/liblibc + url = https://github.com/rust-lang/libc diff --git a/.mailmap b/.mailmap index 8eaf8f16e4b6a..317a92b8f43cb 100644 --- a/.mailmap +++ b/.mailmap @@ -7,142 +7,218 @@ Aaron Todd Abhishek Chanda Abhishek Chanda +Adolfo Ochagavía +Adrien Tétar Ahmed Charles -Aydin Kim aydin.kim Alex Burka Alex Burka Alex Lyon Alex Newman Alex HotShot Newman Alex Rønne Petersen +Alexander Light Alexander Light +Alexis Beingessner Alfie John Alfie John +Anatoly Ikorsky +Andre Bogus Andreas Gal Andrew Kuchev <0coming.soon@gmail.com> Andrew <0coming.soon@gmail.com> Andrew Poelstra Anton Löfgren -Ariel Ben-Yehuda arielb1 +Areski Belaid areski Ariel Ben-Yehuda Ariel Ben-Yehuda +Ariel Ben-Yehuda arielb1 Austin Seipp +Aydin Kim aydin.kim +Barosl Lee Barosl LEE Ben Alpert -Ben Sago Ben S Ben S +Ben Sago Ben S +Ben Sago Ben S Benjamin Jackman +Bheesham Persaud Bheesham Persaud Björn Steinbrink blake2-ppc Boris Egorov +Brandon Sanderson Brandon Sanderson +Brett Cannon Brett Cannon Brian Anderson Brian Dawn +Brian Leibig Brian Leibig Carl-Anton Ingmarsson Carol (Nichols || Goulding) Carol Nichols +Carol (Nichols || Goulding) Carol Nichols Carol Willing Chris C Cerami Chris C Cerami Chris Pressey +Chris Thorn Chris Thorn Clark Gaebel +Clinton Ryan Corey Farwell Corey Farwell Corey Richardson Elaine "See More" Nemo +Damien Schoof +Daniel Ramos David Klein David Manescu -Damien Schoof +David Ross Derek Chiang Derek Chiang (Enchi Jiang) Diggory Hardy Diggory Hardy Dylan Braithwaite -Eduardo Bautista +Dzmitry Malyshau Eduardo Bautista <=> +Eduardo Bautista Elliott Slaughter Elly Fong-Jones Emily Dunham edunham -Eric Holk Eric Holk +Eric Holk Eric Holmes Eric Reed Erick Tryzelaar Evgeny Sologubov Falco Hirschenberger Felix S. Klock II Felix S Klock II +Flaper Fesp +Florian Wilkens Florian Wilkens Gareth Daniel Smith gareth +Gareth Daniel Smith Gareth Smith Georges Dubus -Graham Fawcett +Graham Fawcett Graham Fawcett Graydon Hoare Graydon Hoare -Heather +Guillaume Gomez Heather +Heather +Herman J. Radtke III Herman J. Radtke III Ilyong Cho +Ivan Ivaschenko J. J. Weber Jakub Bukaj Jakub Bukaj +Jakub Bukaj Jakub Bukaj James Deng James Miller -Jason Orendorff +James Perry +Jason Fager Jason Orendorff +Jason Orendorff +Jason Toffaletti Jason Toffaletti +Jauhien Piatlicki Jauhien Piatlicki +Jay True Jeremy Letang -Jihyun Yu jihyun -Jihyun Yu -Johann Hofmann Johann Johann Hofmann +Jihyun Yu +Jihyun Yu jihyun +Jihyun Yu Jihyun Yu +Johann Hofmann Johann John Clements John Hodge John Hodge -Jorge Aparicio +John Kåre Alsaker +John Talling Jonathan Bailey +Jonathan S Jonathan S +Jorge Aparicio +Joseph Martin +João Oliveira joaoxsouls Junyoung Cho Jyun-Yan You Kang Seonghoon -Keegan McAllister +Keegan McAllister +Kevin Butler Kyeongwoon Lee -Lee Wondong Lee Jeffery Lee Jeffery +Lee Wondong Lennart Kudling +Léo Testard Lindsey Kuper Lindsey Kuper -Luqman Aden -Luqman Aden Luke Metz +Luqman Aden +Luqman Aden Makoto Nakashima Makoto Nakashima gifnksm -Markus Westerlind Markus +Makoto Nakashima NAKASHIMA, Makoto +Marcell Pardavi Margaret Meyerhofer Mark Sinclair Mark Sinclair =Mark Sinclair <=125axel125@gmail.com> +Markus Westerlind Markus Matej Lach Matej Ľach Matt Brubeck Matthew Auld Matthew McPherrin Matthijs Hofstra Michael Williams -Michael Woerister Michael Woerister +Michael Woerister +Mickaël Raybaud-Roig m-r-r Ms2ger +Mukilan Thiagarajan +NAKASHIMA, Makoto +Nathan Wilson +Nathaniel Herman Nathaniel Herman Neil Pankey Nicholas Mazzuca Nicholas -Oliver Schneider Oliver 'ker' Schneider -Oliver Schneider Oliver Schneider Oliver Schneider Oliver Schneider +Nick Platt +Nif Ward +Oliver Schneider oli-obk +Oliver Schneider Oliver 'ker' Schneider +Oliver Schneider Oliver Schneider +Oliver Schneider Oliver Schneider +Oliver Schneider Oliver Schneider +Oliver Schneider Oliver Schneider Ožbolt Menegatti gareins Paul Faria Paul Faria Peer Aramillo Irizar parir Peter Elmers +Peter Zotov +Phil Dawes Phil Dawes Philipp Brüschweiler Philipp Brüschweiler -Pradeep Kumar Przemysław Wesołek Przemek Wesołek +Rafael Ávila de Espíndola Rafael Avila de Espindola Ralph Giles Ralph Giles +Renato Riccieri Santos Zannon Richard Diamond Rob Arnold +Rob Arnold Rob Arnold Robert Foss robertfoss Robert Gawdzik Robert Gawdzik ☢ Robert Millar +Rohit Joshi Rohit Joshi +Russell Johnston Ruud van Asseldonk Ruud van Asseldonk Ryan Scheel +S Pradeep Kumar +Scott Olson Scott Olson Sean Gillespie swgillespie Seonghyun Kim Simon Barber-Dueck Simon BD Simon Sapin +Simonas Kazlauskas Simonas Kazlauskas startling +Stepan Koltsov Stepan Koltsov Steven Fackler Steven Stewart-Gallus +Stuart Pernsteiner Stuart Pernsteiner Tamir Duberstein Tamir Duberstein +Tero Hänninen Tero Hänninen +Theo Belaire Theo Belaire Thiago Pontes thiagopnts +Thomas Bracht Laumann Jespersen Ticki Ticki <@> +Tim Brooks Tim Brooks Tim Chevalier +Tim JIANG +Tim Joseph Dumol Torsten Weber -Ulrik Sverdrup Ulrik Sverdrup +Ty Overby +Ulrik Sverdrup bluss Ulrik Sverdrup bluss bluss +Ulrik Sverdrup Ulrik Sverdrup +Vadim Petrochenkov Vadim Petrochenkov petrochenkov Vitali Haravy Vitali Haravy William Ting -Xuefeng Wu Xuefeng Wu XuefengWu +Xuefeng Wu Xuefeng Wu +Xuefeng Wu XuefengWu +York Xiang Youngsoo Son +Zach Pomerantz Zack Corr Zack Slayton +Zbigniew Siciarz Zbigniew Siciarz diff --git a/AUTHORS.txt b/AUTHORS.txt index f0b3fe19e5c35..b7fa4a5a4a73b 100644 --- a/AUTHORS.txt +++ b/AUTHORS.txt @@ -98,7 +98,6 @@ Anton Löfgren Antti Keränen Aram Visser arcnmx -Arcterus Areski Belaid Ariel Ben-Yehuda Arjan Topolovec @@ -136,7 +135,6 @@ Ben Gesoff Ben Harris Ben Kelly Ben Noordhuis -Ben S Ben Sago Ben Striegel benaryorg @@ -314,7 +312,6 @@ David Szotten David Vazgenovich Shakaryan David Voit Davis Silverman -defuz Denis Defreyne DenisKolodin Derecho @@ -435,7 +432,6 @@ Gábor Horváth Gábor Lehel Gabriel gamazeps -gareth Gareth Daniel Smith Garming Sam Garrett Heel @@ -496,12 +492,12 @@ Igor Strebezhev Ilya Dmitrichenko Ilyong Cho Ingo Blechschmidt -inrustwetrust Irving A.J. Rivas Z. Isaac Aggrey Isaac Dupree Isaac Ge Ivan Enderlin +Ivan Ivaschenko Ivan Jager Ivan Petkov Ivan Radanov Ivanov @@ -733,7 +729,6 @@ Liam Monahan Liigo Zhuang Lindsey Kuper Lionel Flandrin -llogiq Logan Chien Loïc Damien Lorenz @@ -760,7 +755,7 @@ Manuel Hoffmann Marc-Antoine Perennou Marcel Müller Marcel Rodrigues -marcell +Marcell Pardavi Marcello Seri Marcus Klaas Margaret Meyerhofer @@ -924,9 +919,7 @@ Oak OGINO Masanori OlegTsyba Oliver Schneider -Oliver Schneider -Oliver Schneider -Oliver Schneider +Oliver Schneider Olivier Saut olivren Olle Jonsson @@ -937,7 +930,6 @@ Oren Hazi Orphée Lafond-Lummis Orpheus Lummis osa1 -Overmind JIANG Ožbolt Menegatti P1start Pablo Brasero @@ -978,7 +970,6 @@ Peter Schuller Peter Williams Peter Zotov Petter Remen -pez Phil Dawes Phil Ruffwind Philip Munksgaard @@ -1065,7 +1056,6 @@ Ryan Pendleton Ryan Prichard Ryan Riginding Ryan Scheel -Ryman Ryo Munakata S Pradeep Kumar Sae-bom Kim @@ -1153,7 +1143,6 @@ Swaroop C H Sylvestre Ledru Taliesin Beynon Tamir Duberstein -Tamir Duberstein Taras Shpot tav Taylor Hutchison @@ -1169,7 +1158,6 @@ Thiago Pontes Thomas Backman Thomas Bracht Laumann Jespersen Thomas Daede -Thomas Jespersen Thomas Karpiniec Tiago Nobrega Tibor Benke @@ -1255,7 +1243,6 @@ Wei-Ming Yang Wendell Smith Wesley Wiser whataloadofwhat -whitequark wickerwaka Wilfred Hughes Will @@ -1275,8 +1262,6 @@ Xavier Shay Xiao Chuan Yu Xue Fuqiao Xuefeng Wu -Xuefeng Wu -XuefengWu Yasuhiro Fujii YawarRaza7349 Yazhong Liu diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 515e6e18f7050..a11e9a7d68053 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -34,6 +34,9 @@ While bugs are unfortunate, they're a reality in software. We can't fix what we don't know about, so please report liberally. If you're not sure if something is a bug or not, feel free to file a bug anyway. +**If you believe reporting your bug publicly represents a security risk to Rust users, +please follow our [instructions for reporting security vulnerabilities](https://www.rust-lang.org/security.html)**. + If you have the chance, before reporting a bug, please [search existing issues](https://github.com/rust-lang/rust/search?q=&type=Issues&utf8=%E2%9C%93), as it's possible that someone else has already reported your error. This doesn't diff --git a/README.md b/README.md index 5e208a76e0315..8eb742f0a22fc 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,9 @@ # The Rust Programming Language -Rust is a fast systems programming language that guarantees -memory safety and offers painless concurrency ([no data races]). -It does not employ a garbage collector and has minimal runtime overhead. +This is the main source code repository for [Rust]. It contains the compiler, standard library, +and documentation. -This repo contains the code for the compiler (`rustc`), as well -as standard libraries, tools and documentation for Rust. - -[no data races]: http://blog.rust-lang.org/2015/04/10/Fearless-Concurrency.html +[Rust]: https://www.rust-lang.org ## Quick Start diff --git a/RELEASES.md b/RELEASES.md index 9b61ce0e05414..54fe87dc65816 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,3 +1,182 @@ +Version 1.4.0 (2015-10-29) +============================ + +* ~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]. +* [`str::parse` no longer introduces avoidable rounding error when + parsing floating point numbers. Together with earlier changes to + float formatting/output, "round trips" like f.to_string().parse() + now preserve the value of f exactly. Additionally, leading plus + signs are now accepted][fp3]. + + +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]: `>::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` and `FromIterator` where `T: + Copy`][ext] as part of [RFC 839]. This will cause type inferance + breakage in rare situations. +* [`BinaryHeap` implements `Debug`][bh2]. +* [`Borrow` and `BorrowMut` are implemented for fixed-size + arrays][bm]. +* [`extern fn`s with the "Rust" and "C" ABIs implement common + traits including `Eq`, `Ord`, `Debug`, `Hash`][fp]. +* [String comparison is faster][faststr]. +* `&mut T` where `T: std::fmt::Write` [also implements + `std::fmt::Write`][mutw]. +* [A stable regression in `VecDeque::push_back` and other + capicity-altering methods 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 +[fp3]: https://github.com/rust-lang/rust/pull/27307 +[i]: https://github.com/rust-lang/rust/pull/27451 +[into2]: 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) ============================== diff --git a/configure b/configure index 76bee86182282..4fb6cb53bd855 100755 --- a/configure +++ b/configure @@ -1484,25 +1484,9 @@ do done fi - if [ ${do_reconfigure} -ne 0 ] && [ ${is_msvc} -ne 0 ] + # We need the generator later on for compiler-rt even if LLVM's not built + if [ ${is_msvc} -ne 0 ] then - msg "configuring LLVM for $t with cmake" - - CMAKE_ARGS="-DLLVM_INCLUDE_TESTS=OFF" - if [ -n "$CFG_DISABLE_OPTIMIZE_LLVM" ]; then - CMAKE_ARGS="$CMAKE_ARGS -DCMAKE_BUILD_TYPE=Debug" - else - CMAKE_ARGS="$CMAKE_ARGS -DCMAKE_BUILD_TYPE=Release" - fi - if [ -z "$CFG_ENABLE_LLVM_ASSERTIONS" ] - then - CMAKE_ARGS="$CMAKE_ARGS -DLLVM_ENABLE_ASSERTIONS=OFF" - else - CMAKE_ARGS="$CMAKE_ARGS -DLLVM_ENABLE_ASSERTIONS=ON" - fi - - msg "configuring LLVM with:" - msg "$CMAKE_ARGS" case "$CFG_MSVC_ROOT" in *14.0*) generator="Visual Studio 14 2015" @@ -1524,8 +1508,32 @@ do err "can only build LLVM for x86 platforms" ;; esac + CFG_CMAKE_GENERATOR=$generator + putvar CFG_CMAKE_GENERATOR + fi + + if [ ${do_reconfigure} -ne 0 ] && [ ${is_msvc} -ne 0 ] + then + msg "configuring LLVM for $t with cmake" + + CMAKE_ARGS="-DLLVM_INCLUDE_TESTS=OFF" + if [ -n "$CFG_DISABLE_OPTIMIZE_LLVM" ]; then + CMAKE_ARGS="$CMAKE_ARGS -DCMAKE_BUILD_TYPE=Debug" + else + CMAKE_ARGS="$CMAKE_ARGS -DCMAKE_BUILD_TYPE=Release" + fi + if [ -z "$CFG_ENABLE_LLVM_ASSERTIONS" ] + then + CMAKE_ARGS="$CMAKE_ARGS -DLLVM_ENABLE_ASSERTIONS=OFF" + else + CMAKE_ARGS="$CMAKE_ARGS -DLLVM_ENABLE_ASSERTIONS=ON" + fi + + msg "configuring LLVM with:" + msg "$CMAKE_ARGS" + (cd $LLVM_BUILD_DIR && "$CFG_CMAKE" $CFG_LLVM_SRC_DIR \ - -G "$generator" \ + -G "$CFG_CMAKE_GENERATOR" \ $CMAKE_ARGS) need_ok "LLVM cmake configure failed" fi diff --git a/mk/cfg/i686-pc-windows-gnu.mk b/mk/cfg/i686-pc-windows-gnu.mk index ced8bf43163e7..67453d8ca790e 100644 --- a/mk/cfg/i686-pc-windows-gnu.mk +++ b/mk/cfg/i686-pc-windows-gnu.mk @@ -22,4 +22,5 @@ CFG_LDPATH_i686-pc-windows-gnu := CFG_RUN_i686-pc-windows-gnu=$(2) CFG_RUN_TARG_i686-pc-windows-gnu=$(call CFG_RUN_i686-pc-windows-gnu,,$(2)) CFG_GNU_TRIPLE_i686-pc-windows-gnu := i686-w64-mingw32 -CFG_LIBC_STARTUP_OBJECTS_i686-pc-windows-gnu := crt2.o dllcrt2.o +CFG_THIRD_PARTY_OBJECTS_i686-pc-windows-gnu := crt2.o dllcrt2.o +CFG_INSTALLED_OBJECTS_i686-pc-windows-gnu := crt2.o dllcrt2.o rsbegin.o rsend.o diff --git a/mk/cfg/x86_64-pc-windows-gnu.mk b/mk/cfg/x86_64-pc-windows-gnu.mk index 0f49b6d585c6e..fc5001c3b027c 100644 --- a/mk/cfg/x86_64-pc-windows-gnu.mk +++ b/mk/cfg/x86_64-pc-windows-gnu.mk @@ -22,4 +22,5 @@ CFG_LDPATH_x86_64-pc-windows-gnu := CFG_RUN_x86_64-pc-windows-gnu=$(2) CFG_RUN_TARG_x86_64-pc-windows-gnu=$(call CFG_RUN_x86_64-pc-windows-gnu,,$(2)) CFG_GNU_TRIPLE_x86_64-pc-windows-gnu := x86_64-w64-mingw32 -CFG_LIBC_STARTUP_OBJECTS_x86_64-pc-windows-gnu := crt2.o dllcrt2.o \ No newline at end of file +CFG_THIRD_PARTY_OBJECTS_x86_64-pc-windows-gnu := crt2.o dllcrt2.o +CFG_INSTALLED_OBJECTS_x86_64-pc-windows-gnu := crt2.o dllcrt2.o rsbegin.o rsend.o diff --git a/mk/cfg/x86_64-unknown-linux-musl.mk b/mk/cfg/x86_64-unknown-linux-musl.mk index 960dabdcf9f18..9d6dd5c73d7b7 100644 --- a/mk/cfg/x86_64-unknown-linux-musl.mk +++ b/mk/cfg/x86_64-unknown-linux-musl.mk @@ -21,8 +21,8 @@ CFG_LDPATH_x86_64-unknown-linux-musl := CFG_RUN_x86_64-unknown-linux-musl=$(2) CFG_RUN_TARG_x86_64-unknown-linux-musl=$(call CFG_RUN_x86_64-unknown-linux-musl,,$(2)) CFG_GNU_TRIPLE_x86_64-unknown-linux-musl := x86_64-unknown-linux-musl +CFG_THIRD_PARTY_OBJECTS_x86_64-unknown-linux-musl := crt1.o crti.o crtn.o +CFG_INSTALLED_OBJECTS_x86_64-unknown-linux-musl := crt1.o crti.o crtn.o NATIVE_DEPS_libc_T_x86_64-unknown-linux-musl += libc.a -NATIVE_DEPS_std_T_x86_64-unknown-linux-musl += libunwind.a \ - crt1.o crti.o crtn.o -INSTALLED_OBJECTS_x86_64-unknown-linux-musl += crt1.o crti.o crtn.o +NATIVE_DEPS_std_T_x86_64-unknown-linux-musl += libunwind.a crt1.o crti.o crtn.o diff --git a/mk/crates.mk b/mk/crates.mk index 6673b9b28e716..89a836eb7cb31 100644 --- a/mk/crates.mk +++ b/mk/crates.mk @@ -103,7 +103,7 @@ DEPS_rustc_mir := rustc rustc_front syntax DEPS_rustc_resolve := rustc rustc_front log syntax DEPS_rustc_platform_intrinsics := rustc rustc_llvm DEPS_rustc_privacy := rustc rustc_front log syntax -DEPS_rustc_trans := arena flate getopts graphviz libc rustc rustc_back \ +DEPS_rustc_trans := arena flate getopts graphviz libc rustc rustc_back rustc_mir \ log syntax serialize rustc_llvm rustc_front rustc_platform_intrinsics DEPS_rustc_typeck := rustc syntax rustc_front rustc_platform_intrinsics @@ -174,3 +174,6 @@ $(foreach crate,$(TOOLS),$(eval $(call RUST_TOOL,$(crate)))) ifdef CFG_DISABLE_ELF_TLS RUSTFLAGS_std := --cfg no_elf_tls endif + +CRATEFILE_libc := $(SREL)src/liblibc/src/lib.rs +RUSTFLAGS_libc := --cfg stdbuild diff --git a/mk/dist.mk b/mk/dist.mk index 4cdee8bda9d4c..7ef95d1e78f80 100644 --- a/mk/dist.mk +++ b/mk/dist.mk @@ -59,6 +59,7 @@ PKG_FILES := \ libcoretest \ libbacktrace \ rt \ + rtstartup \ rustllvm \ snapshots.txt \ rust-installer \ diff --git a/mk/llvm.mk b/mk/llvm.mk index 1cbf4a9fb841c..b2a90f583f7b2 100644 --- a/mk/llvm.mk +++ b/mk/llvm.mk @@ -64,10 +64,10 @@ $$(LLVM_AR_$(1)): $$(LLVM_CONFIG_$(1)) # when we changed something not otherwise captured by builtin # dependencies. In these cases, commit a change that touches # the stamp in the source dir. -$$(LLVM_STAMP_$(1)): $(S)src/rustllvm/llvm-auto-clean-trigger +$$(LLVM_STAMP_$(1)): $$(S)src/rustllvm/llvm-auto-clean-trigger @$$(call E, make: cleaning llvm) - $(Q)touch $$@.start_time - $(Q)$(MAKE) clean-llvm$(1) + $$(Q)touch $$@.start_time + $$(Q)$$(MAKE) clean-llvm$(1) @$$(call E, make: done cleaning llvm) touch -r $$@.start_time $$@ && rm $$@.start_time diff --git a/mk/main.mk b/mk/main.mk index 07186bd41b469..1be09ca72579b 100644 --- a/mk/main.mk +++ b/mk/main.mk @@ -111,8 +111,7 @@ CFG_RUSTC_FLAGS := $(RUSTFLAGS) CFG_GCCISH_CFLAGS := CFG_GCCISH_LINK_FLAGS := -# Turn off broken quarantine (see jemalloc/jemalloc#161) -CFG_JEMALLOC_FLAGS := --disable-fill +CFG_JEMALLOC_FLAGS := ifdef CFG_DISABLE_OPTIMIZE $(info cfg: disabling rustc optimization (CFG_DISABLE_OPTIMIZE)) @@ -184,7 +183,7 @@ include $(CFG_SRC_DIR)mk/platform.mk # Run the stage1/2 compilers under valgrind ifdef VALGRIND_COMPILE - CFG_VALGRIND_COMPILE :=$(CFG_VALGRIND) + CFG_VALGRIND_COMPILE := $(CFG_VALGRIND) else CFG_VALGRIND_COMPILE := endif @@ -202,6 +201,7 @@ endif ifdef CFG_ENABLE_VALGRIND $(info cfg: enabling valgrind (CFG_ENABLE_VALGRIND)) + CFG_JEMALLOC_FLAGS += --enable-valgrind else CFG_VALGRIND := endif @@ -380,7 +380,7 @@ HBIN$(1)_H_$(3) = $$(HROOT$(1)_H_$(3))/bin ifeq ($$(CFG_WINDOWSY_$(3)),1) # On Windows we always store host runtime libraries in the 'bin' directory because # there's no rpath. Target libraries go under $CFG_LIBDIR_RELATIVE (usually 'lib'). -HLIB$(1)_H_$(3) = $$(HROOT$(1)_H_$(3))/bin +HLIB_RELATIVE$(1)_H_$(3) = bin TROOT$(1)_T_$(2)_H_$(3) = $$(HROOT$(1)_H_$(3))/$$(CFG_LIBDIR_RELATIVE)/rustlib/$(2) # Remove the next 3 lines after a snapshot ifeq ($(1),0) @@ -390,13 +390,14 @@ endif else ifeq ($(1),0) -HLIB$(1)_H_$(3) = $$(HROOT$(1)_H_$(3))/lib +HLIB_RELATIVE$(1)_H_$(3) = lib else -HLIB$(1)_H_$(3) = $$(HROOT$(1)_H_$(3))/$$(CFG_LIBDIR_RELATIVE) +HLIB_RELATIVE$(1)_H_$(3) = $$(CFG_LIBDIR_RELATIVE) endif TROOT$(1)_T_$(2)_H_$(3) = $$(HLIB$(1)_H_$(3))/rustlib/$(2) endif +HLIB$(1)_H_$(3) = $$(HROOT$(1)_H_$(3))/$$(HLIB_RELATIVE$(1)_H_$(3)) # Destinations of artifacts for target architectures TBIN$(1)_T_$(2)_H_$(3) = $$(TROOT$(1)_T_$(2)_H_$(3))/bin @@ -415,7 +416,7 @@ endif # Prerequisites for using the stageN compiler to build target artifacts TSREQ$(1)_T_$(2)_H_$(3) = \ $$(HSREQ$(1)_H_$(3)) \ - $$(foreach obj,$$(INSTALLED_OBJECTS_$(2)),\ + $$(foreach obj,$$(REQUIRED_OBJECTS_$(2)),\ $$(TLIB$(1)_T_$(2)_H_$(3))/$$(obj)) # Prerequisites for a working stageN compiler and libraries, for a specific diff --git a/mk/platform.mk b/mk/platform.mk index 856a22dc6067d..b8058882f9d94 100644 --- a/mk/platform.mk +++ b/mk/platform.mk @@ -113,7 +113,10 @@ CFG_RLIB_GLOB=lib$(1)-*.rlib include $(wildcard $(CFG_SRC_DIR)mk/cfg/*.mk) define ADD_INSTALLED_OBJECTS + INSTALLED_OBJECTS_$(1) += $$(CFG_INSTALLED_OBJECTS_$(1)) + REQUIRED_OBJECTS_$(1) += $$(CFG_THIRD_PARTY_OBJECTS_$(1)) INSTALLED_OBJECTS_$(1) += $$(call CFG_STATIC_LIB_NAME_$(1),compiler-rt) + REQUIRED_OBJECTS_$(1) += $$(call CFG_STATIC_LIB_NAME_$(1),compiler-rt) endef $(foreach target,$(CFG_TARGET), \ diff --git a/mk/prepare.mk b/mk/prepare.mk index e263a6d2e4d32..5a16afdf23a27 100644 --- a/mk/prepare.mk +++ b/mk/prepare.mk @@ -90,6 +90,8 @@ PREPARE_TOOLS = $(filter-out compiletest rustbook error-index-generator, $(TOOLS # $(3) is host # $(4) tag define DEF_PREPARE_HOST_TOOL +prepare-host-tool-$(1)-$(2)-$(3)-$(4): \ + PREPARE_SOURCE_BIN_DIR=$$(HBIN$(2)_H_$(3)) prepare-host-tool-$(1)-$(2)-$(3)-$(4): prepare-maybe-clean-$(4) \ $$(foreach dep,$$(TOOL_DEPS_$(1)),prepare-host-lib-$$(dep)-$(2)-$(3)-$(4)) \ $$(HBIN$(2)_H_$(3))/$(1)$$(X_$(3)) \ @@ -110,8 +112,10 @@ endef # $(3) is host # $(4) tag define DEF_PREPARE_HOST_LIB -prepare-host-lib-$(1)-$(2)-$(3)-$(4): PREPARE_WORKING_SOURCE_LIB_DIR=$$(PREPARE_SOURCE_LIB_DIR) -prepare-host-lib-$(1)-$(2)-$(3)-$(4): PREPARE_WORKING_DEST_LIB_DIR=$$(PREPARE_DEST_LIB_DIR) +prepare-host-lib-$(1)-$(2)-$(3)-$(4): \ + PREPARE_WORKING_SOURCE_LIB_DIR=$$(HLIB$(2)_H_$(3)) +prepare-host-lib-$(1)-$(2)-$(3)-$(4): \ + PREPARE_WORKING_DEST_LIB_DIR=$$(PREPARE_DEST_DIR)/$$(HLIB_RELATIVE$(2)_H_$(3)) prepare-host-lib-$(1)-$(2)-$(3)-$(4): prepare-maybe-clean-$(4) \ $$(foreach dep,$$(RUST_DEPS_$(1)),prepare-host-lib-$$(dep)-$(2)-$(3)-$(4)) \ $$(HLIB$(2)_H_$(3))/stamp.$(1) \ @@ -129,10 +133,14 @@ endef # $(4) tag define DEF_PREPARE_TARGET_N # Rebind PREPARE_*_LIB_DIR to point to rustlib, then install the libs for the targets -prepare-target-$(2)-host-$(3)-$(1)-$(4): PREPARE_WORKING_SOURCE_LIB_DIR=$$(PREPARE_SOURCE_LIB_DIR)/rustlib/$(2)/lib -prepare-target-$(2)-host-$(3)-$(1)-$(4): PREPARE_WORKING_DEST_LIB_DIR=$$(PREPARE_DEST_LIB_DIR)/rustlib/$(2)/lib -prepare-target-$(2)-host-$(3)-$(1)-$(4): PREPARE_SOURCE_BIN_DIR=$$(PREPARE_SOURCE_LIB_DIR)/rustlib/$(3)/bin -prepare-target-$(2)-host-$(3)-$(1)-$(4): PREPARE_DEST_BIN_DIR=$$(PREPARE_DEST_LIB_DIR)/rustlib/$(3)/bin +prepare-target-$(2)-host-$(3)-$(1)-$(4): \ + PREPARE_WORKING_SOURCE_LIB_DIR=$$(TLIB$(1)_T_$(2)_H_$(3)) +prepare-target-$(2)-host-$(3)-$(1)-$(4): \ + PREPARE_WORKING_DEST_LIB_DIR=$$(PREPARE_DEST_LIB_DIR)/rustlib/$(2)/lib +prepare-target-$(2)-host-$(3)-$(1)-$(4): \ + PREPARE_SOURCE_BIN_DIR=$$(TBIN$(1)_T_$(2)_H_$(3)) +prepare-target-$(2)-host-$(3)-$(1)-$(4): \ + PREPARE_DEST_BIN_DIR=$$(PREPARE_DEST_LIB_DIR)/rustlib/$(3)/bin prepare-target-$(2)-host-$(3)-$(1)-$(4): prepare-maybe-clean-$(4) \ $$(foreach crate,$$(TARGET_CRATES), \ $$(TLIB$(1)_T_$(2)_H_$(3))/stamp.$$(crate)) \ @@ -185,9 +193,6 @@ INSTALL_DEBUGGER_SCRIPT_COMMANDS=$(if $(findstring windows,$(1)),\ define DEF_PREPARE -prepare-base-$(1)-%: PREPARE_SOURCE_DIR=$$(PREPARE_HOST)/stage$$(PREPARE_STAGE) -prepare-base-$(1)-%: PREPARE_SOURCE_BIN_DIR=$$(PREPARE_SOURCE_DIR)/bin -prepare-base-$(1)-%: PREPARE_SOURCE_LIB_DIR=$$(PREPARE_SOURCE_DIR)/$$(CFG_LIBDIR_RELATIVE) prepare-base-$(1)-%: PREPARE_SOURCE_MAN_DIR=$$(S)/man prepare-base-$(1)-%: PREPARE_DEST_BIN_DIR=$$(PREPARE_DEST_DIR)/bin prepare-base-$(1)-%: PREPARE_DEST_LIB_DIR=$$(PREPARE_DEST_DIR)/$$(CFG_LIBDIR_RELATIVE) diff --git a/mk/rt.mk b/mk/rt.mk index 1f60aaed4730b..8433b588e6ba4 100644 --- a/mk/rt.mk +++ b/mk/rt.mk @@ -216,22 +216,31 @@ COMPRT_NAME_$(1) := $$(call CFG_STATIC_LIB_NAME_$(1),compiler-rt) COMPRT_LIB_$(1) := $$(RT_OUTPUT_DIR_$(1))/$$(COMPRT_NAME_$(1)) COMPRT_BUILD_DIR_$(1) := $$(RT_OUTPUT_DIR_$(1))/compiler-rt -# Note that on MSVC-targeting builds we hardwire CC/AR to gcc/ar even though -# we're targeting MSVC. This is because although compiler-rt has a CMake build -# config I can't actually figure out how to use it, so I'm not sure how to use -# cl.exe to build the objects. Additionally, the compiler-rt library when built -# with gcc has the same ABI as cl.exe, so they're largely compatible -COMPRT_CC_$(1) := $$(CC_$(1)) -COMPRT_AR_$(1) := $$(AR_$(1)) -COMPRT_CFLAGS_$(1) := $$(CFG_GCCISH_CFLAGS_$(1)) ifeq ($$(findstring msvc,$(1)),msvc) -COMPRT_CC_$(1) := gcc -COMPRT_AR_$(1) := ar -ifeq ($$(findstring i686,$(1)),i686) -COMPRT_CFLAGS_$(1) := $$(CFG_GCCISH_CFLAGS_$(1)) -m32 +$$(COMPRT_LIB_$(1)): $$(COMPRT_DEPS) $$(MKFILE_DEPS) $$(LLVM_CONFIG_$(1)) + @$$(call E, cmake: compiler-rt) + $$(Q)cd "$$(COMPRT_BUILD_DIR_$(1))"; $$(CFG_CMAKE) "$(S)src/compiler-rt" \ + -DCMAKE_BUILD_TYPE=$$(LLVM_BUILD_CONFIG_MODE) \ + -DLLVM_CONFIG_PATH=$$(LLVM_CONFIG_$(1)) \ + -G"$$(CFG_CMAKE_GENERATOR)" + $$(Q)$$(CFG_CMAKE) --build "$$(COMPRT_BUILD_DIR_$(1))" \ + --target lib/builtins/builtins \ + --config $$(LLVM_BUILD_CONFIG_MODE) \ + -- //v:m //nologo + $$(Q)cp $$(COMPRT_BUILD_DIR_$(1))/lib/windows/$$(LLVM_BUILD_CONFIG_MODE)/clang_rt.builtins-$$(HOST_$(1)).lib $$@ else -COMPRT_CFLAGS_$(1) := $$(CFG_GCCISH_CFLAGS_$(1)) -m64 -endif +COMPRT_CC_$(1) := $$(CC_$(1)) +COMPRT_AR_$(1) := $$(AR_$(1)) +# We chomp -Werror here because GCC warns about the type signature of +# builtins not matching its own and the build fails. It's a bit hacky, +# but what can we do, we're building libclang-rt using GCC ...... +COMPRT_CFLAGS_$(1) := $$(subst -Werror,,$$(CFG_GCCISH_CFLAGS_$(1))) -std=c99 + +# FreeBSD Clang's packaging is problematic; it doesn't copy unwind.h to +# the standard include directory. This should really be in our changes to +# compiler-rt, but we override the CFLAGS here so there isn't much choice +ifeq ($$(findstring freebsd,$(1)),freebsd) + COMPRT_CFLAGS_$(1) += -I/usr/include/c++/v1 endif $$(COMPRT_LIB_$(1)): $$(COMPRT_DEPS) $$(MKFILE_DEPS) @@ -246,7 +255,7 @@ $$(COMPRT_LIB_$(1)): $$(COMPRT_DEPS) $$(MKFILE_DEPS) TargetTriple=$(1) \ triple-builtins $$(Q)cp $$(COMPRT_BUILD_DIR_$(1))/triple/builtins/libcompiler_rt.a $$@ - +endif ################################################################################ # libbacktrace # @@ -343,6 +352,10 @@ endif # endif for darwin ifeq ($$(findstring musl,$(1)),musl) $$(RT_OUTPUT_DIR_$(1))/%: $$(CFG_MUSL_ROOT)/lib/% cp $$^ $$@ +else +# Ask gcc where it is +$$(RT_OUTPUT_DIR_$(1))/%: + cp $$(shell $$(CC_$(1)) -print-file-name=$$(@F)) $$@ endif endef diff --git a/mk/snap.mk b/mk/snap.mk index 86c89cf0210ee..0b34f52b7ebbe 100644 --- a/mk/snap.mk +++ b/mk/snap.mk @@ -18,8 +18,8 @@ snap-stage$(1)-H-$(2): $$(HSREQ$(1)_H_$(2)) endef $(foreach host,$(CFG_HOST), \ - $(eval $(foreach stage,1 2 3, \ - $(eval $(call DEF_SNAP_FOR_STAGE_H,$(stage),$(host)))))) + $(foreach stage,1 2 3, \ + $(eval $(call DEF_SNAP_FOR_STAGE_H,$(stage),$(host))))) snap-stage1: snap-stage1-H-$(CFG_BUILD) diff --git a/mk/target.mk b/mk/target.mk index 5caf8d8e81eda..ae9fd9d1adacf 100644 --- a/mk/target.mk +++ b/mk/target.mk @@ -132,26 +132,6 @@ $$(TBIN$(1)_T_$(2)_H_$(3))/$(4)$$(X_$(2)): \ endef -# Macro for building runtime startup objects -# Of those we have two kinds: -# - Rust runtime-specific: these are Rust's equivalents of GCC's crti.o/crtn.o, -# - LibC-specific: these we don't build ourselves, but copy them from the system lib directory. -# -# $(1) - stage -# $(2) - target triple -# $(3) - host triple -define TARGET_RT_STARTUP - -# Expand build rules for rsbegin.o and rsend.o -$$(foreach obj,rsbegin rsend, \ - $$(eval $$(call TARGET_RUSTRT_STARTUP_OBJ,$(1),$(2),$(3),$$(obj))) ) - -# Expand build rules for libc startup objects -$$(foreach obj,$$(CFG_LIBC_STARTUP_OBJECTS_$(2)), \ - $$(eval $$(call TARGET_LIBC_STARTUP_OBJ,$(1),$(2),$(3),$$(obj))) ) - -endef - # Macro for building runtime startup/shutdown object files; # these are Rust's equivalent of crti.o, crtn.o # @@ -178,27 +158,6 @@ $$(foreach crate, $$(TARGET_CRATES), \ endef -# Macro for copying libc startup objects into the target's lib directory. -# -# $(1) - stage -# $(2) - target triple -# $(3) - host triple -# $(4) - object name -define TARGET_LIBC_STARTUP_OBJ - -# Ask gcc where the startup object is located -$$(TLIB$(1)_T_$(2)_H_$(3))/$(4) : $$(shell $$(CC_$(2)) -print-file-name=$(4)) - @$$(call E, cp: $$@) - @cp $$^ $$@ - -# Make sure this is done before libcore has finished building -# (libcore itself does not depend on these objects, but other crates do, -# so might as well do it here) -$$(TLIB$(1)_T_$(2)_H_$(3))/stamp.core : $$(TLIB$(1)_T_$(2)_H_$(3))/$(4) - -endef - - # Every recipe in RUST_TARGET_STAGE_N outputs to $$(TLIB$(1)_T_$(2)_H_$(3), # a directory that can be cleaned out during the middle of a run of # the get-snapshot.py script. Therefore, every recipe needs to have @@ -245,4 +204,5 @@ $(foreach host,$(CFG_HOST), \ $(foreach host,$(CFG_HOST), \ $(foreach target,$(CFG_TARGET), \ $(foreach stage,$(STAGES), \ - $(eval $(call TARGET_RT_STARTUP,$(stage),$(target),$(host)))))) + $(foreach obj,rsbegin rsend, \ + $(eval $(call TARGET_RUSTRT_STARTUP_OBJ,$(stage),$(target),$(host),$(obj))))))) diff --git a/mk/tests.mk b/mk/tests.mk index d004558d1bf3f..73aec5de8da32 100644 --- a/mk/tests.mk +++ b/mk/tests.mk @@ -22,10 +22,11 @@ $(eval $(call RUST_CRATE,coretest)) DEPS_collectionstest := $(eval $(call RUST_CRATE,collectionstest)) -TEST_TARGET_CRATES = $(filter-out core rustc_unicode alloc_system \ +TEST_TARGET_CRATES = $(filter-out core rustc_unicode alloc_system libc \ alloc_jemalloc,$(TARGET_CRATES)) \ collectionstest coretest -TEST_DOC_CRATES = $(DOC_CRATES) +TEST_DOC_CRATES = $(DOC_CRATES) arena flate fmt_macros getopts graphviz \ + log rand rbml serialize syntax term test TEST_HOST_CRATES = $(filter-out rustc_typeck rustc_borrowck rustc_resolve \ rustc_trans rustc_lint,\ $(HOST_CRATES)) @@ -283,6 +284,7 @@ tidy-binaries: | grep '^$(S)src/compiler-rt' -v \ | grep '^$(S)src/libbacktrace' -v \ | grep '^$(S)src/rust-installer' -v \ + | grep '^$(S)src/liblibc' -v \ | xargs $(CFG_PYTHON) $(S)src/etc/check-binaries.py .PHONY: tidy-errors diff --git a/src/compiler-rt b/src/compiler-rt index 58ab642c30d9f..b6087e82ba138 160000 --- a/src/compiler-rt +++ b/src/compiler-rt @@ -1 +1 @@ -Subproject commit 58ab642c30d9f97735d5745b5d01781ee199c6ae +Subproject commit b6087e82ba1384c4af3adf2dc68e92316f0d4caf diff --git a/src/compiletest/raise_fd_limit.rs b/src/compiletest/raise_fd_limit.rs index 89b9135558e06..0cf90ec95f38e 100644 --- a/src/compiletest/raise_fd_limit.rs +++ b/src/compiletest/raise_fd_limit.rs @@ -23,25 +23,8 @@ pub unsafe fn raise_fd_limit() { use std::mem::size_of_val; use std::ptr::null_mut; - type rlim_t = libc::uint64_t; - - #[repr(C)] - struct rlimit { - rlim_cur: rlim_t, - rlim_max: rlim_t - } - extern { - // name probably doesn't need to be mut, but the C function doesn't - // specify const - fn sysctl(name: *mut libc::c_int, namelen: libc::c_uint, - oldp: *mut libc::c_void, oldlenp: *mut libc::size_t, - newp: *mut libc::c_void, newlen: libc::size_t) -> libc::c_int; - fn getrlimit(resource: libc::c_int, rlp: *mut rlimit) -> libc::c_int; - fn setrlimit(resource: libc::c_int, rlp: *const rlimit) -> libc::c_int; - } static CTL_KERN: libc::c_int = 1; static KERN_MAXFILESPERPROC: libc::c_int = 29; - static RLIMIT_NOFILE: libc::c_int = 8; // The strategy here is to fetch the current resource limits, read the // kern.maxfilesperproc sysctl value, and bump the soft resource limit for @@ -51,25 +34,25 @@ pub unsafe fn raise_fd_limit() { let mut mib: [libc::c_int; 2] = [CTL_KERN, KERN_MAXFILESPERPROC]; let mut maxfiles: libc::c_int = 0; let mut size: libc::size_t = size_of_val(&maxfiles) as libc::size_t; - if sysctl(&mut mib[0], 2, &mut maxfiles as *mut _ as *mut _, &mut size, + if libc::sysctl(&mut mib[0], 2, &mut maxfiles as *mut _ as *mut _, &mut size, null_mut(), 0) != 0 { let err = io::Error::last_os_error(); panic!("raise_fd_limit: error calling sysctl: {}", err); } // Fetch the current resource limits - let mut rlim = rlimit{rlim_cur: 0, rlim_max: 0}; - if getrlimit(RLIMIT_NOFILE, &mut rlim) != 0 { + let mut rlim = libc::rlimit{rlim_cur: 0, rlim_max: 0}; + if libc::getrlimit(libc::RLIMIT_NOFILE, &mut rlim) != 0 { let err = io::Error::last_os_error(); panic!("raise_fd_limit: error calling getrlimit: {}", err); } // Bump the soft limit to the smaller of kern.maxfilesperproc and the hard // limit - rlim.rlim_cur = cmp::min(maxfiles as rlim_t, rlim.rlim_max); + rlim.rlim_cur = cmp::min(maxfiles as libc::rlim_t, rlim.rlim_max); // Set our newly-increased resource limit - if setrlimit(RLIMIT_NOFILE, &rlim) != 0 { + if libc::setrlimit(libc::RLIMIT_NOFILE, &rlim) != 0 { let err = io::Error::last_os_error(); panic!("raise_fd_limit: error calling setrlimit: {}", err); } diff --git a/src/compiletest/runtest.rs b/src/compiletest/runtest.rs index 8db6725f7a8f8..8042e2f966ca7 100644 --- a/src/compiletest/runtest.rs +++ b/src/compiletest/runtest.rs @@ -430,7 +430,7 @@ fn run_debuginfo_gdb_test(config: &Config, props: &TestProps, testfile: &Path) { .expect(&format!("failed to exec `{:?}`", config.adb_path)); loop { //waiting 1 second for gdbserver start - ::std::thread::sleep_ms(1000); + ::std::thread::sleep(::std::time::Duration::new(1,0)); if TcpStream::connect("127.0.0.1:5039").is_ok() { break } diff --git a/src/doc/nomicon/lifetimes.md b/src/doc/nomicon/lifetimes.md index e48d5f852f06a..e21207efdcf9d 100644 --- a/src/doc/nomicon/lifetimes.md +++ b/src/doc/nomicon/lifetimes.md @@ -193,7 +193,7 @@ println!("{}", x); } ``` -The problem here is is bit more subtle and interesting. We want Rust to +The problem here is a bit more subtle and interesting. We want Rust to reject this program for the following reason: We have a live shared reference `x` to a descendant of `data` when we try to take a mutable reference to `data` to `push`. This would create an aliased mutable reference, which would diff --git a/src/doc/nomicon/other-reprs.md b/src/doc/nomicon/other-reprs.md index e361fbb7ae868..2639c1d4d6f76 100644 --- a/src/doc/nomicon/other-reprs.md +++ b/src/doc/nomicon/other-reprs.md @@ -26,6 +26,9 @@ still consumes a byte of space. * DSTs, tuples, and tagged unions are not a concept in C and as such are never FFI safe. +* Tuple structs are like structs with regards to `repr(C)`, as the only + difference from a struct is that the fields aren’t named. + * **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 diff --git a/src/doc/reference.md b/src/doc/reference.md index 037fb6a8d98d8..de9352a42753c 100644 --- a/src/doc/reference.md +++ b/src/doc/reference.md @@ -99,13 +99,12 @@ Comments in Rust code follow the general C++ style of line (`//`) and block (`/* ... */`) comment forms. Nested block comments are supported. Line comments beginning with exactly _three_ slashes (`///`), and block -comments beginning with exactly one repeated asterisk in the block-open -sequence (`/**`), are interpreted as a special syntax for `doc` +comments (`/** ... */`), are interpreted as a special syntax for `doc` [attributes](#attributes). That is, they are equivalent to writing `#[doc="..."]` around the body of the comment, i.e., `/// Foo` turns into `#[doc="Foo"]`. -Line comments beginning with `//!` and block comments beginning with `/*!` are +Line comments beginning with `//!` and block comments `/*! ... !*/` are doc comments that apply to the parent of the comment, rather than the item that follows. That is, they are equivalent to writing `#![doc="..."]` around the body of the comment. `//!` comments are usually used to document @@ -547,9 +546,20 @@ a `$` literally, including delimiters. For parsing reasons, delimiters must be 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), and `meta` (contents of an attribute). In the transcriber, the +syntax named by _designator_. Valid designators are: + +* `item`: an [item](#items) +* `block`: a [block](#block-expressions) +* `stmt`: a [statement](#statements) +* `pat`: a [pattern](#match-expressions) +* `expr`: an [expression](#expressions) +* `ty`: a [type](#types) +* `ident`: an [identifier](#identifiers) +* `path`: a [path](#paths) +* `tt`: either side of the `=>` in macro rules +* `meta`: the contents of an [attribute](#attributes) + +In the transcriber, the designator is already known, and so only the name of a matched nonterminal comes after the dollar sign. @@ -2316,13 +2326,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_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 - that this style of variant should remain in the language. - For now this style of variant is hidden behind a feature - flag. - * `thread_local` - The usage of the `#[thread_local]` attribute is experimental and should be seen as unstable. This attribute is used to declare a `static` as being unique per-thread leveraging diff --git a/src/doc/style/safety/lib-guarantees.md b/src/doc/style/safety/lib-guarantees.md index aa87223383a10..8ee64f1806a69 100644 --- a/src/doc/style/safety/lib-guarantees.md +++ b/src/doc/style/safety/lib-guarantees.md @@ -70,8 +70,8 @@ that all instances are valid utf-8: Providing library-level guarantees sometimes entails inconvenience (for static checks) or overhead (for dynamic checks). So it is sometimes desirable to allow clients to sidestep this checking, while promising to use the API in a way that -still provides the guarantee. Such escape hatches should only be be introduced -when there is a demonstrated need for them. +still provides the guarantee. Such escape hatches should only be introduced when +there is a demonstrated need for them. It should be trivial for clients to audit their use of the library for escape hatches. diff --git a/src/doc/trpl/README.md b/src/doc/trpl/README.md index 6962f828e194d..7acb7f835b8dd 100644 --- a/src/doc/trpl/README.md +++ b/src/doc/trpl/README.md @@ -41,158 +41,8 @@ Copious cross-linking connects these parts together. ### Contributing -The source files from which this book is generated can be found on GitHub: -[github.com/rust-lang/rust/tree/master/src/doc/trpl](https://github.com/rust-lang/rust/tree/master/src/doc/trpl) +The source files from which this book is generated can be found on +[GitHub][trpl]. -## A brief introduction to Rust +[trpl]: https://github.com/rust-lang/rust/tree/master/src/doc/trpl -Is Rust a language you might be interested in? Let’s examine a few small code -samples to show off a few of its strengths. - -The main concept that makes Rust unique is called ‘ownership’. Consider this -small example: - -```rust -fn main() { - let mut x = vec!["Hello", "world"]; -} -``` - -This program makes a [variable binding][var] named `x`. The value of this -binding is a `Vec`, a ‘vector’, that we create through a [macro][macro] -defined in the standard library. This macro is called `vec`, and we invoke -macros with a `!`. This follows a general principle of Rust: make things -explicit. Macros can do significantly more complicated things than function -calls, and so they’re visually distinct. The `!` also helps with parsing, -making tooling easier to write, which is also important. - -We used `mut` to make `x` mutable: bindings are immutable by default in Rust. -We’ll be mutating this vector later in the example. - -It’s also worth noting that we didn’t need a type annotation here: while Rust -is statically typed, we didn’t need to explicitly annotate the type. Rust has -type inference to balance out the power of static typing with the verbosity of -annotating types. - -Rust prefers stack allocation to heap allocation: `x` is placed directly on the -stack. However, the `Vec` type allocates space for the elements of the vector -on the heap. If you’re not familiar with this distinction, you can ignore it for -now, or check out [‘The Stack and the Heap’][heap]. As a systems programming -language, Rust gives us the ability to control how our memory is allocated, but -when we’re getting started, it’s less of a big deal. - -[var]: variable-bindings.html -[macro]: macros.html -[heap]: the-stack-and-the-heap.html - -Earlier, we mentioned that ‘ownership’ is the key new concept in Rust. In Rust -parlance, `x` is said to ‘own’ the vector. This means that when `x` goes out of -scope, the vector’s memory will be de-allocated. This is done deterministically -by the Rust compiler, rather than through a mechanism such as a garbage -collector. In other words, in Rust, we don’t call functions like `malloc` and -`free` ourselves: the compiler statically determines when we need to allocate or -deallocate memory, and inserts those calls itself. To err is to be human, but -compilers never forget. - -Let’s add another line to our example: - -```rust -fn main() { - let mut x = vec!["Hello", "world"]; - - let y = &x[0]; -} -``` - -We’ve introduced another binding, `y`. In this case, `y` is a ‘reference’ to the -first element of the vector. Rust’s references are similar to pointers in other -languages, but with additional compile-time safety checks. References interact -with the ownership system by [‘borrowing’][borrowing] what they point to, rather -than owning it. The difference is, when the reference goes out of scope, it -won't deallocate the underlying memory. If it did, we’d de-allocate twice, which -is bad! - -[borrowing]: references-and-borrowing.html - -Let’s add a third line. It looks innocent enough, but causes a compiler error: - -```rust,ignore -fn main() { - let mut x = vec!["Hello", "world"]; - - let y = &x[0]; - - x.push("foo"); -} -``` - -`push` is a method on vectors that appends another element to the end of the -vector. When we try to compile this program, we get an error: - -```text -error: cannot borrow `x` as mutable because it is also borrowed as immutable - x.push("foo"); - ^ -note: previous borrow of `x` occurs here; the immutable borrow prevents -subsequent moves or mutable borrows of `x` until the borrow ends - let y = &x[0]; - ^ -note: previous borrow ends here -fn main() { - -} -^ -``` - -Whew! The Rust compiler gives quite detailed errors at times, and this is one -of those times. As the error explains, while we made our binding mutable, we -still can't call `push`. This is because we already have a reference to an -element of the vector, `y`. Mutating something while another reference exists -is dangerous, because we may invalidate the reference. In this specific case, -when we create the vector, we may have only allocated space for two elements. -Adding a third would mean allocating a new chunk of memory for all those elements, -copying the old values over, and updating the internal pointer to that memory. -That all works just fine. The problem is that `y` wouldn’t get updated, and so -we’d have a ‘dangling pointer’. That’s bad. Any use of `y` would be an error in -this case, and so the compiler has caught this for us. - -So how do we solve this problem? There are two approaches we can take. The first -is making a copy rather than using a reference: - -```rust -fn main() { - let mut x = vec!["Hello", "world"]; - - let y = x[0].clone(); - - x.push("foo"); -} -``` - -Rust has [move semantics][move] by default, so if we want to make a copy of some -data, we call the `clone()` method. In this example, `y` is no longer a reference -to the vector stored in `x`, but a copy of its first element, `"Hello"`. Now -that we don’t have a reference, our `push()` works just fine. - -[move]: ownership.html#move-semantics - -If we truly want a reference, we need the other option: ensure that our reference -goes out of scope before we try to do the mutation. That looks like this: - -```rust -fn main() { - let mut x = vec!["Hello", "world"]; - - { - let y = &x[0]; - } - - x.push("foo"); -} -``` - -We created an inner scope with an additional set of curly braces. `y` will go out of -scope before we call `push()`, and so we’re all good. - -This concept of ownership isn’t just good for preventing dangling pointers, but an -entire set of related problems, like iterator invalidation, concurrency, and more. diff --git a/src/doc/trpl/SUMMARY.md b/src/doc/trpl/SUMMARY.md index 2b5d1fa70aada..704bcf1587b8a 100644 --- a/src/doc/trpl/SUMMARY.md +++ b/src/doc/trpl/SUMMARY.md @@ -1,9 +1,6 @@ # Summary * [Getting Started](getting-started.md) - * [Installing Rust](installing-rust.md) - * [Hello, world!](hello-world.md) - * [Hello, Cargo!](hello-cargo.md) * [Learn Rust](learn-rust.md) * [Guessing Game](guessing-game.md) * [Dining Philosophers](dining-philosophers.md) diff --git a/src/doc/trpl/associated-constants.md b/src/doc/trpl/associated-constants.md index 7d51dd0aa5701..81f7ea104e48f 100644 --- a/src/doc/trpl/associated-constants.md +++ b/src/doc/trpl/associated-constants.md @@ -74,6 +74,6 @@ for a `struct` or an `enum` works fine too: struct Foo; impl Foo { - pub const FOO: u32 = 3; + const FOO: u32 = 3; } ``` diff --git a/src/doc/trpl/compiler-plugins.md b/src/doc/trpl/compiler-plugins.md index e1c9825111709..42dfaa1a8090a 100644 --- a/src/doc/trpl/compiler-plugins.md +++ b/src/doc/trpl/compiler-plugins.md @@ -46,7 +46,7 @@ extern crate rustc; use syntax::codemap::Span; use syntax::parse::token; -use syntax::ast::{TokenTree, TtToken}; +use syntax::ast::TokenTree; use syntax::ext::base::{ExtCtxt, MacResult, DummyResult, MacEager}; use syntax::ext::build::AstBuilder; // trait for expr_usize use rustc::plugin::Registry; @@ -61,7 +61,7 @@ fn expand_rn(cx: &mut ExtCtxt, sp: Span, args: &[TokenTree]) ("I", 1)]; let text = match args { - [TtToken(_, token::Ident(s, _))] => s.to_string(), + [TokenTree::Token(_, token::Ident(s, _))] => s.to_string(), _ => { cx.span_err(sp, "argument should be a single identifier"); return DummyResult::any(sp); diff --git a/src/doc/trpl/concurrency.md b/src/doc/trpl/concurrency.md index 7b3f13a3ed223..cc6cfc2f4a097 100644 --- a/src/doc/trpl/concurrency.md +++ b/src/doc/trpl/concurrency.md @@ -121,6 +121,7 @@ languages. It will not compile: ```ignore use std::thread; +use std::time::Duration; fn main() { let mut data = vec![1, 2, 3]; @@ -131,7 +132,7 @@ fn main() { }); } - thread::sleep_ms(50); + thread::sleep(Duration::from_millis(50)); } ``` @@ -165,6 +166,7 @@ indivisible operations which can't have data races. ```ignore use std::thread; use std::sync::Arc; +use std::time::Duration; fn main() { let mut data = Arc::new(vec![1, 2, 3]); @@ -176,7 +178,7 @@ fn main() { }); } - thread::sleep_ms(50); + thread::sleep(Duration::from_millis(50)); } ``` @@ -207,6 +209,7 @@ Here's the working version: ```rust use std::sync::{Arc, Mutex}; use std::thread; +use std::time::Duration; fn main() { let data = Arc::new(Mutex::new(vec![1, 2, 3])); @@ -219,7 +222,7 @@ fn main() { }); } - thread::sleep_ms(50); + thread::sleep(Duration::from_millis(50)); } ``` @@ -241,6 +244,7 @@ Let's examine the body of the thread more closely: ```rust # use std::sync::{Arc, Mutex}; # use std::thread; +# use std::time::Duration; # fn main() { # let data = Arc::new(Mutex::new(vec![1, 2, 3])); # for i in 0..3 { @@ -250,7 +254,7 @@ thread::spawn(move || { data[i] += 1; }); # } -# thread::sleep_ms(50); +# thread::sleep(Duration::from_millis(50)); # } ``` diff --git a/src/doc/trpl/dining-philosophers.md b/src/doc/trpl/dining-philosophers.md index e81ae4648ad43..50d758c3a108f 100644 --- a/src/doc/trpl/dining-philosophers.md +++ b/src/doc/trpl/dining-philosophers.md @@ -232,7 +232,7 @@ also called a ‘vector’, and it’s a growable array type. We then use a [`for`][for] loop to iterate through the vector, getting a reference to each philosopher in turn. -[for]: for-loops.html +[for]: loops.html#for In the body of the loop, we call `p.eat()`, which is defined above: @@ -264,6 +264,7 @@ eat. Here’s the next version: ```rust use std::thread; +use std::time::Duration; struct Philosopher { name: String, @@ -279,7 +280,7 @@ impl Philosopher { fn eat(&self) { println!("{} is eating.", self.name); - thread::sleep_ms(1000); + thread::sleep(Duration::from_millis(1000)); println!("{} is done eating.", self.name); } @@ -313,13 +314,13 @@ from the standard library, and so we need to `use` it. fn eat(&self) { println!("{} is eating.", self.name); - thread::sleep_ms(1000); + thread::sleep(Duration::from_millis(1000)); println!("{} is done eating.", self.name); } ``` -We now print out two messages, with a `sleep_ms()` in the middle. This will +We now print out two messages, with a `sleep` in the middle. This will simulate the time it takes a philosopher to eat. If you run this program, you should see each philosopher eat in turn: @@ -345,6 +346,7 @@ Here’s the next iteration: ```rust use std::thread; +use std::time::Duration; struct Philosopher { name: String, @@ -360,7 +362,7 @@ impl Philosopher { fn eat(&self) { println!("{} is eating.", self.name); - thread::sleep_ms(1000); + thread::sleep(Duration::from_millis(1000)); println!("{} is done eating.", self.name); } @@ -493,6 +495,7 @@ Let’s modify the program to use the `Table`: ```rust use std::thread; +use std::time::Duration; use std::sync::{Mutex, Arc}; struct Philosopher { @@ -512,12 +515,12 @@ impl Philosopher { fn eat(&self, table: &Table) { let _left = table.forks[self.left].lock().unwrap(); - thread::sleep_ms(150); + thread::sleep(Duration::from_millis(150)); let _right = table.forks[self.right].lock().unwrap(); println!("{} is eating.", self.name); - thread::sleep_ms(1000); + thread::sleep(Duration::from_millis(1000)); println!("{} is done eating.", self.name); } @@ -598,12 +601,12 @@ We now need to construct those `left` and `right` values, so we add them to ```rust,ignore fn eat(&self, table: &Table) { let _left = table.forks[self.left].lock().unwrap(); - thread::sleep_ms(150); + thread::sleep(Duration::from_millis(150)); let _right = table.forks[self.right].lock().unwrap(); println!("{} is eating.", self.name); - thread::sleep_ms(1000); + thread::sleep(Duration::from_millis(1000)); println!("{} is done eating.", self.name); } @@ -614,8 +617,8 @@ We have three new lines. We’ve added an argument, `table`. We access the the fork at that particular index. That gives us access to the `Mutex` at that index, and we call `lock()` on it. If the mutex is currently being accessed by someone else, we’ll block until it becomes available. We have also a call to -`thread::sleep_ms` between the moment first fork is picked and the moment the -second forked is picked, as the process of picking up the fork is not +`thread::sleep` between the moment the first fork is picked and the moment the +second forked is picked, as the process of picking up the fork is not immediate. The call to `lock()` might fail, and if it does, we want to crash. In this diff --git a/src/doc/trpl/documentation.md b/src/doc/trpl/documentation.md index e101d4bc0d4dc..80aed0d1ca7da 100644 --- a/src/doc/trpl/documentation.md +++ b/src/doc/trpl/documentation.md @@ -373,6 +373,36 @@ we can add the `#[macro_use]` attribute. Second, we’ll need to add our own `main()` as well. Finally, a judicious use of `#` to comment out those two things, so they don’t show up in the output. +Another case where the use of `#` is handy is when you want to ignore +error handling. Lets say you want the following, + +```rust,ignore +/// use std::io; +/// let mut input = String::new(); +/// try!(io::stdin().read_line(&mut input)); +``` + +The problem is that `try!` returns a `Result` and test functions +don't return anything so this will give a mismatched types error. + +```rust,ignore +/// A doc test using try! +/// +/// ``` +/// use std::io; +/// # fn foo() -> io::Result<()> { +/// let mut input = String::new(); +/// try!(io::stdin().read_line(&mut input)); +/// # Ok(()) +/// # } +/// ``` +# fn foo() {} +``` + +You can get around this by wrapping the code in a function. This catches +and swallows the `Result` when running tests on the docs. This +pattern appears regularly in the standard library. + ### Running documentation tests To run the tests, either: @@ -590,6 +620,18 @@ You can control a few aspects of the HTML that `rustdoc` generates through the This sets a few different options, with a logo, favicon, and a root URL. +### Configuring documentation tests + +You can also configure the way that `rustdoc` tests your documentation examples +through the `#![doc(test(..))]` attribute. + +```rust +#![doc(test(attr(allow(unused_variables), deny(warnings))))] +``` + +This allows unused variables within the examples, but will fail the test for any +other lint warning thrown. + ## Generation options `rustdoc` also contains a few other options on the command line, for further customization: diff --git a/src/doc/trpl/error-handling.md b/src/doc/trpl/error-handling.md index b74aaef927d88..52a4e7324ee56 100644 --- a/src/doc/trpl/error-handling.md +++ b/src/doc/trpl/error-handling.md @@ -1137,11 +1137,7 @@ impl error::Error for CliError { // implementations. match *self { CliError::Io(ref err) => err.description(), - // Normally we can just write `err.description()`, but the error - // type has a concrete method called `description`, which conflicts - // with the trait method. For now, we must explicitly call - // `description` through the `Error` trait. - CliError::Parse(ref err) => error::Error::description(err), + CliError::Parse(ref err) => err.description(), } } @@ -1605,14 +1601,11 @@ arguments. ## Writing the logic -We're all different in how we write code, but error handling is -usually the last thing we want to think about. This isn't very good -practice for good design, but it can be useful for rapidly -prototyping. In our case, because Rust forces us to be explicit about -error handling, it will also make it obvious what parts of our program -can cause errors. Why? Because Rust will make us call `unwrap`! This -can give us a nice bird's eye view of how we need to approach error -handling. +We all write code differently, but error handling is usually the last thing we +want to think about. This isn't great for the overall design of a program, but +it can be useful for rapid prototyping. Because Rust forces us to be explicit +about error handling (by making us call `unwrap`), it is easy to see which +parts of our program can cause errors. In this case study, the logic is really simple. All we need to do is parse the CSV data given to us and print out a field in matching rows. Let's do it. (Make @@ -1845,6 +1838,22 @@ impl<'a, 'b> From<&'b str> for Box impl From for Box ``` +Since `search` now returns a `Result`, `main` should use case analysis +when calling `search`: + +```rust,ignore +... +match search(&data_file, &city) { + Ok(pops) => { + for pop in pops { + println!("{}, {}: {:?}", pop.city, pop.country, pop.count); + } + } + Err(err) => println!("{}", err) +} +... +``` + Now that we've seen how to do proper error handling with `Box`, let's try a different approach with our own custom error type. But first, let's take a quick break from error handling and add support for reading from `stdin`. diff --git a/src/doc/trpl/getting-started.md b/src/doc/trpl/getting-started.md index 549f8c3ca5724..5b1040dd05ee1 100644 --- a/src/doc/trpl/getting-started.md +++ b/src/doc/trpl/getting-started.md @@ -3,3 +3,608 @@ This first section of the book will get us going with Rust and its tooling. First, we’ll install Rust. Then, the classic ‘Hello World’ program. Finally, we’ll talk about Cargo, Rust’s build system and package manager. + +# Installing Rust + +The first step to using Rust is to install it. Generally speaking, you’ll need +an Internet connection to run the commands in this chapter, as we’ll be +downloading Rust from the internet. + +We’ll be showing off a number of commands using a terminal, and those lines all +start with `$`. We don't need to type in the `$`s, they are there to indicate +the start of each command. We’ll see many tutorials and examples around the web +that follow this convention: `$` for commands run as our regular user, and `#` +for commands we should be running as an administrator. + +## Platform support + +The Rust compiler runs on, and compiles to, a great number of platforms, though +not all platforms are equally supported. Rust's support levels are organized +into three tiers, each with a different set of guarantees. + +Platforms are identified by their "target triple" which is the string to inform +the compiler what kind of output should be produced. The columns below indicate +whether the corresponding component works on the specified platform. + +### Tier 1 + +Tier 1 platforms can be thought of as "guaranteed to build and work". +Specifically they will each satisfy the following requirements: + +* Automated testing is set up to run tests for the platform. +* Landing changes to the `rust-lang/rust` repository's master branch is gated on + tests passing. +* Official release artifacts are provided for the platform. +* Documentation for how to use and how to build the platform is available. + +| Target | std |rustc|cargo| notes | +|-------------------------------|-----|-----|-----|----------------------------| +| `x86_64-pc-windows-msvc` | ✓ | ✓ | ✓ | 64-bit MSVC (Windows 7+) | +| `i686-pc-windows-gnu` | ✓ | ✓ | ✓ | 32-bit MinGW (Windows 7+) | +| `x86_64-pc-windows-gnu` | ✓ | ✓ | ✓ | 64-bit MinGW (Windows 7+) | +| `i686-apple-darwin` | ✓ | ✓ | ✓ | 32-bit OSX (10.7+, Lion+) | +| `x86_64-apple-darwin` | ✓ | ✓ | ✓ | 64-bit OSX (10.7+, Lion+) | +| `i686-unknown-linux-gnu` | ✓ | ✓ | ✓ | 32-bit Linux (2.6.18+) | +| `x86_64-unknown-linux-gnu` | ✓ | ✓ | ✓ | 64-bit Linux (2.6.18+) | + +### Tier 2 + +Tier 2 platforms can be thought of as "guaranteed to build". Automated tests +are not run so it's not guaranteed to produce a working build, but platforms +often work to quite a good degree and patches are always welcome! Specifically, +these platforms are required to have each of the following: + +* Automated building is set up, but may not be running tests. +* Landing changes to the `rust-lang/rust` repository's master branch is gated on + platforms **building**. Note that this means for some platforms only the + standard library is compiled, but for others the full bootstrap is run. +* Official release artifacts are provided for the platform. + +| Target | std |rustc|cargo| notes | +|-------------------------------|-----|-----|-----|----------------------------| +| `i686-pc-windows-msvc` | ✓ | ✓ | ✓ | 32-bit MSVC (Windows 7+) | + +### Tier 3 + +Tier 3 platforms are those which Rust has support for, but landing changes is +not gated on the platform either building or passing tests. Working builds for +these platforms may be spotty as their reliability is often defined in terms of +community contributions. Additionally, release artifacts and installers are not +provided, but there may be community infrastructure producing these in +unofficial locations. + +| Target | std |rustc|cargo| notes | +|-------------------------------|-----|-----|-----|----------------------------| +| `x86_64-unknown-linux-musl` | ✓ | | | 64-bit Linux with MUSL | +| `arm-linux-androideabi` | ✓ | | | ARM Android | +| `i686-linux-android` | ✓ | | | 32-bit x86 Android | +| `aarch64-linux-android` | ✓ | | | ARM64 Android | +| `arm-unknown-linux-gnueabi` | ✓ | ✓ | | ARM Linux (2.6.18+) | +| `arm-unknown-linux-gnueabihf` | ✓ | ✓ | | ARM Linux (2.6.18+) | +| `aarch64-unknown-linux-gnu` | ✓ | | | ARM64 Linux (2.6.18+) | +| `mips-unknown-linux-gnu` | ✓ | | | MIPS Linux (2.6.18+) | +| `mipsel-unknown-linux-gnu` | ✓ | | | MIPS (LE) Linux (2.6.18+) | +| `powerpc-unknown-linux-gnu` | ✓ | | | PowerPC Linux (2.6.18+) | +| `i386-apple-ios` | ✓ | | | 32-bit x86 iOS | +| `x86_64-apple-ios` | ✓ | | | 64-bit x86 iOS | +| `armv7-apple-ios` | ✓ | | | ARM iOS | +| `armv7s-apple-ios` | ✓ | | | ARM iOS | +| `aarch64-apple-ios` | ✓ | | | ARM64 iOS | +| `i686-unknown-freebsd` | ✓ | ✓ | | 32-bit FreeBSD | +| `x86_64-unknown-freebsd` | ✓ | ✓ | | 64-bit FreeBSD | +| `x86_64-unknown-openbsd` | ✓ | ✓ | | 64-bit OpenBSD | +| `x86_64-unknown-netbsd` | ✓ | ✓ | | 64-bit NetBSD | +| `x86_64-unknown-bitrig` | ✓ | ✓ | | 64-bit Bitrig | +| `x86_64-unknown-dragonfly` | ✓ | ✓ | | 64-bit DragonFlyBSD | +| `x86_64-rumprun-netbsd` | ✓ | | | 64-bit NetBSD Rump Kernel | +| `i686-pc-windows-msvc` (XP) | ✓ | | | Windows XP support | +| `x86_64-pc-windows-msvc` (XP) | ✓ | | | Windows XP support | + +Note that this table can be expanded over time, this isn't the exhaustive set of +tier 3 platforms that will ever be! + +## Installing on Linux or Mac + +If we're on Linux or a Mac, all we need to do is open a terminal and type this: + +```bash +$ curl -sSf https://static.rust-lang.org/rustup.sh | sh +``` + +This will download a script, and stat the installation. If it all goes well, +you’ll see this appear: + +```text +Welcome to Rust. + +This script will download the Rust compiler and its package manager, Cargo, and +install them to /usr/local. You may install elsewhere by running this script +with the --prefix= option. + +The installer will run under ‘sudo’ and may ask you for your password. If you do +not want the script to run ‘sudo’ then pass it the --disable-sudo flag. + +You may uninstall later by running /usr/local/lib/rustlib/uninstall.sh, +or by running this script again with the --uninstall flag. + +Continue? (y/N) +``` + +From here, press `y` for ‘yes’, and then follow the rest of the prompts. + +## Installing on Windows + +If you're on Windows, please download the appropriate [installer][install-page]. + +[install-page]: https://www.rust-lang.org/install.html + +## Uninstalling + +Uninstalling Rust is as easy as installing it. On Linux or Mac, just run +the uninstall script: + +```bash +$ sudo /usr/local/lib/rustlib/uninstall.sh +``` + +If we used the Windows installer, we can re-run the `.msi` and it will give us +an uninstall option. + +## Troubleshooting + +If we've got Rust installed, we can open up a shell, and type this: + +```bash +$ rustc --version +``` + +You should see the version number, commit hash, and commit date. + +If you do, Rust has been installed successfully! Congrats! + +If you don't and you're on Windows, check that Rust is in your %PATH% system +variable. If it isn't, run the installer again, select "Change" on the "Change, +repair, or remove installation" page and ensure "Add to PATH" is installed on +the local hard drive. + +If not, there are a number of places where we can get help. The easiest is +[the #rust IRC channel on irc.mozilla.org][irc], which we can access through +[Mibbit][mibbit]. Click that link, and we'll be chatting with other Rustaceans +(a silly nickname we call ourselves) who can help us out. Other great resources +include [the user’s forum][users], and [Stack Overflow][stackoverflow]. + +[irc]: irc://irc.mozilla.org/#rust +[mibbit]: http://chat.mibbit.com/?server=irc.mozilla.org&channel=%23rust +[users]: https://users.rust-lang.org/ +[stackoverflow]: http://stackoverflow.com/questions/tagged/rust + +This installer also installs a copy of the documentation locally, so we can +read it offline. On UNIX systems, `/usr/local/share/doc/rust` is the location. +On Windows, it's in a `share/doc` directory, inside the directory to which Rust +was installed. + +# Hello, world! + +Now that you have Rust installed, we'll help you write your first Rust program. +It's traditional when learning a new language to write a little program to +print the text “Hello, world!” to the screen, and in this section, we'll follow +that tradition. + +The nice thing about starting with such a simple program is that you can +quickly verify that your compiler is installed, and that it's working properly. +Printing information to the screen is also just a pretty common thing to do, so +practicing it early on is good. + +> Note: This book assumes basic familiarity with the command line. Rust itself +> makes no specific demands about your editing, tooling, or where your code +> lives, so if you prefer an IDE to the command line, that's an option. You may +> want to check out [SolidOak], which was built specifically with Rust in mind. +> There are a number of extensions in development by the community, and the +> Rust team ships plugins for [various editors]. Configuring your editor or +> IDE is out of the scope of this tutorial, so check the documentation for your +> specific setup. + +[SolidOak]: https://github.com/oakes/SolidOak +[various editors]: https://github.com/rust-lang/rust/blob/master/src/etc/CONFIGS.md + +## Creating a Project File + +First, make a file to put your Rust code in. Rust doesn't care where your code +lives, but for this book, I suggest making a *projects* directory in your home +directory, and keeping all your projects there. Open a terminal and enter the +following commands to make a directory for this particular project: + +```bash +$ mkdir ~/projects +$ cd ~/projects +$ mkdir hello_world +$ cd hello_world +``` + +> Note: If you’re on Windows and not using PowerShell, the `~` may not work. +> Consult the documentation for your shell for more details. + +## Writing and Running a Rust Program + +Next, make a new source file and call it *main.rs*. Rust files always end +in a *.rs* extension. If you’re using more than one word in your filename, use +an underscore to separate them; for example, you'd use *hello_world.rs* rather +than *helloworld.rs*. + +Now open the *main.rs* file you just created, and type the following code: + +```rust +fn main() { + println!("Hello, world!"); +} +``` + +Save the file, and go back to your terminal window. On Linux or OSX, enter the +following commands: + +```bash +$ rustc main.rs +$ ./main +Hello, world! +``` + +In Windows, just replace `main` with `main.exe`. Regardless of your operating +system, you should see the string `Hello, world!` print to the terminal. If you +did, then congratulations! You've officially written a Rust program. That makes +you a Rust programmer! Welcome. + +## Anatomy of a Rust Program + +Now, let’s go over what just happened in your "Hello, world!" program in +detail. Here's the first piece of the puzzle: + +```rust +fn main() { + +} +``` + +These lines define a *function* in Rust. The `main` function is special: it's +the beginning of every Rust program. The first line says, “I’m declaring a +function named `main` that takes no arguments and returns nothing.” If there +were arguments, they would go inside the parentheses (`(` and `)`), and because +we aren’t returning anything from this function, we can omit the return type +entirely. + +Also note that the function body is wrapped in curly braces (`{` and `}`). Rust +requires these around all function bodies. It's considered good style to put +the opening curly brace on the same line as the function declaration, with one +space in between. + +Inside the `main()` function: + +```rust + println!("Hello, world!"); +``` + +This line does all of the work in this little program: it prints text to the +screen. There are a number of details that are important here. The first is +that it’s indented with four spaces, not tabs. + +The second important part is the `println!()` line. This is calling a Rust +*[macro]*, which is how metaprogramming is done in Rust. If it were calling a +function instead, it would look like this: `println()` (without the !). We'll +discuss Rust macros in more detail later, but for now you just need to +know that when you see a `!` that means that you’re calling a macro instead of +a normal function. + + +[macro]: macros.html + +Next is `"Hello, world!"` which is a *string*. Strings are a surprisingly +complicated topic in a systems programming language, and this is a *[statically +allocated]* string. We pass this string as an argument to `println!`, which +prints the string to the screen. Easy enough! + +[statically allocated]: the-stack-and-the-heap.html + +The line ends with a semicolon (`;`). Rust is an *[expression oriented]* +language, which means that most things are expressions, rather than statements. +The `;` indicates that this expression is over, and the next one is ready to +begin. Most lines of Rust code end with a `;`. + +[expression-oriented language]: glossary.html#expression-oriented-language + +## Compiling and Running Are Separate Steps + +In "Writing and Running a Rust Program", we showed you how to run a newly +created program. We'll break that process down and examine each step now. + +Before running a Rust program, you have to compile it. You can use the Rust +compiler by entering the `rustc` command and passing it the name of your source +file, like this: + +```bash +$ rustc main.rs +``` + +If you come from a C or C++ background, you'll notice that this is similar to +`gcc` or `clang`. After compiling successfully, Rust should output a binary +executable, which you can see on Linux or OSX by entering the `ls` command in +your shell as follows: + +```bash +$ ls +main main.rs +``` + +On Windows, you'd enter: + +```bash +$ dir +main.exe main.rs +``` + +This shows we have two files: the source code, with an `.rs` extension, and the +executable (`main.exe` on Windows, `main` everywhere else). All that's left to +do from here is run the `main` or `main.exe` file, like this: + +```bash +$ ./main # or main.exe on Windows +``` + +If *main.rs* were your "Hello, world!" program, this would print `Hello, +world!` to your terminal. + +If you come from a dynamic language like Ruby, Python, or JavaScript, you may +not be used to compiling and running a program being separate steps. Rust is an +*ahead-of-time compiled* language, which means that you can compile a program, +give it to someone else, and they can run it even without Rust installed. If +you give someone a `.rb` or `.py` or `.js` file, on the other hand, they need +to have a Ruby, Python, or JavaScript implementation installed (respectively), +but you only need one command to both compile and run your program. Everything +is a tradeoff in language design. + +Just compiling with `rustc` is fine for simple programs, but as your project +grows, you'll want to be able to manage all of the options your project has, +and make it easy to share your code with other people and projects. Next, I'll +introduce you to a tool called Cargo, which will help you write real-world Rust +programs. + +# Hello, Cargo! + +Cargo is Rust’s build system and package manager, and Rustaceans use Cargo to +manage their Rust projects. Cargo manages three things: building your code, +downloading the libraries your code depends on, and building those libraries. +We call libraries your code needs ‘dependencies’ since your code depends on +them. + +The simplest Rust programs don’t have any dependencies, so right now, you'd +only use the first part of its functionality. As you write more complex Rust +programs, you’ll want to add dependencies, and if you start off using Cargo, +that will be a lot easier to do. + +As the vast, vast majority of Rust projects use Cargo, we will assume that +you’re using it for the rest of the book. Cargo comes installed with Rust +itself, if you used the official installers. If you installed Rust through some +other means, you can check if you have Cargo installed by typing: + +```bash +$ cargo --version +``` + +Into a terminal. If you see a version number, great! If you see an error like +‘`command not found`’, then you should look at the documentation for the system +in which you installed Rust, to determine if Cargo is separate. + +## Converting to Cargo + +Let’s convert the Hello World program to Cargo. To Cargo-fy a project, you need +to do three things: + +1. Put your source file in the right directory. +2. Get rid of the old executable (`main.exe` on Windows, `main` everywhere else) + and make a new one. +3. Make a Cargo configuration file. + +Let's get started! + +### Creating a new Executable and Source Directory + +First, go back to your terminal, move to your *hello_world* directory, and +enter the following commands: + +```bash +$ mkdir src +$ mv main.rs src/main.rs +$ rm main # or 'del main.exe' on Windows +``` + +Cargo expects your source files to live inside a *src* directory, so do that +first. This leaves the top-level project directory (in this case, +*hello_world*) for READMEs, license information, and anything else not related +to your code. In this way, using Cargo helps you keep your projects nice and +tidy. There's a place for everything, and everything is in its place. + +Now, copy *main.rs* to the *src* directory, and delete the compiled file you +created with `rustc`. As usual, replace `main` with `main.exe` if you're on +Windows. + +This example retains `main.rs` as the source filename because it's creating an +executable. If you wanted to make a library instead, you'd name the file +`lib.rs`. This convention is used by Cargo to successfully compile your +projects, but it can be overridden if you wish. + +### Creating a Configuration File + +Next, create a new file inside your *hello_world* directory, and call it +`Cargo.toml`. + +Make sure to capitalize the `C` in `Cargo.toml`, or Cargo won't know what to do +with the configuration file. + +This file is in the *[TOML]* (Tom's Obvious, Minimal Language) format. TOML is +similar to INI, but has some extra goodies, and is used as Cargo’s +configuration format. + +[TOML]: https://github.com/toml-lang/toml + +Inside this file, type the following information: + +```toml +[package] + +name = "hello_world" +version = "0.0.1" +authors = [ "Your name " ] +``` + +The first line, `[package]`, indicates that the following statements are +configuring a package. As we add more information to this file, we’ll add other +sections, but for now, we just have the package configuration. + +The other three lines set the three bits of configuration that Cargo needs to +know to compile your program: its name, what version it is, and who wrote it. + +Once you've added this information to the *Cargo.toml* file, save it to finish +creating the configuration file. + +## Building and Running a Cargo Project + +With your *Cargo.toml* file in place in your project's root directory, you +should be ready to build and run your Hello World program! To do so, enter the +following commands: + +```bash +$ cargo build + Compiling hello_world v0.0.1 (file:///home/yourname/projects/hello_world) +$ ./target/debug/hello_world +Hello, world! +``` + +Bam! If all goes well, `Hello, world!` should print to the terminal once more. + +You just built a project with `cargo build` and ran it with +`./target/debug/hello_world`, but you can actually do both in one step with +`cargo run` as follows: + +```bash +$ cargo run + Running `target/debug/hello_world` +Hello, world! +``` + +Notice that this example didn’t re-build the project. Cargo figured out that +the file hasn’t changed, and so it just ran the binary. If you'd modified your +source code, Cargo would have rebuilt the project before running it, and you +would have seen something like this: + +```bash +$ cargo run + Compiling hello_world v0.0.1 (file:///home/yourname/projects/hello_world) + Running `target/debug/hello_world` +Hello, world! +``` + +Cargo checks to see if any of your project’s files have been modified, and only +rebuilds your project if they’ve changed since the last time you built it. + +With simple projects, Cargo doesn't bring a whole lot over just using `rustc`, +but it will become useful in future. With complex projects composed of multiple +crates, it’s much easier to let Cargo coordinate the build. With Cargo, you can +just run `cargo build`, and it should work the right way. + +## Building for Release + +When your project is finally ready for release, you can use `cargo build +--release` to compile your project with optimizations. These optimizations make +your Rust code run faster, but turning them on makes your program take longer +to compile. This is why there are two different profiles, one for development, +and one for building the final program you’ll give to a user. + +Running this command also causes Cargo to create a new file called +*Cargo.lock*, which looks like this: + +```toml +[root] +name = "hello_world" +version = "0.0.1" +``` + +Cargo uses the *Cargo.lock* file to keep track of dependencies in your +application. This is the Hello World project's *Cargo.lock* file. This project +doesn't have dependencies, so the file is a bit sparse. Realistically, you +won't ever need to touch this file yourself; just let Cargo handle it. + +That’s it! If you've been following along, you should have successfully built +`hello_world` with Cargo. + +Even though the project is simple, it now uses much of the real tooling you’ll +use for the rest of your Rust career. In fact, you can expect to start +virtually all Rust projects with some variation on the following commands: + +```bash +$ git clone someurl.com/foo +$ cd foo +$ cargo build +``` + +## Making A New Cargo Project the Easy Way + +You don’t have to go through that previous process every time you want to start +a new project! Cargo can quickly make a bare-bones project directory that you +can start developing in right away. + +To start a new project with Cargo, enter `cargo new` at the command line: + +```bash +$ cargo new hello_world --bin +``` + +This command passes `--bin` because the goal is to get straight to making an +executable application, as opposed to a library. Executables are often called +*binaries* (as in `/usr/bin`, if you’re on a Unix system). + +Cargo has generated two files and one directory for us: a `Cargo.toml` and a +*src* directory with a *main.rs* file inside. These should look familliar, +they’re exactly what we created by hand, above. + +This output is all you need to get started. First, open `Cargo.toml`. It should +look something like this: + +```toml +[package] + +name = "hello_world" +version = "0.1.0" +authors = ["Your Name "] +``` + +Cargo has populated *Cargo.toml* with reasonable defaults based on the arguments +you gave it and your `git` global configuration. You may notice that Cargo has +also initialized the `hello_world` directory as a `git` repository. + +Here’s what should be in `src/main.rs`: + +```rust +fn main() { + println!("Hello, world!"); +} +``` + +Cargo has generated a "Hello World!" for you, and you’re ready to start coding! + +> Note: If you want to look at Cargo in more detail, check out the official [Cargo +guide], which covers all of its features. + +[Cargo guide]: http://doc.crates.io/guide.html + +# Closing Thoughts + +This chapter covered the basics that will serve you well through the rest of +this book, and the rest of your time with Rust. Now that you’ve got the tools +down, we'll cover more about the Rust language itself. + +You have two options: Dive into a project with ‘[Learn Rust][learnrust]’, or +start from the bottom and work your way up with ‘[Syntax and +Semantics][syntax]’. More experienced systems programmers will probably prefer +‘Learn Rust’, while those from dynamic backgrounds may enjoy either. Different +people learn differently! Choose whatever’s right for you. + +[learnrust]: learn-rust.html +[syntax]: syntax-and-semantics.html diff --git a/src/doc/trpl/guessing-game.md b/src/doc/trpl/guessing-game.md index db484a28cb02c..6a513fb2c5963 100644 --- a/src/doc/trpl/guessing-game.md +++ b/src/doc/trpl/guessing-game.md @@ -83,7 +83,6 @@ fn main() { let mut guess = String::new(); io::stdin().read_line(&mut guess) - .ok() .expect("Failed to read line"); println!("You guessed: {}", guess); @@ -189,7 +188,6 @@ Let’s move forward: ```rust,ignore io::stdin().read_line(&mut guess) - .ok() .expect("Failed to read line"); ``` @@ -245,7 +243,6 @@ a single line of text, it’s only the first part of the single logical line of code: ```rust,ignore - .ok() .expect("Failed to read line"); ``` @@ -254,33 +251,27 @@ and other whitespace. This helps you split up long lines. We _could_ have done: ```rust,ignore - io::stdin().read_line(&mut guess).ok().expect("failed to read line"); + io::stdin().read_line(&mut guess).expect("failed to read line"); ``` -But that gets hard to read. So we’ve split it up, three lines for three -method calls. We already talked about `read_line()`, but what about `ok()` -and `expect()`? Well, we already mentioned that `read_line()` puts what -the user types into the `&mut String` we pass it. But it also returns -a value: in this case, an [`io::Result`][ioresult]. Rust has a number of -types named `Result` in its standard library: a generic [`Result`][result], -and then specific versions for sub-libraries, like `io::Result`. +But that gets hard to read. So we’ve split it up, three lines for three method +calls. We already talked about `read_line()`, but what about `expect()`? Well, +we already mentioned that `read_line()` puts what the user types into the `&mut +String` we pass it. But it also returns a value: in this case, an +[`io::Result`][ioresult]. Rust has a number of types named `Result` in its +standard library: a generic [`Result`][result], and then specific versions for +sub-libraries, like `io::Result`. [ioresult]: ../std/io/type.Result.html [result]: ../std/result/enum.Result.html The purpose of these `Result` types is to encode error handling information. Values of the `Result` type, like any type, have methods defined on them. In -this case, `io::Result` has an `ok()` method, which says ‘we want to assume -this value is a successful one. If not, just throw away the error -information’. Why throw it away? Well, for a basic program, we just want to -print a generic error, as basically any issue means we can’t continue. The -[`ok()` method][ok] returns a value which has another method defined on it: -`expect()`. The [`expect()` method][expect] takes a value it’s called on, and -if it isn’t a successful one, [`panic!`][panic]s with a message you -passed it. A `panic!` like this will cause our program to crash, displaying -the message. - -[ok]: ../std/result/enum.Result.html#method.ok +this case, `io::Result` has an [`expect()` method][expect] that takes a value +it’s called on, and if it isn’t a successful one, [`panic!`][panic]s with a +message you passed it. A `panic!` like this will cause our program to crash, +displaying the message. + [expect]: ../std/option/enum.Option.html#method.expect [panic]: error-handling.html @@ -468,7 +459,6 @@ fn main() { let mut guess = String::new(); io::stdin().read_line(&mut guess) - .ok() .expect("failed to read line"); println!("You guessed: {}", guess); @@ -557,7 +547,6 @@ fn main() { let mut guess = String::new(); io::stdin().read_line(&mut guess) - .ok() .expect("failed to read line"); println!("You guessed: {}", guess); @@ -668,11 +657,9 @@ fn main() { let mut guess = String::new(); io::stdin().read_line(&mut guess) - .ok() .expect("failed to read line"); let guess: u32 = guess.trim().parse() - .ok() .expect("Please type a number!"); println!("You guessed: {}", guess); @@ -689,7 +676,6 @@ The new three lines: ```rust,ignore let guess: u32 = guess.trim().parse() - .ok() .expect("Please type a number!"); ``` @@ -706,27 +692,26 @@ We bind `guess` to an expression that looks like something we wrote earlier: guess.trim().parse() ``` -Followed by an `ok().expect()` invocation. Here, `guess` refers to the old -`guess`, the one that was a `String` with our input in it. The `trim()` -method on `String`s will eliminate any white space at the beginning and end of -our string. This is important, as we had to press the ‘return’ key to satisfy -`read_line()`. This means that if we type `5` and hit return, `guess` looks -like this: `5\n`. The `\n` represents ‘newline’, the enter key. `trim()` gets -rid of this, leaving our string with just the `5`. The [`parse()` method on -strings][parse] parses a string into some kind of number. Since it can parse a -variety of numbers, we need to give Rust a hint as to the exact type of number -we want. Hence, `let guess: u32`. The colon (`:`) after `guess` tells Rust -we’re going to annotate its type. `u32` is an unsigned, thirty-two bit -integer. Rust has [a number of built-in number types][number], but we’ve -chosen `u32`. It’s a good default choice for a small positive number. +Here, `guess` refers to the old `guess`, the one that was a `String` with our +input in it. The `trim()` method on `String`s will eliminate any white space at +the beginning and end of our string. This is important, as we had to press the +‘return’ key to satisfy `read_line()`. This means that if we type `5` and hit +return, `guess` looks like this: `5\n`. The `\n` represents ‘newline’, the +enter key. `trim()` gets rid of this, leaving our string with just the `5`. The +[`parse()` method on strings][parse] parses a string into some kind of number. +Since it can parse a variety of numbers, we need to give Rust a hint as to the +exact type of number we want. Hence, `let guess: u32`. The colon (`:`) after +`guess` tells Rust we’re going to annotate its type. `u32` is an unsigned, +thirty-two bit integer. Rust has [a number of built-in number types][number], +but we’ve chosen `u32`. It’s a good default choice for a small positive number. [parse]: ../std/primitive.str.html#method.parse [number]: primitive-types.html#numeric-types Just like `read_line()`, our call to `parse()` could cause an error. What if our string contained `A👍%`? There’d be no way to convert that to a number. As -such, we’ll do the same thing we did with `read_line()`: use the `ok()` and -`expect()` methods to crash if there’s an error. +such, we’ll do the same thing we did with `read_line()`: use the `expect()` +method to crash if there’s an error. Let’s try our program out! @@ -773,11 +758,9 @@ fn main() { let mut guess = String::new(); io::stdin().read_line(&mut guess) - .ok() .expect("failed to read line"); let guess: u32 = guess.trim().parse() - .ok() .expect("Please type a number!"); println!("You guessed: {}", guess); @@ -841,11 +824,9 @@ fn main() { let mut guess = String::new(); io::stdin().read_line(&mut guess) - .ok() .expect("failed to read line"); let guess: u32 = guess.trim().parse() - .ok() .expect("Please type a number!"); println!("You guessed: {}", guess); @@ -888,7 +869,6 @@ fn main() { let mut guess = String::new(); io::stdin().read_line(&mut guess) - .ok() .expect("failed to read line"); let guess: u32 = match guess.trim().parse() { @@ -920,7 +900,6 @@ let guess: u32 = match guess.trim().parse() { ``` This is how you generally move from ‘crash on error’ to ‘actually handle the -error’, by switching from `ok().expect()` to a `match` statement. The `Result` returned by `parse()` is an `enum` just like `Ordering`, but in this case, each variant has some data associated with it: `Ok` is a success, and `Err` is a failure. Each contains more information: the successfully parsed integer, or an @@ -977,7 +956,6 @@ fn main() { let mut guess = String::new(); io::stdin().read_line(&mut guess) - .ok() .expect("failed to read line"); let guess: u32 = match guess.trim().parse() { diff --git a/src/doc/trpl/hello-cargo.md b/src/doc/trpl/hello-cargo.md deleted file mode 100644 index 97bc4575f81f7..0000000000000 --- a/src/doc/trpl/hello-cargo.md +++ /dev/null @@ -1,210 +0,0 @@ -% Hello, Cargo! - -[Cargo][cratesio] is a tool that Rustaceans use to help manage their Rust -projects. Cargo is currently in a pre-1.0 state, and so it is still a work in -progress. However, it is already good enough to use for many Rust projects, and -so it is assumed that Rust projects will use Cargo from the beginning. - -[cratesio]: http://doc.crates.io - -Cargo manages three things: building our code, downloading the dependencies our -code needs, and building those dependencies. At first, our program doesn’t have -any dependencies, so we’ll only be using the first part of its functionality. -Eventually, we’ll add more. Since we started off by using Cargo, it'll be easy -to add later. - -If you installed Rust via the official installers you will also have Cargo. If -you installed Rust some other way, you may want to -[check the Cargo README][cargoreadme] for specific instructions about installing -it. - -[cargoreadme]: https://github.com/rust-lang/cargo#installing-cargo-from-nightlies - -## Converting to Cargo - -Let’s convert Hello World to Cargo. - -To Cargo-ify our project, we need to do three things: Make a `Cargo.toml` -configuration file, put our source file in the right place, and get rid of the -old executable (`main.exe` on Windows, `main` everywhere else). Let's do that part first: - -```bash -$ mkdir src -$ mv main.rs src/main.rs -$ rm main # or 'del main.exe' on Windows -``` - -> Note: since we're creating an executable, we retain `main.rs` as the source -> filename. If we want to make a library instead, we should use `lib.rs`. This -> convention is used by Cargo to successfully compile our projects, but it can -> be overridden if we wish. Custom file locations for the entry point can be -> specified with a [`[lib]` or `[[bin]]`][crates-custom] key in the TOML file. - -[crates-custom]: http://doc.crates.io/manifest.html#configuring-a-target - -Cargo expects our source files to live inside a `src` directory. That leaves the -top level for other things, like READMEs, license information, and anything not -related to our code. Cargo helps us keep our projects nice and tidy. A place for -everything, and everything in its place. - -Next, our configuration file: - -```bash -$ editor Cargo.toml # or 'notepad Cargo.toml' on Windows -``` - -Make sure to get this name right: we need the capital `C`! - -Put this inside: - -```toml -[package] - -name = "hello_world" -version = "0.0.1" -authors = [ "Your name " ] -``` - -This file is in the [TOML][toml] format. TOML is similar to INI, but has some -extra goodies. According to the TOML docs, - -> TOML aims to be a minimal configuration file format that's easy to read due -> to obvious semantics. TOML is designed to map unambiguously to a hash table. -> TOML should be easy to parse into data structures in a wide variety of -> languages. - -[toml]: https://github.com/toml-lang/toml - -Once we have this file in place in our project's root directory, we should be -ready to build! To do so, run: - -```bash -$ cargo build - Compiling hello_world v0.0.1 (file:///home/yourname/projects/hello_world) -$ ./target/debug/hello_world -Hello, world! -``` - -Bam! We built our project with `cargo build`, and ran it with -`./target/debug/hello_world`. We can do both in one step with `cargo run`: - -```bash -$ cargo run - Running `target/debug/hello_world` -Hello, world! -``` - -Notice that we didn’t re-build the project this time. Cargo figured out that -we hadn’t changed the source file, and so it just ran the binary. If we had -made a modification, we would have seen it do both: - -```bash -$ cargo run - Compiling hello_world v0.0.1 (file:///home/yourname/projects/hello_world) - Running `target/debug/hello_world` -Hello, world! -``` - -This hasn’t bought us a whole lot over our simple use of `rustc`, but think -about the future: when our project gets more complex, we need to do more -things to get all of the parts to properly compile. With Cargo, as our project -grows, we can just run `cargo build`, and it’ll work the right way. - -When our project is finally ready for release, we can use `cargo build ---release` to compile our project with optimizations. - -You'll also notice that Cargo has created a new file: `Cargo.lock`. - -```toml -[root] -name = "hello_world" -version = "0.0.1" -``` - -The `Cargo.lock` file is used by Cargo to keep track of dependencies in our -application. Right now, we don’t have any, so it’s a bit sparse. We won't ever -need to touch this file ourselves, just let Cargo handle it. - -That’s it! We’ve successfully built `hello_world` with Cargo. Even though our -program is simple, it’s using much of the real tooling that we’ll use for the -rest of our Rust career. We can expect to do this to get started with virtually -all Rust projects: - -```bash -$ git clone someurl.com/foo -$ cd foo -$ cargo build -``` - -## A New Project - -We don’t have to go through this whole process every time we want to start a new -project! Cargo has the ability to make a bare-bones project directory in which -we can start developing right away. - -To start a new project with Cargo, we use `cargo new`: - -```bash -$ cargo new hello_world --bin -``` - -We’re passing `--bin` because our goal is to get straight to making an -executable application, as opposed to a library. Executables are often called -‘binaries.’ (as in `/usr/bin`, if we’re on a Unix system) - -Let's check out what Cargo has generated for us: - -```bash -$ cd hello_world -$ tree . -. -├── Cargo.toml -└── src - └── main.rs - -1 directory, 2 files -``` - -If we don't have the `tree` command, we can probably get it from our -distribution’s package manager. It’s not necessary, but it’s certainly useful. - -This is all we need to get started. First, let’s check out `Cargo.toml`: - -```toml -[package] - -name = "hello_world" -version = "0.1.0" -authors = ["Your Name "] -``` - -Cargo has populated this file with reasonable defaults based off the arguments -we gave it and our `git` global configuration. You may notice that Cargo has -also initialized the `hello_world` directory as a `git` repository. - -Here’s what’s in `src/main.rs`: - -```rust -fn main() { - println!("Hello, world!"); -} -``` - -Cargo has generated a "Hello World!" for us, and we’re ready to start coding! -Cargo has its own [guide][guide] which covers Cargo’s features in much more -depth. - -[guide]: http://doc.crates.io/guide.html - -Now that we’ve got the tools down, let’s actually learn more about the Rust -language itself. These are the basics that will serve us well through the rest -of our time with Rust. - -You have two options: Dive into a project with ‘[Learn Rust][learnrust]’, or -start from the bottom and work your way up with -‘[Syntax and Semantics][syntax]’. More experienced systems programmers will -probably prefer ‘Learn Rust’, while those from dynamic backgrounds may enjoy -either. Different people learn differently! Choose whatever’s right for you. - -[learnrust]: learn-rust.html -[syntax]: syntax-and-semantics.html diff --git a/src/doc/trpl/hello-world.md b/src/doc/trpl/hello-world.md deleted file mode 100644 index 2f9166751d965..0000000000000 --- a/src/doc/trpl/hello-world.md +++ /dev/null @@ -1,171 +0,0 @@ -% Hello, world! - -Now that we have Rust installed, let’s write our first Rust program. It’s -traditional to make our first program in any new language one that prints the -text “Hello, world!” to the screen. The nice thing about starting with such a -simple program is that we can verify that our compiler isn’t just installed, but -also working properly. And printing information to the screen is a pretty common -thing to do. - -The first thing that we need to do is make a file to put our code in. I like to -make a `projects` directory in my home directory, and keep all my projects -there. Rust doesn't care where our code lives. - -This actually leads to one other concern we should address: this guide will -assume that we have basic familiarity with the command line. Rust itself makes -no specific demands on our editing tooling, or where our code lives. If we -prefer an IDE to the command line, we may want to check out -[SolidOak][solidoak], or wherever plugins are for our favorite IDE. There are a -number of extensions of varying quality in development by the community. The -Rust team also ships [plugins for various editors][plugins]. Configuring our -editor or IDE is out of the scope of this tutorial, so check the documentation -for our setup, specifically. - -[solidoak]: https://github.com/oakes/SolidOak -[plugins]: https://github.com/rust-lang/rust/blob/master/src/etc/CONFIGS.md - -With that said, let’s make a directory in our projects directory. - -```bash -$ mkdir ~/projects -$ cd ~/projects -$ mkdir hello_world -$ cd hello_world -``` - -If we’re on Windows and not using PowerShell, the `~` may not work. Consult the -documentation for our shell for more details. - -Let’s make a new source file next. We’ll call our file `main.rs`. Rust files -always end in a `.rs` extension, and if we’re using more than one word in a -Rust filename, we use an underscore: for example, `linked_list.rs`, not -`linkedlist.rs` or `LinkedList.rs`. - -Now that we’ve got our file open, type this in: - -```rust -fn main() { - println!("Hello, world!"); -} -``` - -Save the file, and then type this into our terminal window: - -```bash -$ rustc main.rs -$ ./main # or main.exe on Windows -Hello, world! -``` - -Success! Let’s go over what just happened in detail. - -```rust -fn main() { - -} -``` - -These lines define a *function* in Rust. The `main` function is special: -it's the beginning of every Rust program. The first line says "I’m declaring a -function named `main` which takes no arguments and returns nothing." If there -were arguments, they would go inside the parentheses (`(` and `)`), and because -we aren’t returning anything from this function, we can omit the return type -entirely. We’ll get to it later. - -You’ll also note that the function is wrapped in curly braces (`{` and `}`). -Rust requires these around all function bodies. It is also considered good style -to put the opening curly brace on the same line as the function declaration, -with one space in between. - -Next up is this line: - -```rust - println!("Hello, world!"); -``` - -This line does all of the work in our little program. There are a number of -details that are important here. The first is that it’s indented with four -spaces, not tabs. Please configure your editor of choice to insert four spaces -with the tab key. We provide some -[sample configurations for various editors][configs]. - -[configs]: https://github.com/rust-lang/rust/tree/master/src/etc/CONFIGS.md - -The second point is the `println!()` part. This is calling a Rust -[macro][macro], which is how metaprogramming is done in Rust. If it were a -function instead, it would look like this: `println()`. For our purposes, we -don’t need to worry about this difference. Just know that sometimes, we’ll see a -`!`, and that means that we’re calling a macro instead of a normal function. -Rust implements `println!` as a macro rather than a function for good reasons, -but that's an advanced topic. One last thing to mention: Rust’s macros are -significantly different from C macros, if you’ve used those. Don’t be scared of -using macros. We’ll get to the details eventually, you’ll just have to take it -on trust for now. - -[macro]: macros.html - -Next, `"Hello, world!"` is a ‘string’. Strings are a surprisingly complicated -topic in a systems programming language, and this is a ‘statically allocated’ -string. If you want to read further about allocation, check out [the stack and -the heap][allocation], but you don’t need to right now if you don’t want to. We -pass this string as an argument to `println!`, which prints the string to the -screen. Easy enough! - -[allocation]: the-stack-and-the-heap.html - -Finally, the line ends with a semicolon (`;`). Rust is an [‘expression oriented’ -language][expression-oriented language], which means that most things are -expressions, rather than statements. The `;` is used to indicate that this -expression is over, and the next one is ready to begin. Most lines of Rust code -end with a `;`. - -[expression-oriented language]: glossary.html#expression-oriented-language - -Finally, actually compiling and running our program. We can compile with our -compiler, `rustc`, by passing it the name of our source file: - -```bash -$ rustc main.rs -``` - -This is similar to `gcc` or `clang`, if you come from a C or C++ background. -Rust will output a binary executable. We can see it with `ls`: - -```bash -$ ls -main main.rs -``` - -Or on Windows: - -```bash -$ dir -main.exe main.rs -``` - -There are now two files: our source code, with the `.rs` extension, and the -executable (`main.exe` on Windows, `main` everywhere else). - -```bash -$ ./main # or main.exe on Windows -``` - -This prints out our `Hello, world!` text to our terminal. - -If you come from a dynamic language like Ruby, Python, or JavaScript, you may -not be used to these two steps being separate. Rust is an ‘ahead-of-time -compiled language’, which means that we can compile a program, give it to -someone else, and they don't need to have Rust installed. If we give someone a -`.rb` or `.py` or `.js` file, they need to have a Ruby/Python/JavaScript -implementation installed, but we just need one command to both compile and run -our program. Everything is a tradeoff in language design, and Rust has made its -choice. - -Congratulations! You have officially written a Rust program. That makes you a -Rust programmer! Welcome. 🎊🎉👍 - -Next, I'd like to introduce you to another tool, Cargo, which is used to write -real-world Rust programs. Just using `rustc` is nice for simple things, but as -our project grows, we'll want something to help us manage all of the options -that it has, and to make it easy to share our code with other people and -projects. diff --git a/src/doc/trpl/installing-rust.md b/src/doc/trpl/installing-rust.md deleted file mode 100644 index 49ee5317c7883..0000000000000 --- a/src/doc/trpl/installing-rust.md +++ /dev/null @@ -1,184 +0,0 @@ -% Installing Rust - -The first step to using Rust is to install it! There are a number of ways to -install Rust, but the easiest is to use the `rustup` script. If we're on Linux -or a Mac, all we need to do is this: - -> Note: we don't need to type in the `$`s, they are there to indicate the start of -> each command. We’ll see many tutorials and examples around the web that -> follow this convention: `$` for commands run as our regular user, and `#` for -> commands we should be running as an administrator. - -```bash -$ curl -sf -L https://static.rust-lang.org/rustup.sh | sh -``` - -If we're concerned about the [potential insecurity][insecurity] of using `curl | -sh`, please keep reading and see our disclaimer below. And feel free to use a -two-step version of the installation and examine our installation script: - -```bash -$ curl -f -L https://static.rust-lang.org/rustup.sh -O -$ sh rustup.sh -``` - -[insecurity]: http://curlpipesh.tumblr.com - -If you're on Windows, please download the appropriate [installer][install-page]. - -> Note: By default, the Windows installer won't add Rust to the %PATH% system -> variable. If this is the only version of Rust we are installing and we want to -> be able to run it from the command line, click on "Advanced" on the install -> dialog and on the "Product Features" page ensure "Add to PATH" is installed on -> the local hard drive. - - -[install-page]: https://www.rust-lang.org/install.html - -## Uninstalling - -If you decide you don't want Rust anymore, we'll be a bit sad, but that's okay. -Not every programming language is great for everyone. We can run the -uninstall script: - -```bash -$ sudo /usr/local/lib/rustlib/uninstall.sh -``` - -If we used the Windows installer, we can re-run the `.msi` and it will give -us an uninstall option. - -## That disclaimer we promised - -Some people, and somewhat rightfully so, get very upset when we tell them to -`curl | sh`. Their concern is that `curl | sh` implicitly requires you to trust -that the good people who maintain Rust aren't going to hack your computer and -do bad things — and even having accepted that, there is still the possibility -that the Rust website has been hacked and the `rustup` script compromised. - -Being wary of such possibilities is a good instinct! If you're uncomfortable -using `curl | sh` for reasons like these, please check out the 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 - -## Platform support - -The Rust compiler runs on, and compiles to, a great number of platforms, though -not all platforms are equally supported. Rust's support levels are organized -into three tiers, each with a different set of guarantees. - -Platforms are identified by their "target triple" which is the string to inform -the compiler what kind of output should be produced. The columns below indicate -whether the corresponding component works on the specified platform. - -### Tier 1 - -Tier 1 platforms can be thought of as "guaranteed to build and work". -Specifically they will each satisfy the following requirements: - -* Automated testing is set up to run tests for the platform. -* Landing changes to the `rust-lang/rust` repository's master branch is gated on - tests passing. -* Official release artifacts are provided for the platform. -* Documentation for how to use and how to build the platform is available. - -| Target | std |rustc|cargo| notes | -|-------------------------------|-----|-----|-----|----------------------------| -| `x86_64-pc-windows-msvc` | ✓ | ✓ | ✓ | 64-bit MSVC (Windows 7+) | -| `i686-pc-windows-gnu` | ✓ | ✓ | ✓ | 32-bit MinGW (Windows 7+) | -| `x86_64-pc-windows-gnu` | ✓ | ✓ | ✓ | 64-bit MinGW (Windows 7+) | -| `i686-apple-darwin` | ✓ | ✓ | ✓ | 32-bit OSX (10.7+, Lion+) | -| `x86_64-apple-darwin` | ✓ | ✓ | ✓ | 64-bit OSX (10.7+, Lion+) | -| `i686-unknown-linux-gnu` | ✓ | ✓ | ✓ | 32-bit Linux (2.6.18+) | -| `x86_64-unknown-linux-gnu` | ✓ | ✓ | ✓ | 64-bit Linux (2.6.18+) | - -### Tier 2 - -Tier 2 platforms can be thought of as "guaranteed to build". Automated tests are -not run so it's not guaranteed to produce a working build, but platforms often -work to quite a good degree and patches are always welcome! Specifically, these -platforms are required to have each of the following: - -* Automated building is set up, but may not be running tests. -* Landing changes to the `rust-lang/rust` repository's master branch is gated on - platforms **building**. Note that this means for some platforms only the - standard library is compiled, but for others the full bootstrap is run. -* Official release artifacts are provided for the platform. - -| Target | std |rustc|cargo| notes | -|-------------------------------|-----|-----|-----|----------------------------| -| `i686-pc-windows-msvc` | ✓ | ✓ | ✓ | 32-bit MSVC (Windows 7+) | - -### Tier 3 - -Tier 3 platforms are those which Rust has support for, but landing changes is -not gated on the platform either building or passing tests. Working builds for -these platforms may be spotty as their reliability is often defined in terms of -community contributions. Additionally, release artifacts and installers are not -provided, but there may be community infrastructure producing these in -unofficial locations. - -| Target | std |rustc|cargo| notes | -|-------------------------------|-----|-----|-----|----------------------------| -| `x86_64-unknown-linux-musl` | ✓ | | | 64-bit Linux with MUSL | -| `arm-linux-androideabi` | ✓ | | | ARM Android | -| `i686-linux-android` | ✓ | | | 32-bit x86 Android | -| `aarch64-linux-android` | ✓ | | | ARM64 Android | -| `arm-unknown-linux-gnueabi` | ✓ | ✓ | | ARM Linux (2.6.18+) | -| `arm-unknown-linux-gnueabihf` | ✓ | ✓ | | ARM Linux (2.6.18+) | -| `aarch64-unknown-linux-gnu` | ✓ | | | ARM64 Linux (2.6.18+) | -| `mips-unknown-linux-gnu` | ✓ | | | MIPS Linux (2.6.18+) | -| `mipsel-unknown-linux-gnu` | ✓ | | | MIPS (LE) Linux (2.6.18+) | -| `powerpc-unknown-linux-gnu` | ✓ | | | PowerPC Linux (2.6.18+) | -| `i386-apple-ios` | ✓ | | | 32-bit x86 iOS | -| `x86_64-apple-ios` | ✓ | | | 64-bit x86 iOS | -| `armv7-apple-ios` | ✓ | | | ARM iOS | -| `armv7s-apple-ios` | ✓ | | | ARM iOS | -| `aarch64-apple-ios` | ✓ | | | ARM64 iOS | -| `i686-unknown-freebsd` | ✓ | ✓ | | 32-bit FreeBSD | -| `x86_64-unknown-freebsd` | ✓ | ✓ | | 64-bit FreeBSD | -| `x86_64-unknown-openbsd` | ✓ | ✓ | | 64-bit OpenBSD | -| `x86_64-unknown-netbsd` | ✓ | ✓ | | 64-bit NetBSD | -| `x86_64-unknown-bitrig` | ✓ | ✓ | | 64-bit Bitrig | -| `x86_64-unknown-dragonfly` | ✓ | ✓ | | 64-bit DragonFlyBSD | -| `x86_64-rumprun-netbsd` | ✓ | | | 64-bit NetBSD Rump Kernel | -| `i686-pc-windows-msvc` (XP) | ✓ | | | Windows XP support | -| `x86_64-pc-windows-msvc` (XP) | ✓ | | | Windows XP support | - -Note that this table can be expanded over time, this isn't the exhaustive set of -tier 3 platforms that will ever be! - -## After installation - -If we've got Rust installed, we can open up a shell, and type this: - -```bash -$ rustc --version -``` - -You should see the version number, commit hash, and commit date. - -If you do, Rust has been installed successfully! Congrats! - -If you don't and you're on Windows, check that Rust is in your %PATH% system -variable. If it isn't, run the installer again, select "Change" on the "Change, -repair, or remove installation" page and ensure "Add to PATH" is installed on -the local hard drive. - -This installer also installs a copy of the documentation locally, so we can read -it offline. On UNIX systems, `/usr/local/share/doc/rust` is the location. On -Windows, it's in a `share/doc` directory, inside the directory to which Rust was -installed. - -If not, there are a number of places where we can get help. The easiest is -[the #rust IRC channel on irc.mozilla.org][irc], which we can access through -[Mibbit][mibbit]. Click that link, and we'll be chatting with other Rustaceans -(a silly nickname we call ourselves) who can help us out. Other great resources -include [the user’s forum][users], and [Stack Overflow][stackoverflow]. - -[irc]: irc://irc.mozilla.org/#rust -[mibbit]: http://chat.mibbit.com/?server=irc.mozilla.org&channel=%23rust -[users]: https://users.rust-lang.org/ -[stackoverflow]: http://stackoverflow.com/questions/tagged/rust diff --git a/src/doc/trpl/method-syntax.md b/src/doc/trpl/method-syntax.md index d31d823247082..41c134b29f3d1 100644 --- a/src/doc/trpl/method-syntax.md +++ b/src/doc/trpl/method-syntax.md @@ -43,8 +43,6 @@ fn main() { This will print `12.566371`. - - We’ve made a `struct` that represents a circle. We then write an `impl` block, and inside it, define a method, `area`. @@ -83,6 +81,35 @@ impl Circle { } ``` +You can use as many `impl` blocks as you’d like. The previous example could +have also been written like this: + +```rust +struct Circle { + x: f64, + y: f64, + radius: f64, +} + +impl Circle { + fn reference(&self) { + println!("taking self by reference!"); + } +} + +impl Circle { + fn mutable_reference(&mut self) { + println!("taking self by mutable reference!"); + } +} + +impl Circle { + fn takes_ownership(self) { + println!("taking ownership of self!"); + } +} +``` + # Chaining method calls So, now we know how to call a method, such as `foo.bar()`. But what about our diff --git a/src/doc/trpl/references-and-borrowing.md b/src/doc/trpl/references-and-borrowing.md index 944417d1096b0..d8758e0c695c2 100644 --- a/src/doc/trpl/references-and-borrowing.md +++ b/src/doc/trpl/references-and-borrowing.md @@ -171,9 +171,9 @@ to the definition of a data race: > operations are not synchronized. With references, you may have as many as you’d like, since none of them are -writing. If you are writing, you need two or more pointers to the same memory, -and you can only have one `&mut` at a time. This is how Rust prevents data -races at compile time: we’ll get errors if we break the rules. +writing. However, as we can only have one `&mut` at a time, it is impossible to +have a data race. This is how Rust prevents data races at compile time: we’ll +get errors if we break the rules. With this in mind, let’s consider our example again. @@ -378,3 +378,4 @@ statement 1 at 3:14 In the above example, `y` is declared before `x`, meaning that `y` lives longer than `x`, which is not allowed. + diff --git a/src/doc/trpl/rust-inside-other-languages.md b/src/doc/trpl/rust-inside-other-languages.md index 5c0bde02f9605..61627c0b5a2fe 100644 --- a/src/doc/trpl/rust-inside-other-languages.md +++ b/src/doc/trpl/rust-inside-other-languages.md @@ -177,7 +177,8 @@ build deps examples libembed.so native That `libembed.so` is our ‘shared object’ library. We can use this file just like any shared object library written in C! As an aside, this may be -`embed.dll` or `libembed.dylib`, depending on the platform. +`embed.dll` (Microsoft Windows) or `libembed.dylib` (Mac OS X), depending on +your operating system. Now that we’ve got our Rust library built, let’s use it from our Ruby. diff --git a/src/doc/trpl/strings.md b/src/doc/trpl/strings.md index 1848366498981..42a0acd21a2a0 100644 --- a/src/doc/trpl/strings.md +++ b/src/doc/trpl/strings.md @@ -12,21 +12,42 @@ encoding of UTF-8 sequences. Additionally, unlike some systems languages, strings are not null-terminated and can contain null bytes. Rust has two main types of strings: `&str` and `String`. Let’s talk about -`&str` first. These are called ‘string slices’. String literals are of the type -`&'static str`: +`&str` first. These are called ‘string slices’. A string slice has a fixed +size, and cannot be mutated. It is a reference to a sequence of UTF-8 bytes. ```rust let greeting = "Hello there."; // greeting: &'static str ``` -This string is statically allocated, meaning that it’s saved inside our -compiled program, and exists for the entire duration it runs. The `greeting` -binding is a reference to this statically allocated string. String slices -have a fixed size, and cannot be mutated. +`"Hello there."` is a string literal and its type is `&'static str`. A string +literal is a string slice that is statically allocated, meaning that it’s saved +inside our compiled program, and exists for the entire duration it runs. The +`greeting` binding is a reference to this statically allocated string. Any +function expecting a string slice will also accept a string literal. -A `String`, on the other hand, is a heap-allocated string. This string is -growable, and is also guaranteed to be UTF-8. `String`s are commonly created by -converting from a string slice using the `to_string` method. +String literals can span multiple lines. There are two forms. The first will +include the newline and the leading spaces: + +```rust +let s = "foo + bar"; + +assert_eq!("foo\n bar", s); +``` + +The second, with a `\`, trims the spaces and the newline: + +```rust +let s = "foo\ + bar"; + +assert_eq!("foobar", s); +``` + +Rust has more than just `&str`s though. A `String`, is a heap-allocated string. +This string is growable, and is also guaranteed to be UTF-8. `String`s are +commonly created by converting from a string slice using the `to_string` +method. ```rust let mut s = "Hello".to_string(); // mut s: String diff --git a/src/doc/trpl/the-stack-and-the-heap.md b/src/doc/trpl/the-stack-and-the-heap.md index 0bc2ca263d5b7..f835322ee716e 100644 --- a/src/doc/trpl/the-stack-and-the-heap.md +++ b/src/doc/trpl/the-stack-and-the-heap.md @@ -74,7 +74,9 @@ visualize what’s going on with memory. Your operating system presents a view o memory to your program that’s pretty simple: a huge list of addresses, from 0 to a large number, representing how much RAM your computer has. For example, if you have a gigabyte of RAM, your addresses go from `0` to `1,073,741,823`. That -number comes from 230, the number of bytes in a gigabyte. +number comes from 230, the number of bytes in a gigabyte. [^gigabyte] + +[^gigabyte]: ‘Gigabyte’ can mean two things: 10^9, or 2^30. The SI standard resolved this by stating that ‘gigabyte’ is 10^9, and ‘gibibyte’ is 2^30. However, very few people use this terminology, and rely on context to differentiate. We follow in that tradition here. This memory is kind of like a giant array: addresses start at zero and go up to the final number. So here’s a diagram of our first stack frame: diff --git a/src/etc/add-authors.sh b/src/etc/add-authors.sh old mode 100644 new mode 100755 index 3ae0ec73957e7..e45b803fa07e2 --- a/src/etc/add-authors.sh +++ b/src/etc/add-authors.sh @@ -30,8 +30,8 @@ range="$1" authors_file="./AUTHORS.txt" tmp_file="./AUTHORS.txt.tmp" old_authors="$(cat "$authors_file" | tail -n +2 | sed "/^$/d" | sort)" -new_authors="$(git log "$range" --format="%aN <%aE>" | sort | uniq)" +new_authors="$(git log "$range" --use-mailmap --format="%aN <%aE>" | sort | uniq)" printf "%s\n\n" "Rust was written by these fine people:" > "$tmp_file" -printf "%s\n%s" "$old_authors" "$new_authors" | sort | uniq >> "$tmp_file" +printf "%s\n%s" "$old_authors" "$new_authors" | sort -fs | uniq >> "$tmp_file" mv -f "$tmp_file" "$authors_file" diff --git a/src/etc/apple-darwin.supp b/src/etc/apple-darwin.supp index 7e2598f76949c..866578930a3d8 100644 --- a/src/etc/apple-darwin.supp +++ b/src/etc/apple-darwin.supp @@ -1,9 +1,105 @@ { - issue_1333_setenv_leak + osx-frameworks.rs-fails-otherwise-1 Memcheck:Leak - fun:malloc_zone_malloc + match-leak-kinds: possible + fun:malloc + ... + fun:__CFInitialize + fun:_ZN16ImageLoaderMachO11doImageInitERKN11ImageLoader11LinkContextE + fun:_ZN16ImageLoaderMachO16doInitializationERKN11ImageLoader11LinkContextE + fun:_ZN11ImageLoader23recursiveInitializationERKNS_11LinkContextEjRNS_21InitializerTimingListERNS_15UninitedUpwardsE + fun:_ZN11ImageLoader23recursiveInitializationERKNS_11LinkContextEjRNS_21InitializerTimingListERNS_15UninitedUpwardsE + fun:_ZN11ImageLoader19processInitializersERKNS_11LinkContextEjRNS_21InitializerTimingListERNS_15UninitedUpwardsE + fun:_ZN11ImageLoader15runInitializersERKNS_11LinkContextERNS_21InitializerTimingListE + fun:_ZN4dyld24initializeMainExecutableEv +} + +{ + osx-frameworks.rs-fails-otherwise-2 + Memcheck:Leak + match-leak-kinds: possible + fun:malloc_zone_calloc + ... + fun:__CFInitialize + fun:_ZN16ImageLoaderMachO11doImageInitERKN11ImageLoader11LinkContextE + fun:_ZN16ImageLoaderMachO16doInitializationERKN11ImageLoader11LinkContextE + fun:_ZN11ImageLoader23recursiveInitializationERKNS_11LinkContextEjRNS_21InitializerTimingListERNS_15UninitedUpwardsE + fun:_ZN11ImageLoader23recursiveInitializationERKNS_11LinkContextEjRNS_21InitializerTimingListERNS_15UninitedUpwardsE + fun:_ZN11ImageLoader19processInitializersERKNS_11LinkContextEjRNS_21InitializerTimingListERNS_15UninitedUpwardsE +} + +{ + osx-frameworks.rs-fails-otherwise-3 + Memcheck:Leak + match-leak-kinds: possible + fun:realloc + fun:_ZL12realizeClassP10objc_class + fun:_ZL12realizeClassP10objc_class + fun:_ZN13list_array_ttIm15protocol_list_tE11attachListsEPKPS0_j + fun:_read_images + fun:map_images_nolock + fun:map_2_images + fun:_ZN4dyldL18notifyBatchPartialE17dyld_image_statesbPFPKcS0_jPK15dyld_image_infoE + fun:_ZN4dyld36registerImageStateBatchChangeHandlerE17dyld_image_statesPFPKcS0_jPK15dyld_image_infoE + fun:dyld_register_image_state_change_handler + fun:_objc_init + fun:_os_object_init +} + +{ + osx-frameworks.rs-fails-otherwise-4 + Memcheck:Leak + match-leak-kinds: possible + fun:calloc ... - fun:setenv - fun:setenv__c_stack_shim + fun:__CFInitialize + fun:_ZN16ImageLoaderMachO11doImageInitERKN11ImageLoader11LinkContextE + fun:_ZN16ImageLoaderMachO16doInitializationERKN11ImageLoader11LinkContextE + fun:_ZN11ImageLoader23recursiveInitializationERKNS_11LinkContextEjRNS_21InitializerTimingListERNS_15UninitedUpwardsE +} + +{ + osx-frameworks.rs-fails-otherwise-5 + Memcheck:Leak + match-leak-kinds: definite + fun:calloc + ... + fun:__CFInitialize + fun:_ZN16ImageLoaderMachO11doImageInitERKN11ImageLoader11LinkContextE + fun:_ZN16ImageLoaderMachO16doInitializationERKN11ImageLoader11LinkContextE + fun:_ZN11ImageLoader23recursiveInitializationERKNS_11LinkContextEjRNS_21InitializerTimingListERNS_15UninitedUpwardsE +} + +{ + osx-frameworks.rs-fails-otherwise-6 + Memcheck:Leak + match-leak-kinds: definite + fun:malloc + fun:strdup + fun:_CFProcessPath + fun:__CFInitialize + fun:_ZN16ImageLoaderMachO11doImageInitERKN11ImageLoader11LinkContextE + fun:_ZN16ImageLoaderMachO16doInitializationERKN11ImageLoader11LinkContextE + fun:_ZN11ImageLoader23recursiveInitializationERKNS_11LinkContextEjRNS_21InitializerTimingListERNS_15UninitedUpwardsE + fun:_ZN11ImageLoader23recursiveInitializationERKNS_11LinkContextEjRNS_21InitializerTimingListERNS_15UninitedUpwardsE + fun:_ZN11ImageLoader19processInitializersERKNS_11LinkContextEjRNS_21InitializerTimingListERNS_15UninitedUpwardsE + fun:_ZN11ImageLoader15runInitializersERKNS_11LinkContextERNS_21InitializerTimingListE + fun:_ZN4dyld24initializeMainExecutableEv + fun:_ZN4dyld5_mainEPK12macho_headermiPPKcS5_S5_Pm +} + +{ + osx-frameworks.rs-fails-otherwise-7 + Memcheck:Leak + match-leak-kinds: definite + fun:malloc_zone_malloc ... + fun:__CFInitialize + fun:_ZN16ImageLoaderMachO11doImageInitERKN11ImageLoader11LinkContextE + fun:_ZN16ImageLoaderMachO16doInitializationERKN11ImageLoader11LinkContextE + fun:_ZN11ImageLoader23recursiveInitializationERKNS_11LinkContextEjRNS_21InitializerTimingListERNS_15UninitedUpwardsE + fun:_ZN11ImageLoader23recursiveInitializationERKNS_11LinkContextEjRNS_21InitializerTimingListERNS_15UninitedUpwardsE + fun:_ZN11ImageLoader19processInitializersERKNS_11LinkContextEjRNS_21InitializerTimingListERNS_15UninitedUpwardsE + fun:_ZN11ImageLoader15runInitializersERKNS_11LinkContextERNS_21InitializerTimingListE + fun:_ZN4dyld24initializeMainExecutableEv } diff --git a/src/etc/make-win-dist.py b/src/etc/make-win-dist.py index 817215ffba070..eda5f85408574 100644 --- a/src/etc/make-win-dist.py +++ b/src/etc/make-win-dist.py @@ -58,10 +58,6 @@ def make_win_dist(rust_root, plat_root, target_triple): rustc_dlls.append("libgcc_s_seh-1.dll") target_libs = [ # MinGW libs - "crtbegin.o", - "crtend.o", - "crt2.o", - "dllcrt2.o", "libgcc.a", "libgcc_eh.a", "libgcc_s.a", diff --git a/src/etc/tidy.py b/src/etc/tidy.py index 9f5f919bce8d8..942793adc31de 100644 --- a/src/etc/tidy.py +++ b/src/etc/tidy.py @@ -108,7 +108,8 @@ def interesting_file(f): 'src/rustllvm', 'src/rt/valgrind', 'src/rt/msvc', - 'src/rust-installer' + 'src/rust-installer', + 'src/liblibc', } if any(d in dirpath for d in skippable_dirs): diff --git a/src/etc/x86.supp b/src/etc/x86.supp index 58eb109d860ed..e4368da90331f 100644 --- a/src/etc/x86.supp +++ b/src/etc/x86.supp @@ -1,496 +1,65 @@ { - our-failure-to-setup-freeres-structure - Memcheck:Free - fun:free - fun:__libc_freeres - fun:_vgnU_freeres -} - -{ - our-failure-to-setup-freeres-structure2 - Memcheck:Free - fun:free - fun:free_mem - fun:__libc_freeres - fun:_vgnU_freeres -} - -{ - leaked-TLS-chunk-x86-exit-path-fails-to-clean-up - Memcheck:Leak - fun:calloc - fun:_dl_allocate_tls -} - -{ - linux-dl-prob - Memcheck:Param - read(buf) - ... - fun:_dl_map_object -} - -{ - mac-dyld-oddity - Memcheck:Cond - fun:_ZN4dyld5_mainEPK12macho_headermiPPKcS5_S5_ - fun:_ZN13dyldbootstrap5startEPK12macho_headeriPPKcl - fun:_dyld_start - obj:* -} - -{ - mac-dlopen-weirdness - Memcheck:Cond - fun:_ZNK16ImageLoaderMachO9getRPathsERKN11ImageLoader11LinkContextERSt6vectorIPKcSaIS6_EE - fun:_ZN11ImageLoader22recursiveLoadLibrariesERKNS_11LinkContextEbRKNS_10RPathChainE - fun:_ZN11ImageLoader4linkERKNS_11LinkContextEbbRKNS_10RPathChainE - fun:_ZN4dyld4linkEP11ImageLoaderbRKNS0_10RPathChainE - fun:dlopen - fun:dlopen - fun:_ZN16rust_crate_cache3libC1EP8rust_domPKc - fun:_ZN16rust_crate_cache7get_libEmPKc - fun:_ZL11fetch_c_symP9rust_taskPK10rust_cratemmPKcS5_ -} - -{ - mac-dlopen-weirdness-2 - Memcheck:Value4 - fun:_ZNK16ImageLoaderMachO9getRPathsERKN11ImageLoader11LinkContextERSt6vectorIPKcSaIS6_EE - fun:_ZN11ImageLoader22recursiveLoadLibrariesERKNS_11LinkContextEbRKNS_10RPathChainE - fun:_ZN11ImageLoader4linkERKNS_11LinkContextEbbRKNS_10RPathChainE - fun:_ZN4dyld4linkEP11ImageLoaderbRKNS0_10RPathChainE - fun:dlopen - fun:dlopen - fun:_ZN16rust_crate_cache3libC1EP8rust_domPKc - fun:_ZN16rust_crate_cache7get_libEmPKc - fun:_ZL11fetch_c_symP9rust_taskPK10rust_cratemmPKcS5_ -} - -{ - mac-dlopen-weirdness-3 - Memcheck:Value4 - fun:strcpy - fun:_ZN11ImageLoader22recursiveLoadLibrariesERKNS_11LinkContextEbRKNS_10RPathChainE - fun:_ZN11ImageLoader4linkERKNS_11LinkContextEbbRKNS_10RPathChainE - fun:_ZN4dyld4linkEP11ImageLoaderbRKNS0_10RPathChainE - fun:dlopen - fun:dlopen - fun:_ZN16rust_crate_cache3libC1EP8rust_domPKc - fun:_ZN16rust_crate_cache7get_libEmPKc - fun:_ZL11fetch_c_symP9rust_taskPK10rust_cratemmPKcS5_ -} - -{ - mac-dlopen-weirdness-4 - Memcheck:Value4 - obj:* - fun:_ZNK16ImageLoaderMachO9getRPathsERKN11ImageLoader11LinkContextERSt6vectorIPKcSaIS6_EE - fun:_ZN11ImageLoader22recursiveLoadLibrariesERKNS_11LinkContextEbRKNS_10RPathChainE - fun:_ZN11ImageLoader4linkERKNS_11LinkContextEbbRKNS_10RPathChainE - fun:_ZN4dyld4linkEP11ImageLoaderbRKNS0_10RPathChainE - fun:dlopen - fun:dlopen - fun:_ZN16rust_crate_cache3libC1EP8rust_domPKc - fun:_ZN16rust_crate_cache7get_libEmPKc - fun:_ZL11fetch_c_symP9rust_taskPK10rust_cratemmPKcS5_ -} - -{ - mac-dlopen-weirdness-5 - Memcheck:Cond - fun:memcpy - fun:strdup - fun:_ZNK16ImageLoaderMachO9getRPathsERKN11ImageLoader11LinkContextERSt6vectorIPKcSaIS6_EE - fun:_ZN11ImageLoader22recursiveLoadLibrariesERKNS_11LinkContextEbRKNS_10RPathChainE - fun:_ZN11ImageLoader4linkERKNS_11LinkContextEbbRKNS_10RPathChainE - fun:_ZN4dyld4linkEP11ImageLoaderbRKNS0_10RPathChainE - fun:dlopen - fun:dlopen - fun:_ZN16rust_crate_cache3libC1EP8rust_domPKc - fun:_ZN16rust_crate_cache7get_libEmPKc - fun:_ZL11fetch_c_symP9rust_taskPK10rust_cratemmPKcS5_ -} - -{ - mac-dlopen-weirdness-6 - Memcheck:Value4 - fun:memcpy - fun:strdup - fun:_ZNK16ImageLoaderMachO9getRPathsERKN11ImageLoader11LinkContextERSt6vectorIPKcSaIS6_EE - fun:_ZN11ImageLoader22recursiveLoadLibrariesERKNS_11LinkContextEbRKNS_10RPathChainE - fun:_ZN11ImageLoader4linkERKNS_11LinkContextEbbRKNS_10RPathChainE - fun:_ZN4dyld4linkEP11ImageLoaderbRKNS0_10RPathChainE - fun:dlopen - fun:dlopen - fun:_ZN16rust_crate_cache3libC1EP8rust_domPKc - fun:_ZN16rust_crate_cache7get_libEmPKc - fun:_ZL11fetch_c_symP9rust_taskPK10rust_cratemmPKcS5_ -} - -{ - mac-dyld - Memcheck:Cond - ... - fun:_ZN13dyldbootstrap5startEPK12macho_headeriPPKcl - fun:_dyld_start - obj:* -} - -{ - mac-dyld-2 - Memcheck:Value4 - ... - fun:_ZN13dyldbootstrap5startEPK12macho_headeriPPKcl - fun:_dyld_start - obj:* -} - -{ - mac-dyld-3 - Memcheck:Param - stat(path) - ... - fun:_ZN13dyldbootstrap5startEPK12macho_headeriPPKcl - fun:_dyld_start - obj:* -} - -{ - mac-dyld-4 - Memcheck:Param - open(filename) - ... - fun:_ZN13dyldbootstrap5startEPK12macho_headeriPPKcl - fun:_dyld_start - obj:* -} - -{ - mac-dyld-5 - Memcheck:Cond - ... - fun:_ZN4dyld4loadEPKcRKNS_11LoadContextE - fun:_ZN4dyld5_mainEPK12macho_headermiPPKcS5_S5_ -} - -{ - mac-dyld-6 - Memcheck:Value4 - ... - fun:_ZN4dyld4loadEPKcRKNS_11LoadContextE - fun:_ZN4dyld5_mainEPK12macho_headermiPPKcS5_S5_ -} - -{ - mac-dyld-7 - Memcheck:Value4 - ... - fun:_ZN4dyld4loadEPKcRKNS_11LoadContextE -} - -{ - mac-dyld-8 - Memcheck:Cond - ... - fun:_ZN4dyld4loadEPKcRKNS_11LoadContextE -} - -{ - mac-dyld-9 - Memcheck:Value4 - ... - fun:_ZN4dyldL10loadPhase0EPKcRKNS_11LoadContextEPSt6vectorIS1_SaIS1_EE -} - -{ - mac-dyld-10 - Memcheck:Cond - ... - fun:_ZN4dyldL10loadPhase0EPKcRKNS_11LoadContextEPSt6vectorIS1_SaIS1_EE -} - -{ - mac-dyld-11 - Memcheck:Param - stat(path) - ... - fun:_ZN4dyld5_mainEPK12macho_headermiPPKcS5_S5_ - fun:_ZN13dyldbootstrap5startEPK12macho_headeriPPKcl -} - -{ - mac-dyld-12 - Memcheck:Param - open(filename) - ... - fun:_ZN4dyld5_mainEPK12macho_headermiPPKcS5_S5_ - fun:_ZN13dyldbootstrap5startEPK12macho_headeriPPKcl -} - -{ - mac-dyld-13 - Memcheck:Cond - ... - fun:_ZN4dyld5_mainEPK12macho_headermiPPKcS5_S5_ - fun:_ZN13dyldbootstrap5startEPK12macho_headeriPPKcl - fun:_dyld_start -} - -{ - mac-dyld-14 - Memcheck:Value4 - ... - fun:_ZN4dyld5_mainEPK12macho_headermiPPKcS5_S5_ - fun:_ZN13dyldbootstrap5startEPK12macho_headeriPPKcl - fun:_dyld_start -} - -{ - mac-dyld-15 - Memcheck:Value4 - ... - fun:_ZN4dyld5_mainEPK12macho_headermiPPKcS5_S5_ - fun:_ZN13dyldbootstrap5startEPK12macho_headeriPPKcl -} - -{ - mac-dyld-16 - Memcheck:Value4 - ... - fun:_ZN4dyld4linkEP11ImageLoaderbRKNS0_10RPathChainE - fun:_ZN4dyld5_mainEPK12macho_headermiPPKcS5_S5_ -} - -{ - mac-dyld-17 - Memcheck:Value4 - ... - fun:_ZN4dyld4linkEP11ImageLoaderbRKNS0_10RPathChainE -} - -{ - mac-dyld-18 - Memcheck:Cond - ... - fun:_ZN4dyld5_mainEPK12macho_headermiPPKcS5_S5_ - fun:_ZN13dyldbootstrap5startEPK12macho_headeriPPKcl -} - -{ - mac-dyld-19 - Memcheck:Value4 - ... - fun:_ZN4dyld5_mainEPK12macho_headermiPPKcS5_S5_ -} - -{ - mac-dyld-20 - Memcheck:Value4 - ... - fun:_ZN4dyld24initializeMainExecutableEv -} - -{ - mac-dyld-21 - Memcheck:Cond - ... - fun:_ZN4dyld24initializeMainExecutableEv - fun:_ZN4dyld5_mainEPK12macho_headermiPPKcS5_S5_ -} - -{ - mac-dyld-22 - Memcheck:Cond - ... - fun:_ZN4dyld24initializeMainExecutableEv -} - -{ - mac-dyld-23 - Memcheck:Value4 - ... - fun:_ZN11ImageLoader15runInitializersERKNS_11LinkContextE -} - -{ - mac-dyld-24 + goddammit-llvm-why-u-no-valgrind Memcheck:Cond + fun:* ... - fun:dyld_stub_binder_ - fun:main -} - -{ - mac-dyld-25 - Memcheck:Value4 - ... - fun:dyld_stub_binder_ - fun:main } { - mac-dyld-26 - Memcheck:Cond - ... - fun:dyld_stub_binder_ + down-with-thread-dtors.rs-fails-otherwise-1 + Memcheck:Addr1 ... + fun:tlv_finalize + fun:_pthread_tsd_cleanup + fun:_pthread_exit + fun:_pthread_body + fun:_pthread_start + fun:thread_start } { - mac-dyld-27 - Memcheck:Value4 - ... - fun:dyld_stub_binder_ + down-with-thread-dtors.rs-fails-otherwise-2 + Memcheck:Addr2 ... + fun:tlv_finalize + fun:_pthread_tsd_cleanup + fun:_pthread_exit + fun:_pthread_body + fun:_pthread_start + fun:thread_start } { - mac-dyld-28 - Memcheck:Cond - fun:_ZN4dyld14runTerminatorsEPv + down-with-thread-dtors.rs-fails-otherwise-3 + Memcheck:Addr4 ... + fun:tlv_finalize + fun:_pthread_tsd_cleanup + fun:_pthread_exit + fun:_pthread_body + fun:_pthread_start + fun:thread_start } { - mac-dyld-29 - Memcheck:Cond - fun:_ZN4dyldL18notifyBatchPartialE17dyld_image_statesbPFPKcS0_jPK15dyld_image_infoE + down-with-thread-dtors.rs-fails-otherwise-4 + Memcheck:Addr8 ... + fun:tlv_finalize + fun:_pthread_tsd_cleanup + fun:_pthread_exit + fun:_pthread_body + fun:_pthread_start + fun:thread_start } { - mac-dyld-30 - Memcheck:Value4 - fun:_ZN4dyldL18notifyBatchPartialE17dyld_image_statesbPFPKcS0_jPK15dyld_image_infoE - ... -} - -{ - llvm-user-new-leak + down-with-thread-dtors.rs-fails-otherwise-5 Memcheck:Leak - fun:_Znwj - fun:_ZN4llvm4UsernwEjj -} - -{ - race-or-something-ask-pcwalton-0 - Memcheck:Value4 - fun:*task_start_wrapper* - ... -} - -{ - race-or-something-ask-pcwalton-1 - Memcheck:Value4 - ... - fun:*build_start_wrapper* - ... -} - -{ - lock_and_signal-probably-threadsafe-access-outside-of-lock - Helgrind:Race - fun:_ZN15lock_and_signal27lock_held_by_current_threadEv - ... -} - -{ - lock_and_signal-probably-threadsafe-access-outside-of-lock2 - Helgrind:Race - fun:_ZN15lock_and_signal6unlockEv - ... -} - -{ - lock_and_signal-probably-threadsafe-access-outside-of-lock3 - Helgrind:Race - fun:_ZN15lock_and_signal4lockEv - ... -} - -{ - lock_and_signal-probably-threadsafe-access-outside-of-lock4 - Helgrind:Race - fun:_ZN15lock_and_signal4waitEv - ... -} - -{ - uv-async-send-does-racy-things - Helgrind:Race - fun:pipecb - fun:ev_invoke_pending - fun:ev_run - fun:uv_run - ... -} - -{ - uv-loop-init-does-some-checks-that-are-not-lock-protected - Helgrind:Race - fun:loop_init - fun:ev_loop_new - fun:uv_loop_new - ... -} - -{ - random-locking-order-but-it-only-happens-in-a-single-thread-at-a-time-I-polled-2-other-people-and-they-thought-it-was-prabably-ok - Helgrind:LockOrder - fun:pthread_mutex_lock - fun:_ZN15lock_and_signal4lockEv - fun:_ZN18rust_port_selector6selectEP9rust_taskPP9rust_portS4_mPm - ... -} - -{ - random-locking-order-but-it-only-happens-in-a-single-thread-at-a-time-I-polled-2-other-people-and-they-thought-it-was-prabably-ok - Helgrind:LockOrder - fun:pthread_mutex_lock - fun:pthread_mutex_lock - fun:_ZN15lock_and_signal4lockEv - fun:_ZN18rust_port_selector6selectEP9rust_taskPP9rust_portS4_mPm - ... -} - -{ - random-locking-order-but-it-only-happens-in-a-single-thread-at-a-time-I-polled-2-other-people-and-they-thought-it-was-prabably-ok-i686 - Helgrind:LockOrder - fun:pthread_mutex_lock - fun:pthread_mutex_lock - fun:_ZN15lock_and_signal4lockEv - fun:_ZN18rust_port_selector6selectEP9rust_taskPP9rust_portS4_jPj -} - -{ - libunwind-surely-this-is-ok - Helgrind:Race - ... - fun:_Unwind_RaiseException - fun:__cxa_throw - ... -} - -{ - libunwind-surely-this-is-ok2 - Helgrind:Race - ... - fun:_Unwind_Resume - ... -} - -{ - libunwind-surely-this-is-ok3 - Helgrind:Race - fun:_Unwind_SetGR - fun:__gxx_personality_v0 - ... -} - -{ - goddammit-llvm-why-u-no-valgrind - Memcheck:Cond - fun:* + match-leak-kinds: definite + fun:malloc + fun:tlv_allocate_and_initialize_for_key + fun:tlv_get_addr ... + fun:start } diff --git a/src/liballoc/arc.rs b/src/liballoc/arc.rs index 95dcdd22fd084..8205e13205ff8 100644 --- a/src/liballoc/arc.rs +++ b/src/liballoc/arc.rs @@ -79,11 +79,15 @@ use core::cmp::Ordering; use core::mem::{align_of_val, size_of_val}; use core::intrinsics::abort; use core::mem; -use core::ops::{Deref, CoerceUnsized}; +use core::ops::Deref; +#[cfg(not(stage0))] +use core::ops::CoerceUnsized; use core::ptr::{self, Shared}; +#[cfg(not(stage0))] use core::marker::Unsize; use core::hash::{Hash, Hasher}; use core::{usize, isize}; +use core::convert::From; use heap::deallocate; const MAX_REFCOUNT: usize = (isize::MAX) as usize; @@ -881,7 +885,6 @@ impl fmt::Pointer for Arc { #[stable(feature = "rust1", since = "1.0.0")] impl Default for Arc { - #[stable(feature = "rust1", since = "1.0.0")] fn default() -> Arc { Arc::new(Default::default()) } @@ -894,6 +897,13 @@ impl Hash for Arc { } } +#[stable(feature = "from_for_ptrs", since = "1.6.0")] +impl From for Arc { + fn from(t: T) -> Self { + Arc::new(t) + } +} + #[cfg(test)] mod tests { use std::clone::Clone; @@ -908,6 +918,7 @@ mod tests { use std::vec::Vec; use super::{Arc, Weak}; use std::sync::Mutex; + use std::convert::From; struct Canary(*mut atomic::AtomicUsize); @@ -1137,6 +1148,13 @@ mod tests { drop(x); assert!(y.upgrade().is_none()); } + + #[test] + fn test_from_owned() { + let foo = 123; + let foo_arc = Arc::from(foo); + assert!(123 == *foo_arc); + } } impl borrow::Borrow for Arc { diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 4783b4339dac3..b5c6cdff119d6 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -67,6 +67,7 @@ use core::ops::{CoerceUnsized, Deref, DerefMut}; use core::ops::{Placer, Boxed, Place, InPlace, BoxPlace}; use core::ptr::{self, Unique}; use core::raw::TraitObject; +use core::convert::From; /// A value that represents the heap. This is the default place that the `box` /// keyword allocates into when no place is supplied. @@ -264,7 +265,6 @@ impl Box { #[stable(feature = "rust1", since = "1.0.0")] impl Default for Box { - #[stable(feature = "rust1", since = "1.0.0")] fn default() -> Box { box Default::default() } @@ -272,7 +272,6 @@ impl Default for Box { #[stable(feature = "rust1", since = "1.0.0")] impl Default for Box<[T]> { - #[stable(feature = "rust1", since = "1.0.0")] fn default() -> Box<[T]> { Box::<[T; 0]>::new([]) } @@ -375,6 +374,13 @@ impl Hash for Box { } } +#[stable(feature = "from_for_ptrs", since = "1.6.0")] +impl From for Box { + fn from(t: T) -> Self { + Box::new(t) + } +} + impl Box { #[inline] #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index 899e7de4ed59f..4113f67e617d1 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -70,7 +70,7 @@ html_favicon_url = "https://doc.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/nightly/", issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/", - test(no_crate_inject))] + test(no_crate_inject, attr(allow(unused_variables), deny(warnings))))] #![no_std] #![cfg_attr(not(stage0), needs_allocator)] diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index d229d1c815c2d..88db3cfe4b612 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -161,10 +161,15 @@ use core::cmp::Ordering; use core::fmt; use core::hash::{Hasher, Hash}; use core::intrinsics::{assume, abort}; -use core::marker::{self, Unsize}; +use core::marker; +#[cfg(not(stage0))] +use core::marker::Unsize; use core::mem::{self, align_of_val, size_of_val, forget}; -use core::ops::{CoerceUnsized, Deref}; +use core::ops::Deref; +#[cfg(not(stage0))] +use core::ops::CoerceUnsized; use core::ptr::{self, Shared}; +use core::convert::From; use heap::deallocate; @@ -508,7 +513,6 @@ impl Default for Rc { /// let x: Rc = Default::default(); /// ``` #[inline] - #[stable(feature = "rust1", since = "1.0.0")] fn default() -> Rc { Rc::new(Default::default()) } @@ -698,6 +702,13 @@ impl fmt::Pointer for Rc { } } +#[stable(feature = "from_for_ptrs", since = "1.6.0")] +impl From for Rc { + fn from(t: T) -> Self { + Rc::new(t) + } +} + /// A weak version of `Rc`. /// /// Weak references do not count when determining if the inner value should be @@ -903,6 +914,7 @@ mod tests { use std::result::Result::{Err, Ok}; use std::mem::drop; use std::clone::Clone; + use std::convert::From; #[test] fn test_clone() { @@ -1105,6 +1117,13 @@ mod tests { let foo: Rc<[i32]> = Rc::new([1, 2, 3]); assert_eq!(foo, foo.clone()); } + + #[test] + fn test_from_owned() { + let foo = 123; + let foo_rc = Rc::from(foo); + assert!(123 == *foo_rc); + } } impl borrow::Borrow for Rc { diff --git a/src/liballoc_jemalloc/lib.rs b/src/liballoc_jemalloc/lib.rs index f46b12e80c56a..f2ff0593bfa54 100644 --- a/src/liballoc_jemalloc/lib.rs +++ b/src/liballoc_jemalloc/lib.rs @@ -14,6 +14,7 @@ #![staged_api] #![no_std] #![cfg_attr(not(stage0), allocator)] +#![cfg_attr(stage0, allow(improper_ctypes))] #![unstable(feature = "alloc_jemalloc", reason = "this library is unlikely to be stabilized in its current \ form or name", diff --git a/src/liballoc_system/lib.rs b/src/liballoc_system/lib.rs index c447dfbec4440..93b64c9caebc9 100644 --- a/src/liballoc_system/lib.rs +++ b/src/liballoc_system/lib.rs @@ -14,6 +14,7 @@ #![staged_api] #![no_std] #![cfg_attr(not(stage0), allocator)] +#![cfg_attr(stage0, allow(improper_ctypes))] #![unstable(feature = "alloc_system", reason = "this library is unlikely to be stabilized in its current \ form or name", @@ -141,10 +142,16 @@ mod imp { } #[cfg(windows)] +#[allow(bad_style)] mod imp { - use libc::{BOOL, DWORD, HANDLE, LPVOID, SIZE_T}; use MIN_ALIGN; + type LPVOID = *mut u8; + type HANDLE = LPVOID; + type SIZE_T = usize; + type DWORD = u32; + type BOOL = i32; + extern "system" { fn GetProcessHeap() -> HANDLE; fn HeapAlloc(hHeap: HANDLE, dwFlags: DWORD, dwBytes: SIZE_T) -> LPVOID; diff --git a/src/libarena/lib.rs b/src/libarena/lib.rs index 5bc1c44e1b1fb..2234d3608f3f3 100644 --- a/src/libarena/lib.rs +++ b/src/libarena/lib.rs @@ -28,7 +28,8 @@ #![crate_type = "dylib"] #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "https://doc.rust-lang.org/favicon.ico", - html_root_url = "https://doc.rust-lang.org/nightly/")] + html_root_url = "https://doc.rust-lang.org/nightly/", + test(no_crate_inject, attr(deny(warnings))))] #![feature(alloc)] #![feature(box_syntax)] diff --git a/src/libcollections/binary_heap.rs b/src/libcollections/binary_heap.rs index 30fc22e400a81..57646bef124c8 100644 --- a/src/libcollections/binary_heap.rs +++ b/src/libcollections/binary_heap.rs @@ -233,6 +233,7 @@ impl BinaryHeap { /// /// ``` /// #![feature(binary_heap_extras)] + /// # #![allow(deprecated)] /// /// use std::collections::BinaryHeap; /// let heap = BinaryHeap::from_vec(vec![9, 1, 2, 7, 3, 2]); @@ -521,29 +522,30 @@ impl BinaryHeap { while hole.pos() > start { let parent = (hole.pos() - 1) / 2; - if hole.removed() <= hole.get(parent) { break } + if hole.element() <= hole.get(parent) { break; } hole.move_to(parent); } } } - fn sift_down_range(&mut self, mut pos: usize, end: usize) { - let start = pos; + /// Take an element at `pos` and move it down the heap, + /// while its children are larger. + fn sift_down_range(&mut self, pos: usize, end: usize) { unsafe { let mut hole = Hole::new(&mut self.data, pos); let mut child = 2 * pos + 1; while child < end { let right = child + 1; + // compare with the greater of the two children if right < end && !(hole.get(child) > hole.get(right)) { child = right; } + // if we are already in order, stop. + if hole.element() >= hole.get(child) { break; } hole.move_to(child); child = 2 * hole.pos() + 1; } - - pos = hole.pos; } - self.sift_up(start, pos); } fn sift_down(&mut self, pos: usize) { @@ -605,7 +607,7 @@ impl<'a, T> Hole<'a, T> { /// Return a reference to the element removed #[inline(always)] - fn removed(&self) -> &T { + fn element(&self) -> &T { self.elt.as_ref().unwrap() } diff --git a/src/libcollections/borrow.rs b/src/libcollections/borrow.rs index bd1864b28cdd3..9b8f8c8f5bb84 100644 --- a/src/libcollections/borrow.rs +++ b/src/libcollections/borrow.rs @@ -72,6 +72,7 @@ impl ToOwned for T where T: Clone { /// ``` /// use std::borrow::Cow; /// +/// # #[allow(dead_code)] /// fn abs_all(input: &mut Cow<[i32]>) { /// for i in 0..input.len() { /// let v = input[i]; diff --git a/src/libcollections/btree/map.rs b/src/libcollections/btree/map.rs index 1ad836f9bdfb9..178d7a4a05294 100644 --- a/src/libcollections/btree/map.rs +++ b/src/libcollections/btree/map.rs @@ -319,8 +319,9 @@ impl BTreeMap { /// /// If the map did not have this key present, `None` is returned. /// - /// If the map did have this key present, that value is returned, and the - /// entry is not updated. See the [module-level documentation] for more. + /// If the map did have this key present, the key is not updated, the + /// value is updated and the old value is returned. + /// See the [module-level documentation] for more. /// /// [module-level documentation]: index.html#insert-and-complex-keys /// @@ -903,7 +904,6 @@ impl Hash for BTreeMap { #[stable(feature = "rust1", since = "1.0.0")] impl Default for BTreeMap { - #[stable(feature = "rust1", since = "1.0.0")] fn default() -> BTreeMap { BTreeMap::new() } diff --git a/src/libcollections/btree/set.rs b/src/libcollections/btree/set.rs index 3ca0aa377c102..0c70a1544ef92 100644 --- a/src/libcollections/btree/set.rs +++ b/src/libcollections/btree/set.rs @@ -89,6 +89,7 @@ impl BTreeSet { /// # Examples /// /// ``` + /// # #![allow(unused_mut)] /// use std::collections::BTreeSet; /// /// let mut set: BTreeSet = BTreeSet::new(); @@ -559,7 +560,6 @@ impl<'a, T: 'a + Ord + Copy> Extend<&'a T> for BTreeSet { #[stable(feature = "rust1", since = "1.0.0")] impl Default for BTreeSet { - #[stable(feature = "rust1", since = "1.0.0")] fn default() -> BTreeSet { BTreeSet::new() } diff --git a/src/libcollections/fmt.rs b/src/libcollections/fmt.rs index a31ad6c109362..990575ebbb336 100644 --- a/src/libcollections/fmt.rs +++ b/src/libcollections/fmt.rs @@ -150,6 +150,7 @@ //! implement a method of the signature: //! //! ``` +//! # #![allow(dead_code)] //! # use std::fmt; //! # struct Foo; // our custom type //! # impl fmt::Display for Foo { @@ -174,7 +175,6 @@ //! like: //! //! ``` -//! #![feature(fmt_flags)] //! use std::fmt; //! //! #[derive(Debug)] @@ -288,6 +288,7 @@ //! off, some example usage is: //! //! ``` +//! # #![allow(unused_must_use)] //! use std::fmt; //! use std::io::{self, Write}; //! diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs index 670c32776df7b..54b98c6e17992 100644 --- a/src/libcollections/lib.rs +++ b/src/libcollections/lib.rs @@ -27,7 +27,7 @@ html_root_url = "https://doc.rust-lang.org/nightly/", html_playground_url = "https://play.rust-lang.org/", issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/", - test(no_crate_inject))] + test(no_crate_inject, attr(allow(unused_variables), deny(warnings))))] #![allow(trivial_casts)] #![cfg_attr(test, allow(deprecated))] // rand diff --git a/src/libcollections/linked_list.rs b/src/libcollections/linked_list.rs index fca7d3b26fc2e..8e6b0183d53d2 100644 --- a/src/libcollections/linked_list.rs +++ b/src/libcollections/linked_list.rs @@ -230,7 +230,6 @@ impl LinkedList { #[stable(feature = "rust1", since = "1.0.0")] impl Default for LinkedList { #[inline] - #[stable(feature = "rust1", since = "1.0.0")] fn default() -> LinkedList { LinkedList::new() } } diff --git a/src/libcollections/slice.rs b/src/libcollections/slice.rs index ea4830fc3e6ce..25ff1f1a82aac 100644 --- a/src/libcollections/slice.rs +++ b/src/libcollections/slice.rs @@ -160,7 +160,6 @@ mod hack { /// Allocating extension methods for slices. #[lang = "slice"] #[cfg(not(test))] -#[stable(feature = "rust1", since = "1.0.0")] impl [T] { /// Returns the number of elements in the slice. /// @@ -732,6 +731,8 @@ impl [T] { /// /// This is equivalent to `self.sort_by(|a, b| a.cmp(b))`. /// + /// This is a stable sort. + /// /// # Examples /// /// ```rust @@ -851,6 +852,7 @@ pub trait SliceConcatExt { /// # Examples /// /// ``` + /// # #![allow(deprecated)] /// assert_eq!(["hello", "world"].connect(" "), "hello world"); /// ``` #[stable(feature = "rust1", since = "1.0.0")] @@ -1066,6 +1068,18 @@ fn merge_sort(v: &mut [T], mut compare: F) where F: FnMut(&T, &T) -> Order let mut out = buf_tmp.offset(start as isize); let out_end = buf_tmp.offset(right_end_idx as isize); + // If left[last] <= right[0], they are already in order: + // fast-forward the left side (the right side is handled + // in the loop). + // If `right` is not empty then left is not empty, and + // the offsets are in bounds. + if right != right_end && compare(&*right.offset(-1), &*right) != Greater { + let elems = (right_start as usize - left as usize) / mem::size_of::(); + ptr::copy_nonoverlapping(&*left, out, elems); + out = out.offset(elems as isize); + left = right_start; + } + while out < out_end { // Either the left or the right run are exhausted, // so just copy the remainder from the other run diff --git a/src/libcollections/str.rs b/src/libcollections/str.rs index 21406354d81c3..a5013f4e75b18 100644 --- a/src/libcollections/str.rs +++ b/src/libcollections/str.rs @@ -153,7 +153,6 @@ impl ToOwned for str { /// Any string that can be represented as a slice. #[lang = "str"] #[cfg(not(test))] -#[stable(feature = "rust1", since = "1.0.0")] impl str { /// Returns the length of `self` in bytes. /// @@ -299,7 +298,7 @@ impl str { /// done by `.chars()` or `.char_indices()`. /// /// ``` - /// #![feature(str_char, core)] + /// #![feature(str_char)] /// /// use std::str::CharRange; /// @@ -359,7 +358,7 @@ impl str { /// done by `.chars().rev()` or `.char_indices()`. /// /// ``` - /// #![feature(str_char, core)] + /// #![feature(str_char)] /// /// use std::str::CharRange; /// @@ -635,6 +634,7 @@ impl str { /// # Examples /// /// ``` + /// # #![allow(deprecated)] /// let four_lines = "foo\r\nbar\n\r\nbaz"; /// let v: Vec<&str> = four_lines.lines_any().collect(); /// @@ -644,6 +644,7 @@ impl str { /// Leaving off the trailing character: /// /// ``` + /// # #![allow(deprecated)] /// let four_lines = "foo\r\nbar\n\r\nbaz\n"; /// let v: Vec<&str> = four_lines.lines_any().collect(); /// @@ -1180,8 +1181,6 @@ impl str { /// # Examples /// /// ``` - /// #![feature(str_match_indices)] - /// /// let v: Vec<_> = "abcXXXabcYYYabc".match_indices("abc").collect(); /// assert_eq!(v, [(0, "abc"), (6, "abc"), (12, "abc")]); /// @@ -1217,8 +1216,6 @@ impl str { /// # Examples /// /// ``` - /// #![feature(str_match_indices)] - /// /// let v: Vec<_> = "abcXXXabcYYYabc".rmatch_indices("abc").collect(); /// assert_eq!(v, [(12, "abc"), (6, "abc"), (0, "abc")]); /// diff --git a/src/libcollections/string.rs b/src/libcollections/string.rs index 96a28d3ee3ba3..804e798c600a5 100644 --- a/src/libcollections/string.rs +++ b/src/libcollections/string.rs @@ -55,6 +55,7 @@ impl String { /// # Examples /// /// ``` + /// # #![allow(unused_mut)] /// let mut s = String::new(); /// ``` #[inline] @@ -73,6 +74,20 @@ impl String { /// /// ``` /// let mut s = String::with_capacity(10); + /// + /// // The String contains no chars, even though it has capacity for more + /// assert_eq!(s.len(), 0); + /// + /// // These are all done without reallocating... + /// let cap = s.capacity(); + /// for i in 0..10 { + /// s.push('a'); + /// } + /// + /// assert_eq!(s.capacity(), cap); + /// + /// // ...but this may make the vector reallocate + /// s.push('a'); /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] @@ -963,7 +978,7 @@ impl PartialEq for String { macro_rules! impl_eq { ($lhs:ty, $rhs: ty) => { #[stable(feature = "rust1", since = "1.0.0")] - impl<'a> PartialEq<$rhs> for $lhs { + impl<'a, 'b> PartialEq<$rhs> for $lhs { #[inline] fn eq(&self, other: &$rhs) -> bool { PartialEq::eq(&self[..], &other[..]) } #[inline] @@ -971,7 +986,7 @@ macro_rules! impl_eq { } #[stable(feature = "rust1", since = "1.0.0")] - impl<'a> PartialEq<$lhs> for $rhs { + impl<'a, 'b> PartialEq<$lhs> for $rhs { #[inline] fn eq(&self, other: &$lhs) -> bool { PartialEq::eq(&self[..], &other[..]) } #[inline] @@ -984,28 +999,12 @@ macro_rules! impl_eq { impl_eq! { String, str } impl_eq! { String, &'a str } impl_eq! { Cow<'a, str>, str } +impl_eq! { Cow<'a, str>, &'b str } impl_eq! { Cow<'a, str>, String } -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a, 'b> PartialEq<&'b str> for Cow<'a, str> { - #[inline] - fn eq(&self, other: &&'b str) -> bool { PartialEq::eq(&self[..], &other[..]) } - #[inline] - fn ne(&self, other: &&'b str) -> bool { PartialEq::ne(&self[..], &other[..]) } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a, 'b> PartialEq> for &'b str { - #[inline] - fn eq(&self, other: &Cow<'a, str>) -> bool { PartialEq::eq(&self[..], &other[..]) } - #[inline] - fn ne(&self, other: &Cow<'a, str>) -> bool { PartialEq::ne(&self[..], &other[..]) } -} - #[stable(feature = "rust1", since = "1.0.0")] impl Default for String { #[inline] - #[stable(feature = "rust1", since = "1.0.0")] fn default() -> String { String::new() } diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index a22e66583c4a9..9153d624268ed 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -242,6 +242,7 @@ impl Vec { /// # Examples /// /// ``` + /// # #![allow(unused_mut)] /// let mut vec: Vec = Vec::new(); /// ``` #[inline] @@ -1220,8 +1221,7 @@ impl FromIterator for Vec { // expanded on this iteration in every case when the iterable is not // empty, but the loop in extend_desugared() is not going to see the // vector being full in the few subsequent loop iterations. - // So we get better branch prediction and the possibility to - // construct the vector with initial estimated capacity. + // So we get better branch prediction. let mut iterator = iterable.into_iter(); let mut vector = match iterator.next() { None => return Vec::new(), @@ -1384,10 +1384,6 @@ impl Ord for Vec { impl Drop for Vec { #[unsafe_destructor_blind_to_params] fn drop(&mut self) { - // NOTE: this is currently abusing the fact that ZSTs can't impl Drop. - // Or rather, that impl'ing Drop makes them not zero-sized. This is - // OK because exactly when this stops being a valid assumption, we - // don't need unsafe_no_drop_flag shenanigans anymore. if self.buf.unsafe_no_drop_flag_needs_drop() { unsafe { // The branch on needs_drop() is an -O1 performance optimization. @@ -1405,7 +1401,6 @@ impl Drop for Vec { #[stable(feature = "rust1", since = "1.0.0")] impl Default for Vec { - #[stable(feature = "rust1", since = "1.0.0")] fn default() -> Vec { Vec::new() } diff --git a/src/libcollections/vec_deque.rs b/src/libcollections/vec_deque.rs index 937ace00fdcca..67db0227cbee9 100644 --- a/src/libcollections/vec_deque.rs +++ b/src/libcollections/vec_deque.rs @@ -148,9 +148,9 @@ impl VecDeque { /// Copies a contiguous block of memory len long from src to dst #[inline] unsafe fn copy(&self, dst: usize, src: usize, len: usize) { - debug_assert!(dst + len <= self.cap(), "dst={} src={} len={} cap={}", dst, src, len, + debug_assert!(dst + len <= self.cap(), "cpy dst={} src={} len={} cap={}", dst, src, len, self.cap()); - debug_assert!(src + len <= self.cap(), "dst={} src={} len={} cap={}", dst, src, len, + debug_assert!(src + len <= self.cap(), "cpy dst={} src={} len={} cap={}", dst, src, len, self.cap()); ptr::copy( self.ptr().offset(src as isize), @@ -161,9 +161,9 @@ impl VecDeque { /// Copies a contiguous block of memory len long from src to dst #[inline] unsafe fn copy_nonoverlapping(&self, dst: usize, src: usize, len: usize) { - debug_assert!(dst + len <= self.cap(), "dst={} src={} len={} cap={}", dst, src, len, + debug_assert!(dst + len <= self.cap(), "cno dst={} src={} len={} cap={}", dst, src, len, self.cap()); - debug_assert!(src + len <= self.cap(), "dst={} src={} len={} cap={}", dst, src, len, + debug_assert!(src + len <= self.cap(), "cno dst={} src={} len={} cap={}", dst, src, len, self.cap()); ptr::copy_nonoverlapping( self.ptr().offset(src as isize), @@ -175,9 +175,11 @@ impl VecDeque { /// (abs(dst - src) + len) must be no larger than cap() (There must be at /// most one continuous overlapping region between src and dest). unsafe fn wrap_copy(&self, dst: usize, src: usize, len: usize) { - debug_assert!( - (if src <= dst { dst - src } else { src - dst }) + len <= self.cap(), - "dst={} src={} len={} cap={}", dst, src, len, self.cap()); + #[allow(dead_code)] + fn diff(a: usize, b: usize) -> usize {if a <= b {b - a} else {a - b}} + debug_assert!(cmp::min(diff(dst, src), + self.cap() - diff(dst, src)) + len <= self.cap(), + "wrc dst={} src={} len={} cap={}", dst, src, len, self.cap()); if src == dst || len == 0 { return } diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs index 1dc989018ad26..59b05c21d8005 100644 --- a/src/libcore/cell.rs +++ b/src/libcore/cell.rs @@ -76,6 +76,7 @@ //! a trait method that was originally defined to take `&self`. //! //! ``` +//! # #![allow(dead_code)] //! use std::cell::RefCell; //! //! struct Graph { @@ -125,6 +126,7 @@ //! } //! //! struct RcBox { +//! # #[allow(dead_code)] //! value: T, //! refcount: Cell //! } @@ -249,7 +251,6 @@ impl Clone for Cell { #[stable(feature = "rust1", since = "1.0.0")] impl Default for Cell { - #[stable(feature = "rust1", since = "1.0.0")] #[inline] fn default() -> Cell { Cell::new(Default::default()) @@ -468,7 +469,6 @@ impl Clone for RefCell { #[stable(feature = "rust1", since = "1.0.0")] impl Default for RefCell { - #[stable(feature = "rust1", since = "1.0.0")] #[inline] fn default() -> RefCell { RefCell::new(Default::default()) @@ -778,6 +778,7 @@ impl<'b, T: ?Sized> DerefMut for RefMut<'b, T> { /// use std::cell::UnsafeCell; /// use std::marker::Sync; /// +/// # #[allow(dead_code)] /// struct NotThreadSafe { /// value: UnsafeCell, /// } diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs index fa1f4727bc078..5458a7b9c38b0 100644 --- a/src/libcore/cmp.rs +++ b/src/libcore/cmp.rs @@ -140,8 +140,6 @@ impl Ordering { /// This method can be used to reverse a comparison: /// /// ``` - /// use std::cmp::Ordering; - /// /// let mut data: &mut [_] = &mut [2, 10, 5, 8]; /// /// // sort the array from largest to smallest. @@ -199,7 +197,6 @@ impl Eq for Ordering {} #[stable(feature = "rust1", since = "1.0.0")] impl Ord for Ordering { #[inline] - #[stable(feature = "rust1", since = "1.0.0")] fn cmp(&self, other: &Ordering) -> Ordering { (*self as i32).cmp(&(*other as i32)) } @@ -208,7 +205,6 @@ impl Ord for Ordering { #[stable(feature = "rust1", since = "1.0.0")] impl PartialOrd for Ordering { #[inline] - #[stable(feature = "rust1", since = "1.0.0")] fn partial_cmp(&self, other: &Ordering) -> Option { (*self as i32).partial_cmp(&(*other as i32)) } @@ -265,8 +261,6 @@ pub trait PartialOrd: PartialEq { /// # Examples /// /// ``` - /// use std::cmp::Ordering; - /// /// let result = 1.0 < 2.0; /// assert_eq!(result, true); /// diff --git a/src/libcore/default.rs b/src/libcore/default.rs index f7fda3d04fd61..12c4a5ca200ad 100644 --- a/src/libcore/default.rs +++ b/src/libcore/default.rs @@ -15,6 +15,7 @@ //! that define a set of options: //! //! ``` +//! # #[allow(dead_code)] //! struct SomeOptions { //! foo: i32, //! bar: f32, @@ -24,6 +25,7 @@ //! How can we define some default values? You can use `Default`: //! //! ``` +//! # #[allow(dead_code)] //! #[derive(Default)] //! struct SomeOptions { //! foo: i32, @@ -40,6 +42,7 @@ //! If you have your own type, you need to implement `Default` yourself: //! //! ``` +//! # #![allow(dead_code)] //! enum Kind { //! A, //! B, @@ -66,6 +69,7 @@ //! If you want to override a particular option, but still retain the other defaults: //! //! ``` +//! # #[allow(dead_code)] //! # #[derive(Default)] //! # struct SomeOptions { //! # foo: i32, @@ -88,6 +92,7 @@ use marker::Sized; /// # Examples /// /// ``` +/// # #[allow(dead_code)] /// #[derive(Default)] /// struct SomeOptions { /// foo: i32, @@ -114,6 +119,7 @@ pub trait Default: Sized { /// Making your own: /// /// ``` + /// # #[allow(dead_code)] /// enum Kind { /// A, /// B, @@ -133,7 +139,6 @@ macro_rules! default_impl { #[stable(feature = "rust1", since = "1.0.0")] impl Default for $t { #[inline] - #[stable(feature = "rust1", since = "1.0.0")] fn default() -> $t { $v } } } diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index f850cdbbd6090..8fe65e27c0308 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -328,7 +328,7 @@ impl<'a> Display for Arguments<'a> { /// /// impl fmt::Debug for Point { /// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { -/// write!(f, "({}, {})", self.x, self.y) +/// write!(f, "Point {{ x: {}, y: {} }}", self.x, self.y) /// } /// } /// diff --git a/src/libcore/hash/mod.rs b/src/libcore/hash/mod.rs index 4e038f455e1be..0899dc2884819 100644 --- a/src/libcore/hash/mod.rs +++ b/src/libcore/hash/mod.rs @@ -45,6 +45,7 @@ //! //! struct Person { //! id: u32, +//! # #[allow(dead_code)] //! name: String, //! phone: u64, //! } diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index ea4792bb495f6..a094bcd0192d2 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -334,6 +334,7 @@ extern "rust-intrinsic" { /// use std::mem; /// use std::ptr; /// + /// # #[allow(dead_code)] /// fn swap(x: &mut T, y: &mut T) { /// unsafe { /// // Give ourselves some scratch space to work with @@ -372,6 +373,7 @@ extern "rust-intrinsic" { /// ``` /// use std::ptr; /// + /// # #[allow(dead_code)] /// unsafe fn from_buf_raw(ptr: *const T, elts: usize) -> Vec { /// let mut dst = Vec::with_capacity(elts); /// dst.set_len(elts); diff --git a/src/libcore/iter.rs b/src/libcore/iter.rs index f1199919fcb0e..8558927e4acae 100644 --- a/src/libcore/iter.rs +++ b/src/libcore/iter.rs @@ -241,6 +241,7 @@ //! method calls a closure on each element it iterates over: //! //! ``` +//! # #![allow(unused_must_use)] //! let v = vec![1, 2, 3, 4, 5]; //! v.iter().map(|x| println!("{}", x)); //! ``` @@ -369,6 +370,24 @@ pub trait Iterator { /// `None` here means that either there is no known upper bound, or the /// upper bound is larger than `usize`. /// + /// # Implementation notes + /// + /// It is not enforced that an iterator implementation yields the declared + /// number of elements. A buggy iterator may yield less than the lower bound + /// or more than the upper bound of elements. + /// + /// `size_hint()` is primarily intended to be used for optimizations such as + /// reserving space for the elements of the iterator, but must not be + /// trusted to e.g. omit bounds checks in unsafe code. An incorrect + /// implementation of `size_hint()` should not lead to memory safety + /// violations. + /// + /// That said, the implementation should provide a correct estimation, + /// because otherwise it would be a violation of the trait's protocol. + /// + /// The default implementation returns `(0, None)` which is correct for any + /// iterator. + /// /// # Examples /// /// Basic usage: @@ -401,7 +420,7 @@ pub trait Iterator { /// /// ``` /// // an infinite iterator has no upper bound - /// let iter = (0..); + /// let iter = 0..; /// /// assert_eq!((0, None), iter.size_hint()); /// ``` @@ -691,6 +710,7 @@ pub trait Iterator { /// If you're doing some sort of side effect, prefer [`for`] to `map()`: /// /// ``` + /// # #![allow(unused_must_use)] /// // don't do this: /// (0..5).map(|x| println!("{}", x)); /// @@ -1565,6 +1585,8 @@ pub trait Iterator { /// as soon as it finds a `false`, given that no matter what else happens, /// the result will also be `false`. /// + /// An empty iterator returns `true`. + /// /// # Examples /// /// Basic usage: @@ -1613,6 +1635,8 @@ pub trait Iterator { /// as soon as it finds a `true`, given that no matter what else happens, /// the result will also be `true`. /// + /// An empty iterator returns `false`. + /// /// # Examples /// /// Basic usage: @@ -1705,7 +1729,7 @@ pub trait Iterator { /// Searches for an element in an iterator, returning its index. /// /// `position()` takes a closure that returns `true` or `false`. It applies - /// this closure to each element of the iterator, and if if one of them + /// this closure to each element of the iterator, and if one of them /// returns `true`, then `position()` returns `Some(index)`. If all of /// them return `false`, it returns `None`. /// @@ -1768,7 +1792,7 @@ pub trait Iterator { /// /// `rposition()` takes a closure that returns `true` or `false`. It applies /// this closure to each element of the iterator, starting from the end, - /// and if if one of them returns `true`, then `rposition()` returns + /// and if one of them returns `true`, then `rposition()` returns /// `Some(index)`. If all of them return `false`, it returns `None`. /// /// `rposition()` is short-circuting; in other words, it will stop @@ -2071,6 +2095,8 @@ pub trait Iterator { /// /// Takes each element, adds them together, and returns the result. /// + /// An empty iterator returns the zero value of the type. + /// /// # Examples /// /// Basic usage: @@ -2094,6 +2120,8 @@ pub trait Iterator { /// Iterates over the entire iterator, multiplying all the elements /// + /// An empty iterator returns the one value of the type. + /// /// # Examples /// /// ``` @@ -2669,7 +2697,7 @@ impl<'a, I: DoubleEndedIterator + ?Sized> DoubleEndedIterator for &'a mut I { /// /// ``` /// // a finite range knows exactly how many times it will iterate -/// let five = (0..5); +/// let five = 0..5; /// /// assert_eq!(5, five.len()); /// ``` @@ -2723,7 +2751,11 @@ pub trait ExactSizeIterator: Iterator { /// implementation, you can do so. See the [trait-level] docs for an /// example. /// + /// This function has the same safety guarantees as the [`size_hint()`] + /// function. + /// /// [trait-level]: trait.ExactSizeIterator.html + /// [`size_hint()`]: trait.Iterator.html#method.size_hint /// /// # Examples /// @@ -2731,7 +2763,7 @@ pub trait ExactSizeIterator: Iterator { /// /// ``` /// // a finite range knows exactly how many times it will iterate - /// let five = (0..5); + /// let five = 0..5; /// /// assert_eq!(5, five.len()); /// ``` @@ -3378,7 +3410,6 @@ impl Iterator for Peekable { #[stable(feature = "rust1", since = "1.0.0")] impl ExactSizeIterator for Peekable {} -#[stable(feature = "rust1", since = "1.0.0")] impl Peekable { /// Returns a reference to the next() value without advancing the iterator. /// diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 94408072932ea..df7b7c437c3cc 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -60,7 +60,7 @@ html_root_url = "https://doc.rust-lang.org/nightly/", html_playground_url = "https://play.rust-lang.org/", issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/")] -#![doc(test(no_crate_inject))] +#![doc(test(no_crate_inject, attr(allow(unused_variables), deny(warnings))))] #![no_core] #![allow(raw_pointer_derive)] diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs index 5b5f59d5ddbb7..bc8656b32b8e4 100644 --- a/src/libcore/macros.rs +++ b/src/libcore/macros.rs @@ -89,7 +89,7 @@ macro_rules! assert_eq { (left_val, right_val) => { if !(*left_val == *right_val) { panic!("assertion failed: `(left == right)` \ - (left: `{:?}`, right: `{:?}`)", *left_val, *right_val) + (left: `{:?}`, right: `{:?}`)", left_val, right_val) } } } @@ -247,6 +247,7 @@ macro_rules! writeln { /// Match arms: /// /// ``` +/// # #[allow(dead_code)] /// fn foo(x: Option) { /// match x { /// Some(n) if n >= 0 => println!("Some(Non-negative)"), @@ -260,6 +261,7 @@ macro_rules! writeln { /// Iterators: /// /// ``` +/// # #[allow(dead_code)] /// fn divide_by_three(x: u32) -> u32 { // one of the poorest implementations of x/3 /// for i in 0.. { /// if 3*i < i { panic!("u32 overflow"); } @@ -308,27 +310,27 @@ macro_rules! unreachable { /// /// ``` /// # trait Foo { -/// # fn foo(&self); /// # fn bar(&self); +/// # fn baz(&self); /// # } /// struct MyStruct; /// /// impl Foo for MyStruct { -/// fn foo(&self) { +/// fn bar(&self) { /// // implementation goes here /// } /// -/// fn bar(&self) { -/// // let's not worry about implementing bar() for now +/// fn baz(&self) { +/// // let's not worry about implementing baz() for now /// unimplemented!(); /// } /// } /// /// fn main() { /// let s = MyStruct; -/// s.foo(); +/// s.bar(); /// -/// // we aren't even using bar() yet, so this is fine. +/// // we aren't even using baz() yet, so this is fine. /// } /// ``` #[macro_export] diff --git a/src/libcore/marker.rs b/src/libcore/marker.rs index f6baf23b564b0..6e6ae61852787 100644 --- a/src/libcore/marker.rs +++ b/src/libcore/marker.rs @@ -23,7 +23,7 @@ use option::Option; use hash::Hash; use hash::Hasher; -/// Types able to be transferred across thread boundaries. +/// Types that can be transferred across thread boundaries. #[stable(feature = "rust1", since = "1.0.0")] #[lang = "send"] #[rustc_on_unimplemented = "`{Self}` cannot be sent between threads safely"] @@ -42,6 +42,7 @@ impl !Send for *mut T { } /// `?Sized` can be used to remove this bound if it is not appropriate. /// /// ``` +/// # #![allow(dead_code)] /// struct Foo(T); /// struct Bar(T); /// @@ -106,6 +107,7 @@ pub trait Unsize { /// `struct` can be `Copy`: /// /// ``` +/// # #[allow(dead_code)] /// struct Point { /// x: i32, /// y: i32, @@ -115,6 +117,7 @@ pub trait Unsize { /// A `struct` can be `Copy`, and `i32` is `Copy`, so therefore, `Point` is eligible to be `Copy`. /// /// ``` +/// # #![allow(dead_code)] /// # struct Point; /// struct PointList { /// points: Vec, @@ -303,6 +306,7 @@ macro_rules! impls{ /// ``` /// use std::marker::PhantomData; /// +/// # #[allow(dead_code)] /// struct Slice<'a, T:'a> { /// start: *const T, /// end: *const T, @@ -323,6 +327,7 @@ macro_rules! impls{ /// mismatches by enforcing types in the method implementations: /// /// ``` +/// # #![allow(dead_code)] /// # trait ResType { fn foo(&self); } /// # struct ParamType; /// # mod foreign_lib { @@ -382,16 +387,19 @@ mod impls { unsafe impl<'a, T: Send + ?Sized> Send for &'a mut T {} } -/// A marker trait indicates a type that can be reflected over. This -/// trait is implemented for all types. Its purpose is to ensure that -/// when you write a generic function that will employ reflection, -/// that must be reflected (no pun intended) in the generic bounds of -/// that function. Here is an example: +/// Types that can be reflected over. +/// +/// This trait is implemented for all types. Its purpose is to ensure +/// that when you write a generic function that will employ +/// reflection, that must be reflected (no pun intended) in the +/// generic bounds of that function. Here is an example: /// /// ``` /// #![feature(reflect_marker)] /// use std::marker::Reflect; /// use std::any::Any; +/// +/// # #[allow(dead_code)] /// fn foo(x: &T) { /// let any: &Any = x; /// if any.is::() { println!("u32"); } diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index a87d135e42592..2f01ea383400a 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -92,6 +92,7 @@ pub use intrinsics::transmute; /// use std::mem; /// use std::ptr; /// +/// # #[allow(dead_code)] /// fn swap(x: &mut T, y: &mut T) { /// unsafe { /// // Give ourselves some scratch space to work with @@ -151,6 +152,7 @@ pub fn size_of_val(val: &T) -> usize { /// # Examples /// /// ``` +/// # #![allow(deprecated)] /// use std::mem; /// /// assert_eq!(4, mem::min_align_of::()); @@ -167,6 +169,7 @@ pub fn min_align_of() -> usize { /// # Examples /// /// ``` +/// # #![allow(deprecated)] /// use std::mem; /// /// assert_eq!(4, mem::min_align_of_val(&5i32)); @@ -414,6 +417,7 @@ pub fn swap(x: &mut T, y: &mut T) { /// `self`, allowing it to be returned: /// /// ``` +/// # #![allow(dead_code)] /// use std::mem; /// # struct Buffer { buf: Vec } /// impl Buffer { diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index c397d02d2450e..3afc89c984142 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -141,6 +141,8 @@ macro_rules! int_impl { /// /// # Examples /// + /// Basic usage: + /// /// ``` /// assert_eq!(u32::from_str_radix("A", 16), Ok(10)); /// ``` @@ -153,7 +155,9 @@ macro_rules! int_impl { /// /// # Examples /// - /// ```rust + /// Basic usage: + /// + /// ``` /// let n = 0b01001100u8; /// /// assert_eq!(n.count_ones(), 3); @@ -166,7 +170,9 @@ macro_rules! int_impl { /// /// # Examples /// - /// ```rust + /// Basic usage: + /// + /// ``` /// let n = 0b01001100u8; /// /// assert_eq!(n.count_zeros(), 5); @@ -182,7 +188,9 @@ macro_rules! int_impl { /// /// # Examples /// - /// ```rust + /// Basic usage: + /// + /// ``` /// let n = 0b0101000u16; /// /// assert_eq!(n.leading_zeros(), 10); @@ -198,7 +206,9 @@ macro_rules! int_impl { /// /// # Examples /// - /// ```rust + /// Basic usage: + /// + /// ``` /// let n = 0b0101000u16; /// /// assert_eq!(n.trailing_zeros(), 3); @@ -214,7 +224,9 @@ macro_rules! int_impl { /// /// # Examples /// - /// ```rust + /// Basic usage: + /// + /// ``` /// let n = 0x0123456789ABCDEFu64; /// let m = 0x3456789ABCDEF012u64; /// @@ -232,7 +244,9 @@ macro_rules! int_impl { /// /// # Examples /// - /// ```rust + /// Basic usage: + /// + /// ``` /// let n = 0x0123456789ABCDEFu64; /// let m = 0xDEF0123456789ABCu64; /// @@ -248,7 +262,9 @@ macro_rules! int_impl { /// /// # Examples /// - /// ```rust + /// Basic usage: + /// + /// ``` /// let n = 0x0123456789ABCDEFu64; /// let m = 0xEFCDAB8967452301u64; /// @@ -267,7 +283,9 @@ macro_rules! int_impl { /// /// # Examples /// - /// ```rust + /// Basic usage: + /// + /// ``` /// let n = 0x0123456789ABCDEFu64; /// /// if cfg!(target_endian = "big") { @@ -289,7 +307,9 @@ macro_rules! int_impl { /// /// # Examples /// - /// ```rust + /// Basic usage: + /// + /// ``` /// let n = 0x0123456789ABCDEFu64; /// /// if cfg!(target_endian = "little") { @@ -311,7 +331,9 @@ macro_rules! int_impl { /// /// # Examples /// - /// ```rust + /// Basic usage: + /// + /// ``` /// let n = 0x0123456789ABCDEFu64; /// /// if cfg!(target_endian = "big") { @@ -333,7 +355,9 @@ macro_rules! int_impl { /// /// # Examples /// - /// ```rust + /// Basic usage: + /// + /// ``` /// let n = 0x0123456789ABCDEFu64; /// /// if cfg!(target_endian = "little") { @@ -353,7 +377,9 @@ macro_rules! int_impl { /// /// # Examples /// - /// ```rust + /// Basic usage: + /// + /// ``` /// assert_eq!(5u16.checked_add(65530), Some(65535)); /// assert_eq!(6u16.checked_add(65530), None); /// ``` @@ -368,7 +394,9 @@ macro_rules! int_impl { /// /// # Examples /// - /// ```rust + /// Basic usage: + /// + /// ``` /// assert_eq!((-127i8).checked_sub(1), Some(-128)); /// assert_eq!((-128i8).checked_sub(1), None); /// ``` @@ -383,7 +411,9 @@ macro_rules! int_impl { /// /// # Examples /// - /// ```rust + /// Basic usage: + /// + /// ``` /// assert_eq!(5u8.checked_mul(51), Some(255)); /// assert_eq!(5u8.checked_mul(52), None); /// ``` @@ -398,7 +428,9 @@ macro_rules! int_impl { /// /// # Examples /// - /// ```rust + /// Basic usage: + /// + /// ``` /// assert_eq!((-127i8).checked_div(-1), Some(127)); /// assert_eq!((-128i8).checked_div(-1), None); /// assert_eq!((1i8).checked_div(0), None); @@ -416,6 +448,15 @@ macro_rules! int_impl { /// Saturating integer addition. Computes `self + other`, saturating at /// the numeric bounds instead of overflowing. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// assert_eq!(100i8.saturating_add(1), 101); + /// assert_eq!(100i8.saturating_add(127), 127); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn saturating_add(self, other: Self) -> Self { @@ -428,6 +469,15 @@ macro_rules! int_impl { /// Saturating integer subtraction. Computes `self - other`, saturating /// at the numeric bounds instead of overflowing. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// assert_eq!(100i8.saturating_sub(127), -27); + /// assert_eq!((-100i8).saturating_sub(127), -128); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn saturating_sub(self, other: Self) -> Self { @@ -440,6 +490,15 @@ macro_rules! int_impl { /// Wrapping (modular) addition. Computes `self + other`, /// wrapping around at the boundary of the type. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// assert_eq!(100i8.wrapping_add(27), 127); + /// assert_eq!(100i8.wrapping_add(127), -29); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn wrapping_add(self, rhs: Self) -> Self { @@ -450,6 +509,15 @@ macro_rules! int_impl { /// Wrapping (modular) subtraction. Computes `self - other`, /// wrapping around at the boundary of the type. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// assert_eq!(0i8.wrapping_sub(127), -127); + /// assert_eq!((-2i8).wrapping_sub(127), 127); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn wrapping_sub(self, rhs: Self) -> Self { @@ -460,6 +528,15 @@ macro_rules! int_impl { /// Wrapping (modular) multiplication. Computes `self * /// other`, wrapping around at the boundary of the type. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// assert_eq!(10i8.wrapping_mul(12), 120); + /// assert_eq!(11i8.wrapping_mul(12), -124); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn wrapping_mul(self, rhs: Self) -> Self { @@ -477,6 +554,15 @@ macro_rules! int_impl { /// to `-MIN`, a positive value that is too large to represent /// in the type. In such a case, this function returns `MIN` /// itself. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// assert_eq!(100u8.wrapping_div(10), 10); + /// assert_eq!((-128i8).wrapping_div(-1), -128); + /// ``` #[stable(feature = "num_wrapping", since = "1.2.0")] #[inline(always)] pub fn wrapping_div(self, rhs: Self) -> Self { @@ -490,6 +576,15 @@ macro_rules! int_impl { /// implementation artifacts make `x % y` invalid for `MIN / /// -1` on a signed type (where `MIN` is the negative /// minimal value). In such a case, this function returns `0`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// assert_eq!(100i8.wrapping_rem(10), 0); + /// assert_eq!((-128i8).wrapping_rem(-1), 0); + /// ``` #[stable(feature = "num_wrapping", since = "1.2.0")] #[inline(always)] pub fn wrapping_rem(self, rhs: Self) -> Self { @@ -504,6 +599,15 @@ macro_rules! int_impl { /// negative minimal value for the type); this is a positive /// value that is too large to represent in the type. In such /// a case, this function returns `MIN` itself. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// assert_eq!(100i8.wrapping_neg(), -100); + /// assert_eq!((-128i8).wrapping_neg(), -128); + /// ``` #[stable(feature = "num_wrapping", since = "1.2.0")] #[inline(always)] pub fn wrapping_neg(self) -> Self { @@ -513,6 +617,15 @@ macro_rules! int_impl { /// Panic-free bitwise shift-left; yields `self << mask(rhs)`, /// where `mask` removes any high-order bits of `rhs` that /// would cause the shift to exceed the bitwidth of the type. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// assert_eq!(1u8.wrapping_shl(7), 128); + /// assert_eq!(1u8.wrapping_shl(8), 1); + /// ``` #[stable(feature = "num_wrapping", since = "1.2.0")] #[inline(always)] pub fn wrapping_shl(self, rhs: u32) -> Self { @@ -522,6 +635,15 @@ macro_rules! int_impl { /// Panic-free bitwise shift-left; yields `self >> mask(rhs)`, /// where `mask` removes any high-order bits of `rhs` that /// would cause the shift to exceed the bitwidth of the type. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// assert_eq!(128u8.wrapping_shr(7), 1); + /// assert_eq!(128u8.wrapping_shr(8), 128); + /// ``` #[stable(feature = "num_wrapping", since = "1.2.0")] #[inline(always)] pub fn wrapping_shr(self, rhs: u32) -> Self { @@ -532,6 +654,8 @@ macro_rules! int_impl { /// /// # Examples /// + /// Basic usage: + /// /// ``` /// let x: i32 = 2; // or any other integer type /// @@ -569,6 +693,15 @@ macro_rules! int_impl { /// `i32`, and attempting to calculate it will cause an overflow. This /// means that code in debug mode will trigger a panic on this case and /// optimized code will return `i32::min_value()` without a panic. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// assert_eq!(10i8.abs(), 10); + /// assert_eq!((-10i8).abs(), 10); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn abs(self) -> Self { @@ -587,6 +720,16 @@ macro_rules! int_impl { /// - `0` if the number is zero /// - `1` if the number is positive /// - `-1` if the number is negative + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// assert_eq!(10i8.signum(), 1); + /// assert_eq!(0i8.signum(), 0); + /// assert_eq!((-10i8).signum(), -1); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn signum(self) -> Self { @@ -599,12 +742,30 @@ macro_rules! int_impl { /// Returns `true` if `self` is positive and `false` if the number /// is zero or negative. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// assert!(10i8.is_positive()); + /// assert!(!(-10i8).is_positive()); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn is_positive(self) -> bool { self > 0 } /// Returns `true` if `self` is negative and `false` if the number /// is zero or positive. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// assert!((-10i8).is_negative()); + /// assert!(!10i8.is_negative()); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn is_negative(self) -> bool { self < 0 } @@ -759,7 +920,9 @@ macro_rules! uint_impl { /// /// # Examples /// - /// ```rust + /// Basic usage: + /// + /// ``` /// let n = 0b01001100u8; /// /// assert_eq!(n.count_ones(), 3); @@ -774,7 +937,9 @@ macro_rules! uint_impl { /// /// # Examples /// - /// ```rust + /// Basic usage: + /// + /// ``` /// let n = 0b01001100u8; /// /// assert_eq!(n.count_zeros(), 5); @@ -790,7 +955,9 @@ macro_rules! uint_impl { /// /// # Examples /// - /// ```rust + /// Basic usage: + /// + /// ``` /// let n = 0b0101000u16; /// /// assert_eq!(n.leading_zeros(), 10); @@ -825,7 +992,9 @@ macro_rules! uint_impl { /// /// # Examples /// - /// ```rust + /// Basic usage: + /// + /// ``` /// let n = 0b0101000u16; /// /// assert_eq!(n.trailing_zeros(), 3); @@ -855,7 +1024,9 @@ macro_rules! uint_impl { /// /// # Examples /// - /// ```rust + /// Basic usage: + /// + /// ``` /// let n = 0x0123456789ABCDEFu64; /// let m = 0x3456789ABCDEF012u64; /// @@ -875,7 +1046,9 @@ macro_rules! uint_impl { /// /// # Examples /// - /// ```rust + /// Basic usage: + /// + /// ``` /// let n = 0x0123456789ABCDEFu64; /// let m = 0xDEF0123456789ABCu64; /// @@ -893,7 +1066,9 @@ macro_rules! uint_impl { /// /// # Examples /// - /// ```rust + /// Basic usage: + /// + /// ``` /// let n = 0x0123456789ABCDEFu64; /// let m = 0xEFCDAB8967452301u64; /// @@ -912,7 +1087,9 @@ macro_rules! uint_impl { /// /// # Examples /// - /// ```rust + /// Basic usage: + /// + /// ``` /// let n = 0x0123456789ABCDEFu64; /// /// if cfg!(target_endian = "big") { @@ -934,7 +1111,9 @@ macro_rules! uint_impl { /// /// # Examples /// - /// ```rust + /// Basic usage: + /// + /// ``` /// let n = 0x0123456789ABCDEFu64; /// /// if cfg!(target_endian = "little") { @@ -956,7 +1135,9 @@ macro_rules! uint_impl { /// /// # Examples /// - /// ```rust + /// Basic usage: + /// + /// ``` /// let n = 0x0123456789ABCDEFu64; /// /// if cfg!(target_endian = "big") { @@ -978,7 +1159,9 @@ macro_rules! uint_impl { /// /// # Examples /// - /// ```rust + /// Basic usage: + /// + /// ``` /// let n = 0x0123456789ABCDEFu64; /// /// if cfg!(target_endian = "little") { @@ -998,7 +1181,9 @@ macro_rules! uint_impl { /// /// # Examples /// - /// ```rust + /// Basic usage: + /// + /// ``` /// assert_eq!(5u16.checked_add(65530), Some(65535)); /// assert_eq!(6u16.checked_add(65530), None); /// ``` @@ -1013,7 +1198,9 @@ macro_rules! uint_impl { /// /// # Examples /// - /// ```rust + /// Basic usage: + /// + /// ``` /// assert_eq!((-127i8).checked_sub(1), Some(-128)); /// assert_eq!((-128i8).checked_sub(1), None); /// ``` @@ -1028,7 +1215,9 @@ macro_rules! uint_impl { /// /// # Examples /// - /// ```rust + /// Basic usage: + /// + /// ``` /// assert_eq!(5u8.checked_mul(51), Some(255)); /// assert_eq!(5u8.checked_mul(52), None); /// ``` @@ -1043,7 +1232,9 @@ macro_rules! uint_impl { /// /// # Examples /// - /// ```rust + /// Basic usage: + /// + /// ``` /// assert_eq!((-127i8).checked_div(-1), Some(127)); /// assert_eq!((-128i8).checked_div(-1), None); /// assert_eq!((1i8).checked_div(0), None); @@ -1059,6 +1250,15 @@ macro_rules! uint_impl { /// Saturating integer addition. Computes `self + other`, saturating at /// the numeric bounds instead of overflowing. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// assert_eq!(100i8.saturating_add(1), 101); + /// assert_eq!(100i8.saturating_add(127), 127); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn saturating_add(self, other: Self) -> Self { @@ -1071,6 +1271,15 @@ macro_rules! uint_impl { /// Saturating integer subtraction. Computes `self - other`, saturating /// at the numeric bounds instead of overflowing. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// assert_eq!(100i8.saturating_sub(127), -27); + /// assert_eq!((-100i8).saturating_sub(127), -128); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn saturating_sub(self, other: Self) -> Self { @@ -1083,6 +1292,15 @@ macro_rules! uint_impl { /// Wrapping (modular) addition. Computes `self + other`, /// wrapping around at the boundary of the type. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// assert_eq!(100i8.wrapping_add(27), 127); + /// assert_eq!(100i8.wrapping_add(127), -29); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn wrapping_add(self, rhs: Self) -> Self { @@ -1093,6 +1311,15 @@ macro_rules! uint_impl { /// Wrapping (modular) subtraction. Computes `self - other`, /// wrapping around at the boundary of the type. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// assert_eq!(0i8.wrapping_sub(127), -127); + /// assert_eq!((-2i8).wrapping_sub(127), 127); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn wrapping_sub(self, rhs: Self) -> Self { @@ -1103,6 +1330,15 @@ macro_rules! uint_impl { /// Wrapping (modular) multiplication. Computes `self * /// other`, wrapping around at the boundary of the type. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// assert_eq!(10i8.wrapping_mul(12), 120); + /// assert_eq!(11i8.wrapping_mul(12), -124); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn wrapping_mul(self, rhs: Self) -> Self { @@ -1120,6 +1356,15 @@ macro_rules! uint_impl { /// to `-MIN`, a positive value that is too large to represent /// in the type. In such a case, this function returns `MIN` /// itself. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// assert_eq!(100u8.wrapping_div(10), 10); + /// assert_eq!((-128i8).wrapping_div(-1), -128); + /// ``` #[stable(feature = "num_wrapping", since = "1.2.0")] #[inline(always)] pub fn wrapping_div(self, rhs: Self) -> Self { @@ -1133,6 +1378,15 @@ macro_rules! uint_impl { /// implementation artifacts make `x % y` invalid for `MIN / /// -1` on a signed type (where `MIN` is the negative /// minimal value). In such a case, this function returns `0`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// assert_eq!(100i8.wrapping_rem(10), 0); + /// assert_eq!((-128i8).wrapping_rem(-1), 0); + /// ``` #[stable(feature = "num_wrapping", since = "1.2.0")] #[inline(always)] pub fn wrapping_rem(self, rhs: Self) -> Self { @@ -1147,6 +1401,15 @@ macro_rules! uint_impl { /// negative minimal value for the type); this is a positive /// value that is too large to represent in the type. In such /// a case, this function returns `MIN` itself. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// assert_eq!(100i8.wrapping_neg(), -100); + /// assert_eq!((-128i8).wrapping_neg(), -128); + /// ``` #[stable(feature = "num_wrapping", since = "1.2.0")] #[inline(always)] pub fn wrapping_neg(self) -> Self { @@ -1156,6 +1419,15 @@ macro_rules! uint_impl { /// Panic-free bitwise shift-left; yields `self << mask(rhs)`, /// where `mask` removes any high-order bits of `rhs` that /// would cause the shift to exceed the bitwidth of the type. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// assert_eq!(1u8.wrapping_shl(7), 128); + /// assert_eq!(1u8.wrapping_shl(8), 1); + /// ``` #[stable(feature = "num_wrapping", since = "1.2.0")] #[inline(always)] pub fn wrapping_shl(self, rhs: u32) -> Self { @@ -1165,6 +1437,15 @@ macro_rules! uint_impl { /// Panic-free bitwise shift-left; yields `self >> mask(rhs)`, /// where `mask` removes any high-order bits of `rhs` that /// would cause the shift to exceed the bitwidth of the type. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// assert_eq!(128u8.wrapping_shr(7), 1); + /// assert_eq!(128u8.wrapping_shr(8), 128); + /// ``` #[stable(feature = "num_wrapping", since = "1.2.0")] #[inline(always)] pub fn wrapping_shr(self, rhs: u32) -> Self { @@ -1175,7 +1456,9 @@ macro_rules! uint_impl { /// /// # Examples /// - /// ```rust + /// Basic usage: + /// + /// ``` /// assert_eq!(2i32.pow(4), 16); /// ``` #[stable(feature = "rust1", since = "1.0.0")] @@ -1207,6 +1490,15 @@ macro_rules! uint_impl { } /// Returns `true` if and only if `self == 2^k` for some `k`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// assert!(16u8.is_power_of_two()); + /// assert!(!10u8.is_power_of_two()); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn is_power_of_two(self) -> bool { @@ -1216,6 +1508,15 @@ macro_rules! uint_impl { /// Returns the smallest power of two greater than or equal to `self`. /// Unspecified behavior on overflow. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// assert_eq!(2u8.next_power_of_two(), 2); + /// assert_eq!(3u8.next_power_of_two(), 4); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn next_power_of_two(self) -> Self { @@ -1227,6 +1528,16 @@ macro_rules! uint_impl { /// Returns the smallest power of two greater than or equal to `n`. If /// the next power of two is greater than the type's maximum value, /// `None` is returned, otherwise the power of two is wrapped in `Some`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// assert_eq!(2u8.checked_next_power_of_two(), Some(2)); + /// assert_eq!(3u8.checked_next_power_of_two(), Some(4)); + /// assert_eq!(200u8.checked_next_power_of_two(), None); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn checked_next_power_of_two(self) -> Option { let npot = self.next_power_of_two(); @@ -1636,7 +1947,6 @@ macro_rules! impl_from { ($Small: ty, $Large: ty) => { #[stable(feature = "lossless_prim_conv", since = "1.5.0")] impl From<$Small> for $Large { - #[stable(feature = "lossless_prim_conv", since = "1.5.0")] #[inline] fn from(small: $Small) -> $Large { small as $Large diff --git a/src/libcore/ops.rs b/src/libcore/ops.rs index 582c091091fb2..7ad49eef8f711 100644 --- a/src/libcore/ops.rs +++ b/src/libcore/ops.rs @@ -542,11 +542,9 @@ macro_rules! neg_impl_core { ($id:ident => $body:expr, $($t:ty)*) => ($( #[stable(feature = "rust1", since = "1.0.0")] impl Neg for $t { - #[stable(feature = "rust1", since = "1.0.0")] type Output = $t; #[inline] - #[stable(feature = "rust1", since = "1.0.0")] fn neg(self) -> $t { let $id = self; $body } } @@ -949,6 +947,7 @@ shr_impl_all! { u8 u16 u32 u64 usize i8 i16 i32 i64 isize } /// } /// } /// +/// # #[allow(unused_assignments)] /// fn main() { /// let mut foo = Foo; /// foo += Foo; @@ -998,6 +997,7 @@ add_assign_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 } /// } /// } /// +/// # #[allow(unused_assignments)] /// fn main() { /// let mut foo = Foo; /// foo -= Foo; @@ -1047,6 +1047,7 @@ sub_assign_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 } /// } /// } /// +/// # #[allow(unused_assignments)] /// fn main() { /// let mut foo = Foo; /// foo *= Foo; @@ -1096,6 +1097,7 @@ mul_assign_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 } /// } /// } /// +/// # #[allow(unused_assignments)] /// fn main() { /// let mut foo = Foo; /// foo /= Foo; @@ -1145,6 +1147,7 @@ div_assign_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 } /// } /// } /// +/// # #[allow(unused_assignments)] /// fn main() { /// let mut foo = Foo; /// foo %= Foo; @@ -1194,6 +1197,7 @@ rem_assign_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 } /// } /// } /// +/// # #[allow(unused_assignments)] /// fn main() { /// let mut foo = Foo; /// foo &= Foo; @@ -1243,6 +1247,7 @@ bitand_assign_impl! { bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 } /// } /// } /// +/// # #[allow(unused_assignments)] /// fn main() { /// let mut foo = Foo; /// foo |= Foo; @@ -1292,6 +1297,7 @@ bitor_assign_impl! { bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 } /// } /// } /// +/// # #[allow(unused_assignments)] /// fn main() { /// let mut foo = Foo; /// foo ^= Foo; @@ -1341,6 +1347,7 @@ bitxor_assign_impl! { bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 } /// } /// } /// +/// # #[allow(unused_assignments)] /// fn main() { /// let mut foo = Foo; /// foo <<= Foo; @@ -1409,6 +1416,7 @@ shl_assign_impl_all! { u8 u16 u32 u64 usize i8 i16 i32 i64 isize } /// } /// } /// +/// # #[allow(unused_assignments)] /// fn main() { /// let mut foo = Foo; /// foo >>= Foo; diff --git a/src/libcore/option.rs b/src/libcore/option.rs index 8fce64bd561dc..7a3b83f68d0d8 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -275,6 +275,7 @@ impl Option { /// /// ``` /// #![feature(as_slice)] + /// # #![allow(deprecated)] /// /// let mut x = Some("Diamonds"); /// { @@ -756,7 +757,6 @@ impl Option { #[stable(feature = "rust1", since = "1.0.0")] impl Default for Option { #[inline] - #[stable(feature = "rust1", since = "1.0.0")] fn default() -> Option { None } } @@ -940,7 +940,6 @@ impl> FromIterator> for Option { /// assert!(res == Some(vec!(2, 3))); /// ``` #[inline] - #[stable(feature = "rust1", since = "1.0.0")] fn from_iter>>(iter: I) -> Option { // FIXME(#11084): This could be replaced with Iterator::scan when this // performance bug is closed. diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index 86292ce9703fb..6183034c08426 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -161,7 +161,6 @@ pub unsafe fn write(dst: *mut T, src: T) { intrinsics::move_val_init(&mut *dst, src) } -#[stable(feature = "rust1", since = "1.0.0")] #[lang = "const_ptr"] impl *const T { /// Returns true if the pointer is null. @@ -210,7 +209,6 @@ impl *const T { } } -#[stable(feature = "rust1", since = "1.0.0")] #[lang = "mut_ptr"] impl *mut T { /// Returns true if the pointer is null. diff --git a/src/libcore/result.rs b/src/libcore/result.rs index ee3bfacd731c3..6e1f120a1db48 100644 --- a/src/libcore/result.rs +++ b/src/libcore/result.rs @@ -16,6 +16,7 @@ //! and containing an error value. //! //! ``` +//! # #[allow(dead_code)] //! enum Result { //! Ok(T), //! Err(E) @@ -104,6 +105,7 @@ //! something like this: //! //! ```no_run +//! # #![allow(unused_must_use)] // \o/ //! use std::fs::File; //! use std::io::prelude::*; //! @@ -143,6 +145,7 @@ //! # use std::fs::File; //! # use std::io::prelude::*; //! # use std::io; +//! # #[allow(dead_code)] //! fn write_message() -> io::Result<()> { //! let mut file = try!(File::create("valuable_data.txt")); //! try!(file.write_all(b"important message")); @@ -160,6 +163,7 @@ //! It replaces this: //! //! ``` +//! # #![allow(dead_code)] //! use std::fs::File; //! use std::io::prelude::*; //! use std::io; @@ -189,6 +193,7 @@ //! With this: //! //! ``` +//! # #![allow(dead_code)] //! use std::fs::File; //! use std::io::prelude::*; //! use std::io; @@ -257,7 +262,6 @@ pub enum Result { // Type implementation ///////////////////////////////////////////////////////////////////////////// -#[stable(feature = "rust1", since = "1.0.0")] impl Result { ///////////////////////////////////////////////////////////////////////// // Querying the contained values @@ -423,6 +427,7 @@ impl Result { /// /// ``` /// #![feature(as_slice)] + /// # #![allow(deprecated)] /// /// let mut x: Result<&str, u32> = Ok("Gold"); /// { @@ -457,7 +462,7 @@ impl Result { // Transforming contained values ///////////////////////////////////////////////////////////////////////// - /// Maps a `Result` to `Result` by applying a function to an + /// Maps a `Result` to `Result` by applying a function to a /// contained `Ok` value, leaving an `Err` value untouched. /// /// This function can be used to compose the results of two functions. @@ -485,7 +490,7 @@ impl Result { } } - /// Maps a `Result` to `Result` by applying a function to an + /// Maps a `Result` to `Result` by applying a function to a /// contained `Err` value, leaving an `Ok` value untouched. /// /// This function can be used to pass through a successful result while handling @@ -708,7 +713,6 @@ impl Result { } } -#[stable(feature = "rust1", since = "1.0.0")] impl Result { /// Unwraps a result, yielding the content of an `Ok`. /// @@ -758,7 +762,6 @@ impl Result { } } -#[stable(feature = "rust1", since = "1.0.0")] impl Result { /// Unwraps a result, yielding the content of an `Err`. /// diff --git a/src/libcore/slice.rs b/src/libcore/slice.rs index a49d91ca03e5b..8ba4e9605c8e8 100644 --- a/src/libcore/slice.rs +++ b/src/libcore/slice.rs @@ -651,7 +651,6 @@ impl ops::IndexMut for [T] { #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T> Default for &'a [T] { - #[stable(feature = "rust1", since = "1.0.0")] fn default() -> &'a [T] { &[] } } diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index 7a78460a841bd..7954bc3a0bf53 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -142,8 +142,6 @@ impl Utf8Error { /// Basic usage: /// /// ``` - /// #![feature(utf8_error)] - /// /// use std::str; /// /// // some invalid bytes, in a vector @@ -1826,6 +1824,5 @@ fn char_range_at_raw(bytes: &[u8], i: usize) -> (u32, usize) { #[stable(feature = "rust1", since = "1.0.0")] impl<'a> Default for &'a str { - #[stable(feature = "rust1", since = "1.0.0")] fn default() -> &'a str { "" } } diff --git a/src/libcore/sync/atomic.rs b/src/libcore/sync/atomic.rs index 7225b4f6e0d2a..15f46a8602076 100644 --- a/src/libcore/sync/atomic.rs +++ b/src/libcore/sync/atomic.rs @@ -438,7 +438,6 @@ impl AtomicBool { } } -#[stable(feature = "rust1", since = "1.0.0")] impl AtomicIsize { /// Creates a new `AtomicIsize`. /// @@ -631,7 +630,6 @@ impl AtomicIsize { } } -#[stable(feature = "rust1", since = "1.0.0")] impl AtomicUsize { /// Creates a new `AtomicUsize`. /// diff --git a/src/libcore/tuple.rs b/src/libcore/tuple.rs index 6c5ff22232365..33098cfcf8b6d 100644 --- a/src/libcore/tuple.rs +++ b/src/libcore/tuple.rs @@ -105,7 +105,6 @@ macro_rules! tuple_impls { #[stable(feature = "rust1", since = "1.0.0")] impl<$($T:Default),+> Default for ($($T,)+) { - #[stable(feature = "rust1", since = "1.0.0")] #[inline] fn default() -> ($($T,)+) { ($({ let x: $T = Default::default(); x},)+) diff --git a/src/libflate/lib.rs b/src/libflate/lib.rs index 521dddae78ff9..513379b655844 100644 --- a/src/libflate/lib.rs +++ b/src/libflate/lib.rs @@ -23,12 +23,14 @@ #![crate_type = "dylib"] #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "https://doc.rust-lang.org/favicon.ico", - html_root_url = "https://doc.rust-lang.org/nightly/")] + html_root_url = "https://doc.rust-lang.org/nightly/", + test(attr(deny(warnings))))] #![feature(libc)] #![feature(staged_api)] #![feature(unique)] #![cfg_attr(test, feature(rustc_private, rand, vec_push_all))] +#![cfg_attr(stage0, allow(improper_ctypes))] #[cfg(test)] #[macro_use] diff --git a/src/libfmt_macros/lib.rs b/src/libfmt_macros/lib.rs index ed767ab1e5cf9..dc69f38e4e7d0 100644 --- a/src/libfmt_macros/lib.rs +++ b/src/libfmt_macros/lib.rs @@ -24,7 +24,8 @@ #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "https://doc.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/nightly/", - html_playground_url = "https://play.rust-lang.org/")] + html_playground_url = "https://play.rust-lang.org/", + test(attr(deny(warnings))))] #![feature(staged_api)] #![feature(unicode)] diff --git a/src/libgetopts/lib.rs b/src/libgetopts/lib.rs index ab34f2e48ca4a..f49451f827d62 100644 --- a/src/libgetopts/lib.rs +++ b/src/libgetopts/lib.rs @@ -30,9 +30,11 @@ //! file name following `-o`, and accepts both `-h` and `--help` as optional flags. //! //! ```{.rust} +//! #![feature(rustc_private)] +//! //! extern crate getopts; //! use getopts::{optopt,optflag,getopts,OptGroup,usage}; -//! use std::os; +//! use std::env; //! //! fn do_work(inp: &str, out: Option) { //! println!("{}", inp); @@ -44,11 +46,11 @@ //! //! fn print_usage(program: &str, opts: &[OptGroup]) { //! let brief = format!("Usage: {} [options]", program); -//! print!("{}", usage(brief, opts)); +//! print!("{}", usage(&brief, opts)); //! } //! //! fn main() { -//! let args: Vec = os::args(); +//! let args: Vec = env::args().collect(); //! //! let program = args[0].clone(); //! @@ -56,22 +58,22 @@ //! optopt("o", "", "set output file name", "NAME"), //! optflag("h", "help", "print this help menu") //! ]; -//! let matches = match getopts(args[1..], opts) { +//! let matches = match getopts(&args[1..], opts) { //! Ok(m) => { m } //! Err(f) => { panic!(f.to_string()) } //! }; //! if matches.opt_present("h") { -//! print_usage(program, opts); +//! print_usage(&program, opts); //! return; //! } //! let output = matches.opt_str("o"); //! let input = if !matches.free.is_empty() { //! matches.free[0].clone() //! } else { -//! print_usage(program, opts); +//! print_usage(&program, opts); //! return; //! }; -//! do_work(input, output); +//! do_work(&input, output); //! } //! ``` @@ -88,7 +90,8 @@ #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "https://doc.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/nightly/", - html_playground_url = "https://play.rust-lang.org/")] + html_playground_url = "https://play.rust-lang.org/", + test(attr(deny(warnings))))] #![deny(missing_docs)] #![feature(staged_api)] diff --git a/src/libgraphviz/lib.rs b/src/libgraphviz/lib.rs index b82b7d122b3ce..1fb54ed9071ab 100644 --- a/src/libgraphviz/lib.rs +++ b/src/libgraphviz/lib.rs @@ -47,7 +47,7 @@ //! which is cyclic. //! //! ```rust -//! #![feature(rustc_private, core, into_cow)] +//! #![feature(rustc_private, into_cow)] //! //! use std::borrow::IntoCow; //! use std::io::Write; @@ -150,9 +150,8 @@ //! entity `&sube`). //! //! ```rust -//! #![feature(rustc_private, core, into_cow)] +//! #![feature(rustc_private)] //! -//! use std::borrow::IntoCow; //! use std::io::Write; //! use graphviz as dot; //! @@ -174,10 +173,10 @@ //! dot::Id::new(format!("N{}", n)).unwrap() //! } //! fn node_label<'b>(&'b self, n: &Nd) -> dot::LabelText<'b> { -//! dot::LabelText::LabelStr(self.nodes[*n].as_slice().into_cow()) +//! dot::LabelText::LabelStr(self.nodes[*n].into()) //! } //! fn edge_label<'b>(&'b self, _: &Ed) -> dot::LabelText<'b> { -//! dot::LabelText::LabelStr("⊆".into_cow()) +//! dot::LabelText::LabelStr("⊆".into()) //! } //! } //! @@ -209,9 +208,8 @@ //! Hasse-diagram for the subsets of the set `{x, y}`. //! //! ```rust -//! #![feature(rustc_private, core, into_cow)] +//! #![feature(rustc_private)] //! -//! use std::borrow::IntoCow; //! use std::io::Write; //! use graphviz as dot; //! @@ -234,10 +232,10 @@ //! } //! fn node_label<'b>(&'b self, n: &Nd<'b>) -> dot::LabelText<'b> { //! let &(i, _) = n; -//! dot::LabelText::LabelStr(self.nodes[i].into_cow()) +//! dot::LabelText::LabelStr(self.nodes[i].into()) //! } //! fn edge_label<'b>(&'b self, _: &Ed<'b>) -> dot::LabelText<'b> { -//! dot::LabelText::LabelStr("⊆".into_cow()) +//! dot::LabelText::LabelStr("⊆".into()) //! } //! } //! @@ -283,7 +281,8 @@ #![crate_type = "dylib"] #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "https://doc.rust-lang.org/favicon.ico", - html_root_url = "https://doc.rust-lang.org/nightly/")] + html_root_url = "https://doc.rust-lang.org/nightly/", + test(attr(allow(unused_variables), deny(warnings))))] #![feature(into_cow)] #![feature(str_escape)] diff --git a/src/liblibc b/src/liblibc new file mode 160000 index 0000000000000..b1a043feeae3a --- /dev/null +++ b/src/liblibc @@ -0,0 +1 @@ +Subproject commit b1a043feeae3a67f45e75eaf10aa900a1f6832f9 diff --git a/src/liblibc/lib.rs b/src/liblibc/lib.rs deleted file mode 100644 index 13902d674379e..0000000000000 --- a/src/liblibc/lib.rs +++ /dev/null @@ -1,7184 +0,0 @@ -// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364) -#![cfg_attr(stage0, feature(custom_attribute))] -#![crate_name = "libc"] -#![crate_type = "rlib"] -#![cfg_attr(not(feature = "cargo-build"), - unstable(feature = "libc", reason = "use `libc` from crates.io", - issue = "27783"))] -#![cfg_attr(not(feature = "cargo-build"), feature(staged_api, no_std))] -#![cfg_attr(not(feature = "cargo-build"), staged_api)] -#![cfg_attr(not(feature = "cargo-build"), no_std)] -#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", - html_favicon_url = "https://doc.rust-lang.org/favicon.ico", - html_root_url = "https://doc.rust-lang.org/nightly/", - html_playground_url = "https://play.rust-lang.org/", - issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/")] -#![cfg_attr(test, feature(test))] -#![cfg_attr(not(feature = "cargo-build"), feature(cfg_target_vendor))] - -//! Bindings for the C standard library and other platform libraries -//! -//! **NOTE:** These are *architecture and libc* specific. On Linux, these -//! bindings are only correct for glibc. -//! -//! This module contains bindings to the C standard library, organized into -//! modules by their defining standard. Additionally, it contains some assorted -//! platform-specific definitions. For convenience, most functions and types -//! are reexported, so `use libc::*` will import the available C bindings as -//! appropriate for the target platform. The exact set of functions available -//! are platform specific. -//! -//! *Note:* Because these definitions are platform-specific, some may not appear -//! in the generated documentation. -//! -//! We consider the following specs reasonably normative with respect to -//! interoperating with the C standard library (libc/msvcrt): -//! -//! * ISO 9899:1990 ('C95', 'ANSI C', 'Standard C'), NA1, 1995. -//! * ISO 9899:1999 ('C99' or 'C9x'). -//! * ISO 9945:1988 / IEEE 1003.1-1988 ('POSIX.1'). -//! * ISO 9945:2001 / IEEE 1003.1-2001 ('POSIX:2001', 'SUSv3'). -//! * ISO 9945:2008 / IEEE 1003.1-2008 ('POSIX:2008', 'SUSv4'). -//! -//! Note that any reference to the 1996 revision of POSIX, or any revs between -//! 1990 (when '88 was approved at ISO) and 2001 (when the next actual -//! revision-revision happened), are merely additions of other chapters (1b and -//! 1c) outside the core interfaces. -//! -//! Despite having several names each, these are *reasonably* coherent -//! point-in-time, list-of-definition sorts of specs. You can get each under a -//! variety of names but will wind up with the same definition in each case. -//! -//! See standards(7) in linux-manpages for more details. -//! -//! Our interface to these libraries is complicated by the non-universality of -//! conformance to any of them. About the only thing universally supported is -//! the first (C95), beyond that definitions quickly become absent on various -//! platforms. -//! -//! We therefore wind up dividing our module-space up (mostly for the sake of -//! sanity while editing, filling-in-details and eliminating duplication) into -//! definitions common-to-all (held in modules named c95, c99, posix88, posix01 -//! and posix08) and definitions that appear only on *some* platforms (named -//! 'extra'). This would be things like significant OSX foundation kit, or Windows -//! library kernel32.dll, or various fancy glibc, Linux or BSD extensions. -//! -//! In addition to the per-platform 'extra' modules, we define a module of -//! 'common BSD' libc routines that never quite made it into POSIX but show up -//! in multiple derived systems. This is the 4.4BSD r2 / 1995 release, the final -//! one from Berkeley after the lawsuits died down and the CSRG dissolved. - -#![allow(bad_style, raw_pointer_derive)] -#![cfg_attr(target_os = "nacl", allow(unused_imports))] -#[cfg(feature = "cargo-build")] -extern crate std as core; - -#[cfg(test)] -extern crate std; -#[cfg(test)] -extern crate test; - -// Explicit export lists for the intersection (provided here) mean that -// you can write more-platform-agnostic code if you stick to just these -// symbols. - -pub use types::common::c95::*; -pub use types::common::c99::*; -pub use types::common::posix88::*; -pub use types::os::common::posix01::*; -pub use types::os::common::bsd44::*; -pub use types::os::arch::c95::*; -pub use types::os::arch::c99::*; -pub use types::os::arch::posix88::*; -pub use types::os::arch::posix01::*; -pub use types::os::arch::extra::*; - -pub use consts::os::c95::*; -pub use consts::os::posix88::*; -pub use consts::os::posix01::*; -pub use consts::os::posix08::*; -pub use consts::os::bsd44::*; -pub use consts::os::extra::*; - -pub use funcs::c95::ctype::*; -pub use funcs::c95::stdio::*; -pub use funcs::c95::stdlib::*; -pub use funcs::c95::string::*; -pub use funcs::posix88::fcntl::*; -pub use funcs::posix88::stat_::*; -pub use funcs::posix88::stdio::*; -pub use funcs::posix88::unistd::*; - -pub use funcs::bsd43::*; - -// But we also reexport most everything -// if you're interested in writing platform-specific code. - -// FIXME: This is a mess, but the design of this entire module needs to be -// reconsidered, so I'm not inclined to do better right now. As part of -// #11870 I removed all the pub globs here, leaving explicit reexports -// of everything that is actually used in-tree. -// -// So the following exports don't follow any particular plan. - -#[cfg(unix)] -pub use consts::os::sysconf::*; - -#[cfg(unix)] -pub use funcs::posix88::mman::*; -#[cfg(unix)] -pub use funcs::posix88::dirent::*; -#[cfg(unix)] -pub use funcs::posix88::net::*; -#[cfg(unix)] -pub use funcs::posix01::stat_::*; -#[cfg(unix)] -pub use funcs::posix01::unistd::*; -#[cfg(unix)] -pub use funcs::posix01::resource::*; - - -#[cfg(windows)] -pub use funcs::extra::kernel32::*; -#[cfg(windows)] -pub use funcs::extra::winsock::*; -#[cfg(windows)] -pub use funcs::extra::msvcrt::*; - -// On NaCl, these libraries are static. Thus it would be a Bad Idea to link them -// in when creating a test crate. -#[cfg(not(any(windows, - target_env = "musl", - all(target_os = "nacl", test), - all(target_os = "netbsd", target_vendor = "rumprun"))))] -#[link(name = "c")] -#[link(name = "m")] -extern { -} - -// When compiling rust with musl, statically include libc.a in liblibc.rlib. -// A cargo build of the libc crate will therefore automatically pick up the -// libc.a symbols because liblibc is transitively linked to by the stdlib. -#[cfg(all(target_env = "musl", not(feature = "cargo-build"), not(test)))] -#[link(name = "c", kind = "static")] -extern { -} - -#[cfg(all(windows, target_env = "msvc"))] -#[link(name = "kernel32")] -#[link(name = "shell32")] -#[link(name = "msvcrt")] -extern { -} - -// libnacl provides functions that require a trip through the IRT to work. -// ie: _exit, mmap, nanosleep, etc. Anything that would otherwise require a trip -// to the kernel. -#[cfg(all(target_os = "nacl", not(feature = "cargo-build"), not(test)))] -#[link(name = "nacl", kind = "static")] -extern { -} - -// pnaclmm provides a number of functions that the toolchain's Clang emits calls -// to when codegening atomic ops. All the functions within wrap various atomic -// operations. -// Yes, it could be linked by rustc explicitly, however by linking it here -// instead we save a bit of time where bins are involved (by not running the -// optimizations on the whole pnaclmm foreach binary built). -#[cfg(all(target_os = "nacl", not(feature = "cargo-build"), not(test)))] -#[link(name = "pnaclmm", kind = "static")] -extern { -} - -pub mod types { - - // Types tend to vary *per architecture* so we pull their definitions out - // into this module. - - // Standard types that are opaque or common, so are not per-target. - pub mod common { - pub mod c95 { - /// Type used to construct void pointers for use with C. - /// - /// This type is only useful as a pointer target. Do not use it as a - /// return type for FFI functions which have the `void` return type in - /// C. Use the unit type `()` or omit the return type instead. - /// - /// For LLVM to recognize the void pointer type and by extension - /// functions like malloc(), we need to have it represented as i8* - /// in LLVM bitcode. The enum used here ensures this. We need two - /// variants, because the compiler complains about the `repr` - /// attribute otherwise. - #[repr(u8)] - pub enum c_void { - #[doc(hidden)] - __variant1, - #[doc(hidden)] - __variant2, - } - - pub enum FILE {} - pub enum fpos_t {} - } - pub mod c99 { - pub type int8_t = i8; - pub type int16_t = i16; - pub type int32_t = i32; - pub type int64_t = i64; - pub type uint8_t = u8; - pub type uint16_t = u16; - pub type uint32_t = u32; - pub type uint64_t = u64; - } - pub mod posix88 { - pub enum DIR {} - pub enum dirent_t {} - } - pub mod posix01 { - } - pub mod posix08 { - } - pub mod bsd44 { - } - } - - // Standard types that are scalar but vary by OS and arch. - - #[cfg(any(target_os = "linux", target_os = "android", target_os = "nacl"))] - pub mod os { - pub mod common { - pub mod posix01 { - use types::common::c95::c_void; - use types::os::arch::c95::{c_char, c_ulong, size_t, time_t, suseconds_t, c_long}; - - #[cfg(not(target_os = "nacl"))] - pub type pthread_t = c_ulong; - #[cfg(target_os = "nacl")] - pub type pthread_t = *mut c_void; - pub type rlim_t = u64; - - #[repr(C)] - #[derive(Copy, Clone)] - pub struct glob_t { - pub gl_pathc: size_t, - pub gl_pathv: *mut *mut c_char, - pub gl_offs: size_t, - - pub __unused1: *mut c_void, - pub __unused2: *mut c_void, - pub __unused3: *mut c_void, - pub __unused4: *mut c_void, - pub __unused5: *mut c_void, - } - - #[repr(C)] - #[derive(Copy, Clone)] - pub struct timeval { - pub tv_sec: time_t, - pub tv_usec: suseconds_t, - } - - #[repr(C)] - #[derive(Copy, Clone)] - pub struct timespec { - pub tv_sec: time_t, - pub tv_nsec: c_long, - } - - pub enum timezone {} - - pub type sighandler_t = size_t; - - #[repr(C)] - #[derive(Copy, Clone)] - pub struct rlimit { - pub rlim_cur: rlim_t, - pub rlim_max: rlim_t, - } - } - - pub mod bsd43 { - use types::os::common::posix01::timeval; - use types::os::arch::c95::c_long; - // This is also specified in POSIX 2001, but only has two fields. All implementors - // implement BSD 4.3 version. - #[repr(C)] - #[derive(Copy, Clone)] - pub struct rusage { - pub ru_utime: timeval, - pub ru_stime: timeval, - pub ru_maxrss: c_long, - pub ru_ixrss: c_long, - pub ru_idrss: c_long, - pub ru_isrss: c_long, - pub ru_minflt: c_long, - pub ru_majflt: c_long, - pub ru_nswap: c_long, - pub ru_inblock: c_long, - pub ru_oublock: c_long, - pub ru_msgsnd: c_long, - pub ru_msgrcv: c_long, - pub ru_nsignals: c_long, - pub ru_nvcsw: c_long, - pub ru_nivcsw: c_long, - } - } - - pub mod bsd44 { - use types::common::c95::c_void; - use types::os::arch::c95::{c_char, c_int, c_uint}; - - pub type socklen_t = u32; - pub type sa_family_t = u16; - pub type in_port_t = u16; - pub type in_addr_t = u32; - #[repr(C)] - #[derive(Copy, Clone)] - pub struct sockaddr { - pub sa_family: sa_family_t, - pub sa_data: [u8; 14], - } - #[repr(C)] - #[derive(Copy)] - pub struct sockaddr_storage { - pub ss_family: sa_family_t, - pub __ss_align: isize, - #[cfg(target_pointer_width = "32")] - pub __ss_pad2: [u8; 128 - 2 * 4], - #[cfg(target_pointer_width = "64")] - pub __ss_pad2: [u8; 128 - 2 * 8], - } - impl ::core::clone::Clone for sockaddr_storage { - fn clone(&self) -> sockaddr_storage { - *self - } - } - #[repr(C)] - #[derive(Copy, Clone)] - pub struct sockaddr_in { - pub sin_family: sa_family_t, - pub sin_port: in_port_t, - pub sin_addr: in_addr, - pub sin_zero: [u8; 8], - } - #[repr(C)] - #[derive(Copy, Clone)] - pub struct in_addr { - pub s_addr: in_addr_t, - } - #[repr(C)] - #[derive(Copy, Clone)] - pub struct sockaddr_in6 { - pub sin6_family: sa_family_t, - pub sin6_port: in_port_t, - pub sin6_flowinfo: u32, - pub sin6_addr: in6_addr, - pub sin6_scope_id: u32, - } - #[repr(C)] - #[derive(Copy, Clone)] - pub struct in6_addr { - pub s6_addr: [u16; 8], - } - #[repr(C)] - #[derive(Copy, Clone)] - pub struct ip_mreq { - pub imr_multiaddr: in_addr, - pub imr_interface: in_addr, - } - #[repr(C)] - #[derive(Copy, Clone)] - pub struct ip6_mreq { - pub ipv6mr_multiaddr: in6_addr, - pub ipv6mr_interface: c_uint, - } - #[repr(C)] - #[derive(Copy, Clone)] - pub struct addrinfo { - pub ai_flags: c_int, - pub ai_family: c_int, - pub ai_socktype: c_int, - pub ai_protocol: c_int, - pub ai_addrlen: socklen_t, - - #[cfg(target_os = "linux")] - pub ai_addr: *mut sockaddr, - - #[cfg(target_os = "linux")] - pub ai_canonname: *mut c_char, - - #[cfg(any(target_os = "android", target_os = "nacl"))] - pub ai_canonname: *mut c_char, - - #[cfg(any(target_os = "android", target_os = "nacl"))] - pub ai_addr: *mut sockaddr, - - pub ai_next: *mut addrinfo, - } - #[repr(C)] - #[derive(Copy)] - pub struct sockaddr_un { - pub sun_family: sa_family_t, - pub sun_path: [c_char; 108], - } - impl ::core::clone::Clone for sockaddr_un { - fn clone(&self) -> sockaddr_un { - *self - } - } - - #[repr(C)] - #[derive(Copy, Clone)] - pub struct ifaddrs { - pub ifa_next: *mut ifaddrs, - pub ifa_name: *mut c_char, - pub ifa_flags: c_uint, - pub ifa_addr: *mut sockaddr, - pub ifa_netmask: *mut sockaddr, - pub ifa_ifu: *mut sockaddr, // FIXME This should be a union - pub ifa_data: *mut c_void, - } - - } - } - - #[cfg(any(target_arch = "x86", - target_arch = "arm", - target_arch = "mips", - target_arch = "mipsel", - target_arch = "powerpc", - target_arch = "le32"))] - pub mod arch { - pub mod c95 { - pub type c_char = i8; - pub type c_schar = i8; - pub type c_uchar = u8; - pub type c_short = i16; - pub type c_ushort = u16; - pub type c_int = i32; - pub type c_uint = u32; - pub type c_long = i32; - pub type c_ulong = u32; - pub type c_float = f32; - pub type c_double = f64; - pub type size_t = u32; - pub type ptrdiff_t = i32; - pub type clock_t = i32; - pub type time_t = i32; - pub type suseconds_t = i32; - pub type wchar_t = i32; - } - pub mod c99 { - pub type c_longlong = i64; - pub type c_ulonglong = u64; - pub type intptr_t = i32; - pub type uintptr_t = u32; - pub type intmax_t = i64; - pub type uintmax_t = u64; - } - #[cfg(any(target_arch = "mips", - target_arch = "mipsel", - target_arch = "powerpc", - target_arch = "le32", - all(any(target_arch = "arm", target_arch = "x86"), - not(target_os = "android"))))] - pub mod posix88 { - pub type off_t = i32; - pub type dev_t = u64; - pub type ino_t = u32; - pub type pid_t = i32; - pub type uid_t = u32; - pub type gid_t = u32; - pub type useconds_t = u32; - pub type mode_t = u32; - pub type ssize_t = i32; - } - #[cfg(all(any(target_arch = "arm", target_arch = "x86"), - target_os = "android"))] - pub mod posix88 { - pub type off_t = i32; - pub type dev_t = u32; - pub type ino_t = u32; - - pub type pid_t = i32; - pub type uid_t = u32; - pub type gid_t = u32; - pub type useconds_t = u32; - - pub type mode_t = u16; - pub type ssize_t = i32; - } - #[cfg(any(all(any(target_arch = "arm", target_arch = "x86"), - not(target_os = "android")), - target_arch = "le32", - target_arch = "powerpc"))] - pub mod posix01 { - use types::os::arch::c95::{c_short, c_long, time_t}; - use types::os::arch::posix88::{dev_t, gid_t, ino_t}; - use types::os::arch::posix88::{mode_t, off_t}; - use types::os::arch::posix88::uid_t; - - pub type nlink_t = u32; - pub type blksize_t = i32; - pub type blkcnt_t = i32; - - #[repr(C)] - #[derive(Copy, Clone)] - pub struct stat { - pub st_dev: dev_t, - pub __pad1: c_short, - pub st_ino: ino_t, - pub st_mode: mode_t, - pub st_nlink: nlink_t, - pub st_uid: uid_t, - pub st_gid: gid_t, - pub st_rdev: dev_t, - pub __pad2: c_short, - pub st_size: off_t, - pub st_blksize: blksize_t, - pub st_blocks: blkcnt_t, - pub st_atime: time_t, - pub st_atime_nsec: c_long, - pub st_mtime: time_t, - pub st_mtime_nsec: c_long, - pub st_ctime: time_t, - pub st_ctime_nsec: c_long, - pub __unused4: c_long, - pub __unused5: c_long, - } - - #[repr(C)] - #[derive(Copy, Clone)] - pub struct utimbuf { - pub actime: time_t, - pub modtime: time_t, - } - - #[repr(C)] - #[derive(Copy, Clone)] - pub struct pthread_attr_t { - pub __size: [u32; 9], - } - } - - #[cfg(all(any(target_arch = "arm", target_arch = "x86"), - target_os = "android"))] - pub mod posix01 { - use types::os::arch::c95::{c_uchar, c_uint, c_ulong, c_long, time_t}; - use types::os::arch::c99::{c_longlong, c_ulonglong}; - use types::os::arch::posix88::{uid_t, gid_t}; - - pub type nlink_t = u16; - pub type blksize_t = u32; - pub type blkcnt_t = u32; - - #[repr(C)] - #[derive(Copy, Clone)] - pub struct stat { - pub st_dev: c_ulonglong, - pub __pad0: [c_uchar; 4], - pub __st_ino: c_long, - pub st_mode: c_uint, - pub st_nlink: c_uint, - pub st_uid: uid_t, - pub st_gid: gid_t, - pub st_rdev: c_ulonglong, - pub __pad3: [c_uchar; 4], - pub st_size: c_longlong, - pub st_blksize: c_ulong, - pub st_blocks: c_ulonglong, - pub st_atime: time_t, - pub st_atime_nsec: c_ulong, - pub st_mtime: time_t, - pub st_mtime_nsec: c_ulong, - pub st_ctime: time_t, - pub st_ctime_nsec: c_ulong, - pub st_ino: c_ulonglong, - } - - #[repr(C)] - #[derive(Copy, Clone)] - pub struct utimbuf { - pub actime: time_t, - pub modtime: time_t, - } - - #[repr(C)] - #[derive(Copy, Clone)] - pub struct pthread_attr_t { - pub __size: [u32; 9], - } - } - - #[cfg(any(target_arch = "mips", - target_arch = "mipsel"))] - pub mod posix01 { - use types::os::arch::c95::{c_long, c_ulong, time_t}; - use types::os::arch::posix88::{gid_t, ino_t}; - use types::os::arch::posix88::{mode_t, off_t}; - use types::os::arch::posix88::uid_t; - - pub type nlink_t = u32; - pub type blksize_t = i32; - pub type blkcnt_t = i32; - - #[repr(C)] - #[derive(Copy, Clone)] - pub struct stat { - pub st_dev: c_ulong, - pub st_pad1: [c_long; 3], - pub st_ino: ino_t, - pub st_mode: mode_t, - pub st_nlink: nlink_t, - pub st_uid: uid_t, - pub st_gid: gid_t, - pub st_rdev: c_ulong, - pub st_pad2: [c_long; 2], - pub st_size: off_t, - pub st_pad3: c_long, - pub st_atime: time_t, - pub st_atime_nsec: c_long, - pub st_mtime: time_t, - pub st_mtime_nsec: c_long, - pub st_ctime: time_t, - pub st_ctime_nsec: c_long, - pub st_blksize: blksize_t, - pub st_blocks: blkcnt_t, - pub st_pad5: [c_long; 14], - } - - #[repr(C)] - #[derive(Copy, Clone)] - pub struct utimbuf { - pub actime: time_t, - pub modtime: time_t, - } - - #[repr(C)] - #[derive(Copy, Clone)] - pub struct pthread_attr_t { - pub __size: [u32; 9], - } - } - pub mod posix08 { - } - pub mod bsd44 { - } - pub mod extra { - use types::os::arch::c95::{c_ushort, c_int, c_uchar}; - #[repr(C)] - #[derive(Copy, Clone)] - pub struct sockaddr_ll { - pub sll_family: c_ushort, - pub sll_protocol: c_ushort, - pub sll_ifindex: c_int, - pub sll_hatype: c_ushort, - pub sll_pkttype: c_uchar, - pub sll_halen: c_uchar, - pub sll_addr: [c_uchar; 8], - } - } - - } - - #[cfg(any(target_arch = "x86_64", - target_arch = "aarch64"))] - pub mod arch { - pub mod c95 { - #[cfg(not(target_arch = "aarch64"))] - pub type c_char = i8; - #[cfg(target_arch = "aarch64")] - pub type c_char = u8; - pub type c_schar = i8; - pub type c_uchar = u8; - pub type c_short = i16; - pub type c_ushort = u16; - pub type c_int = i32; - pub type c_uint = u32; - pub type c_long = i64; - pub type c_ulong = u64; - pub type c_float = f32; - pub type c_double = f64; - pub type size_t = u64; - pub type ptrdiff_t = i64; - pub type clock_t = i64; - pub type time_t = i64; - pub type suseconds_t = i64; - #[cfg(not(target_arch = "aarch64"))] - pub type wchar_t = i32; - #[cfg(target_arch = "aarch64")] - pub type wchar_t = u32; - } - pub mod c99 { - pub type c_longlong = i64; - pub type c_ulonglong = u64; - pub type intptr_t = i64; - pub type uintptr_t = u64; - pub type intmax_t = i64; - pub type uintmax_t = u64; - } - pub mod posix88 { - pub type off_t = i64; - pub type dev_t = u64; - pub type ino_t = u64; - pub type pid_t = i32; - pub type uid_t = u32; - pub type gid_t = u32; - pub type useconds_t = u32; - pub type mode_t = u32; - pub type ssize_t = i64; - } - #[cfg(not(target_arch = "aarch64"))] - pub mod posix01 { - use types::os::arch::c95::{c_int, c_long, time_t}; - use types::os::arch::posix88::{dev_t, gid_t, ino_t}; - use types::os::arch::posix88::{mode_t, off_t}; - use types::os::arch::posix88::uid_t; - - pub type nlink_t = u64; - pub type blksize_t = i64; - pub type blkcnt_t = i64; - - #[repr(C)] - #[derive(Copy, Clone)] - pub struct stat { - pub st_dev: dev_t, - pub st_ino: ino_t, - pub st_nlink: nlink_t, - pub st_mode: mode_t, - pub st_uid: uid_t, - pub st_gid: gid_t, - pub __pad0: c_int, - pub st_rdev: dev_t, - pub st_size: off_t, - pub st_blksize: blksize_t, - pub st_blocks: blkcnt_t, - pub st_atime: time_t, - pub st_atime_nsec: c_long, - pub st_mtime: time_t, - pub st_mtime_nsec: c_long, - pub st_ctime: time_t, - pub st_ctime_nsec: c_long, - pub __unused: [c_long; 3], - } - - #[repr(C)] - #[derive(Copy, Clone)] - pub struct utimbuf { - pub actime: time_t, - pub modtime: time_t, - } - - #[repr(C)] - #[derive(Copy, Clone)] - pub struct pthread_attr_t { - pub __size: [u64; 7], - } - } - #[cfg(target_arch = "aarch64")] - pub mod posix01 { - use types::os::arch::c95::{c_int, c_long, time_t}; - use types::os::arch::posix88::{dev_t, gid_t, ino_t}; - use types::os::arch::posix88::{mode_t, off_t}; - use types::os::arch::posix88::uid_t; - - pub type nlink_t = u32; - pub type blksize_t = i32; - pub type blkcnt_t = i64; - - #[repr(C)] - #[derive(Copy, Clone)] - pub struct stat { - pub st_dev: dev_t, - pub st_ino: ino_t, - pub st_mode: mode_t, - pub st_nlink: nlink_t, - pub st_uid: uid_t, - pub st_gid: gid_t, - pub st_rdev: dev_t, - pub __pad1: dev_t, - pub st_size: off_t, - pub st_blksize: blksize_t, - pub __pad2: c_int, - pub st_blocks: blkcnt_t, - pub st_atime: time_t, - pub st_atime_nsec: c_long, - pub st_mtime: time_t, - pub st_mtime_nsec: c_long, - pub st_ctime: time_t, - pub st_ctime_nsec: c_long, - pub __unused: [c_int; 2], - } - - #[repr(C)] - #[derive(Copy, Clone)] - pub struct utimbuf { - pub actime: time_t, - pub modtime: time_t, - } - - #[repr(C)] - #[derive(Copy, Clone)] - pub struct pthread_attr_t { - pub __size: [u64; 8], - } - } - pub mod posix08 { - } - pub mod bsd44 { - } - pub mod extra { - use types::os::arch::c95::{c_ushort, c_int, c_uchar}; - #[derive(Copy, Clone)] - pub struct sockaddr_ll { - pub sll_family: c_ushort, - pub sll_protocol: c_ushort, - pub sll_ifindex: c_int, - pub sll_hatype: c_ushort, - pub sll_pkttype: c_uchar, - pub sll_halen: c_uchar, - pub sll_addr: [c_uchar; 8], - } - - } - } - } - - #[cfg(target_os = "freebsd")] - pub mod os { - pub mod common { - pub mod posix01 { - use types::common::c95::c_void; - use types::os::arch::c95::{c_char, c_int, size_t, time_t, suseconds_t, c_long}; - use types::os::arch::c99::uintptr_t; - - pub type pthread_t = uintptr_t; - pub type rlim_t = i64; - - #[repr(C)] - #[derive(Copy, Clone)] - pub struct glob_t { - pub gl_pathc: size_t, - pub __unused1: size_t, - pub gl_offs: size_t, - pub __unused2: c_int, - pub gl_pathv: *mut *mut c_char, - - pub __unused3: *mut c_void, - - pub __unused4: *mut c_void, - pub __unused5: *mut c_void, - pub __unused6: *mut c_void, - pub __unused7: *mut c_void, - pub __unused8: *mut c_void, - } - - #[repr(C)] - #[derive(Copy, Clone)] - pub struct timeval { - pub tv_sec: time_t, - pub tv_usec: suseconds_t, - } - - #[repr(C)] - #[derive(Copy, Clone)] - pub struct timespec { - pub tv_sec: time_t, - pub tv_nsec: c_long, - } - - pub enum timezone {} - - pub type sighandler_t = size_t; - - #[repr(C)] - #[derive(Copy, Clone)] - pub struct rlimit { - pub rlim_cur: rlim_t, - pub rlim_max: rlim_t, - } - } - - pub mod bsd43 { - use types::os::common::posix01::timeval; - use types::os::arch::c95::c_long; - #[repr(C)] - #[derive(Copy, Clone)] - pub struct rusage { - pub ru_utime: timeval, - pub ru_stime: timeval, - pub ru_maxrss: c_long, - pub ru_ixrss: c_long, - pub ru_idrss: c_long, - pub ru_isrss: c_long, - pub ru_minflt: c_long, - pub ru_majflt: c_long, - pub ru_nswap: c_long, - pub ru_inblock: c_long, - pub ru_oublock: c_long, - pub ru_msgsnd: c_long, - pub ru_msgrcv: c_long, - pub ru_nsignals: c_long, - pub ru_nvcsw: c_long, - pub ru_nivcsw: c_long, - } - } - - pub mod bsd44 { - use types::common::c95::c_void; - use types::os::arch::c95::{c_char, c_int, c_uint}; - - pub type socklen_t = u32; - pub type sa_family_t = u8; - pub type in_port_t = u16; - pub type in_addr_t = u32; - #[repr(C)] - #[derive(Copy, Clone)] - pub struct sockaddr { - pub sa_len: u8, - pub sa_family: sa_family_t, - pub sa_data: [u8; 14], - } - #[repr(C)] - #[derive(Copy)] - pub struct sockaddr_storage { - pub ss_len: u8, - pub ss_family: sa_family_t, - pub __ss_pad1: [u8; 6], - pub __ss_align: i64, - pub __ss_pad2: [u8; 112], - } - impl ::core::clone::Clone for sockaddr_storage { - fn clone(&self) -> sockaddr_storage { - *self - } - } - #[repr(C)] - #[derive(Copy, Clone)] - pub struct sockaddr_in { - pub sin_len: u8, - pub sin_family: sa_family_t, - pub sin_port: in_port_t, - pub sin_addr: in_addr, - pub sin_zero: [u8; 8], - } - #[repr(C)] - #[derive(Copy, Clone)] - pub struct in_addr { - pub s_addr: in_addr_t, - } - #[repr(C)] - #[derive(Copy, Clone)] - pub struct sockaddr_in6 { - pub sin6_len: u8, - pub sin6_family: sa_family_t, - pub sin6_port: in_port_t, - pub sin6_flowinfo: u32, - pub sin6_addr: in6_addr, - pub sin6_scope_id: u32, - } - #[repr(C)] - #[derive(Copy, Clone)] - pub struct in6_addr { - pub s6_addr: [u16; 8], - } - #[repr(C)] - #[derive(Copy, Clone)] - pub struct ip_mreq { - pub imr_multiaddr: in_addr, - pub imr_interface: in_addr, - } - #[repr(C)] - #[derive(Copy, Clone)] - pub struct ip6_mreq { - pub ipv6mr_multiaddr: in6_addr, - pub ipv6mr_interface: c_uint, - } - #[repr(C)] - #[derive(Copy, Clone)] - pub struct addrinfo { - pub ai_flags: c_int, - pub ai_family: c_int, - pub ai_socktype: c_int, - pub ai_protocol: c_int, - pub ai_addrlen: socklen_t, - pub ai_canonname: *mut c_char, - pub ai_addr: *mut sockaddr, - pub ai_next: *mut addrinfo, - } - #[repr(C)] - #[derive(Copy)] - pub struct sockaddr_un { - pub sun_len: u8, - pub sun_family: sa_family_t, - pub sun_path: [c_char; 104], - } - impl ::core::clone::Clone for sockaddr_un { - fn clone(&self) -> sockaddr_un { - *self - } - } - #[repr(C)] - #[derive(Copy, Clone)] - pub struct ifaddrs { - pub ifa_next: *mut ifaddrs, - pub ifa_name: *mut c_char, - pub ifa_flags: c_uint, - pub ifa_addr: *mut sockaddr, - pub ifa_netmask: *mut sockaddr, - pub ifa_dstaddr: *mut sockaddr, - pub ifa_data: *mut c_void, - } - - - } - } - - #[cfg(target_arch = "x86")] - pub mod arch { - pub mod c95 { - pub type c_char = i8; - pub type c_schar = i8; - pub type c_uchar = u8; - pub type c_short = i16; - pub type c_ushort = u16; - pub type c_int = i32; - pub type c_uint = u32; - pub type c_long = i32; - pub type c_ulong = u32; - pub type c_float = f32; - pub type c_double = f64; - pub type size_t = u32; - pub type ptrdiff_t = i32; - pub type clock_t = i32; - pub type time_t = i32; - pub type suseconds_t = i32; - pub type wchar_t = i32; - } - pub mod c99 { - pub type c_longlong = i64; - pub type c_ulonglong = u64; - pub type intptr_t = i32; - pub type uintptr_t = u32; - pub type intmax_t = i64; - pub type uintmax_t = u64; - } - pub mod posix88 { - pub type off_t = i64; - pub type dev_t = u32; - pub type ino_t = u32; - pub type pid_t = i32; - pub type uid_t = u32; - pub type gid_t = u32; - pub type useconds_t = u32; - pub type mode_t = u16; - pub type ssize_t = i32; - } - pub mod posix01 { - use types::common::c95::c_void; - use types::common::c99::{uint32_t, int32_t}; - use types::os::arch::c95::{c_long, time_t}; - use types::os::arch::posix88::{dev_t, gid_t, ino_t}; - use types::os::arch::posix88::{mode_t, off_t}; - use types::os::arch::posix88::uid_t; - - pub type nlink_t = u16; - pub type blksize_t = u32; - pub type blkcnt_t = i64; - pub type fflags_t = u32; - #[repr(C)] - #[derive(Copy, Clone)] - pub struct stat { - pub st_dev: dev_t, - pub st_ino: ino_t, - pub st_mode: mode_t, - pub st_nlink: nlink_t, - pub st_uid: uid_t, - pub st_gid: gid_t, - pub st_rdev: dev_t, - pub st_atime: time_t, - pub st_atime_nsec: c_long, - pub st_mtime: time_t, - pub st_mtime_nsec: c_long, - pub st_ctime: time_t, - pub st_ctime_nsec: c_long, - pub st_size: off_t, - pub st_blocks: blkcnt_t, - pub st_blksize: blksize_t, - pub st_flags: fflags_t, - pub st_gen: uint32_t, - pub st_lspare: int32_t, - pub st_birthtime: time_t, - pub st_birthtime_nsec: c_long, - pub __unused: [u8; 8], - } - - #[repr(C)] - #[derive(Copy, Clone)] - pub struct utimbuf { - pub actime: time_t, - pub modtime: time_t, - } - - pub type pthread_attr_t = *mut c_void; - } - pub mod posix08 { - } - pub mod bsd44 { - } - pub mod extra { - } - } - - #[cfg(target_arch = "x86_64")] - pub mod arch { - pub mod c95 { - pub type c_char = i8; - pub type c_schar = i8; - pub type c_uchar = u8; - pub type c_short = i16; - pub type c_ushort = u16; - pub type c_int = i32; - pub type c_uint = u32; - pub type c_long = i64; - pub type c_ulong = u64; - pub type c_float = f32; - pub type c_double = f64; - pub type size_t = u64; - pub type ptrdiff_t = i64; - pub type clock_t = i32; - pub type time_t = i64; - pub type suseconds_t = i64; - pub type wchar_t = i32; - } - pub mod c99 { - pub type c_longlong = i64; - pub type c_ulonglong = u64; - pub type intptr_t = i64; - pub type uintptr_t = u64; - pub type intmax_t = i64; - pub type uintmax_t = u64; - } - pub mod posix88 { - pub type off_t = i64; - pub type dev_t = u32; - pub type ino_t = u32; - pub type pid_t = i32; - pub type uid_t = u32; - pub type gid_t = u32; - pub type useconds_t = u32; - pub type mode_t = u16; - pub type ssize_t = i64; - } - pub mod posix01 { - use types::common::c95::c_void; - use types::common::c99::{uint32_t, int32_t}; - use types::os::arch::c95::{c_long, time_t}; - use types::os::arch::posix88::{dev_t, gid_t, ino_t}; - use types::os::arch::posix88::{mode_t, off_t}; - use types::os::arch::posix88::uid_t; - - pub type nlink_t = u16; - pub type blksize_t = u32; - pub type blkcnt_t = i64; - pub type fflags_t = u32; - #[repr(C)] - #[derive(Copy, Clone)] - pub struct stat { - pub st_dev: dev_t, - pub st_ino: ino_t, - pub st_mode: mode_t, - pub st_nlink: nlink_t, - pub st_uid: uid_t, - pub st_gid: gid_t, - pub st_rdev: dev_t, - pub st_atime: time_t, - pub st_atime_nsec: c_long, - pub st_mtime: time_t, - pub st_mtime_nsec: c_long, - pub st_ctime: time_t, - pub st_ctime_nsec: c_long, - pub st_size: off_t, - pub st_blocks: blkcnt_t, - pub st_blksize: blksize_t, - pub st_flags: fflags_t, - pub st_gen: uint32_t, - pub st_lspare: int32_t, - pub st_birthtime: time_t, - pub st_birthtime_nsec: c_long, - } - - #[repr(C)] - #[derive(Copy, Clone)] - pub struct utimbuf { - pub actime: time_t, - pub modtime: time_t, - } - - pub type pthread_attr_t = *mut c_void; - } - pub mod posix08 { - } - pub mod bsd44 { - } - pub mod extra { - } - } - } - - #[cfg(target_os = "dragonfly")] - pub mod os { - pub mod common { - pub mod posix01 { - use types::common::c95::c_void; - use types::os::arch::c95::{c_char, c_int, size_t, time_t, suseconds_t, c_long}; - use types::os::arch::c99::uintptr_t; - - pub type pthread_t = uintptr_t; - pub type rlim_t = i64; - - #[repr(C)] - #[derive(Copy, Clone)] - pub struct glob_t { - pub gl_pathc: size_t, - pub __unused1: size_t, - pub gl_offs: size_t, - pub __unused2: c_int, - pub gl_pathv: *mut *mut c_char, - - pub __unused3: *mut c_void, - - pub __unused4: *mut c_void, - pub __unused5: *mut c_void, - pub __unused6: *mut c_void, - pub __unused7: *mut c_void, - pub __unused8: *mut c_void, - } - - #[repr(C)] - #[derive(Copy, Clone)] - pub struct timeval { - pub tv_sec: time_t, - pub tv_usec: suseconds_t, - } - - #[repr(C)] - #[derive(Copy, Clone)] - pub struct timespec { - pub tv_sec: time_t, - pub tv_nsec: c_long, - } - - pub enum timezone {} - - pub type sighandler_t = size_t; - - #[repr(C)] - #[derive(Copy, Clone)] - pub struct rlimit { - pub rlim_cur: rlim_t, - pub rlim_max: rlim_t, - } - } - - pub mod bsd43 { - use types::os::common::posix01::timeval; - use types::os::arch::c95::c_long; - #[repr(C)] - #[derive(Copy, Clone)] - pub struct rusage { - pub ru_utime: timeval, - pub ru_stime: timeval, - pub ru_maxrss: c_long, - pub ru_ixrss: c_long, - pub ru_idrss: c_long, - pub ru_isrss: c_long, - pub ru_minflt: c_long, - pub ru_majflt: c_long, - pub ru_nswap: c_long, - pub ru_inblock: c_long, - pub ru_oublock: c_long, - pub ru_msgsnd: c_long, - pub ru_msgrcv: c_long, - pub ru_nsignals: c_long, - pub ru_nvcsw: c_long, - pub ru_nivcsw: c_long, - } - } - - pub mod bsd44 { - use types::common::c95::c_void; - use types::os::arch::c95::{c_char, c_int, c_uint}; - - pub type socklen_t = u32; - pub type sa_family_t = u8; - pub type in_port_t = u16; - pub type in_addr_t = u32; - #[repr(C)] - #[derive(Copy, Clone)] - pub struct sockaddr { - pub sa_len: u8, - pub sa_family: sa_family_t, - pub sa_data: [u8; 14], - } - #[repr(C)] - #[derive(Copy)] - pub struct sockaddr_storage { - pub ss_len: u8, - pub ss_family: sa_family_t, - pub __ss_pad1: [u8; 6], - pub __ss_align: i64, - pub __ss_pad2: [u8; 112], - } - impl ::core::clone::Clone for sockaddr_storage { - fn clone(&self) -> sockaddr_storage { - *self - } - } - #[repr(C)] - #[derive(Copy, Clone)] - pub struct sockaddr_in { - pub sin_len: u8, - pub sin_family: sa_family_t, - pub sin_port: in_port_t, - pub sin_addr: in_addr, - pub sin_zero: [u8; 8], - } - #[repr(C)] - #[derive(Copy, Clone)] - pub struct in_addr { - pub s_addr: in_addr_t, - } - #[repr(C)] - #[derive(Copy, Clone)] - pub struct sockaddr_in6 { - pub sin6_len: u8, - pub sin6_family: sa_family_t, - pub sin6_port: in_port_t, - pub sin6_flowinfo: u32, - pub sin6_addr: in6_addr, - pub sin6_scope_id: u32, - } - #[repr(C)] - #[derive(Copy, Clone)] - pub struct in6_addr { - pub s6_addr: [u16; 8], - } - #[repr(C)] - #[derive(Copy, Clone)] - pub struct ip_mreq { - pub imr_multiaddr: in_addr, - pub imr_interface: in_addr, - } - #[repr(C)] - #[derive(Copy, Clone)] - pub struct ip6_mreq { - pub ipv6mr_multiaddr: in6_addr, - pub ipv6mr_interface: c_uint, - } - #[repr(C)] - #[derive(Copy, Clone)] - pub struct addrinfo { - pub ai_flags: c_int, - pub ai_family: c_int, - pub ai_socktype: c_int, - pub ai_protocol: c_int, - pub ai_addrlen: socklen_t, - pub ai_canonname: *mut c_char, - pub ai_addr: *mut sockaddr, - pub ai_next: *mut addrinfo, - } - #[repr(C)] - #[derive(Copy)] - pub struct sockaddr_un { - pub sun_len: u8, - pub sun_family: sa_family_t, - pub sun_path: [c_char; 104], - } - impl ::core::clone::Clone for sockaddr_un { - fn clone(&self) -> sockaddr_un { - *self - } - } - #[repr(C)] - #[derive(Copy, Clone)] - pub struct ifaddrs { - pub ifa_next: *mut ifaddrs, - pub ifa_name: *mut c_char, - pub ifa_flags: c_uint, - pub ifa_addr: *mut sockaddr, - pub ifa_netmask: *mut sockaddr, - pub ifa_dstaddr: *mut sockaddr, - pub ifa_data: *mut c_void, - } - - } - } - - #[cfg(target_arch = "x86_64")] - pub mod arch { - pub mod c95 { - pub type c_char = i8; - pub type c_schar = i8; - pub type c_uchar = u8; - pub type c_short = i16; - pub type c_ushort = u16; - pub type c_int = i32; - pub type c_uint = u32; - pub type c_long = i64; - pub type c_ulong = u64; - pub type c_float = f32; - pub type c_double = f64; - pub type size_t = u64; - pub type ptrdiff_t = i64; - pub type clock_t = i32; - pub type time_t = i64; - pub type suseconds_t = i64; - pub type wchar_t = i32; - } - pub mod c99 { - pub type c_longlong = i64; - pub type c_ulonglong = u64; - pub type intptr_t = i64; - pub type uintptr_t = u64; - pub type intmax_t = i64; - pub type uintmax_t = u64; - } - pub mod posix88 { - pub type off_t = i64; - pub type dev_t = u32; - pub type pid_t = i32; - pub type uid_t = u32; - pub type gid_t = u32; - pub type useconds_t = u32; - pub type mode_t = u16; - pub type ssize_t = i64; - } - pub mod posix01 { - use types::common::c95::c_void; - use types::common::c99::{uint16_t, uint32_t, int32_t, uint64_t, int64_t}; - use types::os::arch::c95::{c_long, time_t}; - use types::os::arch::posix88::{dev_t, gid_t}; - use types::os::arch::posix88::{mode_t, off_t}; - use types::os::arch::posix88::uid_t; - - pub type nlink_t = u16; - pub type blksize_t = uint32_t; - pub type ino_t = uint64_t; - pub type blkcnt_t = i64; - pub type fflags_t = u32; - - #[repr(C)] - #[derive(Copy, Clone)] - pub struct stat { - pub st_ino: ino_t, - pub st_nlink: nlink_t, - pub st_dev: dev_t, - pub st_mode: mode_t, - pub st_padding1: uint16_t, - pub st_uid: uid_t, - pub st_gid: gid_t, - pub st_rdev: dev_t, - pub st_atime: time_t, - pub st_atime_nsec: c_long, - pub st_mtime: time_t, - pub st_mtime_nsec: c_long, - pub st_ctime: time_t, - pub st_ctime_nsec: c_long, - pub st_size: off_t, - pub st_blocks: blkcnt_t, - pub st_blksize: blksize_t, - pub st_flags: fflags_t, - pub st_gen: uint32_t, - pub st_lspare: int32_t, - pub st_qspare1: int64_t, - pub st_qspare2: int64_t, - } - #[repr(C)] - #[derive(Copy, Clone)] - pub struct utimbuf { - pub actime: time_t, - pub modtime: time_t, - } - - pub type pthread_attr_t = *mut c_void; - } - pub mod posix08 { - } - pub mod bsd44 { - } - pub mod extra { - } - } - } - - #[cfg(any(target_os = "bitrig", target_os = "netbsd", target_os ="openbsd"))] - pub mod os { - pub mod common { - pub mod posix01 { - use types::common::c95::c_void; - use types::os::arch::c95::{c_char, c_int, size_t, time_t, suseconds_t, c_long}; - use types::os::arch::c99::uintptr_t; - - pub type pthread_t = uintptr_t; - pub type rlim_t = u64; - - #[cfg(target_os = "bitrig")] - #[repr(C)] - #[derive(Copy, Clone)] - pub struct glob_t { - pub gl_pathc: c_int, - pub gl_matchc: c_int, - pub gl_offs: c_int, - pub gl_flags: c_int, - pub gl_pathv: *mut *mut c_char, - pub __unused1: *mut c_void, - pub __unused2: *mut c_void, - pub __unused3: *mut c_void, - pub __unused4: *mut c_void, - pub __unused5: *mut c_void, - pub __unused6: *mut c_void, - pub __unused7: *mut c_void, - } - - #[cfg(target_os = "netbsd")] - #[repr(C)] - #[derive(Copy, Clone)] - pub struct glob_t { - pub gl_pathc: size_t, - pub gl_matchc: size_t, - pub gl_offs: size_t, - pub gl_flags: c_int, - pub gl_pathv: *mut *mut c_char, - pub __unused1: *mut c_void, - pub __unused2: *mut c_void, - pub __unused3: *mut c_void, - pub __unused4: *mut c_void, - pub __unused5: *mut c_void, - pub __unused6: *mut c_void, - } - - #[cfg(target_os = "openbsd")] - #[repr(C)] - #[derive(Copy, Clone)] - pub struct glob_t { - pub gl_pathc: c_int, - pub __unused1: c_int, - pub gl_offs: c_int, - pub __unused2: c_int, - pub gl_pathv: *mut *mut c_char, - - pub __unused3: *mut c_void, - - pub __unused4: *mut c_void, - pub __unused5: *mut c_void, - pub __unused6: *mut c_void, - pub __unused7: *mut c_void, - pub __unused8: *mut c_void, - pub __unused9: *mut c_void, - } - - #[repr(C)] - #[derive(Copy, Clone)] - pub struct timeval { - pub tv_sec: time_t, - pub tv_usec: suseconds_t, - } - - #[repr(C)] - #[derive(Copy, Clone)] - pub struct timespec { - pub tv_sec: time_t, - pub tv_nsec: c_long, - } - - pub enum timezone {} - - pub type sighandler_t = size_t; - - #[repr(C)] - #[derive(Copy, Clone)] - pub struct rlimit { - pub rlim_cur: rlim_t, - pub rlim_max: rlim_t, - } - } - - pub mod bsd43 { - use types::os::common::posix01::timeval; - use types::os::arch::c95::c_long; - #[repr(C)] - #[derive(Copy, Clone)] - pub struct rusage { - pub ru_utime: timeval, - pub ru_stime: timeval, - pub ru_maxrss: c_long, - pub ru_ixrss: c_long, - pub ru_idrss: c_long, - pub ru_isrss: c_long, - pub ru_minflt: c_long, - pub ru_majflt: c_long, - pub ru_nswap: c_long, - pub ru_inblock: c_long, - pub ru_oublock: c_long, - pub ru_msgsnd: c_long, - pub ru_msgrcv: c_long, - pub ru_nsignals: c_long, - pub ru_nvcsw: c_long, - pub ru_nivcsw: c_long, - } - } - - pub mod bsd44 { - use types::common::c95::c_void; - use types::os::arch::c95::{c_char, c_int, c_uint}; - - pub type socklen_t = u32; - pub type sa_family_t = u8; - pub type in_port_t = u16; - pub type in_addr_t = u32; - #[repr(C)] - #[derive(Copy, Clone)] - pub struct sockaddr { - pub sa_len: u8, - pub sa_family: sa_family_t, - pub sa_data: [u8; 14], - } - #[repr(C)] - #[derive(Copy)] - pub struct sockaddr_storage { - pub ss_len: u8, - pub ss_family: sa_family_t, - pub __ss_pad1: [u8; 6], - pub __ss_pad2: i64, - pub __ss_pad3: [u8; 240], - } - impl ::core::clone::Clone for sockaddr_storage { - fn clone(&self) -> sockaddr_storage { - *self - } - } - #[repr(C)] - #[derive(Copy, Clone)] - pub struct sockaddr_in { - pub sin_len: u8, - pub sin_family: sa_family_t, - pub sin_port: in_port_t, - pub sin_addr: in_addr, - pub sin_zero: [u8; 8], - } - #[repr(C)] - #[derive(Copy, Clone)] - pub struct in_addr { - pub s_addr: in_addr_t, - } - #[repr(C)] - #[derive(Copy, Clone)] - pub struct sockaddr_in6 { - pub sin6_len: u8, - pub sin6_family: sa_family_t, - pub sin6_port: in_port_t, - pub sin6_flowinfo: u32, - pub sin6_addr: in6_addr, - pub sin6_scope_id: u32, - } - #[repr(C)] - #[derive(Copy, Clone)] - pub struct in6_addr { - pub s6_addr: [u16; 8], - } - #[repr(C)] - #[derive(Copy, Clone)] - pub struct ip_mreq { - pub imr_multiaddr: in_addr, - pub imr_interface: in_addr, - } - #[repr(C)] - #[derive(Copy, Clone)] - pub struct ip6_mreq { - pub ipv6mr_multiaddr: in6_addr, - pub ipv6mr_interface: c_uint, - } - #[cfg(not(target_os = "netbsd"))] - #[repr(C)] - #[derive(Copy, Clone)] - pub struct addrinfo { - pub ai_flags: c_int, - pub ai_family: c_int, - pub ai_socktype: c_int, - pub ai_protocol: c_int, - pub ai_addrlen: socklen_t, - pub ai_addr: *mut sockaddr, - pub ai_canonname: *mut c_char, - pub ai_next: *mut addrinfo, - } - #[cfg(target_os = "netbsd")] - #[repr(C)] - #[derive(Copy, Clone)] - pub struct addrinfo { - pub ai_flags: c_int, - pub ai_family: c_int, - pub ai_socktype: c_int, - pub ai_protocol: c_int, - pub ai_addrlen: socklen_t, - pub ai_canonname: *mut c_char, - pub ai_addr: *mut sockaddr, - pub ai_next: *mut addrinfo, - } - #[repr(C)] - #[derive(Copy)] - pub struct sockaddr_un { - pub sun_len: u8, - pub sun_family: sa_family_t, - pub sun_path: [c_char; 104], - } - impl ::core::clone::Clone for sockaddr_un { - fn clone(&self) -> sockaddr_un { - *self - } - } - #[repr(C)] - #[derive(Copy, Clone)] - pub struct ifaddrs { - pub ifa_next: *mut ifaddrs, - pub ifa_name: *mut c_char, - pub ifa_flags: c_uint, - pub ifa_addr: *mut sockaddr, - pub ifa_netmask: *mut sockaddr, - pub ifa_dstaddr: *mut sockaddr, - pub ifa_data: *mut c_void, - } - } - } - - #[cfg(target_arch = "x86_64")] - pub mod arch { - pub mod c95 { - pub type c_char = i8; - pub type c_schar = i8; - pub type c_uchar = u8; - pub type c_short = i16; - pub type c_ushort = u16; - pub type c_int = i32; - pub type c_uint = u32; - pub type c_long = i64; - pub type c_ulong = u64; - pub type c_float = f32; - pub type c_double = f64; - pub type size_t = u64; - pub type ptrdiff_t = i64; - pub type clock_t = i64; - pub type time_t = i64; - pub type suseconds_t = i64; - pub type wchar_t = i32; - } - pub mod c99 { - pub type c_longlong = i64; - pub type c_ulonglong = u64; - pub type intptr_t = i64; - pub type uintptr_t = u64; - pub type intmax_t = i64; - pub type uintmax_t = u64; - } - pub mod posix88 { - use types::os::arch::c95::c_long; - pub type off_t = i64; - pub type dev_t = i32; - pub type pid_t = i32; - pub type uid_t = u32; - pub type gid_t = u32; - pub type useconds_t = u32; - pub type mode_t = u32; - pub type ssize_t = c_long; - } - pub mod posix01 { - use types::common::c95::c_void; - use types::common::c99::{uint32_t, uint64_t}; - use types::os::arch::c95::{c_long, time_t}; - use types::os::arch::posix88::{dev_t, gid_t}; - use types::os::arch::posix88::{mode_t, off_t}; - use types::os::arch::posix88::uid_t; - #[cfg(target_os = "netbsd")] - use types::os::arch::c95::{c_int, c_uint}; - - pub type nlink_t = uint32_t; - pub type blksize_t = uint32_t; - pub type ino_t = uint64_t; - pub type blkcnt_t = i64; - pub type fflags_t = u32; // type not declared, but struct stat have u_int32_t - - #[cfg(not(target_os = "netbsd"))] - #[repr(C)] - #[derive(Copy, Clone)] - pub struct stat { - pub st_mode: mode_t, - pub st_dev: dev_t, - pub st_ino: ino_t, - pub st_nlink: nlink_t, - pub st_uid: uid_t, - pub st_gid: gid_t, - pub st_rdev: dev_t, - pub st_atime: time_t, - pub st_atime_nsec: c_long, - pub st_mtime: time_t, - pub st_mtime_nsec: c_long, - pub st_ctime: time_t, - pub st_ctime_nsec: c_long, - pub st_size: off_t, - pub st_blocks: blkcnt_t, - pub st_blksize: blksize_t, - pub st_flags: fflags_t, - pub st_gen: uint32_t, - pub st_birthtime: time_t, - pub st_birthtime_nsec: c_long, - } - #[cfg(target_os = "netbsd")] - #[repr(C)] - #[derive(Copy, Clone)] - pub struct stat { - pub st_mode: mode_t, - pub st_dev: dev_t, - pub st_ino: ino_t, - pub st_nlink: nlink_t, - pub st_uid: uid_t, - pub st_gid: gid_t, - pub st_rdev: dev_t, - pub st_atime: time_t, - pub st_atime_nsec: c_long, - pub st_mtime: time_t, - pub st_mtime_nsec: c_long, - pub st_ctime: time_t, - pub st_ctime_nsec: c_long, - pub st_birthtime: time_t, - pub st_birthtime_nsec: c_long, - pub st_size: off_t, - pub st_blocks: blkcnt_t, - pub st_blksize: blksize_t, - pub st_flags: fflags_t, - pub st_gen: uint32_t, - st_spare: [uint32_t; 2], - } - - #[repr(C)] - #[derive(Copy, Clone)] - pub struct utimbuf { - pub actime: time_t, - pub modtime: time_t, - } - - #[cfg(not(target_os = "netbsd"))] - pub type pthread_attr_t = *mut c_void; - #[cfg(target_os = "netbsd")] - #[repr(C)] - #[derive(Copy, Clone)] - pub struct pthread_attr_t { - pta_magic: c_uint, - pta_flags: c_int, - pta_private: *mut c_void, - } - } - pub mod posix08 { - } - pub mod bsd44 { - } - pub mod extra { - } - } - } - - #[cfg(target_os = "windows")] - pub mod os { - pub mod common { - pub mod posix01 { - use types::os::arch::c95::{c_short, time_t, c_long}; - use types::os::arch::extra::{int64, time64_t}; - use types::os::arch::posix88::{dev_t, ino_t}; - - // pub Note: this is the struct called stat64 in Windows. Not stat, - // nor stati64. - #[repr(C)] - #[derive(Copy, Clone)] - pub struct stat { - pub st_dev: dev_t, - pub st_ino: ino_t, - pub st_mode: u16, - pub st_nlink: c_short, - pub st_uid: c_short, - pub st_gid: c_short, - pub st_rdev: dev_t, - pub st_size: int64, - pub st_atime: time64_t, - pub st_mtime: time64_t, - pub st_ctime: time64_t, - } - - // note that this is called utimbuf64 in Windows - #[repr(C)] - #[derive(Copy, Clone)] - pub struct utimbuf { - pub actime: time64_t, - pub modtime: time64_t, - } - - #[repr(C)] - #[derive(Copy, Clone)] - pub struct timeval { - pub tv_sec: c_long, - pub tv_usec: c_long, - } - - #[repr(C)] - #[derive(Copy, Clone)] - pub struct timespec { - pub tv_sec: time_t, - pub tv_nsec: c_long, - } - - pub enum timezone {} - } - - pub mod bsd44 { - use types::os::arch::c95::{c_char, c_int, c_uint, size_t}; - use types::os::arch::c99::uintptr_t; - - pub type SOCKET = uintptr_t; - pub type socklen_t = c_int; - pub type sa_family_t = u16; - pub type in_port_t = u16; - pub type in_addr_t = u32; - #[repr(C)] - #[derive(Copy, Clone)] - pub struct sockaddr { - pub sa_family: sa_family_t, - pub sa_data: [u8; 14], - } - #[repr(C)] - #[derive(Copy)] - pub struct sockaddr_storage { - pub ss_family: sa_family_t, - pub __ss_pad1: [u8; 6], - pub __ss_align: i64, - pub __ss_pad2: [u8; 112], - } - impl ::core::clone::Clone for sockaddr_storage { - fn clone(&self) -> sockaddr_storage { - *self - } - } - #[repr(C)] - #[derive(Copy, Clone)] - pub struct sockaddr_in { - pub sin_family: sa_family_t, - pub sin_port: in_port_t, - pub sin_addr: in_addr, - pub sin_zero: [u8; 8], - } - #[repr(C)] - #[derive(Copy, Clone)] - pub struct in_addr { - pub s_addr: in_addr_t, - } - #[repr(C)] - #[derive(Copy, Clone)] - pub struct sockaddr_in6 { - pub sin6_family: sa_family_t, - pub sin6_port: in_port_t, - pub sin6_flowinfo: u32, - pub sin6_addr: in6_addr, - pub sin6_scope_id: u32, - } - #[repr(C)] - #[derive(Copy, Clone)] - pub struct in6_addr { - pub s6_addr: [u16; 8], - } - #[repr(C)] - #[derive(Copy, Clone)] - pub struct ip_mreq { - pub imr_multiaddr: in_addr, - pub imr_interface: in_addr, - } - #[repr(C)] - #[derive(Copy, Clone)] - pub struct ip6_mreq { - pub ipv6mr_multiaddr: in6_addr, - pub ipv6mr_interface: c_uint, - } - #[repr(C)] - #[derive(Copy, Clone)] - pub struct addrinfo { - pub ai_flags: c_int, - pub ai_family: c_int, - pub ai_socktype: c_int, - pub ai_protocol: c_int, - pub ai_addrlen: size_t, - pub ai_canonname: *mut c_char, - pub ai_addr: *mut sockaddr, - pub ai_next: *mut addrinfo, - } - #[repr(C)] - #[derive(Copy)] - pub struct sockaddr_un { - pub sun_family: sa_family_t, - pub sun_path: [c_char; 108], - } - impl ::core::clone::Clone for sockaddr_un { - fn clone(&self) -> sockaddr_un { - *self - } - } - } - } - - pub mod arch { - pub mod c95 { - pub type c_char = i8; - pub type c_schar = i8; - pub type c_uchar = u8; - pub type c_short = i16; - pub type c_ushort = u16; - pub type c_int = i32; - pub type c_uint = u32; - pub type c_long = i32; - pub type c_ulong = u32; - pub type c_float = f32; - pub type c_double = f64; - - #[cfg(target_arch = "x86")] - pub type size_t = u32; - #[cfg(target_arch = "x86_64")] - pub type size_t = u64; - - #[cfg(target_arch = "x86")] - pub type ptrdiff_t = i32; - #[cfg(target_arch = "x86_64")] - pub type ptrdiff_t = i64; - - pub type clock_t = i32; - - #[cfg(target_arch = "x86")] - pub type time_t = i32; - #[cfg(target_arch = "x86_64")] - pub type time_t = i64; - - #[cfg(target_arch = "x86")] - pub type suseconds_t = i32; - #[cfg(target_arch = "x86_64")] - pub type suseconds_t = i64; - - pub type wchar_t = u16; - } - - pub mod c99 { - pub type c_longlong = i64; - pub type c_ulonglong = u64; - - #[cfg(target_arch = "x86")] - pub type intptr_t = i32; - #[cfg(target_arch = "x86_64")] - pub type intptr_t = i64; - - #[cfg(target_arch = "x86")] - pub type uintptr_t = u32; - #[cfg(target_arch = "x86_64")] - pub type uintptr_t = u64; - - pub type intmax_t = i64; - pub type uintmax_t = u64; - } - - pub mod posix88 { - pub type off_t = i32; - pub type dev_t = u32; - pub type ino_t = u16; - - pub type pid_t = u32; - - pub type useconds_t = u32; - pub type mode_t = u16; - - #[cfg(target_arch = "x86")] - pub type ssize_t = i32; - #[cfg(target_arch = "x86_64")] - pub type ssize_t = i64; - } - - pub mod posix01 { - } - pub mod posix08 { - } - pub mod bsd44 { - } - pub mod extra { - use consts::os::extra::{MAX_PROTOCOL_CHAIN, WSAPROTOCOL_LEN}; - use types::common::c95::c_void; - use types::os::arch::c95::{c_char, c_int, c_uint, size_t}; - use types::os::arch::c95::{c_long, c_ulong}; - use types::os::arch::c95::wchar_t; - use types::os::arch::c99::{c_ulonglong, c_longlong, uintptr_t}; - - pub type BOOL = c_int; - pub type BYTE = u8; - pub type BOOLEAN = BYTE; - pub type CCHAR = c_char; - pub type CHAR = c_char; - - pub type DWORD = c_ulong; - pub type DWORDLONG = c_ulonglong; - - pub type HANDLE = LPVOID; - pub type HINSTANCE = HANDLE; - pub type HMODULE = HINSTANCE; - - pub type LONG = c_long; - pub type PLONG = *mut c_long; - - #[cfg(target_arch = "x86")] - pub type LONG_PTR = c_long; - #[cfg(target_arch = "x86_64")] - pub type LONG_PTR = i64; - - pub type LARGE_INTEGER = c_longlong; - pub type PLARGE_INTEGER = *mut c_longlong; - - pub type LPCWSTR = *const WCHAR; - pub type LPCSTR = *const CHAR; - - pub type LPWSTR = *mut WCHAR; - pub type LPSTR = *mut CHAR; - - pub type LPWCH = *mut WCHAR; - pub type LPCH = *mut CHAR; - - #[repr(C)] - #[derive(Copy, Clone)] - pub struct SECURITY_ATTRIBUTES { - pub nLength: DWORD, - pub lpSecurityDescriptor: LPVOID, - pub bInheritHandle: BOOL, - } - pub type LPSECURITY_ATTRIBUTES = *mut SECURITY_ATTRIBUTES; - - pub type LPVOID = *mut c_void; - pub type LPCVOID = *const c_void; - pub type LPBYTE = *mut BYTE; - pub type LPWORD = *mut WORD; - pub type LPDWORD = *mut DWORD; - pub type LPHANDLE = *mut HANDLE; - - pub type LRESULT = LONG_PTR; - pub type PBOOL = *mut BOOL; - pub type WCHAR = wchar_t; - pub type WORD = u16; - pub type SIZE_T = size_t; - - pub type time64_t = i64; - pub type int64 = i64; - - #[repr(C)] - #[derive(Copy, Clone)] - pub struct STARTUPINFO { - pub cb: DWORD, - pub lpReserved: LPWSTR, - pub lpDesktop: LPWSTR, - pub lpTitle: LPWSTR, - pub dwX: DWORD, - pub dwY: DWORD, - pub dwXSize: DWORD, - pub dwYSize: DWORD, - pub dwXCountChars: DWORD, - pub dwYCountCharts: DWORD, - pub dwFillAttribute: DWORD, - pub dwFlags: DWORD, - pub wShowWindow: WORD, - pub cbReserved2: WORD, - pub lpReserved2: LPBYTE, - pub hStdInput: HANDLE, - pub hStdOutput: HANDLE, - pub hStdError: HANDLE, - } - pub type LPSTARTUPINFO = *mut STARTUPINFO; - - #[repr(C)] - #[derive(Copy, Clone)] - pub struct PROCESS_INFORMATION { - pub hProcess: HANDLE, - pub hThread: HANDLE, - pub dwProcessId: DWORD, - pub dwThreadId: DWORD, - } - pub type LPPROCESS_INFORMATION = *mut PROCESS_INFORMATION; - - #[repr(C)] - #[derive(Copy, Clone)] - pub struct SYSTEM_INFO { - pub wProcessorArchitecture: WORD, - pub wReserved: WORD, - pub dwPageSize: DWORD, - pub lpMinimumApplicationAddress: LPVOID, - pub lpMaximumApplicationAddress: LPVOID, - pub dwActiveProcessorMask: uintptr_t, - pub dwNumberOfProcessors: DWORD, - pub dwProcessorType: DWORD, - pub dwAllocationGranularity: DWORD, - pub wProcessorLevel: WORD, - pub wProcessorRevision: WORD, - } - pub type LPSYSTEM_INFO = *mut SYSTEM_INFO; - - #[repr(C)] - #[derive(Copy, Clone)] - pub struct MEMORY_BASIC_INFORMATION { - pub BaseAddress: LPVOID, - pub AllocationBase: LPVOID, - pub AllocationProtect: DWORD, - pub RegionSize: SIZE_T, - pub State: DWORD, - pub Protect: DWORD, - pub Type: DWORD, - } - pub type LPMEMORY_BASIC_INFORMATION = *mut MEMORY_BASIC_INFORMATION; - - #[repr(C)] - #[derive(Copy, Clone)] - pub struct OVERLAPPED { - pub Internal: *mut c_ulong, - pub InternalHigh: *mut c_ulong, - pub Offset: DWORD, - pub OffsetHigh: DWORD, - pub hEvent: HANDLE, - } - - pub type LPOVERLAPPED = *mut OVERLAPPED; - - #[repr(C)] - #[derive(Copy, Clone)] - pub struct FILETIME { - pub dwLowDateTime: DWORD, - pub dwHighDateTime: DWORD, - } - - pub type LPFILETIME = *mut FILETIME; - - #[repr(C)] - #[derive(Copy, Clone)] - pub struct GUID { - pub Data1: DWORD, - pub Data2: WORD, - pub Data3: WORD, - pub Data4: [BYTE; 8], - } - - #[repr(C)] - #[derive(Copy, Clone)] - pub struct WSAPROTOCOLCHAIN { - pub ChainLen: c_int, - pub ChainEntries: [DWORD; MAX_PROTOCOL_CHAIN as usize], - } - - pub type LPWSAPROTOCOLCHAIN = *mut WSAPROTOCOLCHAIN; - - #[repr(C)] - #[derive(Copy)] - pub struct WSAPROTOCOL_INFO { - pub dwServiceFlags1: DWORD, - pub dwServiceFlags2: DWORD, - pub dwServiceFlags3: DWORD, - pub dwServiceFlags4: DWORD, - pub dwProviderFlags: DWORD, - pub ProviderId: GUID, - pub dwCatalogEntryId: DWORD, - pub ProtocolChain: WSAPROTOCOLCHAIN, - pub iVersion: c_int, - pub iAddressFamily: c_int, - pub iMaxSockAddr: c_int, - pub iMinSockAddr: c_int, - pub iSocketType: c_int, - pub iProtocol: c_int, - pub iProtocolMaxOffset: c_int, - pub iNetworkByteOrder: c_int, - pub iSecurityScheme: c_int, - pub dwMessageSize: DWORD, - pub dwProviderReserved: DWORD, - pub szProtocol: [u8; (WSAPROTOCOL_LEN as usize) + 1], - } - impl ::core::clone::Clone for WSAPROTOCOL_INFO { - fn clone(&self) -> WSAPROTOCOL_INFO { - *self - } - } - - pub type LPWSAPROTOCOL_INFO = *mut WSAPROTOCOL_INFO; - - pub type GROUP = c_uint; - - #[repr(C)] - #[derive(Copy)] - pub struct WIN32_FIND_DATAW { - pub dwFileAttributes: DWORD, - pub ftCreationTime: FILETIME, - pub ftLastAccessTime: FILETIME, - pub ftLastWriteTime: FILETIME, - pub nFileSizeHigh: DWORD, - pub nFileSizeLow: DWORD, - pub dwReserved0: DWORD, - pub dwReserved1: DWORD, - pub cFileName: [wchar_t; 260], // #define MAX_PATH 260 - pub cAlternateFileName: [wchar_t; 14], - } - impl ::core::clone::Clone for WIN32_FIND_DATAW { - fn clone(&self) -> WIN32_FIND_DATAW { - *self - } - } - - pub type LPWIN32_FIND_DATAW = *mut WIN32_FIND_DATAW; - } - } - } - - #[cfg(any(target_os = "macos", target_os = "ios"))] - pub mod os { - pub mod common { - pub mod posix01 { - use types::common::c95::c_void; - use types::os::arch::c95::{c_char, c_int, size_t, time_t}; - use types::os::arch::c95::{suseconds_t, c_long}; - use types::os::arch::c99::uintptr_t; - - pub type pthread_t = uintptr_t; - pub type rlim_t = u64; - - #[repr(C)] - #[derive(Copy, Clone)] - pub struct glob_t { - pub gl_pathc: size_t, - pub __unused1: c_int, - pub gl_offs: size_t, - pub __unused2: c_int, - pub gl_pathv: *mut *mut c_char, - - pub __unused3: *mut c_void, - - pub __unused4: *mut c_void, - pub __unused5: *mut c_void, - pub __unused6: *mut c_void, - pub __unused7: *mut c_void, - pub __unused8: *mut c_void, - } - - #[repr(C)] - #[derive(Copy, Clone)] - pub struct timeval { - pub tv_sec: time_t, - pub tv_usec: suseconds_t, - } - - #[repr(C)] - #[derive(Copy, Clone)] - pub struct timespec { - pub tv_sec: time_t, - pub tv_nsec: c_long, - } - - pub enum timezone {} - - pub type sighandler_t = size_t; - - #[repr(C)] - #[derive(Copy, Clone)] - pub struct rlimit { - pub rlim_cur: rlim_t, - pub rlim_max: rlim_t, - } - } - - pub mod bsd43 { - use types::os::common::posix01::timeval; - use types::os::arch::c95::c_long; - #[repr(C)] - #[derive(Copy, Clone)] - pub struct rusage { - pub ru_utime: timeval, - pub ru_stime: timeval, - pub ru_maxrss: c_long, - pub ru_ixrss: c_long, - pub ru_idrss: c_long, - pub ru_isrss: c_long, - pub ru_minflt: c_long, - pub ru_majflt: c_long, - pub ru_nswap: c_long, - pub ru_inblock: c_long, - pub ru_oublock: c_long, - pub ru_msgsnd: c_long, - pub ru_msgrcv: c_long, - pub ru_nsignals: c_long, - pub ru_nvcsw: c_long, - pub ru_nivcsw: c_long, - } - } - - pub mod bsd44 { - use types::common::c95::c_void; - use types::os::arch::c95::{c_char, c_int, c_uint}; - - pub type socklen_t = u32; - pub type sa_family_t = u8; - pub type in_port_t = u16; - pub type in_addr_t = u32; - #[repr(C)] - #[derive(Copy, Clone)] - pub struct sockaddr { - pub sa_len: u8, - pub sa_family: sa_family_t, - pub sa_data: [u8; 14], - } - - #[repr(C)] - #[derive(Copy)] - pub struct sockaddr_storage { - pub ss_len: u8, - pub ss_family: sa_family_t, - pub __ss_pad1: [u8; 6], - pub __ss_align: i64, - pub __ss_pad2: [u8; 112], - } - impl ::core::clone::Clone for sockaddr_storage { - fn clone(&self) -> sockaddr_storage { - *self - } - } - - #[repr(C)] - #[derive(Copy, Clone)] - pub struct sockaddr_in { - pub sin_len: u8, - pub sin_family: sa_family_t, - pub sin_port: in_port_t, - pub sin_addr: in_addr, - pub sin_zero: [u8; 8], - } - - #[repr(C)] - #[derive(Copy, Clone)] - pub struct in_addr { - pub s_addr: in_addr_t, - } - - #[repr(C)] - #[derive(Copy, Clone)] - pub struct sockaddr_in6 { - pub sin6_len: u8, - pub sin6_family: sa_family_t, - pub sin6_port: in_port_t, - pub sin6_flowinfo: u32, - pub sin6_addr: in6_addr, - pub sin6_scope_id: u32, - } - - #[repr(C)] - #[derive(Copy, Clone)] - pub struct in6_addr { - pub s6_addr: [u16; 8], - } - - #[repr(C)] - #[derive(Copy, Clone)] - pub struct ip_mreq { - pub imr_multiaddr: in_addr, - pub imr_interface: in_addr, - } - - #[repr(C)] - #[derive(Copy, Clone)] - pub struct ip6_mreq { - pub ipv6mr_multiaddr: in6_addr, - pub ipv6mr_interface: c_uint, - } - - #[repr(C)] - #[derive(Copy, Clone)] - pub struct addrinfo { - pub ai_flags: c_int, - pub ai_family: c_int, - pub ai_socktype: c_int, - pub ai_protocol: c_int, - pub ai_addrlen: socklen_t, - pub ai_canonname: *mut c_char, - pub ai_addr: *mut sockaddr, - pub ai_next: *mut addrinfo, - } - - #[repr(C)] - #[derive(Copy)] - pub struct sockaddr_un { - pub sun_len: u8, - pub sun_family: sa_family_t, - pub sun_path: [c_char; 104], - } - impl ::core::clone::Clone for sockaddr_un { - fn clone(&self) -> sockaddr_un { - *self - } - } - - #[repr(C)] - #[derive(Copy, Clone)] - pub struct ifaddrs { - pub ifa_next: *mut ifaddrs, - pub ifa_name: *mut c_char, - pub ifa_flags: c_uint, - pub ifa_addr: *mut sockaddr, - pub ifa_netmask: *mut sockaddr, - pub ifa_dstaddr: *mut sockaddr, - pub ifa_data: *mut c_void, - } - } - } - - #[cfg(any(target_arch = "arm", target_arch = "x86"))] - pub mod arch { - pub mod c95 { - pub type c_char = i8; - pub type c_schar = i8; - pub type c_uchar = u8; - pub type c_short = i16; - pub type c_ushort = u16; - pub type c_int = i32; - pub type c_uint = u32; - pub type c_long = i32; - pub type c_ulong = u32; - pub type c_float = f32; - pub type c_double = f64; - pub type size_t = u32; - pub type ptrdiff_t = i32; - pub type clock_t = c_ulong; - pub type time_t = c_long; - pub type suseconds_t = i32; - pub type wchar_t = i32; - } - pub mod c99 { - pub type c_longlong = i64; - pub type c_ulonglong = u64; - pub type intptr_t = i32; - pub type uintptr_t = u32; - pub type intmax_t = i64; - pub type uintmax_t = u64; - } - pub mod posix88 { - use types::os::arch::c95::c_long; - - pub type off_t = i64; - pub type dev_t = i32; - pub type ino_t = u64; - pub type pid_t = i32; - pub type uid_t = u32; - pub type gid_t = u32; - pub type useconds_t = u32; - pub type mode_t = u16; - pub type ssize_t = c_long; - } - pub mod posix01 { - use types::common::c99::{int32_t, int64_t, uint32_t}; - use types::os::arch::c95::{c_char, c_long, time_t}; - use types::os::arch::posix88::{dev_t, gid_t, ino_t, mode_t, off_t, uid_t}; - - pub type nlink_t = u16; - pub type blksize_t = i32; - pub type blkcnt_t = i64; - - #[repr(C)] - #[derive(Copy, Clone)] - pub struct stat { - pub st_dev: dev_t, - pub st_mode: mode_t, - pub st_nlink: nlink_t, - pub st_ino: ino_t, - pub st_uid: uid_t, - pub st_gid: gid_t, - pub st_rdev: dev_t, - pub st_atime: time_t, - pub st_atime_nsec: c_long, - pub st_mtime: time_t, - pub st_mtime_nsec: c_long, - pub st_ctime: time_t, - pub st_ctime_nsec: c_long, - pub st_birthtime: time_t, - pub st_birthtime_nsec: c_long, - pub st_size: off_t, - pub st_blocks: blkcnt_t, - pub st_blksize: blksize_t, - pub st_flags: uint32_t, - pub st_gen: uint32_t, - pub st_lspare: int32_t, - pub st_qspare: [int64_t; 2], - } - - #[repr(C)] - #[derive(Copy, Clone)] - pub struct utimbuf { - pub actime: time_t, - pub modtime: time_t, - } - - #[repr(C)] - #[derive(Copy)] - pub struct pthread_attr_t { - pub __sig: c_long, - pub __opaque: [c_char; 36], - } - impl ::core::clone::Clone for pthread_attr_t { - fn clone(&self) -> pthread_attr_t { - *self - } - } - } - pub mod posix08 { - } - pub mod bsd44 { - } - pub mod extra { - #[repr(C)] - #[derive(Copy, Clone)] - pub struct mach_timebase_info { - pub numer: u32, - pub denom: u32, - } - - pub type mach_timebase_info_data_t = mach_timebase_info; - } - } - - #[cfg(any(target_arch = "x86_64", target_arch = "aarch64"))] - pub mod arch { - pub mod c95 { - pub type c_char = i8; - pub type c_schar = i8; - pub type c_uchar = u8; - pub type c_short = i16; - pub type c_ushort = u16; - pub type c_int = i32; - pub type c_uint = u32; - pub type c_long = i64; - pub type c_ulong = u64; - pub type c_float = f32; - pub type c_double = f64; - pub type size_t = u64; - pub type ptrdiff_t = i64; - pub type clock_t = c_ulong; - pub type time_t = c_long; - pub type suseconds_t = i32; - pub type wchar_t = i32; - } - pub mod c99 { - pub type c_longlong = i64; - pub type c_ulonglong = u64; - pub type intptr_t = i64; - pub type uintptr_t = u64; - pub type intmax_t = i64; - pub type uintmax_t = u64; - } - pub mod posix88 { - use types::os::arch::c95::c_long; - - pub type off_t = i64; - pub type dev_t = i32; - pub type ino_t = u64; - pub type pid_t = i32; - pub type uid_t = u32; - pub type gid_t = u32; - pub type useconds_t = u32; - pub type mode_t = u16; - pub type ssize_t = c_long; - } - pub mod posix01 { - use types::common::c99::{int32_t, int64_t}; - use types::common::c99::uint32_t; - use types::os::arch::c95::{c_char, c_long, time_t}; - use types::os::arch::posix88::{dev_t, gid_t, ino_t}; - use types::os::arch::posix88::{mode_t, off_t, uid_t}; - - pub type nlink_t = u16; - pub type blksize_t = i32; - pub type blkcnt_t = i64; - - #[repr(C)] - #[derive(Copy, Clone)] - pub struct stat { - pub st_dev: dev_t, - pub st_mode: mode_t, - pub st_nlink: nlink_t, - pub st_ino: ino_t, - pub st_uid: uid_t, - pub st_gid: gid_t, - pub st_rdev: dev_t, - pub st_atime: time_t, - pub st_atime_nsec: c_long, - pub st_mtime: time_t, - pub st_mtime_nsec: c_long, - pub st_ctime: time_t, - pub st_ctime_nsec: c_long, - pub st_birthtime: time_t, - pub st_birthtime_nsec: c_long, - pub st_size: off_t, - pub st_blocks: blkcnt_t, - pub st_blksize: blksize_t, - pub st_flags: uint32_t, - pub st_gen: uint32_t, - pub st_lspare: int32_t, - pub st_qspare: [int64_t; 2], - } - - #[repr(C)] - #[derive(Copy, Clone)] - pub struct utimbuf { - pub actime: time_t, - pub modtime: time_t, - } - - #[repr(C)] - #[derive(Copy)] - pub struct pthread_attr_t { - pub __sig: c_long, - pub __opaque: [c_char; 56], - } - impl ::core::clone::Clone for pthread_attr_t { - fn clone(&self) -> pthread_attr_t { - *self - } - } - } - pub mod posix08 { - } - pub mod bsd44 { - } - pub mod extra { - #[repr(C)] - #[derive(Copy, Clone)] - pub struct mach_timebase_info { - pub numer: u32, - pub denom: u32, - } - - pub type mach_timebase_info_data_t = mach_timebase_info; - } - } - } -} - -pub mod consts { - // Consts tend to vary per OS so we pull their definitions out - // into this module. - - #[cfg(target_os = "windows")] - pub mod os { - pub mod c95 { - use types::os::arch::c95::{c_int, c_uint}; - - pub const EXIT_FAILURE: c_int = 1; - pub const EXIT_SUCCESS: c_int = 0; - pub const RAND_MAX: c_int = 32767; - pub const EOF: c_int = -1; - pub const SEEK_SET: c_int = 0; - pub const SEEK_CUR: c_int = 1; - pub const SEEK_END: c_int = 2; - pub const _IOFBF: c_int = 0; - pub const _IONBF: c_int = 4; - pub const _IOLBF: c_int = 64; - pub const BUFSIZ: c_uint = 512; - pub const FOPEN_MAX: c_uint = 20; - pub const FILENAME_MAX: c_uint = 260; - pub const L_tmpnam: c_uint = 16; - pub const TMP_MAX: c_uint = 32767; - - pub const WSAEINTR: c_int = 10004; - pub const WSAEBADF: c_int = 10009; - pub const WSAEACCES: c_int = 10013; - pub const WSAEFAULT: c_int = 10014; - pub const WSAEINVAL: c_int = 10022; - pub const WSAEMFILE: c_int = 10024; - pub const WSAEWOULDBLOCK: c_int = 10035; - pub const WSAEINPROGRESS: c_int = 10036; - pub const WSAEALREADY: c_int = 10037; - pub const WSAENOTSOCK: c_int = 10038; - pub const WSAEDESTADDRREQ: c_int = 10039; - pub const WSAEMSGSIZE: c_int = 10040; - pub const WSAEPROTOTYPE: c_int = 10041; - pub const WSAENOPROTOOPT: c_int = 10042; - pub const WSAEPROTONOSUPPORT: c_int = 10043; - pub const WSAESOCKTNOSUPPORT: c_int = 10044; - pub const WSAEOPNOTSUPP: c_int = 10045; - pub const WSAEPFNOSUPPORT: c_int = 10046; - pub const WSAEAFNOSUPPORT: c_int = 10047; - pub const WSAEADDRINUSE: c_int = 10048; - pub const WSAEADDRNOTAVAIL: c_int = 10049; - pub const WSAENETDOWN: c_int = 10050; - pub const WSAENETUNREACH: c_int = 10051; - pub const WSAENETRESET: c_int = 10052; - pub const WSAECONNABORTED: c_int = 10053; - pub const WSAECONNRESET: c_int = 10054; - pub const WSAENOBUFS: c_int = 10055; - pub const WSAEISCONN: c_int = 10056; - pub const WSAENOTCONN: c_int = 10057; - pub const WSAESHUTDOWN: c_int = 10058; - pub const WSAETOOMANYREFS: c_int = 10059; - pub const WSAETIMEDOUT: c_int = 10060; - pub const WSAECONNREFUSED: c_int = 10061; - pub const WSAELOOP: c_int = 10062; - pub const WSAENAMETOOLONG: c_int = 10063; - pub const WSAEHOSTDOWN: c_int = 10064; - pub const WSAEHOSTUNREACH: c_int = 10065; - pub const WSAENOTEMPTY: c_int = 10066; - pub const WSAEPROCLIM: c_int = 10067; - pub const WSAEUSERS: c_int = 10068; - pub const WSAEDQUOT: c_int = 10069; - pub const WSAESTALE: c_int = 10070; - pub const WSAEREMOTE: c_int = 10071; - pub const WSASYSNOTREADY: c_int = 10091; - pub const WSAVERNOTSUPPORTED: c_int = 10092; - pub const WSANOTINITIALISED: c_int = 10093; - pub const WSAEDISCON: c_int = 10101; - pub const WSAENOMORE: c_int = 10102; - pub const WSAECANCELLED: c_int = 10103; - pub const WSAEINVALIDPROCTABLE: c_int = 10104; - pub const WSAEINVALIDPROVIDER: c_int = 10105; - pub const WSAEPROVIDERFAILEDINIT: c_int = 10106; - } - pub mod c99 { - } - pub mod posix88 { - use types::os::arch::c95::c_int; - use types::os::arch::posix88::mode_t; - - pub const O_RDONLY: c_int = 0; - pub const O_WRONLY: c_int = 1; - pub const O_RDWR: c_int = 2; - pub const O_APPEND: c_int = 8; - pub const O_CREAT: c_int = 256; - pub const O_EXCL: c_int = 1024; - pub const O_TRUNC: c_int = 512; - pub const S_IFIFO: c_int = 4096; - pub const S_IFCHR: c_int = 8192; - pub const S_IFBLK: c_int = 12288; - pub const S_IFDIR: c_int = 16384; - pub const S_IFREG: c_int = 32768; - pub const S_IFLNK: c_int = 40960; - pub const S_IFSOCK: mode_t = 49152; - pub const S_IFMT: c_int = 61440; - pub const S_IEXEC: c_int = 64; - pub const S_IWRITE: c_int = 128; - pub const S_IREAD: c_int = 256; - pub const S_IRWXU: c_int = 448; - pub const S_IXUSR: c_int = 64; - pub const S_IWUSR: c_int = 128; - pub const S_IRUSR: c_int = 256; - pub const S_IRWXG: mode_t = 56; - pub const S_IXGRP: mode_t = 8; - pub const S_IWGRP: mode_t = 16; - pub const S_IRGRP: mode_t = 32; - pub const S_IRWXO: mode_t = 7; - pub const S_IXOTH: mode_t = 1; - pub const S_IWOTH: mode_t = 2; - pub const S_IROTH: mode_t = 4; - pub const F_OK: c_int = 0; - pub const R_OK: c_int = 4; - pub const W_OK: c_int = 2; - pub const X_OK: c_int = 1; - pub const STDIN_FILENO: c_int = 0; - pub const STDOUT_FILENO: c_int = 1; - pub const STDERR_FILENO: c_int = 2; - } - pub mod posix01 { - } - pub mod posix08 { - } - pub mod bsd44 { - use types::os::arch::c95::c_int; - - pub const AF_INET: c_int = 2; - pub const AF_INET6: c_int = 23; - pub const SOCK_STREAM: c_int = 1; - pub const SOCK_DGRAM: c_int = 2; - pub const SOCK_RAW: c_int = 3; - pub const IPPROTO_TCP: c_int = 6; - pub const IPPROTO_IP: c_int = 0; - pub const IPPROTO_IPV6: c_int = 41; - pub const IP_MULTICAST_TTL: c_int = 10; - pub const IP_MULTICAST_LOOP: c_int = 11; - pub const IP_ADD_MEMBERSHIP: c_int = 12; - pub const IP_DROP_MEMBERSHIP: c_int = 13; - pub const IPV6_ADD_MEMBERSHIP: c_int = 5; - pub const IPV6_DROP_MEMBERSHIP: c_int = 6; - pub const IP_TTL: c_int = 4; - pub const IP_HDRINCL: c_int = 2; - - pub const TCP_NODELAY: c_int = 0x0001; - pub const SOL_SOCKET: c_int = 0xffff; - - pub const SO_DEBUG: c_int = 0x0001; - pub const SO_ACCEPTCONN: c_int = 0x0002; - pub const SO_REUSEADDR: c_int = 0x0004; - pub const SO_KEEPALIVE: c_int = 0x0008; - pub const SO_DONTROUTE: c_int = 0x0010; - pub const SO_BROADCAST: c_int = 0x0020; - pub const SO_USELOOPBACK: c_int = 0x0040; - pub const SO_LINGER: c_int = 0x0080; - pub const SO_OOBINLINE: c_int = 0x0100; - pub const SO_SNDBUF: c_int = 0x1001; - pub const SO_RCVBUF: c_int = 0x1002; - pub const SO_SNDLOWAT: c_int = 0x1003; - pub const SO_RCVLOWAT: c_int = 0x1004; - pub const SO_SNDTIMEO: c_int = 0x1005; - pub const SO_RCVTIMEO: c_int = 0x1006; - pub const SO_ERROR: c_int = 0x1007; - pub const SO_TYPE: c_int = 0x1008; - - pub const IFF_LOOPBACK: c_int = 4; - - pub const SHUT_RD: c_int = 0; - pub const SHUT_WR: c_int = 1; - pub const SHUT_RDWR: c_int = 2; - } - pub mod extra { - use types::os::common::bsd44::SOCKET; - use types::os::arch::c95::{c_int, c_long}; - use types::os::arch::extra::{WORD, DWORD, BOOL, HANDLE}; - - pub const TRUE: BOOL = 1; - pub const FALSE: BOOL = 0; - - pub const O_TEXT: c_int = 16384; - pub const O_BINARY: c_int = 32768; - pub const O_NOINHERIT: c_int = 128; - - pub const ERROR_SUCCESS: c_int = 0; - pub const ERROR_INVALID_FUNCTION: c_int = 1; - pub const ERROR_FILE_NOT_FOUND: c_int = 2; - pub const ERROR_ACCESS_DENIED: c_int = 5; - pub const ERROR_INVALID_HANDLE: c_int = 6; - pub const ERROR_BROKEN_PIPE: c_int = 109; - pub const ERROR_DISK_FULL: c_int = 112; - pub const ERROR_CALL_NOT_IMPLEMENTED: c_int = 120; - pub const ERROR_INSUFFICIENT_BUFFER: c_int = 122; - pub const ERROR_INVALID_NAME: c_int = 123; - pub const ERROR_ALREADY_EXISTS: c_int = 183; - pub const ERROR_PIPE_BUSY: c_int = 231; - pub const ERROR_NO_DATA: c_int = 232; - pub const ERROR_INVALID_ADDRESS: c_int = 487; - pub const ERROR_PIPE_CONNECTED: c_int = 535; - pub const ERROR_NOTHING_TO_TERMINATE: c_int = 758; - pub const ERROR_OPERATION_ABORTED: c_int = 995; - pub const ERROR_IO_PENDING: c_int = 997; - pub const ERROR_FILE_INVALID: c_int = 1006; - pub const ERROR_NOT_FOUND: c_int = 1168; - pub const INVALID_HANDLE_VALUE: HANDLE = !0 as HANDLE; - - pub const DELETE: DWORD = 0x00010000; - pub const READ_CONTROL: DWORD = 0x00020000; - pub const SYNCHRONIZE: DWORD = 0x00100000; - pub const WRITE_DAC: DWORD = 0x00040000; - pub const WRITE_OWNER: DWORD = 0x00080000; - - pub const PROCESS_CREATE_PROCESS: DWORD = 0x0080; - pub const PROCESS_CREATE_THREAD: DWORD = 0x0002; - pub const PROCESS_DUP_HANDLE: DWORD = 0x0040; - pub const PROCESS_QUERY_INFORMATION: DWORD = 0x0400; - pub const PROCESS_QUERY_LIMITED_INFORMATION: DWORD = 0x1000; - pub const PROCESS_SET_INFORMATION: DWORD = 0x0200; - pub const PROCESS_SET_QUOTA: DWORD = 0x0100; - pub const PROCESS_SUSPEND_RESUME: DWORD = 0x0800; - pub const PROCESS_TERMINATE: DWORD = 0x0001; - pub const PROCESS_VM_OPERATION: DWORD = 0x0008; - pub const PROCESS_VM_READ: DWORD = 0x0010; - pub const PROCESS_VM_WRITE: DWORD = 0x0020; - - pub const STARTF_FORCEONFEEDBACK: DWORD = 0x00000040; - pub const STARTF_FORCEOFFFEEDBACK: DWORD = 0x00000080; - pub const STARTF_PREVENTPINNING: DWORD = 0x00002000; - pub const STARTF_RUNFULLSCREEN: DWORD = 0x00000020; - pub const STARTF_TITLEISAPPID: DWORD = 0x00001000; - pub const STARTF_TITLEISLINKNAME: DWORD = 0x00000800; - pub const STARTF_USECOUNTCHARS: DWORD = 0x00000008; - pub const STARTF_USEFILLATTRIBUTE: DWORD = 0x00000010; - pub const STARTF_USEHOTKEY: DWORD = 0x00000200; - pub const STARTF_USEPOSITION: DWORD = 0x00000004; - pub const STARTF_USESHOWWINDOW: DWORD = 0x00000001; - pub const STARTF_USESIZE: DWORD = 0x00000002; - pub const STARTF_USESTDHANDLES: DWORD = 0x00000100; - - pub const WAIT_ABANDONED: DWORD = 0x00000080; - pub const WAIT_OBJECT_0: DWORD = 0x00000000; - pub const WAIT_TIMEOUT: DWORD = 0x00000102; - pub const WAIT_FAILED: DWORD = !0; - - pub const DUPLICATE_CLOSE_SOURCE: DWORD = 0x00000001; - pub const DUPLICATE_SAME_ACCESS: DWORD = 0x00000002; - - pub const INFINITE: DWORD = !0; - pub const STILL_ACTIVE: DWORD = 259; - - pub const MEM_COMMIT: DWORD = 0x00001000; - pub const MEM_RESERVE: DWORD = 0x00002000; - pub const MEM_DECOMMIT: DWORD = 0x00004000; - pub const MEM_RELEASE: DWORD = 0x00008000; - pub const MEM_RESET: DWORD = 0x00080000; - pub const MEM_RESET_UNDO: DWORD = 0x1000000; - pub const MEM_LARGE_PAGES: DWORD = 0x20000000; - pub const MEM_PHYSICAL: DWORD = 0x00400000; - pub const MEM_TOP_DOWN: DWORD = 0x00100000; - pub const MEM_WRITE_WATCH: DWORD = 0x00200000; - - pub const PAGE_EXECUTE: DWORD = 0x10; - pub const PAGE_EXECUTE_READ: DWORD = 0x20; - pub const PAGE_EXECUTE_READWRITE: DWORD = 0x40; - pub const PAGE_EXECUTE_WRITECOPY: DWORD = 0x80; - pub const PAGE_NOACCESS: DWORD = 0x01; - pub const PAGE_READONLY: DWORD = 0x02; - pub const PAGE_READWRITE: DWORD = 0x04; - pub const PAGE_WRITECOPY: DWORD = 0x08; - pub const PAGE_GUARD: DWORD = 0x100; - pub const PAGE_NOCACHE: DWORD = 0x200; - pub const PAGE_WRITECOMBINE: DWORD = 0x400; - - pub const SEC_COMMIT: DWORD = 0x8000000; - pub const SEC_IMAGE: DWORD = 0x1000000; - pub const SEC_IMAGE_NO_EXECUTE: DWORD = 0x11000000; - pub const SEC_LARGE_PAGES: DWORD = 0x80000000; - pub const SEC_NOCACHE: DWORD = 0x10000000; - pub const SEC_RESERVE: DWORD = 0x4000000; - pub const SEC_WRITECOMBINE: DWORD = 0x40000000; - - pub const FILE_MAP_ALL_ACCESS: DWORD = 0xf001f; - pub const FILE_MAP_READ: DWORD = 0x4; - pub const FILE_MAP_WRITE: DWORD = 0x2; - pub const FILE_MAP_COPY: DWORD = 0x1; - pub const FILE_MAP_EXECUTE: DWORD = 0x20; - - pub const PROCESSOR_ARCHITECTURE_INTEL: WORD = 0; - pub const PROCESSOR_ARCHITECTURE_ARM: WORD = 5; - pub const PROCESSOR_ARCHITECTURE_IA64: WORD = 6; - pub const PROCESSOR_ARCHITECTURE_AMD64: WORD = 9; - pub const PROCESSOR_ARCHITECTURE_UNKNOWN: WORD = 0xffff; - - pub const MOVEFILE_COPY_ALLOWED: DWORD = 2; - pub const MOVEFILE_CREATE_HARDLINK: DWORD = 16; - pub const MOVEFILE_DELAY_UNTIL_REBOOT: DWORD = 4; - pub const MOVEFILE_FAIL_IF_NOT_TRACKABLE: DWORD = 32; - pub const MOVEFILE_REPLACE_EXISTING: DWORD = 1; - pub const MOVEFILE_WRITE_THROUGH: DWORD = 8; - - pub const SYMBOLIC_LINK_FLAG_DIRECTORY: DWORD = 1; - - pub const FILE_SHARE_DELETE: DWORD = 0x4; - pub const FILE_SHARE_READ: DWORD = 0x1; - pub const FILE_SHARE_WRITE: DWORD = 0x2; - - pub const CREATE_ALWAYS: DWORD = 2; - pub const CREATE_NEW: DWORD = 1; - pub const OPEN_ALWAYS: DWORD = 4; - pub const OPEN_EXISTING: DWORD = 3; - pub const TRUNCATE_EXISTING: DWORD = 5; - - pub const FILE_APPEND_DATA: DWORD = 0x00000004; - pub const FILE_READ_DATA: DWORD = 0x00000001; - pub const FILE_WRITE_DATA: DWORD = 0x00000002; - - pub const FILE_ATTRIBUTE_ARCHIVE: DWORD = 0x20; - pub const FILE_ATTRIBUTE_COMPRESSED: DWORD = 0x800; - pub const FILE_ATTRIBUTE_DEVICE: DWORD = 0x40; - pub const FILE_ATTRIBUTE_DIRECTORY: DWORD = 0x10; - pub const FILE_ATTRIBUTE_ENCRYPTED: DWORD = 0x4000; - pub const FILE_ATTRIBUTE_HIDDEN: DWORD = 0x2; - pub const FILE_ATTRIBUTE_INTEGRITY_STREAM: DWORD = 0x8000; - pub const FILE_ATTRIBUTE_NORMAL: DWORD = 0x80; - pub const FILE_ATTRIBUTE_NOT_CONTENT_INDEXED: DWORD = 0x2000; - pub const FILE_ATTRIBUTE_NO_SCRUB_DATA: DWORD = 0x20000; - pub const FILE_ATTRIBUTE_OFFLINE: DWORD = 0x1000; - pub const FILE_ATTRIBUTE_READONLY: DWORD = 0x1; - pub const FILE_ATTRIBUTE_REPARSE_POINT: DWORD = 0x400; - pub const FILE_ATTRIBUTE_SPARSE_FILE: DWORD = 0x200; - pub const FILE_ATTRIBUTE_SYSTEM: DWORD = 0x4; - pub const FILE_ATTRIBUTE_TEMPORARY: DWORD = 0x100; - pub const FILE_ATTRIBUTE_VIRTUAL: DWORD = 0x10000; - - pub const FILE_FLAG_BACKUP_SEMANTICS: DWORD = 0x02000000; - pub const FILE_FLAG_DELETE_ON_CLOSE: DWORD = 0x04000000; - pub const FILE_FLAG_NO_BUFFERING: DWORD = 0x20000000; - pub const FILE_FLAG_OPEN_NO_RECALL: DWORD = 0x00100000; - pub const FILE_FLAG_OPEN_REPARSE_POINT: DWORD = 0x00200000; - pub const FILE_FLAG_OVERLAPPED: DWORD = 0x40000000; - pub const FILE_FLAG_POSIX_SEMANTICS: DWORD = 0x0100000; - pub const FILE_FLAG_RANDOM_ACCESS: DWORD = 0x10000000; - pub const FILE_FLAG_SESSION_AWARE: DWORD = 0x00800000; - pub const FILE_FLAG_SEQUENTIAL_SCAN: DWORD = 0x08000000; - pub const FILE_FLAG_WRITE_THROUGH: DWORD = 0x80000000; - pub const FILE_FLAG_FIRST_PIPE_INSTANCE: DWORD = 0x00080000; - - pub const FILE_NAME_NORMALIZED: DWORD = 0x0; - pub const FILE_NAME_OPENED: DWORD = 0x8; - - pub const VOLUME_NAME_DOS: DWORD = 0x0; - pub const VOLUME_NAME_GUID: DWORD = 0x1; - pub const VOLUME_NAME_NONE: DWORD = 0x4; - pub const VOLUME_NAME_NT: DWORD = 0x2; - - pub const GENERIC_READ: DWORD = 0x80000000; - pub const GENERIC_WRITE: DWORD = 0x40000000; - pub const GENERIC_EXECUTE: DWORD = 0x20000000; - pub const GENERIC_ALL: DWORD = 0x10000000; - pub const FILE_WRITE_ATTRIBUTES: DWORD = 0x00000100; - pub const FILE_READ_ATTRIBUTES: DWORD = 0x00000080; - - pub const STANDARD_RIGHTS_READ: DWORD = 0x20000; - pub const STANDARD_RIGHTS_WRITE: DWORD = 0x20000; - pub const FILE_WRITE_EA: DWORD = 0x00000010; - pub const FILE_READ_EA: DWORD = 0x00000008; - pub const FILE_GENERIC_READ: DWORD = STANDARD_RIGHTS_READ | FILE_READ_DATA | - FILE_READ_ATTRIBUTES | - FILE_READ_EA | - SYNCHRONIZE; - pub const FILE_GENERIC_WRITE: DWORD = STANDARD_RIGHTS_WRITE | FILE_WRITE_DATA | - FILE_WRITE_ATTRIBUTES | - FILE_WRITE_EA | - FILE_APPEND_DATA | - SYNCHRONIZE; - - pub const FILE_BEGIN: DWORD = 0; - pub const FILE_CURRENT: DWORD = 1; - pub const FILE_END: DWORD = 2; - - pub const MAX_PROTOCOL_CHAIN: DWORD = 7; - pub const WSAPROTOCOL_LEN: DWORD = 255; - pub const INVALID_SOCKET: SOCKET = !0; - - pub const DETACHED_PROCESS: DWORD = 0x00000008; - pub const CREATE_NEW_PROCESS_GROUP: DWORD = 0x00000200; - pub const CREATE_UNICODE_ENVIRONMENT: DWORD = 0x00000400; - - pub const PIPE_ACCESS_DUPLEX: DWORD = 0x00000003; - pub const PIPE_ACCESS_INBOUND: DWORD = 0x00000001; - pub const PIPE_ACCESS_OUTBOUND: DWORD = 0x00000002; - pub const PIPE_TYPE_BYTE: DWORD = 0x00000000; - pub const PIPE_TYPE_MESSAGE: DWORD = 0x00000004; - pub const PIPE_READMODE_BYTE: DWORD = 0x00000000; - pub const PIPE_READMODE_MESSAGE: DWORD = 0x00000002; - pub const PIPE_WAIT: DWORD = 0x00000000; - pub const PIPE_NOWAIT: DWORD = 0x00000001; - pub const PIPE_ACCEPT_REMOTE_CLIENTS: DWORD = 0x00000000; - pub const PIPE_REJECT_REMOTE_CLIENTS: DWORD = 0x00000008; - pub const PIPE_UNLIMITED_INSTANCES: DWORD = 255; - - pub const IPPROTO_RAW: c_int = 255; - - pub const FIONBIO: c_long = -0x7FFB9982; - } - pub mod sysconf { - } - } - - - #[cfg(any(target_os = "linux", target_os = "android", target_os = "nacl"))] - pub mod os { - pub mod c95 { - use types::os::arch::c95::{c_int, c_uint}; - - pub const EXIT_FAILURE: c_int = 1; - pub const EXIT_SUCCESS: c_int = 0; - pub const RAND_MAX: c_int = 2147483647; - pub const EOF: c_int = -1; - pub const SEEK_SET: c_int = 0; - pub const SEEK_CUR: c_int = 1; - pub const SEEK_END: c_int = 2; - pub const _IOFBF: c_int = 0; - pub const _IONBF: c_int = 2; - pub const _IOLBF: c_int = 1; - pub const BUFSIZ: c_uint = 8192; - pub const FOPEN_MAX: c_uint = 16; - pub const FILENAME_MAX: c_uint = 4096; - pub const L_tmpnam: c_uint = 20; - pub const TMP_MAX: c_uint = 238328; - } - pub mod c99 { - } - #[cfg(any(target_arch = "x86", - target_arch = "x86_64", - target_arch = "arm", - target_arch = "aarch64", - target_arch = "le32", - target_arch = "powerpc"))] - pub mod posix88 { - use types::os::arch::c95::c_int; - use types::common::c95::c_void; - use types::os::arch::posix88::mode_t; - - pub const O_RDONLY: c_int = 0; - pub const O_WRONLY: c_int = 1; - pub const O_RDWR: c_int = 2; - pub const O_APPEND: c_int = 1024; - pub const O_CREAT: c_int = 64; - pub const O_EXCL: c_int = 128; - pub const O_NOCTTY: c_int = 256; - pub const O_TRUNC: c_int = 512; - pub const S_IFIFO: mode_t = 4096; - pub const S_IFCHR: mode_t = 8192; - pub const S_IFBLK: mode_t = 24576; - pub const S_IFDIR: mode_t = 16384; - pub const S_IFREG: mode_t = 32768; - pub const S_IFLNK: mode_t = 40960; - pub const S_IFSOCK: mode_t = 49152; - pub const S_IFMT: mode_t = 61440; - pub const S_IEXEC: mode_t = 64; - pub const S_IWRITE: mode_t = 128; - pub const S_IREAD: mode_t = 256; - pub const S_IRWXU: mode_t = 448; - pub const S_IXUSR: mode_t = 64; - pub const S_IWUSR: mode_t = 128; - pub const S_IRUSR: mode_t = 256; - pub const S_IRWXG: mode_t = 56; - pub const S_IXGRP: mode_t = 8; - pub const S_IWGRP: mode_t = 16; - pub const S_IRGRP: mode_t = 32; - pub const S_IRWXO: mode_t = 7; - pub const S_IXOTH: mode_t = 1; - pub const S_IWOTH: mode_t = 2; - pub const S_IROTH: mode_t = 4; - pub const F_OK: c_int = 0; - pub const R_OK: c_int = 4; - pub const W_OK: c_int = 2; - pub const X_OK: c_int = 1; - pub const STDIN_FILENO: c_int = 0; - pub const STDOUT_FILENO: c_int = 1; - pub const STDERR_FILENO: c_int = 2; - pub const F_LOCK: c_int = 1; - pub const F_TEST: c_int = 3; - pub const F_TLOCK: c_int = 2; - pub const F_ULOCK: c_int = 0; - pub const SIGHUP: c_int = 1; - pub const SIGINT: c_int = 2; - pub const SIGQUIT: c_int = 3; - pub const SIGILL: c_int = 4; - pub const SIGABRT: c_int = 6; - pub const SIGFPE: c_int = 8; - pub const SIGKILL: c_int = 9; - pub const SIGSEGV: c_int = 11; - pub const SIGPIPE: c_int = 13; - pub const SIGALRM: c_int = 14; - pub const SIGTERM: c_int = 15; - - pub const PROT_NONE: c_int = 0; - pub const PROT_READ: c_int = 1; - pub const PROT_WRITE: c_int = 2; - pub const PROT_EXEC: c_int = 4; - - pub const MAP_FILE: c_int = 0x0000; - pub const MAP_SHARED: c_int = 0x0001; - pub const MAP_PRIVATE: c_int = 0x0002; - pub const MAP_FIXED: c_int = 0x0010; - pub const MAP_ANON: c_int = 0x0020; - - pub const MAP_FAILED: *mut c_void = !0 as *mut c_void; - - pub const MCL_CURRENT: c_int = 0x0001; - pub const MCL_FUTURE: c_int = 0x0002; - - pub const MS_ASYNC: c_int = 0x0001; - pub const MS_INVALIDATE: c_int = 0x0002; - pub const MS_SYNC: c_int = 0x0004; - - pub const EPERM: c_int = 1; - pub const ENOENT: c_int = 2; - pub const ESRCH: c_int = 3; - pub const EINTR: c_int = 4; - pub const EIO: c_int = 5; - pub const ENXIO: c_int = 6; - pub const E2BIG: c_int = 7; - pub const ENOEXEC: c_int = 8; - pub const EBADF: c_int = 9; - pub const ECHILD: c_int = 10; - pub const EAGAIN: c_int = 11; - pub const ENOMEM: c_int = 12; - pub const EACCES: c_int = 13; - pub const EFAULT: c_int = 14; - pub const ENOTBLK: c_int = 15; - pub const EBUSY: c_int = 16; - pub const EEXIST: c_int = 17; - pub const EXDEV: c_int = 18; - pub const ENODEV: c_int = 19; - pub const ENOTDIR: c_int = 20; - pub const EISDIR: c_int = 21; - pub const EINVAL: c_int = 22; - pub const ENFILE: c_int = 23; - pub const EMFILE: c_int = 24; - pub const ENOTTY: c_int = 25; - pub const ETXTBSY: c_int = 26; - pub const EFBIG: c_int = 27; - pub const ENOSPC: c_int = 28; - pub const ESPIPE: c_int = 29; - pub const EROFS: c_int = 30; - pub const EMLINK: c_int = 31; - pub const EPIPE: c_int = 32; - pub const EDOM: c_int = 33; - pub const ERANGE: c_int = 34; - - pub const EDEADLK: c_int = 35; - pub const ENAMETOOLONG: c_int = 36; - pub const ENOLCK: c_int = 37; - pub const ENOSYS: c_int = 38; - pub const ENOTEMPTY: c_int = 39; - pub const ELOOP: c_int = 40; - pub const EWOULDBLOCK: c_int = EAGAIN; - pub const ENOMSG: c_int = 42; - pub const EIDRM: c_int = 43; - pub const ECHRNG: c_int = 44; - pub const EL2NSYNC: c_int = 45; - pub const EL3HLT: c_int = 46; - pub const EL3RST: c_int = 47; - pub const ELNRNG: c_int = 48; - pub const EUNATCH: c_int = 49; - pub const ENOCSI: c_int = 50; - pub const EL2HLT: c_int = 51; - pub const EBADE: c_int = 52; - pub const EBADR: c_int = 53; - pub const EXFULL: c_int = 54; - pub const ENOANO: c_int = 55; - pub const EBADRQC: c_int = 56; - pub const EBADSLT: c_int = 57; - - pub const EDEADLOCK: c_int = EDEADLK; - - pub const EBFONT: c_int = 59; - pub const ENOSTR: c_int = 60; - pub const ENODATA: c_int = 61; - pub const ETIME: c_int = 62; - pub const ENOSR: c_int = 63; - pub const ENONET: c_int = 64; - pub const ENOPKG: c_int = 65; - pub const EREMOTE: c_int = 66; - pub const ENOLINK: c_int = 67; - pub const EADV: c_int = 68; - pub const ESRMNT: c_int = 69; - pub const ECOMM: c_int = 70; - pub const EPROTO: c_int = 71; - pub const EMULTIHOP: c_int = 72; - pub const EDOTDOT: c_int = 73; - pub const EBADMSG: c_int = 74; - pub const EOVERFLOW: c_int = 75; - pub const ENOTUNIQ: c_int = 76; - pub const EBADFD: c_int = 77; - pub const EREMCHG: c_int = 78; - pub const ELIBACC: c_int = 79; - pub const ELIBBAD: c_int = 80; - pub const ELIBSCN: c_int = 81; - pub const ELIBMAX: c_int = 82; - pub const ELIBEXEC: c_int = 83; - pub const EILSEQ: c_int = 84; - pub const ERESTART: c_int = 85; - pub const ESTRPIPE: c_int = 86; - pub const EUSERS: c_int = 87; - pub const ENOTSOCK: c_int = 88; - pub const EDESTADDRREQ: c_int = 89; - pub const EMSGSIZE: c_int = 90; - pub const EPROTOTYPE: c_int = 91; - pub const ENOPROTOOPT: c_int = 92; - pub const EPROTONOSUPPORT: c_int = 93; - pub const ESOCKTNOSUPPORT: c_int = 94; - pub const EOPNOTSUPP: c_int = 95; - pub const EPFNOSUPPORT: c_int = 96; - pub const EAFNOSUPPORT: c_int = 97; - pub const EADDRINUSE: c_int = 98; - pub const EADDRNOTAVAIL: c_int = 99; - pub const ENETDOWN: c_int = 100; - pub const ENETUNREACH: c_int = 101; - pub const ENETRESET: c_int = 102; - pub const ECONNABORTED: c_int = 103; - pub const ECONNRESET: c_int = 104; - pub const ENOBUFS: c_int = 105; - pub const EISCONN: c_int = 106; - pub const ENOTCONN: c_int = 107; - pub const ESHUTDOWN: c_int = 108; - pub const ETOOMANYREFS: c_int = 109; - pub const ETIMEDOUT: c_int = 110; - pub const ECONNREFUSED: c_int = 111; - pub const EHOSTDOWN: c_int = 112; - pub const EHOSTUNREACH: c_int = 113; - pub const EALREADY: c_int = 114; - pub const EINPROGRESS: c_int = 115; - pub const ESTALE: c_int = 116; - pub const EUCLEAN: c_int = 117; - pub const ENOTNAM: c_int = 118; - pub const ENAVAIL: c_int = 119; - pub const EISNAM: c_int = 120; - pub const EREMOTEIO: c_int = 121; - pub const EDQUOT: c_int = 122; - - pub const ENOMEDIUM: c_int = 123; - pub const EMEDIUMTYPE: c_int = 124; - pub const ECANCELED: c_int = 125; - pub const ENOKEY: c_int = 126; - pub const EKEYEXPIRED: c_int = 127; - pub const EKEYREVOKED: c_int = 128; - pub const EKEYREJECTED: c_int = 129; - - pub const EOWNERDEAD: c_int = 130; - pub const ENOTRECOVERABLE: c_int = 131; - - pub const ERFKILL: c_int = 132; - - pub const EHWPOISON: c_int = 133; - } - - #[cfg(any(target_arch = "mips", - target_arch = "mipsel"))] - pub mod posix88 { - use types::os::arch::c95::c_int; - use types::common::c95::c_void; - use types::os::arch::posix88::mode_t; - - pub const O_RDONLY: c_int = 0; - pub const O_WRONLY: c_int = 1; - pub const O_RDWR: c_int = 2; - pub const O_APPEND: c_int = 8; - pub const O_CREAT: c_int = 256; - pub const O_EXCL: c_int = 1024; - pub const O_NOCTTY: c_int = 2048; - pub const O_TRUNC: c_int = 512; - pub const S_IFIFO: mode_t = 4096; - pub const S_IFCHR: mode_t = 8192; - pub const S_IFBLK: mode_t = 24576; - pub const S_IFDIR: mode_t = 16384; - pub const S_IFREG: mode_t = 32768; - pub const S_IFLNK: mode_t = 40960; - pub const S_IFSOCK: mode_t = 49152; - pub const S_IFMT: mode_t = 61440; - pub const S_IEXEC: mode_t = 64; - pub const S_IWRITE: mode_t = 128; - pub const S_IREAD: mode_t = 256; - pub const S_IRWXU: mode_t = 448; - pub const S_IXUSR: mode_t = 64; - pub const S_IWUSR: mode_t = 128; - pub const S_IRUSR: mode_t = 256; - pub const S_IRWXG: mode_t = 56; - pub const S_IXGRP: mode_t = 8; - pub const S_IWGRP: mode_t = 16; - pub const S_IRGRP: mode_t = 32; - pub const S_IRWXO: mode_t = 7; - pub const S_IXOTH: mode_t = 1; - pub const S_IWOTH: mode_t = 2; - pub const S_IROTH: mode_t = 4; - pub const F_OK: c_int = 0; - pub const R_OK: c_int = 4; - pub const W_OK: c_int = 2; - pub const X_OK: c_int = 1; - pub const STDIN_FILENO: c_int = 0; - pub const STDOUT_FILENO: c_int = 1; - pub const STDERR_FILENO: c_int = 2; - pub const F_LOCK: c_int = 1; - pub const F_TEST: c_int = 3; - pub const F_TLOCK: c_int = 2; - pub const F_ULOCK: c_int = 0; - pub const SIGHUP: c_int = 1; - pub const SIGINT: c_int = 2; - pub const SIGQUIT: c_int = 3; - pub const SIGILL: c_int = 4; - pub const SIGABRT: c_int = 6; - pub const SIGFPE: c_int = 8; - pub const SIGKILL: c_int = 9; - pub const SIGSEGV: c_int = 11; - pub const SIGPIPE: c_int = 13; - pub const SIGALRM: c_int = 14; - pub const SIGTERM: c_int = 15; - - pub const PROT_NONE: c_int = 0; - pub const PROT_READ: c_int = 1; - pub const PROT_WRITE: c_int = 2; - pub const PROT_EXEC: c_int = 4; - - pub const MAP_FILE: c_int = 0x0000; - pub const MAP_SHARED: c_int = 0x0001; - pub const MAP_PRIVATE: c_int = 0x0002; - pub const MAP_FIXED: c_int = 0x0010; - pub const MAP_ANON: c_int = 0x0800; - - pub const MAP_FAILED: *mut c_void = !0 as *mut c_void; - - pub const MCL_CURRENT: c_int = 0x0001; - pub const MCL_FUTURE: c_int = 0x0002; - - pub const MS_ASYNC: c_int = 0x0001; - pub const MS_INVALIDATE: c_int = 0x0002; - pub const MS_SYNC: c_int = 0x0004; - - pub const EPERM: c_int = 1; - pub const ENOENT: c_int = 2; - pub const ESRCH: c_int = 3; - pub const EINTR: c_int = 4; - pub const EIO: c_int = 5; - pub const ENXIO: c_int = 6; - pub const E2BIG: c_int = 7; - pub const ENOEXEC: c_int = 8; - pub const EBADF: c_int = 9; - pub const ECHILD: c_int = 10; - pub const EAGAIN: c_int = 11; - pub const ENOMEM: c_int = 12; - pub const EACCES: c_int = 13; - pub const EFAULT: c_int = 14; - pub const ENOTBLK: c_int = 15; - pub const EBUSY: c_int = 16; - pub const EEXIST: c_int = 17; - pub const EXDEV: c_int = 18; - pub const ENODEV: c_int = 19; - pub const ENOTDIR: c_int = 20; - pub const EISDIR: c_int = 21; - pub const EINVAL: c_int = 22; - pub const ENFILE: c_int = 23; - pub const EMFILE: c_int = 24; - pub const ENOTTY: c_int = 25; - pub const ETXTBSY: c_int = 26; - pub const EFBIG: c_int = 27; - pub const ENOSPC: c_int = 28; - pub const ESPIPE: c_int = 29; - pub const EROFS: c_int = 30; - pub const EMLINK: c_int = 31; - pub const EPIPE: c_int = 32; - pub const EDOM: c_int = 33; - pub const ERANGE: c_int = 34; - - pub const ENOMSG: c_int = 35; - pub const EIDRM: c_int = 36; - pub const ECHRNG: c_int = 37; - pub const EL2NSYNC: c_int = 38; - pub const EL3HLT: c_int = 39; - pub const EL3RST: c_int = 40; - pub const ELNRNG: c_int = 41; - pub const EUNATCH: c_int = 42; - pub const ENOCSI: c_int = 43; - pub const EL2HLT: c_int = 44; - pub const EDEADLK: c_int = 45; - pub const ENOLCK: c_int = 46; - pub const EBADE: c_int = 50; - pub const EBADR: c_int = 51; - pub const EXFULL: c_int = 52; - pub const ENOANO: c_int = 53; - pub const EBADRQC: c_int = 54; - pub const EBADSLT: c_int = 55; - pub const EDEADLOCK: c_int = 56; - pub const EBFONT: c_int = 59; - pub const ENOSTR: c_int = 60; - pub const ENODATA: c_int = 61; - pub const ETIME: c_int = 62; - pub const ENOSR: c_int = 63; - pub const ENONET: c_int = 64; - pub const ENOPKG: c_int = 65; - pub const EREMOTE: c_int = 66; - pub const ENOLINK: c_int = 67; - pub const EADV: c_int = 68; - pub const ESRMNT: c_int = 69; - pub const ECOMM: c_int = 70; - pub const EPROTO: c_int = 71; - pub const EDOTDOT: c_int = 73; - pub const EMULTIHOP: c_int = 74; - pub const EBADMSG: c_int = 77; - pub const ENAMETOOLONG: c_int = 78; - pub const EOVERFLOW: c_int = 79; - pub const ENOTUNIQ: c_int = 80; - pub const EBADFD: c_int = 81; - pub const EREMCHG: c_int = 82; - pub const ELIBACC: c_int = 83; - pub const ELIBBAD: c_int = 84; - pub const ELIBSCN: c_int = 95; - pub const ELIBMAX: c_int = 86; - pub const ELIBEXEC: c_int = 87; - pub const EILSEQ: c_int = 88; - pub const ENOSYS: c_int = 89; - pub const ELOOP: c_int = 90; - pub const ERESTART: c_int = 91; - pub const ESTRPIPE: c_int = 92; - pub const ENOTEMPTY: c_int = 93; - pub const EUSERS: c_int = 94; - pub const ENOTSOCK: c_int = 95; - pub const EDESTADDRREQ: c_int = 96; - pub const EMSGSIZE: c_int = 97; - pub const EPROTOTYPE: c_int = 98; - pub const ENOPROTOOPT: c_int = 99; - pub const EPROTONOSUPPORT: c_int = 120; - pub const ESOCKTNOSUPPORT: c_int = 121; - pub const EOPNOTSUPP: c_int = 122; - pub const EPFNOSUPPORT: c_int = 123; - pub const EAFNOSUPPORT: c_int = 124; - pub const EADDRINUSE: c_int = 125; - pub const EADDRNOTAVAIL: c_int = 126; - pub const ENETDOWN: c_int = 127; - pub const ENETUNREACH: c_int = 128; - pub const ENETRESET: c_int = 129; - pub const ECONNABORTED: c_int = 130; - pub const ECONNRESET: c_int = 131; - pub const ENOBUFS: c_int = 132; - pub const EISCONN: c_int = 133; - pub const ENOTCONN: c_int = 134; - pub const EUCLEAN: c_int = 135; - pub const ENOTNAM: c_int = 137; - pub const ENAVAIL: c_int = 138; - pub const EISNAM: c_int = 139; - pub const EREMOTEIO: c_int = 140; - pub const ESHUTDOWN: c_int = 143; - pub const ETOOMANYREFS: c_int = 144; - pub const ETIMEDOUT: c_int = 145; - pub const ECONNREFUSED: c_int = 146; - pub const EHOSTDOWN: c_int = 147; - pub const EHOSTUNREACH: c_int = 148; - pub const EWOULDBLOCK: c_int = EAGAIN; - pub const EALREADY: c_int = 149; - pub const EINPROGRESS: c_int = 150; - pub const ESTALE: c_int = 151; - pub const ECANCELED: c_int = 158; - - pub const ENOMEDIUM: c_int = 159; - pub const EMEDIUMTYPE: c_int = 160; - pub const ENOKEY: c_int = 161; - pub const EKEYEXPIRED: c_int = 162; - pub const EKEYREVOKED: c_int = 163; - pub const EKEYREJECTED: c_int = 164; - - pub const EOWNERDEAD: c_int = 165; - pub const ENOTRECOVERABLE: c_int = 166; - - pub const ERFKILL: c_int = 167; - - pub const EHWPOISON: c_int = 168; - - pub const EDQUOT: c_int = 1133; - } - #[cfg(not(target_os = "nacl"))] - pub mod posix01 { - use types::os::arch::c95::{c_int, size_t}; - use types::os::common::posix01::rlim_t; - - pub const F_DUPFD: c_int = 0; - pub const F_GETFD: c_int = 1; - pub const F_SETFD: c_int = 2; - pub const F_GETFL: c_int = 3; - pub const F_SETFL: c_int = 4; - - pub const O_ACCMODE: c_int = 3; - - pub const SIGTRAP: c_int = 5; - pub const SIG_IGN: size_t = 1; - - pub const GLOB_ERR: c_int = 1 << 0; - pub const GLOB_MARK: c_int = 1 << 1; - pub const GLOB_NOSORT: c_int = 1 << 2; - pub const GLOB_DOOFFS: c_int = 1 << 3; - pub const GLOB_NOCHECK: c_int = 1 << 4; - pub const GLOB_APPEND: c_int = 1 << 5; - pub const GLOB_NOESCAPE: c_int = 1 << 6; - - pub const GLOB_NOSPACE: c_int = 1; - pub const GLOB_ABORTED: c_int = 2; - pub const GLOB_NOMATCH: c_int = 3; - - pub const POSIX_MADV_NORMAL: c_int = 0; - pub const POSIX_MADV_RANDOM: c_int = 1; - pub const POSIX_MADV_SEQUENTIAL: c_int = 2; - pub const POSIX_MADV_WILLNEED: c_int = 3; - pub const POSIX_MADV_DONTNEED: c_int = 4; - - pub const _SC_MQ_PRIO_MAX: c_int = 28; - pub const _SC_IOV_MAX: c_int = 60; - pub const _SC_GETGR_R_SIZE_MAX: c_int = 69; - pub const _SC_GETPW_R_SIZE_MAX: c_int = 70; - pub const _SC_LOGIN_NAME_MAX: c_int = 71; - pub const _SC_TTY_NAME_MAX: c_int = 72; - pub const _SC_THREADS: c_int = 67; - pub const _SC_THREAD_SAFE_FUNCTIONS: c_int = 68; - pub const _SC_THREAD_DESTRUCTOR_ITERATIONS: c_int = 73; - pub const _SC_THREAD_KEYS_MAX: c_int = 74; - pub const _SC_THREAD_STACK_MIN: c_int = 75; - pub const _SC_THREAD_THREADS_MAX: c_int = 76; - pub const _SC_THREAD_ATTR_STACKADDR: c_int = 77; - pub const _SC_THREAD_ATTR_STACKSIZE: c_int = 78; - pub const _SC_THREAD_PRIORITY_SCHEDULING: c_int = 79; - pub const _SC_THREAD_PRIO_INHERIT: c_int = 80; - pub const _SC_THREAD_PRIO_PROTECT: c_int = 81; - pub const _SC_THREAD_PROCESS_SHARED: c_int = 82; - pub const _SC_ATEXIT_MAX: c_int = 87; - pub const _SC_XOPEN_VERSION: c_int = 89; - pub const _SC_XOPEN_XCU_VERSION: c_int = 90; - pub const _SC_XOPEN_UNIX: c_int = 91; - pub const _SC_XOPEN_CRYPT: c_int = 92; - pub const _SC_XOPEN_ENH_I18N: c_int = 93; - pub const _SC_XOPEN_SHM: c_int = 94; - pub const _SC_XOPEN_LEGACY: c_int = 129; - pub const _SC_XOPEN_REALTIME: c_int = 130; - pub const _SC_XOPEN_REALTIME_THREADS: c_int = 131; - - - - pub const PTHREAD_CREATE_JOINABLE: c_int = 0; - pub const PTHREAD_CREATE_DETACHED: c_int = 1; - - #[cfg(target_os = "android")] - pub const PTHREAD_STACK_MIN: size_t = 8192; - - #[cfg(all(target_os = "linux", - any(target_arch = "arm", - target_arch = "x86", - target_arch = "x86_64")))] - pub const PTHREAD_STACK_MIN: size_t = 16384; - - #[cfg(all(target_os = "linux", - any(target_arch = "mips", - target_arch = "mipsel", - target_arch = "aarch64", - target_arch = "powerpc")))] - pub const PTHREAD_STACK_MIN: size_t = 131072; - - pub const CLOCK_REALTIME: c_int = 0; - pub const CLOCK_MONOTONIC: c_int = 1; - - pub const RLIMIT_CPU: c_int = 0; - pub const RLIMIT_FSIZE: c_int = 1; - pub const RLIMIT_DATA: c_int = 2; - pub const RLIMIT_STACK: c_int = 3; - pub const RLIMIT_CORE: c_int = 4; - pub const RLIMIT_RSS: c_int = 5; - pub const RLIMIT_NOFILE: c_int = 7; - pub const RLIMIT_AS: c_int = 9; - pub const RLIMIT_NPROC: c_int = 6; - pub const RLIMIT_MEMLOCK: c_int = 8; - pub const RLIMIT_LOCKS: c_int = 10; - pub const RLIMIT_SIGPENDING: c_int = 11; - pub const RLIMIT_MSGQUEUE: c_int = 12; - pub const RLIMIT_NICE: c_int = 13; - pub const RLIMIT_RTPRIO: c_int = 14; - pub const RLIMIT_RTTIME: c_int = 15; - pub const RLIMIT_NLIMITS: c_int = 16; - pub const RLIM_INFINITY: rlim_t = 0xffff_ffff_ffff_ffff; - pub const RLIM_SAVED_MAX: rlim_t = RLIM_INFINITY; - pub const RLIM_SAVED_CUR: rlim_t = RLIM_INFINITY; - - pub const RUSAGE_SELF: c_int = 0; - pub const RUSAGE_CHILDREN: c_int = -1; - pub const RUSAGE_THREAD: c_int = 1; - } - #[cfg(target_os = "nacl")] - pub mod posix01 { - use types::os::arch::c95::{c_int, size_t}; - use types::os::common::posix01::rlim_t; - - pub const F_DUPFD: c_int = 0; - pub const F_GETFD: c_int = 1; - pub const F_SETFD: c_int = 2; - pub const F_GETFL: c_int = 3; - pub const F_SETFL: c_int = 4; - - pub const SIGTRAP: c_int = 5; - pub const SIG_IGN: size_t = 1; - - pub const GLOB_ERR: c_int = 1 << 0; - pub const GLOB_MARK: c_int = 1 << 1; - pub const GLOB_NOSORT: c_int = 1 << 2; - pub const GLOB_DOOFFS: c_int = 1 << 3; - pub const GLOB_NOCHECK: c_int = 1 << 4; - pub const GLOB_APPEND: c_int = 1 << 5; - pub const GLOB_NOESCAPE: c_int = 1 << 6; - - pub const GLOB_NOSPACE: c_int = 1; - pub const GLOB_ABORTED: c_int = 2; - pub const GLOB_NOMATCH: c_int = 3; - - pub const POSIX_MADV_NORMAL: c_int = 0; - pub const POSIX_MADV_RANDOM: c_int = 1; - pub const POSIX_MADV_SEQUENTIAL: c_int = 2; - pub const POSIX_MADV_WILLNEED: c_int = 3; - pub const POSIX_MADV_DONTNEED: c_int = 4; - - pub const _SC_MQ_PRIO_MAX: c_int = 28; - pub const _SC_IOV_MAX: c_int = 60; - pub const _SC_GETGR_R_SIZE_MAX: c_int = 69; - pub const _SC_GETPW_R_SIZE_MAX: c_int = 70; - pub const _SC_LOGIN_NAME_MAX: c_int = 71; - pub const _SC_TTY_NAME_MAX: c_int = 72; - pub const _SC_THREADS: c_int = 67; - pub const _SC_THREAD_SAFE_FUNCTIONS: c_int = 68; - pub const _SC_THREAD_DESTRUCTOR_ITERATIONS: c_int = 73; - pub const _SC_THREAD_KEYS_MAX: c_int = 74; - pub const _SC_THREAD_STACK_MIN: c_int = 75; - pub const _SC_THREAD_THREADS_MAX: c_int = 76; - pub const _SC_THREAD_ATTR_STACKADDR: c_int = 77; - pub const _SC_THREAD_ATTR_STACKSIZE: c_int = 78; - pub const _SC_THREAD_PRIORITY_SCHEDULING: c_int = 79; - pub const _SC_THREAD_PRIO_INHERIT: c_int = 80; - pub const _SC_THREAD_PRIO_PROTECT: c_int = 81; - pub const _SC_THREAD_PROCESS_SHARED: c_int = 82; - pub const _SC_ATEXIT_MAX: c_int = 87; - pub const _SC_XOPEN_VERSION: c_int = 89; - pub const _SC_XOPEN_XCU_VERSION: c_int = 90; - pub const _SC_XOPEN_UNIX: c_int = 91; - pub const _SC_XOPEN_CRYPT: c_int = 92; - pub const _SC_XOPEN_ENH_I18N: c_int = 93; - pub const _SC_XOPEN_SHM: c_int = 94; - pub const _SC_XOPEN_LEGACY: c_int = 129; - pub const _SC_XOPEN_REALTIME: c_int = 130; - pub const _SC_XOPEN_REALTIME_THREADS: c_int = 131; - - pub const PTHREAD_CREATE_JOINABLE: c_int = 1; - pub const PTHREAD_CREATE_DETACHED: c_int = 0; - - pub const PTHREAD_STACK_MIN: size_t = 1024; - - pub const CLOCK_REALTIME: c_int = 0; - pub const CLOCK_MONOTONIC: c_int = 1; - - pub const RLIMIT_CPU: c_int = 0; - pub const RLIMIT_FSIZE: c_int = 1; - pub const RLIMIT_DATA: c_int = 2; - pub const RLIMIT_STACK: c_int = 3; - pub const RLIMIT_CORE: c_int = 4; - pub const RLIMIT_RSS: c_int = 5; - pub const RLIMIT_NOFILE: c_int = 7; - pub const RLIMIT_AS: c_int = 9; - pub const RLIMIT_NPROC: c_int = 6; - pub const RLIMIT_MEMLOCK: c_int = 8; - pub const RLIMIT_LOCKS: c_int = 10; - pub const RLIMIT_SIGPENDING: c_int = 11; - pub const RLIMIT_MSGQUEUE: c_int = 12; - pub const RLIMIT_NICE: c_int = 13; - pub const RLIMIT_RTPRIO: c_int = 14; - pub const RLIMIT_RTTIME: c_int = 15; - pub const RLIMIT_NLIMITS: c_int = 16; - - pub const RLIM_INFINITY: rlim_t = 0xffff_ffff_ffff_ffff; - pub const RLIM_SAVED_MAX: rlim_t = RLIM_INFINITY; - pub const RLIM_SAVED_CUR: rlim_t = RLIM_INFINITY; - - pub const RUSAGE_SELF: c_int = 0; - pub const RUSAGE_CHILDREN: c_int = -1; - pub const RUSAGE_THREAD: c_int = 1; - } - pub mod posix08 { - use types::os::arch::c95::c_int; - pub const O_CLOEXEC: c_int = 0x80000; - pub const F_DUPFD_CLOEXEC: c_int = 1030; - } - #[cfg(any(target_arch = "arm", - target_arch = "aarch64", - target_arch = "x86", - target_arch = "x86_64", - target_arch = "le32", - target_arch = "powerpc"))] - pub mod bsd44 { - use types::os::arch::c95::c_int; - - pub const MADV_NORMAL: c_int = 0; - pub const MADV_RANDOM: c_int = 1; - pub const MADV_SEQUENTIAL: c_int = 2; - pub const MADV_WILLNEED: c_int = 3; - pub const MADV_DONTNEED: c_int = 4; - pub const MADV_REMOVE: c_int = 9; - pub const MADV_DONTFORK: c_int = 10; - pub const MADV_DOFORK: c_int = 11; - pub const MADV_MERGEABLE: c_int = 12; - pub const MADV_UNMERGEABLE: c_int = 13; - pub const MADV_HWPOISON: c_int = 100; - - pub const IFF_LOOPBACK: c_int = 0x8; - - pub const AF_UNIX: c_int = 1; - pub const AF_INET: c_int = 2; - pub const AF_INET6: c_int = 10; - pub const SOCK_STREAM: c_int = 1; - pub const SOCK_DGRAM: c_int = 2; - pub const SOCK_RAW: c_int = 3; - pub const IPPROTO_TCP: c_int = 6; - pub const IPPROTO_IP: c_int = 0; - pub const IPPROTO_IPV6: c_int = 41; - pub const IP_MULTICAST_TTL: c_int = 33; - pub const IP_MULTICAST_LOOP: c_int = 34; - pub const IP_TTL: c_int = 2; - pub const IP_HDRINCL: c_int = 3; - pub const IP_ADD_MEMBERSHIP: c_int = 35; - pub const IP_DROP_MEMBERSHIP: c_int = 36; - pub const IPV6_ADD_MEMBERSHIP: c_int = 20; - pub const IPV6_DROP_MEMBERSHIP: c_int = 21; - - pub const TCP_NODELAY: c_int = 1; - pub const TCP_MAXSEG: c_int = 2; - pub const TCP_CORK: c_int = 3; - pub const TCP_KEEPIDLE: c_int = 4; - pub const TCP_KEEPINTVL: c_int = 5; - pub const TCP_KEEPCNT: c_int = 6; - pub const TCP_SYNCNT: c_int = 7; - pub const TCP_LINGER2: c_int = 8; - pub const TCP_DEFER_ACCEPT: c_int = 9; - pub const TCP_WINDOW_CLAMP: c_int = 10; - pub const TCP_INFO: c_int = 11; - pub const TCP_QUICKACK: c_int = 12; - pub const TCP_CONGESTION: c_int = 13; - pub const TCP_MD5SIG: c_int = 14; - pub const TCP_COOKIE_TRANSACTIONS: c_int = 15; - pub const TCP_THIN_LINEAR_TIMEOUTS: c_int = 16; - pub const TCP_THIN_DUPACK: c_int = 17; - pub const TCP_USER_TIMEOUT: c_int = 18; - pub const TCP_REPAIR: c_int = 19; - pub const TCP_REPAIR_QUEUE: c_int = 20; - pub const TCP_QUEUE_SEQ: c_int = 21; - pub const TCP_REPAIR_OPTIONS: c_int = 22; - pub const TCP_FASTOPEN: c_int = 23; - pub const TCP_TIMESTAMP: c_int = 24; - - pub const SOL_SOCKET: c_int = 1; - - pub const SO_DEBUG: c_int = 1; - pub const SO_REUSEADDR: c_int = 2; - pub const SO_TYPE: c_int = 3; - pub const SO_ERROR: c_int = 4; - pub const SO_DONTROUTE: c_int = 5; - pub const SO_BROADCAST: c_int = 6; - pub const SO_SNDBUF: c_int = 7; - pub const SO_RCVBUF: c_int = 8; - pub const SO_KEEPALIVE: c_int = 9; - pub const SO_OOBINLINE: c_int = 10; - pub const SO_LINGER: c_int = 13; - pub const SO_REUSEPORT: c_int = 15; - pub const SO_RCVLOWAT: c_int = 18; - pub const SO_SNDLOWAT: c_int = 19; - pub const SO_RCVTIMEO: c_int = 20; - pub const SO_SNDTIMEO: c_int = 21; - pub const SO_ACCEPTCONN: c_int = 30; - - pub const SHUT_RD: c_int = 0; - pub const SHUT_WR: c_int = 1; - pub const SHUT_RDWR: c_int = 2; - - pub const LOCK_SH: c_int = 1; - pub const LOCK_EX: c_int = 2; - pub const LOCK_NB: c_int = 4; - pub const LOCK_UN: c_int = 8; - } - #[cfg(any(target_arch = "mips", - target_arch = "mipsel"))] - pub mod bsd44 { - use types::os::arch::c95::c_int; - - pub const MADV_NORMAL: c_int = 0; - pub const MADV_RANDOM: c_int = 1; - pub const MADV_SEQUENTIAL: c_int = 2; - pub const MADV_WILLNEED: c_int = 3; - pub const MADV_DONTNEED: c_int = 4; - pub const MADV_REMOVE: c_int = 9; - pub const MADV_DONTFORK: c_int = 10; - pub const MADV_DOFORK: c_int = 11; - pub const MADV_MERGEABLE: c_int = 12; - pub const MADV_UNMERGEABLE: c_int = 13; - pub const MADV_HWPOISON: c_int = 100; - - pub const AF_UNIX: c_int = 1; - pub const AF_INET: c_int = 2; - pub const AF_INET6: c_int = 10; - pub const SOCK_STREAM: c_int = 2; - pub const SOCK_DGRAM: c_int = 1; - pub const SOCK_RAW: c_int = 3; - pub const IPPROTO_TCP: c_int = 6; - pub const IPPROTO_IP: c_int = 0; - pub const IPPROTO_IPV6: c_int = 41; - pub const IP_MULTICAST_TTL: c_int = 33; - pub const IP_MULTICAST_LOOP: c_int = 34; - pub const IP_TTL: c_int = 2; - pub const IP_HDRINCL: c_int = 3; - pub const IP_ADD_MEMBERSHIP: c_int = 35; - pub const IP_DROP_MEMBERSHIP: c_int = 36; - pub const IPV6_ADD_MEMBERSHIP: c_int = 20; - pub const IPV6_DROP_MEMBERSHIP: c_int = 21; - - pub const TCP_NODELAY: c_int = 1; - pub const TCP_MAXSEG: c_int = 2; - pub const TCP_CORK: c_int = 3; - pub const TCP_KEEPIDLE: c_int = 4; - pub const TCP_KEEPINTVL: c_int = 5; - pub const TCP_KEEPCNT: c_int = 6; - pub const TCP_SYNCNT: c_int = 7; - pub const TCP_LINGER2: c_int = 8; - pub const TCP_DEFER_ACCEPT: c_int = 9; - pub const TCP_WINDOW_CLAMP: c_int = 10; - pub const TCP_INFO: c_int = 11; - pub const TCP_QUICKACK: c_int = 12; - pub const TCP_CONGESTION: c_int = 13; - pub const TCP_MD5SIG: c_int = 14; - pub const TCP_COOKIE_TRANSACTIONS: c_int = 15; - pub const TCP_THIN_LINEAR_TIMEOUTS: c_int = 16; - pub const TCP_THIN_DUPACK: c_int = 17; - pub const TCP_USER_TIMEOUT: c_int = 18; - pub const TCP_REPAIR: c_int = 19; - pub const TCP_REPAIR_QUEUE: c_int = 20; - pub const TCP_QUEUE_SEQ: c_int = 21; - pub const TCP_REPAIR_OPTIONS: c_int = 22; - pub const TCP_FASTOPEN: c_int = 23; - pub const TCP_TIMESTAMP: c_int = 24; - - pub const SOL_SOCKET: c_int = 65535; - - pub const SO_DEBUG: c_int = 0x0001; - pub const SO_REUSEADDR: c_int = 0x0004; - pub const SO_KEEPALIVE: c_int = 0x0008; - pub const SO_DONTROUTE: c_int = 0x0010; - pub const SO_BROADCAST: c_int = 0x0020; - pub const SO_LINGER: c_int = 0x0080; - pub const SO_OOBINLINE: c_int = 0x100; - pub const SO_REUSEPORT: c_int = 0x0200; - pub const SO_SNDBUF: c_int = 0x1001; - pub const SO_RCVBUF: c_int = 0x1002; - pub const SO_SNDLOWAT: c_int = 0x1003; - pub const SO_RCVLOWAT: c_int = 0x1004; - pub const SO_SNDTIMEO: c_int = 0x1005; - pub const SO_RCVTIMEO: c_int = 0x1006; - pub const SO_ERROR: c_int = 0x1007; - pub const SO_TYPE: c_int = 0x1008; - pub const SO_ACCEPTCONN: c_int = 0x1009; - - pub const SHUT_RD: c_int = 0; - pub const SHUT_WR: c_int = 1; - pub const SHUT_RDWR: c_int = 2; - - pub const LOCK_SH: c_int = 1; - pub const LOCK_EX: c_int = 2; - pub const LOCK_NB: c_int = 4; - pub const LOCK_UN: c_int = 8; - } - #[cfg(any(target_arch = "x86", - target_arch = "x86_64", - target_arch = "arm", - target_arch = "aarch64", - target_arch = "le32", - target_arch = "powerpc"))] - pub mod extra { - use types::os::arch::c95::c_int; - - pub const AF_PACKET: c_int = 17; - pub const IPPROTO_RAW: c_int = 255; - - pub const O_RSYNC: c_int = 1052672; - pub const O_DSYNC: c_int = 4096; - pub const O_NONBLOCK: c_int = 2048; - pub const O_SYNC: c_int = 1052672; - - pub const PROT_GROWSDOWN: c_int = 0x010000000; - pub const PROT_GROWSUP: c_int = 0x020000000; - - pub const MAP_TYPE: c_int = 0x000f; - pub const MAP_ANONYMOUS: c_int = 0x0020; - pub const MAP_32BIT: c_int = 0x0040; - pub const MAP_GROWSDOWN: c_int = 0x0100; - pub const MAP_DENYWRITE: c_int = 0x0800; - pub const MAP_EXECUTABLE: c_int = 0x01000; - pub const MAP_LOCKED: c_int = 0x02000; - pub const MAP_NORESERVE: c_int = 0x04000; - pub const MAP_POPULATE: c_int = 0x08000; - pub const MAP_NONBLOCK: c_int = 0x010000; - pub const MAP_STACK: c_int = 0x020000; - - pub const PATH_MAX: c_int = 4096; - } - #[cfg(any(target_arch = "mips", - target_arch = "mipsel"))] - pub mod extra { - use types::os::arch::c95::c_int; - - pub const AF_PACKET: c_int = 17; - pub const IPPROTO_RAW: c_int = 255; - - pub const O_RSYNC: c_int = 16400; - pub const O_DSYNC: c_int = 16; - pub const O_NONBLOCK: c_int = 128; - pub const O_SYNC: c_int = 16400; - - pub const PROT_GROWSDOWN: c_int = 0x01000000; - pub const PROT_GROWSUP: c_int = 0x02000000; - - pub const MAP_TYPE: c_int = 0x000f; - pub const MAP_ANONYMOUS: c_int = 0x0800; - pub const MAP_GROWSDOWN: c_int = 0x01000; - pub const MAP_DENYWRITE: c_int = 0x02000; - pub const MAP_EXECUTABLE: c_int = 0x04000; - pub const MAP_LOCKED: c_int = 0x08000; - pub const MAP_NORESERVE: c_int = 0x0400; - pub const MAP_POPULATE: c_int = 0x010000; - pub const MAP_NONBLOCK: c_int = 0x020000; - pub const MAP_STACK: c_int = 0x040000; - - pub const PATH_MAX: c_int = 4096; - } - #[cfg(target_os = "linux")] - pub mod sysconf { - use types::os::arch::c95::c_int; - - pub const _SC_ARG_MAX: c_int = 0; - pub const _SC_CHILD_MAX: c_int = 1; - pub const _SC_CLK_TCK: c_int = 2; - pub const _SC_NGROUPS_MAX: c_int = 3; - pub const _SC_OPEN_MAX: c_int = 4; - pub const _SC_STREAM_MAX: c_int = 5; - pub const _SC_TZNAME_MAX: c_int = 6; - pub const _SC_JOB_CONTROL: c_int = 7; - pub const _SC_SAVED_IDS: c_int = 8; - pub const _SC_REALTIME_SIGNALS: c_int = 9; - pub const _SC_PRIORITY_SCHEDULING: c_int = 10; - pub const _SC_TIMERS: c_int = 11; - pub const _SC_ASYNCHRONOUS_IO: c_int = 12; - pub const _SC_PRIORITIZED_IO: c_int = 13; - pub const _SC_SYNCHRONIZED_IO: c_int = 14; - pub const _SC_FSYNC: c_int = 15; - pub const _SC_MAPPED_FILES: c_int = 16; - pub const _SC_MEMLOCK: c_int = 17; - pub const _SC_MEMLOCK_RANGE: c_int = 18; - pub const _SC_MEMORY_PROTECTION: c_int = 19; - pub const _SC_MESSAGE_PASSING: c_int = 20; - pub const _SC_SEMAPHORES: c_int = 21; - pub const _SC_SHARED_MEMORY_OBJECTS: c_int = 22; - pub const _SC_AIO_LISTIO_MAX: c_int = 23; - pub const _SC_AIO_MAX: c_int = 24; - pub const _SC_AIO_PRIO_DELTA_MAX: c_int = 25; - pub const _SC_DELAYTIMER_MAX: c_int = 26; - pub const _SC_MQ_OPEN_MAX: c_int = 27; - pub const _SC_VERSION: c_int = 29; - pub const _SC_PAGESIZE: c_int = 30; - pub const _SC_RTSIG_MAX: c_int = 31; - pub const _SC_SEM_NSEMS_MAX: c_int = 32; - pub const _SC_SEM_VALUE_MAX: c_int = 33; - pub const _SC_SIGQUEUE_MAX: c_int = 34; - pub const _SC_TIMER_MAX: c_int = 35; - pub const _SC_BC_BASE_MAX: c_int = 36; - pub const _SC_BC_DIM_MAX: c_int = 37; - pub const _SC_BC_SCALE_MAX: c_int = 38; - pub const _SC_BC_STRING_MAX: c_int = 39; - pub const _SC_COLL_WEIGHTS_MAX: c_int = 40; - pub const _SC_EXPR_NEST_MAX: c_int = 42; - pub const _SC_LINE_MAX: c_int = 43; - pub const _SC_RE_DUP_MAX: c_int = 44; - pub const _SC_2_VERSION: c_int = 46; - pub const _SC_2_C_BIND: c_int = 47; - pub const _SC_2_C_DEV: c_int = 48; - pub const _SC_2_FORT_DEV: c_int = 49; - pub const _SC_2_FORT_RUN: c_int = 50; - pub const _SC_2_SW_DEV: c_int = 51; - pub const _SC_2_LOCALEDEF: c_int = 52; - pub const _SC_NPROCESSORS_ONLN: c_int = 84; - pub const _SC_2_CHAR_TERM: c_int = 95; - pub const _SC_2_C_VERSION: c_int = 96; - pub const _SC_2_UPE: c_int = 97; - pub const _SC_XBS5_ILP32_OFF32: c_int = 125; - pub const _SC_XBS5_ILP32_OFFBIG: c_int = 126; - pub const _SC_XBS5_LPBIG_OFFBIG: c_int = 128; - - pub const _PC_NAME_MAX: c_int = 3; - pub const _PC_PATH_MAX: c_int = 4; - } - #[cfg(target_os = "nacl")] - pub mod sysconf { - use types::os::arch::c95::c_int; - - pub static _SC_SENDMSG_MAX_SIZE: c_int = 0; - pub static _SC_NPROCESSORS_ONLN: c_int = 1; - pub static _SC_PAGESIZE: c_int = 2; - - pub const _PC_NAME_MAX: c_int = 3; - pub const _PC_PATH_MAX: c_int = 4; - } - - #[cfg(target_os = "android")] - pub mod sysconf { - use types::os::arch::c95::c_int; - - pub const _SC_ARG_MAX: c_int = 0; - pub const _SC_BC_BASE_MAX: c_int = 1; - pub const _SC_BC_DIM_MAX: c_int = 2; - pub const _SC_BC_SCALE_MAX: c_int = 3; - pub const _SC_BC_STRING_MAX: c_int = 4; - pub const _SC_CHILD_MAX: c_int = 5; - pub const _SC_CLK_TCK: c_int = 6; - pub const _SC_COLL_WEIGHTS_MAX: c_int = 7; - pub const _SC_EXPR_NEST_MAX: c_int = 8; - pub const _SC_LINE_MAX: c_int = 9; - pub const _SC_NGROUPS_MAX: c_int = 10; - pub const _SC_OPEN_MAX: c_int = 11; - pub const _SC_2_C_BIND: c_int = 13; - pub const _SC_2_C_DEV: c_int = 14; - pub const _SC_2_C_VERSION: c_int = 15; - pub const _SC_2_CHAR_TERM: c_int = 16; - pub const _SC_2_FORT_DEV: c_int = 17; - pub const _SC_2_FORT_RUN: c_int = 18; - pub const _SC_2_LOCALEDEF: c_int = 19; - pub const _SC_2_SW_DEV: c_int = 20; - pub const _SC_2_UPE: c_int = 21; - pub const _SC_2_VERSION: c_int = 22; - pub const _SC_JOB_CONTROL: c_int = 23; - pub const _SC_SAVED_IDS: c_int = 24; - pub const _SC_VERSION: c_int = 25; - pub const _SC_RE_DUP_MAX: c_int = 26; - pub const _SC_STREAM_MAX: c_int = 27; - pub const _SC_TZNAME_MAX: c_int = 28; - pub const _SC_PAGESIZE: c_int = 39; - - pub const _PC_NAME_MAX: c_int = 4; - pub const _PC_PATH_MAX: c_int = 5; - } - } - - #[cfg(any(target_os = "freebsd", - target_os = "dragonfly"))] - pub mod os { - pub mod c95 { - use types::os::arch::c95::{c_int, c_uint}; - - pub const EXIT_FAILURE: c_int = 1; - pub const EXIT_SUCCESS: c_int = 0; - pub const RAND_MAX: c_int = 2147483647; - pub const EOF: c_int = -1; - pub const SEEK_SET: c_int = 0; - pub const SEEK_CUR: c_int = 1; - pub const SEEK_END: c_int = 2; - pub const _IOFBF: c_int = 0; - pub const _IONBF: c_int = 2; - pub const _IOLBF: c_int = 1; - pub const BUFSIZ: c_uint = 1024; - pub const FOPEN_MAX: c_uint = 20; - pub const FILENAME_MAX: c_uint = 1024; - pub const L_tmpnam: c_uint = 1024; - pub const TMP_MAX: c_uint = 308915776; - } - pub mod c99 { - } - pub mod posix88 { - use types::common::c95::c_void; - use types::os::arch::c95::c_int; - use types::os::arch::posix88::mode_t; - - pub const O_RDONLY: c_int = 0; - pub const O_WRONLY: c_int = 1; - pub const O_RDWR: c_int = 2; - pub const O_APPEND: c_int = 8; - pub const O_CREAT: c_int = 512; - pub const O_EXCL: c_int = 2048; - pub const O_NOCTTY: c_int = 32768; - pub const O_TRUNC: c_int = 1024; - pub const S_IFIFO: mode_t = 4096; - pub const S_IFCHR: mode_t = 8192; - pub const S_IFBLK: mode_t = 24576; - pub const S_IFDIR: mode_t = 16384; - pub const S_IFREG: mode_t = 32768; - pub const S_IFLNK: mode_t = 40960; - pub const S_IFSOCK: mode_t = 49152; - pub const S_IFMT: mode_t = 61440; - pub const S_IEXEC: mode_t = 64; - pub const S_IWRITE: mode_t = 128; - pub const S_IREAD: mode_t = 256; - pub const S_IRWXU: mode_t = 448; - pub const S_IXUSR: mode_t = 64; - pub const S_IWUSR: mode_t = 128; - pub const S_IRUSR: mode_t = 256; - pub const S_IRWXG: mode_t = 56; - pub const S_IXGRP: mode_t = 8; - pub const S_IWGRP: mode_t = 16; - pub const S_IRGRP: mode_t = 32; - pub const S_IRWXO: mode_t = 7; - pub const S_IXOTH: mode_t = 1; - pub const S_IWOTH: mode_t = 2; - pub const S_IROTH: mode_t = 4; - pub const F_OK: c_int = 0; - pub const R_OK: c_int = 4; - pub const W_OK: c_int = 2; - pub const X_OK: c_int = 1; - pub const STDIN_FILENO: c_int = 0; - pub const STDOUT_FILENO: c_int = 1; - pub const STDERR_FILENO: c_int = 2; - pub const F_LOCK: c_int = 1; - pub const F_TEST: c_int = 3; - pub const F_TLOCK: c_int = 2; - pub const F_ULOCK: c_int = 0; - pub const SIGHUP: c_int = 1; - pub const SIGINT: c_int = 2; - pub const SIGQUIT: c_int = 3; - pub const SIGILL: c_int = 4; - pub const SIGABRT: c_int = 6; - pub const SIGFPE: c_int = 8; - pub const SIGKILL: c_int = 9; - pub const SIGSEGV: c_int = 11; - pub const SIGPIPE: c_int = 13; - pub const SIGALRM: c_int = 14; - pub const SIGTERM: c_int = 15; - - pub const PROT_NONE: c_int = 0; - pub const PROT_READ: c_int = 1; - pub const PROT_WRITE: c_int = 2; - pub const PROT_EXEC: c_int = 4; - - pub const MAP_FILE: c_int = 0x0000; - pub const MAP_SHARED: c_int = 0x0001; - pub const MAP_PRIVATE: c_int = 0x0002; - pub const MAP_FIXED: c_int = 0x0010; - pub const MAP_ANON: c_int = 0x1000; - - pub const MAP_FAILED: *mut c_void = !0 as *mut c_void; - - pub const MCL_CURRENT: c_int = 0x0001; - pub const MCL_FUTURE: c_int = 0x0002; - - pub const MS_SYNC: c_int = 0x0000; - pub const MS_ASYNC: c_int = 0x0001; - pub const MS_INVALIDATE: c_int = 0x0002; - - pub const EPERM: c_int = 1; - pub const ENOENT: c_int = 2; - pub const ESRCH: c_int = 3; - pub const EINTR: c_int = 4; - pub const EIO: c_int = 5; - pub const ENXIO: c_int = 6; - pub const E2BIG: c_int = 7; - pub const ENOEXEC: c_int = 8; - pub const EBADF: c_int = 9; - pub const ECHILD: c_int = 10; - pub const EDEADLK: c_int = 11; - pub const ENOMEM: c_int = 12; - pub const EACCES: c_int = 13; - pub const EFAULT: c_int = 14; - pub const ENOTBLK: c_int = 15; - pub const EBUSY: c_int = 16; - pub const EEXIST: c_int = 17; - pub const EXDEV: c_int = 18; - pub const ENODEV: c_int = 19; - pub const ENOTDIR: c_int = 20; - pub const EISDIR: c_int = 21; - pub const EINVAL: c_int = 22; - pub const ENFILE: c_int = 23; - pub const EMFILE: c_int = 24; - pub const ENOTTY: c_int = 25; - pub const ETXTBSY: c_int = 26; - pub const EFBIG: c_int = 27; - pub const ENOSPC: c_int = 28; - pub const ESPIPE: c_int = 29; - pub const EROFS: c_int = 30; - pub const EMLINK: c_int = 31; - pub const EPIPE: c_int = 32; - pub const EDOM: c_int = 33; - pub const ERANGE: c_int = 34; - pub const EAGAIN: c_int = 35; - pub const EWOULDBLOCK: c_int = 35; - pub const EINPROGRESS: c_int = 36; - pub const EALREADY: c_int = 37; - pub const ENOTSOCK: c_int = 38; - pub const EDESTADDRREQ: c_int = 39; - pub const EMSGSIZE: c_int = 40; - pub const EPROTOTYPE: c_int = 41; - pub const ENOPROTOOPT: c_int = 42; - pub const EPROTONOSUPPORT: c_int = 43; - pub const ESOCKTNOSUPPORT: c_int = 44; - pub const EOPNOTSUPP: c_int = 45; - pub const EPFNOSUPPORT: c_int = 46; - pub const EAFNOSUPPORT: c_int = 47; - pub const EADDRINUSE: c_int = 48; - pub const EADDRNOTAVAIL: c_int = 49; - pub const ENETDOWN: c_int = 50; - pub const ENETUNREACH: c_int = 51; - pub const ENETRESET: c_int = 52; - pub const ECONNABORTED: c_int = 53; - pub const ECONNRESET: c_int = 54; - pub const ENOBUFS: c_int = 55; - pub const EISCONN: c_int = 56; - pub const ENOTCONN: c_int = 57; - pub const ESHUTDOWN: c_int = 58; - pub const ETOOMANYREFS: c_int = 59; - pub const ETIMEDOUT: c_int = 60; - pub const ECONNREFUSED: c_int = 61; - pub const ELOOP: c_int = 62; - pub const ENAMETOOLONG: c_int = 63; - pub const EHOSTDOWN: c_int = 64; - pub const EHOSTUNREACH: c_int = 65; - pub const ENOTEMPTY: c_int = 66; - pub const EPROCLIM: c_int = 67; - pub const EUSERS: c_int = 68; - pub const EDQUOT: c_int = 69; - pub const ESTALE: c_int = 70; - pub const EREMOTE: c_int = 71; - pub const EBADRPC: c_int = 72; - pub const ERPCMISMATCH: c_int = 73; - pub const EPROGUNAVAIL: c_int = 74; - pub const EPROGMISMATCH: c_int = 75; - pub const EPROCUNAVAIL: c_int = 76; - pub const ENOLCK: c_int = 77; - pub const ENOSYS: c_int = 78; - pub const EFTYPE: c_int = 79; - pub const EAUTH: c_int = 80; - pub const ENEEDAUTH: c_int = 81; - pub const EIDRM: c_int = 82; - pub const ENOMSG: c_int = 83; - pub const EOVERFLOW: c_int = 84; - pub const ECANCELED: c_int = 85; - pub const EILSEQ: c_int = 86; - pub const ENOATTR: c_int = 87; - pub const EDOOFUS: c_int = 88; - pub const EBADMSG: c_int = 89; - pub const EMULTIHOP: c_int = 90; - pub const ENOLINK: c_int = 91; - pub const EPROTO: c_int = 92; - pub const ENOMEDIUM: c_int = 93; - pub const EUNUSED94: c_int = 94; - pub const EUNUSED95: c_int = 95; - pub const EUNUSED96: c_int = 96; - pub const EUNUSED97: c_int = 97; - pub const EUNUSED98: c_int = 98; - pub const EASYNC: c_int = 99; - pub const ELAST: c_int = 99; - } - pub mod posix01 { - use types::os::arch::c95::{c_int, size_t}; - use types::os::common::posix01::rlim_t; - - pub const F_DUPFD: c_int = 0; - pub const F_GETFD: c_int = 1; - pub const F_SETFD: c_int = 2; - pub const F_GETFL: c_int = 3; - pub const F_SETFL: c_int = 4; - - pub const SIGTRAP: c_int = 5; - pub const SIG_IGN: size_t = 1; - - pub const GLOB_APPEND: c_int = 0x0001; - pub const GLOB_DOOFFS: c_int = 0x0002; - pub const GLOB_ERR: c_int = 0x0004; - pub const GLOB_MARK: c_int = 0x0008; - pub const GLOB_NOCHECK: c_int = 0x0010; - pub const GLOB_NOSORT: c_int = 0x0020; - pub const GLOB_NOESCAPE: c_int = 0x2000; - - pub const GLOB_NOSPACE: c_int = -1; - pub const GLOB_ABORTED: c_int = -2; - pub const GLOB_NOMATCH: c_int = -3; - - pub const POSIX_MADV_NORMAL: c_int = 0; - pub const POSIX_MADV_RANDOM: c_int = 1; - pub const POSIX_MADV_SEQUENTIAL: c_int = 2; - pub const POSIX_MADV_WILLNEED: c_int = 3; - pub const POSIX_MADV_DONTNEED: c_int = 4; - - pub const _SC_IOV_MAX: c_int = 56; - pub const _SC_GETGR_R_SIZE_MAX: c_int = 70; - pub const _SC_GETPW_R_SIZE_MAX: c_int = 71; - pub const _SC_LOGIN_NAME_MAX: c_int = 73; - pub const _SC_MQ_PRIO_MAX: c_int = 75; - pub const _SC_THREAD_ATTR_STACKADDR: c_int = 82; - pub const _SC_THREAD_ATTR_STACKSIZE: c_int = 83; - pub const _SC_THREAD_DESTRUCTOR_ITERATIONS: c_int = 85; - pub const _SC_THREAD_KEYS_MAX: c_int = 86; - pub const _SC_THREAD_PRIO_INHERIT: c_int = 87; - pub const _SC_THREAD_PRIO_PROTECT: c_int = 88; - pub const _SC_THREAD_PRIORITY_SCHEDULING: c_int = 89; - pub const _SC_THREAD_PROCESS_SHARED: c_int = 90; - pub const _SC_THREAD_SAFE_FUNCTIONS: c_int = 91; - pub const _SC_THREAD_STACK_MIN: c_int = 93; - pub const _SC_THREAD_THREADS_MAX: c_int = 94; - pub const _SC_THREADS: c_int = 96; - pub const _SC_TTY_NAME_MAX: c_int = 101; - pub const _SC_ATEXIT_MAX: c_int = 107; - pub const _SC_XOPEN_CRYPT: c_int = 108; - pub const _SC_XOPEN_ENH_I18N: c_int = 109; - pub const _SC_XOPEN_LEGACY: c_int = 110; - pub const _SC_XOPEN_REALTIME: c_int = 111; - pub const _SC_XOPEN_REALTIME_THREADS: c_int = 112; - pub const _SC_XOPEN_SHM: c_int = 113; - pub const _SC_XOPEN_UNIX: c_int = 115; - pub const _SC_XOPEN_VERSION: c_int = 116; - pub const _SC_XOPEN_XCU_VERSION: c_int = 117; - - pub const PTHREAD_CREATE_JOINABLE: c_int = 0; - pub const PTHREAD_CREATE_DETACHED: c_int = 1; - - #[cfg(target_arch = "arm")] - pub const PTHREAD_STACK_MIN: size_t = 4096; - - #[cfg(all(target_os = "freebsd", - any(target_arch = "mips", - target_arch = "mipsel", - target_arch = "x86", - target_arch = "x86_64")))] - pub const PTHREAD_STACK_MIN: size_t = 2048; - - #[cfg(target_os = "dragonfly")] - pub const PTHREAD_STACK_MIN: size_t = 1024; - - pub const CLOCK_REALTIME: c_int = 0; - pub const CLOCK_MONOTONIC: c_int = 4; - - pub const RLIMIT_CPU: c_int = 0; - pub const RLIMIT_FSIZE: c_int = 1; - pub const RLIMIT_DATA: c_int = 2; - pub const RLIMIT_STACK: c_int = 3; - pub const RLIMIT_CORE: c_int = 4; - pub const RLIMIT_RSS: c_int = 5; - pub const RLIMIT_MEMLOCK: c_int = 6; - pub const RLIMIT_NPROC: c_int = 7; - pub const RLIMIT_NOFILE: c_int = 8; - pub const RLIMIT_SBSIZE: c_int = 9; - pub const RLIMIT_VMEM: c_int = 10; - pub const RLIMIT_AS: c_int = RLIMIT_VMEM; - pub const RLIMIT_NPTS: c_int = 11; - pub const RLIMIT_SWAP: c_int = 12; - pub const RLIMIT_KQUEUES: c_int = 13; - - pub const RLIM_NLIMITS: rlim_t = 14; - pub const RLIM_INFINITY: rlim_t = 0x7fff_ffff_ffff_ffff; - - pub const RUSAGE_SELF: c_int = 0; - pub const RUSAGE_CHILDREN: c_int = -1; - pub const RUSAGE_THREAD: c_int = 1; - } - #[cfg(target_os = "freebsd")] - pub mod posix08 { - use types::os::arch::c95::c_int; - pub const O_CLOEXEC: c_int = 0x100000; - pub const F_DUPFD_CLOEXEC: c_int = 17; - } - #[cfg(target_os = "dragonfly")] - pub mod posix08 { - use types::os::arch::c95::c_int; - pub const O_CLOEXEC: c_int = 0x20000; - pub const F_DUPFD_CLOEXEC: c_int = 17; - } - pub mod bsd44 { - use types::os::arch::c95::c_int; - - pub const MADV_NORMAL: c_int = 0; - pub const MADV_RANDOM: c_int = 1; - pub const MADV_SEQUENTIAL: c_int = 2; - pub const MADV_WILLNEED: c_int = 3; - pub const MADV_DONTNEED: c_int = 4; - pub const MADV_FREE: c_int = 5; - pub const MADV_NOSYNC: c_int = 6; - pub const MADV_AUTOSYNC: c_int = 7; - pub const MADV_NOCORE: c_int = 8; - pub const MADV_CORE: c_int = 9; - pub const MADV_PROTECT: c_int = 10; - - pub const MINCORE_INCORE: c_int = 0x1; - pub const MINCORE_REFERENCED: c_int = 0x2; - pub const MINCORE_MODIFIED: c_int = 0x4; - pub const MINCORE_REFERENCED_OTHER: c_int = 0x8; - pub const MINCORE_MODIFIED_OTHER: c_int = 0x10; - pub const MINCORE_SUPER: c_int = 0x20; - - pub const AF_INET: c_int = 2; - pub const AF_INET6: c_int = 28; - pub const AF_UNIX: c_int = 1; - pub const SOCK_STREAM: c_int = 1; - pub const SOCK_DGRAM: c_int = 2; - pub const SOCK_RAW: c_int = 3; - pub const IPPROTO_TCP: c_int = 6; - pub const IPPROTO_IP: c_int = 0; - pub const IPPROTO_IPV6: c_int = 41; - pub const IP_MULTICAST_TTL: c_int = 10; - pub const IP_MULTICAST_LOOP: c_int = 11; - pub const IP_TTL: c_int = 4; - pub const IP_HDRINCL: c_int = 2; - pub const IP_ADD_MEMBERSHIP: c_int = 12; - pub const IP_DROP_MEMBERSHIP: c_int = 13; - pub const IPV6_ADD_MEMBERSHIP: c_int = 12; - pub const IPV6_DROP_MEMBERSHIP: c_int = 13; - - pub const TCP_NODELAY: c_int = 1; - pub const TCP_KEEPIDLE: c_int = 256; - pub const SOL_SOCKET: c_int = 0xffff; - pub const SO_DEBUG: c_int = 0x01; - pub const SO_ACCEPTCONN: c_int = 0x0002; - pub const SO_REUSEADDR: c_int = 0x0004; - pub const SO_KEEPALIVE: c_int = 0x0008; - pub const SO_DONTROUTE: c_int = 0x0010; - pub const SO_BROADCAST: c_int = 0x0020; - pub const SO_USELOOPBACK: c_int = 0x0040; - pub const SO_LINGER: c_int = 0x0080; - pub const SO_OOBINLINE: c_int = 0x0100; - pub const SO_REUSEPORT: c_int = 0x0200; - pub const SO_SNDBUF: c_int = 0x1001; - pub const SO_RCVBUF: c_int = 0x1002; - pub const SO_SNDLOWAT: c_int = 0x1003; - pub const SO_RCVLOWAT: c_int = 0x1004; - pub const SO_SNDTIMEO: c_int = 0x1005; - pub const SO_RCVTIMEO: c_int = 0x1006; - pub const SO_ERROR: c_int = 0x1007; - pub const SO_TYPE: c_int = 0x1008; - - pub const IFF_LOOPBACK: c_int = 0x8; - - pub const SHUT_RD: c_int = 0; - pub const SHUT_WR: c_int = 1; - pub const SHUT_RDWR: c_int = 2; - - pub const LOCK_SH: c_int = 1; - pub const LOCK_EX: c_int = 2; - pub const LOCK_NB: c_int = 4; - pub const LOCK_UN: c_int = 8; - } - pub mod extra { - use types::os::arch::c95::c_int; - - pub const O_SYNC: c_int = 128; - pub const O_NONBLOCK: c_int = 4; - pub const CTL_KERN: c_int = 1; - pub const KERN_PROC: c_int = 14; - #[cfg(target_os = "freebsd")] - pub const KERN_PROC_PATHNAME: c_int = 12; - #[cfg(target_os = "dragonfly")] - pub const KERN_PROC_PATHNAME: c_int = 9; - - pub const MAP_COPY: c_int = 0x0002; - pub const MAP_RENAME: c_int = 0x0020; - pub const MAP_NORESERVE: c_int = 0x0040; - pub const MAP_HASSEMAPHORE: c_int = 0x0200; - pub const MAP_STACK: c_int = 0x0400; - pub const MAP_NOSYNC: c_int = 0x0800; - pub const MAP_NOCORE: c_int = 0x020000; - - pub const IPPROTO_RAW: c_int = 255; - } - pub mod sysconf { - use types::os::arch::c95::c_int; - - pub const _SC_ARG_MAX: c_int = 1; - pub const _SC_CHILD_MAX: c_int = 2; - pub const _SC_CLK_TCK: c_int = 3; - pub const _SC_NGROUPS_MAX: c_int = 4; - pub const _SC_OPEN_MAX: c_int = 5; - pub const _SC_JOB_CONTROL: c_int = 6; - pub const _SC_SAVED_IDS: c_int = 7; - pub const _SC_VERSION: c_int = 8; - pub const _SC_BC_BASE_MAX: c_int = 9; - pub const _SC_BC_DIM_MAX: c_int = 10; - pub const _SC_BC_SCALE_MAX: c_int = 11; - pub const _SC_BC_STRING_MAX: c_int = 12; - pub const _SC_COLL_WEIGHTS_MAX: c_int = 13; - pub const _SC_EXPR_NEST_MAX: c_int = 14; - pub const _SC_LINE_MAX: c_int = 15; - pub const _SC_RE_DUP_MAX: c_int = 16; - pub const _SC_2_VERSION: c_int = 17; - pub const _SC_2_C_BIND: c_int = 18; - pub const _SC_2_C_DEV: c_int = 19; - pub const _SC_2_CHAR_TERM: c_int = 20; - pub const _SC_2_FORT_DEV: c_int = 21; - pub const _SC_2_FORT_RUN: c_int = 22; - pub const _SC_2_LOCALEDEF: c_int = 23; - pub const _SC_2_SW_DEV: c_int = 24; - pub const _SC_2_UPE: c_int = 25; - pub const _SC_STREAM_MAX: c_int = 26; - pub const _SC_TZNAME_MAX: c_int = 27; - pub const _SC_ASYNCHRONOUS_IO: c_int = 28; - pub const _SC_MAPPED_FILES: c_int = 29; - pub const _SC_MEMLOCK: c_int = 30; - pub const _SC_MEMLOCK_RANGE: c_int = 31; - pub const _SC_MEMORY_PROTECTION: c_int = 32; - pub const _SC_MESSAGE_PASSING: c_int = 33; - pub const _SC_PRIORITIZED_IO: c_int = 34; - pub const _SC_PRIORITY_SCHEDULING: c_int = 35; - pub const _SC_REALTIME_SIGNALS: c_int = 36; - pub const _SC_SEMAPHORES: c_int = 37; - pub const _SC_FSYNC: c_int = 38; - pub const _SC_SHARED_MEMORY_OBJECTS: c_int = 39; - pub const _SC_SYNCHRONIZED_IO: c_int = 40; - pub const _SC_TIMERS: c_int = 41; - pub const _SC_AIO_LISTIO_MAX: c_int = 42; - pub const _SC_AIO_MAX: c_int = 43; - pub const _SC_AIO_PRIO_DELTA_MAX: c_int = 44; - pub const _SC_DELAYTIMER_MAX: c_int = 45; - pub const _SC_MQ_OPEN_MAX: c_int = 46; - pub const _SC_PAGESIZE: c_int = 47; - pub const _SC_RTSIG_MAX: c_int = 48; - pub const _SC_SEM_NSEMS_MAX: c_int = 49; - pub const _SC_SEM_VALUE_MAX: c_int = 50; - pub const _SC_SIGQUEUE_MAX: c_int = 51; - pub const _SC_TIMER_MAX: c_int = 52; - - pub const _PC_NAME_MAX: c_int = 4; - pub const _PC_PATH_MAX: c_int = 5; - } - } - - #[cfg(any(target_os = "bitrig", target_os = "openbsd"))] - pub mod os { - pub mod c95 { - use types::os::arch::c95::{c_int, c_uint}; - - pub const EXIT_FAILURE: c_int = 1; - pub const EXIT_SUCCESS: c_int = 0; - pub const RAND_MAX: c_int = 2147483647; - pub const EOF: c_int = -1; - pub const SEEK_SET: c_int = 0; - pub const SEEK_CUR: c_int = 1; - pub const SEEK_END: c_int = 2; - pub const _IOFBF: c_int = 0; - pub const _IONBF: c_int = 2; - pub const _IOLBF: c_int = 1; - pub const BUFSIZ: c_uint = 1024; - pub const FOPEN_MAX: c_uint = 20; - pub const FILENAME_MAX: c_uint = 1024; - pub const L_tmpnam: c_uint = 1024; - pub const TMP_MAX: c_uint = 308915776; - } - pub mod c99 { - } - pub mod posix88 { - use types::common::c95::c_void; - use types::os::arch::c95::c_int; - use types::os::arch::posix88::mode_t; - - pub const O_RDONLY: c_int = 0; - pub const O_WRONLY: c_int = 1; - pub const O_RDWR: c_int = 2; - pub const O_APPEND: c_int = 8; - pub const O_CREAT: c_int = 512; - pub const O_EXCL: c_int = 2048; - pub const O_NOCTTY: c_int = 32768; - pub const O_TRUNC: c_int = 1024; - pub const S_IFIFO: mode_t = 4096; - pub const S_IFCHR: mode_t = 8192; - pub const S_IFBLK: mode_t = 24576; - pub const S_IFDIR: mode_t = 16384; - pub const S_IFREG: mode_t = 32768; - pub const S_IFLNK: mode_t = 40960; - pub const S_IFSOCK: mode_t = 49152; - pub const S_IFMT: mode_t = 61440; - pub const S_IEXEC: mode_t = 64; - pub const S_IWRITE: mode_t = 128; - pub const S_IREAD: mode_t = 256; - pub const S_IRWXU: mode_t = 448; - pub const S_IXUSR: mode_t = 64; - pub const S_IWUSR: mode_t = 128; - pub const S_IRUSR: mode_t = 256; - pub const S_IRWXG: mode_t = 56; - pub const S_IXGRP: mode_t = 8; - pub const S_IWGRP: mode_t = 16; - pub const S_IRGRP: mode_t = 32; - pub const S_IRWXO: mode_t = 7; - pub const S_IXOTH: mode_t = 1; - pub const S_IWOTH: mode_t = 2; - pub const S_IROTH: mode_t = 4; - pub const F_OK: c_int = 0; - pub const R_OK: c_int = 4; - pub const W_OK: c_int = 2; - pub const X_OK: c_int = 1; - pub const STDIN_FILENO: c_int = 0; - pub const STDOUT_FILENO: c_int = 1; - pub const STDERR_FILENO: c_int = 2; - pub const F_LOCK: c_int = 1; - pub const F_TEST: c_int = 3; - pub const F_TLOCK: c_int = 2; - pub const F_ULOCK: c_int = 0; - pub const SIGHUP: c_int = 1; - pub const SIGINT: c_int = 2; - pub const SIGQUIT: c_int = 3; - pub const SIGILL: c_int = 4; - pub const SIGABRT: c_int = 6; - pub const SIGFPE: c_int = 8; - pub const SIGKILL: c_int = 9; - pub const SIGSEGV: c_int = 11; - pub const SIGPIPE: c_int = 13; - pub const SIGALRM: c_int = 14; - pub const SIGTERM: c_int = 15; - - pub const PROT_NONE: c_int = 0; - pub const PROT_READ: c_int = 1; - pub const PROT_WRITE: c_int = 2; - pub const PROT_EXEC: c_int = 4; - - pub const MAP_FILE: c_int = 0x0000; - pub const MAP_SHARED: c_int = 0x0001; - pub const MAP_PRIVATE: c_int = 0x0002; - pub const MAP_FIXED: c_int = 0x0010; - pub const MAP_ANON: c_int = 0x1000; - - pub const MAP_FAILED: *mut c_void = !0 as *mut c_void; - - pub const MCL_CURRENT: c_int = 0x0001; - pub const MCL_FUTURE: c_int = 0x0002; - - pub const MS_ASYNC: c_int = 0x0001; - pub const MS_SYNC: c_int = 0x0002; - pub const MS_INVALIDATE: c_int = 0x0004; - - pub const EPERM: c_int = 1; - pub const ENOENT: c_int = 2; - pub const ESRCH: c_int = 3; - pub const EINTR: c_int = 4; - pub const EIO: c_int = 5; - pub const ENXIO: c_int = 6; - pub const E2BIG: c_int = 7; - pub const ENOEXEC: c_int = 8; - pub const EBADF: c_int = 9; - pub const ECHILD: c_int = 10; - pub const EDEADLK: c_int = 11; - pub const ENOMEM: c_int = 12; - pub const EACCES: c_int = 13; - pub const EFAULT: c_int = 14; - pub const ENOTBLK: c_int = 15; - pub const EBUSY: c_int = 16; - pub const EEXIST: c_int = 17; - pub const EXDEV: c_int = 18; - pub const ENODEV: c_int = 19; - pub const ENOTDIR: c_int = 20; - pub const EISDIR: c_int = 21; - pub const EINVAL: c_int = 22; - pub const ENFILE: c_int = 23; - pub const EMFILE: c_int = 24; - pub const ENOTTY: c_int = 25; - pub const ETXTBSY: c_int = 26; - pub const EFBIG: c_int = 27; - pub const ENOSPC: c_int = 28; - pub const ESPIPE: c_int = 29; - pub const EROFS: c_int = 30; - pub const EMLINK: c_int = 31; - pub const EPIPE: c_int = 32; - pub const EDOM: c_int = 33; - pub const ERANGE: c_int = 34; - pub const EAGAIN: c_int = 35; - pub const EWOULDBLOCK: c_int = 35; - pub const EINPROGRESS: c_int = 36; - pub const EALREADY: c_int = 37; - pub const ENOTSOCK: c_int = 38; - pub const EDESTADDRREQ: c_int = 39; - pub const EMSGSIZE: c_int = 40; - pub const EPROTOTYPE: c_int = 41; - pub const ENOPROTOOPT: c_int = 42; - pub const EPROTONOSUPPORT: c_int = 43; - pub const ESOCKTNOSUPPORT: c_int = 44; - pub const EOPNOTSUPP: c_int = 45; - pub const EPFNOSUPPORT: c_int = 46; - pub const EAFNOSUPPORT: c_int = 47; - pub const EADDRINUSE: c_int = 48; - pub const EADDRNOTAVAIL: c_int = 49; - pub const ENETDOWN: c_int = 50; - pub const ENETUNREACH: c_int = 51; - pub const ENETRESET: c_int = 52; - pub const ECONNABORTED: c_int = 53; - pub const ECONNRESET: c_int = 54; - pub const ENOBUFS: c_int = 55; - pub const EISCONN: c_int = 56; - pub const ENOTCONN: c_int = 57; - pub const ESHUTDOWN: c_int = 58; - pub const ETOOMANYREFS: c_int = 59; - pub const ETIMEDOUT: c_int = 60; - pub const ECONNREFUSED: c_int = 61; - pub const ELOOP: c_int = 62; - pub const ENAMETOOLONG: c_int = 63; - pub const EHOSTDOWN: c_int = 64; - pub const EHOSTUNREACH: c_int = 65; - pub const ENOTEMPTY: c_int = 66; - pub const EPROCLIM: c_int = 67; - pub const EUSERS: c_int = 68; - pub const EDQUOT: c_int = 69; - pub const ESTALE: c_int = 70; - pub const EREMOTE: c_int = 71; - pub const EBADRPC: c_int = 72; - pub const ERPCMISMATCH: c_int = 73; - pub const EPROGUNAVAIL: c_int = 74; - pub const EPROGMISMATCH: c_int = 75; - pub const EPROCUNAVAIL: c_int = 76; - pub const ENOLCK: c_int = 77; - pub const ENOSYS: c_int = 78; - pub const EFTYPE: c_int = 79; - pub const EAUTH: c_int = 80; - pub const ENEEDAUTH: c_int = 81; - pub const EIPSEC: c_int = 82; - pub const ENOATTR: c_int = 83; - pub const EILSEQ: c_int = 84; - pub const ENOMEDIUM: c_int = 85; - pub const EMEDIUMTYPE: c_int = 86; - pub const EOVERFLOW: c_int = 87; - pub const ECANCELED: c_int = 88; - pub const EIDRM: c_int = 89; - pub const ENOMSG: c_int = 90; - pub const ENOTSUP: c_int = 91; - pub const ELAST: c_int = 91; // must be equal to largest errno - } - pub mod posix01 { - use types::os::arch::c95::{c_int, size_t}; - use types::os::common::posix01::rlim_t; - - pub const F_DUPFD: c_int = 0; - pub const F_GETFD: c_int = 1; - pub const F_SETFD: c_int = 2; - pub const F_GETFL: c_int = 3; - pub const F_SETFL: c_int = 4; - pub const F_GETOWN: c_int = 5; - pub const F_SETOWN: c_int = 6; - pub const F_GETLK: c_int = 7; - pub const F_SETLK: c_int = 8; - pub const F_SETLKW: c_int = 9; - - pub const SIGTRAP: c_int = 5; - pub const SIG_IGN: size_t = 1; - - pub const GLOB_APPEND: c_int = 0x0001; - pub const GLOB_DOOFFS: c_int = 0x0002; - pub const GLOB_ERR: c_int = 0x0004; - pub const GLOB_MARK: c_int = 0x0008; - pub const GLOB_NOCHECK: c_int = 0x0010; - pub const GLOB_NOSORT: c_int = 0x0020; - pub const GLOB_NOESCAPE: c_int = 0x1000; - - pub const GLOB_NOSPACE: c_int = -1; - pub const GLOB_ABORTED: c_int = -2; - pub const GLOB_NOMATCH: c_int = -3; - pub const GLOB_NOSYS: c_int = -4; - - pub const POSIX_MADV_NORMAL: c_int = 0; - pub const POSIX_MADV_RANDOM: c_int = 1; - pub const POSIX_MADV_SEQUENTIAL: c_int = 2; - pub const POSIX_MADV_WILLNEED: c_int = 3; - pub const POSIX_MADV_DONTNEED: c_int = 4; - - pub const _SC_IOV_MAX: c_int = 51; - pub const _SC_GETGR_R_SIZE_MAX: c_int = 100; - pub const _SC_GETPW_R_SIZE_MAX: c_int = 101; - pub const _SC_LOGIN_NAME_MAX: c_int = 102; - pub const _SC_MQ_PRIO_MAX: c_int = 59; - pub const _SC_THREAD_ATTR_STACKADDR: c_int = 77; - pub const _SC_THREAD_ATTR_STACKSIZE: c_int = 78; - pub const _SC_THREAD_DESTRUCTOR_ITERATIONS: c_int = 80; - pub const _SC_THREAD_KEYS_MAX: c_int = 81; - pub const _SC_THREAD_PRIO_INHERIT: c_int = 82; - pub const _SC_THREAD_PRIO_PROTECT: c_int = 83; - pub const _SC_THREAD_PRIORITY_SCHEDULING: c_int = 84; - pub const _SC_THREAD_PROCESS_SHARED: c_int = 85; - pub const _SC_THREAD_SAFE_FUNCTIONS: c_int = 103; - pub const _SC_THREAD_STACK_MIN: c_int = 89; - pub const _SC_THREAD_THREADS_MAX: c_int = 90; - pub const _SC_THREADS: c_int = 91; - pub const _SC_TTY_NAME_MAX: c_int = 107; - pub const _SC_ATEXIT_MAX: c_int = 46; - pub const _SC_XOPEN_CRYPT: c_int = 117; - pub const _SC_XOPEN_ENH_I18N: c_int = 118; - pub const _SC_XOPEN_LEGACY: c_int = 119; - pub const _SC_XOPEN_REALTIME: c_int = 120; - pub const _SC_XOPEN_REALTIME_THREADS: c_int = 121; - pub const _SC_XOPEN_SHM: c_int = 30; - pub const _SC_XOPEN_UNIX: c_int = 123; - pub const _SC_XOPEN_VERSION: c_int = 125; - - pub const PTHREAD_CREATE_JOINABLE: c_int = 0; - pub const PTHREAD_CREATE_DETACHED: c_int = 1; - pub const PTHREAD_STACK_MIN: size_t = 2048; - - pub const CLOCK_REALTIME: c_int = 0; - pub const CLOCK_MONOTONIC: c_int = 3; - - pub const RLIMIT_CPU: c_int = 0; - pub const RLIMIT_FSIZE: c_int = 1; - pub const RLIMIT_DATA: c_int = 2; - pub const RLIMIT_STACK: c_int = 3; - pub const RLIMIT_CORE: c_int = 4; - pub const RLIMIT_RSS: c_int = 5; - pub const RLIMIT_MEMLOCK: c_int = 6; - pub const RLIMIT_NPROC: c_int = 7; - pub const RLIMIT_NOFILE: c_int = 8; - pub const RLIM_NLIMITS: c_int = 9; - - pub const RLIM_INFINITY: rlim_t = 0x7fff_ffff_ffff_ffff; - pub const RLIM_SAVED_MAX: rlim_t = RLIM_INFINITY; - pub const RLIM_SAVED_CUR: rlim_t = RLIM_INFINITY; - - pub const RUSAGE_SELF: c_int = 0; - pub const RUSAGE_CHILDREN: c_int = -1; - pub const RUSAGE_THREAD: c_int = 1; - } - pub mod posix08 { - use types::os::arch::c95::c_int; - pub const O_CLOEXEC: c_int = 0x10000; - pub const F_DUPFD_CLOEXEC: c_int = 10; - } - pub mod bsd44 { - use types::os::arch::c95::c_int; - - pub const MADV_NORMAL: c_int = 0; - pub const MADV_RANDOM: c_int = 1; - pub const MADV_SEQUENTIAL: c_int = 2; - pub const MADV_WILLNEED: c_int = 3; - pub const MADV_DONTNEED: c_int = 4; - pub const MADV_FREE: c_int = 6; - - pub const AF_UNIX: c_int = 1; - pub const AF_INET: c_int = 2; - pub const AF_INET6: c_int = 24; - pub const SOCK_STREAM: c_int = 1; - pub const SOCK_DGRAM: c_int = 2; - pub const SOCK_RAW: c_int = 3; - pub const IPPROTO_TCP: c_int = 6; - pub const IPPROTO_IP: c_int = 0; - pub const IPPROTO_IPV6: c_int = 41; - pub const IP_MULTICAST_TTL: c_int = 10; - pub const IP_MULTICAST_LOOP: c_int = 11; - pub const IP_TTL: c_int = 4; - pub const IP_HDRINCL: c_int = 2; - pub const IP_ADD_MEMBERSHIP: c_int = 12; - pub const IP_DROP_MEMBERSHIP: c_int = 13; - pub const IPV6_ADD_MEMBERSHIP: c_int = 12; // don't exist - pub const IPV6_DROP_MEMBERSHIP: c_int = 13; // don't exist - - pub const TCP_NODELAY: c_int = 0x01; - pub const SOL_SOCKET: c_int = 0xffff; - pub const SO_DEBUG: c_int = 0x01; - pub const SO_ACCEPTCONN: c_int = 0x0002; - pub const SO_REUSEADDR: c_int = 0x0004; - pub const SO_KEEPALIVE: c_int = 0x0008; - pub const SO_DONTROUTE: c_int = 0x0010; - pub const SO_BROADCAST: c_int = 0x0020; - pub const SO_USELOOPBACK: c_int = 0x0040; - pub const SO_LINGER: c_int = 0x0080; - pub const SO_OOBINLINE: c_int = 0x0100; - pub const SO_REUSEPORT: c_int = 0x0200; - pub const SO_SNDBUF: c_int = 0x1001; - pub const SO_RCVBUF: c_int = 0x1002; - pub const SO_SNDLOWAT: c_int = 0x1003; - pub const SO_RCVLOWAT: c_int = 0x1004; - pub const SO_SNDTIMEO: c_int = 0x1005; - pub const SO_RCVTIMEO: c_int = 0x1006; - pub const SO_ERROR: c_int = 0x1007; - pub const SO_TYPE: c_int = 0x1008; - - pub const IFF_LOOPBACK: c_int = 0x8; - - pub const SHUT_RD: c_int = 0; - pub const SHUT_WR: c_int = 1; - pub const SHUT_RDWR: c_int = 2; - - pub const LOCK_SH: c_int = 1; - pub const LOCK_EX: c_int = 2; - pub const LOCK_NB: c_int = 4; - pub const LOCK_UN: c_int = 8; - } - pub mod extra { - use types::os::arch::c95::c_int; - - pub const O_DSYNC: c_int = 128; // same as SYNC - pub const O_SYNC: c_int = 128; - pub const O_NONBLOCK: c_int = 4; - pub const CTL_KERN: c_int = 1; - pub const KERN_PROC: c_int = 66; - - pub const MAP_COPY: c_int = 0x0002; - pub const MAP_RENAME: c_int = 0x0000; - pub const MAP_NORESERVE: c_int = 0x0000; - pub const MAP_NOEXTEND: c_int = 0x0000; - pub const MAP_HASSEMAPHORE: c_int = 0x0000; - - pub const IPPROTO_RAW: c_int = 255; - - pub const PATH_MAX: c_int = 1024; - } - pub mod sysconf { - use types::os::arch::c95::c_int; - - pub const _SC_ARG_MAX: c_int = 1; - pub const _SC_CHILD_MAX: c_int = 2; - pub const _SC_CLK_TCK: c_int = 3; - pub const _SC_NGROUPS_MAX: c_int = 4; - pub const _SC_OPEN_MAX: c_int = 5; - pub const _SC_JOB_CONTROL: c_int = 6; - pub const _SC_SAVED_IDS: c_int = 7; - pub const _SC_VERSION: c_int = 8; - pub const _SC_BC_BASE_MAX: c_int = 9; - pub const _SC_BC_DIM_MAX: c_int = 10; - pub const _SC_BC_SCALE_MAX: c_int = 11; - pub const _SC_BC_STRING_MAX: c_int = 12; - pub const _SC_COLL_WEIGHTS_MAX: c_int = 13; - pub const _SC_EXPR_NEST_MAX: c_int = 14; - pub const _SC_LINE_MAX: c_int = 15; - pub const _SC_RE_DUP_MAX: c_int = 16; - pub const _SC_2_VERSION: c_int = 17; - pub const _SC_2_C_BIND: c_int = 18; - pub const _SC_2_C_DEV: c_int = 19; - pub const _SC_2_CHAR_TERM: c_int = 20; - pub const _SC_2_FORT_DEV: c_int = 21; - pub const _SC_2_FORT_RUN: c_int = 22; - pub const _SC_2_LOCALEDEF: c_int = 23; - pub const _SC_2_SW_DEV: c_int = 24; - pub const _SC_2_UPE: c_int = 25; - pub const _SC_STREAM_MAX: c_int = 26; - pub const _SC_TZNAME_MAX: c_int = 27; - pub const _SC_PAGESIZE: c_int = 28; - pub const _SC_FSYNC: c_int = 29; - pub const _SC_SEM_NSEMS_MAX: c_int = 31; - pub const _SC_SEM_VALUE_MAX: c_int = 32; - pub const _SC_AIO_LISTIO_MAX: c_int = 42; - pub const _SC_AIO_MAX: c_int = 43; - pub const _SC_AIO_PRIO_DELTA_MAX: c_int = 44; - pub const _SC_ASYNCHRONOUS_IO: c_int = 45; - pub const _SC_DELAYTIMER_MAX: c_int = 50; - pub const _SC_MAPPED_FILES: c_int = 53; - pub const _SC_MEMLOCK: c_int = 54; - pub const _SC_MEMLOCK_RANGE: c_int = 55; - pub const _SC_MEMORY_PROTECTION: c_int = 56; - pub const _SC_MESSAGE_PASSING: c_int = 57; - pub const _SC_MQ_OPEN_MAX: c_int = 58; - pub const _SC_PRIORITIZED_IO: c_int = 60; - pub const _SC_PRIORITY_SCHEDULING: c_int = 61; - pub const _SC_REALTIME_SIGNALS: c_int = 64; - pub const _SC_RTSIG_MAX: c_int = 66; - pub const _SC_SEMAPHORES: c_int = 67; - pub const _SC_SHARED_MEMORY_OBJECTS: c_int = 68; - pub const _SC_SIGQUEUE_MAX: c_int = 70; - pub const _SC_SYNCHRONIZED_IO: c_int = 75; - pub const _SC_TIMER_MAX: c_int = 93; - pub const _SC_TIMERS: c_int = 94; - - pub const _PC_NAME_MAX: c_int = 4; - pub const _PC_PATH_MAX: c_int = 5; - } - } - - #[cfg(target_os = "netbsd")] - pub mod os { - pub mod c95 { - use types::os::arch::c95::{c_int, c_uint}; - - pub const EXIT_FAILURE: c_int = 1; - pub const EXIT_SUCCESS: c_int = 0; - pub const RAND_MAX: c_int = 2147483647; - pub const EOF: c_int = -1; - pub const SEEK_SET: c_int = 0; - pub const SEEK_CUR: c_int = 1; - pub const SEEK_END: c_int = 2; - pub const _IOFBF: c_int = 0; - pub const _IONBF: c_int = 2; - pub const _IOLBF: c_int = 1; - pub const BUFSIZ: c_uint = 1024; - pub const FOPEN_MAX: c_uint = 20; - pub const FILENAME_MAX: c_uint = 1024; - pub const L_tmpnam: c_uint = 1024; - pub const TMP_MAX: c_uint = 308915776; - } - pub mod c99 { - } - pub mod posix88 { - use types::common::c95::c_void; - use types::os::arch::c95::c_int; - use types::os::arch::posix88::mode_t; - - pub const O_RDONLY: c_int = 0; - pub const O_WRONLY: c_int = 1; - pub const O_RDWR: c_int = 2; - pub const O_APPEND: c_int = 8; - pub const O_CREAT: c_int = 512; - pub const O_EXCL: c_int = 2048; - pub const O_NOCTTY: c_int = 32768; - pub const O_TRUNC: c_int = 1024; - pub const S_IFIFO: mode_t = 4096; - pub const S_IFCHR: mode_t = 8192; - pub const S_IFBLK: mode_t = 24576; - pub const S_IFDIR: mode_t = 16384; - pub const S_IFREG: mode_t = 32768; - pub const S_IFLNK: mode_t = 40960; - pub const S_IFSOCK: mode_t = 49152; - pub const S_IFMT: mode_t = 61440; - pub const S_IEXEC: mode_t = 64; - pub const S_IWRITE: mode_t = 128; - pub const S_IREAD: mode_t = 256; - pub const S_IRWXU: mode_t = 448; - pub const S_IXUSR: mode_t = 64; - pub const S_IWUSR: mode_t = 128; - pub const S_IRUSR: mode_t = 256; - pub const S_IRWXG: mode_t = 56; - pub const S_IXGRP: mode_t = 8; - pub const S_IWGRP: mode_t = 16; - pub const S_IRGRP: mode_t = 32; - pub const S_IRWXO: mode_t = 7; - pub const S_IXOTH: mode_t = 1; - pub const S_IWOTH: mode_t = 2; - pub const S_IROTH: mode_t = 4; - pub const F_OK: c_int = 0; - pub const R_OK: c_int = 4; - pub const W_OK: c_int = 2; - pub const X_OK: c_int = 1; - pub const STDIN_FILENO: c_int = 0; - pub const STDOUT_FILENO: c_int = 1; - pub const STDERR_FILENO: c_int = 2; - pub const F_LOCK: c_int = 1; - pub const F_TEST: c_int = 3; - pub const F_TLOCK: c_int = 2; - pub const F_ULOCK: c_int = 0; - pub const SIGHUP: c_int = 1; - pub const SIGINT: c_int = 2; - pub const SIGQUIT: c_int = 3; - pub const SIGILL: c_int = 4; - pub const SIGABRT: c_int = 6; - pub const SIGFPE: c_int = 8; - pub const SIGKILL: c_int = 9; - pub const SIGSEGV: c_int = 11; - pub const SIGPIPE: c_int = 13; - pub const SIGALRM: c_int = 14; - pub const SIGTERM: c_int = 15; - - pub const PROT_NONE: c_int = 0; - pub const PROT_READ: c_int = 1; - pub const PROT_WRITE: c_int = 2; - pub const PROT_EXEC: c_int = 4; - - pub const MAP_FILE: c_int = 0; - pub const MAP_SHARED: c_int = 1; - pub const MAP_PRIVATE: c_int = 2; - pub const MAP_FIXED: c_int = 16; - pub const MAP_ANON: c_int = 4096; - - pub const MAP_FAILED: *mut c_void = !0 as *mut c_void; - - pub const MCL_CURRENT: c_int = 1; - pub const MCL_FUTURE: c_int = 2; - - pub const MS_ASYNC: c_int = 1; - pub const MS_SYNC: c_int = 4; - pub const MS_INVALIDATE: c_int = 2; - - pub const EPERM: c_int = 1; - pub const ENOENT: c_int = 2; - pub const ESRCH: c_int = 3; - pub const EINTR: c_int = 4; - pub const EIO: c_int = 5; - pub const ENXIO: c_int = 6; - pub const E2BIG: c_int = 7; - pub const ENOEXEC: c_int = 8; - pub const EBADF: c_int = 9; - pub const ECHILD: c_int = 10; - pub const EDEADLK: c_int = 11; - pub const ENOMEM: c_int = 12; - pub const EACCES: c_int = 13; - pub const EFAULT: c_int = 14; - pub const ENOTBLK: c_int = 15; - pub const EBUSY: c_int = 16; - pub const EEXIST: c_int = 17; - pub const EXDEV: c_int = 18; - pub const ENODEV: c_int = 19; - pub const ENOTDIR: c_int = 20; - pub const EISDIR: c_int = 21; - pub const EINVAL: c_int = 22; - pub const ENFILE: c_int = 23; - pub const EMFILE: c_int = 24; - pub const ENOTTY: c_int = 25; - pub const ETXTBSY: c_int = 26; - pub const EFBIG: c_int = 27; - pub const ENOSPC: c_int = 28; - pub const ESPIPE: c_int = 29; - pub const EROFS: c_int = 30; - pub const EMLINK: c_int = 31; - pub const EPIPE: c_int = 32; - pub const EDOM: c_int = 33; - pub const ERANGE: c_int = 34; - pub const EAGAIN: c_int = 35; - pub const EWOULDBLOCK: c_int = 35; - pub const EINPROGRESS: c_int = 36; - pub const EALREADY: c_int = 37; - pub const ENOTSOCK: c_int = 38; - pub const EDESTADDRREQ: c_int = 39; - pub const EMSGSIZE: c_int = 40; - pub const EPROTOTYPE: c_int = 41; - pub const ENOPROTOOPT: c_int = 42; - pub const EPROTONOSUPPORT: c_int = 43; - pub const ESOCKTNOSUPPORT: c_int = 44; - pub const EOPNOTSUPP: c_int = 45; - pub const EPFNOSUPPORT: c_int = 46; - pub const EAFNOSUPPORT: c_int = 47; - pub const EADDRINUSE: c_int = 48; - pub const EADDRNOTAVAIL: c_int = 49; - pub const ENETDOWN: c_int = 50; - pub const ENETUNREACH: c_int = 51; - pub const ENETRESET: c_int = 52; - pub const ECONNABORTED: c_int = 53; - pub const ECONNRESET: c_int = 54; - pub const ENOBUFS: c_int = 55; - pub const EISCONN: c_int = 56; - pub const ENOTCONN: c_int = 57; - pub const ESHUTDOWN: c_int = 58; - pub const ETOOMANYREFS: c_int = 59; - pub const ETIMEDOUT: c_int = 60; - pub const ECONNREFUSED: c_int = 61; - pub const ELOOP: c_int = 62; - pub const ENAMETOOLONG: c_int = 63; - pub const EHOSTDOWN: c_int = 64; - pub const EHOSTUNREACH: c_int = 65; - pub const ENOTEMPTY: c_int = 66; - pub const EPROCLIM: c_int = 67; - pub const EUSERS: c_int = 68; - pub const EDQUOT: c_int = 69; - pub const ESTALE: c_int = 70; - pub const EREMOTE: c_int = 71; - pub const EBADRPC: c_int = 72; - pub const ERPCMISMATCH: c_int = 73; - pub const EPROGUNAVAIL: c_int = 74; - pub const EPROGMISMATCH: c_int = 75; - pub const EPROCUNAVAIL: c_int = 76; - pub const ENOLCK: c_int = 77; - pub const ENOSYS: c_int = 78; - pub const EFTYPE: c_int = 79; - pub const EAUTH: c_int = 80; - pub const ENEEDAUTH: c_int = 81; - pub const ENOATTR: c_int = 93; - pub const EILSEQ: c_int = 85; - pub const EOVERFLOW: c_int = 84; - pub const ECANCELED: c_int = 87; - pub const EIDRM: c_int = 82; - pub const ENOMSG: c_int = 83; - pub const ENOTSUP: c_int = 86; - pub const ELAST: c_int = 96; - } - pub mod posix01 { - use types::os::arch::c95::{c_int, size_t}; - use types::os::common::posix01::rlim_t; - - pub const F_DUPFD: c_int = 0; - pub const F_GETFD: c_int = 1; - pub const F_SETFD: c_int = 2; - pub const F_GETFL: c_int = 3; - pub const F_SETFL: c_int = 4; - pub const F_GETOWN: c_int = 5; - pub const F_SETOWN: c_int = 6; - pub const F_GETLK: c_int = 7; - pub const F_SETLK: c_int = 8; - pub const F_SETLKW: c_int = 9; - - pub const SIGTRAP: c_int = 5; - pub const SIG_IGN: size_t = 1; - - pub const GLOB_APPEND: c_int = 1; - pub const GLOB_DOOFFS: c_int = 2; - pub const GLOB_ERR: c_int = 4; - pub const GLOB_MARK: c_int = 8; - pub const GLOB_NOCHECK: c_int = 16; - pub const GLOB_NOSORT: c_int = 32; - pub const GLOB_NOESCAPE: c_int = 4096; - - pub const GLOB_NOSPACE: c_int = -1; - pub const GLOB_ABORTED: c_int = -2; - pub const GLOB_NOMATCH: c_int = -3; - pub const GLOB_NOSYS: c_int = -4; - - pub const POSIX_MADV_NORMAL: c_int = 0; - pub const POSIX_MADV_RANDOM: c_int = 1; - pub const POSIX_MADV_SEQUENTIAL: c_int = 2; - pub const POSIX_MADV_WILLNEED: c_int = 3; - pub const POSIX_MADV_DONTNEED: c_int = 4; - - pub const _SC_IOV_MAX: c_int = 32; - pub const _SC_GETGR_R_SIZE_MAX: c_int = 47; - pub const _SC_GETPW_R_SIZE_MAX: c_int = 48; - pub const _SC_LOGIN_NAME_MAX: c_int = 37; - pub const _SC_MQ_PRIO_MAX: c_int = 55; - pub const _SC_THREAD_ATTR_STACKADDR: c_int = 61; - pub const _SC_THREAD_ATTR_STACKSIZE: c_int = 62; - pub const _SC_THREAD_DESTRUCTOR_ITERATIONS: c_int = 57; - pub const _SC_THREAD_KEYS_MAX: c_int = 58; - pub const _SC_THREAD_PRIO_INHERIT: c_int = 64; - pub const _SC_THREAD_PRIO_PROTECT: c_int = 65; - pub const _SC_THREAD_PRIORITY_SCHEDULING: c_int = 63; - pub const _SC_THREAD_PROCESS_SHARED: c_int = 66; - pub const _SC_THREAD_SAFE_FUNCTIONS: c_int = 67; - pub const _SC_THREAD_STACK_MIN: c_int = 59; - pub const _SC_THREAD_THREADS_MAX: c_int = 60; - pub const _SC_THREADS: c_int = 41; - pub const _SC_TTY_NAME_MAX: c_int = 68; - pub const _SC_ATEXIT_MAX: c_int = 40; - pub const _SC_XOPEN_SHM: c_int = 30; - - pub const PTHREAD_CREATE_JOINABLE: c_int = 0; - pub const PTHREAD_CREATE_DETACHED: c_int = 1; - pub const PTHREAD_STACK_MIN: size_t = 2048; - - pub const CLOCK_REALTIME: c_int = 0; - pub const CLOCK_MONOTONIC: c_int = 3; - - pub const RLIMIT_CPU: c_int = 0; - pub const RLIMIT_FSIZE: c_int = 1; - pub const RLIMIT_DATA: c_int = 2; - pub const RLIMIT_STACK: c_int = 3; - pub const RLIMIT_CORE: c_int = 4; - pub const RLIMIT_RSS: c_int = 5; - pub const RLIMIT_MEMLOCK: c_int = 6; - pub const RLIMIT_NPROC: c_int = 7; - pub const RLIMIT_NOFILE: c_int = 8; - pub const RLIM_NLIMITS: c_int = 9; - - pub const RLIM_INFINITY: rlim_t = 0x7fff_ffff_ffff_ffff; - pub const RLIM_SAVED_MAX: rlim_t = RLIM_INFINITY; - pub const RLIM_SAVED_CUR: rlim_t = RLIM_INFINITY; - - pub const RUSAGE_SELF: c_int = 0; - pub const RUSAGE_CHILDREN: c_int = -1; - pub const RUSAGE_THREAD: c_int = 1; - } - pub mod posix08 { - use types::os::arch::c95::c_int; - pub const O_CLOEXEC: c_int = 0x400000; - pub const F_DUPFD_CLOEXEC: c_int = 12; - } - pub mod bsd44 { - use types::os::arch::c95::c_int; - - pub const MADV_NORMAL: c_int = 0; - pub const MADV_RANDOM: c_int = 1; - pub const MADV_SEQUENTIAL: c_int = 2; - pub const MADV_WILLNEED: c_int = 3; - pub const MADV_DONTNEED: c_int = 4; - pub const MADV_FREE: c_int = 6; - - pub const AF_UNIX: c_int = 1; - pub const AF_INET: c_int = 2; - pub const AF_INET6: c_int = 24; - pub const SOCK_STREAM: c_int = 1; - pub const SOCK_DGRAM: c_int = 2; - pub const SOCK_RAW: c_int = 3; - pub const IPPROTO_TCP: c_int = 6; - pub const IPPROTO_IP: c_int = 0; - pub const IPPROTO_IPV6: c_int = 41; - pub const IP_MULTICAST_TTL: c_int = 10; - pub const IP_MULTICAST_LOOP: c_int = 11; - pub const IP_TTL: c_int = 4; - pub const IP_HDRINCL: c_int = 2; - pub const IP_ADD_MEMBERSHIP: c_int = 12; - pub const IP_DROP_MEMBERSHIP: c_int = 13; - - pub const TCP_NODELAY: c_int = 1; - pub const SOL_SOCKET: c_int = 65535; - pub const SO_DEBUG: c_int = 1; - pub const SO_ACCEPTCONN: c_int = 2; - pub const SO_REUSEADDR: c_int = 4; - pub const SO_KEEPALIVE: c_int = 8; - pub const SO_DONTROUTE: c_int = 16; - pub const SO_BROADCAST: c_int = 32; - pub const SO_USELOOPBACK: c_int = 64; - pub const SO_LINGER: c_int = 128; - pub const SO_OOBINLINE: c_int = 256; - pub const SO_REUSEPORT: c_int = 512; - pub const SO_SNDBUF: c_int = 4097; - pub const SO_RCVBUF: c_int = 4098; - pub const SO_SNDLOWAT: c_int = 4099; - pub const SO_RCVLOWAT: c_int = 4100; - pub const SO_SNDTIMEO: c_int = 4107; - pub const SO_RCVTIMEO: c_int = 4108; - pub const SO_ERROR: c_int = 4103; - pub const SO_TYPE: c_int = 4104; - - pub const IFF_LOOPBACK: c_int = 0x8; - - pub const SHUT_RD: c_int = 0; - pub const SHUT_WR: c_int = 1; - pub const SHUT_RDWR: c_int = 2; - - pub const LOCK_SH: c_int = 1; - pub const LOCK_EX: c_int = 2; - pub const LOCK_NB: c_int = 4; - pub const LOCK_UN: c_int = 8; - } - pub mod extra { - use types::os::arch::c95::c_int; - - - pub const MAP_RENAME: c_int = 32; - pub const MAP_NORESERVE: c_int = 64; - pub const MAP_HASSEMAPHORE: c_int = 512; - - pub const IPPROTO_RAW: c_int = 255; - - pub const PATH_MAX: c_int = 1024; - } - pub mod sysconf { - use types::os::arch::c95::c_int; - - pub const _SC_ARG_MAX: c_int = 1; - pub const _SC_CHILD_MAX: c_int = 2; - pub const _SC_CLK_TCK: c_int = 39; - pub const _SC_NGROUPS_MAX: c_int = 4; - pub const _SC_OPEN_MAX: c_int = 5; - pub const _SC_JOB_CONTROL: c_int = 6; - pub const _SC_SAVED_IDS: c_int = 7; - pub const _SC_VERSION: c_int = 8; - pub const _SC_BC_BASE_MAX: c_int = 9; - pub const _SC_BC_DIM_MAX: c_int = 10; - pub const _SC_BC_SCALE_MAX: c_int = 11; - pub const _SC_BC_STRING_MAX: c_int = 12; - pub const _SC_COLL_WEIGHTS_MAX: c_int = 13; - pub const _SC_EXPR_NEST_MAX: c_int = 14; - pub const _SC_LINE_MAX: c_int = 15; - pub const _SC_RE_DUP_MAX: c_int = 16; - pub const _SC_2_VERSION: c_int = 17; - pub const _SC_2_C_BIND: c_int = 18; - pub const _SC_2_C_DEV: c_int = 19; - pub const _SC_2_CHAR_TERM: c_int = 20; - pub const _SC_2_FORT_DEV: c_int = 21; - pub const _SC_2_FORT_RUN: c_int = 22; - pub const _SC_2_LOCALEDEF: c_int = 23; - pub const _SC_2_SW_DEV: c_int = 24; - pub const _SC_2_UPE: c_int = 25; - pub const _SC_STREAM_MAX: c_int = 26; - pub const _SC_TZNAME_MAX: c_int = 27; - pub const _SC_PAGESIZE: c_int = 28; - pub const _SC_FSYNC: c_int = 29; - pub const _SC_AIO_LISTIO_MAX: c_int = 51; - pub const _SC_AIO_MAX: c_int = 52; - pub const _SC_ASYNCHRONOUS_IO: c_int = 50; - pub const _SC_MAPPED_FILES: c_int = 33; - pub const _SC_MEMLOCK: c_int = 34; - pub const _SC_MEMLOCK_RANGE: c_int = 35; - pub const _SC_MEMORY_PROTECTION: c_int = 36; - pub const _SC_MESSAGE_PASSING: c_int = 53; - pub const _SC_MQ_OPEN_MAX: c_int = 54; - pub const _SC_PRIORITY_SCHEDULING: c_int = 56; - pub const _SC_SEMAPHORES: c_int = 42; - pub const _SC_SHARED_MEMORY_OBJECTS: c_int = 87; - pub const _SC_SYNCHRONIZED_IO: c_int = 31; - pub const _SC_TIMERS: c_int = 44; - - pub const _PC_NAME_MAX: c_int = 4; - pub const _PC_PATH_MAX: c_int = 5; - } - } - - #[cfg(any(target_os = "macos", target_os = "ios"))] - pub mod os { - pub mod c95 { - use types::os::arch::c95::{c_int, c_uint}; - - pub const EXIT_FAILURE: c_int = 1; - pub const EXIT_SUCCESS: c_int = 0; - pub const RAND_MAX: c_int = 2147483647; - pub const EOF: c_int = -1; - pub const SEEK_SET: c_int = 0; - pub const SEEK_CUR: c_int = 1; - pub const SEEK_END: c_int = 2; - pub const _IOFBF: c_int = 0; - pub const _IONBF: c_int = 2; - pub const _IOLBF: c_int = 1; - pub const BUFSIZ: c_uint = 1024; - pub const FOPEN_MAX: c_uint = 20; - pub const FILENAME_MAX: c_uint = 1024; - pub const L_tmpnam: c_uint = 1024; - pub const TMP_MAX: c_uint = 308915776; - } - pub mod c99 { - } - pub mod posix88 { - use types::common::c95::c_void; - use types::os::arch::c95::c_int; - use types::os::arch::posix88::mode_t; - - pub const O_RDONLY: c_int = 0; - pub const O_WRONLY: c_int = 1; - pub const O_RDWR: c_int = 2; - pub const O_APPEND: c_int = 8; - pub const O_CREAT: c_int = 512; - pub const O_EXCL: c_int = 2048; - pub const O_NOCTTY: c_int = 131072; - pub const O_TRUNC: c_int = 1024; - pub const S_IFIFO: mode_t = 4096; - pub const S_IFCHR: mode_t = 8192; - pub const S_IFBLK: mode_t = 24576; - pub const S_IFDIR: mode_t = 16384; - pub const S_IFREG: mode_t = 32768; - pub const S_IFLNK: mode_t = 40960; - pub const S_IFSOCK: mode_t = 49152; - pub const S_IFMT: mode_t = 61440; - pub const S_IEXEC: mode_t = 64; - pub const S_IWRITE: mode_t = 128; - pub const S_IREAD: mode_t = 256; - pub const S_IRWXU: mode_t = 448; - pub const S_IXUSR: mode_t = 64; - pub const S_IWUSR: mode_t = 128; - pub const S_IRUSR: mode_t = 256; - pub const S_IRWXG: mode_t = 56; - pub const S_IXGRP: mode_t = 8; - pub const S_IWGRP: mode_t = 16; - pub const S_IRGRP: mode_t = 32; - pub const S_IRWXO: mode_t = 7; - pub const S_IXOTH: mode_t = 1; - pub const S_IWOTH: mode_t = 2; - pub const S_IROTH: mode_t = 4; - pub const F_OK: c_int = 0; - pub const R_OK: c_int = 4; - pub const W_OK: c_int = 2; - pub const X_OK: c_int = 1; - pub const STDIN_FILENO: c_int = 0; - pub const STDOUT_FILENO: c_int = 1; - pub const STDERR_FILENO: c_int = 2; - pub const F_LOCK: c_int = 1; - pub const F_TEST: c_int = 3; - pub const F_TLOCK: c_int = 2; - pub const F_ULOCK: c_int = 0; - pub const SIGHUP: c_int = 1; - pub const SIGINT: c_int = 2; - pub const SIGQUIT: c_int = 3; - pub const SIGILL: c_int = 4; - pub const SIGABRT: c_int = 6; - pub const SIGFPE: c_int = 8; - pub const SIGKILL: c_int = 9; - pub const SIGSEGV: c_int = 11; - pub const SIGPIPE: c_int = 13; - pub const SIGALRM: c_int = 14; - pub const SIGTERM: c_int = 15; - - pub const PROT_NONE: c_int = 0; - pub const PROT_READ: c_int = 1; - pub const PROT_WRITE: c_int = 2; - pub const PROT_EXEC: c_int = 4; - - pub const MAP_FILE: c_int = 0x0000; - pub const MAP_SHARED: c_int = 0x0001; - pub const MAP_PRIVATE: c_int = 0x0002; - pub const MAP_FIXED: c_int = 0x0010; - pub const MAP_ANON: c_int = 0x1000; - - pub const MAP_FAILED: *mut c_void = !0 as *mut c_void; - - pub const MCL_CURRENT: c_int = 0x0001; - pub const MCL_FUTURE: c_int = 0x0002; - - pub const MS_ASYNC: c_int = 0x0001; - pub const MS_INVALIDATE: c_int = 0x0002; - pub const MS_SYNC: c_int = 0x0010; - - pub const MS_KILLPAGES: c_int = 0x0004; - pub const MS_DEACTIVATE: c_int = 0x0008; - - pub const EPERM: c_int = 1; - pub const ENOENT: c_int = 2; - pub const ESRCH: c_int = 3; - pub const EINTR: c_int = 4; - pub const EIO: c_int = 5; - pub const ENXIO: c_int = 6; - pub const E2BIG: c_int = 7; - pub const ENOEXEC: c_int = 8; - pub const EBADF: c_int = 9; - pub const ECHILD: c_int = 10; - pub const EDEADLK: c_int = 11; - pub const ENOMEM: c_int = 12; - pub const EACCES: c_int = 13; - pub const EFAULT: c_int = 14; - pub const ENOTBLK: c_int = 15; - pub const EBUSY: c_int = 16; - pub const EEXIST: c_int = 17; - pub const EXDEV: c_int = 18; - pub const ENODEV: c_int = 19; - pub const ENOTDIR: c_int = 20; - pub const EISDIR: c_int = 21; - pub const EINVAL: c_int = 22; - pub const ENFILE: c_int = 23; - pub const EMFILE: c_int = 24; - pub const ENOTTY: c_int = 25; - pub const ETXTBSY: c_int = 26; - pub const EFBIG: c_int = 27; - pub const ENOSPC: c_int = 28; - pub const ESPIPE: c_int = 29; - pub const EROFS: c_int = 30; - pub const EMLINK: c_int = 31; - pub const EPIPE: c_int = 32; - pub const EDOM: c_int = 33; - pub const ERANGE: c_int = 34; - pub const EAGAIN: c_int = 35; - pub const EWOULDBLOCK: c_int = EAGAIN; - pub const EINPROGRESS: c_int = 36; - pub const EALREADY: c_int = 37; - pub const ENOTSOCK: c_int = 38; - pub const EDESTADDRREQ: c_int = 39; - pub const EMSGSIZE: c_int = 40; - pub const EPROTOTYPE: c_int = 41; - pub const ENOPROTOOPT: c_int = 42; - pub const EPROTONOSUPPORT: c_int = 43; - pub const ESOCKTNOSUPPORT: c_int = 44; - pub const ENOTSUP: c_int = 45; - pub const EPFNOSUPPORT: c_int = 46; - pub const EAFNOSUPPORT: c_int = 47; - pub const EADDRINUSE: c_int = 48; - pub const EADDRNOTAVAIL: c_int = 49; - pub const ENETDOWN: c_int = 50; - pub const ENETUNREACH: c_int = 51; - pub const ENETRESET: c_int = 52; - pub const ECONNABORTED: c_int = 53; - pub const ECONNRESET: c_int = 54; - pub const ENOBUFS: c_int = 55; - pub const EISCONN: c_int = 56; - pub const ENOTCONN: c_int = 57; - pub const ESHUTDOWN: c_int = 58; - pub const ETOOMANYREFS: c_int = 59; - pub const ETIMEDOUT: c_int = 60; - pub const ECONNREFUSED: c_int = 61; - pub const ELOOP: c_int = 62; - pub const ENAMETOOLONG: c_int = 63; - pub const EHOSTDOWN: c_int = 64; - pub const EHOSTUNREACH: c_int = 65; - pub const ENOTEMPTY: c_int = 66; - pub const EPROCLIM: c_int = 67; - pub const EUSERS: c_int = 68; - pub const EDQUOT: c_int = 69; - pub const ESTALE: c_int = 70; - pub const EREMOTE: c_int = 71; - pub const EBADRPC: c_int = 72; - pub const ERPCMISMATCH: c_int = 73; - pub const EPROGUNAVAIL: c_int = 74; - pub const EPROGMISMATCH: c_int = 75; - pub const EPROCUNAVAIL: c_int = 76; - pub const ENOLCK: c_int = 77; - pub const ENOSYS: c_int = 78; - pub const EFTYPE: c_int = 79; - pub const EAUTH: c_int = 80; - pub const ENEEDAUTH: c_int = 81; - pub const EPWROFF: c_int = 82; - pub const EDEVERR: c_int = 83; - pub const EOVERFLOW: c_int = 84; - pub const EBADEXEC: c_int = 85; - pub const EBADARCH: c_int = 86; - pub const ESHLIBVERS: c_int = 87; - pub const EBADMACHO: c_int = 88; - pub const ECANCELED: c_int = 89; - pub const EIDRM: c_int = 90; - pub const ENOMSG: c_int = 91; - pub const EILSEQ: c_int = 92; - pub const ENOATTR: c_int = 93; - pub const EBADMSG: c_int = 94; - pub const EMULTIHOP: c_int = 95; - pub const ENODATA: c_int = 96; - pub const ENOLINK: c_int = 97; - pub const ENOSR: c_int = 98; - pub const ENOSTR: c_int = 99; - pub const EPROTO: c_int = 100; - pub const ETIME: c_int = 101; - pub const EOPNOTSUPP: c_int = 102; - pub const ENOPOLICY: c_int = 103; - pub const ENOTRECOVERABLE: c_int = 104; - pub const EOWNERDEAD: c_int = 105; - pub const EQFULL: c_int = 106; - pub const ELAST: c_int = 106; - } - pub mod posix01 { - use types::os::arch::c95::{c_int, size_t}; - use types::os::common::posix01::rlim_t; - - pub const F_DUPFD: c_int = 0; - pub const F_GETFD: c_int = 1; - pub const F_SETFD: c_int = 2; - pub const F_GETFL: c_int = 3; - pub const F_SETFL: c_int = 4; - - pub const O_ACCMODE: c_int = 3; - - pub const SIGTRAP: c_int = 5; - pub const SIG_IGN: size_t = 1; - - pub const GLOB_APPEND: c_int = 0x0001; - pub const GLOB_DOOFFS: c_int = 0x0002; - pub const GLOB_ERR: c_int = 0x0004; - pub const GLOB_MARK: c_int = 0x0008; - pub const GLOB_NOCHECK: c_int = 0x0010; - pub const GLOB_NOSORT: c_int = 0x0020; - pub const GLOB_NOESCAPE: c_int = 0x2000; - - pub const GLOB_NOSPACE: c_int = -1; - pub const GLOB_ABORTED: c_int = -2; - pub const GLOB_NOMATCH: c_int = -3; - - pub const POSIX_MADV_NORMAL: c_int = 0; - pub const POSIX_MADV_RANDOM: c_int = 1; - pub const POSIX_MADV_SEQUENTIAL: c_int = 2; - pub const POSIX_MADV_WILLNEED: c_int = 3; - pub const POSIX_MADV_DONTNEED: c_int = 4; - - pub const _SC_IOV_MAX: c_int = 56; - pub const _SC_GETGR_R_SIZE_MAX: c_int = 70; - pub const _SC_GETPW_R_SIZE_MAX: c_int = 71; - pub const _SC_LOGIN_NAME_MAX: c_int = 73; - pub const _SC_MQ_PRIO_MAX: c_int = 75; - pub const _SC_THREAD_ATTR_STACKADDR: c_int = 82; - pub const _SC_THREAD_ATTR_STACKSIZE: c_int = 83; - pub const _SC_THREAD_DESTRUCTOR_ITERATIONS: c_int = 85; - pub const _SC_THREAD_KEYS_MAX: c_int = 86; - pub const _SC_THREAD_PRIO_INHERIT: c_int = 87; - pub const _SC_THREAD_PRIO_PROTECT: c_int = 88; - pub const _SC_THREAD_PRIORITY_SCHEDULING: c_int = 89; - pub const _SC_THREAD_PROCESS_SHARED: c_int = 90; - pub const _SC_THREAD_SAFE_FUNCTIONS: c_int = 91; - pub const _SC_THREAD_STACK_MIN: c_int = 93; - pub const _SC_THREAD_THREADS_MAX: c_int = 94; - pub const _SC_THREADS: c_int = 96; - pub const _SC_TTY_NAME_MAX: c_int = 101; - pub const _SC_ATEXIT_MAX: c_int = 107; - pub const _SC_XOPEN_CRYPT: c_int = 108; - pub const _SC_XOPEN_ENH_I18N: c_int = 109; - pub const _SC_XOPEN_LEGACY: c_int = 110; - pub const _SC_XOPEN_REALTIME: c_int = 111; - pub const _SC_XOPEN_REALTIME_THREADS: c_int = 112; - pub const _SC_XOPEN_SHM: c_int = 113; - pub const _SC_XOPEN_UNIX: c_int = 115; - pub const _SC_XOPEN_VERSION: c_int = 116; - pub const _SC_XOPEN_XCU_VERSION: c_int = 121; - - pub const PTHREAD_CREATE_JOINABLE: c_int = 1; - pub const PTHREAD_CREATE_DETACHED: c_int = 2; - pub const PTHREAD_STACK_MIN: size_t = 8192; - - pub const RLIMIT_CPU: c_int = 0; - pub const RLIMIT_FSIZE: c_int = 1; - pub const RLIMIT_DATA: c_int = 2; - pub const RLIMIT_STACK: c_int = 3; - pub const RLIMIT_CORE: c_int = 4; - pub const RLIMIT_AS: c_int = 5; - pub const RLIMIT_MEMLOCK: c_int = 6; - pub const RLIMIT_NPROC: c_int = 7; - pub const RLIMIT_NOFILE: c_int = 8; - pub const RLIM_NLIMITS: c_int = 9; - pub const _RLIMIT_POSIX_FLAG: c_int = 0x1000; - - pub const RLIM_INFINITY: rlim_t = 0xffff_ffff_ffff_ffff; - - pub const RUSAGE_SELF: c_int = 0; - pub const RUSAGE_CHILDREN: c_int = -1; - pub const RUSAGE_THREAD: c_int = 1; - } - pub mod posix08 { - use types::os::arch::c95::c_int; - pub const O_CLOEXEC: c_int = 0x1000000; - pub const F_DUPFD_CLOEXEC: c_int = 67; - } - pub mod bsd44 { - use types::os::arch::c95::c_int; - - pub const MADV_NORMAL: c_int = 0; - pub const MADV_RANDOM: c_int = 1; - pub const MADV_SEQUENTIAL: c_int = 2; - pub const MADV_WILLNEED: c_int = 3; - pub const MADV_DONTNEED: c_int = 4; - pub const MADV_FREE: c_int = 5; - pub const MADV_ZERO_WIRED_PAGES: c_int = 6; - pub const MADV_FREE_REUSABLE: c_int = 7; - pub const MADV_FREE_REUSE: c_int = 8; - pub const MADV_CAN_REUSE: c_int = 9; - - pub const MINCORE_INCORE: c_int = 0x1; - pub const MINCORE_REFERENCED: c_int = 0x2; - pub const MINCORE_MODIFIED: c_int = 0x4; - pub const MINCORE_REFERENCED_OTHER: c_int = 0x8; - pub const MINCORE_MODIFIED_OTHER: c_int = 0x10; - - pub const AF_UNIX: c_int = 1; - pub const AF_INET: c_int = 2; - pub const AF_INET6: c_int = 30; - pub const SOCK_STREAM: c_int = 1; - pub const SOCK_DGRAM: c_int = 2; - pub const SOCK_RAW: c_int = 3; - pub const IPPROTO_TCP: c_int = 6; - pub const IPPROTO_IP: c_int = 0; - pub const IPPROTO_IPV6: c_int = 41; - pub const IP_MULTICAST_TTL: c_int = 10; - pub const IP_MULTICAST_LOOP: c_int = 11; - pub const IP_TTL: c_int = 4; - pub const IP_HDRINCL: c_int = 2; - pub const IP_ADD_MEMBERSHIP: c_int = 12; - pub const IP_DROP_MEMBERSHIP: c_int = 13; - pub const IPV6_ADD_MEMBERSHIP: c_int = 12; - pub const IPV6_DROP_MEMBERSHIP: c_int = 13; - - pub const TCP_NODELAY: c_int = 0x01; - pub const TCP_KEEPALIVE: c_int = 0x10; - pub const SOL_SOCKET: c_int = 0xffff; - - pub const SO_DEBUG: c_int = 0x01; - pub const SO_ACCEPTCONN: c_int = 0x0002; - pub const SO_REUSEADDR: c_int = 0x0004; - pub const SO_KEEPALIVE: c_int = 0x0008; - pub const SO_DONTROUTE: c_int = 0x0010; - pub const SO_BROADCAST: c_int = 0x0020; - pub const SO_USELOOPBACK: c_int = 0x0040; - pub const SO_LINGER: c_int = 0x0080; - pub const SO_OOBINLINE: c_int = 0x0100; - pub const SO_REUSEPORT: c_int = 0x0200; - pub const SO_SNDBUF: c_int = 0x1001; - pub const SO_RCVBUF: c_int = 0x1002; - pub const SO_SNDLOWAT: c_int = 0x1003; - pub const SO_RCVLOWAT: c_int = 0x1004; - pub const SO_SNDTIMEO: c_int = 0x1005; - pub const SO_RCVTIMEO: c_int = 0x1006; - pub const SO_ERROR: c_int = 0x1007; - pub const SO_TYPE: c_int = 0x1008; - - pub const IFF_LOOPBACK: c_int = 0x8; - - pub const SHUT_RD: c_int = 0; - pub const SHUT_WR: c_int = 1; - pub const SHUT_RDWR: c_int = 2; - - pub const LOCK_SH: c_int = 1; - pub const LOCK_EX: c_int = 2; - pub const LOCK_NB: c_int = 4; - pub const LOCK_UN: c_int = 8; - } - pub mod extra { - use types::os::arch::c95::c_int; - - pub const O_DSYNC: c_int = 4194304; - pub const O_SYNC: c_int = 128; - pub const O_NONBLOCK: c_int = 4; - pub const F_GETPATH: c_int = 50; - pub const F_FULLFSYNC: c_int = 51; - - pub const MAP_COPY: c_int = 0x0002; - pub const MAP_RENAME: c_int = 0x0020; - pub const MAP_NORESERVE: c_int = 0x0040; - pub const MAP_NOEXTEND: c_int = 0x0100; - pub const MAP_HASSEMAPHORE: c_int = 0x0200; - pub const MAP_NOCACHE: c_int = 0x0400; - pub const MAP_JIT: c_int = 0x0800; - pub const MAP_STACK: c_int = 0; - - pub const IPPROTO_RAW: c_int = 255; - - pub const SO_NREAD: c_int = 0x1020; - pub const SO_NKE: c_int = 0x1021; - pub const SO_NOSIGPIPE: c_int = 0x1022; - pub const SO_NOADDRERR: c_int = 0x1023; - pub const SO_NWRITE: c_int = 0x1024; - pub const SO_DONTTRUNC: c_int = 0x2000; - pub const SO_WANTMORE: c_int = 0x4000; - pub const SO_WANTOOBFLAG: c_int = 0x8000; - - pub const PATH_MAX: c_int = 1024; - } - pub mod sysconf { - use types::os::arch::c95::c_int; - - pub const _SC_ARG_MAX: c_int = 1; - pub const _SC_CHILD_MAX: c_int = 2; - pub const _SC_CLK_TCK: c_int = 3; - pub const _SC_NGROUPS_MAX: c_int = 4; - pub const _SC_OPEN_MAX: c_int = 5; - pub const _SC_JOB_CONTROL: c_int = 6; - pub const _SC_SAVED_IDS: c_int = 7; - pub const _SC_VERSION: c_int = 8; - pub const _SC_BC_BASE_MAX: c_int = 9; - pub const _SC_BC_DIM_MAX: c_int = 10; - pub const _SC_BC_SCALE_MAX: c_int = 11; - pub const _SC_BC_STRING_MAX: c_int = 12; - pub const _SC_COLL_WEIGHTS_MAX: c_int = 13; - pub const _SC_EXPR_NEST_MAX: c_int = 14; - pub const _SC_LINE_MAX: c_int = 15; - pub const _SC_RE_DUP_MAX: c_int = 16; - pub const _SC_2_VERSION: c_int = 17; - pub const _SC_2_C_BIND: c_int = 18; - pub const _SC_2_C_DEV: c_int = 19; - pub const _SC_2_CHAR_TERM: c_int = 20; - pub const _SC_2_FORT_DEV: c_int = 21; - pub const _SC_2_FORT_RUN: c_int = 22; - pub const _SC_2_LOCALEDEF: c_int = 23; - pub const _SC_2_SW_DEV: c_int = 24; - pub const _SC_2_UPE: c_int = 25; - pub const _SC_STREAM_MAX: c_int = 26; - pub const _SC_TZNAME_MAX: c_int = 27; - pub const _SC_ASYNCHRONOUS_IO: c_int = 28; - pub const _SC_PAGESIZE: c_int = 29; - pub const _SC_MEMLOCK: c_int = 30; - pub const _SC_MEMLOCK_RANGE: c_int = 31; - pub const _SC_MEMORY_PROTECTION: c_int = 32; - pub const _SC_MESSAGE_PASSING: c_int = 33; - pub const _SC_PRIORITIZED_IO: c_int = 34; - pub const _SC_PRIORITY_SCHEDULING: c_int = 35; - pub const _SC_REALTIME_SIGNALS: c_int = 36; - pub const _SC_SEMAPHORES: c_int = 37; - pub const _SC_FSYNC: c_int = 38; - pub const _SC_SHARED_MEMORY_OBJECTS: c_int = 39; - pub const _SC_SYNCHRONIZED_IO: c_int = 40; - pub const _SC_TIMERS: c_int = 41; - pub const _SC_AIO_LISTIO_MAX: c_int = 42; - pub const _SC_AIO_MAX: c_int = 43; - pub const _SC_AIO_PRIO_DELTA_MAX: c_int = 44; - pub const _SC_DELAYTIMER_MAX: c_int = 45; - pub const _SC_MQ_OPEN_MAX: c_int = 46; - pub const _SC_MAPPED_FILES: c_int = 47; - pub const _SC_RTSIG_MAX: c_int = 48; - pub const _SC_SEM_NSEMS_MAX: c_int = 49; - pub const _SC_SEM_VALUE_MAX: c_int = 50; - pub const _SC_SIGQUEUE_MAX: c_int = 51; - pub const _SC_TIMER_MAX: c_int = 52; - pub const _SC_NPROCESSORS_CONF: c_int = 57; - pub const _SC_NPROCESSORS_ONLN: c_int = 58; - pub const _SC_2_PBS: c_int = 59; - pub const _SC_2_PBS_ACCOUNTING: c_int = 60; - pub const _SC_2_PBS_CHECKPOINT: c_int = 61; - pub const _SC_2_PBS_LOCATE: c_int = 62; - pub const _SC_2_PBS_MESSAGE: c_int = 63; - pub const _SC_2_PBS_TRACK: c_int = 64; - pub const _SC_ADVISORY_INFO: c_int = 65; - pub const _SC_BARRIERS: c_int = 66; - pub const _SC_CLOCK_SELECTION: c_int = 67; - pub const _SC_CPUTIME: c_int = 68; - pub const _SC_FILE_LOCKING: c_int = 69; - pub const _SC_HOST_NAME_MAX: c_int = 72; - pub const _SC_MONOTONIC_CLOCK: c_int = 74; - pub const _SC_READER_WRITER_LOCKS: c_int = 76; - pub const _SC_REGEXP: c_int = 77; - pub const _SC_SHELL: c_int = 78; - pub const _SC_SPAWN: c_int = 79; - pub const _SC_SPIN_LOCKS: c_int = 80; - pub const _SC_SPORADIC_SERVER: c_int = 81; - pub const _SC_THREAD_CPUTIME: c_int = 84; - pub const _SC_THREAD_SPORADIC_SERVER: c_int = 92; - pub const _SC_TIMEOUTS: c_int = 95; - pub const _SC_TRACE: c_int = 97; - pub const _SC_TRACE_EVENT_FILTER: c_int = 98; - pub const _SC_TRACE_INHERIT: c_int = 99; - pub const _SC_TRACE_LOG: c_int = 100; - pub const _SC_TYPED_MEMORY_OBJECTS: c_int = 102; - pub const _SC_V6_ILP32_OFF32: c_int = 103; - pub const _SC_V6_ILP32_OFFBIG: c_int = 104; - pub const _SC_V6_LP64_OFF64: c_int = 105; - pub const _SC_V6_LPBIG_OFFBIG: c_int = 106; - pub const _SC_IPV6: c_int = 118; - pub const _SC_RAW_SOCKETS: c_int = 119; - pub const _SC_SYMLOOP_MAX: c_int = 120; - pub const _SC_PAGE_SIZE: c_int = _SC_PAGESIZE; - pub const _SC_XOPEN_STREAMS: c_int = 114; - pub const _SC_XBS5_ILP32_OFF32: c_int = 122; - pub const _SC_XBS5_ILP32_OFFBIG: c_int = 123; - pub const _SC_XBS5_LP64_OFF64: c_int = 124; - pub const _SC_XBS5_LPBIG_OFFBIG: c_int = 125; - pub const _SC_SS_REPL_MAX: c_int = 126; - pub const _SC_TRACE_EVENT_NAME_MAX: c_int = 127; - pub const _SC_TRACE_NAME_MAX: c_int = 128; - pub const _SC_TRACE_SYS_MAX: c_int = 129; - pub const _SC_TRACE_USER_EVENT_MAX: c_int = 130; - pub const _SC_PASS_MAX: c_int = 131; - - pub const _PC_NAME_MAX: c_int = 4; - pub const _PC_PATH_MAX: c_int = 5; - } - } -} - - -pub mod funcs { - // Thankfully most of c95 is universally available and does not vary by OS - // or anything. The same is not true of POSIX. - - pub mod c95 { - pub mod ctype { - use types::os::arch::c95::{c_char, c_int}; - - extern { - pub fn isalnum(c: c_int) -> c_int; - pub fn isalpha(c: c_int) -> c_int; - pub fn iscntrl(c: c_int) -> c_int; - pub fn isdigit(c: c_int) -> c_int; - pub fn isgraph(c: c_int) -> c_int; - pub fn islower(c: c_int) -> c_int; - pub fn isprint(c: c_int) -> c_int; - pub fn ispunct(c: c_int) -> c_int; - pub fn isspace(c: c_int) -> c_int; - pub fn isupper(c: c_int) -> c_int; - pub fn isxdigit(c: c_int) -> c_int; - pub fn tolower(c: c_char) -> c_char; - pub fn toupper(c: c_char) -> c_char; - } - } - - pub mod stdio { - use types::common::c95::{FILE, c_void, fpos_t}; - use types::os::arch::c95::{c_char, c_int, c_long, size_t}; - - extern { - pub fn fopen(filename: *const c_char, mode: *const c_char) -> *mut FILE; - pub fn freopen(filename: *const c_char, - mode: *const c_char, - file: *mut FILE) - -> *mut FILE; - pub fn fflush(file: *mut FILE) -> c_int; - pub fn fclose(file: *mut FILE) -> c_int; - pub fn remove(filename: *const c_char) -> c_int; - pub fn rename(oldname: *const c_char, newname: *const c_char) -> c_int; - pub fn tmpfile() -> *mut FILE; - pub fn setvbuf(stream: *mut FILE, - buffer: *mut c_char, - mode: c_int, - size: size_t) - -> c_int; - pub fn setbuf(stream: *mut FILE, buf: *mut c_char); - // Omitted: printf and scanf variants. - pub fn fgetc(stream: *mut FILE) -> c_int; - pub fn fgets(buf: *mut c_char, n: c_int, stream: *mut FILE) -> *mut c_char; - pub fn fputc(c: c_int, stream: *mut FILE) -> c_int; - pub fn fputs(s: *const c_char, stream: *mut FILE) -> c_int; - // Omitted: getc, getchar (might be macros). - - // Omitted: gets, so ridiculously unsafe that it should not - // survive. - - // Omitted: putc, putchar (might be macros). - pub fn puts(s: *const c_char) -> c_int; - pub fn ungetc(c: c_int, stream: *mut FILE) -> c_int; - pub fn fread(ptr: *mut c_void, - size: size_t, - nobj: size_t, - stream: *mut FILE) - -> size_t; - pub fn fwrite(ptr: *const c_void, - size: size_t, - nobj: size_t, - stream: *mut FILE) - -> size_t; - pub fn fseek(stream: *mut FILE, offset: c_long, whence: c_int) -> c_int; - pub fn ftell(stream: *mut FILE) -> c_long; - pub fn rewind(stream: *mut FILE); - pub fn fgetpos(stream: *mut FILE, ptr: *mut fpos_t) -> c_int; - pub fn fsetpos(stream: *mut FILE, ptr: *mut fpos_t) -> c_int; - pub fn feof(stream: *mut FILE) -> c_int; - pub fn ferror(stream: *mut FILE) -> c_int; - pub fn perror(s: *const c_char); - } - } - - pub mod stdlib { - use types::common::c95::c_void; - use types::os::arch::c95::{c_char, c_double, c_int}; - use types::os::arch::c95::{c_long, c_uint, c_ulong}; - use types::os::arch::c95::size_t; - - extern { - pub fn abs(i: c_int) -> c_int; - pub fn labs(i: c_long) -> c_long; - // Omitted: div, ldiv (return pub type incomplete). - pub fn atof(s: *const c_char) -> c_double; - pub fn atoi(s: *const c_char) -> c_int; - pub fn strtod(s: *const c_char, endp: *mut *mut c_char) -> c_double; - pub fn strtol(s: *const c_char, endp: *mut *mut c_char, base: c_int) -> c_long; - pub fn strtoul(s: *const c_char, endp: *mut *mut c_char, base: c_int) -> c_ulong; - pub fn calloc(nobj: size_t, size: size_t) -> *mut c_void; - pub fn malloc(size: size_t) -> *mut c_void; - pub fn realloc(p: *mut c_void, size: size_t) -> *mut c_void; - pub fn free(p: *mut c_void); - - /// Exits the running program in a possibly dangerous manner. - /// - /// # Safety - /// - /// While this forces your program to exit, it does so in a way that has - /// consequences. This will skip all unwinding code, which means that anything - /// relying on unwinding for cleanup (such as flushing and closing a buffer to a - /// file) may act in an unexpected way. - /// - /// # Examples - /// - /// ```no_run,ignore - /// extern crate libc; - /// - /// fn main() { - /// unsafe { - /// libc::exit(1); - /// } - /// } - /// ``` - pub fn exit(status: c_int) -> !; - pub fn _exit(status: c_int) -> !; - pub fn atexit(cb: extern "C" fn()) -> c_int; - pub fn system(s: *const c_char) -> c_int; - pub fn getenv(s: *const c_char) -> *mut c_char; - // Omitted: bsearch, qsort - pub fn rand() -> c_int; - pub fn srand(seed: c_uint); - } - } - - pub mod string { - use types::common::c95::c_void; - use types::os::arch::c95::{c_char, c_int, size_t}; - use types::os::arch::c95::wchar_t; - - extern { - pub fn strcpy(dst: *mut c_char, src: *const c_char) -> *mut c_char; - pub fn strncpy(dst: *mut c_char, src: *const c_char, n: size_t) -> *mut c_char; - pub fn strcat(s: *mut c_char, ct: *const c_char) -> *mut c_char; - pub fn strncat(s: *mut c_char, ct: *const c_char, n: size_t) -> *mut c_char; - pub fn strcmp(cs: *const c_char, ct: *const c_char) -> c_int; - pub fn strncmp(cs: *const c_char, ct: *const c_char, n: size_t) -> c_int; - pub fn strcoll(cs: *const c_char, ct: *const c_char) -> c_int; - pub fn strchr(cs: *const c_char, c: c_int) -> *mut c_char; - pub fn strrchr(cs: *const c_char, c: c_int) -> *mut c_char; - pub fn strspn(cs: *const c_char, ct: *const c_char) -> size_t; - pub fn strcspn(cs: *const c_char, ct: *const c_char) -> size_t; - pub fn strpbrk(cs: *const c_char, ct: *const c_char) -> *mut c_char; - pub fn strstr(cs: *const c_char, ct: *const c_char) -> *mut c_char; - pub fn strlen(cs: *const c_char) -> size_t; - pub fn strerror(n: c_int) -> *mut c_char; - pub fn strtok(s: *mut c_char, t: *const c_char) -> *mut c_char; - pub fn strxfrm(s: *mut c_char, ct: *const c_char, n: size_t) -> size_t; - pub fn wcslen(buf: *const wchar_t) -> size_t; - - // Omitted: memcpy, memmove, memset (provided by LLVM) - - // These are fine to execute on the Rust stack. They must be, - // in fact, because LLVM generates calls to them! - pub fn memcmp(cx: *const c_void, ct: *const c_void, n: size_t) -> c_int; - pub fn memchr(cx: *const c_void, c: c_int, n: size_t) -> *mut c_void; - } - } - } - - // Microsoft helpfully underscore-qualifies all of its POSIX-like symbols - // to make sure you don't use them accidentally. It also randomly deviates - // from the exact signatures you might otherwise expect, and omits much, - // so be careful when trying to write portable code; it won't always work - // with the same POSIX functions and types as other platforms. - - #[cfg(target_os = "windows")] - pub mod posix88 { - pub mod stat_ { - use types::os::common::posix01::{stat, utimbuf}; - use types::os::arch::c95::{c_int, c_char, wchar_t}; - - extern { - #[link_name = "_chmod"] - pub fn chmod(path: *const c_char, mode: c_int) -> c_int; - #[link_name = "_wchmod"] - pub fn wchmod(path: *const wchar_t, mode: c_int) -> c_int; - #[link_name = "_mkdir"] - pub fn mkdir(path: *const c_char) -> c_int; - #[link_name = "_wrmdir"] - pub fn wrmdir(path: *const wchar_t) -> c_int; - #[link_name = "_fstat64"] - pub fn fstat(fildes: c_int, buf: *mut stat) -> c_int; - #[link_name = "_stat64"] - pub fn stat(path: *const c_char, buf: *mut stat) -> c_int; - #[link_name = "_wstat64"] - pub fn wstat(path: *const wchar_t, buf: *mut stat) -> c_int; - #[link_name = "_wutime64"] - pub fn wutime(file: *const wchar_t, buf: *mut utimbuf) -> c_int; - } - } - - pub mod stdio { - use types::common::c95::FILE; - use types::os::arch::c95::{c_int, c_char}; - - extern { - #[link_name = "_popen"] - pub fn popen(command: *const c_char, mode: *const c_char) -> *mut FILE; - #[link_name = "_pclose"] - pub fn pclose(stream: *mut FILE) -> c_int; - #[link_name = "_fdopen"] - pub fn fdopen(fd: c_int, mode: *const c_char) -> *mut FILE; - #[link_name = "_fileno"] - pub fn fileno(stream: *mut FILE) -> c_int; - } - } - - pub mod fcntl { - use types::os::arch::c95::{c_int, c_char, wchar_t}; - extern { - #[link_name = "_open"] - pub fn open(path: *const c_char, oflag: c_int, mode: c_int) -> c_int; - #[link_name = "_wopen"] - pub fn wopen(path: *const wchar_t, oflag: c_int, mode: c_int) -> c_int; - #[link_name = "_creat"] - pub fn creat(path: *const c_char, mode: c_int) -> c_int; - } - } - - pub mod dirent { - // Not supplied at all. - } - - pub mod unistd { - use types::common::c95::c_void; - use types::os::arch::c95::{c_int, c_uint, c_char, c_long, size_t}; - use types::os::arch::c99::intptr_t; - - extern { - #[link_name = "_access"] - pub fn access(path: *const c_char, amode: c_int) -> c_int; - #[link_name = "_chdir"] - pub fn chdir(dir: *const c_char) -> c_int; - #[link_name = "_close"] - pub fn close(fd: c_int) -> c_int; - #[link_name = "_dup"] - pub fn dup(fd: c_int) -> c_int; - #[link_name = "_dup2"] - pub fn dup2(src: c_int, dst: c_int) -> c_int; - #[link_name = "_execv"] - pub fn execv(prog: *const c_char, argv: *const *const c_char) -> intptr_t; - #[link_name = "_execve"] - pub fn execve(prog: *const c_char, - argv: *const *const c_char, - envp: *const *const c_char) - -> c_int; - #[link_name = "_execvp"] - pub fn execvp(c: *const c_char, argv: *const *const c_char) -> c_int; - #[link_name = "_execvpe"] - pub fn execvpe(c: *const c_char, - argv: *const *const c_char, - envp: *const *const c_char) - -> c_int; - #[link_name = "_getcwd"] - pub fn getcwd(buf: *mut c_char, size: size_t) -> *mut c_char; - #[link_name = "_getpid"] - pub fn getpid() -> c_int; - #[link_name = "_isatty"] - pub fn isatty(fd: c_int) -> c_int; - #[link_name = "_lseek"] - pub fn lseek(fd: c_int, offset: c_long, origin: c_int) -> c_long; - #[link_name = "_pipe"] - pub fn pipe(fds: *mut c_int, psize: c_uint, textmode: c_int) -> c_int; - #[link_name = "_read"] - pub fn read(fd: c_int, buf: *mut c_void, count: c_uint) -> c_int; - #[link_name = "_rmdir"] - pub fn rmdir(path: *const c_char) -> c_int; - #[link_name = "_unlink"] - pub fn unlink(c: *const c_char) -> c_int; - #[link_name = "_write"] - pub fn write(fd: c_int, buf: *const c_void, count: c_uint) -> c_int; - } - } - - pub mod mman { - } - } - - #[cfg(any(target_os = "linux", - target_os = "android", - target_os = "macos", - target_os = "ios", - target_os = "freebsd", - target_os = "dragonfly", - target_os = "bitrig", - target_os = "netbsd", - target_os = "openbsd", - target_os = "nacl"))] - pub mod posix88 { - pub mod stat_ { - use types::os::arch::c95::{c_char, c_int}; - use types::os::arch::posix01::stat; - use types::os::arch::posix88::mode_t; - - extern { - pub fn chmod(path: *const c_char, mode: mode_t) -> c_int; - pub fn fchmod(fd: c_int, mode: mode_t) -> c_int; - - #[cfg_attr(target_os = "macos", link_name = "fstat64")] - #[cfg_attr(target_os = "netbsd", link_name = "__fstat50")] - pub fn fstat(fildes: c_int, buf: *mut stat) -> c_int; - - pub fn mkdir(path: *const c_char, mode: mode_t) -> c_int; - #[cfg(not(target_os = "nacl"))] - pub fn mkfifo(path: *const c_char, mode: mode_t) -> c_int; - - #[cfg_attr(target_os = "macos", link_name = "stat64")] - #[cfg_attr(target_os = "netbsd", link_name = "__stat50")] - pub fn stat(path: *const c_char, buf: *mut stat) -> c_int; - } - } - - pub mod stdio { - use types::common::c95::FILE; - use types::os::arch::c95::{c_char, c_int}; - - extern { - pub fn popen(command: *const c_char, mode: *const c_char) -> *mut FILE; - pub fn pclose(stream: *mut FILE) -> c_int; - pub fn fdopen(fd: c_int, mode: *const c_char) -> *mut FILE; - pub fn fileno(stream: *mut FILE) -> c_int; - } - } - - pub mod fcntl { - use types::os::arch::c95::{c_char, c_int}; - use types::os::arch::posix88::mode_t; - - mod open_shim { - extern { - #[cfg(any(target_os = "macos", - target_os = "ios"))] - pub fn open(path: *const ::c_char, oflag: ::c_int, ...) -> ::c_int; - - #[cfg(not(any(target_os = "macos", - target_os = "ios")))] - pub fn open(path: *const ::c_char, oflag: ::c_int, mode: ::mode_t) -> ::c_int; - } - } - - #[cfg(any(target_os = "macos", - target_os = "ios"))] - #[inline] - pub unsafe extern "C" fn open(path: *const c_char, - oflag: c_int, - mode: mode_t) - -> c_int { - use types::os::arch::c95::c_uint; - open_shim::open(path, oflag, mode as c_uint) - } - - #[cfg(not(any(target_os = "macos", - target_os = "ios")))] - #[inline] - pub unsafe extern "C" fn open(path: *const c_char, - oflag: c_int, - mode: mode_t) - -> c_int { - open_shim::open(path, oflag, mode) - } - - extern { - pub fn creat(path: *const c_char, mode: mode_t) -> c_int; - pub fn fcntl(fd: c_int, cmd: c_int, ...) -> c_int; - } - } - - pub mod dirent { - use types::common::posix88::{DIR, dirent_t}; - use types::os::arch::c95::{c_char, c_int, c_long}; - - // NB: On OS X opendir and readdir have two versions, - // one for 32-bit kernelspace and one for 64. - // We should be linking to the 64-bit ones, called - // opendir$INODE64, etc. but for some reason rustc - // doesn't link it correctly on i686, so we're going - // through a C function that mysteriously does work. - - extern { - #[link_name="rust_opendir"] - pub fn opendir(dirname: *const c_char) -> *mut DIR; - #[link_name="rust_readdir_r"] - pub fn readdir_r(dirp: *mut DIR, - entry: *mut dirent_t, - result: *mut *mut dirent_t) - -> c_int; - } - - extern { - pub fn closedir(dirp: *mut DIR) -> c_int; - pub fn rewinddir(dirp: *mut DIR); - pub fn seekdir(dirp: *mut DIR, loc: c_long); - pub fn telldir(dirp: *mut DIR) -> c_long; - } - } - - pub mod unistd { - use types::common::c95::c_void; - use types::os::arch::c95::{c_char, c_int, c_long, c_uint}; - use types::os::arch::c95::size_t; - use types::os::common::posix01::timespec; - use types::os::arch::posix01::utimbuf; - use types::os::arch::posix88::{gid_t, off_t, pid_t}; - use types::os::arch::posix88::{ssize_t, uid_t}; - - #[cfg(not(target_os = "nacl"))] - extern { - pub fn access(path: *const c_char, amode: c_int) -> c_int; - pub fn alarm(seconds: c_uint) -> c_uint; - pub fn chdir(dir: *const c_char) -> c_int; - pub fn chown(path: *const c_char, uid: uid_t, gid: gid_t) -> c_int; - pub fn close(fd: c_int) -> c_int; - pub fn dup(fd: c_int) -> c_int; - pub fn dup2(src: c_int, dst: c_int) -> c_int; - pub fn execv(prog: *const c_char, argv: *const *const c_char) -> c_int; - pub fn execve(prog: *const c_char, - argv: *const *const c_char, - envp: *const *const c_char) - -> c_int; - pub fn execvp(c: *const c_char, argv: *const *const c_char) -> c_int; - pub fn fork() -> pid_t; - pub fn fpathconf(filedes: c_int, name: c_int) -> c_long; - pub fn getcwd(buf: *mut c_char, size: size_t) -> *mut c_char; - pub fn getegid() -> gid_t; - pub fn geteuid() -> uid_t; - pub fn getgid() -> gid_t; - pub fn getgroups(ngroups_max: c_int, groups: *mut gid_t) -> c_int; - pub fn getlogin() -> *mut c_char; - // GNU getopt(3) modifies its arguments despite the - // char * const [] prototype; see the manpage. - pub fn getopt(argc: c_int, argv: *mut *mut c_char, optstr: *const c_char) -> c_int; - pub fn getpgrp() -> pid_t; - pub fn getpid() -> pid_t; - pub fn getppid() -> pid_t; - pub fn getuid() -> uid_t; - pub fn getsid(pid: pid_t) -> pid_t; - pub fn isatty(fd: c_int) -> c_int; - pub fn link(src: *const c_char, dst: *const c_char) -> c_int; - pub fn lseek(fd: c_int, offset: off_t, whence: c_int) -> off_t; - pub fn pathconf(path: *mut c_char, name: c_int) -> c_long; - pub fn pause() -> c_int; - pub fn pipe(fds: *mut c_int) -> c_int; - pub fn read(fd: c_int, buf: *mut c_void, count: size_t) -> ssize_t; - pub fn rmdir(path: *const c_char) -> c_int; - pub fn setgid(gid: gid_t) -> c_int; - pub fn setpgid(pid: pid_t, pgid: pid_t) -> c_int; - pub fn setsid() -> pid_t; - pub fn setuid(uid: uid_t) -> c_int; - pub fn sleep(secs: c_uint) -> c_uint; - pub fn usleep(secs: c_uint) -> c_int; - #[cfg_attr(target_os = "netbsd", link_name = "__nanosleep50")] - pub fn nanosleep(rqtp: *const timespec, rmtp: *mut timespec) -> c_int; - pub fn sysconf(name: c_int) -> c_long; - pub fn tcgetpgrp(fd: c_int) -> pid_t; - pub fn ttyname(fd: c_int) -> *mut c_char; - pub fn unlink(c: *const c_char) -> c_int; - pub fn wait(status: *const c_int) -> pid_t; - pub fn waitpid(pid: pid_t, status: *const c_int, options: c_int) -> pid_t; - pub fn write(fd: c_int, buf: *const c_void, count: size_t) -> ssize_t; - pub fn pread(fd: c_int, buf: *mut c_void, count: size_t, offset: off_t) -> ssize_t; - pub fn pwrite(fd: c_int, - buf: *const c_void, - count: size_t, - offset: off_t) - -> ssize_t; - #[cfg_attr(target_os = "netbsd", link_name = "__utime50")] - pub fn utime(file: *const c_char, buf: *const utimbuf) -> c_int; - } - #[cfg(target_os = "nacl")] - extern { - pub fn access(path: *const c_char, amode: c_int) -> c_int; - pub fn chdir(dir: *const c_char) -> c_int; - pub fn chown(path: *const c_char, uid: uid_t, gid: gid_t) -> c_int; - pub fn close(fd: c_int) -> c_int; - pub fn dup(fd: c_int) -> c_int; - pub fn dup2(src: c_int, dst: c_int) -> c_int; - pub fn execv(prog: *const c_char, argv: *const *const c_char) -> c_int; - pub fn execve(prog: *const c_char, - argv: *const *const c_char, - envp: *const *const c_char) - -> c_int; - pub fn execvp(c: *const c_char, argv: *const *const c_char) -> c_int; - pub fn fork() -> pid_t; - pub fn getcwd(buf: *mut c_char, size: size_t) -> *mut c_char; - pub fn getegid() -> gid_t; - pub fn geteuid() -> uid_t; - pub fn getgid() -> gid_t; - pub fn getlogin() -> *mut c_char; - pub fn getopt(argc: c_int, - argv: *const *const c_char, - optstr: *const c_char) - -> c_int; - pub fn getuid() -> uid_t; - pub fn getsid(pid: pid_t) -> pid_t; - pub fn isatty(fd: c_int) -> c_int; - pub fn link(src: *const c_char, dst: *const c_char) -> c_int; - pub fn lseek(fd: c_int, offset: off_t, whence: c_int) -> off_t; - pub fn pipe(fds: *mut c_int) -> c_int; - pub fn read(fd: c_int, buf: *mut c_void, count: size_t) -> ssize_t; - pub fn rmdir(path: *const c_char) -> c_int; - pub fn setgid(gid: gid_t) -> c_int; - pub fn setuid(uid: uid_t) -> c_int; - pub fn sleep(secs: c_uint) -> c_uint; - pub fn usleep(secs: c_uint) -> c_int; - pub fn nanosleep(rqtp: *const timespec, rmtp: *mut timespec) -> c_int; - pub fn sysconf(name: c_int) -> c_long; - pub fn ttyname(fd: c_int) -> *mut c_char; - pub fn unlink(c: *const c_char) -> c_int; - pub fn wait(status: *const c_int) -> pid_t; - pub fn waitpid(pid: pid_t, status: *const c_int, options: c_int) -> pid_t; - pub fn write(fd: c_int, buf: *const c_void, count: size_t) -> ssize_t; - pub fn pread(fd: c_int, buf: *mut c_void, count: size_t, offset: off_t) -> ssize_t; - pub fn pwrite(fd: c_int, - buf: *const c_void, - count: size_t, - offset: off_t) - -> ssize_t; - pub fn utime(file: *const c_char, buf: *const utimbuf) -> c_int; - } - } - - pub mod signal { - use types::os::arch::c95::c_int; - use types::os::arch::posix88::pid_t; - - extern { - pub fn kill(pid: pid_t, sig: c_int) -> c_int; - } - } - - pub mod mman { - use types::common::c95::c_void; - use types::os::arch::c95::{size_t, c_int, c_char}; - use types::os::arch::posix88::{mode_t, off_t}; - - #[cfg(not(target_os = "nacl"))] - extern { - pub fn mlock(addr: *const c_void, len: size_t) -> c_int; - pub fn munlock(addr: *const c_void, len: size_t) -> c_int; - pub fn mlockall(flags: c_int) -> c_int; - pub fn munlockall() -> c_int; - - pub fn mprotect(addr: *mut c_void, len: size_t, prot: c_int) -> c_int; - - #[cfg_attr(target_os = "netbsd", link_name = "__msync13")] - pub fn msync(addr: *mut c_void, len: size_t, flags: c_int) -> c_int; - - pub fn shm_open(name: *const c_char, oflag: c_int, mode: mode_t) -> c_int; - pub fn shm_unlink(name: *const c_char) -> c_int; - } - - extern { - pub fn mmap(addr: *mut c_void, - len: size_t, - prot: c_int, - flags: c_int, - fd: c_int, - offset: off_t) - -> *mut c_void; - pub fn munmap(addr: *mut c_void, len: size_t) -> c_int; - - } - } - - pub mod net { - use types::os::arch::c95::{c_char, c_uint}; - - extern { - pub fn if_nametoindex(ifname: *const c_char) -> c_uint; - } - } - - } - - #[cfg(any(target_os = "linux", - target_os = "android", - target_os = "macos", - target_os = "ios", - target_os = "freebsd", - target_os = "dragonfly", - target_os = "bitrig", - target_os = "netbsd", - target_os = "openbsd", - target_os = "nacl"))] - pub mod posix01 { - pub mod stat_ { - use types::os::arch::c95::{c_char, c_int}; - use types::os::arch::posix01::stat; - - extern { - #[cfg_attr(target_os = "macos", link_name = "lstat64")] - #[cfg_attr(target_os = "netbsd", link_name = "__lstat50")] - pub fn lstat(path: *const c_char, buf: *mut stat) -> c_int; - } - } - - pub mod unistd { - use types::os::arch::c95::{c_char, c_int, size_t}; - use types::os::arch::posix88::{ssize_t, off_t}; - - extern { - pub fn readlink(path: *const c_char, buf: *mut c_char, bufsz: size_t) -> ssize_t; - - pub fn fsync(fd: c_int) -> c_int; - - #[cfg(any(target_os = "linux", target_os = "android"))] - pub fn fdatasync(fd: c_int) -> c_int; - - pub fn setenv(name: *const c_char, val: *const c_char, overwrite: c_int) -> c_int; - #[cfg_attr(target_os = "netbsd", link_name = "__unsetenv13")] - pub fn unsetenv(name: *const c_char) -> c_int; - #[cfg_attr(target_os = "netbsd", link_name = "__putenv50")] - pub fn putenv(string: *mut c_char) -> c_int; - - pub fn symlink(path1: *const c_char, path2: *const c_char) -> c_int; - - pub fn ftruncate(fd: c_int, length: off_t) -> c_int; - } - } - - pub mod signal { - use types::os::arch::c95::c_int; - use types::os::common::posix01::sighandler_t; - - #[cfg(not(all(target_os = "android", any(target_arch = "arm", - target_arch = "x86"))))] - extern { - pub fn signal(signum: c_int, handler: sighandler_t) -> sighandler_t; - } - - #[cfg(all(target_os = "android", any(target_arch = "arm", - target_arch = "x86")))] - extern { - #[link_name = "bsd_signal"] - pub fn signal(signum: c_int, handler: sighandler_t) -> sighandler_t; - } - } - - pub mod glob { - use types::os::arch::c95::{c_char, c_int}; - use types::os::common::posix01::glob_t; - - extern { - #[cfg_attr(target_os = "netbsd", link_name = "__glob30")] - pub fn glob(pattern: *const c_char, - flags: c_int, - errfunc: ::core::option::Option c_int>, - pglob: *mut glob_t); - #[cfg_attr(target_os = "netbsd", link_name = "__globfree30")] - pub fn globfree(pglob: *mut glob_t); - } - } - - pub mod mman { - use types::common::c95::c_void; - use types::os::arch::c95::{c_int, size_t}; - - #[cfg(not(target_os = "nacl"))] - extern { - pub fn posix_madvise(addr: *mut c_void, len: size_t, advice: c_int) -> c_int; - } - } - - pub mod resource { - use types::os::arch::c95::c_int; - use types::os::common::posix01::rlimit; - use types::os::common::bsd43::rusage; - extern { - pub fn getrlimit(resource: c_int, rlim: *mut rlimit) -> c_int; - pub fn setrlimit(resource: c_int, rlim: *const rlimit) -> c_int; - #[cfg_attr(target_os = "netbsd", link_name = "__getrusage50")] - pub fn getrusage(resource: c_int, usage: *mut rusage) -> c_int; - } - } - } - - #[cfg(target_os = "windows")] - pub mod posix01 { - pub mod stat_ { - } - - pub mod unistd { - } - - pub mod glob { - } - - pub mod mman { - } - - pub mod net { - } - } - - - #[cfg(any(target_os = "android", - target_os = "bitrig", - target_os = "dragonfly", - target_os = "ios", - target_os = "freebsd", - target_os = "linux", - target_os = "macos", - target_os = "nacl", - target_os = "netbsd", - target_os = "openbsd", - target_os = "windows"))] - pub mod posix08 { - pub mod unistd { - } - } - - #[cfg(not(windows))] - pub mod bsd43 { - use types::common::c95::c_void; - use types::os::common::bsd44::{socklen_t, sockaddr, ifaddrs}; - use types::os::arch::c95::{c_int, size_t}; - use types::os::arch::posix88::ssize_t; - - extern "system" { - #[cfg_attr(target_os = "netbsd", link_name = "__socket30")] - pub fn socket(domain: c_int, ty: c_int, protocol: c_int) -> c_int; - - pub fn connect(socket: c_int, address: *const sockaddr, len: socklen_t) -> c_int; - pub fn bind(socket: c_int, address: *const sockaddr, address_len: socklen_t) -> c_int; - pub fn listen(socket: c_int, backlog: c_int) -> c_int; - pub fn accept(socket: c_int, - address: *mut sockaddr, - address_len: *mut socklen_t) - -> c_int; - pub fn getpeername(socket: c_int, - address: *mut sockaddr, - address_len: *mut socklen_t) - -> c_int; - pub fn getsockname(socket: c_int, - address: *mut sockaddr, - address_len: *mut socklen_t) - -> c_int; - pub fn setsockopt(socket: c_int, - level: c_int, - name: c_int, - value: *const c_void, - option_len: socklen_t) - -> c_int; - pub fn recv(socket: c_int, buf: *mut c_void, len: size_t, flags: c_int) -> ssize_t; - pub fn send(socket: c_int, buf: *const c_void, len: size_t, flags: c_int) -> ssize_t; - pub fn recvfrom(socket: c_int, - buf: *mut c_void, - len: size_t, - flags: c_int, - addr: *mut sockaddr, - addrlen: *mut socklen_t) - -> ssize_t; - pub fn sendto(socket: c_int, - buf: *const c_void, - len: size_t, - flags: c_int, - addr: *const sockaddr, - addrlen: socklen_t) - -> ssize_t; - pub fn getifaddrs(ifap: *mut *mut ifaddrs) -> c_int; - pub fn freeifaddrs(ifa: *mut ifaddrs); - pub fn shutdown(socket: c_int, how: c_int) -> c_int; - } - } - - #[cfg(windows)] - pub mod bsd43 { - use types::common::c95::c_void; - use types::os::common::bsd44::{socklen_t, sockaddr, SOCKET}; - use types::os::arch::c95::c_int; - - extern "system" { - pub fn socket(domain: c_int, ty: c_int, protocol: c_int) -> SOCKET; - pub fn connect(socket: SOCKET, address: *const sockaddr, len: socklen_t) -> c_int; - pub fn bind(socket: SOCKET, address: *const sockaddr, address_len: socklen_t) -> c_int; - pub fn listen(socket: SOCKET, backlog: c_int) -> c_int; - pub fn accept(socket: SOCKET, - address: *mut sockaddr, - address_len: *mut socklen_t) - -> SOCKET; - pub fn getpeername(socket: SOCKET, - address: *mut sockaddr, - address_len: *mut socklen_t) - -> c_int; - pub fn getsockname(socket: SOCKET, - address: *mut sockaddr, - address_len: *mut socklen_t) - -> c_int; - pub fn setsockopt(socket: SOCKET, - level: c_int, - name: c_int, - value: *const c_void, - option_len: socklen_t) - -> c_int; - pub fn closesocket(socket: SOCKET) -> c_int; - pub fn recv(socket: SOCKET, buf: *mut c_void, len: c_int, flags: c_int) -> c_int; - pub fn send(socket: SOCKET, buf: *const c_void, len: c_int, flags: c_int) -> c_int; - pub fn recvfrom(socket: SOCKET, - buf: *mut c_void, - len: c_int, - flags: c_int, - addr: *mut sockaddr, - addrlen: *mut c_int) - -> c_int; - pub fn sendto(socket: SOCKET, - buf: *const c_void, - len: c_int, - flags: c_int, - addr: *const sockaddr, - addrlen: c_int) - -> c_int; - pub fn shutdown(socket: SOCKET, how: c_int) -> c_int; - } - } - - #[cfg(any(target_os = "macos", - target_os = "ios", - target_os = "freebsd", - target_os = "dragonfly", - target_os = "bitrig", - target_os = "netbsd", - target_os = "openbsd"))] - pub mod bsd44 { - use types::common::c95::c_void; - use types::os::arch::c95::{c_char, c_uchar, c_int, c_uint, c_ulong, size_t}; - - extern { - pub fn ioctl(fd: c_int, request: c_ulong, ...) -> c_int; - pub fn sysctl(name: *mut c_int, - namelen: c_uint, - oldp: *mut c_void, - oldlenp: *mut size_t, - newp: *mut c_void, - newlen: size_t) - -> c_int; - pub fn sysctlbyname(name: *const c_char, - oldp: *mut c_void, - oldlenp: *mut size_t, - newp: *mut c_void, - newlen: size_t) - -> c_int; - pub fn sysctlnametomib(name: *const c_char, - mibp: *mut c_int, - sizep: *mut size_t) - -> c_int; - pub fn getdtablesize() -> c_int; - pub fn madvise(addr: *mut c_void, len: size_t, advice: c_int) -> c_int; - pub fn mincore(addr: *mut c_void, len: size_t, vec: *mut c_uchar) -> c_int; - pub fn realpath(pathname: *const c_char, resolved: *mut c_char) -> *mut c_char; - pub fn flock(fd: c_int, operation: c_int) -> c_int; - } - } - - #[cfg(any(target_os = "linux", target_os = "android"))] - pub mod bsd44 { - use types::common::c95::c_void; - use types::os::arch::c95::{c_uchar, c_int, size_t}; - #[cfg(not(feature = "cargo-build"))] - use types::os::arch::c95::c_ulong; - - extern { - #[cfg(not(all(target_os = "android", target_arch = "aarch64")))] - pub fn getdtablesize() -> c_int; - - // Note that the correct signature of ioctl broke some crates on - // crates.io, so for now we keep the broken signature for crates.io - // but we fix it locally in the main Rust distribution. Once a new - // major version of libc is released on crates.io this #[cfg] should - // go away. - #[cfg(feature = "cargo-build")] - pub fn ioctl(fd: c_int, request: c_int, ...) -> c_int; - #[cfg(not(feature = "cargo-build"))] - pub fn ioctl(fd: c_int, request: c_ulong, ...) -> c_int; - pub fn madvise(addr: *mut c_void, len: size_t, advice: c_int) -> c_int; - pub fn mincore(addr: *mut c_void, len: size_t, vec: *mut c_uchar) -> c_int; - pub fn flock(fd: c_int, operation: c_int) -> c_int; - } - } - - #[cfg(target_os = "nacl")] - pub mod bsd44 { - use types::os::arch::c95::c_int; - extern { - pub fn getdtablesize() -> c_int; - } - } - - #[cfg(target_os = "windows")] - pub mod bsd44 { - } - - #[cfg(any(target_os = "macos", target_os = "ios"))] - pub mod extra { - use types::os::arch::c95::{c_char, c_int}; - - extern { - pub fn _NSGetExecutablePath(buf: *mut c_char, bufsize: *mut u32) -> c_int; - } - } - - #[cfg(any(target_os = "freebsd", - target_os = "dragonfly", - target_os = "bitrig", - target_os = "netbsd", - target_os = "openbsd"))] - pub mod extra { - } - - #[cfg(any(target_os = "linux", target_os = "android", target_os = "nacl"))] - pub mod extra { - } - - - #[cfg(target_os = "windows")] - pub mod extra { - - pub mod kernel32 { - use types::os::arch::c95::c_uint; - use types::os::arch::extra::{BOOL, DWORD, SIZE_T, HMODULE, LPCWSTR, LPWSTR, LPWCH, - LPDWORD, LPVOID, LPCVOID, LPOVERLAPPED, - LPSECURITY_ATTRIBUTES, LPSTARTUPINFO, - LPPROCESS_INFORMATION, LPMEMORY_BASIC_INFORMATION, - LPSYSTEM_INFO, HANDLE, LPHANDLE, LARGE_INTEGER, - PLARGE_INTEGER, LPFILETIME, LPWIN32_FIND_DATAW}; - - extern "system" { - pub fn GetEnvironmentVariableW(n: LPCWSTR, v: LPWSTR, nsize: DWORD) -> DWORD; - pub fn SetEnvironmentVariableW(n: LPCWSTR, v: LPCWSTR) -> BOOL; - pub fn GetEnvironmentStringsW() -> LPWCH; - pub fn FreeEnvironmentStringsW(env_ptr: LPWCH) -> BOOL; - pub fn GetModuleFileNameW(hModule: HMODULE, - lpFilename: LPWSTR, - nSize: DWORD) - -> DWORD; - pub fn CreateDirectoryW(lpPathName: LPCWSTR, - lpSecurityAttributes: LPSECURITY_ATTRIBUTES) - -> BOOL; - pub fn CopyFileW(lpExistingFileName: LPCWSTR, - lpNewFileName: LPCWSTR, - bFailIfExists: BOOL) - -> BOOL; - pub fn DeleteFileW(lpPathName: LPCWSTR) -> BOOL; - pub fn RemoveDirectoryW(lpPathName: LPCWSTR) -> BOOL; - pub fn GetCurrentDirectoryW(nBufferLength: DWORD, lpBuffer: LPWSTR) -> DWORD; - pub fn SetCurrentDirectoryW(lpPathName: LPCWSTR) -> BOOL; - pub fn GetLastError() -> DWORD; - pub fn FindFirstFileW(fileName: LPCWSTR, - findFileData: LPWIN32_FIND_DATAW) - -> HANDLE; - pub fn FindNextFileW(findFile: HANDLE, findFileData: LPWIN32_FIND_DATAW) -> BOOL; - pub fn FindClose(findFile: HANDLE) -> BOOL; - pub fn DuplicateHandle(hSourceProcessHandle: HANDLE, - hSourceHandle: HANDLE, - hTargetProcessHandle: HANDLE, - lpTargetHandle: LPHANDLE, - dwDesiredAccess: DWORD, - bInheritHandle: BOOL, - dwOptions: DWORD) - -> BOOL; - pub fn CloseHandle(hObject: HANDLE) -> BOOL; - pub fn OpenProcess(dwDesiredAccess: DWORD, - bInheritHandle: BOOL, - dwProcessId: DWORD) - -> HANDLE; - pub fn GetCurrentProcess() -> HANDLE; - pub fn CreateProcessW(lpApplicationName: LPCWSTR, - lpCommandLine: LPWSTR, - lpProcessAttributes: LPSECURITY_ATTRIBUTES, - lpThreadAttributes: LPSECURITY_ATTRIBUTES, - bInheritHandles: BOOL, - dwCreationFlags: DWORD, - lpEnvironment: LPVOID, - lpCurrentDirectory: LPCWSTR, - lpStartupInfo: LPSTARTUPINFO, - lpProcessInformation: LPPROCESS_INFORMATION) - -> BOOL; - pub fn WaitForSingleObject(hHandle: HANDLE, dwMilliseconds: DWORD) -> DWORD; - pub fn TerminateProcess(hProcess: HANDLE, uExitCode: c_uint) -> BOOL; - pub fn GetExitCodeProcess(hProcess: HANDLE, lpExitCode: LPDWORD) -> BOOL; - pub fn GetSystemInfo(lpSystemInfo: LPSYSTEM_INFO); - pub fn VirtualAlloc(lpAddress: LPVOID, - dwSize: SIZE_T, - flAllocationType: DWORD, - flProtect: DWORD) - -> LPVOID; - pub fn VirtualFree(lpAddress: LPVOID, dwSize: SIZE_T, dwFreeType: DWORD) -> BOOL; - pub fn VirtualLock(lpAddress: LPVOID, dwSize: SIZE_T) -> BOOL; - pub fn VirtualUnlock(lpAddress: LPVOID, dwSize: SIZE_T) -> BOOL; - pub fn VirtualProtect(lpAddress: LPVOID, - dwSize: SIZE_T, - flNewProtect: DWORD, - lpflOldProtect: LPDWORD) - -> BOOL; - pub fn VirtualQuery(lpAddress: LPCVOID, - lpBuffer: LPMEMORY_BASIC_INFORMATION, - dwLength: SIZE_T) - -> SIZE_T; - pub fn CreateFileMappingW(hFile: HANDLE, - lpAttributes: LPSECURITY_ATTRIBUTES, - flProtect: DWORD, - dwMaximumSizeHigh: DWORD, - dwMaximumSizeLow: DWORD, - lpName: LPCWSTR) - -> HANDLE; - pub fn MapViewOfFile(hFileMappingObject: HANDLE, - dwDesiredAccess: DWORD, - dwFileOffsetHigh: DWORD, - dwFileOffsetLow: DWORD, - dwNumberOfBytesToMap: SIZE_T) - -> LPVOID; - pub fn UnmapViewOfFile(lpBaseAddress: LPCVOID) -> BOOL; - pub fn MoveFileExW(lpExistingFileName: LPCWSTR, - lpNewFileName: LPCWSTR, - dwFlags: DWORD) - -> BOOL; - pub fn CreateHardLinkW(lpSymlinkFileName: LPCWSTR, - lpTargetFileName: LPCWSTR, - lpSecurityAttributes: LPSECURITY_ATTRIBUTES) - -> BOOL; - pub fn FlushFileBuffers(hFile: HANDLE) -> BOOL; - pub fn CreateFileW(lpFileName: LPCWSTR, - dwDesiredAccess: DWORD, - dwShareMode: DWORD, - lpSecurityAttributes: LPSECURITY_ATTRIBUTES, - dwCreationDisposition: DWORD, - dwFlagsAndAttributes: DWORD, - hTemplateFile: HANDLE) - -> HANDLE; - pub fn ReadFile(hFile: HANDLE, - lpBuffer: LPVOID, - nNumberOfBytesToRead: DWORD, - lpNumberOfBytesRead: LPDWORD, - lpOverlapped: LPOVERLAPPED) - -> BOOL; - pub fn WriteFile(hFile: HANDLE, - lpBuffer: LPVOID, - nNumberOfBytesToWrite: DWORD, - lpNumberOfBytesWritten: LPDWORD, - lpOverlapped: LPOVERLAPPED) - -> BOOL; - pub fn SetFilePointerEx(hFile: HANDLE, - liDistanceToMove: LARGE_INTEGER, - lpNewFilePointer: PLARGE_INTEGER, - dwMoveMethod: DWORD) - -> BOOL; - pub fn SetEndOfFile(hFile: HANDLE) -> BOOL; - - pub fn GetSystemTimeAsFileTime(lpSystemTimeAsFileTime: LPFILETIME); - - pub fn QueryPerformanceFrequency(lpFrequency: *mut LARGE_INTEGER) -> BOOL; - pub fn QueryPerformanceCounter(lpPerformanceCount: *mut LARGE_INTEGER) -> BOOL; - - pub fn GetCurrentProcessId() -> DWORD; - pub fn CreateNamedPipeW(lpName: LPCWSTR, - dwOpenMode: DWORD, - dwPipeMode: DWORD, - nMaxInstances: DWORD, - nOutBufferSize: DWORD, - nInBufferSize: DWORD, - nDefaultTimeOut: DWORD, - lpSecurityAttributes: LPSECURITY_ATTRIBUTES) - -> HANDLE; - pub fn ConnectNamedPipe(hNamedPipe: HANDLE, lpOverlapped: LPOVERLAPPED) -> BOOL; - pub fn WaitNamedPipeW(lpNamedPipeName: LPCWSTR, nTimeOut: DWORD) -> BOOL; - pub fn SetNamedPipeHandleState(hNamedPipe: HANDLE, - lpMode: LPDWORD, - lpMaxCollectionCount: LPDWORD, - lpCollectDataTimeout: LPDWORD) - -> BOOL; - pub fn CreateEventW(lpEventAttributes: LPSECURITY_ATTRIBUTES, - bManualReset: BOOL, - bInitialState: BOOL, - lpName: LPCWSTR) - -> HANDLE; - pub fn GetOverlappedResult(hFile: HANDLE, - lpOverlapped: LPOVERLAPPED, - lpNumberOfBytesTransferred: LPDWORD, - bWait: BOOL) - -> BOOL; - pub fn DisconnectNamedPipe(hNamedPipe: HANDLE) -> BOOL; - } - } - - pub mod msvcrt { - use types::os::arch::c95::{c_int, c_long}; - use types::os::arch::c99::intptr_t; - - extern { - #[link_name = "_commit"] - pub fn commit(fd: c_int) -> c_int; - - #[link_name = "_get_osfhandle"] - pub fn get_osfhandle(fd: c_int) -> c_long; - - #[link_name = "_open_osfhandle"] - pub fn open_osfhandle(osfhandle: intptr_t, flags: c_int) -> c_int; - } - } - - pub mod winsock { - use types::os::arch::c95::{c_int, c_long, c_ulong}; - use types::os::common::bsd44::SOCKET; - - extern "system" { - pub fn ioctlsocket(s: SOCKET, cmd: c_long, argp: *mut c_ulong) -> c_int; - } - } - } -} - -#[test] -fn work_on_windows() { -} // FIXME #10872 needed for a happy windows diff --git a/src/liblog/lib.rs b/src/liblog/lib.rs index 9cb835bd8525d..1de7ebfffdea2 100644 --- a/src/liblog/lib.rs +++ b/src/liblog/lib.rs @@ -13,6 +13,7 @@ //! # Examples //! //! ``` +//! # #![feature(rustc_private)] //! #[macro_use] extern crate log; //! //! fn main() { @@ -167,7 +168,8 @@ #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "https://doc.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/nightly/", - html_playground_url = "https://play.rust-lang.org/")] + html_playground_url = "https://play.rust-lang.org/", + test(attr(deny(warnings))))] #![deny(missing_docs)] #![feature(box_syntax)] diff --git a/src/liblog/macros.rs b/src/liblog/macros.rs index 46b51f50c8583..803a2df9ccc8b 100644 --- a/src/liblog/macros.rs +++ b/src/liblog/macros.rs @@ -19,6 +19,7 @@ /// # Examples /// /// ``` +/// # #![feature(rustc_private)] /// #[macro_use] extern crate log; /// /// fn main() { @@ -67,6 +68,7 @@ macro_rules! log { /// # Examples /// /// ``` +/// # #![feature(rustc_private)] /// #[macro_use] extern crate log; /// /// fn main() { @@ -92,6 +94,7 @@ macro_rules! error { /// # Examples /// /// ``` +/// # #![feature(rustc_private)] /// #[macro_use] extern crate log; /// /// fn main() { @@ -116,6 +119,7 @@ macro_rules! warn { /// # Examples /// /// ``` +/// # #![feature(rustc_private)] /// #[macro_use] extern crate log; /// /// fn main() { @@ -142,6 +146,7 @@ macro_rules! info { /// # Examples /// /// ``` +/// # #![feature(rustc_private)] /// #[macro_use] extern crate log; /// /// fn main() { @@ -165,9 +170,10 @@ macro_rules! debug { /// # Examples /// /// ``` +/// # #![feature(rustc_private)] /// #[macro_use] extern crate log; /// -/// struct Point { x: int, y: int } +/// struct Point { x: i32, y: i32 } /// fn some_expensive_computation() -> Point { Point { x: 1, y: 2 } } /// /// fn main() { diff --git a/src/librand/lib.rs b/src/librand/lib.rs index b5a1eb9520cec..cf2118b45a471 100644 --- a/src/librand/lib.rs +++ b/src/librand/lib.rs @@ -23,7 +23,8 @@ #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk.png", html_favicon_url = "https://doc.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/nightly/", - html_playground_url = "https://play.rust-lang.org/")] + html_playground_url = "https://play.rust-lang.org/", + test(attr(deny(warnings))))] #![no_std] #![staged_api] #![unstable(feature = "rand", diff --git a/src/librand/reseeding.rs b/src/librand/reseeding.rs index 584cf78a1cdbf..8ef94eb16f25d 100644 --- a/src/librand/reseeding.rs +++ b/src/librand/reseeding.rs @@ -113,7 +113,6 @@ impl Reseeder for ReseedWithDefault { } #[stable(feature = "rust1", since = "1.0.0")] impl Default for ReseedWithDefault { - #[stable(feature = "rust1", since = "1.0.0")] fn default() -> ReseedWithDefault { ReseedWithDefault } diff --git a/src/librbml/lib.rs b/src/librbml/lib.rs index 1c6cb06d54ae4..a1b15cd9e6f11 100644 --- a/src/librbml/lib.rs +++ b/src/librbml/lib.rs @@ -121,7 +121,8 @@ #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "https://doc.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/nightly/", - html_playground_url = "https://play.rust-lang.org/")] + html_playground_url = "https://play.rust-lang.org/", + test(attr(deny(warnings))))] #![feature(rustc_private)] #![feature(staged_api)] diff --git a/src/librustc/front/map/mod.rs b/src/librustc/front/map/mod.rs index 94800db184e98..11f0fd1bb2c5e 100644 --- a/src/librustc/front/map/mod.rs +++ b/src/librustc/front/map/mod.rs @@ -847,14 +847,14 @@ pub fn map_decoded_item<'ast, F: FoldOps>(map: &Map<'ast>, -> &'ast InlinedItem { let mut fld = IdAndSpanUpdater { fold_ops: fold_ops }; let ii = match ii { - II::Item(i) => II::Item(fld.fold_item(i).expect_one("expected one item")), + II::Item(i) => II::Item(fld.fold_item(i)), II::TraitItem(d, ti) => { II::TraitItem(fld.fold_ops.new_def_id(d), - fld.fold_trait_item(ti).expect_one("expected one trait item")) + fld.fold_trait_item(ti)) } II::ImplItem(d, ii) => { II::ImplItem(fld.fold_ops.new_def_id(d), - fld.fold_impl_item(ii).expect_one("expected one impl item")) + fld.fold_impl_item(ii)) } II::Foreign(i) => II::Foreign(fld.fold_foreign_item(i)) }; diff --git a/src/librustc/metadata/csearch.rs b/src/librustc/metadata/csearch.rs index e04df51dc6862..09dec375a69a5 100644 --- a/src/librustc/metadata/csearch.rs +++ b/src/librustc/metadata/csearch.rs @@ -344,6 +344,11 @@ pub fn is_const_fn(cstore: &cstore::CStore, did: DefId) -> bool { decoder::is_const_fn(&*cdata, did.index) } +pub fn is_static(cstore: &cstore::CStore, did: DefId) -> bool { + let cdata = cstore.get_crate_data(did.krate); + decoder::is_static(&*cdata, did.index) +} + pub fn is_impl(cstore: &cstore::CStore, did: DefId) -> bool { let cdata = cstore.get_crate_data(did.krate); decoder::is_impl(&*cdata, did.index) diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index 0780252fc887b..b102213eff021 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -1425,6 +1425,14 @@ pub fn is_const_fn(cdata: Cmd, id: DefIndex) -> bool { } } +pub fn is_static(cdata: Cmd, id: DefIndex) -> bool { + let item_doc = cdata.lookup_item(id); + match item_family(item_doc) { + ImmStatic | MutStatic => true, + _ => false, + } +} + pub fn is_impl(cdata: Cmd, id: DefIndex) -> bool { let item_doc = cdata.lookup_item(id); match item_family(item_doc) { diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index 8e2c2e6a0bfbd..1cd196895e3a4 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -1500,7 +1500,7 @@ fn encode_info_for_items<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>, &[], CRATE_NODE_ID, [].iter().cloned().chain(LinkedPath::empty()), - syntax::parse::token::special_idents::invalid.name, + syntax::parse::token::intern(&ecx.link_meta.crate_name), hir::Public); visit::walk_crate(&mut EncodeVisitor { diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs index e81445f19ede6..a92fe1a0f2b5b 100644 --- a/src/librustc/middle/astencode.rs +++ b/src/librustc/middle/astencode.rs @@ -389,20 +389,13 @@ fn simplify_ast(ii: InlinedItemRef) -> InlinedItem { match ii { // HACK we're not dropping items. InlinedItemRef::Item(i) => { - InlinedItem::Item(fold::noop_fold_item(P(i.clone()), &mut fld) - .expect_one("expected one item")) + InlinedItem::Item(fold::noop_fold_item(P(i.clone()), &mut fld)) } InlinedItemRef::TraitItem(d, ti) => { - InlinedItem::TraitItem(d, - fold::noop_fold_trait_item(P(ti.clone()), &mut fld) - .expect_one("noop_fold_trait_item must produce \ - exactly one trait item")) + InlinedItem::TraitItem(d, fold::noop_fold_trait_item(P(ti.clone()), &mut fld)) } InlinedItemRef::ImplItem(d, ii) => { - InlinedItem::ImplItem(d, - fold::noop_fold_impl_item(P(ii.clone()), &mut fld) - .expect_one("noop_fold_impl_item must produce \ - exactly one impl item")) + InlinedItem::ImplItem(d, fold::noop_fold_impl_item(P(ii.clone()), &mut fld)) } InlinedItemRef::Foreign(i) => { InlinedItem::Foreign(fold::noop_fold_foreign_item(P(i.clone()), &mut fld)) diff --git a/src/librustc/middle/cfg/construct.rs b/src/librustc/middle/cfg/construct.rs index 9f83cb9fddea4..5b931857decca 100644 --- a/src/librustc/middle/cfg/construct.rs +++ b/src/librustc/middle/cfg/construct.rs @@ -472,7 +472,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { let guard_exit = self.expr(&**guard, guard_start); let this_has_bindings = pat_util::pat_contains_bindings_or_wild( - &self.tcx.def_map, &**pat); + &self.tcx.def_map.borrow(), &**pat); // If both this pattern and the previous pattern // were free of bindings, they must consist only diff --git a/src/librustc/middle/check_const.rs b/src/librustc/middle/check_const.rs index 76fa54317fc11..a3eeb12da0114 100644 --- a/src/librustc/middle/check_const.rs +++ b/src/librustc/middle/check_const.rs @@ -225,7 +225,7 @@ impl<'a, 'tcx> CheckCrateVisitor<'a, 'tcx> { { self.tcx.sess.span_err( expr.span, - &format!("const fns are an unstable feature")); + "const fns are an unstable feature"); fileline_help!( self.tcx.sess, expr.span, diff --git a/src/librustc/middle/check_match.rs b/src/librustc/middle/check_match.rs index fce96457d174b..f46e55e244140 100644 --- a/src/librustc/middle/check_match.rs +++ b/src/librustc/middle/check_match.rs @@ -702,7 +702,7 @@ fn is_useful(cx: &MatchCheckCtxt, Some(constructor) => { let matrix = rows.iter().filter_map(|r| { - if pat_is_binding_or_wild(&cx.tcx.def_map, raw_pat(r[0])) { + if pat_is_binding_or_wild(&cx.tcx.def_map.borrow(), raw_pat(r[0])) { Some(r[1..].to_vec()) } else { None @@ -1073,7 +1073,7 @@ fn check_legality_of_move_bindings(cx: &MatchCheckCtxt, // check legality of moving out of the enum // x @ Foo(..) is legal, but x @ Foo(y) isn't. - if sub.map_or(false, |p| pat_contains_bindings(def_map, &*p)) { + if sub.map_or(false, |p| pat_contains_bindings(&def_map.borrow(), &*p)) { span_err!(cx.tcx.sess, p.span, E0007, "cannot bind by-move with sub-bindings"); } else if has_guard { span_err!(cx.tcx.sess, p.span, E0008, "cannot bind by-move into a pattern guard"); @@ -1086,7 +1086,7 @@ fn check_legality_of_move_bindings(cx: &MatchCheckCtxt, for pat in pats { front_util::walk_pat(&**pat, |p| { - if pat_is_binding(def_map, &*p) { + if pat_is_binding(&def_map.borrow(), &*p) { match p.node { hir::PatIdent(hir::BindByValue(_), _, ref sub) => { let pat_ty = tcx.node_id_to_type(p.id); @@ -1181,7 +1181,7 @@ struct AtBindingPatternVisitor<'a, 'b:'a, 'tcx:'b> { impl<'a, 'b, 'tcx, 'v> Visitor<'v> for AtBindingPatternVisitor<'a, 'b, 'tcx> { fn visit_pat(&mut self, pat: &Pat) { - if !self.bindings_allowed && pat_is_binding(&self.cx.tcx.def_map, pat) { + if !self.bindings_allowed && pat_is_binding(&self.cx.tcx.def_map.borrow(), pat) { span_err!(self.cx.tcx.sess, pat.span, E0303, "pattern bindings are not allowed \ after an `@`"); diff --git a/src/librustc/middle/check_static_recursion.rs b/src/librustc/middle/check_static_recursion.rs index 45671367a5c3c..dd49010c43672 100644 --- a/src/librustc/middle/check_static_recursion.rs +++ b/src/librustc/middle/check_static_recursion.rs @@ -237,7 +237,7 @@ impl<'a, 'ast: 'a> Visitor<'ast> for CheckItemRecursionVisitor<'a, 'ast> { fn visit_expr(&mut self, e: &'ast hir::Expr) { match e.node { hir::ExprPath(..) => { - match self.def_map.borrow().get(&e.id).map(|d| d.base_def) { + match self.def_map.get(&e.id).map(|d| d.base_def) { Some(DefStatic(def_id, _)) | Some(DefAssociatedConst(def_id)) | Some(DefConst(def_id)) => { diff --git a/src/librustc/middle/const_eval.rs b/src/librustc/middle/const_eval.rs index 1651e71c49a2a..34d002d334277 100644 --- a/src/librustc/middle/const_eval.rs +++ b/src/librustc/middle/const_eval.rs @@ -39,6 +39,7 @@ use std::borrow::{Cow, IntoCow}; use std::num::wrapping::OverflowingOps; use std::cmp::Ordering; use std::collections::hash_map::Entry::Vacant; +use std::hash; use std::mem::transmute; use std::{i8, i16, i32, i64, u8, u16, u32, u64}; use std::rc::Rc; @@ -257,6 +258,22 @@ pub enum ConstVal { Function(DefId), } +impl hash::Hash for ConstVal { + fn hash(&self, state: &mut H) { + match *self { + Float(a) => unsafe { transmute::<_,u64>(a) }.hash(state), + Int(a) => a.hash(state), + Uint(a) => a.hash(state), + Str(ref a) => a.hash(state), + ByteStr(ref a) => a.hash(state), + Bool(a) => a.hash(state), + Struct(a) => a.hash(state), + Tuple(a) => a.hash(state), + Function(a) => a.hash(state), + } + } +} + /// Note that equality for `ConstVal` means that the it is the same /// constant, not that the rust values are equal. In particular, `NaN /// == NaN` (at least if it's the same NaN; distinct encodings for NaN @@ -278,6 +295,8 @@ impl PartialEq for ConstVal { } } +impl Eq for ConstVal { } + impl ConstVal { pub fn description(&self) -> &'static str { match *self { @@ -1213,7 +1232,7 @@ fn resolve_trait_associated_const<'a, 'tcx: 'a>(tcx: &'a ty::ctxt<'tcx>, _ => { tcx.sess.span_bug( ti.span, - &format!("resolve_trait_associated_const: unexpected vtable type")) + "resolve_trait_associated_const: unexpected vtable type") } } } diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs index 1a1a9d4b1b48f..fff080a70e622 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc/middle/dead.rs @@ -250,7 +250,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for MarkSymbolVisitor<'a, 'tcx> { fn visit_arm(&mut self, arm: &hir::Arm) { if arm.pats.len() == 1 { let pat = &*arm.pats[0]; - let variants = pat_util::necessary_variants(&self.tcx.def_map, pat); + let variants = pat_util::necessary_variants(&self.tcx.def_map.borrow(), pat); // Inside the body, ignore constructions of variants // necessary for the pattern to match. Those construction sites @@ -270,7 +270,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for MarkSymbolVisitor<'a, 'tcx> { hir::PatStruct(_, ref fields, _) => { self.handle_field_pattern_match(pat, fields); } - _ if pat_util::pat_is_const(def_map, pat) => { + _ if pat_util::pat_is_const(&def_map.borrow(), pat) => { // it might be the only use of a const self.lookup_and_handle_definition(&pat.id) } @@ -539,19 +539,18 @@ impl<'a, 'tcx, 'v> Visitor<'v> for DeadVisitor<'a, 'tcx> { item.node.descriptive_variant() ); } else { - match item.node { - hir::ItemEnum(ref enum_def, _) => { - for variant in &enum_def.variants { - if self.should_warn_about_variant(&variant.node) { - self.warn_dead_code(variant.node.data.id(), variant.span, - variant.node.name, "variant"); - } - } - }, - _ => () - } + // Only continue if we didn't warn + visit::walk_item(self, item); + } + } + + fn visit_variant(&mut self, variant: &hir::Variant, g: &hir::Generics, id: ast::NodeId) { + if self.should_warn_about_variant(&variant.node) { + self.warn_dead_code(variant.node.data.id(), variant.span, + variant.node.name, "variant"); + } else { + visit::walk_variant(self, variant, g, id); } - visit::walk_item(self, item); } fn visit_foreign_item(&mut self, fi: &hir::ForeignItem) { diff --git a/src/librustc/middle/def.rs b/src/librustc/middle/def.rs index ef2b918a9f5d7..b1d2418795753 100644 --- a/src/librustc/middle/def.rs +++ b/src/librustc/middle/def.rs @@ -17,8 +17,6 @@ use util::nodemap::NodeMap; use syntax::ast; use rustc_front::hir; -use std::cell::RefCell; - #[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub enum Def { DefFn(DefId, bool /* is_ctor */), @@ -103,7 +101,7 @@ impl PathResolution { } // Definition mapping -pub type DefMap = RefCell>; +pub type DefMap = NodeMap; // This is the replacement export map. It maps a module to all of the exports // within. pub type ExportMap = NodeMap>; diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index 6e469da33f98e..ce8d74bf191c7 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -934,7 +934,7 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> { return_if_err!(self.mc.cat_pattern(cmt_discr, pat, |_mc, cmt_pat, pat| { let tcx = self.tcx(); let def_map = &self.tcx().def_map; - if pat_util::pat_is_binding(def_map, pat) { + if pat_util::pat_is_binding(&def_map.borrow(), pat) { match pat.node { hir::PatIdent(hir::BindByRef(_), _, _) => mode.lub(BorrowingMatch), @@ -969,7 +969,7 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> { let def_map = &self.tcx().def_map; let delegate = &mut self.delegate; return_if_err!(mc.cat_pattern(cmt_discr.clone(), pat, |mc, cmt_pat, pat| { - if pat_util::pat_is_binding(def_map, pat) { + if pat_util::pat_is_binding(&def_map.borrow(), pat) { let tcx = typer.tcx; debug!("binding cmt_pat={:?} pat={:?} match_mode={:?}", diff --git a/src/librustc/middle/infer/error_reporting.rs b/src/librustc/middle/infer/error_reporting.rs index 0ab572c543b29..a16ef808bb6d3 100644 --- a/src/librustc/middle/infer/error_reporting.rs +++ b/src/librustc/middle/infer/error_reporting.rs @@ -1751,7 +1751,7 @@ impl<'a, 'tcx> ErrorReportingHelpers<'tcx> for InferCtxt<'a, 'tcx> { infer::ParameterInScope(_, span) => { self.tcx.sess.span_note( span, - &format!("...so that a type/lifetime parameter is in scope here")); + "...so that a type/lifetime parameter is in scope here"); } infer::DataBorrowed(ty, span) => { self.tcx.sess.span_note( diff --git a/src/librustc/middle/infer/mod.rs b/src/librustc/middle/infer/mod.rs index f80c486f237b1..684e60304eb4d 100644 --- a/src/librustc/middle/infer/mod.rs +++ b/src/librustc/middle/infer/mod.rs @@ -1130,7 +1130,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { match self.tables.borrow().node_types.get(&ex.id) { Some(&t) => t, None => { - self.tcx.sess.bug(&format!("no type for expr in fcx")); + self.tcx.sess.bug("no type for expr in fcx"); } } } diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index 3b56597d353a3..b25ad66fd1fa5 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -1555,7 +1555,11 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { // Ignore unused self. let name = path1.node; if name != special_idents::self_.name { - self.warn_about_unused(sp, p_id, entry_ln, var); + if !self.warn_about_unused(sp, p_id, entry_ln, var) { + if self.live_on_entry(entry_ln, var).is_none() { + self.report_dead_assign(p_id, sp, var, true); + } + } } }) } @@ -1609,11 +1613,19 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { ln: LiveNode, var: Variable) { if self.live_on_exit(ln, var).is_none() { - let r = self.should_warn(var); - if let Some(name) = r { + self.report_dead_assign(id, sp, var, false); + } + } + + fn report_dead_assign(&self, id: NodeId, sp: Span, var: Variable, is_argument: bool) { + if let Some(name) = self.should_warn(var) { + if is_argument { + self.ir.tcx.sess.add_lint(lint::builtin::UNUSED_ASSIGNMENTS, id, sp, + format!("value passed to `{}` is never read", name)); + } else { self.ir.tcx.sess.add_lint(lint::builtin::UNUSED_ASSIGNMENTS, id, sp, format!("value assigned to `{}` is never read", name)); } } } - } +} diff --git a/src/librustc/middle/pat_util.rs b/src/librustc/middle/pat_util.rs index c3555273850bc..e794ab39e5450 100644 --- a/src/librustc/middle/pat_util.rs +++ b/src/librustc/middle/pat_util.rs @@ -14,18 +14,21 @@ use middle::ty; use util::nodemap::FnvHashMap; use syntax::ast; +use syntax::ext::mtwt; use rustc_front::hir; use rustc_front::util::walk_pat; use syntax::codemap::{respan, Span, Spanned, DUMMY_SP}; +use std::cell::RefCell; + pub type PatIdMap = FnvHashMap; // This is used because same-named variables in alternative patterns need to // use the NodeId of their namesake in the first pattern. -pub fn pat_id_map(dm: &DefMap, pat: &hir::Pat) -> PatIdMap { +pub fn pat_id_map(dm: &RefCell, pat: &hir::Pat) -> PatIdMap { let mut map = FnvHashMap(); - pat_bindings(dm, pat, |_bm, p_id, _s, path1| { - map.insert(path1.node, p_id); + pat_bindings_hygienic(dm, pat, |_bm, p_id, _s, path1| { + map.insert(mtwt::resolve(path1.node), p_id); }); map } @@ -36,7 +39,7 @@ pub fn pat_is_refutable(dm: &DefMap, pat: &hir::Pat) -> bool { hir::PatEnum(_, _) | hir::PatIdent(_, _, None) | hir::PatStruct(..) => { - match dm.borrow().get(&pat.id).map(|d| d.full_def()) { + match dm.get(&pat.id).map(|d| d.full_def()) { Some(DefVariant(..)) => true, _ => false } @@ -51,7 +54,7 @@ pub fn pat_is_variant_or_struct(dm: &DefMap, pat: &hir::Pat) -> bool { hir::PatEnum(_, _) | hir::PatIdent(_, _, None) | hir::PatStruct(..) => { - match dm.borrow().get(&pat.id).map(|d| d.full_def()) { + match dm.get(&pat.id).map(|d| d.full_def()) { Some(DefVariant(..)) | Some(DefStruct(..)) => true, _ => false } @@ -63,7 +66,7 @@ pub fn pat_is_variant_or_struct(dm: &DefMap, pat: &hir::Pat) -> bool { pub fn pat_is_const(dm: &DefMap, pat: &hir::Pat) -> bool { match pat.node { hir::PatIdent(_, _, None) | hir::PatEnum(..) | hir::PatQPath(..) => { - match dm.borrow().get(&pat.id).map(|d| d.full_def()) { + match dm.get(&pat.id).map(|d| d.full_def()) { Some(DefConst(..)) | Some(DefAssociatedConst(..)) => true, _ => false } @@ -77,7 +80,7 @@ pub fn pat_is_const(dm: &DefMap, pat: &hir::Pat) -> bool { pub fn pat_is_resolved_const(dm: &DefMap, pat: &hir::Pat) -> bool { match pat.node { hir::PatIdent(_, _, None) | hir::PatEnum(..) | hir::PatQPath(..) => { - match dm.borrow().get(&pat.id) + match dm.get(&pat.id) .and_then(|d| if d.depth == 0 { Some(d.base_def) } else { None } ) { Some(DefConst(..)) | Some(DefAssociatedConst(..)) => true, @@ -108,12 +111,12 @@ pub fn pat_is_binding_or_wild(dm: &DefMap, pat: &hir::Pat) -> bool { /// Call `it` on every "binding" in a pattern, e.g., on `a` in /// `match foo() { Some(a) => (), None => () }` -pub fn pat_bindings(dm: &DefMap, pat: &hir::Pat, mut it: I) where +pub fn pat_bindings(dm: &RefCell, pat: &hir::Pat, mut it: I) where I: FnMut(hir::BindingMode, ast::NodeId, Span, &Spanned), { walk_pat(pat, |p| { match p.node { - hir::PatIdent(binding_mode, ref pth, _) if pat_is_binding(dm, p) => { + hir::PatIdent(binding_mode, ref pth, _) if pat_is_binding(&dm.borrow(), p) => { it(binding_mode, p.id, p.span, &respan(pth.span, pth.node.name)); } _ => {} @@ -122,12 +125,12 @@ pub fn pat_bindings(dm: &DefMap, pat: &hir::Pat, mut it: I) where }); } -pub fn pat_bindings_hygienic(dm: &DefMap, pat: &hir::Pat, mut it: I) where +pub fn pat_bindings_hygienic(dm: &RefCell, pat: &hir::Pat, mut it: I) where I: FnMut(hir::BindingMode, ast::NodeId, Span, &Spanned), { walk_pat(pat, |p| { match p.node { - hir::PatIdent(binding_mode, ref pth, _) if pat_is_binding(dm, p) => { + hir::PatIdent(binding_mode, ref pth, _) if pat_is_binding(&dm.borrow(), p) => { it(binding_mode, p.id, p.span, &respan(pth.span, pth.node)); } _ => {} @@ -153,7 +156,7 @@ pub fn pat_contains_bindings(dm: &DefMap, pat: &hir::Pat) -> bool { /// Checks if the pattern contains any `ref` or `ref mut` bindings, /// and if yes wether its containing mutable ones or just immutables ones. -pub fn pat_contains_ref_binding(dm: &DefMap, pat: &hir::Pat) -> Option { +pub fn pat_contains_ref_binding(dm: &RefCell, pat: &hir::Pat) -> Option { let mut result = None; pat_bindings(dm, pat, |mode, _, _, _| { match mode { @@ -172,7 +175,7 @@ pub fn pat_contains_ref_binding(dm: &DefMap, pat: &hir::Pat) -> Option Option { +pub fn arm_contains_ref_binding(dm: &RefCell, arm: &hir::Arm) -> Option { arm.pats.iter() .filter_map(|pat| pat_contains_ref_binding(dm, pat)) .max_by(|m| match *m { @@ -226,7 +229,7 @@ pub fn necessary_variants(dm: &DefMap, pat: &hir::Pat) -> Vec { hir::PatEnum(_, _) | hir::PatIdent(_, _, None) | hir::PatStruct(..) => { - match dm.borrow().get(&p.id) { + match dm.get(&p.id) { Some(&PathResolution { base_def: DefVariant(_, id, _), .. }) => { variants.push(id); } diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs index 97ab9c2dfb7f9..7175fbe0e570d 100644 --- a/src/librustc/middle/reachable.rs +++ b/src/librustc/middle/reachable.rs @@ -125,6 +125,9 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ReachableContext<'a, 'tcx> { hir::ExprMethodCall(..) => { let method_call = ty::MethodCall::expr(expr.id); let def_id = self.tcx.tables.borrow().method_map[&method_call].def_id; + + // Mark the trait item (and, possibly, its default impl) as reachable + // Or mark inherent impl item as reachable if let Some(node_id) = self.tcx.map.as_local_node_id(def_id) { if self.def_id_represents_local_inlined_item(def_id) { self.worklist.push(node_id) @@ -322,57 +325,69 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> { } } } +} - // Step 3: Mark all destructors as reachable. - // - // FIXME #10732: This is a conservative overapproximation, but fixing - // this properly would result in the necessity of computing *type* - // reachability, which might result in a compile time loss. - fn mark_destructors_reachable(&mut self) { - let drop_trait = match self.tcx.lang_items.drop_trait() { - Some(id) => self.tcx.lookup_trait_def(id), None => { return } - }; - drop_trait.for_each_impl(self.tcx, |drop_impl| { - for destructor in &self.tcx.impl_items.borrow()[&drop_impl] { - let destructor_did = destructor.def_id(); - if let Some(destructor_node_id) = self.tcx.map.as_local_node_id(destructor_did) { - self.reachable_symbols.insert(destructor_node_id); +// Some methods from non-exported (completely private) trait impls still have to be +// reachable if they are called from inlinable code. Generally, it's not known until +// monomorphization if a specific trait impl item can be reachable or not. So, we +// conservatively mark all of them as reachable. +// FIXME: One possible strategy for pruning the reachable set is to avoid marking impl +// items of non-exported traits (or maybe all local traits?) unless their respective +// trait items are used from inlinable code through method call syntax or UFCS, or their +// trait is a lang item. +struct CollectPrivateImplItemsVisitor<'a> { + exported_items: &'a privacy::ExportedItems, + worklist: &'a mut Vec, +} + +impl<'a, 'v> Visitor<'v> for CollectPrivateImplItemsVisitor<'a> { + fn visit_item(&mut self, item: &hir::Item) { + // We need only trait impls here, not inherent impls, and only non-exported ones + if let hir::ItemImpl(_, _, _, Some(_), _, ref impl_items) = item.node { + if !self.exported_items.contains(&item.id) { + for impl_item in impl_items { + self.worklist.push(impl_item.id); } } - }) + } + + visit::walk_item(self, item); } } pub fn find_reachable(tcx: &ty::ctxt, exported_items: &privacy::ExportedItems) -> NodeSet { + let mut reachable_context = ReachableContext::new(tcx); // Step 1: Seed the worklist with all nodes which were found to be public as - // a result of the privacy pass along with all local lang items. If - // other crates link to us, they're going to expect to be able to + // a result of the privacy pass along with all local lang items and impl items. + // If other crates link to us, they're going to expect to be able to // use the lang items, so we need to be sure to mark them as // exported. for id in exported_items { reachable_context.worklist.push(*id); } for (_, item) in tcx.lang_items.items() { - match *item { - Some(did) => { - if let Some(node_id) = tcx.map.as_local_node_id(did) { - reachable_context.worklist.push(node_id); - } + if let Some(did) = *item { + if let Some(node_id) = tcx.map.as_local_node_id(did) { + reachable_context.worklist.push(node_id); } - _ => {} } } + { + let mut collect_private_impl_items = CollectPrivateImplItemsVisitor { + exported_items: exported_items, + worklist: &mut reachable_context.worklist, + }; + + visit::walk_crate(&mut collect_private_impl_items, tcx.map.krate()); + } // Step 2: Mark all symbols that the symbols on the worklist touch. reachable_context.propagate(); - // Step 3: Mark all destructors as reachable. - reachable_context.mark_destructors_reachable(); - // Return the set of reachable symbols. reachable_context.reachable_symbols } diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index d9398a1c58cd9..fa0c6c41ce5cc 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -205,7 +205,7 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> { hir::TyPath(None, ref path) => { // if this path references a trait, then this will resolve to // a trait ref, which introduces a binding scope. - match self.def_map.borrow().get(&ty.id).map(|d| (d.base_def, d.depth)) { + match self.def_map.get(&ty.id).map(|d| (d.base_def, d.depth)) { Some((def::DefTrait(..), 0)) => { self.with(LateScope(&Vec::new(), self.scope), |_, this| { this.visit_path(path, ty.id); diff --git a/src/librustc/middle/traits/error_reporting.rs b/src/librustc/middle/traits/error_reporting.rs index a54818b2b5369..0931c138e46f4 100644 --- a/src/librustc/middle/traits/error_reporting.rs +++ b/src/librustc/middle/traits/error_reporting.rs @@ -498,7 +498,7 @@ fn note_obligation_cause_code<'a, 'tcx, T>(infcx: &InferCtxt<'a, 'tcx>, ObligationCauseCode::SliceOrArrayElem => { tcx.sess.fileline_note( cause_span, - &format!("slice and array elements must have `Sized` type")); + "slice and array elements must have `Sized` type"); } ObligationCauseCode::ProjectionWf(data) => { tcx.sess.fileline_note( diff --git a/src/librustc/middle/traits/mod.rs b/src/librustc/middle/traits/mod.rs index a037621f5c025..691bac0cef865 100644 --- a/src/librustc/middle/traits/mod.rs +++ b/src/librustc/middle/traits/mod.rs @@ -44,6 +44,7 @@ pub use self::object_safety::object_safety_violations; pub use self::object_safety::ObjectSafetyViolation; pub use self::object_safety::MethodViolationCode; pub use self::object_safety::is_vtable_safe_method; +pub use self::select::EvaluationCache; pub use self::select::SelectionContext; pub use self::select::SelectionCache; pub use self::select::{MethodMatchResult, MethodMatched, MethodAmbiguous, MethodDidNotMatch}; @@ -339,32 +340,53 @@ pub fn type_known_to_meet_builtin_bound<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>, ty, bound); - let mut fulfill_cx = FulfillmentContext::new(false); - - // We can use a dummy node-id here because we won't pay any mind - // to region obligations that arise (there shouldn't really be any - // anyhow). let cause = ObligationCause::misc(span, ast::DUMMY_NODE_ID); - - fulfill_cx.register_builtin_bound(infcx, ty, bound, cause); - - // Note: we only assume something is `Copy` if we can - // *definitively* show that it implements `Copy`. Otherwise, - // assume it is move; linear is always ok. - match fulfill_cx.select_all_or_error(infcx) { - Ok(()) => { - debug!("type_known_to_meet_builtin_bound: ty={:?} bound={:?} success", - ty, - bound); - true - } - Err(e) => { - debug!("type_known_to_meet_builtin_bound: ty={:?} bound={:?} errors={:?}", - ty, - bound, - e); - false + let obligation = + util::predicate_for_builtin_bound(infcx.tcx, cause, bound, 0, ty); + let obligation = match obligation { + Ok(o) => o, + Err(..) => return false + }; + let result = SelectionContext::new(infcx) + .evaluate_obligation_conservatively(&obligation); + debug!("type_known_to_meet_builtin_bound: ty={:?} bound={:?} => {:?}", + ty, bound, result); + + if result && (ty.has_infer_types() || ty.has_closure_types()) { + // Because of inference "guessing", selection can sometimes claim + // to succeed while the success requires a guess. To ensure + // this function's result remains infallible, we must confirm + // that guess. While imperfect, I believe this is sound. + + let mut fulfill_cx = FulfillmentContext::new(false); + + // We can use a dummy node-id here because we won't pay any mind + // to region obligations that arise (there shouldn't really be any + // anyhow). + let cause = ObligationCause::misc(span, ast::DUMMY_NODE_ID); + + fulfill_cx.register_builtin_bound(infcx, ty, bound, cause); + + // Note: we only assume something is `Copy` if we can + // *definitively* show that it implements `Copy`. Otherwise, + // assume it is move; linear is always ok. + match fulfill_cx.select_all_or_error(infcx) { + Ok(()) => { + debug!("type_known_to_meet_builtin_bound: ty={:?} bound={:?} success", + ty, + bound); + true + } + Err(e) => { + debug!("type_known_to_meet_builtin_bound: ty={:?} bound={:?} errors={:?}", + ty, + bound, + e); + false + } } + } else { + result } } diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs index f6e35cf739d62..ba69632fde1b1 100644 --- a/src/librustc/middle/traits/select.rs +++ b/src/librustc/middle/traits/select.rs @@ -9,7 +9,6 @@ // except according to those terms. //! See `README.md` for high-level documentation -#![allow(dead_code)] // FIXME -- just temporarily pub use self::MethodMatchResult::*; pub use self::MethodMatchedData::*; @@ -190,7 +189,6 @@ pub enum MethodMatchedData { /// parameter environment. #[derive(PartialEq,Eq,Debug,Clone)] enum SelectionCandidate<'tcx> { - PhantomFnCandidate, BuiltinCandidate(ty::BuiltinBound), ParamCandidate(ty::PolyTraitRef<'tcx>), ImplCandidate(DefId), @@ -236,11 +234,24 @@ enum BuiltinBoundConditions<'tcx> { AmbiguousBuiltin } -#[derive(Debug)] -enum EvaluationResult<'tcx> { +#[derive(Copy, Clone, Debug, PartialOrd, Ord, PartialEq, Eq)] +/// The result of trait evaluation. The order is important +/// here as the evaluation of a list is the maximum of the +/// evaluations. +enum EvaluationResult { + /// Evaluation successful EvaluatedToOk, + /// Evaluation failed because of recursion - treated as ambiguous + EvaluatedToUnknown, + /// Evaluation is known to be ambiguous EvaluatedToAmbig, - EvaluatedToErr(SelectionError<'tcx>), + /// Evaluation failed + EvaluatedToErr, +} + +#[derive(Clone)] +pub struct EvaluationCache<'tcx> { + hashmap: RefCell, EvaluationResult>> } impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { @@ -381,6 +392,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // The result is "true" if the obligation *may* hold and "false" if // we can be sure it does not. + /// Evaluates whether the obligation `obligation` can be satisfied (by any means). pub fn evaluate_obligation(&mut self, obligation: &PredicateObligation<'tcx>) @@ -389,45 +401,50 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { debug!("evaluate_obligation({:?})", obligation); - self.evaluate_predicate_recursively(TraitObligationStackList::empty(), obligation) - .may_apply() + self.infcx.probe(|_| { + self.evaluate_predicate_recursively(TraitObligationStackList::empty(), obligation) + .may_apply() + }) } - fn evaluate_builtin_bound_recursively<'o>(&mut self, - bound: ty::BuiltinBound, - previous_stack: &TraitObligationStack<'o, 'tcx>, - ty: Ty<'tcx>) - -> EvaluationResult<'tcx> + /// Evaluates whether the obligation `obligation` can be satisfied, + /// and returns `false` if not certain. However, this is not entirely + /// accurate if inference variables are involved. + pub fn evaluate_obligation_conservatively(&mut self, + obligation: &PredicateObligation<'tcx>) + -> bool { - let obligation = - util::predicate_for_builtin_bound( - self.tcx(), - previous_stack.obligation.cause.clone(), - bound, - previous_stack.obligation.recursion_depth + 1, - ty); - - match obligation { - Ok(obligation) => { - self.evaluate_predicate_recursively(previous_stack.list(), &obligation) - } - Err(ErrorReported) => { - EvaluatedToOk - } - } + debug!("evaluate_obligation_conservatively({:?})", + obligation); + + self.infcx.probe(|_| { + self.evaluate_predicate_recursively(TraitObligationStackList::empty(), obligation) + == EvaluatedToOk + }) } + /// Evaluates the predicates in `predicates` recursively. Note that + /// this applies projections in the predicates, and therefore + /// is run within an inference probe. fn evaluate_predicates_recursively<'a,'o,I>(&mut self, stack: TraitObligationStackList<'o, 'tcx>, predicates: I) - -> EvaluationResult<'tcx> + -> EvaluationResult where I : Iterator>, 'tcx:'a { let mut result = EvaluatedToOk; for obligation in predicates { - match self.evaluate_predicate_recursively(stack, obligation) { - EvaluatedToErr(e) => { return EvaluatedToErr(e); } + let eval = self.evaluate_predicate_recursively(stack, obligation); + debug!("evaluate_predicate_recursively({:?}) = {:?}", + obligation, eval); + match eval { + EvaluatedToErr => { return EvaluatedToErr; } EvaluatedToAmbig => { result = EvaluatedToAmbig; } + EvaluatedToUnknown => { + if result < EvaluatedToUnknown { + result = EvaluatedToUnknown; + } + } EvaluatedToOk => { } } } @@ -437,7 +454,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn evaluate_predicate_recursively<'o>(&mut self, previous_stack: TraitObligationStackList<'o, 'tcx>, obligation: &PredicateObligation<'tcx>) - -> EvaluationResult<'tcx> + -> EvaluationResult { debug!("evaluate_predicate_recursively({:?})", obligation); @@ -459,12 +476,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } ty::Predicate::Equate(ref p) => { - let result = self.infcx.probe(|_| { - self.infcx.equality_predicate(obligation.cause.span, p) - }); - match result { + // does this code ever run? + match self.infcx.equality_predicate(obligation.cause.span, p) { Ok(()) => EvaluatedToOk, - Err(_) => EvaluatedToErr(Unimplemented), + Err(_) => EvaluatedToErr } } @@ -489,26 +504,24 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { if object_safety::is_object_safe(self.tcx(), trait_def_id) { EvaluatedToOk } else { - EvaluatedToErr(Unimplemented) + EvaluatedToErr } } ty::Predicate::Projection(ref data) => { - self.infcx.probe(|_| { - let project_obligation = obligation.with(data.clone()); - match project::poly_project_and_unify_type(self, &project_obligation) { - Ok(Some(subobligations)) => { - self.evaluate_predicates_recursively(previous_stack, - subobligations.iter()) - } - Ok(None) => { - EvaluatedToAmbig - } - Err(_) => { - EvaluatedToErr(Unimplemented) - } + let project_obligation = obligation.with(data.clone()); + match project::poly_project_and_unify_type(self, &project_obligation) { + Ok(Some(subobligations)) => { + self.evaluate_predicates_recursively(previous_stack, + subobligations.iter()) } - }) + Ok(None) => { + EvaluatedToAmbig + } + Err(_) => { + EvaluatedToErr + } + } } } } @@ -516,22 +529,33 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn evaluate_obligation_recursively<'o>(&mut self, previous_stack: TraitObligationStackList<'o, 'tcx>, obligation: &TraitObligation<'tcx>) - -> EvaluationResult<'tcx> + -> EvaluationResult { debug!("evaluate_obligation_recursively({:?})", obligation); let stack = self.push_stack(previous_stack, obligation); + let fresh_trait_ref = stack.fresh_trait_ref; + if let Some(result) = self.check_evaluation_cache(fresh_trait_ref) { + debug!("CACHE HIT: EVAL({:?})={:?}", + fresh_trait_ref, + result); + return result; + } let result = self.evaluate_stack(&stack); - debug!("result: {:?}", result); + debug!("CACHE MISS: EVAL({:?})={:?}", + fresh_trait_ref, + result); + self.insert_evaluation_cache(fresh_trait_ref, result); + result } fn evaluate_stack<'o>(&mut self, stack: &TraitObligationStack<'o, 'tcx>) - -> EvaluationResult<'tcx> + -> EvaluationResult { // In intercrate mode, whenever any of the types are unbound, // there can always be an impl. Even if there are no impls in @@ -559,16 +583,19 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // precise still. let input_types = stack.fresh_trait_ref.0.input_types(); let unbound_input_types = input_types.iter().any(|ty| ty.is_fresh()); - if - unbound_input_types && - (self.intercrate || + if unbound_input_types && self.intercrate { + debug!("evaluate_stack({:?}) --> unbound argument, intercrate --> ambiguous", + stack.fresh_trait_ref); + return EvaluatedToAmbig; + } + if unbound_input_types && stack.iter().skip(1).any( |prev| self.match_fresh_trait_refs(&stack.fresh_trait_ref, - &prev.fresh_trait_ref))) + &prev.fresh_trait_ref)) { - debug!("evaluate_stack({:?}) --> unbound argument, recursion --> ambiguous", + debug!("evaluate_stack({:?}) --> unbound argument, recursive --> giving up", stack.fresh_trait_ref); - return EvaluatedToAmbig; + return EvaluatedToUnknown; } // If there is any previous entry on the stack that precisely @@ -601,40 +628,74 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } match self.candidate_from_obligation(stack) { - Ok(Some(c)) => self.winnow_candidate(stack, &c), + Ok(Some(c)) => self.evaluate_candidate(stack, &c), Ok(None) => EvaluatedToAmbig, - Err(e) => EvaluatedToErr(e), + Err(..) => EvaluatedToErr } } - /// Evaluates whether the impl with id `impl_def_id` could be applied to the self type - /// `obligation_self_ty`. This can be used either for trait or inherent impls. - pub fn evaluate_impl(&mut self, - impl_def_id: DefId, - obligation: &TraitObligation<'tcx>) - -> bool + /// Further evaluate `candidate` to decide whether all type parameters match and whether nested + /// obligations are met. Returns true if `candidate` remains viable after this further + /// scrutiny. + fn evaluate_candidate<'o>(&mut self, + stack: &TraitObligationStack<'o, 'tcx>, + candidate: &SelectionCandidate<'tcx>) + -> EvaluationResult { - debug!("evaluate_impl(impl_def_id={:?}, obligation={:?})", - impl_def_id, - obligation); - - self.infcx.probe(|snapshot| { - match self.match_impl(impl_def_id, obligation, snapshot) { - Ok((substs, skol_map)) => { - let vtable_impl = self.vtable_impl(impl_def_id, - substs, - obligation.cause.clone(), - obligation.recursion_depth + 1, - skol_map, - snapshot); - self.winnow_selection(TraitObligationStackList::empty(), - VtableImpl(vtable_impl)).may_apply() - } - Err(()) => { - false + debug!("evaluate_candidate: depth={} candidate={:?}", + stack.obligation.recursion_depth, candidate); + let result = self.infcx.probe(|_| { + let candidate = (*candidate).clone(); + match self.confirm_candidate(stack.obligation, candidate) { + Ok(selection) => { + self.evaluate_predicates_recursively( + stack.list(), + selection.nested_obligations().iter()) } + Err(..) => EvaluatedToErr } - }) + }); + debug!("evaluate_candidate: depth={} result={:?}", + stack.obligation.recursion_depth, result); + result + } + + fn pick_evaluation_cache(&self) -> &EvaluationCache<'tcx> { + // see comment in `pick_candidate_cache` + if self.intercrate || + !self.param_env().caller_bounds.is_empty() + { + &self.param_env().evaluation_cache + } else + { + &self.tcx().evaluation_cache + } + } + + fn check_evaluation_cache(&self, trait_ref: ty::PolyTraitRef<'tcx>) + -> Option + { + let cache = self.pick_evaluation_cache(); + cache.hashmap.borrow().get(&trait_ref).cloned() + } + + fn insert_evaluation_cache(&mut self, + trait_ref: ty::PolyTraitRef<'tcx>, + result: EvaluationResult) + { + // Avoid caching results that depend on more than just the trait-ref: + // The stack can create EvaluatedToUnknown, and closure signatures + // being yet uninferred can create "spurious" EvaluatedToAmbig + // and EvaluatedToOk. + if result == EvaluatedToUnknown || + ((result == EvaluatedToAmbig || result == EvaluatedToOk) + && trait_ref.has_closure_types()) + { + return; + } + + let cache = self.pick_evaluation_cache(); + cache.hashmap.borrow_mut().insert(trait_ref, result); } /////////////////////////////////////////////////////////////////////////// @@ -669,7 +730,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { match self.check_candidate_cache(&cache_fresh_trait_pred) { Some(c) => { - debug!("CACHE HIT: cache_fresh_trait_pred={:?}, candidate={:?}", + debug!("CACHE HIT: SELECT({:?})={:?}", cache_fresh_trait_pred, c); return c; @@ -681,7 +742,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let candidate = self.candidate_from_obligation_no_cache(stack); if self.should_update_candidate_cache(&cache_fresh_trait_pred, &candidate) { - debug!("CACHE MISS: cache_fresh_trait_pred={:?}, candidate={:?}", + debug!("CACHE MISS: SELECT({:?})={:?}", cache_fresh_trait_pred, candidate); self.insert_candidate_cache(cache_fresh_trait_pred, candidate.clone()); } @@ -740,7 +801,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // Instead, we select the right impl now but report `Bar does // not implement Clone`. if candidates.len() > 1 { - candidates.retain(|c| self.winnow_candidate(stack, c).may_apply()) + candidates.retain(|c| self.evaluate_candidate(stack, c).may_apply()) } // If there are STILL multiple candidate, we can further reduce @@ -1138,16 +1199,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn evaluate_where_clause<'o>(&mut self, stack: &TraitObligationStack<'o, 'tcx>, where_clause_trait_ref: ty::PolyTraitRef<'tcx>) - -> EvaluationResult<'tcx> + -> EvaluationResult { self.infcx().probe(move |_| { match self.match_where_clause_trait_ref(stack.obligation, where_clause_trait_ref) { Ok(obligations) => { self.evaluate_predicates_recursively(stack.list(), obligations.iter()) } - Err(()) => { - EvaluatedToErr(Unimplemented) - } + Err(()) => EvaluatedToErr } }) } @@ -1486,37 +1545,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // attempt to evaluate recursive bounds to see if they are // satisfied. - /// Further evaluate `candidate` to decide whether all type parameters match and whether nested - /// obligations are met. Returns true if `candidate` remains viable after this further - /// scrutiny. - fn winnow_candidate<'o>(&mut self, - stack: &TraitObligationStack<'o, 'tcx>, - candidate: &SelectionCandidate<'tcx>) - -> EvaluationResult<'tcx> - { - debug!("winnow_candidate: candidate={:?}", candidate); - let result = self.infcx.probe(|_| { - let candidate = (*candidate).clone(); - match self.confirm_candidate(stack.obligation, candidate) { - Ok(selection) => self.winnow_selection(stack.list(), - selection), - Err(error) => EvaluatedToErr(error), - } - }); - debug!("winnow_candidate depth={} result={:?}", - stack.obligation.recursion_depth, result); - result - } - - fn winnow_selection<'o>(&mut self, - stack: TraitObligationStackList<'o,'tcx>, - selection: Selection<'tcx>) - -> EvaluationResult<'tcx> - { - self.evaluate_predicates_recursively(stack, - selection.nested_obligations().iter()) - } - /// Returns true if `candidate_i` should be dropped in favor of /// `candidate_j`. Generally speaking we will drop duplicate /// candidates and prefer where-clause candidates. @@ -1542,9 +1570,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { "default implementations shouldn't be recorded \ when there are other valid candidates"); } - &PhantomFnCandidate => { - self.tcx().sess.bug("PhantomFn didn't short-circuit selection"); - } &ImplCandidate(..) | &ClosureCandidate(..) | &FnPointerCandidate(..) | @@ -1974,7 +1999,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { try!(self.confirm_builtin_candidate(obligation, builtin_bound)))) } - PhantomFnCandidate | ErrorCandidate => { Ok(VtableBuiltin(VtableBuiltinData { nested: vec![] })) } @@ -2260,6 +2284,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { impl_def_id, impl_obligations); + // Because of RFC447, the impl-trait-ref and obligations + // are sufficient to determine the impl substs, without + // relying on projections in the impl-trait-ref. + // + // e.g. `impl> Foo<::T> for V` impl_obligations.append(&mut substs.obligations); VtableImplData { impl_def_id: impl_def_id, @@ -2744,74 +2773,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } } - /// Determines whether the self type declared against - /// `impl_def_id` matches `obligation_self_ty`. If successful, - /// returns the substitutions used to make them match. See - /// `match_impl()`. For example, if `impl_def_id` is declared - /// as: - /// - /// impl Foo for Box { ... } - /// - /// and `obligation_self_ty` is `int`, we'd get back an `Err(_)` - /// result. But if `obligation_self_ty` were `Box`, we'd get - /// back `Ok(T=int)`. - fn match_inherent_impl(&mut self, - impl_def_id: DefId, - obligation_cause: &ObligationCause, - obligation_self_ty: Ty<'tcx>) - -> Result,()> - { - // Create fresh type variables for each type parameter declared - // on the impl etc. - let impl_substs = util::fresh_type_vars_for_impl(self.infcx, - obligation_cause.span, - impl_def_id); - - // Find the self type for the impl. - let impl_self_ty = self.tcx().lookup_item_type(impl_def_id).ty; - let impl_self_ty = impl_self_ty.subst(self.tcx(), &impl_substs); - - debug!("match_impl_self_types(obligation_self_ty={:?}, impl_self_ty={:?})", - obligation_self_ty, - impl_self_ty); - - match self.match_self_types(obligation_cause, - impl_self_ty, - obligation_self_ty) { - Ok(()) => { - debug!("Matched impl_substs={:?}", impl_substs); - Ok(impl_substs) - } - Err(()) => { - debug!("NoMatch"); - Err(()) - } - } - } - - fn match_self_types(&mut self, - cause: &ObligationCause, - - // The self type provided by the impl/caller-obligation: - provided_self_ty: Ty<'tcx>, - - // The self type the obligation is for: - required_self_ty: Ty<'tcx>) - -> Result<(),()> - { - // FIXME(#5781) -- equating the types is stronger than - // necessary. Should consider variance of trait w/r/t Self. - - let origin = infer::RelateSelfType(cause.span); - match self.infcx.eq_types(false, - origin, - provided_self_ty, - required_self_ty) { - Ok(()) => Ok(()), - Err(_) => Err(()), - } - } - /////////////////////////////////////////////////////////////////////////// // Miscellany @@ -2892,17 +2853,37 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { -> Vec> { debug!("impl_or_trait_obligations(def_id={:?})", def_id); + let tcx = self.tcx(); - let predicates = self.tcx().lookup_predicates(def_id); - let predicates = predicates.instantiate(self.tcx(), substs); - let predicates = normalize_with_depth(self, cause.clone(), recursion_depth, &predicates); - let mut predicates = self.infcx().plug_leaks(skol_map, snapshot, &predicates); - let mut obligations = - util::predicates_for_generics(cause, - recursion_depth, - &predicates.value); - obligations.append(&mut predicates.obligations); - obligations + // To allow for one-pass evaluation of the nested obligation, + // each predicate must be preceded by the obligations required + // to normalize it. + // for example, if we have: + // impl> Foo for V where U::Item: Copy + // the impl will have the following predicates: + // ::Item = U, + // U: Iterator, U: Sized, + // V: Iterator, V: Sized, + // ::Item: Copy + // When we substitute, say, `V => IntoIter, U => $0`, the last + // obligation will normalize to `<$0 as Iterator>::Item = $1` and + // `$1: Copy`, so we must ensure the obligations are emitted in + // that order. + let predicates = tcx + .lookup_predicates(def_id) + .predicates.iter() + .flat_map(|predicate| { + let predicate = + normalize_with_depth(self, cause.clone(), recursion_depth, + &predicate.subst(tcx, substs)); + predicate.obligations.into_iter().chain( + Some(Obligation { + cause: cause.clone(), + recursion_depth: recursion_depth, + predicate: predicate.value + })) + }).collect(); + self.infcx().plug_leaks(skol_map, snapshot, &predicates) } #[allow(unused_comparisons)] @@ -2956,6 +2937,14 @@ impl<'tcx> SelectionCache<'tcx> { } } +impl<'tcx> EvaluationCache<'tcx> { + pub fn new() -> EvaluationCache<'tcx> { + EvaluationCache { + hashmap: RefCell::new(FnvHashMap()) + } + } +} + impl<'o,'tcx> TraitObligationStack<'o,'tcx> { fn list(&'o self) -> TraitObligationStackList<'o,'tcx> { TraitObligationStackList::with(self) @@ -3001,17 +2990,14 @@ impl<'o,'tcx> fmt::Debug for TraitObligationStack<'o,'tcx> { } } -impl<'tcx> EvaluationResult<'tcx> { +impl EvaluationResult { fn may_apply(&self) -> bool { match *self { EvaluatedToOk | EvaluatedToAmbig | - EvaluatedToErr(OutputTypeParameterMismatch(..)) | - EvaluatedToErr(TraitNotObjectSafe(_)) => - true, + EvaluatedToUnknown => true, - EvaluatedToErr(Unimplemented) => - false, + EvaluatedToErr => false } } } diff --git a/src/librustc/middle/ty/context.rs b/src/librustc/middle/ty/context.rs index 830232cf373b8..e02a120a5c60f 100644 --- a/src/librustc/middle/ty/context.rs +++ b/src/librustc/middle/ty/context.rs @@ -121,6 +121,13 @@ pub struct Tables<'tcx> { /// Records the type of each closure. The def ID is the ID of the /// expression defining the closure. pub closure_kinds: DefIdMap, + + /// For each fn, records the "liberated" types of its arguments + /// and return type. Liberated means that all bound regions + /// (including late-bound regions) are replaced with free + /// equivalents. This table is not used in trans (since regions + /// are erased there) and hence is not serialized to metadata. + pub liberated_fn_sigs: NodeMap>, } impl<'tcx> Tables<'tcx> { @@ -133,6 +140,7 @@ impl<'tcx> Tables<'tcx> { upvar_capture_map: FnvHashMap(), closure_tys: DefIdMap(), closure_kinds: DefIdMap(), + liberated_fn_sigs: NodeMap(), } } @@ -220,7 +228,7 @@ pub struct ctxt<'tcx> { pub types: CommonTypes<'tcx>, pub sess: &'tcx Session, - pub def_map: DefMap, + pub def_map: RefCell, pub named_region_map: resolve_lifetime::NamedRegionMap, @@ -324,6 +332,11 @@ pub struct ctxt<'tcx> { /// for things that do not have to do with the parameters in scope. pub selection_cache: traits::SelectionCache<'tcx>, + /// Caches the results of trait evaluation. This cache is used + /// for things that do not have to do with the parameters in scope. + /// Merge this with `selection_cache`? + pub evaluation_cache: traits::EvaluationCache<'tcx>, + /// A set of predicates that have been fulfilled *somewhere*. /// This is used to avoid duplicate work. Predicates are only /// added to this set when they mention only "global" names @@ -445,10 +458,10 @@ impl<'tcx> ctxt<'tcx> { /// reference to the context, to allow formatting values that need it. pub fn create_and_enter(s: &'tcx Session, arenas: &'tcx CtxtArenas<'tcx>, - def_map: DefMap, + def_map: RefCell, named_region_map: resolve_lifetime::NamedRegionMap, map: ast_map::Map<'tcx>, - freevars: RefCell, + freevars: FreevarMap, region_maps: RegionMaps, lang_items: middle::lang_items::LanguageItems, stability: stability::Index<'tcx>, @@ -481,7 +494,7 @@ impl<'tcx> ctxt<'tcx> { super_predicates: RefCell::new(DefIdMap()), fulfilled_predicates: RefCell::new(traits::FulfilledPredicates::new()), map: map, - freevars: freevars, + freevars: RefCell::new(freevars), tcache: RefCell::new(DefIdMap()), rcache: RefCell::new(FnvHashMap()), tc_cache: RefCell::new(FnvHashMap()), @@ -504,6 +517,7 @@ impl<'tcx> ctxt<'tcx> { transmute_restrictions: RefCell::new(Vec::new()), stability: RefCell::new(stability), selection_cache: traits::SelectionCache::new(), + evaluation_cache: traits::EvaluationCache::new(), repr_hint_cache: RefCell::new(DefIdMap()), const_qualif_map: RefCell::new(NodeMap()), custom_coerce_unsized_kinds: RefCell::new(DefIdMap()), diff --git a/src/librustc/middle/ty/error.rs b/src/librustc/middle/ty/error.rs index 61536934aae13..d9033eaa29f6b 100644 --- a/src/librustc/middle/ty/error.rs +++ b/src/librustc/middle/ty/error.rs @@ -288,10 +288,9 @@ impl<'tcx> ty::ctxt<'tcx> { let found_str = values.found.sort_string(self); if expected_str == found_str && expected_str == "closure" { self.sess.span_note(sp, - &format!("no two closures, even if identical, have the same type")); + "no two closures, even if identical, have the same type"); self.sess.span_help(sp, - &format!("consider boxing your closure and/or \ - using it as a trait object")); + "consider boxing your closure and/or using it as a trait object"); } }, TyParamDefaultMismatch(values) => { @@ -307,8 +306,7 @@ impl<'tcx> ty::ctxt<'tcx> { .and_then(|node_id| self.map.opt_span(node_id)) { Some(span) => { - self.sess.span_note(span, - &format!("a default was defined here...")); + self.sess.span_note(span, "a default was defined here..."); } None => { self.sess.note( @@ -319,15 +317,14 @@ impl<'tcx> ty::ctxt<'tcx> { self.sess.span_note( expected.origin_span, - &format!("...that was applied to an unconstrained type variable here")); + "...that was applied to an unconstrained type variable here"); match self.map.as_local_node_id(found.def_id) .and_then(|node_id| self.map.opt_span(node_id)) { Some(span) => { - self.sess.span_note(span, - &format!("a second default was defined here...")); + self.sess.span_note(span, "a second default was defined here..."); } None => { self.sess.note( @@ -338,7 +335,7 @@ impl<'tcx> ty::ctxt<'tcx> { self.sess.span_note( found.origin_span, - &format!("...that also applies to the same type variable here")); + "...that also applies to the same type variable here"); } _ => {} } diff --git a/src/librustc/middle/ty/mod.rs b/src/librustc/middle/ty/mod.rs index 573634414932b..0a9fa1d6ce394 100644 --- a/src/librustc/middle/ty/mod.rs +++ b/src/librustc/middle/ty/mod.rs @@ -1091,6 +1091,9 @@ pub struct ParameterEnvironment<'a, 'tcx:'a> { /// for things that have to do with the parameters in scope. pub selection_cache: traits::SelectionCache<'tcx>, + /// Caches the results of trait evaluation. + pub evaluation_cache: traits::EvaluationCache<'tcx>, + /// Scope that is attached to free regions for this scope. This /// is usually the id of the fn body, but for more abstract scopes /// like structs we often use the node-id of the struct. @@ -1112,6 +1115,7 @@ impl<'a, 'tcx> ParameterEnvironment<'a, 'tcx> { implicit_region_bound: self.implicit_region_bound, caller_bounds: caller_bounds, selection_cache: traits::SelectionCache::new(), + evaluation_cache: traits::EvaluationCache::new(), free_id: self.free_id, } } @@ -1731,6 +1735,13 @@ impl<'tcx, 'container> VariantDefData<'tcx, 'container> { self.fields.iter().find(|f| f.name == name) } + #[inline] + pub fn index_of_field_named(&self, + name: ast::Name) + -> Option { + self.fields.iter().position(|f| f.name == name) + } + #[inline] pub fn field_named(&self, name: ast::Name) -> &FieldDefData<'tcx, 'container> { self.find_field_named(name).unwrap() @@ -2577,6 +2588,7 @@ impl<'tcx> ctxt<'tcx> { caller_bounds: Vec::new(), implicit_region_bound: ty::ReEmpty, selection_cache: traits::SelectionCache::new(), + evaluation_cache: traits::EvaluationCache::new(), // for an empty parameter // environment, there ARE no free @@ -2666,6 +2678,7 @@ impl<'tcx> ctxt<'tcx> { implicit_region_bound: ty::ReScope(free_id_outlive), caller_bounds: predicates, selection_cache: traits::SelectionCache::new(), + evaluation_cache: traits::EvaluationCache::new(), free_id: free_id, }; diff --git a/src/librustc/middle/ty/structural_impls.rs b/src/librustc/middle/ty/structural_impls.rs index 176dc5a743d05..41303b46dfd09 100644 --- a/src/librustc/middle/ty/structural_impls.rs +++ b/src/librustc/middle/ty/structural_impls.rs @@ -822,6 +822,7 @@ impl<'a, 'tcx> TypeFoldable<'tcx> for ty::ParameterEnvironment<'a, 'tcx> where ' implicit_region_bound: self.implicit_region_bound.fold_with(folder), caller_bounds: self.caller_bounds.fold_with(folder), selection_cache: traits::SelectionCache::new(), + evaluation_cache: traits::EvaluationCache::new(), free_id: self.free_id, } } diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 3714a43744fe5..808a63982c263 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -510,7 +510,7 @@ options! {CodegenOptions, CodegenSetter, basic_codegen_options, "debug info emission level, 0 = no debug info, 1 = line tables only, \ 2 = full debug info with variable and type information"), opt_level: Option = (None, parse_opt_uint, - "Optimize with possible levels 0-3"), + "optimize with possible levels 0-3"), debug_assertions: Option = (None, parse_opt_bool, "explicitly enable the cfg(debug_assertions) directive"), } @@ -527,6 +527,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, "count where LLVM instrs originate"), time_llvm_passes: bool = (false, parse_bool, "measure time of each LLVM pass"), + input_stats: bool = (false, parse_bool, + "gather statistics about the input"), trans_stats: bool = (false, parse_bool, "gather trans statistics"), asm_comments: bool = (false, parse_bool, @@ -544,56 +546,56 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, meta_stats: bool = (false, parse_bool, "gather metadata statistics"), print_link_args: bool = (false, parse_bool, - "Print the arguments passed to the linker"), + "print the arguments passed to the linker"), gc: bool = (false, parse_bool, - "Garbage collect shared data (experimental)"), + "garbage collect shared data (experimental)"), print_llvm_passes: bool = (false, parse_bool, - "Prints the llvm optimization passes being run"), + "prints the llvm optimization passes being run"), ast_json: bool = (false, parse_bool, - "Print the AST as JSON and halt"), + "print the AST as JSON and halt"), ast_json_noexpand: bool = (false, parse_bool, - "Print the pre-expansion AST as JSON and halt"), + "print the pre-expansion AST as JSON and halt"), ls: bool = (false, parse_bool, - "List the symbols defined by a library crate"), + "list the symbols defined by a library crate"), save_analysis: bool = (false, parse_bool, - "Write syntax and type analysis information in addition to normal output"), + "write syntax and type analysis information in addition to normal output"), print_move_fragments: bool = (false, parse_bool, - "Print out move-fragment data for every fn"), + "print out move-fragment data for every fn"), flowgraph_print_loans: bool = (false, parse_bool, - "Include loan analysis data in --pretty flowgraph output"), + "include loan analysis data in --unpretty flowgraph output"), flowgraph_print_moves: bool = (false, parse_bool, - "Include move analysis data in --pretty flowgraph output"), + "include move analysis data in --unpretty flowgraph output"), flowgraph_print_assigns: bool = (false, parse_bool, - "Include assignment analysis data in --pretty flowgraph output"), + "include assignment analysis data in --unpretty flowgraph output"), flowgraph_print_all: bool = (false, parse_bool, - "Include all dataflow analysis data in --pretty flowgraph output"), + "include all dataflow analysis data in --unpretty flowgraph output"), print_region_graph: bool = (false, parse_bool, - "Prints region inference graph. \ + "prints region inference graph. \ Use with RUST_REGION_GRAPH=help for more info"), parse_only: bool = (false, parse_bool, - "Parse only; do not compile, assemble, or link"), + "parse only; do not compile, assemble, or link"), no_trans: bool = (false, parse_bool, - "Run all passes except translation; no output"), + "run all passes except translation; no output"), treat_err_as_bug: bool = (false, parse_bool, - "Treat all errors that occur as bugs"), + "treat all errors that occur as bugs"), no_analysis: bool = (false, parse_bool, - "Parse and expand the source, but run no analysis"), + "parse and expand the source, but run no analysis"), extra_plugins: Vec = (Vec::new(), parse_list, "load extra plugins"), unstable_options: bool = (false, parse_bool, - "Adds unstable command line options to rustc interface"), + "adds unstable command line options to rustc interface"), print_enum_sizes: bool = (false, parse_bool, - "Print the size of enums and their variants"), + "print the size of enums and their variants"), force_overflow_checks: Option = (None, parse_opt_bool, - "Force overflow checks on or off"), + "force overflow checks on or off"), force_dropflag_checks: Option = (None, parse_opt_bool, - "Force drop flag checks on or off"), + "force drop flag checks on or off"), trace_macros: bool = (false, parse_bool, - "For every macro invocation, print its name and arguments"), + "for every macro invocation, print its name and arguments"), enable_nonzeroing_move_hints: bool = (false, parse_bool, - "Force nonzeroing move optimization on"), + "force nonzeroing move optimization on"), keep_mtwt_tables: bool = (false, parse_bool, - "Don't clear the resolution tables after analysis"), + "don't clear the resolution tables after analysis"), } pub fn default_lib_output() -> CrateType { @@ -610,22 +612,28 @@ pub fn default_configuration(sess: &Session) -> ast::CrateConfig { let env = &sess.target.target.target_env; let vendor = &sess.target.target.target_vendor; - let fam = match sess.target.target.options.is_like_windows { - true => InternedString::new("windows"), - false => InternedString::new("unix") + let fam = if let Some(ref fam) = sess.target.target.options.target_family { + intern(fam) + } else if sess.target.target.options.is_like_windows { + InternedString::new("windows") + } else { + InternedString::new("unix") }; let mk = attr::mk_name_value_item_str; let mut ret = vec![ // Target bindings. - attr::mk_word_item(fam.clone()), - mk(InternedString::new("target_os"), intern(os)), - mk(InternedString::new("target_family"), fam), - mk(InternedString::new("target_arch"), intern(arch)), - mk(InternedString::new("target_endian"), intern(end)), - mk(InternedString::new("target_pointer_width"), intern(wordsz)), - mk(InternedString::new("target_env"), intern(env)), - mk(InternedString::new("target_vendor"), intern(vendor)), + mk(InternedString::new("target_os"), intern(os)), + mk(InternedString::new("target_family"), fam.clone()), + mk(InternedString::new("target_arch"), intern(arch)), + mk(InternedString::new("target_endian"), intern(end)), + mk(InternedString::new("target_pointer_width"), intern(wordsz)), + mk(InternedString::new("target_env"), intern(env)), + mk(InternedString::new("target_vendor"), intern(vendor)), ]; + match &fam[..] { + "windows" | "unix" => ret.push(attr::mk_word_item(fam)), + _ => (), + } if sess.opts.debug_assertions { ret.push(attr::mk_word_item(InternedString::new("debug_assertions"))); } diff --git a/src/librustc/util/common.rs b/src/librustc/util/common.rs index a6ca6a45f9568..74b92318f2774 100644 --- a/src/librustc/util/common.rs +++ b/src/librustc/util/common.rs @@ -96,25 +96,30 @@ fn get_resident() -> Option { } #[cfg(windows)] +#[cfg_attr(stage0, allow(improper_ctypes))] fn get_resident() -> Option { - use libc::{BOOL, DWORD, HANDLE, SIZE_T, GetCurrentProcess}; + type BOOL = i32; + type DWORD = u32; + type HANDLE = *mut u8; + use libc::size_t; use std::mem; #[repr(C)] #[allow(non_snake_case)] struct PROCESS_MEMORY_COUNTERS { cb: DWORD, PageFaultCount: DWORD, - PeakWorkingSetSize: SIZE_T, - WorkingSetSize: SIZE_T, - QuotaPeakPagedPoolUsage: SIZE_T, - QuotaPagedPoolUsage: SIZE_T, - QuotaPeakNonPagedPoolUsage: SIZE_T, - QuotaNonPagedPoolUsage: SIZE_T, - PagefileUsage: SIZE_T, - PeakPagefileUsage: SIZE_T, + PeakWorkingSetSize: size_t, + WorkingSetSize: size_t, + QuotaPeakPagedPoolUsage: size_t, + QuotaPagedPoolUsage: size_t, + QuotaPeakNonPagedPoolUsage: size_t, + QuotaNonPagedPoolUsage: size_t, + PagefileUsage: size_t, + PeakPagefileUsage: size_t, } type PPROCESS_MEMORY_COUNTERS = *mut PROCESS_MEMORY_COUNTERS; #[link(name = "psapi")] extern "system" { + fn GetCurrentProcess() -> HANDLE; fn GetProcessMemoryInfo(Process: HANDLE, ppsmemCounters: PPROCESS_MEMORY_COUNTERS, cb: DWORD) -> BOOL; diff --git a/src/librustc_back/target/mod.rs b/src/librustc_back/target/mod.rs index 078a767c0ca3b..0d53b0db34ec1 100644 --- a/src/librustc_back/target/mod.rs +++ b/src/librustc_back/target/mod.rs @@ -150,6 +150,8 @@ pub struct TargetOptions { pub staticlib_prefix: String, /// String to append to the name of every static library. Defaults to ".a". pub staticlib_suffix: String, + /// OS family to use for conditional compilation. Valid options: "unix", "windows". + pub target_family: Option, /// Whether the target toolchain is like OSX's. Only useful for compiling against iOS/OS X, in /// particular running dsymutil and some other stuff like `-dead_strip`. Defaults to false. pub is_like_osx: bool, @@ -219,6 +221,7 @@ impl Default for TargetOptions { exe_suffix: "".to_string(), staticlib_prefix: "lib".to_string(), staticlib_suffix: ".a".to_string(), + target_family: None, is_like_osx: false, is_like_windows: false, is_like_android: false, @@ -339,6 +342,7 @@ impl Target { key!(disable_redzone, bool); key!(eliminate_frame_pointer, bool); key!(function_sections, bool); + key!(target_family, optional); key!(is_like_osx, bool); key!(is_like_windows, bool); key!(linker_is_gnu, bool); diff --git a/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs b/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs index cf9de56c8dbf7..90c9361623252 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs @@ -44,7 +44,7 @@ pub fn gather_decl<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, pub fn gather_move_from_expr<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, move_data: &MoveData<'tcx>, - move_error_collector: &MoveErrorCollector<'tcx>, + move_error_collector: &mut MoveErrorCollector<'tcx>, move_expr_id: ast::NodeId, cmt: mc::cmt<'tcx>, move_reason: euv::MoveReason) { @@ -63,7 +63,7 @@ pub fn gather_move_from_expr<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, pub fn gather_match_variant<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, move_data: &MoveData<'tcx>, - _move_error_collector: &MoveErrorCollector<'tcx>, + _move_error_collector: &mut MoveErrorCollector<'tcx>, move_pat: &hir::Pat, cmt: mc::cmt<'tcx>, mode: euv::MatchMode) { @@ -94,7 +94,7 @@ pub fn gather_match_variant<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, pub fn gather_move_from_pat<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, move_data: &MoveData<'tcx>, - move_error_collector: &MoveErrorCollector<'tcx>, + move_error_collector: &mut MoveErrorCollector<'tcx>, move_pat: &hir::Pat, cmt: mc::cmt<'tcx>) { let pat_span_path_opt = match move_pat.node { @@ -115,7 +115,7 @@ pub fn gather_move_from_pat<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, fn gather_move<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, move_data: &MoveData<'tcx>, - move_error_collector: &MoveErrorCollector<'tcx>, + move_error_collector: &mut MoveErrorCollector<'tcx>, move_info: GatherMoveInfo<'tcx>) { debug!("gather_move(move_id={}, cmt={:?})", move_info.id, move_info.cmt); diff --git a/src/librustc_borrowck/borrowck/gather_loans/mod.rs b/src/librustc_borrowck/borrowck/gather_loans/mod.rs index 99e4bb60aff28..de0b1fddc2006 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/mod.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/mod.rs @@ -86,7 +86,7 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for GatherLoanCtxt<'a, 'tcx> { match mode { euv::Move(move_reason) => { gather_moves::gather_move_from_expr( - self.bccx, &self.move_data, &self.move_error_collector, + self.bccx, &self.move_data, &mut self.move_error_collector, consume_id, cmt, move_reason); } euv::Copy => { } @@ -104,7 +104,7 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for GatherLoanCtxt<'a, 'tcx> { if let Categorization::Downcast(..) = cmt.cat { gather_moves::gather_match_variant( - self.bccx, &self.move_data, &self.move_error_collector, + self.bccx, &self.move_data, &mut self.move_error_collector, matched_pat, cmt, mode); } } @@ -124,7 +124,7 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for GatherLoanCtxt<'a, 'tcx> { } gather_moves::gather_move_from_pat( - self.bccx, &self.move_data, &self.move_error_collector, + self.bccx, &self.move_data, &mut self.move_error_collector, consume_pat, cmt); } diff --git a/src/librustc_borrowck/borrowck/gather_loans/move_error.rs b/src/librustc_borrowck/borrowck/gather_loans/move_error.rs index fb703a9f9bca5..a56a03174f609 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/move_error.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/move_error.rs @@ -13,28 +13,27 @@ use rustc::middle::mem_categorization as mc; use rustc::middle::mem_categorization::Categorization; use rustc::middle::mem_categorization::InteriorOffsetKind as Kind; use rustc::middle::ty; -use std::cell::RefCell; use syntax::ast; use syntax::codemap; use rustc_front::hir; pub struct MoveErrorCollector<'tcx> { - errors: RefCell>> + errors: Vec> } impl<'tcx> MoveErrorCollector<'tcx> { pub fn new() -> MoveErrorCollector<'tcx> { MoveErrorCollector { - errors: RefCell::new(Vec::new()) + errors: Vec::new() } } - pub fn add_error(&self, error: MoveError<'tcx>) { - self.errors.borrow_mut().push(error); + pub fn add_error(&mut self, error: MoveError<'tcx>) { + self.errors.push(error); } pub fn report_potential_errors<'a>(&self, bccx: &BorrowckCtxt<'a, 'tcx>) { - report_move_errors(bccx, &*self.errors.borrow()) + report_move_errors(bccx, &self.errors) } } diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs index e8179a8cee0cc..ccb48ed2edfaa 100644 --- a/src/librustc_borrowck/borrowck/mod.rs +++ b/src/librustc_borrowck/borrowck/mod.rs @@ -1015,7 +1015,18 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { self by mutable reference"); } } - _ => {} + _ => { + if let Categorization::Local(local_id) = err.cmt.cat { + let span = self.tcx.map.span(local_id); + if let Ok(snippet) = self.tcx.sess.codemap().span_to_snippet(span) { + self.tcx.sess.span_suggestion( + span, + &format!("to make the {} mutable, use `mut` as shown:", + self.cmt_to_string(&err.cmt)), + format!("mut {}", snippet)); + } + } + } } } diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index 69c4dcb0a197c..2d7f5544402a2 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -11,6 +11,7 @@ use rustc::front; use rustc::front::map as hir_map; use rustc_mir as mir; +use rustc_mir::mir_map::MirMap; use rustc::session::Session; use rustc::session::config::{self, Input, OutputFilenames, OutputType}; use rustc::session::search_paths::PathKind; @@ -22,6 +23,7 @@ use rustc::middle::dependency_format; use rustc::middle; use rustc::plugin::registry::Registry; use rustc::plugin; +use rustc::util::nodemap::NodeMap; use rustc::util::common::time; use rustc_borrowck as borrowck; use rustc_resolve as resolve; @@ -50,6 +52,8 @@ use syntax::feature_gate::UnstableFeatures; use syntax::fold::Folder; use syntax::parse; use syntax::parse::token; +use syntax::util::node_count::NodeCounter; +use syntax::visit; use syntax; pub fn compile_input(sess: Session, @@ -78,27 +82,17 @@ pub fn compile_input(sess: Session, controller_entry_point!(after_parse, sess, - CompileState::state_after_parse(input, - &sess, - outdir, - &krate)); - - let outputs = build_output_filenames(input, - outdir, - output, - &krate.attrs, - &sess); - let id = link::find_crate_name(Some(&sess), - &krate.attrs, - input); - let expanded_crate - = match phase_2_configure_and_expand(&sess, - krate, - &id[..], - addl_plugins) { - None => return, - Some(k) => k - }; + CompileState::state_after_parse(input, &sess, outdir, &krate)); + + let outputs = build_output_filenames(input, outdir, output, &krate.attrs, &sess); + let id = link::find_crate_name(Some(&sess), &krate.attrs, input); + let expanded_crate = match phase_2_configure_and_expand(&sess, + krate, + &id[..], + addl_plugins) { + None => return, + Some(k) => k, + }; (outputs, expanded_crate, id) }; @@ -137,51 +131,55 @@ pub fn compile_input(sess: Session, front::check_attr::check_crate(&sess, &expanded_crate); }); - time(sess.time_passes(), "early lint checks", || { - lint::check_ast_crate(&sess, &expanded_crate) - }); + time(sess.time_passes(), + "early lint checks", + || lint::check_ast_crate(&sess, &expanded_crate)); phase_3_run_analysis_passes(&sess, ast_map, &arenas, &id, control.make_glob_map, - |tcx, analysis| { - - { - let state = CompileState::state_after_analysis(input, - &tcx.sess, - outdir, - &expanded_crate, - tcx.map.krate(), - &analysis, - tcx, - &lcx, - &id); - (control.after_analysis.callback)(state); - - tcx.sess.abort_if_errors(); - if control.after_analysis.stop == Compilation::Stop { - return Err(()); - } - } - - if log_enabled!(::log::INFO) { - println!("Pre-trans"); - tcx.print_debug_stats(); - } - let trans = phase_4_translate_to_llvm(tcx, analysis); - - if log_enabled!(::log::INFO) { - println!("Post-trans"); - tcx.print_debug_stats(); - } - - // Discard interned strings as they are no longer required. - token::get_ident_interner().clear(); - - Ok((outputs, trans)) - }) + |tcx, mir_map, analysis| { + + { + let state = + CompileState::state_after_analysis(input, + &tcx.sess, + outdir, + &expanded_crate, + tcx.map.krate(), + &analysis, + &mir_map, + tcx, + &lcx, + &id); + (control.after_analysis.callback)(state); + + tcx.sess.abort_if_errors(); + if control.after_analysis.stop == Compilation::Stop { + return Err(()); + } + } + + if log_enabled!(::log::INFO) { + println!("Pre-trans"); + tcx.print_debug_stats(); + } + let trans = phase_4_translate_to_llvm(tcx, + &mir_map, + analysis); + + if log_enabled!(::log::INFO) { + println!("Post-trans"); + tcx.print_debug_stats(); + } + + // Discard interned strings as they are no longer required. + token::get_ident_interner().clear(); + + Ok((outputs, trans)) + }) }; let (outputs, trans) = if let Ok(out) = result { @@ -194,10 +192,7 @@ pub fn compile_input(sess: Session, controller_entry_point!(after_llvm, sess, - CompileState::state_after_llvm(input, - &sess, - outdir, - &trans)); + CompileState::state_after_llvm(input, &sess, outdir, &trans)); phase_6_link_output(&sess, &trans, &outputs); } @@ -212,7 +207,7 @@ pub fn source_name(input: &Input) -> String { match *input { // FIXME (#9639): This needs to handle non-utf8 paths Input::File(ref ifile) => ifile.to_str().unwrap().to_string(), - Input::Str(_) => anon_src() + Input::Str(_) => anon_src(), } } @@ -245,7 +240,7 @@ impl<'a> CompileController<'a> { CompileController { after_parse: PhaseController::basic(), after_expand: PhaseController::basic(), - after_write_deps: PhaseController::basic(), + after_write_deps: PhaseController::basic(), after_analysis: PhaseController::basic(), after_llvm: PhaseController::basic(), make_glob_map: resolve::MakeGlobMap::No, @@ -281,6 +276,7 @@ pub struct CompileState<'a, 'ast: 'a, 'tcx: 'a> { pub expanded_crate: Option<&'a ast::Crate>, pub hir_crate: Option<&'a hir::Crate>, pub ast_map: Option<&'a hir_map::Map<'ast>>, + pub mir_map: Option<&'a MirMap<'tcx>>, pub analysis: Option<&'a ty::CrateAnalysis<'a>>, pub tcx: Option<&'a ty::ctxt<'tcx>>, pub lcx: Option<&'a LoweringContext<'a>>, @@ -304,6 +300,7 @@ impl<'a, 'ast, 'tcx> CompileState<'a, 'ast, 'tcx> { hir_crate: None, ast_map: None, analysis: None, + mir_map: None, tcx: None, lcx: None, trans: None, @@ -315,10 +312,7 @@ impl<'a, 'ast, 'tcx> CompileState<'a, 'ast, 'tcx> { out_dir: &'a Option, krate: &'a ast::Crate) -> CompileState<'a, 'ast, 'tcx> { - CompileState { - krate: Some(krate), - .. CompileState::empty(input, session, out_dir) - } + CompileState { krate: Some(krate), ..CompileState::empty(input, session, out_dir) } } fn state_after_expand(input: &'a Input, @@ -330,7 +324,7 @@ impl<'a, 'ast, 'tcx> CompileState<'a, 'ast, 'tcx> { CompileState { crate_name: Some(crate_name), expanded_crate: Some(expanded_crate), - .. CompileState::empty(input, session, out_dir) + ..CompileState::empty(input, session, out_dir) } } @@ -349,7 +343,7 @@ impl<'a, 'ast, 'tcx> CompileState<'a, 'ast, 'tcx> { krate: Some(krate), hir_crate: Some(hir_crate), lcx: Some(lcx), - .. CompileState::empty(input, session, out_dir) + ..CompileState::empty(input, session, out_dir) } } @@ -359,18 +353,20 @@ impl<'a, 'ast, 'tcx> CompileState<'a, 'ast, 'tcx> { krate: &'a ast::Crate, hir_crate: &'a hir::Crate, analysis: &'a ty::CrateAnalysis, + mir_map: &'a MirMap<'tcx>, tcx: &'a ty::ctxt<'tcx>, lcx: &'a LoweringContext<'a>, crate_name: &'a str) -> CompileState<'a, 'ast, 'tcx> { CompileState { analysis: Some(analysis), + mir_map: Some(mir_map), tcx: Some(tcx), krate: Some(krate), hir_crate: Some(hir_crate), lcx: Some(lcx), crate_name: Some(crate_name), - .. CompileState::empty(input, session, out_dir) + ..CompileState::empty(input, session, out_dir) } } @@ -380,15 +376,11 @@ impl<'a, 'ast, 'tcx> CompileState<'a, 'ast, 'tcx> { out_dir: &'a Option, trans: &'a trans::CrateTranslation) -> CompileState<'a, 'ast, 'tcx> { - CompileState { - trans: Some(trans), - .. CompileState::empty(input, session, out_dir) - } + CompileState { trans: Some(trans), ..CompileState::empty(input, session, out_dir) } } } -pub fn phase_1_parse_input(sess: &Session, cfg: ast::CrateConfig, input: &Input) - -> ast::Crate { +pub fn phase_1_parse_input(sess: &Session, cfg: ast::CrateConfig, input: &Input) -> ast::Crate { // These may be left in an incoherent state after a previous compile. // `clear_tables` and `get_ident_interner().clear()` can be used to free // memory, but they do not restore the initial state. @@ -413,6 +405,11 @@ pub fn phase_1_parse_input(sess: &Session, cfg: ast::CrateConfig, input: &Input) println!("{}", json::as_json(&krate)); } + if sess.opts.debugging_opts.input_stats { + println!("Lines of code: {}", sess.codemap().count_lines()); + println!("Pre-expansion node count: {}", count_nodes(&krate)); + } + if let Some(ref s) = sess.opts.show_span { syntax::show_span::run(sess.diagnostic(), s, &krate); } @@ -420,6 +417,12 @@ pub fn phase_1_parse_input(sess: &Session, cfg: ast::CrateConfig, input: &Input) krate } +fn count_nodes(krate: &ast::Crate) -> usize { + let mut counter = NodeCounter::new(); + visit::walk_crate(&mut counter, krate); + counter.count +} + // For continuing compilation after a parsed crate has been // modified @@ -446,24 +449,21 @@ pub fn phase_2_configure_and_expand(sess: &Session, // baz! should not use this definition unless foo is enabled. let mut feature_gated_cfgs = vec![]; - krate = time(time_passes, "configuration 1", || - syntax::config::strip_unconfigured_items(sess.diagnostic(), krate, - &mut feature_gated_cfgs)); + krate = time(time_passes, "configuration 1", || { + syntax::config::strip_unconfigured_items(sess.diagnostic(), krate, &mut feature_gated_cfgs) + }); - *sess.crate_types.borrow_mut() = - collect_crate_types(sess, &krate.attrs); - *sess.crate_metadata.borrow_mut() = - collect_crate_metadata(sess, &krate.attrs); + *sess.crate_types.borrow_mut() = collect_crate_types(sess, &krate.attrs); + *sess.crate_metadata.borrow_mut() = collect_crate_metadata(sess, &krate.attrs); time(time_passes, "recursion limit", || { middle::recursion_limit::update_recursion_limit(sess, &krate); }); time(time_passes, "gated macro checking", || { - let features = - syntax::feature_gate::check_crate_macros(sess.codemap(), - &sess.parse_sess.span_diagnostic, - &krate); + let features = syntax::feature_gate::check_crate_macros(sess.codemap(), + &sess.parse_sess.span_diagnostic, + &krate); // these need to be set "early" so that expansion sees `quote` if enabled. *sess.features.borrow_mut() = features; @@ -471,27 +471,29 @@ pub fn phase_2_configure_and_expand(sess: &Session, }); - krate = time(time_passes, "crate injection", || - syntax::std_inject::maybe_inject_crates_ref(krate, - sess.opts.alt_std_name.clone())); + krate = time(time_passes, "crate injection", || { + syntax::std_inject::maybe_inject_crates_ref(krate, sess.opts.alt_std_name.clone()) + }); - let macros = time(time_passes, "macro loading", || - metadata::macro_import::read_macro_defs(sess, &krate)); + let macros = time(time_passes, + "macro loading", + || metadata::macro_import::read_macro_defs(sess, &krate)); let mut addl_plugins = Some(addl_plugins); - let registrars = time(time_passes, "plugin loading", || - plugin::load::load_plugins(sess, &krate, addl_plugins.take().unwrap())); + let registrars = time(time_passes, "plugin loading", || { + plugin::load::load_plugins(sess, &krate, addl_plugins.take().unwrap()) + }); let mut registry = Registry::new(sess, &krate); time(time_passes, "plugin registration", || { if sess.features.borrow().rustc_diagnostic_macros { registry.register_macro("__diagnostic_used", - diagnostics::plugin::expand_diagnostic_used); + diagnostics::plugin::expand_diagnostic_used); registry.register_macro("__register_diagnostic", - diagnostics::plugin::expand_register_diagnostic); + diagnostics::plugin::expand_register_diagnostic); registry.register_macro("__build_diagnostic_array", - diagnostics::plugin::expand_build_diagnostic_array); + diagnostics::plugin::expand_build_diagnostic_array); } for registrar in registrars { @@ -552,11 +554,11 @@ pub fn phase_2_configure_and_expand(sess: &Session, trace_mac: sess.opts.debugging_opts.trace_macros, }; let ret = syntax::ext::expand::expand_crate(&sess.parse_sess, - cfg, - macros, - syntax_exts, - &mut feature_gated_cfgs, - krate); + cfg, + macros, + syntax_exts, + &mut feature_gated_cfgs, + krate); if cfg!(windows) { env::set_var("PATH", &_old_path); } @@ -568,11 +570,11 @@ pub fn phase_2_configure_and_expand(sess: &Session, // much as possible (e.g. help the programmer avoid platform // specific differences) time(time_passes, "complete gated feature checking 1", || { - let features = - syntax::feature_gate::check_crate(sess.codemap(), - &sess.parse_sess.span_diagnostic, - &krate, &attributes, - sess.opts.unstable_features); + let features = syntax::feature_gate::check_crate(sess.codemap(), + &sess.parse_sess.span_diagnostic, + &krate, + &attributes, + sess.opts.unstable_features); *sess.features.borrow_mut() = features; sess.abort_if_errors(); }); @@ -580,9 +582,9 @@ pub fn phase_2_configure_and_expand(sess: &Session, // JBC: make CFG processing part of expansion to avoid this problem: // strip again, in case expansion added anything with a #[cfg]. - krate = time(time_passes, "configuration 2", || - syntax::config::strip_unconfigured_items(sess.diagnostic(), krate, - &mut feature_gated_cfgs)); + krate = time(time_passes, "configuration 2", || { + syntax::config::strip_unconfigured_items(sess.diagnostic(), krate, &mut feature_gated_cfgs) + }); time(time_passes, "gated configuration checking", || { let features = sess.features.borrow(); @@ -593,41 +595,45 @@ pub fn phase_2_configure_and_expand(sess: &Session, } }); - krate = time(time_passes, "maybe building test harness", || - syntax::test::modify_for_testing(&sess.parse_sess, - &sess.opts.cfg, - krate, - sess.diagnostic())); + krate = time(time_passes, "maybe building test harness", || { + syntax::test::modify_for_testing(&sess.parse_sess, &sess.opts.cfg, krate, sess.diagnostic()) + }); - krate = time(time_passes, "prelude injection", || - syntax::std_inject::maybe_inject_prelude(&sess.parse_sess, krate)); + krate = time(time_passes, + "prelude injection", + || syntax::std_inject::maybe_inject_prelude(&sess.parse_sess, krate)); - time(time_passes, "checking that all macro invocations are gone", || - syntax::ext::expand::check_for_macros(&sess.parse_sess, &krate)); + time(time_passes, + "checking that all macro invocations are gone", + || syntax::ext::expand::check_for_macros(&sess.parse_sess, &krate)); - time(time_passes, "checking for inline asm in case the target doesn't support it", || - middle::check_no_asm::check_crate(sess, &krate)); + time(time_passes, + "checking for inline asm in case the target doesn't support it", + || middle::check_no_asm::check_crate(sess, &krate)); // One final feature gating of the true AST that gets compiled // later, to make sure we've got everything (e.g. configuration // can insert new attributes via `cfg_attr`) time(time_passes, "complete gated feature checking 2", || { - let features = - syntax::feature_gate::check_crate(sess.codemap(), - &sess.parse_sess.span_diagnostic, - &krate, &attributes, - sess.opts.unstable_features); + let features = syntax::feature_gate::check_crate(sess.codemap(), + &sess.parse_sess.span_diagnostic, + &krate, + &attributes, + sess.opts.unstable_features); *sess.features.borrow_mut() = features; sess.abort_if_errors(); }); + if sess.opts.debugging_opts.input_stats { + println!("Post-expansion node count: {}", count_nodes(&krate)); + } + Some(krate) } -pub fn assign_node_ids(sess: &Session, - krate: ast::Crate) -> ast::Crate { +pub fn assign_node_ids(sess: &Session, krate: ast::Crate) -> ast::Crate { struct NodeIdAssigner<'a> { - sess: &'a Session + sess: &'a Session, } impl<'a> Folder for NodeIdAssigner<'a> { @@ -669,17 +675,18 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session, make_glob_map: resolve::MakeGlobMap, f: F) -> R - where F: for<'a> FnOnce(&'a ty::ctxt<'tcx>, - ty::CrateAnalysis) -> R + where F: for<'a> FnOnce(&'a ty::ctxt<'tcx>, MirMap<'tcx>, ty::CrateAnalysis) -> R { let time_passes = sess.time_passes(); let krate = ast_map.krate(); - time(time_passes, "external crate/lib resolution", || - LocalCrateReader::new(sess, &ast_map).read_crates(krate)); + time(time_passes, + "external crate/lib resolution", + || LocalCrateReader::new(sess, &ast_map).read_crates(krate)); - let lang_items = time(time_passes, "language item collection", || - middle::lang_items::collect_language_items(&sess, &ast_map)); + let lang_items = time(time_passes, + "language item collection", + || middle::lang_items::collect_language_items(&sess, &ast_map)); let resolve::CrateMap { def_map, @@ -688,34 +695,39 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session, trait_map, external_exports, glob_map, - } = - time(time_passes, "resolution", + } = time(time_passes, + "resolution", || resolve::resolve_crate(sess, &ast_map, make_glob_map)); // Discard MTWT tables that aren't required past resolution. + // FIXME: get rid of uses of MTWT tables in typeck, mir and trans and clear them if !sess.opts.debugging_opts.keep_mtwt_tables { - syntax::ext::mtwt::clear_tables(); + // syntax::ext::mtwt::clear_tables(); } - let named_region_map = time(time_passes, "lifetime resolution", - || middle::resolve_lifetime::krate(sess, krate, &def_map)); + let named_region_map = time(time_passes, + "lifetime resolution", + || middle::resolve_lifetime::krate(sess, krate, &def_map.borrow())); - time(time_passes, "looking for entry point", + time(time_passes, + "looking for entry point", || middle::entry::find_entry_point(sess, &ast_map)); - sess.plugin_registrar_fn.set( - time(time_passes, "looking for plugin registrar", || - plugin::build::find_plugin_registrar( - sess.diagnostic(), krate))); + sess.plugin_registrar_fn.set(time(time_passes, "looking for plugin registrar", || { + plugin::build::find_plugin_registrar(sess.diagnostic(), krate) + })); - let region_map = time(time_passes, "region resolution", || - middle::region::resolve_crate(sess, krate)); + let region_map = time(time_passes, + "region resolution", + || middle::region::resolve_crate(sess, krate)); - time(time_passes, "loop checking", || - middle::check_loop::check_crate(sess, krate)); + time(time_passes, + "loop checking", + || middle::check_loop::check_crate(sess, krate)); - time(time_passes, "static item recursion checking", || - middle::check_static_recursion::check_crate(sess, krate, &def_map, &ast_map)); + time(time_passes, + "static item recursion checking", + || middle::check_static_recursion::check_crate(sess, krate, &def_map.borrow(), &ast_map)); ty::ctxt::create_and_enter(sess, arenas, @@ -728,105 +740,128 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session, stability::Index::new(krate), |tcx| { - // passes are timed inside typeck - typeck::check_crate(tcx, trait_map); - - time(time_passes, "const checking", || - middle::check_const::check_crate(tcx)); - - let (exported_items, public_items) = - time(time_passes, "privacy checking", || - rustc_privacy::check_crate(tcx, &export_map, external_exports)); - - // Do not move this check past lint - time(time_passes, "stability index", || - tcx.stability.borrow_mut().build(tcx, krate, &public_items)); - - time(time_passes, "intrinsic checking", || - middle::intrinsicck::check_crate(tcx)); - - time(time_passes, "effect checking", || - middle::effect::check_crate(tcx)); - - time(time_passes, "match checking", || - middle::check_match::check_crate(tcx)); - - match tcx.sess.opts.unstable_features { - UnstableFeatures::Disallow => { - // use this as a shorthand for beta/stable, and skip - // MIR construction there until known regressions are - // addressed - } - UnstableFeatures::Allow | UnstableFeatures::Cheat => { - let _mir_map = - time(time_passes, "MIR dump", || - mir::mir_map::build_mir_for_crate(tcx)); - } - } - - time(time_passes, "liveness checking", || - middle::liveness::check_crate(tcx)); - - time(time_passes, "borrow checking", || - borrowck::check_crate(tcx)); - - time(time_passes, "rvalue checking", || - middle::check_rvalues::check_crate(tcx, krate)); - - // Avoid overwhelming user with errors if type checking failed. - // I'm not sure how helpful this is, to be honest, but it avoids a - // lot of annoying errors in the compile-fail tests (basically, - // lint warnings and so on -- kindck used to do this abort, but - // kindck is gone now). -nmatsakis - tcx.sess.abort_if_errors(); - - let reachable_map = - time(time_passes, "reachability checking", || - reachable::find_reachable(tcx, &exported_items)); - - time(time_passes, "death checking", || { - middle::dead::check_crate(tcx, - &exported_items, - &reachable_map) - }); - - let ref lib_features_used = - time(time_passes, "stability checking", || - stability::check_unstable_api_usage(tcx)); - - time(time_passes, "unused lib feature checking", || - stability::check_unused_or_stable_features( - &tcx.sess, lib_features_used)); - - time(time_passes, "lint checking", || - lint::check_crate(tcx, krate, &exported_items)); - - // The above three passes generate errors w/o aborting - tcx.sess.abort_if_errors(); - - f(tcx, ty::CrateAnalysis { - export_map: export_map, - exported_items: exported_items, - public_items: public_items, - reachable: reachable_map, - name: name, - glob_map: glob_map, - }) - }) + // passes are timed inside typeck + typeck::check_crate(tcx, trait_map); + + time(time_passes, + "const checking", + || middle::check_const::check_crate(tcx)); + + let (exported_items, public_items) = + time(time_passes, "privacy checking", || { + rustc_privacy::check_crate(tcx, + &export_map, + external_exports) + }); + + // Do not move this check past lint + time(time_passes, "stability index", || { + tcx.stability.borrow_mut().build(tcx, krate, &public_items) + }); + + time(time_passes, + "intrinsic checking", + || middle::intrinsicck::check_crate(tcx)); + + time(time_passes, + "effect checking", + || middle::effect::check_crate(tcx)); + + time(time_passes, + "match checking", + || middle::check_match::check_crate(tcx)); + + let mir_map = match tcx.sess.opts.unstable_features { + UnstableFeatures::Disallow => { + // use this as a shorthand for beta/stable, and skip + // MIR construction there until known regressions are + // addressed + NodeMap() + } + UnstableFeatures::Allow | UnstableFeatures::Cheat => { + time(time_passes, + "MIR dump", + || mir::mir_map::build_mir_for_crate(tcx)) + } + }; + + time(time_passes, + "liveness checking", + || middle::liveness::check_crate(tcx)); + + time(time_passes, + "borrow checking", + || borrowck::check_crate(tcx)); + + time(time_passes, + "rvalue checking", + || middle::check_rvalues::check_crate(tcx, krate)); + + // Avoid overwhelming user with errors if type checking failed. + // I'm not sure how helpful this is, to be honest, but it avoids + // a + // lot of annoying errors in the compile-fail tests (basically, + // lint warnings and so on -- kindck used to do this abort, but + // kindck is gone now). -nmatsakis + tcx.sess.abort_if_errors(); + + let reachable_map = + time(time_passes, + "reachability checking", + || reachable::find_reachable(tcx, &exported_items)); + + time(time_passes, "death checking", || { + middle::dead::check_crate(tcx, + &exported_items, + &reachable_map) + }); + + let ref lib_features_used = + time(time_passes, + "stability checking", + || stability::check_unstable_api_usage(tcx)); + + time(time_passes, "unused lib feature checking", || { + stability::check_unused_or_stable_features(&tcx.sess, + lib_features_used) + }); + + time(time_passes, + "lint checking", + || lint::check_crate(tcx, krate, &exported_items)); + + // The above three passes generate errors w/o aborting + tcx.sess.abort_if_errors(); + + f(tcx, + mir_map, + ty::CrateAnalysis { + export_map: export_map, + exported_items: exported_items, + public_items: public_items, + reachable: reachable_map, + name: name, + glob_map: glob_map, + }) + }) } /// Run the translation phase to LLVM, after which the AST and analysis can /// be discarded. -pub fn phase_4_translate_to_llvm(tcx: &ty::ctxt, analysis: ty::CrateAnalysis) - -> trans::CrateTranslation { +pub fn phase_4_translate_to_llvm<'tcx>(tcx: &ty::ctxt<'tcx>, + mir_map: &MirMap<'tcx>, + analysis: ty::CrateAnalysis) + -> trans::CrateTranslation { let time_passes = tcx.sess.time_passes(); - time(time_passes, "resolving dependency formats", || - dependency_format::calculate(&tcx.sess)); + time(time_passes, + "resolving dependency formats", + || dependency_format::calculate(&tcx.sess)); // Option dance to work around the lack of stack once closures. - time(time_passes, "translation", move || - trans::trans_crate(tcx, analysis)) + time(time_passes, + "translation", + move || trans::trans_crate(tcx, mir_map, analysis)) } /// Run LLVM itself, producing a bitcode file, assembly file or object file @@ -837,8 +872,9 @@ pub fn phase_5_run_llvm_passes(sess: &Session, if sess.opts.cg.no_integrated_as { let mut map = HashMap::new(); map.insert(OutputType::Assembly, None); - time(sess.time_passes(), "LLVM passes", || - write::run_passes(sess, trans, &map, outputs)); + time(sess.time_passes(), + "LLVM passes", + || write::run_passes(sess, trans, &map, outputs)); write::run_assembler(sess, outputs); @@ -847,11 +883,9 @@ pub fn phase_5_run_llvm_passes(sess: &Session, fs::remove_file(&outputs.temp_path(OutputType::Assembly)).unwrap(); } } else { - time(sess.time_passes(), "LLVM passes", || - write::run_passes(sess, - trans, - &sess.opts.output_types, - outputs)); + time(sess.time_passes(), + "LLVM passes", + || write::run_passes(sess, trans, &sess.opts.output_types, outputs)); } sess.abort_if_errors(); @@ -862,11 +896,9 @@ pub fn phase_5_run_llvm_passes(sess: &Session, pub fn phase_6_link_output(sess: &Session, trans: &trans::CrateTranslation, outputs: &OutputFilenames) { - time(sess.time_passes(), "linking", || - link::link_binary(sess, - trans, - outputs, - &trans.link.crate_name)); + time(sess.time_passes(), + "linking", + || link::link_binary(sess, trans, outputs, &trans.link.crate_name)); } fn escape_dep_filename(filename: &str) -> String { @@ -882,96 +914,101 @@ fn write_out_deps(sess: &Session, outputs: &OutputFilenames, id: &str) { match *output_type { OutputType::Exe => { for output in sess.crate_types.borrow().iter() { - let p = link::filename_for_input(sess, *output, id, - outputs); + let p = link::filename_for_input(sess, *output, id, outputs); out_filenames.push(p); } } - _ => { out_filenames.push(file); } + _ => { + out_filenames.push(file); + } } } // Write out dependency rules to the dep-info file if requested if !sess.opts.output_types.contains_key(&OutputType::DepInfo) { - return + return; } let deps_filename = outputs.path(OutputType::DepInfo); - let result = (|| -> io::Result<()> { - // Build a list of files used to compile the output and - // write Makefile-compatible dependency rules - let files: Vec = sess.codemap().files.borrow() - .iter() - .filter(|fmap| fmap.is_real_file()) - .filter(|fmap| !fmap.is_imported()) - .map(|fmap| escape_dep_filename(&fmap.name)) - .collect(); - let mut file = try!(fs::File::create(&deps_filename)); - for path in &out_filenames { - try!(write!(file, - "{}: {}\n\n", path.display(), files.join(" "))); - } + let result = + (|| -> io::Result<()> { + // Build a list of files used to compile the output and + // write Makefile-compatible dependency rules + let files: Vec = sess.codemap() + .files + .borrow() + .iter() + .filter(|fmap| fmap.is_real_file()) + .filter(|fmap| !fmap.is_imported()) + .map(|fmap| escape_dep_filename(&fmap.name)) + .collect(); + let mut file = try!(fs::File::create(&deps_filename)); + for path in &out_filenames { + try!(write!(file, "{}: {}\n\n", path.display(), files.join(" "))); + } - // Emit a fake target for each input file to the compilation. This - // prevents `make` from spitting out an error if a file is later - // deleted. For more info see #28735 - for path in files { - try!(writeln!(file, "{}:", path)); - } - Ok(()) - })(); + // Emit a fake target for each input file to the compilation. This + // prevents `make` from spitting out an error if a file is later + // deleted. For more info see #28735 + for path in files { + try!(writeln!(file, "{}:", path)); + } + Ok(()) + })(); match result { Ok(()) => {} Err(e) => { sess.fatal(&format!("error writing dependencies to `{}`: {}", - deps_filename.display(), e)); + deps_filename.display(), + e)); } } } -pub fn collect_crate_types(session: &Session, - attrs: &[ast::Attribute]) -> Vec { +pub fn collect_crate_types(session: &Session, attrs: &[ast::Attribute]) -> Vec { // Unconditionally collect crate types from attributes to make them used - let attr_types: Vec = attrs.iter().filter_map(|a| { - if a.check_name("crate_type") { - match a.value_str() { - Some(ref n) if *n == "rlib" => { - Some(config::CrateTypeRlib) - } - Some(ref n) if *n == "dylib" => { - Some(config::CrateTypeDylib) - } - Some(ref n) if *n == "lib" => { - Some(config::default_lib_output()) - } - Some(ref n) if *n == "staticlib" => { - Some(config::CrateTypeStaticlib) - } - Some(ref n) if *n == "bin" => Some(config::CrateTypeExecutable), - Some(_) => { - session.add_lint(lint::builtin::UNKNOWN_CRATE_TYPES, - ast::CRATE_NODE_ID, - a.span, - "invalid `crate_type` \ - value".to_string()); - None - } - _ => { - session.span_err(a.span, "`crate_type` requires a value"); - session.note("for example: `#![crate_type=\"lib\"]`"); - None - } - } - } else { - None - } - }).collect(); + let attr_types: Vec = + attrs.iter() + .filter_map(|a| { + if a.check_name("crate_type") { + match a.value_str() { + Some(ref n) if *n == "rlib" => { + Some(config::CrateTypeRlib) + } + Some(ref n) if *n == "dylib" => { + Some(config::CrateTypeDylib) + } + Some(ref n) if *n == "lib" => { + Some(config::default_lib_output()) + } + Some(ref n) if *n == "staticlib" => { + Some(config::CrateTypeStaticlib) + } + Some(ref n) if *n == "bin" => Some(config::CrateTypeExecutable), + Some(_) => { + session.add_lint(lint::builtin::UNKNOWN_CRATE_TYPES, + ast::CRATE_NODE_ID, + a.span, + "invalid `crate_type` value".to_string()); + None + } + _ => { + session.span_err(a.span, "`crate_type` requires a value"); + session.note("for example: `#![crate_type=\"lib\"]`"); + None + } + } + } else { + None + } + }) + .collect(); // If we're generating a test executable, then ignore all other output // styles at all other locations if session.opts.test { - return vec!(config::CrateTypeExecutable) + return vec![config::CrateTypeExecutable]; } // Only check command line flags if present. If no types are specified by @@ -987,21 +1024,22 @@ pub fn collect_crate_types(session: &Session, base.dedup(); } - base.into_iter().filter(|crate_type| { - let res = !link::invalid_output_for_target(session, *crate_type); + base.into_iter() + .filter(|crate_type| { + let res = !link::invalid_output_for_target(session, *crate_type); - if !res { - session.warn(&format!("dropping unsupported crate type `{}` \ - for target `{}`", - *crate_type, session.opts.target_triple)); - } + if !res { + session.warn(&format!("dropping unsupported crate type `{}` for target `{}`", + *crate_type, + session.opts.target_triple)); + } - res - }).collect() + res + }) + .collect() } -pub fn collect_crate_metadata(session: &Session, - _attrs: &[ast::Attribute]) -> Vec { +pub fn collect_crate_metadata(session: &Session, _attrs: &[ast::Attribute]) -> Vec { session.opts.cg.metadata.clone() } @@ -1010,7 +1048,7 @@ pub fn build_output_filenames(input: &Input, ofile: &Option, attrs: &[ast::Attribute], sess: &Session) - -> OutputFilenames { + -> OutputFilenames { match *ofile { None => { // "-" as input file will cause the parser to read from stdin so we @@ -1018,13 +1056,15 @@ pub fn build_output_filenames(input: &Input, // We want to toss everything after the final '.' let dirpath = match *odir { Some(ref d) => d.clone(), - None => PathBuf::new() + None => PathBuf::new(), }; // If a crate name is present, we use it as the link name - let stem = sess.opts.crate_name.clone().or_else(|| { - attr::find_crate_name(attrs).map(|n| n.to_string()) - }).unwrap_or(input.filestem()); + let stem = sess.opts + .crate_name + .clone() + .or_else(|| attr::find_crate_name(attrs).map(|n| n.to_string())) + .unwrap_or(input.filestem()); OutputFilenames { out_directory: dirpath, @@ -1036,12 +1076,14 @@ pub fn build_output_filenames(input: &Input, } Some(ref out_file) => { - let unnamed_output_types = sess.opts.output_types.values() + let unnamed_output_types = sess.opts + .output_types + .values() .filter(|a| a.is_none()) .count(); let ofile = if unnamed_output_types > 1 { - sess.warn("ignoring specified output filename because multiple \ - outputs were requested"); + sess.warn("ignoring specified output filename because multiple outputs were \ + requested"); None } else { Some(out_file.clone()) @@ -1054,8 +1096,11 @@ pub fn build_output_filenames(input: &Input, OutputFilenames { out_directory: out_file.parent().unwrap_or(cur_dir).to_path_buf(), - out_filestem: out_file.file_stem().unwrap_or(OsStr::new("")) - .to_str().unwrap().to_string(), + out_filestem: out_file.file_stem() + .unwrap_or(OsStr::new("")) + .to_str() + .unwrap() + .to_string(), single_output_file: ofile, extra: sess.opts.cg.extra_filename.clone(), outputs: sess.opts.output_types.clone(), diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index ce40d9b53ff0a..63326c538c915 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -51,8 +51,10 @@ extern crate rustc_trans; extern crate rustc_typeck; extern crate serialize; extern crate rustc_llvm as llvm; -#[macro_use] extern crate log; -#[macro_use] extern crate syntax; +#[macro_use] +extern crate log; +#[macro_use] +extern crate syntax; pub use syntax::diagnostic; @@ -94,8 +96,8 @@ pub mod pretty; pub mod target_features; -const BUG_REPORT_URL: &'static str = - "https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.md#bug-reports"; +const BUG_REPORT_URL: &'static str = "https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.\ + md#bug-reports"; pub fn run(args: Vec) -> isize { @@ -105,8 +107,7 @@ pub fn run(args: Vec) -> isize { // Parse args and run the compiler. This is the primary entry point for rustc. // See comments on CompilerCalls below for details about the callbacks argument. -pub fn run_compiler<'a>(args: &[String], - callbacks: &mut CompilerCalls<'a>) { +pub fn run_compiler<'a>(args: &[String], callbacks: &mut CompilerCalls<'a>) { macro_rules! do_or_return {($expr: expr) => { match $expr { Compilation::Stop => return, @@ -116,7 +117,7 @@ pub fn run_compiler<'a>(args: &[String], let matches = match handle_options(args.to_vec()) { Some(matches) => matches, - None => return + None => return, }; let sopts = config::build_session_options(&matches); @@ -130,8 +131,8 @@ pub fn run_compiler<'a>(args: &[String], Some((input, input_file_path)) => callbacks.some_input(input, input_file_path), None => match callbacks.no_input(&matches, &sopts, &odir, &ofile, &descriptions) { Some((input, input_file_path)) => (input, input_file_path), - None => return - } + None => return, + }, }; let mut sess = build_session(sopts, input_file_path, descriptions); @@ -152,7 +153,9 @@ pub fn run_compiler<'a>(args: &[String], pretty::pretty_print_input(sess, cfg, &input, ppm, opt_uii, ofile); return; } - None => {/* continue */ } + None => { + // continue + } } let plugins = sess.opts.debugging_opts.extra_plugins.clone(); @@ -176,7 +179,8 @@ fn make_input(free_matches: &[String]) -> Option<(Input, Option)> { io::stdin().read_to_string(&mut src).unwrap(); Some((Input::Str(src), None)) } else { - Some((Input::File(PathBuf::from(ifile)), Some(PathBuf::from(ifile)))) + Some((Input::File(PathBuf::from(ifile)), + Some(PathBuf::from(ifile)))) } } else { None @@ -194,7 +198,7 @@ impl Compilation { pub fn and_then Compilation>(self, next: F) -> Compilation { match self { Compilation::Stop => Compilation::Stop, - Compilation::Continue => next() + Compilation::Continue => next(), } } } @@ -229,7 +233,9 @@ pub trait CompilerCalls<'a> { // Called after we extract the input from the arguments. Gives the implementer // an opportunity to change the inputs or to add some custom input handling. // The default behaviour is to simply pass through the inputs. - fn some_input(&mut self, input: Input, input_path: Option) + fn some_input(&mut self, + input: Input, + input_path: Option) -> (Input, Option) { (input, input_path) } @@ -269,7 +275,8 @@ pub trait CompilerCalls<'a> { None } - // Create a CompilController struct for controlling the behaviour of compilation. + // Create a CompilController struct for controlling the behaviour of + // compilation. fn build_controller(&mut self, &Session) -> CompileController<'a>; } @@ -300,8 +307,8 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls { } } return Compilation::Stop; - }, - None => () + } + None => (), } return Compilation::Continue; @@ -331,7 +338,7 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls { early_error(sopts.color, "no input filename given"); } 1 => panic!("make_input should have provided valid inputs"), - _ => early_error(sopts.color, "multiple input filenames provided") + _ => early_error(sopts.color, "multiple input filenames provided"), } None @@ -366,15 +373,14 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls { odir: &Option, ofile: &Option) -> Compilation { - RustcDefaultCalls::print_crate_info(sess, Some(input), odir, ofile).and_then( - || RustcDefaultCalls::list_metadata(sess, matches, input)) + RustcDefaultCalls::print_crate_info(sess, Some(input), odir, ofile) + .and_then(|| RustcDefaultCalls::list_metadata(sess, matches, input)) } fn build_controller(&mut self, sess: &Session) -> CompileController<'a> { let mut control = CompileController::basic(); - if sess.opts.parse_only || - sess.opts.show_span.is_some() || + if sess.opts.parse_only || sess.opts.show_span.is_some() || sess.opts.debugging_opts.ast_json_noexpand { control.after_parse.stop = Compilation::Stop; } @@ -393,14 +399,14 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls { if sess.opts.debugging_opts.save_analysis { control.after_analysis.callback = box |state| { - time(state.session.time_passes(), - "save analysis", - || save::process_crate(state.tcx.unwrap(), - state.lcx.unwrap(), - state.krate.unwrap(), - state.analysis.unwrap(), - state.crate_name.unwrap(), - state.out_dir)); + time(state.session.time_passes(), "save analysis", || { + save::process_crate(state.tcx.unwrap(), + state.lcx.unwrap(), + state.krate.unwrap(), + state.analysis.unwrap(), + state.crate_name.unwrap(), + state.out_dir) + }); }; control.make_glob_map = resolve::MakeGlobMap::Yes; } @@ -410,19 +416,15 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls { } impl RustcDefaultCalls { - pub fn list_metadata(sess: &Session, - matches: &getopts::Matches, - input: &Input) - -> Compilation { + pub fn list_metadata(sess: &Session, matches: &getopts::Matches, input: &Input) -> Compilation { let r = matches.opt_strs("Z"); if r.contains(&("ls".to_string())) { match input { &Input::File(ref ifile) => { let path = &(*ifile); let mut v = Vec::new(); - metadata::loader::list_file_metadata(&sess.target.target, - path, - &mut v).unwrap(); + metadata::loader::list_file_metadata(&sess.target.target, path, &mut v) + .unwrap(); println!("{}", String::from_utf8(v).unwrap()); } &Input::Str(_) => { @@ -456,26 +458,21 @@ impl RustcDefaultCalls { None => early_error(sess.opts.color, "no input file provided"), }; let attrs = attrs.as_ref().unwrap(); - let t_outputs = driver::build_output_filenames(input, - odir, - ofile, - attrs, - sess); - let id = link::find_crate_name(Some(sess), - attrs, - input); + let t_outputs = driver::build_output_filenames(input, odir, ofile, attrs, sess); + let id = link::find_crate_name(Some(sess), attrs, input); if *req == PrintRequest::CrateName { println!("{}", id); - continue + continue; } let crate_types = driver::collect_crate_types(sess, attrs); let metadata = driver::collect_crate_metadata(sess, attrs); *sess.crate_metadata.borrow_mut() = metadata; for &style in &crate_types { - let fname = link::filename_for_input(sess, style, &id, - &t_outputs); - println!("{}", fname.file_name().unwrap() - .to_string_lossy()); + let fname = link::filename_for_input(sess, style, &id, &t_outputs); + println!("{}", + fname.file_name() + .unwrap() + .to_string_lossy()); } } } @@ -503,9 +500,13 @@ pub fn commit_date_str() -> Option<&'static str> { pub fn version(binary: &str, matches: &getopts::Matches) { let verbose = matches.opt_present("verbose"); - println!("{} {}", binary, option_env!("CFG_VERSION").unwrap_or("unknown version")); + println!("{} {}", + binary, + option_env!("CFG_VERSION").unwrap_or("unknown version")); if verbose { - fn unw(x: Option<&str>) -> &str { x.unwrap_or("unknown") } + fn unw(x: Option<&str>) -> &str { + x.unwrap_or("unknown") + } println!("binary: {}", binary); println!("commit-hash: {}", unw(commit_hash_str())); println!("commit-date: {}", unw(commit_date_str())); @@ -520,32 +521,35 @@ fn usage(verbose: bool, include_unstable_options: bool) { } else { config::rustc_short_optgroups() }; - let groups : Vec<_> = groups.into_iter() - .filter(|x| include_unstable_options || x.is_stable()) - .map(|x|x.opt_group) - .collect(); + let groups: Vec<_> = groups.into_iter() + .filter(|x| include_unstable_options || x.is_stable()) + .map(|x| x.opt_group) + .collect(); let message = format!("Usage: rustc [OPTIONS] INPUT"); let extra_help = if verbose { "" } else { "\n --help -v Print the full set of options rustc accepts" }; - println!("{}\n\ -Additional help: + println!("{}\nAdditional help: -C help Print codegen options - -W help Print 'lint' options and default settings - -Z help Print internal options for debugging rustc{}\n", - getopts::usage(&message, &groups), - extra_help); + -W help \ + Print 'lint' options and default settings + -Z help Print internal \ + options for debugging rustc{}\n", + getopts::usage(&message, &groups), + extra_help); } fn describe_lints(lint_store: &lint::LintStore, loaded_plugins: bool) { println!(" Available lint options: -W Warn about - -A Allow + -A \ + Allow -D Deny - -F Forbid (deny, and deny all overrides) + -F Forbid \ + (deny, and deny all overrides) "); @@ -562,7 +566,7 @@ Available lint options: } fn sort_lint_groups(lints: Vec<(&'static str, Vec, bool)>) - -> Vec<(&'static str, Vec)> { + -> Vec<(&'static str, Vec)> { let mut lints: Vec<_> = lints.into_iter().map(|(x, y, _)| (x, y)).collect(); lints.sort_by(|&(x, _): &(&'static str, Vec), &(y, _): &(&'static str, Vec)| { @@ -572,21 +576,28 @@ Available lint options: } let (plugin, builtin): (Vec<_>, _) = lint_store.get_lints() - .iter().cloned().partition(|&(_, p)| p); + .iter() + .cloned() + .partition(|&(_, p)| p); let plugin = sort_lints(plugin); let builtin = sort_lints(builtin); let (plugin_groups, builtin_groups): (Vec<_>, _) = lint_store.get_lint_groups() - .iter().cloned().partition(|&(_, _, p)| p); + .iter() + .cloned() + .partition(|&(_, _, p)| p); let plugin_groups = sort_lint_groups(plugin_groups); let builtin_groups = sort_lint_groups(builtin_groups); - let max_name_len = plugin.iter().chain(&builtin) - .map(|&s| s.name.chars().count()) - .max().unwrap_or(0); + let max_name_len = plugin.iter() + .chain(&builtin) + .map(|&s| s.name.chars().count()) + .max() + .unwrap_or(0); let padded = |x: &str| { - let mut s = repeat(" ").take(max_name_len - x.chars().count()) - .collect::(); + let mut s = repeat(" ") + .take(max_name_len - x.chars().count()) + .collect::(); s.push_str(x); s }; @@ -599,7 +610,9 @@ Available lint options: for lint in lints { let name = lint.name_lower().replace("_", "-"); println!(" {} {:7.7} {}", - padded(&name[..]), lint.default_level.as_str(), lint.desc); + padded(&name[..]), + lint.default_level.as_str(), + lint.desc); } println!("\n"); }; @@ -608,12 +621,15 @@ Available lint options: - let max_name_len = plugin_groups.iter().chain(&builtin_groups) - .map(|&(s, _)| s.chars().count()) - .max().unwrap_or(0); + let max_name_len = plugin_groups.iter() + .chain(&builtin_groups) + .map(|&(s, _)| s.chars().count()) + .max() + .unwrap_or(0); let padded = |x: &str| { - let mut s = repeat(" ").take(max_name_len - x.chars().count()) - .collect::(); + let mut s = repeat(" ") + .take(max_name_len - x.chars().count()) + .collect::(); s.push_str(x); s }; @@ -625,10 +641,11 @@ Available lint options: let print_lint_groups = |lints: Vec<(&'static str, Vec)>| { for (name, to) in lints { let name = name.to_lowercase().replace("_", "-"); - let desc = to.into_iter().map(|x| x.as_str().replace("_", "-")) - .collect::>().join(", "); - println!(" {} {}", - padded(&name[..]), desc); + let desc = to.into_iter() + .map(|x| x.as_str().replace("_", "-")) + .collect::>() + .join(", "); + println!(" {} {}", padded(&name[..]), desc); } println!("\n"); }; @@ -657,25 +674,38 @@ Available lint options: fn describe_debug_flags() { println!("\nAvailable debug options:\n"); - for &(name, _, opt_type_desc, desc) in config::DB_OPTIONS { - let (width, extra) = match opt_type_desc { - Some(..) => (21, "=val"), - None => (25, "") - }; - println!(" -Z {:>width$}{} -- {}", name.replace("_", "-"), - extra, desc, width=width); - } + print_flag_list("-Z", config::DB_OPTIONS); } fn describe_codegen_flags() { println!("\nAvailable codegen options:\n"); - for &(name, _, opt_type_desc, desc) in config::CG_OPTIONS { + print_flag_list("-C", config::CG_OPTIONS); +} + +fn print_flag_list(cmdline_opt: &str, + flag_list: &[(&'static str, T, Option<&'static str>, &'static str)]) { + let max_len = flag_list.iter() + .map(|&(name, _, opt_type_desc, _)| { + let extra_len = match opt_type_desc { + Some(..) => 4, + None => 0, + }; + name.chars().count() + extra_len + }) + .max() + .unwrap_or(0); + + for &(name, _, opt_type_desc, desc) in flag_list { let (width, extra) = match opt_type_desc { - Some(..) => (21, "=val"), - None => (25, "") + Some(..) => (max_len - 4, "=val"), + None => (max_len, ""), }; - println!(" -C {:>width$}{} -- {}", name.replace("_", "-"), - extra, desc, width=width); + println!(" {} {:>width$}{} -- {}", + cmdline_opt, + name.replace("_", "-"), + extra, + desc, + width = width); } } @@ -699,8 +729,10 @@ pub fn handle_options(mut args: Vec) -> Option { } fn parse_all_options(args: &Vec) -> getopts::Matches { - let all_groups : Vec - = config::rustc_optgroups().into_iter().map(|x|x.opt_group).collect(); + let all_groups: Vec = config::rustc_optgroups() + .into_iter() + .map(|x| x.opt_group) + .collect(); match getopts::getopts(&args[..], &all_groups) { Ok(m) => { if !allows_unstable_options(&m) { @@ -713,15 +745,16 @@ pub fn handle_options(mut args: Vec) -> Option { &opt.opt_group.short_name }; if m.opt_present(opt_name) { - early_error(diagnostic::Auto, &format!("use of unstable option '{}' \ - requires -Z unstable-options", - opt_name)); + early_error(diagnostic::Auto, + &format!("use of unstable option '{}' requires -Z \ + unstable-options", + opt_name)); } } } m } - Err(f) => early_error(diagnostic::Auto, &f.to_string()) + Err(f) => early_error(diagnostic::Auto, &f.to_string()), } } @@ -744,7 +777,8 @@ pub fn handle_options(mut args: Vec) -> Option { }; if matches.opt_present("h") || matches.opt_present("help") { - usage(matches.opt_present("verbose"), allows_unstable_options(&matches)); + usage(matches.opt_present("verbose"), + allows_unstable_options(&matches)); return None; } @@ -763,7 +797,9 @@ pub fn handle_options(mut args: Vec) -> Option { } if cg_flags.contains(&"passes=list".to_string()) { - unsafe { ::llvm::LLVMRustPrintPasses(); } + unsafe { + ::llvm::LLVMRustPrintPasses(); + } return None; } @@ -775,20 +811,16 @@ pub fn handle_options(mut args: Vec) -> Option { Some(matches) } -fn parse_crate_attrs(sess: &Session, input: &Input) -> - Vec { +fn parse_crate_attrs(sess: &Session, input: &Input) -> Vec { let result = match *input { Input::File(ref ifile) => { - parse::parse_crate_attrs_from_file(ifile, - Vec::new(), - &sess.parse_sess) + parse::parse_crate_attrs_from_file(ifile, Vec::new(), &sess.parse_sess) } Input::Str(ref src) => { - parse::parse_crate_attrs_from_source_str( - driver::anon_src().to_string(), - src.to_string(), - Vec::new(), - &sess.parse_sess) + parse::parse_crate_attrs_from_source_str(driver::anon_src().to_string(), + src.to_string(), + Vec::new(), + &sess.parse_sess) } }; result.into_iter().collect() @@ -799,7 +831,7 @@ fn parse_crate_attrs(sess: &Session, input: &Input) -> /// /// The diagnostic emitter yielded to the procedure should be used for reporting /// errors of the compiler. -pub fn monitor(f: F) { +pub fn monitor(f: F) { const STACK_SIZE: usize = 8 * 1024 * 1024; // 8MB struct Sink(Arc>>); @@ -807,7 +839,9 @@ pub fn monitor(f: F) { fn write(&mut self, data: &[u8]) -> io::Result { Write::write(&mut *self.0.lock().unwrap(), data) } - fn flush(&mut self) -> io::Result<()> { Ok(()) } + fn flush(&mut self) -> io::Result<()> { + Ok(()) + } } let data = Arc::new(Mutex::new(Vec::new())); @@ -821,8 +855,15 @@ pub fn monitor(f: F) { cfg = cfg.stack_size(STACK_SIZE); } - match cfg.spawn(move || { io::set_panic(box err); f() }).unwrap().join() { - Ok(()) => { /* fallthrough */ } + match cfg.spawn(move || { + io::set_panic(box err); + f() + }) + .unwrap() + .join() { + Ok(()) => { + // fallthrough + } Err(value) => { // Thread panicked without emitting a fatal diagnostic if !value.is::() { @@ -831,24 +872,19 @@ pub fn monitor(f: F) { // a .span_bug or .bug call has already printed what // it wants to print. if !value.is::() { - emitter.emit( - None, - "unexpected panic", - None, - diagnostic::Bug); + emitter.emit(None, "unexpected panic", None, diagnostic::Bug); } - let xs = [ - "the compiler unexpectedly panicked. this is a bug.".to_string(), - format!("we would appreciate a bug report: {}", - BUG_REPORT_URL), - ]; + let xs = ["the compiler unexpectedly panicked. this is a bug.".to_string(), + format!("we would appreciate a bug report: {}", BUG_REPORT_URL)]; for note in &xs { emitter.emit(None, ¬e[..], None, diagnostic::Note) } if let None = env::var_os("RUST_BACKTRACE") { - emitter.emit(None, "run with `RUST_BACKTRACE=1` for a backtrace", - None, diagnostic::Note); + emitter.emit(None, + "run with `RUST_BACKTRACE=1` for a backtrace", + None, + diagnostic::Note); } println!("{}", str::from_utf8(&data.lock().unwrap()).unwrap()); diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs index a30c437197c3b..bdad13526b882 100644 --- a/src/librustc_driver/pretty.rs +++ b/src/librustc_driver/pretty.rs @@ -79,33 +79,34 @@ pub enum PpMode { pub fn parse_pretty(sess: &Session, name: &str, - extended: bool) -> (PpMode, Option) { + extended: bool) + -> (PpMode, Option) { let mut split = name.splitn(2, '='); let first = split.next().unwrap(); let opt_second = split.next(); let first = match (first, extended) { - ("normal", _) => PpmSource(PpmNormal), - ("identified", _) => PpmSource(PpmIdentified), + ("normal", _) => PpmSource(PpmNormal), + ("identified", _) => PpmSource(PpmIdentified), ("everybody_loops", true) => PpmSource(PpmEveryBodyLoops), - ("expanded", _) => PpmSource(PpmExpanded), + ("expanded", _) => PpmSource(PpmExpanded), ("expanded,identified", _) => PpmSource(PpmExpandedIdentified), ("expanded,hygiene", _) => PpmSource(PpmExpandedHygiene), - ("hir", true) => PpmHir(PpmNormal), + ("hir", true) => PpmHir(PpmNormal), ("hir,identified", true) => PpmHir(PpmIdentified), - ("hir,typed", true) => PpmHir(PpmTyped), - ("flowgraph", true) => PpmFlowGraph(PpFlowGraphMode::Default), - ("flowgraph,unlabelled", true) => PpmFlowGraph(PpFlowGraphMode::UnlabelledEdges), + ("hir,typed", true) => PpmHir(PpmTyped), + ("flowgraph", true) => PpmFlowGraph(PpFlowGraphMode::Default), + ("flowgraph,unlabelled", true) => PpmFlowGraph(PpFlowGraphMode::UnlabelledEdges), _ => { if extended { - sess.fatal(&format!( - "argument to `unpretty` must be one of `normal`, \ - `expanded`, `flowgraph[,unlabelled]=`, `identified`, \ - `expanded,identified`, `everybody_loops`, `hir`, \ - `hir,identified`, or `hir,typed`; got {}", name)); + sess.fatal(&format!("argument to `unpretty` must be one of `normal`, \ + `expanded`, `flowgraph[,unlabelled]=`, \ + `identified`, `expanded,identified`, `everybody_loops`, \ + `hir`, `hir,identified`, or `hir,typed`; got {}", + name)); } else { - sess.fatal(&format!( - "argument to `pretty` must be one of `normal`, `expanded`, \ - `identified`, or `expanded,identified`; got {}", name)); + sess.fatal(&format!("argument to `pretty` must be one of `normal`, `expanded`, \ + `identified`, or `expanded,identified`; got {}", + name)); } } }; @@ -134,21 +135,31 @@ impl PpSourceMode { sess: &'tcx Session, ast_map: Option>, payload: B, - f: F) -> A where - F: FnOnce(&PrinterSupport, B) -> A, + f: F) + -> A + where F: FnOnce(&PrinterSupport, B) -> A { match *self { PpmNormal | PpmEveryBodyLoops | PpmExpanded => { - let annotation = NoAnn { sess: sess, ast_map: ast_map }; + let annotation = NoAnn { + sess: sess, + ast_map: ast_map, + }; f(&annotation, payload) } PpmIdentified | PpmExpandedIdentified => { - let annotation = IdentifiedAnnotation { sess: sess, ast_map: ast_map }; + let annotation = IdentifiedAnnotation { + sess: sess, + ast_map: ast_map, + }; f(&annotation, payload) } PpmExpandedHygiene => { - let annotation = HygieneAnnotation { sess: sess, ast_map: ast_map }; + let annotation = HygieneAnnotation { + sess: sess, + ast_map: ast_map, + }; f(&annotation, payload) } _ => panic!("Should use call_with_pp_support_hir"), @@ -160,19 +171,23 @@ impl PpSourceMode { arenas: &'tcx ty::CtxtArenas<'tcx>, id: &str, payload: B, - f: F) -> A where - F: FnOnce(&HirPrinterSupport, B, &hir::Crate) -> A, + f: F) + -> A + where F: FnOnce(&HirPrinterSupport, B, &hir::Crate) -> A { match *self { PpmNormal => { - let annotation = NoAnn { sess: sess, ast_map: Some(ast_map.clone()) }; + let annotation = NoAnn { + sess: sess, + ast_map: Some(ast_map.clone()), + }; f(&annotation, payload, &ast_map.forest.krate) } PpmIdentified => { let annotation = IdentifiedAnnotation { sess: sess, - ast_map: Some(ast_map.clone()) + ast_map: Some(ast_map.clone()), }; f(&annotation, payload, &ast_map.forest.krate) } @@ -182,10 +197,14 @@ impl PpSourceMode { arenas, id, resolve::MakeGlobMap::No, - |tcx, _| { - let annotation = TypedAnnotation { tcx: tcx }; - f(&annotation, payload, &ast_map.forest.krate) - }) + |tcx, _, _| { + let annotation = TypedAnnotation { + tcx: tcx, + }; + f(&annotation, + payload, + &ast_map.forest.krate) + }) } _ => panic!("Should use call_with_pp_support"), } @@ -226,27 +245,35 @@ trait HirPrinterSupport<'ast>: pprust_hir::PpAnn { struct NoAnn<'ast> { sess: &'ast Session, - ast_map: Option> + ast_map: Option>, } impl<'ast> PrinterSupport<'ast> for NoAnn<'ast> { - fn sess<'a>(&'a self) -> &'a Session { self.sess } + fn sess<'a>(&'a self) -> &'a Session { + self.sess + } fn ast_map<'a>(&'a self) -> Option<&'a hir_map::Map<'ast>> { self.ast_map.as_ref() } - fn pp_ann<'a>(&'a self) -> &'a pprust::PpAnn { self } + fn pp_ann<'a>(&'a self) -> &'a pprust::PpAnn { + self + } } impl<'ast> HirPrinterSupport<'ast> for NoAnn<'ast> { - fn sess<'a>(&'a self) -> &'a Session { self.sess } + fn sess<'a>(&'a self) -> &'a Session { + self.sess + } fn ast_map<'a>(&'a self) -> Option<&'a hir_map::Map<'ast>> { self.ast_map.as_ref() } - fn pp_ann<'a>(&'a self) -> &'a pprust_hir::PpAnn { self } + fn pp_ann<'a>(&'a self) -> &'a pprust_hir::PpAnn { + self + } } impl<'ast> pprust::PpAnn for NoAnn<'ast> {} @@ -258,27 +285,27 @@ struct IdentifiedAnnotation<'ast> { } impl<'ast> PrinterSupport<'ast> for IdentifiedAnnotation<'ast> { - fn sess<'a>(&'a self) -> &'a Session { self.sess } + fn sess<'a>(&'a self) -> &'a Session { + self.sess + } fn ast_map<'a>(&'a self) -> Option<&'a hir_map::Map<'ast>> { self.ast_map.as_ref() } - fn pp_ann<'a>(&'a self) -> &'a pprust::PpAnn { self } + fn pp_ann<'a>(&'a self) -> &'a pprust::PpAnn { + self + } } impl<'ast> pprust::PpAnn for IdentifiedAnnotation<'ast> { - fn pre(&self, - s: &mut pprust::State, - node: pprust::AnnNode) -> io::Result<()> { + fn pre(&self, s: &mut pprust::State, node: pprust::AnnNode) -> io::Result<()> { match node { pprust::NodeExpr(_) => s.popen(), - _ => Ok(()) + _ => Ok(()), } } - fn post(&self, - s: &mut pprust::State, - node: pprust::AnnNode) -> io::Result<()> { + fn post(&self, s: &mut pprust::State, node: pprust::AnnNode) -> io::Result<()> { match node { pprust::NodeIdent(_) | pprust::NodeName(_) => Ok(()), @@ -308,27 +335,27 @@ impl<'ast> pprust::PpAnn for IdentifiedAnnotation<'ast> { } impl<'ast> HirPrinterSupport<'ast> for IdentifiedAnnotation<'ast> { - fn sess<'a>(&'a self) -> &'a Session { self.sess } + fn sess<'a>(&'a self) -> &'a Session { + self.sess + } fn ast_map<'a>(&'a self) -> Option<&'a hir_map::Map<'ast>> { self.ast_map.as_ref() } - fn pp_ann<'a>(&'a self) -> &'a pprust_hir::PpAnn { self } + fn pp_ann<'a>(&'a self) -> &'a pprust_hir::PpAnn { + self + } } impl<'ast> pprust_hir::PpAnn for IdentifiedAnnotation<'ast> { - fn pre(&self, - s: &mut pprust_hir::State, - node: pprust_hir::AnnNode) -> io::Result<()> { + fn pre(&self, s: &mut pprust_hir::State, node: pprust_hir::AnnNode) -> io::Result<()> { match node { pprust_hir::NodeExpr(_) => s.popen(), - _ => Ok(()) + _ => Ok(()), } } - fn post(&self, - s: &mut pprust_hir::State, - node: pprust_hir::AnnNode) -> io::Result<()> { + fn post(&self, s: &mut pprust_hir::State, node: pprust_hir::AnnNode) -> io::Result<()> { match node { pprust_hir::NodeName(_) => Ok(()), pprust_hir::NodeItem(item) => { @@ -362,19 +389,21 @@ struct HygieneAnnotation<'ast> { } impl<'ast> PrinterSupport<'ast> for HygieneAnnotation<'ast> { - fn sess<'a>(&'a self) -> &'a Session { self.sess } + fn sess<'a>(&'a self) -> &'a Session { + self.sess + } fn ast_map<'a>(&'a self) -> Option<&'a hir_map::Map<'ast>> { self.ast_map.as_ref() } - fn pp_ann<'a>(&'a self) -> &'a pprust::PpAnn { self } + fn pp_ann<'a>(&'a self) -> &'a pprust::PpAnn { + self + } } impl<'ast> pprust::PpAnn for HygieneAnnotation<'ast> { - fn post(&self, - s: &mut pprust::State, - node: pprust::AnnNode) -> io::Result<()> { + fn post(&self, s: &mut pprust::State, node: pprust::AnnNode) -> io::Result<()> { match node { pprust::NodeIdent(&ast::Ident { name: ast::Name(nm), ctxt }) => { try!(pp::space(&mut s.s)); @@ -386,7 +415,7 @@ impl<'ast> pprust::PpAnn for HygieneAnnotation<'ast> { try!(pp::space(&mut s.s)); s.synth_comment(nm.to_string()) } - _ => Ok(()) + _ => Ok(()), } } } @@ -397,37 +426,36 @@ struct TypedAnnotation<'a, 'tcx: 'a> { } impl<'b, 'tcx> HirPrinterSupport<'tcx> for TypedAnnotation<'b, 'tcx> { - fn sess<'a>(&'a self) -> &'a Session { &self.tcx.sess } + fn sess<'a>(&'a self) -> &'a Session { + &self.tcx.sess + } fn ast_map<'a>(&'a self) -> Option<&'a hir_map::Map<'tcx>> { Some(&self.tcx.map) } - fn pp_ann<'a>(&'a self) -> &'a pprust_hir::PpAnn { self } + fn pp_ann<'a>(&'a self) -> &'a pprust_hir::PpAnn { + self + } } impl<'a, 'tcx> pprust_hir::PpAnn for TypedAnnotation<'a, 'tcx> { - fn pre(&self, - s: &mut pprust_hir::State, - node: pprust_hir::AnnNode) -> io::Result<()> { + fn pre(&self, s: &mut pprust_hir::State, node: pprust_hir::AnnNode) -> io::Result<()> { match node { pprust_hir::NodeExpr(_) => s.popen(), - _ => Ok(()) + _ => Ok(()), } } - fn post(&self, - s: &mut pprust_hir::State, - node: pprust_hir::AnnNode) -> io::Result<()> { + fn post(&self, s: &mut pprust_hir::State, node: pprust_hir::AnnNode) -> io::Result<()> { match node { pprust_hir::NodeExpr(expr) => { try!(pp::space(&mut s.s)); try!(pp::word(&mut s.s, "as")); try!(pp::space(&mut s.s)); - try!(pp::word(&mut s.s, - &self.tcx.expr_ty(expr).to_string())); + try!(pp::word(&mut s.s, &self.tcx.expr_ty(expr).to_string())); s.pclose() } - _ => Ok(()) + _ => Ok(()), } } } @@ -459,9 +487,9 @@ pub enum UserIdentifiedItem { impl FromStr for UserIdentifiedItem { type Err = (); fn from_str(s: &str) -> Result { - Ok(s.parse().map(ItemViaNode).unwrap_or_else(|_| { - ItemViaPath(s.split("::").map(|s| s.to_string()).collect()) - })) + Ok(s.parse() + .map(ItemViaNode) + .unwrap_or_else(|_| ItemViaPath(s.split("::").map(|s| s.to_string()).collect()))) } } @@ -489,24 +517,22 @@ impl UserIdentifiedItem { } } - fn all_matching_node_ids<'a, 'ast>(&'a self, map: &'a hir_map::Map<'ast>) + fn all_matching_node_ids<'a, 'ast>(&'a self, + map: &'a hir_map::Map<'ast>) -> NodesMatchingUII<'a, 'ast> { match *self { - ItemViaNode(node_id) => - NodesMatchingDirect(Some(node_id).into_iter()), - ItemViaPath(ref parts) => - NodesMatchingSuffix(map.nodes_matching_suffix(&parts[..])), + ItemViaNode(node_id) => NodesMatchingDirect(Some(node_id).into_iter()), + ItemViaPath(ref parts) => NodesMatchingSuffix(map.nodes_matching_suffix(&parts[..])), } } fn to_one_node_id(self, user_option: &str, sess: &Session, map: &hir_map::Map) -> ast::NodeId { let fail_because = |is_wrong_because| -> ast::NodeId { - let message = - format!("{} needs NodeId (int) or unique \ - path suffix (b::c::d); got {}, which {}", - user_option, - self.reconstructed_input(), - is_wrong_because); + let message = format!("{} needs NodeId (int) or unique path suffix (b::c::d); got \ + {}, which {}", + user_option, + self.reconstructed_input(), + is_wrong_because); sess.fatal(&message[..]) }; @@ -608,12 +634,13 @@ impl fold::Folder for ReplaceBodyWithLoop { } fn fold_block(&mut self, b: P) -> P { - fn expr_to_block(rules: ast::BlockCheckMode, - e: Option>) -> P { + fn expr_to_block(rules: ast::BlockCheckMode, e: Option>) -> P { P(ast::Block { expr: e, - stmts: vec![], rules: rules, - id: ast::DUMMY_NODE_ID, span: codemap::DUMMY_SP, + stmts: vec![], + rules: rules, + id: ast::DUMMY_NODE_ID, + span: codemap::DUMMY_SP, }) } @@ -622,7 +649,8 @@ impl fold::Folder for ReplaceBodyWithLoop { let empty_block = expr_to_block(ast::DefaultBlock, None); let loop_expr = P(ast::Expr { node: ast::ExprLoop(empty_block, None), - id: ast::DUMMY_NODE_ID, span: codemap::DUMMY_SP + id: ast::DUMMY_NODE_ID, + span: codemap::DUMMY_SP, }); expr_to_block(b.rules, Some(loop_expr)) @@ -661,7 +689,7 @@ pub fn pretty_print_input(sess: Session, let krate = if compute_ast_map { match driver::phase_2_configure_and_expand(&sess, krate, &id[..], None) { None => return, - Some(k) => driver::assign_node_ids(&sess, k) + Some(k) => driver::assign_node_ids(&sess, k), } } else { krate @@ -681,12 +709,13 @@ pub fn pretty_print_input(sess: Session, }; let src_name = driver::source_name(input); - let src = sess.codemap().get_filemap(&src_name[..]) - .src - .as_ref() - .unwrap() - .as_bytes() - .to_vec(); + let src = sess.codemap() + .get_filemap(&src_name[..]) + .src + .as_ref() + .unwrap() + .as_bytes() + .to_vec(); let mut rdr = &src[..]; let mut out = Vec::new(); @@ -695,36 +724,39 @@ pub fn pretty_print_input(sess: Session, (PpmSource(s), _) => { // Silently ignores an identified node. let out: &mut Write = &mut out; - s.call_with_pp_support( - &sess, ast_map, box out, |annotation, out| { - debug!("pretty printing source code {:?}", s); - let sess = annotation.sess(); - pprust::print_crate(sess.codemap(), - sess.diagnostic(), - &krate, - src_name.to_string(), - &mut rdr, - out, - annotation.pp_ann(), - is_expanded) + s.call_with_pp_support(&sess, ast_map, box out, |annotation, out| { + debug!("pretty printing source code {:?}", s); + let sess = annotation.sess(); + pprust::print_crate(sess.codemap(), + sess.diagnostic(), + &krate, + src_name.to_string(), + &mut rdr, + out, + annotation.pp_ann(), + is_expanded) }) } (PpmHir(s), None) => { let out: &mut Write = &mut out; - s.call_with_pp_support_hir( - &sess, &ast_map.unwrap(), &arenas, &id, box out, |annotation, out, krate| { - debug!("pretty printing source code {:?}", s); - let sess = annotation.sess(); - pprust_hir::print_crate(sess.codemap(), - sess.diagnostic(), - krate, - src_name.to_string(), - &mut rdr, - out, - annotation.pp_ann(), - is_expanded) - }) + s.call_with_pp_support_hir(&sess, + &ast_map.unwrap(), + &arenas, + &id, + box out, + |annotation, out, krate| { + debug!("pretty printing source code {:?}", s); + let sess = annotation.sess(); + pprust_hir::print_crate(sess.codemap(), + sess.diagnostic(), + krate, + src_name.to_string(), + &mut rdr, + out, + annotation.pp_ann(), + is_expanded) + }) } (PpmHir(s), Some(uii)) => { @@ -761,6 +793,7 @@ pub fn pretty_print_input(sess: Session, debug!("pretty printing flow graph for {:?}", opt_uii); let uii = opt_uii.unwrap_or_else(|| { sess.fatal(&format!("`pretty flowgraph=..` needs NodeId (int) or + \ unique path suffix (b::c::d)")) }); @@ -768,8 +801,7 @@ pub fn pretty_print_input(sess: Session, let nodeid = uii.to_one_node_id("--pretty", &sess, &ast_map); let node = ast_map.find(nodeid).unwrap_or_else(|| { - sess.fatal(&format!("--pretty flowgraph couldn't find id: {}", - nodeid)) + sess.fatal(&format!("--pretty flowgraph couldn't find id: {}", nodeid)) }); let code = blocks::Code::from_node(node); @@ -782,33 +814,37 @@ pub fn pretty_print_input(sess: Session, &arenas, &id, resolve::MakeGlobMap::No, - |tcx, _| { - print_flowgraph(variants, tcx, code, mode, out) - }) + |tcx, _, _| { + print_flowgraph(variants, + tcx, + code, + mode, + out) + }) } None => { - let message = format!("--pretty=flowgraph needs \ - block, fn, or method; got {:?}", + let message = format!("--pretty=flowgraph needs block, fn, or method; got \ + {:?}", node); // point to what was found, if there's an // accessible span. match ast_map.opt_span(nodeid) { Some(sp) => sess.span_fatal(sp, &message[..]), - None => sess.fatal(&message[..]) + None => sess.fatal(&message[..]), } } } } - }.unwrap(); + } + .unwrap(); match ofile { None => print!("{}", String::from_utf8(out).unwrap()), Some(p) => { match File::create(&p) { Ok(mut w) => w.write_all(&out).unwrap(), - Err(e) => panic!("print-print failed to open {} due to {}", - p.display(), e), + Err(e) => panic!("print-print failed to open {} due to {}", p.display(), e), } } } @@ -818,7 +854,8 @@ fn print_flowgraph(variants: Vec, tcx: &ty::ctxt, code: blocks::Code, mode: PpFlowGraphMode, - mut out: W) -> io::Result<()> { + mut out: W) + -> io::Result<()> { let cfg = match code { blocks::BlockCode(block) => cfg::CFG::new(tcx, &*block), blocks::FnLikeCode(fn_like) => cfg::CFG::new(tcx, &*fn_like.body()), @@ -837,14 +874,14 @@ fn print_flowgraph(variants: Vec, return expand_err_details(r); } blocks::BlockCode(_) => { - tcx.sess.err("--pretty flowgraph with -Z flowgraph-print \ - annotations requires fn-like node id."); - return Ok(()) + tcx.sess.err("--pretty flowgraph with -Z flowgraph-print annotations requires \ + fn-like node id."); + return Ok(()); } blocks::FnLikeCode(fn_like) => { let fn_parts = borrowck::FnPartsWithCFG::from_fn_like(&fn_like, &cfg); - let (bccx, analysis_data) = - borrowck::build_borrowck_dataflow_data_for_fn(tcx, fn_parts); + let (bccx, analysis_data) = borrowck::build_borrowck_dataflow_data_for_fn(tcx, + fn_parts); let lcfg = borrowck_dot::DataflowLabeller { inner: lcfg, diff --git a/src/librustc_driver/target_features.rs b/src/librustc_driver/target_features.rs index ca76046acf0fb..27ffb595a4051 100644 --- a/src/librustc_driver/target_features.rs +++ b/src/librustc_driver/target_features.rs @@ -48,39 +48,30 @@ pub fn add_configuration(cfg: &mut ast::CrateConfig, sess: &Session) { fn features_contain(sess: &Session, s: &str) -> bool { - sess.target.target.options.features.contains(s) || - sess.opts.cg.target_feature.contains(s) + sess.target.target.options.features.contains(s) || sess.opts.cg.target_feature.contains(s) } pub fn has_sse(sess: &Session) -> bool { - features_contain(sess, "+sse") || - has_sse2(sess) + features_contain(sess, "+sse") || has_sse2(sess) } pub fn has_sse2(sess: &Session) -> bool { // x86-64 requires at least SSE2 support - sess.target.target.arch == "x86_64" || - features_contain(sess, "+sse2") || - has_sse3(sess) + sess.target.target.arch == "x86_64" || features_contain(sess, "+sse2") || has_sse3(sess) } pub fn has_sse3(sess: &Session) -> bool { - features_contain(sess, "+sse3") || - has_ssse3(sess) + features_contain(sess, "+sse3") || has_ssse3(sess) } pub fn has_ssse3(sess: &Session) -> bool { - features_contain(sess, "+ssse3") || - has_sse41(sess) + features_contain(sess, "+ssse3") || has_sse41(sess) } pub fn has_sse41(sess: &Session) -> bool { - features_contain(sess, "+sse4.1") || - has_sse42(sess) + features_contain(sess, "+sse4.1") || has_sse42(sess) } pub fn has_sse42(sess: &Session) -> bool { - features_contain(sess, "+sse4.2") || - has_avx(sess) + features_contain(sess, "+sse4.2") || has_avx(sess) } pub fn has_avx(sess: &Session) -> bool { - features_contain(sess, "+avx") || - has_avx2(sess) + features_contain(sess, "+avx") || has_avx2(sess) } pub fn has_avx2(sess: &Session) -> bool { features_contain(sess, "+avx2") @@ -88,11 +79,9 @@ pub fn has_avx2(sess: &Session) -> bool { pub fn has_neon(sess: &Session) -> bool { // AArch64 requires NEON support - sess.target.target.arch == "aarch64" || - features_contain(sess, "+neon") + sess.target.target.arch == "aarch64" || features_contain(sess, "+neon") } pub fn has_vfp(sess: &Session) -> bool { // AArch64 requires VFP support - sess.target.target.arch == "aarch64" || - features_contain(sess, "+vfp") + sess.target.target.arch == "aarch64" || features_contain(sess, "+vfp") } diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs index 4bbc22ef1a273..fe9cf7cc3875f 100644 --- a/src/librustc_driver/test.rs +++ b/src/librustc_driver/test.rs @@ -30,7 +30,7 @@ use rustc_typeck::middle::infer::lub::Lub; use rustc_typeck::middle::infer::glb::Glb; use rustc_typeck::middle::infer::sub::Sub; use rustc::front::map as hir_map; -use rustc::session::{self,config}; +use rustc::session::{self, config}; use syntax::{abi, ast}; use syntax::codemap; use syntax::codemap::{Span, CodeMap, DUMMY_SP}; @@ -47,19 +47,21 @@ struct Env<'a, 'tcx: 'a> { struct RH<'a> { id: ast::NodeId, - sub: &'a [RH<'a>] + sub: &'a [RH<'a>], } const EMPTY_SOURCE_STR: &'static str = "#![feature(no_core)] #![no_core]"; struct ExpectErrorEmitter { - messages: Vec + messages: Vec, } fn remove_message(e: &mut ExpectErrorEmitter, msg: &str, lvl: Level) { match lvl { - Bug | Fatal | Error => { } - Warning | Note | Help => { return; } + Bug | Fatal | Error => {} + Warning | Note | Help => { + return; + } } debug!("Error: {}", msg); @@ -68,8 +70,7 @@ fn remove_message(e: &mut ExpectErrorEmitter, msg: &str, lvl: Level) { e.messages.remove(i); } None => { - panic!("Unexpected error: {} Expected: {:?}", - msg, e.messages); + panic!("Unexpected error: {} Expected: {:?}", msg, e.messages); } } } @@ -79,41 +80,32 @@ impl Emitter for ExpectErrorEmitter { _cmsp: Option<(&codemap::CodeMap, Span)>, msg: &str, _: Option<&str>, - lvl: Level) - { + lvl: Level) { remove_message(self, msg, lvl); } - fn custom_emit(&mut self, - _cm: &codemap::CodeMap, - _sp: RenderSpan, - msg: &str, - lvl: Level) - { + fn custom_emit(&mut self, _cm: &codemap::CodeMap, _sp: RenderSpan, msg: &str, lvl: Level) { remove_message(self, msg, lvl); } } -fn errors(msgs: &[&str]) -> (Box, usize) { +fn errors(msgs: &[&str]) -> (Box, usize) { let v = msgs.iter().map(|m| m.to_string()).collect(); - (box ExpectErrorEmitter { messages: v } as Box, msgs.len()) + (box ExpectErrorEmitter { messages: v } as Box, + msgs.len()) } fn test_env(source_string: &str, - (emitter, expected_err_count): (Box, usize), - body: F) where - F: FnOnce(Env), + (emitter, expected_err_count): (Box, usize), + body: F) + where F: FnOnce(Env) { - let mut options = - config::basic_options(); + let mut options = config::basic_options(); options.debugging_opts.verbose = true; options.unstable_features = UnstableFeatures::Allow; - let codemap = - CodeMap::new(); - let diagnostic_handler = - diagnostic::Handler::with_emitter(true, emitter); - let span_diagnostic_handler = - diagnostic::SpanHandler::new(diagnostic_handler, codemap); + let codemap = CodeMap::new(); + let diagnostic_handler = diagnostic::Handler::with_emitter(true, emitter); + let span_diagnostic_handler = diagnostic::SpanHandler::new(diagnostic_handler, codemap); let sess = session::build_session_(options, None, span_diagnostic_handler); rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess)); @@ -134,7 +126,7 @@ fn test_env(source_string: &str, let lang_items = lang_items::collect_language_items(&sess, &ast_map); let resolve::CrateMap { def_map, freevars, .. } = resolve::resolve_crate(&sess, &ast_map, resolve::MakeGlobMap::No); - let named_region_map = resolve_lifetime::krate(&sess, krate, &def_map); + let named_region_map = resolve_lifetime::krate(&sess, krate, &def_map.borrow()); let region_map = region::resolve_crate(&sess, krate); ty::ctxt::create_and_enter(&sess, &arenas, @@ -146,12 +138,13 @@ fn test_env(source_string: &str, lang_items, stability::Index::new(krate), |tcx| { - let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None, false); - body(Env { infcx: &infcx }); - let free_regions = FreeRegionMap::new(); - infcx.resolve_regions_and_report_errors(&free_regions, ast::CRATE_NODE_ID); - assert_eq!(tcx.sess.err_count(), expected_err_count); - }); + let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None, false); + body(Env { infcx: &infcx }); + let free_regions = FreeRegionMap::new(); + infcx.resolve_regions_and_report_errors(&free_regions, + ast::CRATE_NODE_ID); + assert_eq!(tcx.sess.err_count(), expected_err_count); + }); } impl<'a, 'tcx> Env<'a, 'tcx> { @@ -169,15 +162,16 @@ impl<'a, 'tcx> Env<'a, 'tcx> { pub fn create_simple_region_hierarchy(&self) { // creates a region hierarchy where 1 is root, 10 and 11 are // children of 1, etc - let dscope = self.infcx.tcx.region_maps.intern_code_extent( - CodeExtentData::DestructionScope(1), region::ROOT_CODE_EXTENT); - self.create_region_hierarchy( - &RH {id: 1, - sub: &[RH {id: 10, - sub: &[]}, - RH {id: 11, - sub: &[]}]}, - dscope); + let dscope = self.infcx + .tcx + .region_maps + .intern_code_extent(CodeExtentData::DestructionScope(1), + region::ROOT_CODE_EXTENT); + self.create_region_hierarchy(&RH { + id: 1, + sub: &[RH { id: 10, sub: &[] }, RH { id: 11, sub: &[] }], + }, + dscope); } #[allow(dead_code)] // this seems like it could be useful, even if we don't use it now @@ -197,30 +191,32 @@ impl<'a, 'tcx> Env<'a, 'tcx> { assert!(idx < names.len()); for item in &m.items { if item.name.to_string() == names[idx] { - return search(this, &**item, idx+1, names); + return search(this, &**item, idx + 1, names); } } return None; } - fn search(this: &Env, - it: &hir::Item, - idx: usize, - names: &[String]) - -> Option { + fn search(this: &Env, it: &hir::Item, idx: usize, names: &[String]) -> Option { if idx == names.len() { return Some(it.id); } return match it.node { - hir::ItemUse(..) | hir::ItemExternCrate(..) | - hir::ItemConst(..) | hir::ItemStatic(..) | hir::ItemFn(..) | - hir::ItemForeignMod(..) | hir::ItemTy(..) => { + hir::ItemUse(..) | + hir::ItemExternCrate(..) | + hir::ItemConst(..) | + hir::ItemStatic(..) | + hir::ItemFn(..) | + hir::ItemForeignMod(..) | + hir::ItemTy(..) => { None } - hir::ItemEnum(..) | hir::ItemStruct(..) | - hir::ItemTrait(..) | hir::ItemImpl(..) | + hir::ItemEnum(..) | + hir::ItemStruct(..) | + hir::ItemTrait(..) | + hir::ItemImpl(..) | hir::ItemDefaultImpl(..) => { None } @@ -235,14 +231,14 @@ impl<'a, 'tcx> Env<'a, 'tcx> { pub fn make_subtype(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> bool { match infer::mk_subty(self.infcx, true, infer::Misc(DUMMY_SP), a, b) { Ok(_) => true, - Err(ref e) => panic!("Encountered error: {}", e) + Err(ref e) => panic!("Encountered error: {}", e), } } pub fn is_subtype(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> bool { match infer::can_mk_subty(self.infcx, a, b) { Ok(_) => true, - Err(_) => false + Err(_) => false, } } @@ -257,22 +253,18 @@ impl<'a, 'tcx> Env<'a, 'tcx> { self.assert_subtype(b, a); } - pub fn t_fn(&self, - input_tys: &[Ty<'tcx>], - output_ty: Ty<'tcx>) - -> Ty<'tcx> - { + pub fn t_fn(&self, input_tys: &[Ty<'tcx>], output_ty: Ty<'tcx>) -> Ty<'tcx> { let input_args = input_tys.iter().cloned().collect(); self.infcx.tcx.mk_fn(None, - self.infcx.tcx.mk_bare_fn(ty::BareFnTy { - unsafety: hir::Unsafety::Normal, - abi: abi::Rust, - sig: ty::Binder(ty::FnSig { - inputs: input_args, - output: ty::FnConverging(output_ty), - variadic: false - }) - })) + self.infcx.tcx.mk_bare_fn(ty::BareFnTy { + unsafety: hir::Unsafety::Normal, + abi: abi::Rust, + sig: ty::Binder(ty::FnSig { + inputs: input_args, + output: ty::FnConverging(output_ty), + variadic: false, + }), + })) } pub fn t_nil(&self) -> Ty<'tcx> { @@ -292,14 +284,13 @@ impl<'a, 'tcx> Env<'a, 'tcx> { space: subst::ParamSpace, index: u32, name: &'static str) - -> ty::Region - { + -> ty::Region { let name = token::intern(name); ty::ReEarlyBound(ty::EarlyBoundRegion { def_id: self.infcx.tcx.map.local_def_id(ast::DUMMY_NODE_ID), space: space, index: index, - name: name + name: name, }) } @@ -308,14 +299,12 @@ impl<'a, 'tcx> Env<'a, 'tcx> { } pub fn t_rptr(&self, r: ty::Region) -> Ty<'tcx> { - self.infcx.tcx.mk_imm_ref(self.infcx.tcx.mk_region(r), - self.tcx().types.isize) + self.infcx.tcx.mk_imm_ref(self.infcx.tcx.mk_region(r), self.tcx().types.isize) } pub fn t_rptr_late_bound(&self, id: u32) -> Ty<'tcx> { let r = self.re_late_bound_with_debruijn(id, ty::DebruijnIndex::new(1)); - self.infcx.tcx.mk_imm_ref(self.infcx.tcx.mk_region(r), - self.tcx().types.isize) + self.infcx.tcx.mk_imm_ref(self.infcx.tcx.mk_region(r), self.tcx().types.isize) } pub fn t_rptr_late_bound_with_debruijn(&self, @@ -323,37 +312,34 @@ impl<'a, 'tcx> Env<'a, 'tcx> { debruijn: ty::DebruijnIndex) -> Ty<'tcx> { let r = self.re_late_bound_with_debruijn(id, debruijn); - self.infcx.tcx.mk_imm_ref(self.infcx.tcx.mk_region(r), - self.tcx().types.isize) + self.infcx.tcx.mk_imm_ref(self.infcx.tcx.mk_region(r), self.tcx().types.isize) } pub fn t_rptr_scope(&self, id: ast::NodeId) -> Ty<'tcx> { let r = ty::ReScope(self.tcx().region_maps.node_extent(id)); - self.infcx.tcx.mk_imm_ref(self.infcx.tcx.mk_region(r), - self.tcx().types.isize) + self.infcx.tcx.mk_imm_ref(self.infcx.tcx.mk_region(r), self.tcx().types.isize) } pub fn re_free(&self, nid: ast::NodeId, id: u32) -> ty::Region { ty::ReFree(ty::FreeRegion { scope: self.tcx().region_maps.item_extent(nid), - bound_region: ty::BrAnon(id) + bound_region: ty::BrAnon(id), }) } pub fn t_rptr_free(&self, nid: ast::NodeId, id: u32) -> Ty<'tcx> { let r = self.re_free(nid, id); - self.infcx.tcx.mk_imm_ref(self.infcx.tcx.mk_region(r), - self.tcx().types.isize) + self.infcx.tcx.mk_imm_ref(self.infcx.tcx.mk_region(r), self.tcx().types.isize) } pub fn t_rptr_static(&self) -> Ty<'tcx> { self.infcx.tcx.mk_imm_ref(self.infcx.tcx.mk_region(ty::ReStatic), - self.tcx().types.isize) + self.tcx().types.isize) } pub fn t_rptr_empty(&self) -> Ty<'tcx> { self.infcx.tcx.mk_imm_ref(self.infcx.tcx.mk_region(ty::ReEmpty), - self.tcx().types.isize) + self.tcx().types.isize) } pub fn dummy_type_trace(&self) -> infer::TypeTrace<'tcx> { @@ -378,7 +364,7 @@ impl<'a, 'tcx> Env<'a, 'tcx> { pub fn make_lub_ty(&self, t1: Ty<'tcx>, t2: Ty<'tcx>) -> Ty<'tcx> { match self.lub().relate(&t1, &t2) { Ok(t) => t, - Err(ref e) => panic!("unexpected error computing LUB: {}", e) + Err(ref e) => panic!("unexpected error computing LUB: {}", e), } } @@ -386,12 +372,9 @@ impl<'a, 'tcx> Env<'a, 'tcx> { /// region checks). pub fn check_sub(&self, t1: Ty<'tcx>, t2: Ty<'tcx>) { match self.sub().relate(&t1, &t2) { - Ok(_) => { } + Ok(_) => {} Err(ref e) => { - panic!("unexpected error computing sub({:?},{:?}): {}", - t1, - t2, - e); + panic!("unexpected error computing sub({:?},{:?}): {}", t1, t2, e); } } } @@ -400,11 +383,9 @@ impl<'a, 'tcx> Env<'a, 'tcx> { /// region checks). pub fn check_not_sub(&self, t1: Ty<'tcx>, t2: Ty<'tcx>) { match self.sub().relate(&t1, &t2) { - Err(_) => { } + Err(_) => {} Ok(_) => { - panic!("unexpected success computing sub({:?},{:?})", - t1, - t2); + panic!("unexpected success computing sub({:?},{:?})", t1, t2); } } } @@ -453,18 +434,16 @@ fn contravariant_region_ptr_ok() { #[test] fn contravariant_region_ptr_err() { - test_env(EMPTY_SOURCE_STR, - errors(&["lifetime mismatch"]), - |env| { - env.create_simple_region_hierarchy(); - let t_rptr1 = env.t_rptr_scope(1); - let t_rptr10 = env.t_rptr_scope(10); - env.assert_eq(t_rptr1, t_rptr1); - env.assert_eq(t_rptr10, t_rptr10); - - // will cause an error when regions are resolved - env.make_subtype(t_rptr10, t_rptr1); - }) + test_env(EMPTY_SOURCE_STR, errors(&["lifetime mismatch"]), |env| { + env.create_simple_region_hierarchy(); + let t_rptr1 = env.t_rptr_scope(1); + let t_rptr10 = env.t_rptr_scope(10); + env.assert_eq(t_rptr1, t_rptr1); + env.assert_eq(t_rptr10, t_rptr10); + + // will cause an error when regions are resolved + env.make_subtype(t_rptr10, t_rptr1); + }) } #[test] @@ -661,8 +640,10 @@ fn glb_bound_free_infer() { // `&'_ isize` let t_resolve1 = env.infcx.shallow_resolve(t_infer1); match t_resolve1.sty { - ty::TyRef(..) => { } - _ => { panic!("t_resolve1={:?}", t_resolve1); } + ty::TyRef(..) => {} + _ => { + panic!("t_resolve1={:?}", t_resolve1); + } } }) } @@ -819,15 +800,13 @@ fn walk_ty() { let tcx = env.infcx.tcx; let int_ty = tcx.types.isize; let uint_ty = tcx.types.usize; - let tup1_ty = tcx.mk_tup(vec!(int_ty, uint_ty, int_ty, uint_ty)); - let tup2_ty = tcx.mk_tup(vec!(tup1_ty, tup1_ty, uint_ty)); + let tup1_ty = tcx.mk_tup(vec![int_ty, uint_ty, int_ty, uint_ty]); + let tup2_ty = tcx.mk_tup(vec![tup1_ty, tup1_ty, uint_ty]); let uniq_ty = tcx.mk_box(tup2_ty); let walked: Vec<_> = uniq_ty.walk().collect(); - assert_eq!(walked, [uniq_ty, - tup2_ty, - tup1_ty, int_ty, uint_ty, int_ty, uint_ty, - tup1_ty, int_ty, uint_ty, int_ty, uint_ty, - uint_ty]); + assert_eq!(walked, + [uniq_ty, tup2_ty, tup1_ty, int_ty, uint_ty, int_ty, uint_ty, tup1_ty, int_ty, + uint_ty, int_ty, uint_ty, uint_ty]); }) } @@ -837,13 +816,13 @@ fn walk_ty_skip_subtree() { let tcx = env.infcx.tcx; let int_ty = tcx.types.isize; let uint_ty = tcx.types.usize; - let tup1_ty = tcx.mk_tup(vec!(int_ty, uint_ty, int_ty, uint_ty)); - let tup2_ty = tcx.mk_tup(vec!(tup1_ty, tup1_ty, uint_ty)); + let tup1_ty = tcx.mk_tup(vec![int_ty, uint_ty, int_ty, uint_ty]); + let tup2_ty = tcx.mk_tup(vec![tup1_ty, tup1_ty, uint_ty]); let uniq_ty = tcx.mk_box(tup2_ty); // types we expect to see (in order), plus a boolean saying // whether to skip the subtree. - let mut expected = vec!((uniq_ty, false), + let mut expected = vec![(uniq_ty, false), (tup2_ty, false), (tup1_ty, false), (int_ty, false), @@ -851,7 +830,7 @@ fn walk_ty_skip_subtree() { (int_ty, false), (uint_ty, false), (tup1_ty, true), // skip the isize/usize/isize/usize - (uint_ty, false)); + (uint_ty, false)]; expected.reverse(); let mut walker = uniq_ty.walk(); @@ -859,7 +838,9 @@ fn walk_ty_skip_subtree() { debug!("walked to {:?}", t); let (expected_ty, skip) = expected.pop().unwrap(); assert_eq!(t, expected_ty); - if skip { walker.skip_current_subtree(); } + if skip { + walker.skip_current_subtree(); + } } assert!(expected.is_empty()); diff --git a/src/librustc_front/fold.rs b/src/librustc_front/fold.rs index f4ea4cb9ea5d6..955de44b43f6e 100644 --- a/src/librustc_front/fold.rs +++ b/src/librustc_front/fold.rs @@ -20,8 +20,6 @@ use syntax::owned_slice::OwnedSlice; use syntax::ptr::P; use syntax::parse::token; use std::ptr; -use syntax::util::small_vector::SmallVector; - // This could have a better place to live. pub trait MoveMap { @@ -79,14 +77,10 @@ pub trait Folder : Sized { noop_fold_foreign_item(ni, self) } - fn fold_item(&mut self, i: P) -> SmallVector> { + fn fold_item(&mut self, i: P) -> P { noop_fold_item(i, self) } - fn fold_item_simple(&mut self, i: Item) -> Item { - noop_fold_item_simple(i, self) - } - fn fold_struct_field(&mut self, sf: StructField) -> StructField { noop_fold_struct_field(sf, self) } @@ -95,11 +89,11 @@ pub trait Folder : Sized { noop_fold_item_underscore(i, self) } - fn fold_trait_item(&mut self, i: P) -> SmallVector> { + fn fold_trait_item(&mut self, i: P) -> P { noop_fold_trait_item(i, self) } - fn fold_impl_item(&mut self, i: P) -> SmallVector> { + fn fold_impl_item(&mut self, i: P) -> P { noop_fold_impl_item(i, self) } @@ -111,8 +105,8 @@ pub trait Folder : Sized { noop_fold_block(b, self) } - fn fold_stmt(&mut self, s: P) -> SmallVector> { - s.and_then(|s| noop_fold_stmt(s, self)) + fn fold_stmt(&mut self, s: P) -> P { + noop_fold_stmt(s, self) } fn fold_arm(&mut self, a: Arm) -> Arm { @@ -123,7 +117,7 @@ pub trait Folder : Sized { noop_fold_pat(p, self) } - fn fold_decl(&mut self, d: P) -> SmallVector> { + fn fold_decl(&mut self, d: P) -> P { noop_fold_decl(d, self) } @@ -340,22 +334,17 @@ pub fn noop_fold_arm(Arm { attrs, pats, guard, body }: Arm, fld: &mut } } -pub fn noop_fold_decl(d: P, fld: &mut T) -> SmallVector> { - d.and_then(|Spanned { node, span }| { +pub fn noop_fold_decl(d: P, fld: &mut T) -> P { + d.map(|Spanned { node, span }| { match node { - DeclLocal(l) => SmallVector::one(P(Spanned { + DeclLocal(l) => Spanned { node: DeclLocal(fld.fold_local(l)), span: fld.new_span(span), - })), - DeclItem(it) => fld.fold_item(it) - .into_iter() - .map(|i| { - P(Spanned { - node: DeclItem(i), - span: fld.new_span(span), - }) - }) - .collect(), + }, + DeclItem(it) => Spanned { + node: DeclItem(fld.fold_item(it)), + span: fld.new_span(span), + }, } }) } @@ -431,14 +420,16 @@ pub fn noop_fold_foreign_mod(ForeignMod { abi, items }: ForeignMod, } pub fn noop_fold_variant(v: P, fld: &mut T) -> P { - v.map(|Spanned {node: Variant_ {name, attrs, data, disr_expr}, span}| Spanned { - node: Variant_ { - name: name, - attrs: fold_attrs(attrs, fld), - data: fld.fold_variant_data(data), - disr_expr: disr_expr.map(|e| fld.fold_expr(e)), - }, - span: fld.new_span(span), + v.map(|Spanned { node: Variant_ { name, attrs, data, disr_expr }, span }| { + Spanned { + node: Variant_ { + name: name, + attrs: fold_attrs(attrs, fld), + data: fld.fold_variant_data(data), + disr_expr: disr_expr.map(|e| fld.fold_expr(e)), + }, + span: fld.new_span(span), + } }) } @@ -696,12 +687,14 @@ pub fn noop_fold_where_predicate(pred: WherePredicate, fld: &mut T) - pub fn noop_fold_variant_data(vdata: VariantData, fld: &mut T) -> VariantData { match vdata { VariantData::Struct(fields, id) => { - VariantData::Struct(fields.move_map(|f| fld.fold_struct_field(f)), fld.new_id(id)) + VariantData::Struct(fields.move_map(|f| fld.fold_struct_field(f)), + fld.new_id(id)) } VariantData::Tuple(fields, id) => { - VariantData::Tuple(fields.move_map(|f| fld.fold_struct_field(f)), fld.new_id(id)) + VariantData::Tuple(fields.move_map(|f| fld.fold_struct_field(f)), + fld.new_id(id)) } - VariantData::Unit(id) => VariantData::Unit(fld.new_id(id)) + VariantData::Unit(id) => VariantData::Unit(fld.new_id(id)), } } @@ -740,8 +733,7 @@ pub fn noop_fold_struct_field(f: StructField, fld: &mut T) -> StructF pub fn noop_fold_field(Field { name, expr, span }: Field, folder: &mut T) -> Field { Field { - name: respan(folder.new_span(name.span), - folder.fold_name(name.node)), + name: respan(folder.new_span(name.span), folder.fold_name(name.node)), expr: folder.fold_expr(expr), span: folder.new_span(span), } @@ -768,7 +760,7 @@ pub fn noop_fold_block(b: P, folder: &mut T) -> P { b.map(|Block { id, stmts, expr, rules, span }| { Block { id: folder.new_id(id), - stmts: stmts.into_iter().flat_map(|s| folder.fold_stmt(s).into_iter()).collect(), + stmts: stmts.into_iter().map(|s| folder.fold_stmt(s)).collect(), expr: expr.map(|x| folder.fold_expr(x)), rules: rules, span: folder.new_span(span), @@ -812,14 +804,11 @@ pub fn noop_fold_item_underscore(i: Item_, folder: &mut T) -> Item_ { ItemStruct(struct_def, folder.fold_generics(generics)) } ItemDefaultImpl(unsafety, ref trait_ref) => { - ItemDefaultImpl(unsafety, - folder.fold_trait_ref((*trait_ref).clone())) + ItemDefaultImpl(unsafety, folder.fold_trait_ref((*trait_ref).clone())) } ItemImpl(unsafety, polarity, generics, ifce, ty, impl_items) => { let new_impl_items = impl_items.into_iter() - .flat_map(|item| { - folder.fold_impl_item(item).into_iter() - }) + .map(|item| folder.fold_impl_item(item)) .collect(); let ifce = match ifce { None => None, @@ -837,7 +826,7 @@ pub fn noop_fold_item_underscore(i: Item_, folder: &mut T) -> Item_ { ItemTrait(unsafety, generics, bounds, items) => { let bounds = folder.fold_bounds(bounds); let items = items.into_iter() - .flat_map(|item| folder.fold_trait_item(item).into_iter()) + .map(|item| folder.fold_trait_item(item)) .collect(); ItemTrait(unsafety, folder.fold_generics(generics), bounds, items) } @@ -846,16 +835,15 @@ pub fn noop_fold_item_underscore(i: Item_, folder: &mut T) -> Item_ { pub fn noop_fold_trait_item(i: P, folder: &mut T) - -> SmallVector> { - SmallVector::one(i.map(|TraitItem { id, name, attrs, node, span }| { + -> P { + i.map(|TraitItem { id, name, attrs, node, span }| { TraitItem { id: folder.new_id(id), name: folder.fold_name(name), attrs: fold_attrs(attrs, folder), node: match node { ConstTraitItem(ty, default) => { - ConstTraitItem(folder.fold_ty(ty), - default.map(|x| folder.fold_expr(x))) + ConstTraitItem(folder.fold_ty(ty), default.map(|x| folder.fold_expr(x))) } MethodTraitItem(sig, body) => { MethodTraitItem(noop_fold_method_sig(sig, folder), @@ -868,11 +856,11 @@ pub fn noop_fold_trait_item(i: P, }, span: folder.new_span(span), } - })) + }) } -pub fn noop_fold_impl_item(i: P, folder: &mut T) -> SmallVector> { - SmallVector::one(i.map(|ImplItem { id, name, attrs, node, vis, span }| { +pub fn noop_fold_impl_item(i: P, folder: &mut T) -> P { + i.map(|ImplItem { id, name, attrs, node, vis, span }| { ImplItem { id: folder.new_id(id), name: folder.fold_name(name), @@ -883,20 +871,19 @@ pub fn noop_fold_impl_item(i: P, folder: &mut T) -> SmallVe ConstImplItem(folder.fold_ty(ty), folder.fold_expr(expr)) } MethodImplItem(sig, body) => { - MethodImplItem(noop_fold_method_sig(sig, folder), - folder.fold_block(body)) + MethodImplItem(noop_fold_method_sig(sig, folder), folder.fold_block(body)) } TypeImplItem(ty) => TypeImplItem(folder.fold_ty(ty)), }, span: folder.new_span(span), } - })) + }) } pub fn noop_fold_mod(Mod { inner, items }: Mod, folder: &mut T) -> Mod { Mod { inner: folder.new_span(inner), - items: items.into_iter().flat_map(|x| folder.fold_item(x).into_iter()).collect(), + items: items.into_iter().map(|x| folder.fold_item(x)).collect(), } } @@ -905,34 +892,22 @@ pub fn noop_fold_crate(Crate { module, attrs, config, span, exported_ -> Crate { let config = folder.fold_meta_items(config); - let mut items = folder.fold_item(P(hir::Item { - name: token::special_idents::invalid.name, - attrs: attrs, - id: DUMMY_NODE_ID, - vis: hir::Public, - span: span, - node: hir::ItemMod(module), - })) - .into_iter(); - - let (module, attrs, span) = match items.next() { - Some(item) => { - assert!(items.next().is_none(), - "a crate cannot expand to more than one item"); - item.and_then(|hir::Item { attrs, span, node, .. }| { - match node { - hir::ItemMod(m) => (m, attrs, span), - _ => panic!("fold converted a module to not a module"), - } - }) - } - None => (hir::Mod { - inner: span, - items: vec![], - }, - vec![], - span), - }; + let crate_mod = folder.fold_item(P(hir::Item { + name: token::special_idents::invalid.name, + attrs: attrs, + id: DUMMY_NODE_ID, + vis: hir::Public, + span: span, + node: hir::ItemMod(module), + })); + + let (module, attrs, span) = + crate_mod.and_then(|hir::Item { attrs, span, node, .. }| { + match node { + hir::ItemMod(m) => (m, attrs, span), + _ => panic!("fold converted a module to not a module"), + } + }); Crate { module: module, @@ -943,34 +918,28 @@ pub fn noop_fold_crate(Crate { module, attrs, config, span, exported_ } } -// fold one item into possibly many items -pub fn noop_fold_item(i: P, folder: &mut T) -> SmallVector> { - SmallVector::one(i.map(|i| folder.fold_item_simple(i))) -} - -// fold one item into exactly one item -pub fn noop_fold_item_simple(Item { id, name, attrs, node, vis, span }: Item, - folder: &mut T) - -> Item { - let id = folder.new_id(id); - let node = folder.fold_item_underscore(node); - // FIXME: we should update the impl_pretty_name, but it uses pretty printing. - // let ident = match node { - // // The node may have changed, recompute the "pretty" impl name. - // ItemImpl(_, _, _, ref maybe_trait, ref ty, _) => { - // impl_pretty_name(maybe_trait, Some(&**ty)) - // } - // _ => ident - // }; - - Item { - id: id, - name: folder.fold_name(name), - attrs: fold_attrs(attrs, folder), - node: node, - vis: vis, - span: folder.new_span(span), - } +pub fn noop_fold_item(item: P, folder: &mut T) -> P { + item.map(|Item { id, name, attrs, node, vis, span }| { + let id = folder.new_id(id); + let node = folder.fold_item_underscore(node); + // FIXME: we should update the impl_pretty_name, but it uses pretty printing. + // let ident = match node { + // // The node may have changed, recompute the "pretty" impl name. + // ItemImpl(_, _, _, ref maybe_trait, ref ty, _) => { + // impl_pretty_name(maybe_trait, Some(&**ty)) + // } + // _ => ident + // }; + + Item { + id: id, + name: folder.fold_name(name), + attrs: fold_attrs(attrs, folder), + node: node, + vis: vis, + span: folder.new_span(span), + } + }) } pub fn noop_fold_foreign_item(ni: P, folder: &mut T) -> P { @@ -981,8 +950,7 @@ pub fn noop_fold_foreign_item(ni: P, folder: &mut T) -> attrs: fold_attrs(attrs, folder), node: match node { ForeignItemFn(fdec, generics) => { - ForeignItemFn(folder.fold_fn_decl(fdec), - folder.fold_generics(generics)) + ForeignItemFn(folder.fold_fn_decl(fdec), folder.fold_generics(generics)) } ForeignItemStatic(t, m) => { ForeignItemStatic(folder.fold_ty(t), m) @@ -1074,12 +1042,10 @@ pub fn noop_fold_expr(Expr { id, node, span }: Expr, folder: &mut T) } ExprTup(elts) => ExprTup(elts.move_map(|x| folder.fold_expr(x))), ExprCall(f, args) => { - ExprCall(folder.fold_expr(f), - args.move_map(|x| folder.fold_expr(x))) + ExprCall(folder.fold_expr(f), args.move_map(|x| folder.fold_expr(x))) } ExprMethodCall(name, tps, args) => { - ExprMethodCall(respan(folder.new_span(name.span), - folder.fold_name(name.node)), + ExprMethodCall(respan(folder.new_span(name.span), folder.fold_name(name.node)), tps.move_map(|x| folder.fold_ty(x)), args.move_map(|x| folder.fold_expr(x))) } @@ -1127,13 +1093,11 @@ pub fn noop_fold_expr(Expr { id, node, span }: Expr, folder: &mut T) } ExprField(el, name) => { ExprField(folder.fold_expr(el), - respan(folder.new_span(name.span), - folder.fold_name(name.node))) + respan(folder.new_span(name.span), folder.fold_name(name.node))) } ExprTupField(el, index) => { ExprTupField(folder.fold_expr(el), - respan(folder.new_span(index.span), - folder.fold_usize(index.node))) + respan(folder.new_span(index.span), folder.fold_usize(index.node))) } ExprIndex(el, er) => { ExprIndex(folder.fold_expr(el), folder.fold_expr(er)) @@ -1152,12 +1116,10 @@ pub fn noop_fold_expr(Expr { id, node, span }: Expr, folder: &mut T) ExprPath(qself, folder.fold_path(path)) } ExprBreak(opt_ident) => ExprBreak(opt_ident.map(|label| { - respan(folder.new_span(label.span), - folder.fold_ident(label.node)) + respan(folder.new_span(label.span), folder.fold_ident(label.node)) })), ExprAgain(opt_ident) => ExprAgain(opt_ident.map(|label| { - respan(folder.new_span(label.span), - folder.fold_ident(label.node)) + respan(folder.new_span(label.span), folder.fold_ident(label.node)) })), ExprRet(e) => ExprRet(e.map(|x| folder.fold_expr(x))), ExprInlineAsm(InlineAsm { @@ -1191,36 +1153,32 @@ pub fn noop_fold_expr(Expr { id, node, span }: Expr, folder: &mut T) } } -pub fn noop_fold_stmt(Spanned { node, span }: Stmt, - folder: &mut T) - -> SmallVector> { - let span = folder.new_span(span); - match node { - StmtDecl(d, id) => { - let id = folder.new_id(id); - folder.fold_decl(d) - .into_iter() - .map(|d| { - P(Spanned { - node: StmtDecl(d, id), - span: span, - }) - }) - .collect() - } - StmtExpr(e, id) => { - let id = folder.new_id(id); - SmallVector::one(P(Spanned { - node: StmtExpr(folder.fold_expr(e), id), - span: span, - })) - } - StmtSemi(e, id) => { - let id = folder.new_id(id); - SmallVector::one(P(Spanned { - node: StmtSemi(folder.fold_expr(e), id), - span: span, - })) +pub fn noop_fold_stmt(stmt: P, folder: &mut T) + -> P { + stmt.map(|Spanned { node, span }| { + let span = folder.new_span(span); + match node { + StmtDecl(d, id) => { + let id = folder.new_id(id); + Spanned { + node: StmtDecl(folder.fold_decl(d), id), + span: span + } + } + StmtExpr(e, id) => { + let id = folder.new_id(id); + Spanned { + node: StmtExpr(folder.fold_expr(e), id), + span: span, + } + } + StmtSemi(e, id) => { + let id = folder.new_id(id); + Spanned { + node: StmtSemi(folder.fold_expr(e), id), + span: span, + } + } } - } + }) } diff --git a/src/librustc_front/hir.rs b/src/librustc_front/hir.rs index 6004a1c6556a5..b017a07dde0a1 100644 --- a/src/librustc_front/hir.rs +++ b/src/librustc_front/hir.rs @@ -1062,7 +1062,6 @@ pub type ViewPath = Spanned; #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub enum ViewPath_ { - /// `foo::bar::baz as quux` /// /// or just @@ -1151,7 +1150,7 @@ impl StructFieldKind { pub fn visibility(&self) -> Visibility { match *self { - NamedField(_, vis) | UnnamedField(vis) => vis + NamedField(_, vis) | UnnamedField(vis) => vis, } } } @@ -1183,24 +1182,36 @@ impl VariantData { } pub fn id(&self) -> NodeId { match *self { - VariantData::Struct(_, id) | VariantData::Tuple(_, id) | VariantData::Unit(id) => id + VariantData::Struct(_, id) | VariantData::Tuple(_, id) | VariantData::Unit(id) => id, } } pub fn is_struct(&self) -> bool { - if let VariantData::Struct(..) = *self { true } else { false } + if let VariantData::Struct(..) = *self { + true + } else { + false + } } pub fn is_tuple(&self) -> bool { - if let VariantData::Tuple(..) = *self { true } else { false } + if let VariantData::Tuple(..) = *self { + true + } else { + false + } } pub fn is_unit(&self) -> bool { - if let VariantData::Unit(..) = *self { true } else { false } + if let VariantData::Unit(..) = *self { + true + } else { + false + } } } -/* - FIXME (#3300): Should allow items to be anonymous. Right now - we just use dummy names for anon items. - */ + + +// FIXME (#3300): Should allow items to be anonymous. Right now +// we just use dummy names for anon items. /// An item /// /// The name might be a dummy name in case of anonymous items @@ -1244,7 +1255,7 @@ pub enum Item_ { // Default trait implementations /// - // `impl Trait for .. {}` + /// `impl Trait for .. {}` ItemDefaultImpl(Unsafety, TraitRef), /// An implementation, eg `impl Trait for Foo { .. }` ItemImpl(Unsafety, diff --git a/src/librustc_front/lowering.rs b/src/librustc_front/lowering.rs index ee2666601eba8..d13b92c04f82a 100644 --- a/src/librustc_front/lowering.rs +++ b/src/librustc_front/lowering.rs @@ -114,7 +114,7 @@ impl<'a, 'hir> LoweringContext<'a> { fn next_id(&self) -> NodeId { let cached = self.cached_id.get(); if cached == 0 { - return self.id_assigner.next_node_id() + return self.id_assigner.next_node_id(); } self.cached_id.set(cached + 1); @@ -214,8 +214,7 @@ pub fn lower_ty(_lctx: &LoweringContext, t: &Ty) -> P { TyVec(ref ty) => hir::TyVec(lower_ty(_lctx, ty)), TyPtr(ref mt) => hir::TyPtr(lower_mt(_lctx, mt)), TyRptr(ref region, ref mt) => { - hir::TyRptr(lower_opt_lifetime(_lctx, region), - lower_mt(_lctx, mt)) + hir::TyRptr(lower_opt_lifetime(_lctx, region), lower_mt(_lctx, mt)) } TyBareFn(ref f) => { hir::TyBareFn(P(hir::BareFnTy { @@ -502,13 +501,17 @@ pub fn lower_variant_data(_lctx: &LoweringContext, vdata: &VariantData) -> hir:: match *vdata { VariantData::Struct(ref fields, id) => { hir::VariantData::Struct(fields.iter() - .map(|f| lower_struct_field(_lctx, f)).collect(), id) + .map(|f| lower_struct_field(_lctx, f)) + .collect(), + id) } VariantData::Tuple(ref fields, id) => { hir::VariantData::Tuple(fields.iter() - .map(|f| lower_struct_field(_lctx, f)).collect(), id) + .map(|f| lower_struct_field(_lctx, f)) + .collect(), + id) } - VariantData::Unit(id) => hir::VariantData::Unit(id) + VariantData::Unit(id) => hir::VariantData::Unit(id), } } @@ -676,8 +679,7 @@ pub fn lower_impl_item(_lctx: &LoweringContext, i: &ImplItem) -> P { - hir::MethodImplItem(lower_method_sig(_lctx, sig), - lower_block(_lctx, body)) + hir::MethodImplItem(lower_method_sig(_lctx, sig), lower_block(_lctx, body)) } TypeImplItem(ref ty) => hir::TypeImplItem(lower_ty(_lctx, ty)), MacImplItem(..) => panic!("Shouldn't exist any more"), @@ -743,8 +745,7 @@ pub fn lower_foreign_item(_lctx: &LoweringContext, i: &ForeignItem) -> P { - hir::ForeignItemFn(lower_fn_decl(_lctx, fdec), - lower_generics(_lctx, generics)) + hir::ForeignItemFn(lower_fn_decl(_lctx, fdec), lower_generics(_lctx, generics)) } ForeignItemStatic(ref t, m) => { hir::ForeignItemStatic(lower_ty(_lctx, t), m) @@ -855,8 +856,9 @@ pub fn lower_pat(_lctx: &LoweringContext, p: &Pat) -> P { } PatTup(ref elts) => hir::PatTup(elts.iter().map(|x| lower_pat(_lctx, x)).collect()), PatBox(ref inner) => hir::PatBox(lower_pat(_lctx, inner)), - PatRegion(ref inner, mutbl) => hir::PatRegion(lower_pat(_lctx, inner), - lower_mutability(_lctx, mutbl)), + PatRegion(ref inner, mutbl) => { + hir::PatRegion(lower_pat(_lctx, inner), lower_mutability(_lctx, mutbl)) + } PatRange(ref e1, ref e2) => { hir::PatRange(lower_expr(_lctx, e1), lower_expr(_lctx, e2)) } @@ -1021,11 +1023,12 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P { // InPlace::finalize(place) // }) let expr = { - let call_move_val_init = hir::StmtSemi(make_call(lctx, - &move_val_init, - vec![expr_ident(lctx, e.span, p_ptr_ident), - pop_unsafe_expr]), - lctx.next_id()); + let call_move_val_init = + hir::StmtSemi(make_call(lctx, + &move_val_init, + vec![expr_ident(lctx, e.span, p_ptr_ident), + pop_unsafe_expr]), + lctx.next_id()); let call_move_val_init = respan(e.span, call_move_val_init); let call = make_call(lctx, @@ -1100,14 +1103,10 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P { } }); - hir::ExprIf(lower_expr(lctx, cond), - lower_block(lctx, blk), - else_opt) + hir::ExprIf(lower_expr(lctx, cond), lower_block(lctx, blk), else_opt) } ExprWhile(ref cond, ref body, opt_ident) => { - hir::ExprWhile(lower_expr(lctx, cond), - lower_block(lctx, body), - opt_ident) + hir::ExprWhile(lower_expr(lctx, cond), lower_block(lctx, body), opt_ident) } ExprLoop(ref body, opt_ident) => { hir::ExprLoop(lower_block(lctx, body), opt_ident) @@ -1132,8 +1131,7 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P { lower_expr(lctx, er)) } ExprField(ref el, ident) => { - hir::ExprField(lower_expr(lctx, el), - respan(ident.span, ident.node.name)) + hir::ExprField(lower_expr(lctx, el), respan(ident.span, ident.node.name)) } ExprTupField(ref el, ident) => { hir::ExprTupField(lower_expr(lctx, el), ident) @@ -1406,10 +1404,7 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P { path_global(e.span, strs) }; - expr_call(lctx, - e.span, - expr_path(lctx, into_iter_path), - vec![head]) + expr_call(lctx, e.span, expr_path(lctx, into_iter_path), vec![head]) }; let match_expr = expr_match(lctx, @@ -1428,7 +1423,7 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P { false, result_ident, match_expr)], - Some(expr_ident(lctx, e.span, result_ident)))) + Some(expr_ident(lctx, e.span, result_ident)))); } ExprMac(_) => panic!("Shouldn't exist here"), @@ -1525,7 +1520,7 @@ pub fn lower_trait_bound_modifier(_lctx: &LoweringContext, fn arm(pats: Vec>, expr: P) -> hir::Arm { hir::Arm { - attrs: vec!(), + attrs: vec![], pats: pats, guard: None, body: expr, @@ -1562,9 +1557,7 @@ fn expr_match(lctx: &LoweringContext, arms: Vec, source: hir::MatchSource) -> P { - expr(lctx, - span, - hir::ExprMatch(arg, arms, source)) + expr(lctx, span, hir::ExprMatch(arg, arms, source)) } fn expr_block(lctx: &LoweringContext, b: P) -> P { @@ -1626,7 +1619,7 @@ fn block_all(lctx: &LoweringContext, fn pat_some(lctx: &LoweringContext, span: Span, pat: P) -> P { let some = std_path(lctx, &["option", "Option", "Some"]); let path = path_global(span, some); - pat_enum(lctx, span, path, vec!(pat)) + pat_enum(lctx, span, path, vec![pat]) } fn pat_none(lctx: &LoweringContext, span: Span) -> P { @@ -1675,7 +1668,7 @@ fn pat(lctx: &LoweringContext, span: Span, pat: hir::Pat_) -> P { } fn path_ident(span: Span, id: Ident) -> hir::Path { - path(span, vec!(id)) + path(span, vec![id]) } fn path(span: Span, strs: Vec) -> hir::Path { @@ -1723,7 +1716,7 @@ fn std_path(lctx: &LoweringContext, components: &[&str]) -> Vec { v.push(str_to_ident(s)); } v.extend(components.iter().map(|s| str_to_ident(s))); - return v + return v; } // Given suffix ["b","c","d"], returns path `::std::b::c::d` when @@ -1765,9 +1758,7 @@ mod test { impl MockAssigner { fn new() -> MockAssigner { - MockAssigner { - next_id: Cell::new(0), - } + MockAssigner { next_id: Cell::new(0) } } } @@ -1787,14 +1778,18 @@ mod test { expn_id: codemap::NO_EXPANSION, } } - fn cfg(&self) -> ast::CrateConfig { Vec::new() } + fn cfg(&self) -> ast::CrateConfig { + Vec::new() + } fn ident_of(&self, st: &str) -> ast::Ident { parse::token::str_to_ident(st) } fn name_of(&self, st: &str) -> ast::Name { parse::token::intern(st) } - fn parse_sess(&self) -> &parse::ParseSess { self } + fn parse_sess(&self) -> &parse::ParseSess { + self + } } impl NodeIdAssigner for MockAssigner { @@ -1821,11 +1816,20 @@ mod test { let cx = parse::ParseSess::new(); let mut assigner = MockAssigner::new(); - let ast_if_let = quote_expr!(&cx, if let Some(foo) = baz { bar(foo); }); + let ast_if_let = quote_expr!(&cx, + if let Some(foo) = baz { + bar(foo); + }); let ast_if_let = assigner.fold_expr(ast_if_let); - let ast_while_let = quote_expr!(&cx, while let Some(foo) = baz { bar(foo); }); + let ast_while_let = quote_expr!(&cx, + while let Some(foo) = baz { + bar(foo); + }); let ast_while_let = assigner.fold_expr(ast_while_let); - let ast_for = quote_expr!(&cx, for i in 0..10 { foo(i); }); + let ast_for = quote_expr!(&cx, + for i in 0..10 { + foo(i); + }); let ast_for = assigner.fold_expr(ast_for); let ast_in = quote_expr!(&cx, in HEAP { foo() }); let ast_in = assigner.fold_expr(ast_in); diff --git a/src/librustc_front/print/pprust.rs b/src/librustc_front/print/pprust.rs index 139f863533b3e..2fd374f756050 100644 --- a/src/librustc_front/print/pprust.rs +++ b/src/librustc_front/print/pprust.rs @@ -899,18 +899,16 @@ impl<'a> State<'a> { if !struct_def.is_struct() { if struct_def.is_tuple() { try!(self.popen()); - try!(self.commasep(Inconsistent, - struct_def.fields(), - |s, field| { - match field.node.kind { - hir::NamedField(..) => panic!("unexpected named field"), - hir::UnnamedField(vis) => { - try!(s.print_visibility(vis)); - try!(s.maybe_print_comment(field.span.lo)); - s.print_type(&*field.node.ty) - } - } - })); + try!(self.commasep(Inconsistent, struct_def.fields(), |s, field| { + match field.node.kind { + hir::NamedField(..) => panic!("unexpected named field"), + hir::UnnamedField(vis) => { + try!(s.print_visibility(vis)); + try!(s.maybe_print_comment(field.span.lo)); + s.print_type(&*field.node.ty) + } + } + })); try!(self.pclose()); } try!(self.print_where_clause(&generics.where_clause)); @@ -1489,44 +1487,37 @@ impl<'a> State<'a> { try!(self.print_string(&a.asm, a.asm_str_style)); try!(self.word_space(":")); - try!(self.commasep(Inconsistent, - &a.outputs, - |s, &(ref co, ref o, is_rw)| { - match co.slice_shift_char() { - Some(('=', operand)) if is_rw => { - try!(s.print_string(&format!("+{}", operand), - ast::CookedStr)) - } - _ => try!(s.print_string(&co, ast::CookedStr)), - } - try!(s.popen()); - try!(s.print_expr(&**o)); - try!(s.pclose()); - Ok(()) - })); + try!(self.commasep(Inconsistent, &a.outputs, |s, &(ref co, ref o, is_rw)| { + match co.slice_shift_char() { + Some(('=', operand)) if is_rw => { + try!(s.print_string(&format!("+{}", operand), ast::CookedStr)) + } + _ => try!(s.print_string(&co, ast::CookedStr)), + } + try!(s.popen()); + try!(s.print_expr(&**o)); + try!(s.pclose()); + Ok(()) + })); try!(space(&mut self.s)); try!(self.word_space(":")); - try!(self.commasep(Inconsistent, - &a.inputs, - |s, &(ref co, ref o)| { - try!(s.print_string(&co, ast::CookedStr)); - try!(s.popen()); - try!(s.print_expr(&**o)); - try!(s.pclose()); - Ok(()) - })); + try!(self.commasep(Inconsistent, &a.inputs, |s, &(ref co, ref o)| { + try!(s.print_string(&co, ast::CookedStr)); + try!(s.popen()); + try!(s.print_expr(&**o)); + try!(s.pclose()); + Ok(()) + })); try!(space(&mut self.s)); try!(self.word_space(":")); - try!(self.commasep(Inconsistent, - &a.clobbers, - |s, co| { - try!(s.print_string(&co, ast::CookedStr)); - Ok(()) - })); + try!(self.commasep(Inconsistent, &a.clobbers, |s, co| { + try!(s.print_string(&co, ast::CookedStr)); + Ok(()) + })); - let mut options = vec!(); + let mut options = vec![]; if a.volatile { options.push("volatile"); } @@ -1540,12 +1531,10 @@ impl<'a> State<'a> { if !options.is_empty() { try!(space(&mut self.s)); try!(self.word_space(":")); - try!(self.commasep(Inconsistent, - &*options, - |s, &co| { - try!(s.print_string(co, ast::CookedStr)); - Ok(()) - })); + try!(self.commasep(Inconsistent, &*options, |s, &co| { + try!(s.print_string(co, ast::CookedStr)); + Ok(()) + })); } try!(self.pclose()); @@ -1610,7 +1599,7 @@ impl<'a> State<'a> { try!(self.maybe_print_comment(path.span.lo)); let mut first = !path.global; - for segment in &path.segments[..path.segments.len()-depth] { + for segment in &path.segments[..path.segments.len() - depth] { if first { first = false } else { @@ -1694,9 +1683,7 @@ impl<'a> State<'a> { hir::ParenthesizedParameters(ref data) => { try!(word(&mut self.s, "(")); - try!(self.commasep(Inconsistent, - &data.inputs, - |s, ty| s.print_type(&**ty))); + try!(self.commasep(Inconsistent, &data.inputs, |s, ty| s.print_type(&**ty))); try!(word(&mut self.s, ")")); match data.output { @@ -1716,8 +1703,8 @@ impl<'a> State<'a> { pub fn print_pat(&mut self, pat: &hir::Pat) -> io::Result<()> { try!(self.maybe_print_comment(pat.span.lo)); try!(self.ann.pre(self, NodePat(pat))); - /* Pat isn't normalized, but the beauty of it - is that it doesn't matter */ + // Pat isn't normalized, but the beauty of it + // is that it doesn't matter match pat.node { hir::PatWild => try!(word(&mut self.s, "_")), hir::PatIdent(binding_mode, ref path1, ref sub) => { @@ -2066,18 +2053,16 @@ impl<'a> State<'a> { ints.push(i); } - try!(self.commasep(Inconsistent, - &ints[..], - |s, &idx| { - if idx < generics.lifetimes.len() { - let lifetime = &generics.lifetimes[idx]; - s.print_lifetime_def(lifetime) - } else { - let idx = idx - generics.lifetimes.len(); - let param = &generics.ty_params[idx]; - s.print_ty_param(param) - } - })); + try!(self.commasep(Inconsistent, &ints[..], |s, &idx| { + if idx < generics.lifetimes.len() { + let lifetime = &generics.lifetimes[idx]; + s.print_lifetime_def(lifetime) + } else { + let idx = idx - generics.lifetimes.len(); + let param = &generics.ty_params[idx]; + s.print_ty_param(param) + } + })); try!(word(&mut self.s, ">")); Ok(()) @@ -2098,7 +2083,7 @@ impl<'a> State<'a> { pub fn print_where_clause(&mut self, where_clause: &hir::WhereClause) -> io::Result<()> { if where_clause.predicates.is_empty() { - return Ok(()) + return Ok(()); } try!(space(&mut self.s)); @@ -2170,18 +2155,16 @@ impl<'a> State<'a> { try!(self.print_path(path, false, 0)); try!(word(&mut self.s, "::{")); } - try!(self.commasep(Inconsistent, - &segments[..], - |s, w| { - match w.node { - hir::PathListIdent { name, .. } => { - s.print_name(name) - } - hir::PathListMod { .. } => { - word(&mut s.s, "self") - } - } - })); + try!(self.commasep(Inconsistent, &segments[..], |s, w| { + match w.node { + hir::PathListIdent { name, .. } => { + s.print_name(name) + } + hir::PathListMod { .. } => { + word(&mut s.s, "self") + } + } + })); word(&mut self.s, "}") } } @@ -2286,7 +2269,7 @@ impl<'a> State<'a> { match self.next_comment() { Some(ref cmnt) => { if (*cmnt).style != comments::Trailing { - return Ok(()) + return Ok(()); } let span_line = cm.lookup_char_pos(span.hi); let comment_line = cm.lookup_char_pos((*cmnt).pos); diff --git a/src/librustc_front/util.rs b/src/librustc_front/util.rs index 07044a7bba0ef..a2c52b274d55f 100644 --- a/src/librustc_front/util.rs +++ b/src/librustc_front/util.rs @@ -175,7 +175,7 @@ impl<'a, 'v, O: ast_util::IdVisitingOperation> Visitor<'v> for IdVisitor<'a, O> fn visit_item(&mut self, item: &Item) { if !self.pass_through_items { if self.visited_outermost { - return + return; } else { self.visited_outermost = true } @@ -282,11 +282,11 @@ impl<'a, 'v, O: ast_util::IdVisitingOperation> Visitor<'v> for IdVisitor<'a, O> } fn visit_variant_data(&mut self, - struct_def: &VariantData, - _: Name, - _: &hir::Generics, - _: NodeId, - _: Span) { + struct_def: &VariantData, + _: Name, + _: &hir::Generics, + _: NodeId, + _: Span) { self.operation.visit_id(struct_def.id()); visit::walk_struct_def(self, struct_def); } diff --git a/src/librustc_front/visit.rs b/src/librustc_front/visit.rs index 7d8bdec51b58c..94986ceced60a 100644 --- a/src/librustc_front/visit.rs +++ b/src/librustc_front/visit.rs @@ -112,15 +112,22 @@ pub trait Visitor<'v> : Sized { fn visit_poly_trait_ref(&mut self, t: &'v PolyTraitRef, m: &'v TraitBoundModifier) { walk_poly_trait_ref(self, t, m) } - fn visit_variant_data(&mut self, s: &'v VariantData, _: Name, - _: &'v Generics, _: NodeId, _: Span) { + fn visit_variant_data(&mut self, + s: &'v VariantData, + _: Name, + _: &'v Generics, + _: NodeId, + _: Span) { walk_struct_def(self, s) } fn visit_struct_field(&mut self, s: &'v StructField) { walk_struct_field(self, s) } - fn visit_enum_def(&mut self, enum_definition: &'v EnumDef, - generics: &'v Generics, item_id: NodeId, _: Span) { + fn visit_enum_def(&mut self, + enum_definition: &'v EnumDef, + generics: &'v Generics, + item_id: NodeId, + _: Span) { walk_enum_def(self, enum_definition, generics, item_id) } fn visit_variant(&mut self, v: &'v Variant, g: &'v Generics, item_id: NodeId) { @@ -226,9 +233,7 @@ pub fn walk_poly_trait_ref<'v, V>(visitor: &mut V, _modifier: &'v TraitBoundModifier) where V: Visitor<'v> { - walk_list!(visitor, - visit_lifetime_def, - &trait_ref.bound_lifetimes); + walk_list!(visitor, visit_lifetime_def, &trait_ref.bound_lifetimes); visitor.visit_trait_ref(&trait_ref.trait_ref); } @@ -298,11 +303,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) { ItemDefaultImpl(_, ref trait_ref) => { visitor.visit_trait_ref(trait_ref) } - ItemImpl(_, _, - ref type_parameters, - ref opt_trait_reference, - ref typ, - ref impl_items) => { + ItemImpl(_, _, ref type_parameters, ref opt_trait_reference, ref typ, ref impl_items) => { visitor.visit_generics(type_parameters); walk_list!(visitor, visit_trait_ref, opt_trait_reference); visitor.visit_ty(typ); @@ -310,8 +311,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) { } ItemStruct(ref struct_definition, ref generics) => { visitor.visit_generics(generics); - visitor.visit_variant_data(struct_definition, item.name, - generics, item.id, item.span); + visitor.visit_variant_data(struct_definition, item.name, generics, item.id, item.span); } ItemTrait(_, ref generics, ref bounds, ref methods) => { visitor.visit_generics(generics); @@ -326,7 +326,11 @@ pub fn walk_enum_def<'v, V: Visitor<'v>>(visitor: &mut V, enum_definition: &'v EnumDef, generics: &'v Generics, item_id: NodeId) { - walk_list!(visitor, visit_variant, &enum_definition.variants, generics, item_id); + walk_list!(visitor, + visit_variant, + &enum_definition.variants, + generics, + item_id); } pub fn walk_variant<'v, V: Visitor<'v>>(visitor: &mut V, @@ -334,8 +338,11 @@ pub fn walk_variant<'v, V: Visitor<'v>>(visitor: &mut V, generics: &'v Generics, item_id: NodeId) { visitor.visit_name(variant.span, variant.node.name); - visitor.visit_variant_data(&variant.node.data, variant.node.name, - generics, item_id, variant.span); + visitor.visit_variant_data(&variant.node.data, + variant.node.name, + generics, + item_id, + variant.span); walk_list!(visitor, visit_expr, &variant.node.disr_expr); walk_list!(visitor, visit_attribute, &variant.node.attrs); } @@ -357,9 +364,7 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) { } TyBareFn(ref function_declaration) => { walk_fn_decl(visitor, &function_declaration.decl); - walk_list!(visitor, - visit_lifetime_def, - &function_declaration.lifetimes); + walk_list!(visitor, visit_lifetime_def, &function_declaration.lifetimes); } TyPath(ref maybe_qself, ref path) => { if let Some(ref qself) = *maybe_qself { diff --git a/src/librustc_llvm/lib.rs b/src/librustc_llvm/lib.rs index fe84cffa8c660..9cb5012cf0f81 100644 --- a/src/librustc_llvm/lib.rs +++ b/src/librustc_llvm/lib.rs @@ -16,6 +16,8 @@ #![allow(dead_code)] #![allow(trivial_casts)] +#![cfg_attr(stage0, allow(improper_ctypes))] + #![crate_name = "rustc_llvm"] #![unstable(feature = "rustc_private", issue = "27812")] #![staged_api] diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs index 3cfc51ec3c98a..e351215276a56 100644 --- a/src/librustc_mir/build/expr/as_rvalue.rs +++ b/src/librustc_mir/build/expr/as_rvalue.rs @@ -44,8 +44,8 @@ impl<'a,'tcx> Builder<'a,'tcx> { } ExprKind::Repeat { value, count } => { let value_operand = unpack!(block = this.as_operand(block, value)); - let count_operand = unpack!(block = this.as_operand(block, count)); - block.and(Rvalue::Repeat(value_operand, count_operand)) + let count = this.as_constant(count); + block.and(Rvalue::Repeat(value_operand, count)) } ExprKind::Borrow { region, borrow_kind, arg } => { let arg_lvalue = unpack!(block = this.as_lvalue(block, arg)); @@ -71,7 +71,7 @@ impl<'a,'tcx> Builder<'a,'tcx> { // schedule a shallow free of that memory, lest we unwind: let extent = this.extent_of_innermost_scope().unwrap(); - this.schedule_drop(expr_span, extent, DropKind::Shallow, &result, value_ty); + this.schedule_drop(expr_span, extent, DropKind::Free, &result, value_ty); // initialize the box contents: let contents = result.clone().deref(); @@ -149,16 +149,19 @@ impl<'a,'tcx> Builder<'a,'tcx> { block.and(Rvalue::Aggregate(AggregateKind::Closure(closure_id, substs), upvars)) } ExprKind::Adt { adt_def, variant_index, substs, fields, base } => { // see (*) above - // first process the set of fields + // first process the set of fields that were provided + // (evaluating them in order given by user) let fields_map: FnvHashMap<_, _> = fields.into_iter() .map(|f| (f.name, unpack!(block = this.as_operand(block, f.expr)))) .collect(); - let field_names = this.hir.fields(adt_def, variant_index); - + // if base expression is given, evaluate it now let base = base.map(|base| unpack!(block = this.as_lvalue(block, base))); + // get list of all fields that we will need + let field_names = this.hir.all_fields(adt_def, variant_index); + // for the actual values we use, take either the // expr the user specified or, if they didn't // specify something for this field name, create a diff --git a/src/librustc_mir/build/expr/as_temp.rs b/src/librustc_mir/build/expr/as_temp.rs index 7c85e9e717463..f0bbc6fb67eaa 100644 --- a/src/librustc_mir/build/expr/as_temp.rs +++ b/src/librustc_mir/build/expr/as_temp.rs @@ -38,7 +38,7 @@ impl<'a,'tcx> Builder<'a,'tcx> { let temp_lifetime = match expr.temp_lifetime { Some(t) => t, None => { - this.hir.span_bug(expr.span, &format!("no temp_lifetime for expr")); + this.hir.span_bug(expr.span, "no temp_lifetime for expr"); } }; this.schedule_drop(expr.span, temp_lifetime, DropKind::Deep, &temp, expr_ty); diff --git a/src/librustc_mir/build/expr/into.rs b/src/librustc_mir/build/expr/into.rs index a7d68b09b5459..57c6db79c5271 100644 --- a/src/librustc_mir/build/expr/into.rs +++ b/src/librustc_mir/build/expr/into.rs @@ -211,10 +211,10 @@ impl<'a,'tcx> Builder<'a,'tcx> { this.cfg.start_new_block().unit() } ExprKind::Call { fun, args } => { - let fun = unpack!(block = this.as_lvalue(block, fun)); + let fun = unpack!(block = this.as_operand(block, fun)); let args: Vec<_> = args.into_iter() - .map(|arg| unpack!(block = this.as_lvalue(block, arg))) + .map(|arg| unpack!(block = this.as_operand(block, arg))) .collect(); let success = this.cfg.start_new_block(); let panic = this.diverge_cleanup(); diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs index 6e0b05d5dea79..cc8549de26a6c 100644 --- a/src/librustc_mir/build/matches/mod.rs +++ b/src/librustc_mir/build/matches/mod.rs @@ -15,6 +15,8 @@ use build::{BlockAnd, Builder}; use repr::*; +use rustc_data_structures::fnv::FnvHashMap; +use rustc::middle::const_eval::ConstVal; use rustc::middle::region::CodeExtent; use rustc::middle::ty::{AdtDef, Ty}; use hair::*; @@ -42,7 +44,7 @@ impl<'a,'tcx> Builder<'a,'tcx> { // be unreachable or reachable multiple times. let var_extent = self.extent_of_innermost_scope().unwrap(); for arm in &arms { - self.declare_bindings(var_extent, arm.patterns[0].clone()); + self.declare_bindings(var_extent, &arm.patterns[0]); } let mut arm_blocks = ArmBlocks { @@ -62,18 +64,18 @@ impl<'a,'tcx> Builder<'a,'tcx> { // highest priority candidate comes last in the list. This the // reverse of the order in which candidates are written in the // source. - let candidates: Vec> = + let candidates: Vec<_> = arms.iter() .enumerate() .rev() // highest priority comes last .flat_map(|(arm_index, arm)| { arm.patterns.iter() .rev() - .map(move |pat| (arm_index, pat.clone(), arm.guard.clone())) + .map(move |pat| (arm_index, pat, arm.guard.clone())) }) .map(|(arm_index, pattern, guard)| { Candidate { - match_pairs: vec![self.match_pair(discriminant_lvalue.clone(), pattern)], + match_pairs: vec![MatchPair::new(discriminant_lvalue.clone(), pattern)], bindings: vec![], guard: guard, arm_index: arm_index, @@ -83,7 +85,15 @@ impl<'a,'tcx> Builder<'a,'tcx> { // this will generate code to test discriminant_lvalue and // branch to the appropriate arm block - self.match_candidates(span, &mut arm_blocks, candidates, block); + let otherwise = self.match_candidates(span, &mut arm_blocks, candidates, block); + + // because all matches are exhaustive, in principle we expect + // an empty vector to be returned here, but the algorithm is + // not entirely precise + if !otherwise.is_empty() { + let join_block = self.join_otherwise_blocks(otherwise); + self.panic(join_block); + } // all the arm blocks will rejoin here let end_block = self.cfg.start_new_block(); @@ -100,12 +110,11 @@ impl<'a,'tcx> Builder<'a,'tcx> { pub fn expr_into_pattern(&mut self, mut block: BasicBlock, var_extent: CodeExtent, // lifetime of vars - irrefutable_pat: PatternRef<'tcx>, + irrefutable_pat: Pattern<'tcx>, initializer: ExprRef<'tcx>) -> BlockAnd<()> { // optimize the case of `let x = ...` - let irrefutable_pat = self.hir.mirror(irrefutable_pat); - match irrefutable_pat.kind { + match *irrefutable_pat.kind { PatternKind::Binding { mutability, name, mode: BindingMode::ByValue, @@ -126,22 +135,22 @@ impl<'a,'tcx> Builder<'a,'tcx> { let lvalue = unpack!(block = self.as_lvalue(block, initializer)); self.lvalue_into_pattern(block, var_extent, - PatternRef::Mirror(Box::new(irrefutable_pat)), + irrefutable_pat, &lvalue) } pub fn lvalue_into_pattern(&mut self, mut block: BasicBlock, var_extent: CodeExtent, - irrefutable_pat: PatternRef<'tcx>, + irrefutable_pat: Pattern<'tcx>, initializer: &Lvalue<'tcx>) -> BlockAnd<()> { // first, creating the bindings - self.declare_bindings(var_extent, irrefutable_pat.clone()); + self.declare_bindings(var_extent, &irrefutable_pat); // create a dummy candidate - let mut candidate = Candidate::<'tcx> { - match_pairs: vec![self.match_pair(initializer.clone(), irrefutable_pat.clone())], + let mut candidate = Candidate { + match_pairs: vec![MatchPair::new(initializer.clone(), &irrefutable_pat)], bindings: vec![], guard: None, arm_index: 0, // since we don't call `match_candidates`, this field is unused @@ -164,29 +173,29 @@ impl<'a,'tcx> Builder<'a,'tcx> { block.unit() } - pub fn declare_bindings(&mut self, var_extent: CodeExtent, pattern: PatternRef<'tcx>) { - let pattern = self.hir.mirror(pattern); - match pattern.kind { - PatternKind::Binding { mutability, name, mode: _, var, ty, subpattern } => { + pub fn declare_bindings(&mut self, var_extent: CodeExtent, pattern: &Pattern<'tcx>) { + match *pattern.kind { + PatternKind::Binding { mutability, name, mode: _, var, ty, ref subpattern } => { self.declare_binding(var_extent, mutability, name, var, ty, pattern.span); - if let Some(subpattern) = subpattern { + if let Some(subpattern) = subpattern.as_ref() { self.declare_bindings(var_extent, subpattern); } } - PatternKind::Array { prefix, slice, suffix } | - PatternKind::Slice { prefix, slice, suffix } => { - for subpattern in prefix.into_iter().chain(slice).chain(suffix) { + PatternKind::Array { ref prefix, ref slice, ref suffix } | + PatternKind::Slice { ref prefix, ref slice, ref suffix } => { + for subpattern in prefix.iter().chain(slice).chain(suffix) { self.declare_bindings(var_extent, subpattern); } } - PatternKind::Constant { .. } | PatternKind::Range { .. } | PatternKind::Wild => {} - PatternKind::Deref { subpattern } => { + PatternKind::Constant { .. } | PatternKind::Range { .. } | PatternKind::Wild => { + } + PatternKind::Deref { ref subpattern } => { self.declare_bindings(var_extent, subpattern); } - PatternKind::Leaf { subpatterns } | - PatternKind::Variant { subpatterns, .. } => { + PatternKind::Leaf { ref subpatterns } | + PatternKind::Variant { ref subpatterns, .. } => { for subpattern in subpatterns { - self.declare_bindings(var_extent, subpattern.pattern); + self.declare_bindings(var_extent, &subpattern.pattern); } } } @@ -200,9 +209,9 @@ struct ArmBlocks { } #[derive(Clone, Debug)] -struct Candidate<'tcx> { +struct Candidate<'pat, 'tcx:'pat> { // all of these must be satisfied... - match_pairs: Vec>, + match_pairs: Vec>, // ...these bindings established... bindings: Vec>, @@ -226,12 +235,12 @@ struct Binding<'tcx> { } #[derive(Clone, Debug)] -struct MatchPair<'tcx> { +struct MatchPair<'pat, 'tcx:'pat> { // this lvalue... lvalue: Lvalue<'tcx>, // ... must match this pattern. - pattern: Pattern<'tcx>, + pattern: &'pat Pattern<'tcx>, } #[derive(Clone, Debug, PartialEq)] @@ -241,6 +250,13 @@ enum TestKind<'tcx> { adt_def: AdtDef<'tcx>, }, + // test the branches of enum + SwitchInt { + switch_ty: Ty<'tcx>, + options: Vec, + indices: FnvHashMap, + }, + // test for equality Eq { value: Literal<'tcx>, @@ -271,11 +287,32 @@ struct Test<'tcx> { // Main matching algorithm impl<'a,'tcx> Builder<'a,'tcx> { - fn match_candidates(&mut self, - span: Span, - arm_blocks: &mut ArmBlocks, - mut candidates: Vec>, - mut block: BasicBlock) + /// The main match algorithm. It begins with a set of candidates + /// `candidates` and has the job of generating code to determine + /// which of these candidates, if any, is the correct one. The + /// candidates are sorted in inverse priority -- so the last item + /// in the list has highest priority. When a candidate is found to + /// match the value, we will generate a branch to the appropriate + /// block found in `arm_blocks`. + /// + /// The return value is a list of "otherwise" blocks. These are + /// points in execution where we found that *NONE* of the + /// candidates apply. In principle, this means that the input + /// list was not exhaustive, though at present we sometimes are + /// not smart enough to recognize all exhaustive inputs. + /// + /// It might be surprising that the input can be inexhaustive. + /// Indeed, initially, it is not, because all matches are + /// exhaustive in Rust. But during processing we sometimes divide + /// up the list of candidates and recurse with a non-exhaustive + /// list. This is important to keep the size of the generated code + /// under control. See `test_candidates` for more details. + fn match_candidates<'pat>(&mut self, + span: Span, + arm_blocks: &mut ArmBlocks, + mut candidates: Vec>, + mut block: BasicBlock) + -> Vec { debug!("matched_candidate(span={:?}, block={:?}, candidates={:?})", span, block, candidates); @@ -303,36 +340,187 @@ impl<'a,'tcx> Builder<'a,'tcx> { } else { // if None is returned, then any remaining candidates // are unreachable (at least not through this path). - return; + return vec![]; } } // If there are no candidates that still need testing, we're done. // Since all matches are exhaustive, execution should never reach this point. if candidates.is_empty() { - return self.panic(block); + return vec![block]; + } + + // Test candidates where possible. + let (otherwise, tested_candidates) = + self.test_candidates(span, arm_blocks, &candidates, block); + + // If the target candidates were exhaustive, then we are done. + if otherwise.is_empty() { + return vec![]; + } + + // If all candidates were sorted into `target_candidates` somewhere, then + // the initial set was inexhaustive. + let untested_candidates = candidates.len() - tested_candidates; + if untested_candidates == 0 { + return otherwise; + } + + // Otherwise, let's process those remaining candidates. + let join_block = self.join_otherwise_blocks(otherwise); + candidates.truncate(untested_candidates); + self.match_candidates(span, arm_blocks, candidates, join_block) + } + + fn join_otherwise_blocks(&mut self, + otherwise: Vec) + -> BasicBlock + { + if otherwise.len() == 1 { + otherwise[0] + } else { + let join_block = self.cfg.start_new_block(); + for block in otherwise { + self.cfg.terminate(block, Terminator::Goto { target: join_block }); + } + join_block } + } - // otherwise, extract the next match pair and construct tests + /// This is the most subtle part of the matching algorithm. At + /// this point, the input candidates have been fully simplified, + /// and so we know that all remaining match-pairs require some + /// sort of test. To decide what test to do, we take the highest + /// priority candidate (last one in the list) and extract the + /// first match-pair from the list. From this we decide what kind + /// of test is needed using `test`, defined in the `test` module. + /// + /// *Note:* taking the first match pair is somewhat arbitrary, and + /// we might do better here by choosing more carefully what to + /// test. + /// + /// For example, consider the following possible match-pairs: + /// + /// 1. `x @ Some(P)` -- we will do a `Switch` to decide what variant `x` has + /// 2. `x @ 22` -- we will do a `SwitchInt` + /// 3. `x @ 3..5` -- we will do a range test + /// 4. etc. + /// + /// Once we know what sort of test we are going to perform, this + /// test may also help us with other candidates. So we walk over + /// the candidates (from high to low priority) and check. This + /// gives us, for each outcome of the test, a transformed list of + /// candidates. For example, if we are testing the current + /// variant of `x.0`, and we have a candidate `{x.0 @ Some(v), x.1 + /// @ 22}`, then we would have a resulting candidate of `{(x.0 as + /// Some).0 @ v, x.1 @ 22}`. Note that the first match-pair is now + /// simpler (and, in fact, irrefutable). + /// + /// But there may also be candidates that the test just doesn't + /// apply to. For example, consider the case of #29740: + /// + /// ```rust + /// match x { + /// "foo" => ..., + /// "bar" => ..., + /// "baz" => ..., + /// _ => ..., + /// } + /// ``` + /// + /// Here the match-pair we are testing will be `x @ "foo"`, and we + /// will generate an `Eq` test. Because `"bar"` and `"baz"` are different + /// constants, we will decide that these later candidates are just not + /// informed by the eq test. So we'll wind up with three candidate sets: + /// + /// - If outcome is that `x == "foo"` (one candidate, derived from `x @ "foo"`) + /// - If outcome is that `x != "foo"` (empty list of candidates) + /// - Otherwise (three candidates, `x @ "bar"`, `x @ "baz"`, `x @ + /// _`). Here we have the invariant that everything in the + /// otherwise list is of **lower priority** than the stuff in the + /// other lists. + /// + /// So we'll compile the test. For each outcome of the test, we + /// recursively call `match_candidates` with the corresponding set + /// of candidates. But note that this set is now inexhaustive: for + /// example, in the case where the test returns false, there are + /// NO candidates, even though there is stll a value to be + /// matched. So we'll collect the return values from + /// `match_candidates`, which are the blocks where control-flow + /// goes if none of the candidates matched. At this point, we can + /// continue with the "otherwise" list. + /// + /// If you apply this to the above test, you basically wind up + /// with an if-else-if chain, testing each candidate in turn, + /// which is precisely what we want. + fn test_candidates<'pat>(&mut self, + span: Span, + arm_blocks: &mut ArmBlocks, + candidates: &[Candidate<'pat, 'tcx>], + block: BasicBlock) + -> (Vec, usize) + { + // extract the match-pair from the highest priority candidate let match_pair = &candidates.last().unwrap().match_pairs[0]; - let test = self.test(match_pair); + let mut test = self.test(match_pair); + + // most of the time, the test to perform is simply a function + // of the main candidate; but for a test like SwitchInt, we + // may want to add cases based on the candidates that are + // available + match test.kind { + TestKind::SwitchInt { switch_ty, ref mut options, ref mut indices } => { + for candidate in candidates.iter().rev() { + if !self.add_cases_to_switch(&match_pair.lvalue, + candidate, + switch_ty, + options, + indices) { + break; + } + } + } + _ => { } + } + + // perform the test, branching to one of N blocks. For each of + // those N possible outcomes, create a (initially empty) + // vector of candidates. Those are the candidates that still + // apply if the test has that particular outcome. debug!("match_candidates: test={:?} match_pair={:?}", test, match_pair); let target_blocks = self.perform_test(block, &match_pair.lvalue, &test); - - for (outcome, mut target_block) in target_blocks.into_iter().enumerate() { - let applicable_candidates: Vec> = - candidates.iter() - .filter_map(|candidate| { - unpack!(target_block = - self.candidate_under_assumption(target_block, - &match_pair.lvalue, - &test.kind, - outcome, - candidate)) - }) - .collect(); - self.match_candidates(span, arm_blocks, applicable_candidates, target_block); - } + let mut target_candidates: Vec<_> = (0..target_blocks.len()).map(|_| vec![]).collect(); + + // Sort the candidates into the appropriate vector in + // `target_candidates`. Note that at some point we may + // encounter a candidate where the test is not relevant; at + // that point, we stop sorting. + let tested_candidates = + candidates.iter() + .rev() + .take_while(|c| self.sort_candidate(&match_pair.lvalue, + &test, + c, + &mut target_candidates)) + .count(); + assert!(tested_candidates > 0); // at least the last candidate ought to be tested + + // For each outcome of test, process the candidates that still + // apply. Collect a list of blocks where control flow will + // branch if one of the `target_candidate` sets is not + // exhaustive. + let otherwise: Vec<_> = + target_blocks.into_iter() + .zip(target_candidates) + .flat_map(|(target_block, target_candidates)| { + self.match_candidates(span, + arm_blocks, + target_candidates, + target_block) + }) + .collect(); + + (otherwise, tested_candidates) } /// Initializes each of the bindings from the candidate by @@ -347,11 +535,11 @@ impl<'a,'tcx> Builder<'a,'tcx> { /// bindings, further tests would be a use-after-move (which would /// in turn be detected by the borrowck code that runs on the /// MIR). - fn bind_and_guard_matched_candidate(&mut self, - mut block: BasicBlock, - arm_blocks: &mut ArmBlocks, - candidate: Candidate<'tcx>) - -> Option { + fn bind_and_guard_matched_candidate<'pat>(&mut self, + mut block: BasicBlock, + arm_blocks: &mut ArmBlocks, + candidate: Candidate<'pat, 'tcx>) + -> Option { debug!("bind_and_guard_matched_candidate(block={:?}, candidate={:?})", block, candidate); diff --git a/src/librustc_mir/build/matches/simplify.rs b/src/librustc_mir/build/matches/simplify.rs index 0267e9b10cecc..e69a04322c201 100644 --- a/src/librustc_mir/build/matches/simplify.rs +++ b/src/librustc_mir/build/matches/simplify.rs @@ -30,10 +30,10 @@ use repr::*; use std::mem; impl<'a,'tcx> Builder<'a,'tcx> { - pub fn simplify_candidate(&mut self, - mut block: BasicBlock, - candidate: &mut Candidate<'tcx>) - -> BlockAnd<()> { + pub fn simplify_candidate<'pat>(&mut self, + mut block: BasicBlock, + candidate: &mut Candidate<'pat, 'tcx>) + -> BlockAnd<()> { // repeatedly simplify match pairs until fixed point is reached loop { let match_pairs = mem::replace(&mut candidate.match_pairs, vec![]); @@ -60,18 +60,18 @@ impl<'a,'tcx> Builder<'a,'tcx> { /// have been pushed into the candidate. If no simplification is /// possible, Err is returned and no changes are made to /// candidate. - fn simplify_match_pair(&mut self, - mut block: BasicBlock, - match_pair: MatchPair<'tcx>, - candidate: &mut Candidate<'tcx>) - -> Result> { - match match_pair.pattern.kind { + fn simplify_match_pair<'pat>(&mut self, + mut block: BasicBlock, + match_pair: MatchPair<'pat, 'tcx>, + candidate: &mut Candidate<'pat, 'tcx>) + -> Result> { + match *match_pair.pattern.kind { PatternKind::Wild(..) => { // nothing left to do Ok(block) } - PatternKind::Binding { name, mutability, mode, var, ty, subpattern } => { + PatternKind::Binding { name, mutability, mode, var, ty, ref subpattern } => { candidate.bindings.push(Binding { name: name, mutability: mutability, @@ -82,9 +82,8 @@ impl<'a,'tcx> Builder<'a,'tcx> { binding_mode: mode, }); - if let Some(subpattern) = subpattern { + if let Some(subpattern) = subpattern.as_ref() { // this is the `x @ P` case; have to keep matching against `P` now - let subpattern = self.hir.mirror(subpattern); candidate.match_pairs.push(MatchPair::new(match_pair.lvalue, subpattern)); } @@ -96,12 +95,12 @@ impl<'a,'tcx> Builder<'a,'tcx> { Err(match_pair) } - PatternKind::Array { prefix, slice, suffix } => { + PatternKind::Array { ref prefix, ref slice, ref suffix } => { unpack!(block = self.prefix_suffix_slice(&mut candidate.match_pairs, block, match_pair.lvalue.clone(), prefix, - slice, + slice.as_ref(), suffix)); Ok(block) } @@ -113,16 +112,15 @@ impl<'a,'tcx> Builder<'a,'tcx> { Err(match_pair) } - PatternKind::Leaf { subpatterns } => { + PatternKind::Leaf { ref subpatterns } => { // tuple struct, match subpats (if any) candidate.match_pairs .extend(self.field_match_pairs(match_pair.lvalue, subpatterns)); Ok(block) } - PatternKind::Deref { subpattern } => { + PatternKind::Deref { ref subpattern } => { let lvalue = match_pair.lvalue.deref(); - let subpattern = self.hir.mirror(subpattern); candidate.match_pairs.push(MatchPair::new(lvalue, subpattern)); Ok(block) } diff --git a/src/librustc_mir/build/matches/test.rs b/src/librustc_mir/build/matches/test.rs index d5745eb28c7a8..dffd83f1c4150 100644 --- a/src/librustc_mir/build/matches/test.rs +++ b/src/librustc_mir/build/matches/test.rs @@ -15,18 +15,21 @@ // identify what tests are needed, perform the tests, and then filter // the candidates based on the result. -use build::{BlockAnd, Builder}; +use build::Builder; use build::matches::{Candidate, MatchPair, Test, TestKind}; use hair::*; use repr::*; +use rustc_data_structures::fnv::FnvHashMap; +use rustc::middle::const_eval::ConstVal; +use rustc::middle::ty::{self, Ty}; use syntax::codemap::Span; impl<'a,'tcx> Builder<'a,'tcx> { /// Identifies what test is needed to decide if `match_pair` is applicable. /// /// It is a bug to call this with a simplifyable pattern. - pub fn test(&mut self, match_pair: &MatchPair<'tcx>) -> Test<'tcx> { - match match_pair.pattern.kind { + pub fn test<'pat>(&mut self, match_pair: &MatchPair<'pat, 'tcx>) -> Test<'tcx> { + match *match_pair.pattern.kind { PatternKind::Variant { ref adt_def, variant_index: _, subpatterns: _ } => { Test { span: match_pair.pattern.span, @@ -34,13 +37,31 @@ impl<'a,'tcx> Builder<'a,'tcx> { } } + PatternKind::Constant { value: Literal::Value { .. } } + if is_switch_ty(match_pair.pattern.ty) => { + // for integers, we use a SwitchInt match, which allows + // us to handle more cases + Test { + span: match_pair.pattern.span, + kind: TestKind::SwitchInt { + switch_ty: match_pair.pattern.ty, + + // these maps are empty to start; cases are + // added below in add_cases_to_switch + options: vec![], + indices: FnvHashMap(), + } + } + } + PatternKind::Constant { ref value } => { + // for other types, we use an equality comparison Test { span: match_pair.pattern.span, kind: TestKind::Eq { value: value.clone(), ty: match_pair.pattern.ty.clone(), - }, + } } } @@ -78,13 +99,54 @@ impl<'a,'tcx> Builder<'a,'tcx> { } } + pub fn add_cases_to_switch<'pat>(&mut self, + test_lvalue: &Lvalue<'tcx>, + candidate: &Candidate<'pat, 'tcx>, + switch_ty: Ty<'tcx>, + options: &mut Vec, + indices: &mut FnvHashMap) + -> bool + { + let match_pair = match candidate.match_pairs.iter().find(|mp| mp.lvalue == *test_lvalue) { + Some(match_pair) => match_pair, + _ => { return false; } + }; + + match *match_pair.pattern.kind { + PatternKind::Constant { value: Literal::Value { ref value } } => { + // if the lvalues match, the type should match + assert_eq!(match_pair.pattern.ty, switch_ty); + + indices.entry(value.clone()) + .or_insert_with(|| { + options.push(value.clone()); + options.len() - 1 + }); + true + } + + PatternKind::Range { .. } | + PatternKind::Constant { .. } | + PatternKind::Variant { .. } | + PatternKind::Slice { .. } | + PatternKind::Array { .. } | + PatternKind::Wild | + PatternKind::Binding { .. } | + PatternKind::Leaf { .. } | + PatternKind::Deref { .. } => { + // don't know how to add these patterns to a switch + false + } + } + } + /// Generates the code to perform a test. pub fn perform_test(&mut self, block: BasicBlock, lvalue: &Lvalue<'tcx>, test: &Test<'tcx>) -> Vec { - match test.kind.clone() { + match test.kind { TestKind::Switch { adt_def } => { let num_enum_variants = self.hir.num_variants(adt_def); let target_blocks: Vec<_> = @@ -92,34 +154,52 @@ impl<'a,'tcx> Builder<'a,'tcx> { .collect(); self.cfg.terminate(block, Terminator::Switch { discr: lvalue.clone(), + adt_def: adt_def, targets: target_blocks.clone() }); target_blocks } - TestKind::Eq { value, ty } => { + TestKind::SwitchInt { switch_ty, ref options, indices: _ } => { + let otherwise = self.cfg.start_new_block(); + let targets: Vec<_> = + options.iter() + .map(|_| self.cfg.start_new_block()) + .chain(Some(otherwise)) + .collect(); + self.cfg.terminate(block, Terminator::SwitchInt { + discr: lvalue.clone(), + switch_ty: switch_ty, + values: options.clone(), + targets: targets.clone(), + }); + targets + } + + TestKind::Eq { ref value, ty } => { // call PartialEq::eq(discrim, constant) - let constant = self.push_literal(block, test.span, ty.clone(), value); + let constant = self.literal_operand(test.span, ty.clone(), value.clone()); let item_ref = self.hir.partial_eq(ty); - self.call_comparison_fn(block, test.span, item_ref, lvalue.clone(), constant) + self.call_comparison_fn(block, test.span, item_ref, + Operand::Consume(lvalue.clone()), constant) } - TestKind::Range { lo, hi, ty } => { + TestKind::Range { ref lo, ref hi, ty } => { // Test `v` by computing `PartialOrd::le(lo, v) && PartialOrd::le(v, hi)`. - let lo = self.push_literal(block, test.span, ty.clone(), lo); - let hi = self.push_literal(block, test.span, ty.clone(), hi); + let lo = self.literal_operand(test.span, ty.clone(), lo.clone()); + let hi = self.literal_operand(test.span, ty.clone(), hi.clone()); let item_ref = self.hir.partial_le(ty); let lo_blocks = self.call_comparison_fn(block, test.span, item_ref.clone(), lo, - lvalue.clone()); + Operand::Consume(lvalue.clone())); let hi_blocks = self.call_comparison_fn(lo_blocks[0], test.span, item_ref, - lvalue.clone(), + Operand::Consume(lvalue.clone()), hi); let failure = self.cfg.start_new_block(); @@ -164,14 +244,14 @@ impl<'a,'tcx> Builder<'a,'tcx> { block: BasicBlock, span: Span, item_ref: ItemRef<'tcx>, - lvalue1: Lvalue<'tcx>, - lvalue2: Lvalue<'tcx>) + lvalue1: Operand<'tcx>, + lvalue2: Operand<'tcx>) -> Vec { let target_blocks = vec![self.cfg.start_new_block(), self.cfg.start_new_block()]; let bool_ty = self.hir.bool_ty(); let eq_result = self.temp(bool_ty); - let func = self.push_item_ref(block, span, item_ref); + let func = self.item_ref_operand(span, item_ref); let call_blocks = [self.cfg.start_new_block(), self.diverge_cleanup()]; self.cfg.terminate(block, Terminator::Call { @@ -193,166 +273,187 @@ impl<'a,'tcx> Builder<'a,'tcx> { target_blocks } - /// Given a candidate and the outcome of a test we have performed, - /// transforms the candidate into a new candidate that reflects - /// further tests still needed. Returns `None` if this candidate - /// has now been ruled out. + /// Given that we are performing `test` against `test_lvalue`, + /// this job sorts out what the status of `candidate` will be + /// after the test. The `resulting_candidates` vector stores, for + /// each possible outcome of `test`, a vector of the candidates + /// that will result. This fn should add a (possibly modified) + /// clone of candidate into `resulting_candidates` wherever + /// appropriate. /// - /// For example, if a candidate included the patterns `[x.0 @ - /// Ok(P1), x.1 @ 22]`, and we did a switch test on `x.0` and - /// found the variant `Err` (as indicated by the `test_outcome` - /// parameter), we would return `None`. But if the test_outcome - /// were `Ok`, we would return `Some([x.0.downcast.0 @ P1, x.1 - /// @ 22])`. - pub fn candidate_under_assumption(&mut self, - mut block: BasicBlock, - test_lvalue: &Lvalue<'tcx>, - test_kind: &TestKind<'tcx>, - test_outcome: usize, - candidate: &Candidate<'tcx>) - -> BlockAnd>> { - let candidate = candidate.clone(); - let match_pairs = candidate.match_pairs; - let result = unpack!(block = self.match_pairs_under_assumption(block, - test_lvalue, - test_kind, - test_outcome, - match_pairs)); - block.and(match result { - Some(match_pairs) => Some(Candidate { match_pairs: match_pairs, ..candidate }), - None => None, - }) - } - - /// Helper for candidate_under_assumption that does the actual - /// work of transforming the list of match pairs. - fn match_pairs_under_assumption(&mut self, - mut block: BasicBlock, - test_lvalue: &Lvalue<'tcx>, - test_kind: &TestKind<'tcx>, - test_outcome: usize, - match_pairs: Vec>) - -> BlockAnd>>> { - let mut result = vec![]; - - for match_pair in match_pairs { - // if the match pair is testing a different lvalue, it - // is unaffected by this test. - if match_pair.lvalue != *test_lvalue { - result.push(match_pair); - continue; - } - - let desired_test = self.test(&match_pair); - - if *test_kind != desired_test.kind { - // if the match pair wants to (e.g.) test for - // equality against some particular constant, but - // we did a switch, then we can't say whether it - // matches or not, so we still have to include it - // as a possibility. - // - // For example, we have a constant `FOO: - // Option = Some(22)`, and `match_pair` is `x - // @ FOO`, but we did a switch on the variant - // (`Some` vs `None`). (OK, in principle this - // could tell us something, but we're not that - // smart yet to actually dig into the constant - // itself) - result.push(match_pair); - continue; + /// So, for example, if this candidate is `x @ Some(P0)` and the + /// test is a variant test, then we would add `(x as Option).0 @ + /// P0` to the `resulting_candidates` entry corresponding to the + /// variant `Some`. + /// + /// However, in some cases, the test may just not be relevant to + /// candidate. For example, suppose we are testing whether `foo.x == 22`, + /// but in one match arm we have `Foo { x: _, ... }`... in that case, + /// the test for what value `x` has has no particular relevance + /// to this candidate. In such cases, this function just returns false + /// without doing anything. This is used by the overall `match_candidates` + /// algorithm to structure the match as a whole. See `match_candidates` for + /// more details. + /// + /// FIXME(#29623). In some cases, we have some tricky choices to + /// make. for example, if we are testing that `x == 22`, but the + /// candidate is `x @ 13..55`, what should we do? In the event + /// that the test is true, we know that the candidate applies, but + /// in the event of false, we don't know that it *doesn't* + /// apply. For now, we return false, indicate that the test does + /// not apply to this candidate, but it might be we can get + /// tighter match code if we do something a bit different. + pub fn sort_candidate<'pat>(&mut self, + test_lvalue: &Lvalue<'tcx>, + test: &Test<'tcx>, + candidate: &Candidate<'pat, 'tcx>, + resulting_candidates: &mut [Vec>]) + -> bool { + // Find the match_pair for this lvalue (if any). At present, + // afaik, there can be at most one. (In the future, if we + // adopted a more general `@` operator, there might be more + // than one, but it'd be very unusual to have two sides that + // both require tests; you'd expect one side to be simplified + // away.) + let tested_match_pair = candidate.match_pairs.iter() + .enumerate() + .filter(|&(_, mp)| mp.lvalue == *test_lvalue) + .next(); + let (match_pair_index, match_pair) = match tested_match_pair { + Some(pair) => pair, + None => { + // We are not testing this lvalue. Therefore, this + // candidate applies to ALL outcomes. + return false; } - - let opt_consequent_match_pairs = - unpack!(block = self.consequent_match_pairs_under_assumption(block, - match_pair, - test_outcome)); - match opt_consequent_match_pairs { - None => { - // Right kind of test, but wrong outcome. That - // means this **entire candidate** is - // inapplicable, since the candidate is only - // applicable if all of its match-pairs apply (and - // this one doesn't). - return block.and(None); - } - - Some(consequent_match_pairs) => { - // Test passed; add any new patterns we have to test to the final result. - result.extend(consequent_match_pairs) + }; + + match test.kind { + // If we are performing a variant switch, then this + // informs variant patterns, but nothing else. + TestKind::Switch { adt_def: tested_adt_def } => { + match *match_pair.pattern.kind { + PatternKind::Variant { adt_def, variant_index, ref subpatterns } => { + assert_eq!(adt_def, tested_adt_def); + let new_candidate = + self.candidate_after_variant_switch(match_pair_index, + adt_def, + variant_index, + subpatterns, + candidate); + resulting_candidates[variant_index].push(new_candidate); + true + } + _ => { + false + } } } - } - block.and(Some(result)) - } - /// Identifies what test is needed to decide if `match_pair` is applicable. - /// - /// It is a bug to call this with a simplifyable pattern. - pub fn consequent_match_pairs_under_assumption(&mut self, - mut block: BasicBlock, - match_pair: MatchPair<'tcx>, - test_outcome: usize) - -> BlockAnd>>> { - match match_pair.pattern.kind { - PatternKind::Variant { adt_def, variant_index, subpatterns } => { - if test_outcome != variant_index { - return block.and(None); + // If we are performing a switch over integers, then this informs integer + // equality, but nothing else. + // + // FIXME(#29623) we could use TestKind::Range to rule + // things out here, in some cases. + TestKind::SwitchInt { switch_ty: _, options: _, ref indices } => { + match *match_pair.pattern.kind { + PatternKind::Constant { value: Literal::Value { ref value } } + if is_switch_ty(match_pair.pattern.ty) => { + let index = indices[value]; + let new_candidate = self.candidate_without_match_pair(match_pair_index, + candidate); + resulting_candidates[index].push(new_candidate); + true + } + _ => { + false + } } - - let elem = ProjectionElem::Downcast(adt_def, variant_index); - let downcast_lvalue = match_pair.lvalue.clone().elem(elem); - let consequent_match_pairs = - subpatterns.into_iter() - .map(|subpattern| { - let lvalue = - downcast_lvalue.clone().field( - subpattern.field); - self.match_pair(lvalue, subpattern.pattern) - }) - .collect(); - block.and(Some(consequent_match_pairs)) } - PatternKind::Constant { .. } | - PatternKind::Range { .. } => { - // these are boolean tests: if we are on the 0th - // successor, then they passed, and otherwise they - // failed, but there are never any more tests to come. - if test_outcome == 0 { - block.and(Some(vec![])) + TestKind::Eq { .. } | + TestKind::Range { .. } | + TestKind::Len { .. } => { + // These are all binary tests. + // + // FIXME(#29623) we can be more clever here + let pattern_test = self.test(&match_pair); + if pattern_test.kind == test.kind { + let new_candidate = self.candidate_without_match_pair(match_pair_index, + candidate); + resulting_candidates[0].push(new_candidate); + true } else { - block.and(None) + false } } + } + } - PatternKind::Slice { prefix, slice, suffix } => { - if test_outcome == 0 { - let mut consequent_match_pairs = vec![]; - unpack!(block = self.prefix_suffix_slice(&mut consequent_match_pairs, - block, - match_pair.lvalue, - prefix, - slice, - suffix)); - block.and(Some(consequent_match_pairs)) - } else { - block.and(None) - } - } + fn candidate_without_match_pair<'pat>(&mut self, + match_pair_index: usize, + candidate: &Candidate<'pat, 'tcx>) + -> Candidate<'pat, 'tcx> { + let other_match_pairs = + candidate.match_pairs.iter() + .enumerate() + .filter(|&(index, _)| index != match_pair_index) + .map(|(_, mp)| mp.clone()) + .collect(); + Candidate { + match_pairs: other_match_pairs, + bindings: candidate.bindings.clone(), + guard: candidate.guard.clone(), + arm_index: candidate.arm_index, + } + } - PatternKind::Array { .. } | - PatternKind::Wild | - PatternKind::Binding { .. } | - PatternKind::Leaf { .. } | - PatternKind::Deref { .. } => { - self.error_simplifyable(&match_pair) - } + fn candidate_after_variant_switch<'pat>(&mut self, + match_pair_index: usize, + adt_def: ty::AdtDef<'tcx>, + variant_index: usize, + subpatterns: &'pat [FieldPattern<'tcx>], + candidate: &Candidate<'pat, 'tcx>) + -> Candidate<'pat, 'tcx> { + let match_pair = &candidate.match_pairs[match_pair_index]; + + // So, if we have a match-pattern like `x @ Enum::Variant(P1, P2)`, + // we want to create a set of derived match-patterns like + // `(x as Variant).0 @ P1` and `(x as Variant).1 @ P1`. + let elem = ProjectionElem::Downcast(adt_def, variant_index); + let downcast_lvalue = match_pair.lvalue.clone().elem(elem); // `(x as Variant)` + let consequent_match_pairs = + subpatterns.iter() + .map(|subpattern| { + // e.g., `(x as Variant).0` + let lvalue = downcast_lvalue.clone().field(subpattern.field); + // e.g., `(x as Variant).0 @ P1` + MatchPair::new(lvalue, &subpattern.pattern) + }); + + // In addition, we need all the other match pairs from the old candidate. + let other_match_pairs = + candidate.match_pairs.iter() + .enumerate() + .filter(|&(index, _)| index != match_pair_index) + .map(|(_, mp)| mp.clone()); + + let all_match_pairs = consequent_match_pairs.chain(other_match_pairs).collect(); + + Candidate { + match_pairs: all_match_pairs, + bindings: candidate.bindings.clone(), + guard: candidate.guard.clone(), + arm_index: candidate.arm_index, } } - fn error_simplifyable(&mut self, match_pair: &MatchPair<'tcx>) -> ! { + fn error_simplifyable<'pat>(&mut self, match_pair: &MatchPair<'pat, 'tcx>) -> ! { self.hir.span_bug(match_pair.pattern.span, &format!("simplifyable pattern found: {:?}", match_pair.pattern)) } } + +fn is_switch_ty<'tcx>(ty: Ty<'tcx>) -> bool { + ty.is_integral() || ty.is_char() || ty.is_bool() +} diff --git a/src/librustc_mir/build/matches/util.rs b/src/librustc_mir/build/matches/util.rs index 28925f9b38b4f..18dde5537da4d 100644 --- a/src/librustc_mir/build/matches/util.rs +++ b/src/librustc_mir/build/matches/util.rs @@ -15,26 +15,18 @@ use repr::*; use std::u32; impl<'a,'tcx> Builder<'a,'tcx> { - pub fn field_match_pairs(&mut self, - lvalue: Lvalue<'tcx>, - subpatterns: Vec>) - -> Vec> { - subpatterns.into_iter() + pub fn field_match_pairs<'pat>(&mut self, + lvalue: Lvalue<'tcx>, + subpatterns: &'pat [FieldPattern<'tcx>]) + -> Vec> { + subpatterns.iter() .map(|fieldpat| { let lvalue = lvalue.clone().field(fieldpat.field); - self.match_pair(lvalue, fieldpat.pattern) + MatchPair::new(lvalue, &fieldpat.pattern) }) .collect() } - pub fn match_pair(&mut self, - lvalue: Lvalue<'tcx>, - pattern: PatternRef<'tcx>) - -> MatchPair<'tcx> { - let pattern = self.hir.mirror(pattern); - MatchPair::new(lvalue, pattern) - } - /// When processing an array/slice pattern like `lv @ [x, y, ..s, z]`, /// this function converts the prefix (`x`, `y`) and suffix (`z`) into /// distinct match pairs: @@ -49,18 +41,17 @@ impl<'a,'tcx> Builder<'a,'tcx> { /// tmp0 = lv[2..-1] // using the special Rvalue::Slice /// /// and creates a match pair `tmp0 @ s` - pub fn prefix_suffix_slice(&mut self, - match_pairs: &mut Vec>, - block: BasicBlock, - lvalue: Lvalue<'tcx>, - prefix: Vec>, - opt_slice: Option>, - suffix: Vec>) - -> BlockAnd<()> { + pub fn prefix_suffix_slice<'pat>(&mut self, + match_pairs: &mut Vec>, + block: BasicBlock, + lvalue: Lvalue<'tcx>, + prefix: &'pat [Pattern<'tcx>], + opt_slice: Option<&'pat Pattern<'tcx>>, + suffix: &'pat [Pattern<'tcx>]) + -> BlockAnd<()> { // If there is a `..P` pattern, create a temporary `t0` for // the slice and then a match pair `t0 @ P`: if let Some(slice) = opt_slice { - let slice = self.hir.mirror(slice); let prefix_len = prefix.len(); let suffix_len = suffix.len(); let rvalue = Rvalue::Slice { @@ -79,17 +70,17 @@ impl<'a,'tcx> Builder<'a,'tcx> { } /// Helper for `prefix_suffix_slice` which just processes the prefix and suffix. - fn prefix_suffix(&mut self, - match_pairs: &mut Vec>, - lvalue: Lvalue<'tcx>, - prefix: Vec>, - suffix: Vec>) { + fn prefix_suffix<'pat>(&mut self, + match_pairs: &mut Vec>, + lvalue: Lvalue<'tcx>, + prefix: &'pat [Pattern<'tcx>], + suffix: &'pat [Pattern<'tcx>]) { let min_length = prefix.len() + suffix.len(); assert!(min_length < u32::MAX as usize); let min_length = min_length as u32; let prefix_pairs: Vec<_> = - prefix.into_iter() + prefix.iter() .enumerate() .map(|(idx, subpattern)| { let elem = ProjectionElem::ConstantIndex { @@ -98,12 +89,12 @@ impl<'a,'tcx> Builder<'a,'tcx> { from_end: false, }; let lvalue = lvalue.clone().elem(elem); - self.match_pair(lvalue, subpattern) + MatchPair::new(lvalue, subpattern) }) .collect(); let suffix_pairs: Vec<_> = - suffix.into_iter() + suffix.iter() .rev() .enumerate() .map(|(idx, subpattern)| { @@ -113,7 +104,7 @@ impl<'a,'tcx> Builder<'a,'tcx> { from_end: true, }; let lvalue = lvalue.clone().elem(elem); - self.match_pair(lvalue, subpattern) + MatchPair::new(lvalue, subpattern) }) .collect(); @@ -121,8 +112,8 @@ impl<'a,'tcx> Builder<'a,'tcx> { } } -impl<'tcx> MatchPair<'tcx> { - pub fn new(lvalue: Lvalue<'tcx>, pattern: Pattern<'tcx>) -> MatchPair<'tcx> { +impl<'pat, 'tcx> MatchPair<'pat, 'tcx> { + pub fn new(lvalue: Lvalue<'tcx>, pattern: &'pat Pattern<'tcx>) -> MatchPair<'pat, 'tcx> { MatchPair { lvalue: lvalue, pattern: pattern, diff --git a/src/librustc_mir/build/misc.rs b/src/librustc_mir/build/misc.rs index 86b6df19b77e7..41274f3f3736e 100644 --- a/src/librustc_mir/build/misc.rs +++ b/src/librustc_mir/build/misc.rs @@ -34,20 +34,17 @@ impl<'a,'tcx> Builder<'a,'tcx> { lvalue } - pub fn push_literal(&mut self, - block: BasicBlock, - span: Span, - ty: Ty<'tcx>, - literal: Literal<'tcx>) - -> Lvalue<'tcx> { - let temp = self.temp(ty.clone()); + pub fn literal_operand(&mut self, + span: Span, + ty: Ty<'tcx>, + literal: Literal<'tcx>) + -> Operand<'tcx> { let constant = Constant { span: span, ty: ty, literal: literal, }; - self.cfg.push_assign_constant(block, span, &temp, constant); - temp + Operand::Constant(constant) } pub fn push_usize(&mut self, block: BasicBlock, span: Span, value: usize) -> Lvalue<'tcx> { @@ -63,15 +60,14 @@ impl<'a,'tcx> Builder<'a,'tcx> { temp } - pub fn push_item_ref(&mut self, - block: BasicBlock, - span: Span, - item_ref: ItemRef<'tcx>) - -> Lvalue<'tcx> { + pub fn item_ref_operand(&mut self, + span: Span, + item_ref: ItemRef<'tcx>) + -> Operand<'tcx> { let literal = Literal::Item { def_id: item_ref.def_id, substs: item_ref.substs, }; - self.push_literal(block, span, item_ref.ty, literal) + self.literal_operand(span, item_ref.ty, literal) } } diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index 857540e2109c0..eb03727d9b2c0 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -8,15 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use hair; +use hair::cx::Cx; use rustc::middle::region::CodeExtent; -use rustc::middle::ty::Ty; +use rustc::middle::ty::{FnOutput, Ty}; use rustc_data_structures::fnv::FnvHashMap; use rustc_front::hir; use repr::*; use syntax::ast; use syntax::codemap::Span; -use tcx::{Cx, PatNode}; struct Builder<'a, 'tcx: 'a> { hir: Cx<'a, 'tcx>, @@ -75,13 +74,14 @@ macro_rules! unpack { /////////////////////////////////////////////////////////////////////////// // construct() -- the main entry point for building MIR for a function -pub fn construct<'a, 'tcx>(mut hir: Cx<'a, 'tcx>, - _span: Span, - implicit_arguments: Vec>, - explicit_arguments: Vec<(Ty<'tcx>, PatNode<'tcx>)>, - argument_extent: CodeExtent, - ast_block: &'tcx hir::Block) - -> Mir<'tcx> { +pub fn construct<'a,'tcx>(mut hir: Cx<'a,'tcx>, + _span: Span, + implicit_arguments: Vec>, + explicit_arguments: Vec<(Ty<'tcx>, &'tcx hir::Pat)>, + argument_extent: CodeExtent, + return_ty: FnOutput<'tcx>, + ast_block: &'tcx hir::Block) + -> Mir<'tcx> { let cfg = CFG { basic_blocks: vec![] }; // it's handy to have a temporary of type `()` sometimes, so make @@ -121,6 +121,7 @@ pub fn construct<'a, 'tcx>(mut hir: Cx<'a, 'tcx>, var_decls: builder.var_decls, arg_decls: arg_decls, temp_decls: builder.temp_decls, + return_ty: return_ty, } } @@ -128,7 +129,7 @@ impl<'a,'tcx> Builder<'a,'tcx> { fn args_and_body(&mut self, mut block: BasicBlock, implicit_arguments: Vec>, - explicit_arguments: Vec<(Ty<'tcx>, PatNode<'tcx>)>, + explicit_arguments: Vec<(Ty<'tcx>, &'tcx hir::Pat)>, argument_extent: CodeExtent, ast_block: &'tcx hir::Block) -> BlockAnd>> @@ -146,9 +147,10 @@ impl<'a,'tcx> Builder<'a,'tcx> { .enumerate() .map(|(index, (ty, pattern))| { let lvalue = Lvalue::Arg(index as u32); + let pattern = this.hir.irrefutable_pat(pattern); unpack!(block = this.lvalue_into_pattern(block, argument_extent, - hair::PatternRef::Hair(pattern), + pattern, &lvalue)); ArgDecl { ty: ty } }); diff --git a/src/librustc_mir/build/stmt.rs b/src/librustc_mir/build/stmt.rs index 01fda2498f712..0c0816a2d9d28 100644 --- a/src/librustc_mir/build/stmt.rs +++ b/src/librustc_mir/build/stmt.rs @@ -40,7 +40,7 @@ impl<'a,'tcx> Builder<'a,'tcx> { StmtKind::Let { remainder_scope, init_scope, pattern, initializer: None, stmts } => { this.in_scope(remainder_scope, block, |this| { unpack!(block = this.in_scope(init_scope, block, |this| { - this.declare_bindings(remainder_scope, pattern); + this.declare_bindings(remainder_scope, &pattern); block.unit() })); this.stmts(block, stmts) diff --git a/src/librustc_mir/tcx/block.rs b/src/librustc_mir/hair/cx/block.rs similarity index 80% rename from src/librustc_mir/tcx/block.rs rename to src/librustc_mir/hair/cx/block.rs index dc168bc7c2b6c..bedcefe3b0dac 100644 --- a/src/librustc_mir/tcx/block.rs +++ b/src/librustc_mir/hair/cx/block.rs @@ -9,10 +9,8 @@ // except according to those terms. use hair::*; - -use tcx::Cx; -use tcx::pattern::PatNode; -use tcx::to_ref::ToRef; +use hair::cx::Cx; +use hair::cx::to_ref::ToRef; use rustc::middle::region::{BlockRemainder, CodeExtentData}; use rustc_front::hir; use syntax::ast; @@ -34,22 +32,11 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Block { } } -impl<'tcx> Mirror<'tcx> for &'tcx hir::Stmt { - type Output = Stmt<'tcx>; - - fn make_mirror<'a>(self, _cx: &mut Cx<'a, 'tcx>) -> Stmt<'tcx> { - // In order to get the scoping correct, we eagerly mirror - // statements when we translate the enclosing block, so we - // should in fact never get to this point. - panic!("statements are eagerly mirrored"); - } -} - -fn mirror_stmts<'a, 'tcx: 'a, STMTS>(cx: &mut Cx<'a, 'tcx>, - block_id: ast::NodeId, - mut stmts: STMTS) - -> Vec> - where STMTS: Iterator)> +fn mirror_stmts<'a,'tcx:'a,STMTS>(cx: &mut Cx<'a,'tcx>, + block_id: ast::NodeId, + mut stmts: STMTS) + -> Vec> + where STMTS: Iterator)> { let mut result = vec![]; while let Some((index, stmt)) = stmts.next() { @@ -77,12 +64,13 @@ fn mirror_stmts<'a, 'tcx: 'a, STMTS>(cx: &mut Cx<'a, 'tcx>, // they are within the scope of this let: let following_stmts = mirror_stmts(cx, block_id, stmts); + let pattern = cx.irrefutable_pat(&local.pat); result.push(StmtRef::Mirror(Box::new(Stmt { span: stmt.span, kind: StmtKind::Let { remainder_scope: remainder_extent, init_scope: cx.tcx.region_maps.node_extent(id), - pattern: PatNode::irrefutable(&local.pat).to_ref(), + pattern: pattern, initializer: local.init.to_ref(), stmts: following_stmts, }, diff --git a/src/librustc_mir/tcx/expr.rs b/src/librustc_mir/hair/cx/expr.rs similarity index 90% rename from src/librustc_mir/tcx/expr.rs rename to src/librustc_mir/hair/cx/expr.rs index 9f7ecf522876f..c546a264be1bb 100644 --- a/src/librustc_mir/tcx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -11,19 +11,17 @@ use hair::*; use repr::*; use rustc_data_structures::fnv::FnvHashMap; -use std::rc::Rc; -use tcx::Cx; -use tcx::block; -use tcx::pattern::PatNode; -use tcx::to_ref::ToRef; +use hair::cx::Cx; +use hair::cx::block; +use hair::cx::to_ref::ToRef; use rustc::front::map; -use rustc::middle::const_eval; use rustc::middle::def; use rustc::middle::region::CodeExtent; use rustc::middle::pat_util; -use rustc::middle::ty::{self, Ty}; +use rustc::middle::ty::{self, VariantDef, Ty}; use rustc_front::hir; use rustc_front::util as hir_util; +use syntax::ext::mtwt; use syntax::parse::token; use syntax::ptr::P; @@ -81,10 +79,9 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr { } } - hir::ExprLit(..) => { - let value = const_eval::eval_const_expr(cx.tcx, self); - ExprKind::Literal { literal: Literal::Value { value: value } } - } + hir::ExprLit(..) => ExprKind::Literal { + literal: cx.const_eval_literal(self) + }, hir::ExprBinary(op, ref lhs, ref rhs) => { if cx.tcx.is_method_call(self.id) { @@ -170,11 +167,12 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr { hir::ExprStruct(_, ref fields, ref base) => { match expr_ty.sty { ty::TyStruct(adt, substs) => { + let field_refs = field_refs(&adt.variants[0], fields); ExprKind::Adt { adt_def: adt, variant_index: 0, substs: substs, - fields: fields.to_ref(), + fields: field_refs, base: base.to_ref(), } } @@ -183,11 +181,12 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr { def::DefVariant(enum_id, variant_id, true) => { debug_assert!(adt.did == enum_id); let index = adt.variant_index_with_id(variant_id); + let field_refs = field_refs(&adt.variants[index], fields); ExprKind::Adt { adt_def: adt, variant_index: index, substs: substs, - fields: fields.to_ref(), + fields: field_refs, base: base.to_ref(), } } @@ -234,15 +233,14 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr { let (adt_def, substs) = match range_ty.sty { ty::TyStruct(adt_def, substs) => (adt_def, substs), _ => { - cx.tcx.sess.span_bug(self.span, &format!("unexpanded ast")); + cx.tcx.sess.span_bug(self.span, "unexpanded ast"); } }; - let field_expr_ref = |s: &'tcx P, nm: &str| { - FieldExprRef { - name: Field::Named(token::intern(nm)), - expr: s.to_ref(), - } + let field_expr_ref = |s: &'tcx P, name: &str| { + let name = token::intern(name); + let index = adt_def.variants[0].index_of_field_named(name).unwrap(); + FieldExprRef { name: Field::new(index), expr: s.to_ref() } }; let start_field = start.as_ref() @@ -272,8 +270,17 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr { // Now comes the rote stuff: - hir::ExprRepeat(ref v, ref c) => - ExprKind::Repeat { value: v.to_ref(), count: c.to_ref() }, + hir::ExprRepeat(ref v, ref c) => ExprKind::Repeat { + value: v.to_ref(), + count: Expr { + ty: cx.tcx.expr_ty(c), + temp_lifetime: None, + span: c.span, + kind: ExprKind::Literal { + literal: cx.const_eval_literal(c) + } + }.to_ref() + }, hir::ExprRet(ref v) => ExprKind::Return { value: v.to_ref() }, hir::ExprBreak(label) => @@ -293,12 +300,25 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr { hir::ExprLoop(ref body, _) => ExprKind::Loop { condition: None, body: block::to_expr_ref(cx, body) }, - hir::ExprField(ref source, name) => - ExprKind::Field { lhs: source.to_ref(), - name: Field::Named(name.node) }, + hir::ExprField(ref source, name) => { + let index = match cx.tcx.expr_ty_adjusted(source).sty { + ty::TyStruct(adt_def, _) => + adt_def.variants[0].index_of_field_named(name.node), + ref ty => + cx.tcx.sess.span_bug( + self.span, + &format!("field of non-struct: {:?}", ty)), + }; + let index = index.unwrap_or_else(|| { + cx.tcx.sess.span_bug( + self.span, + &format!("no index found for field `{}`", name.node)); + }); + ExprKind::Field { lhs: source.to_ref(), name: Field::new(index) } + } hir::ExprTupField(ref source, index) => ExprKind::Field { lhs: source.to_ref(), - name: Field::Indexed(index.node) }, + name: Field::new(index.node as usize) }, hir::ExprCast(ref source, _) => ExprKind::Cast { source: source.to_ref() }, hir::ExprBox(ref value) => @@ -366,14 +386,7 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr { }; } - if let Some(target) = adj.unsize { - expr = Expr { - temp_lifetime: temp_lifetime, - ty: target, - span: self.span, - kind: ExprKind::Unsize { source: expr.to_ref() }, - }; - } else if let Some(autoref) = adj.autoref { + if let Some(autoref) = adj.autoref { let adjusted_ty = expr.ty.adjust_for_autoref(cx.tcx, Some(autoref)); match autoref { ty::adjustment::AutoPtr(r, m) => { @@ -413,6 +426,15 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr { } } } + + if let Some(target) = adj.unsize { + expr = Expr { + temp_lifetime: temp_lifetime, + ty: target, + span: self.span, + kind: ExprKind::Unsize { source: expr.to_ref() }, + }; + } } } @@ -472,19 +494,20 @@ fn to_borrow_kind(m: hir::Mutability) -> BorrowKind { } } -fn convert_arm<'a, 'tcx: 'a>(cx: &Cx<'a, 'tcx>, arm: &'tcx hir::Arm) -> Arm<'tcx> { - let map = if arm.pats.len() == 1 { +fn convert_arm<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>, arm: &'tcx hir::Arm) -> Arm<'tcx> { + let mut map; + let opt_map = if arm.pats.len() == 1 { None } else { - let mut map = FnvHashMap(); - pat_util::pat_bindings(&cx.tcx.def_map, &arm.pats[0], |_, p_id, _, path| { - map.insert(path.node, p_id); + map = FnvHashMap(); + pat_util::pat_bindings_hygienic(&cx.tcx.def_map, &arm.pats[0], |_, p_id, _, path| { + map.insert(mtwt::resolve(path.node), p_id); }); - Some(Rc::new(map)) + Some(&map) }; Arm { - patterns: arm.pats.iter().map(|p| PatNode::new(p, map.clone()).to_ref()).collect(), + patterns: arm.pats.iter().map(|p| cx.refutable_pat(opt_map, p)).collect(), guard: arm.guard.to_ref(), body: arm.body.to_ref(), } @@ -541,14 +564,12 @@ fn convert_var<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>, match expr.node { hir::ExprClosure(_, _, ref body) => body.id, _ => { - cx.tcx.sess.span_bug(expr.span, - &format!("closure expr is not a closure expr")); + cx.tcx.sess.span_bug(expr.span, "closure expr is not a closure expr"); } } } _ => { - cx.tcx.sess.span_bug(expr.span, - &format!("ast-map has garbage for closure expr")); + cx.tcx.sess.span_bug(expr.span, "ast-map has garbage for closure expr"); } }; @@ -616,7 +637,7 @@ fn convert_var<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>, // at this point we have `self.n`, which loads up the upvar let field_kind = ExprKind::Field { lhs: self_expr.to_ref(), - name: Field::Indexed(index), + name: Field::new(index), }; // ...but the upvar might be an `&T` or `&mut T` capture, at which @@ -814,3 +835,15 @@ fn loop_label<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>, expr: &'tcx hir::Expr) -> Cod } } } + +fn field_refs<'tcx>(variant: VariantDef<'tcx>, + fields: &'tcx [hir::Field]) + -> Vec> +{ + fields.iter() + .map(|field| FieldExprRef { + name: Field::new(variant.index_of_field_named(field.name.node).unwrap()), + expr: field.expr.to_ref(), + }) + .collect() +} diff --git a/src/librustc_mir/hair/cx/mod.rs b/src/librustc_mir/hair/cx/mod.rs new file mode 100644 index 0000000000000..cb04df9104225 --- /dev/null +++ b/src/librustc_mir/hair/cx/mod.rs @@ -0,0 +1,152 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +/*! + * This module contains the code to convert from the wacky tcx data + * structures into the hair. The `builder` is generally ignorant of + * the tcx etc, and instead goes through the `Cx` for most of its + * work. + */ + +use hair::*; +use repr::*; + +use rustc::middle::const_eval::{self, ConstVal}; +use rustc::middle::def_id::DefId; +use rustc::middle::infer::InferCtxt; +use rustc::middle::subst::{Subst, Substs}; +use rustc::middle::ty::{self, Ty}; +use syntax::codemap::Span; +use syntax::parse::token; +use rustc_front::hir; + +#[derive(Copy, Clone)] +pub struct Cx<'a, 'tcx: 'a> { + tcx: &'a ty::ctxt<'tcx>, + infcx: &'a InferCtxt<'a, 'tcx>, +} + +impl<'a,'tcx> Cx<'a,'tcx> { + pub fn new(infcx: &'a InferCtxt<'a, 'tcx>) -> Cx<'a, 'tcx> { + Cx { + tcx: infcx.tcx, + infcx: infcx, + } + } +} + +impl<'a,'tcx:'a> Cx<'a, 'tcx> { + /// Normalizes `ast` into the appropriate `mirror` type. + pub fn mirror>(&mut self, ast: M) -> M::Output { + ast.make_mirror(self) + } + + pub fn unit_ty(&mut self) -> Ty<'tcx> { + self.tcx.mk_nil() + } + + pub fn usize_ty(&mut self) -> Ty<'tcx> { + self.tcx.types.usize + } + + pub fn usize_literal(&mut self, value: usize) -> Literal<'tcx> { + Literal::Value { value: ConstVal::Uint(value as u64) } + } + + pub fn bool_ty(&mut self) -> Ty<'tcx> { + self.tcx.types.bool + } + + pub fn true_literal(&mut self) -> Literal<'tcx> { + Literal::Value { value: ConstVal::Bool(true) } + } + + pub fn false_literal(&mut self) -> Literal<'tcx> { + Literal::Value { value: ConstVal::Bool(false) } + } + + pub fn const_eval_literal(&mut self, e: &hir::Expr) -> Literal<'tcx> { + Literal::Value { value: const_eval::eval_const_expr(self.tcx, e) } + } + + pub fn partial_eq(&mut self, ty: Ty<'tcx>) -> ItemRef<'tcx> { + let eq_def_id = self.tcx.lang_items.eq_trait().unwrap(); + self.cmp_method_ref(eq_def_id, "eq", ty) + } + + pub fn partial_le(&mut self, ty: Ty<'tcx>) -> ItemRef<'tcx> { + let ord_def_id = self.tcx.lang_items.ord_trait().unwrap(); + self.cmp_method_ref(ord_def_id, "le", ty) + } + + pub fn num_variants(&mut self, adt_def: ty::AdtDef<'tcx>) -> usize { + adt_def.variants.len() + } + + pub fn all_fields(&mut self, adt_def: ty::AdtDef<'tcx>, variant_index: usize) -> Vec { + (0..adt_def.variants[variant_index].fields.len()) + .map(Field::new) + .collect() + } + + pub fn needs_drop(&mut self, ty: Ty<'tcx>, span: Span) -> bool { + if self.infcx.type_moves_by_default(ty, span) { + // FIXME(#21859) we should do an add'l check here to determine if + // any dtor will execute, but the relevant fn + // (`type_needs_drop`) is currently factored into + // `librustc_trans`, so we can't easily do so. + true + } else { + // if type implements Copy, cannot require drop + false + } + } + + pub fn span_bug(&mut self, span: Span, message: &str) -> ! { + self.tcx.sess.span_bug(span, message) + } + + pub fn tcx(&self) -> &'a ty::ctxt<'tcx> { + self.tcx + } + + fn cmp_method_ref(&mut self, + trait_def_id: DefId, + method_name: &str, + arg_ty: Ty<'tcx>) + -> ItemRef<'tcx> { + let method_name = token::intern(method_name); + let substs = Substs::new_trait(vec![arg_ty], vec![], arg_ty); + for trait_item in self.tcx.trait_items(trait_def_id).iter() { + match *trait_item { + ty::ImplOrTraitItem::MethodTraitItem(ref method) => { + if method.name == method_name { + let method_ty = self.tcx.lookup_item_type(method.def_id); + let method_ty = method_ty.ty.subst(self.tcx, &substs); + return ItemRef { + ty: method_ty, + def_id: method.def_id, + substs: self.tcx.mk_substs(substs), + }; + } + } + ty::ImplOrTraitItem::ConstTraitItem(..) | + ty::ImplOrTraitItem::TypeTraitItem(..) => {} + } + } + + self.tcx.sess.bug(&format!("found no method `{}` in `{:?}`", method_name, trait_def_id)); + } +} + +mod block; +mod expr; +mod pattern; +mod to_ref; diff --git a/src/librustc_mir/tcx/pattern.rs b/src/librustc_mir/hair/cx/pattern.rs similarity index 54% rename from src/librustc_mir/tcx/pattern.rs rename to src/librustc_mir/hair/cx/pattern.rs index db4346364968c..3d5cb83197585 100644 --- a/src/librustc_mir/tcx/pattern.rs +++ b/src/librustc_mir/hair/cx/pattern.rs @@ -9,12 +9,9 @@ // except according to those terms. use hair::*; +use hair::cx::Cx; use repr::*; - use rustc_data_structures::fnv::FnvHashMap; -use std::rc::Rc; -use tcx::Cx; -use tcx::to_ref::ToRef; use rustc::middle::const_eval; use rustc::middle::def; use rustc::middle::pat_util::{pat_is_resolved_const, pat_is_binding}; @@ -22,6 +19,7 @@ use rustc::middle::subst::Substs; use rustc::middle::ty::{self, Ty}; use rustc_front::hir; use syntax::ast; +use syntax::ext::mtwt; use syntax::ptr::P; /// When there are multiple patterns in a single arm, each one has its @@ -37,183 +35,111 @@ use syntax::ptr::P; /// _ => { ... } /// } /// ``` -#[derive(Clone, Debug)] -pub struct PatNode<'tcx> { - pat: &'tcx hir::Pat, - binding_map: Option>>, +struct PatCx<'patcx, 'cx: 'patcx, 'tcx: 'cx> { + cx: &'patcx mut Cx<'cx, 'tcx>, + binding_map: Option<&'patcx FnvHashMap>, } -impl<'tcx> PatNode<'tcx> { - pub fn new(pat: &'tcx hir::Pat, - binding_map: Option>>) - -> PatNode<'tcx> { - PatNode { - pat: pat, - binding_map: binding_map, - } - } - - pub fn irrefutable(pat: &'tcx hir::Pat) -> PatNode<'tcx> { - PatNode::new(pat, None) - } - - fn pat_ref<'a>(&self, pat: &'tcx hir::Pat) -> PatternRef<'tcx> { - PatNode::new(pat, self.binding_map.clone()).to_ref() +impl<'cx, 'tcx> Cx<'cx, 'tcx> { + pub fn irrefutable_pat(&mut self, pat: &'tcx hir::Pat) -> Pattern<'tcx> { + PatCx::new(self, None).to_pat(pat) } - fn pat_refs<'a>(&self, pats: &'tcx Vec>) -> Vec> { - pats.iter().map(|p| self.pat_ref(p)).collect() - } - - fn opt_pat_ref<'a>(&self, pat: &'tcx Option>) -> Option> { - pat.as_ref().map(|p| self.pat_ref(p)) - } - - fn slice_or_array_pattern<'a>(&self, - cx: &mut Cx<'a, 'tcx>, - ty: Ty<'tcx>, - prefix: &'tcx Vec>, - slice: &'tcx Option>, - suffix: &'tcx Vec>) - -> PatternKind<'tcx> { - match ty.sty { - ty::TySlice(..) => - // matching a slice or fixed-length array - PatternKind::Slice { - prefix: self.pat_refs(prefix), - slice: self.opt_pat_ref(slice), - suffix: self.pat_refs(suffix), - }, - - ty::TyArray(_, len) => { - // fixed-length array - assert!(len >= prefix.len() + suffix.len()); - PatternKind::Array { - prefix: self.pat_refs(prefix), - slice: self.opt_pat_ref(slice), - suffix: self.pat_refs(suffix), - } - } - - _ => { - cx.tcx.sess.span_bug(self.pat.span, "unexpanded macro or bad constant etc"); - } - } + pub fn refutable_pat(&mut self, + binding_map: Option<&FnvHashMap>, + pat: &'tcx hir::Pat) + -> Pattern<'tcx> { + PatCx::new(self, binding_map).to_pat(pat) } +} - fn variant_or_leaf<'a>(&self, - cx: &mut Cx<'a, 'tcx>, - subpatterns: Vec>) - -> PatternKind<'tcx> { - let def = cx.tcx.def_map.borrow().get(&self.pat.id).unwrap().full_def(); - match def { - def::DefVariant(enum_id, variant_id, _) => { - let adt_def = cx.tcx.lookup_adt_def(enum_id); - if adt_def.variants.len() > 1 { - PatternKind::Variant { - adt_def: adt_def, - variant_index: adt_def.variant_index_with_id(variant_id), - subpatterns: subpatterns, - } - } else { - PatternKind::Leaf { subpatterns: subpatterns } - } - } - - // NB: resolving to DefStruct means the struct *constructor*, - // not the struct as a type. - def::DefStruct(..) | def::DefTy(..) => { - PatternKind::Leaf { subpatterns: subpatterns } - } - - _ => { - cx.tcx.sess.span_bug(self.pat.span, - &format!("inappropriate def for pattern: {:?}", def)); - } +impl<'patcx, 'cx, 'tcx> PatCx<'patcx, 'cx, 'tcx> { + fn new(cx: &'patcx mut Cx<'cx, 'tcx>, + binding_map: Option<&'patcx FnvHashMap>) + -> PatCx<'patcx, 'cx, 'tcx> { + PatCx { + cx: cx, + binding_map: binding_map, } } -} - -impl<'tcx> Mirror<'tcx> for PatNode<'tcx> { - type Output = Pattern<'tcx>; - fn make_mirror<'a>(self, cx: &mut Cx<'a, 'tcx>) -> Pattern<'tcx> { - let kind = match self.pat.node { + fn to_pat(&mut self, pat: &'tcx hir::Pat) -> Pattern<'tcx> { + let kind = match pat.node { hir::PatWild => PatternKind::Wild, hir::PatLit(ref value) => { - let value = const_eval::eval_const_expr(cx.tcx, value); + let value = const_eval::eval_const_expr(self.cx.tcx, value); let value = Literal::Value { value: value }; PatternKind::Constant { value: value } } hir::PatRange(ref lo, ref hi) => { - let lo = const_eval::eval_const_expr(cx.tcx, lo); + let lo = const_eval::eval_const_expr(self.cx.tcx, lo); let lo = Literal::Value { value: lo }; - let hi = const_eval::eval_const_expr(cx.tcx, hi); + let hi = const_eval::eval_const_expr(self.cx.tcx, hi); let hi = Literal::Value { value: hi }; PatternKind::Range { lo: lo, hi: hi } }, hir::PatEnum(..) | hir::PatIdent(..) | hir::PatQPath(..) - if pat_is_resolved_const(&cx.tcx.def_map, self.pat) => + if pat_is_resolved_const(&self.cx.tcx.def_map.borrow(), pat) => { - let def = cx.tcx.def_map.borrow().get(&self.pat.id).unwrap().full_def(); + let def = self.cx.tcx.def_map.borrow().get(&pat.id).unwrap().full_def(); match def { def::DefConst(def_id) | def::DefAssociatedConst(def_id) => - match const_eval::lookup_const_by_id(cx.tcx, def_id, Some(self.pat.id)) { + match const_eval::lookup_const_by_id(self.cx.tcx, def_id, Some(pat.id)) { Some(const_expr) => { let opt_value = const_eval::eval_const_expr_partial( - cx.tcx, const_expr, + self.cx.tcx, const_expr, const_eval::EvalHint::ExprTypeChecked, None); let literal = if let Ok(value) = opt_value { Literal::Value { value: value } } else { - let substs = cx.tcx.mk_substs(Substs::empty()); + let substs = self.cx.tcx.mk_substs(Substs::empty()); Literal::Item { def_id: def_id, substs: substs } }; PatternKind::Constant { value: literal } } None => { - cx.tcx.sess.span_bug( - self.pat.span, + self.cx.tcx.sess.span_bug( + pat.span, &format!("cannot eval constant: {:?}", def_id)) } }, _ => - cx.tcx.sess.span_bug( - self.pat.span, + self.cx.tcx.sess.span_bug( + pat.span, &format!("def not a constant: {:?}", def)), } } hir::PatRegion(ref subpattern, _) | hir::PatBox(ref subpattern) => { - PatternKind::Deref { subpattern: self.pat_ref(subpattern) } + PatternKind::Deref { subpattern: self.to_pat(subpattern) } } hir::PatVec(ref prefix, ref slice, ref suffix) => { - let ty = cx.tcx.node_id_to_type(self.pat.id); + let ty = self.cx.tcx.node_id_to_type(pat.id); match ty.sty { ty::TyRef(_, mt) => PatternKind::Deref { subpattern: Pattern { ty: mt.ty, - span: self.pat.span, - kind: self.slice_or_array_pattern(cx, mt.ty, prefix, - slice, suffix), - }.to_ref() + span: pat.span, + kind: Box::new(self.slice_or_array_pattern(pat, mt.ty, prefix, + slice, suffix)), + }, }, ty::TySlice(..) | ty::TyArray(..) => - self.slice_or_array_pattern(cx, ty, prefix, slice, suffix), + self.slice_or_array_pattern(pat, ty, prefix, slice, suffix), ref sty => - cx.tcx.sess.span_bug( - self.pat.span, + self.cx.tcx.sess.span_bug( + pat.span, &format!("unexpanded type for vector pattern: {:?}", sty)), } } @@ -222,9 +148,9 @@ impl<'tcx> Mirror<'tcx> for PatNode<'tcx> { let subpatterns = subpatterns.iter() .enumerate() - .map(|(i, subpattern)| FieldPatternRef { - field: Field::Indexed(i), - pattern: self.pat_ref(subpattern), + .map(|(i, subpattern)| FieldPattern { + field: Field::new(i), + pattern: self.to_pat(subpattern), }) .collect(); @@ -232,13 +158,13 @@ impl<'tcx> Mirror<'tcx> for PatNode<'tcx> { } hir::PatIdent(bm, ref ident, ref sub) - if pat_is_binding(&cx.tcx.def_map, self.pat) => + if pat_is_binding(&self.cx.tcx.def_map.borrow(), pat) => { let id = match self.binding_map { - None => self.pat.id, - Some(ref map) => map[&ident.node.name], + None => pat.id, + Some(ref map) => map[&mtwt::resolve(ident.node)], }; - let var_ty = cx.tcx.node_id_to_type(self.pat.id); + let var_ty = self.cx.tcx.node_id_to_type(pat.id); let region = match var_ty.sty { ty::TyRef(&r, _) => Some(r), _ => None, @@ -259,12 +185,12 @@ impl<'tcx> Mirror<'tcx> for PatNode<'tcx> { name: ident.node.name, var: id, ty: var_ty, - subpattern: self.opt_pat_ref(sub), + subpattern: self.to_opt_pat(sub), } } hir::PatIdent(..) => { - self.variant_or_leaf(cx, vec![]) + self.variant_or_leaf(pat, vec![]) } hir::PatEnum(_, ref opt_subpatterns) => { @@ -272,36 +198,131 @@ impl<'tcx> Mirror<'tcx> for PatNode<'tcx> { opt_subpatterns.iter() .flat_map(|v| v.iter()) .enumerate() - .map(|(i, field)| FieldPatternRef { - field: Field::Indexed(i), - pattern: self.pat_ref(field), + .map(|(i, field)| FieldPattern { + field: Field::new(i), + pattern: self.to_pat(field), }) .collect(); - self.variant_or_leaf(cx, subpatterns) + self.variant_or_leaf(pat, subpatterns) } hir::PatStruct(_, ref fields, _) => { + let pat_ty = self.cx.tcx.node_id_to_type(pat.id); + let adt_def = match pat_ty.sty { + ty::TyStruct(adt_def, _) | ty::TyEnum(adt_def, _) => adt_def, + _ => { + self.cx.tcx.sess.span_bug( + pat.span, + "struct pattern not applied to struct or enum"); + } + }; + + let def = self.cx.tcx.def_map.borrow().get(&pat.id).unwrap().full_def(); + let variant_def = adt_def.variant_of_def(def); + let subpatterns = fields.iter() - .map(|field| FieldPatternRef { - field: Field::Named(field.node.name), - pattern: self.pat_ref(&field.node.pat), + .map(|field| { + let index = variant_def.index_of_field_named(field.node.name); + let index = index.unwrap_or_else(|| { + self.cx.tcx.sess.span_bug( + pat.span, + &format!("no field with name {:?}", field.node.name)); + }); + FieldPattern { + field: Field::new(index), + pattern: self.to_pat(&field.node.pat), + } }) .collect(); - self.variant_or_leaf(cx, subpatterns) + + self.variant_or_leaf(pat, subpatterns) } hir::PatQPath(..) => { - cx.tcx.sess.span_bug(self.pat.span, "unexpanded macro or bad constant etc"); + self.cx.tcx.sess.span_bug(pat.span, "unexpanded macro or bad constant etc"); } }; - let ty = cx.tcx.node_id_to_type(self.pat.id); + let ty = self.cx.tcx.node_id_to_type(pat.id); Pattern { - span: self.pat.span, + span: pat.span, ty: ty, - kind: kind, + kind: Box::new(kind), + } + } + + fn to_pats(&mut self, pats: &'tcx Vec>) -> Vec> { + pats.iter().map(|p| self.to_pat(p)).collect() + } + + fn to_opt_pat(&mut self, pat: &'tcx Option>) -> Option> { + pat.as_ref().map(|p| self.to_pat(p)) + } + + fn slice_or_array_pattern(&mut self, + pat: &'tcx hir::Pat, + ty: Ty<'tcx>, + prefix: &'tcx Vec>, + slice: &'tcx Option>, + suffix: &'tcx Vec>) + -> PatternKind<'tcx> { + match ty.sty { + ty::TySlice(..) => { + // matching a slice or fixed-length array + PatternKind::Slice { + prefix: self.to_pats(prefix), + slice: self.to_opt_pat(slice), + suffix: self.to_pats(suffix), + } + } + + ty::TyArray(_, len) => { + // fixed-length array + assert!(len >= prefix.len() + suffix.len()); + PatternKind::Array { + prefix: self.to_pats(prefix), + slice: self.to_opt_pat(slice), + suffix: self.to_pats(suffix), + } + } + + _ => { + self.cx.tcx.sess.span_bug(pat.span, "unexpanded macro or bad constant etc"); + } + } + } + + fn variant_or_leaf(&mut self, + pat: &'tcx hir::Pat, + subpatterns: Vec>) + -> PatternKind<'tcx> { + let def = self.cx.tcx.def_map.borrow().get(&pat.id).unwrap().full_def(); + match def { + def::DefVariant(enum_id, variant_id, _) => { + let adt_def = self.cx.tcx.lookup_adt_def(enum_id); + if adt_def.variants.len() > 1 { + PatternKind::Variant { + adt_def: adt_def, + variant_index: adt_def.variant_index_with_id(variant_id), + subpatterns: subpatterns, + } + } else { + PatternKind::Leaf { subpatterns: subpatterns } + } + } + + // NB: resolving to DefStruct means the struct *constructor*, + // not the struct as a type. + def::DefStruct(..) | def::DefTy(..) => { + PatternKind::Leaf { subpatterns: subpatterns } + } + + _ => { + self.cx.tcx.sess.span_bug(pat.span, + &format!("inappropriate def for pattern: {:?}", def)); + } } } } diff --git a/src/librustc_mir/tcx/to_ref.rs b/src/librustc_mir/hair/cx/to_ref.rs similarity index 70% rename from src/librustc_mir/tcx/to_ref.rs rename to src/librustc_mir/hair/cx/to_ref.rs index 13ca82e3e4c71..da200a8a33f08 100644 --- a/src/librustc_mir/tcx/to_ref.rs +++ b/src/librustc_mir/hair/cx/to_ref.rs @@ -9,9 +9,7 @@ // except according to those terms. use hair::*; -use repr::*; -use tcx::pattern::PatNode; use rustc_front::hir; use syntax::ptr::P; @@ -44,22 +42,6 @@ impl<'a,'tcx:'a> ToRef for Expr<'tcx> { } } -impl<'a,'tcx:'a> ToRef for PatNode<'tcx> { - type Output = PatternRef<'tcx>; - - fn to_ref(self) -> PatternRef<'tcx> { - PatternRef::Hair(self) - } -} - -impl<'a,'tcx:'a> ToRef for Pattern<'tcx> { - type Output = PatternRef<'tcx>; - - fn to_ref(self) -> PatternRef<'tcx> { - PatternRef::Mirror(Box::new(self)) - } -} - impl<'a,'tcx:'a,T,U> ToRef for &'tcx Option where &'tcx T: ToRef { @@ -79,14 +61,3 @@ impl<'a,'tcx:'a,T,U> ToRef for &'tcx Vec self.iter().map(|expr| expr.to_ref()).collect() } } - -impl<'a,'tcx:'a> ToRef for &'tcx hir::Field { - type Output = FieldExprRef<'tcx>; - - fn to_ref(self) -> FieldExprRef<'tcx> { - FieldExprRef { - name: Field::Named(self.name.node), - expr: self.expr.to_ref(), - } - } -} diff --git a/src/librustc_mir/hair.rs b/src/librustc_mir/hair/mod.rs similarity index 87% rename from src/librustc_mir/hair.rs rename to src/librustc_mir/hair/mod.rs index 641cbae4be271..d2d7faac6271e 100644 --- a/src/librustc_mir/hair.rs +++ b/src/librustc_mir/hair/mod.rs @@ -22,7 +22,9 @@ use rustc::middle::ty::{AdtDef, ClosureSubsts, Region, Ty}; use rustc_front::hir; use syntax::ast; use syntax::codemap::Span; -use tcx::{Cx, PatNode}; +use self::cx::Cx; + +pub mod cx; #[derive(Clone, Debug)] pub struct ItemRef<'tcx> { @@ -41,7 +43,6 @@ pub struct Block<'tcx> { #[derive(Clone, Debug)] pub enum StmtRef<'tcx> { - Hair(&'tcx hir::Stmt), Mirror(Box>), } @@ -71,7 +72,7 @@ pub enum StmtKind<'tcx> { init_scope: CodeExtent, /// let = ... - pattern: PatternRef<'tcx>, + pattern: Pattern<'tcx>, /// let pat = ... initializer: Option>, @@ -209,6 +210,9 @@ pub enum ExprKind<'tcx> { }, Repeat { value: ExprRef<'tcx>, + // FIXME(#29789): Add a separate hair::Constant<'tcx> so this could be more explicit about + // its contained data. Currently this should only contain expression of ExprKind::Literal + // kind. count: ExprRef<'tcx>, }, Vec { @@ -251,7 +255,7 @@ pub struct FieldExprRef<'tcx> { #[derive(Clone, Debug)] pub struct Arm<'tcx> { - pub patterns: Vec>, + pub patterns: Vec>, pub guard: Option>, pub body: ExprRef<'tcx>, } @@ -260,7 +264,7 @@ pub struct Arm<'tcx> { pub struct Pattern<'tcx> { pub ty: Ty<'tcx>, pub span: Span, - pub kind: PatternKind<'tcx>, + pub kind: Box>, } #[derive(Copy, Clone, Debug)] @@ -280,23 +284,23 @@ pub enum PatternKind<'tcx> { mode: BindingMode, var: ast::NodeId, ty: Ty<'tcx>, - subpattern: Option>, + subpattern: Option>, }, // Foo(...) or Foo{...} or Foo, where `Foo` is a variant name from an adt with >1 variants Variant { adt_def: AdtDef<'tcx>, variant_index: usize, - subpatterns: Vec>, + subpatterns: Vec>, }, // (...), Foo(...), Foo{...}, or Foo, where `Foo` is a variant name from an adt with 1 variant Leaf { - subpatterns: Vec>, + subpatterns: Vec>, }, Deref { - subpattern: PatternRef<'tcx>, + subpattern: Pattern<'tcx>, }, // box P, &P, &mut P, etc Constant { @@ -310,16 +314,16 @@ pub enum PatternKind<'tcx> { // matches against a slice, checking the length and extracting elements Slice { - prefix: Vec>, - slice: Option>, - suffix: Vec>, + prefix: Vec>, + slice: Option>, + suffix: Vec>, }, // fixed match against an array, irrefutable Array { - prefix: Vec>, - slice: Option>, - suffix: Vec>, + prefix: Vec>, + slice: Option>, + suffix: Vec>, }, } @@ -330,15 +334,9 @@ pub enum BindingMode { } #[derive(Clone, Debug)] -pub enum PatternRef<'tcx> { - Hair(PatNode<'tcx>), - Mirror(Box>), -} - -#[derive(Clone, Debug)] -pub struct FieldPatternRef<'tcx> { +pub struct FieldPattern<'tcx> { pub field: Field, - pub pattern: PatternRef<'tcx>, + pub pattern: Pattern<'tcx>, } /////////////////////////////////////////////////////////////////////////// @@ -392,33 +390,13 @@ impl<'tcx> Mirror<'tcx> for Stmt<'tcx> { impl<'tcx> Mirror<'tcx> for StmtRef<'tcx> { type Output = Stmt<'tcx>; - fn make_mirror<'a>(self, hir: &mut Cx<'a, 'tcx>) -> Stmt<'tcx> { + fn make_mirror<'a>(self, _: &mut Cx<'a,'tcx>) -> Stmt<'tcx> { match self { - StmtRef::Hair(h) => h.make_mirror(hir), StmtRef::Mirror(m) => *m, } } } -impl<'tcx> Mirror<'tcx> for Pattern<'tcx> { - type Output = Pattern<'tcx>; - - fn make_mirror<'a>(self, _: &mut Cx<'a, 'tcx>) -> Pattern<'tcx> { - self - } -} - -impl<'tcx> Mirror<'tcx> for PatternRef<'tcx> { - type Output = Pattern<'tcx>; - - fn make_mirror<'a>(self, hir: &mut Cx<'a, 'tcx>) -> Pattern<'tcx> { - match self { - PatternRef::Hair(h) => h.make_mirror(hir), - PatternRef::Mirror(m) => *m, - } - } -} - impl<'tcx> Mirror<'tcx> for Block<'tcx> { type Output = Block<'tcx>; diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs index 934dd660177b8..c391a01960f86 100644 --- a/src/librustc_mir/lib.rs +++ b/src/librustc_mir/lib.rs @@ -31,7 +31,10 @@ extern crate syntax; pub mod build; pub mod mir_map; -pub mod hair; +mod hair; pub mod repr; mod graphviz; -mod tcx; +pub mod transform; +pub mod tcx; +pub mod visit; + diff --git a/src/librustc_mir/mir_map.rs b/src/librustc_mir/mir_map.rs index 1acbc8d733d5c..1359cbc82a662 100644 --- a/src/librustc_mir/mir_map.rs +++ b/src/librustc_mir/mir_map.rs @@ -22,9 +22,10 @@ extern crate rustc_front; use build; use dot; +use transform::*; use repr::Mir; +use hair::cx::Cx; use std::fs::File; -use tcx::{PatNode, Cx}; use self::rustc::middle::infer; use self::rustc::middle::region::CodeExtentData; @@ -147,7 +148,9 @@ impl<'a, 'm, 'tcx> visit::Visitor<'tcx> for InnerDump<'a,'m,'tcx> { let infcx = infer::new_infer_ctxt(self.tcx, &self.tcx.tables, Some(param_env), true); match build_mir(Cx::new(&infcx), implicit_arg_tys, id, span, decl, body) { - Ok(mir) => { + Ok(mut mir) => { + simplify_cfg::SimplifyCfg::new().run_on_mir(&mut mir); + let meta_item_list = self.attr .iter() .flat_map(|a| a.meta_item_list()) @@ -173,7 +176,7 @@ impl<'a, 'm, 'tcx> visit::Visitor<'tcx> for InnerDump<'a,'m,'tcx> { None => { self.tcx.sess.span_err( item.span, - &format!("graphviz attribute requires a path")); + "graphviz attribute requires a path"); } } } @@ -189,26 +192,42 @@ impl<'a, 'm, 'tcx> visit::Visitor<'tcx> for InnerDump<'a,'m,'tcx> { } } -fn build_mir<'a, 'tcx: 'a>(cx: Cx<'a, 'tcx>, - implicit_arg_tys: Vec>, - fn_id: ast::NodeId, - span: Span, - decl: &'tcx hir::FnDecl, - body: &'tcx hir::Block) - -> Result, ErrorReported> { - let arguments = decl.inputs - .iter() - .map(|arg| { - let ty = cx.tcx().node_id_to_type(arg.id); - (ty, PatNode::irrefutable(&arg.pat)) - }) - .collect(); - - let parameter_scope = cx.tcx().region_maps.lookup_code_extent(CodeExtentData::ParameterScope { - fn_id: fn_id, - body_id: body.id, - }); - Ok(build::construct(cx, span, implicit_arg_tys, arguments, parameter_scope, body)) +fn build_mir<'a,'tcx:'a>(cx: Cx<'a,'tcx>, + implicit_arg_tys: Vec>, + fn_id: ast::NodeId, + span: Span, + decl: &'tcx hir::FnDecl, + body: &'tcx hir::Block) + -> Result, ErrorReported> { + // fetch the fully liberated fn signature (that is, all bound + // types/lifetimes replaced) + let fn_sig = match cx.tcx().tables.borrow().liberated_fn_sigs.get(&fn_id) { + Some(f) => f.clone(), + None => { + cx.tcx().sess.span_bug(span, + &format!("no liberated fn sig for {:?}", fn_id)); + } + }; + + let arguments = + decl.inputs + .iter() + .enumerate() + .map(|(index, arg)| { + (fn_sig.inputs[index], &*arg.pat) + }) + .collect(); + + let parameter_scope = + cx.tcx().region_maps.lookup_code_extent( + CodeExtentData::ParameterScope { fn_id: fn_id, body_id: body.id }); + Ok(build::construct(cx, + span, + implicit_arg_tys, + arguments, + parameter_scope, + fn_sig.output, + body)) } fn closure_self_ty<'a, 'tcx>(tcx: &ty::ctxt<'tcx>, diff --git a/src/librustc_mir/repr.rs b/src/librustc_mir/repr.rs index 5059955c5dc33..8007f7496b4a7 100644 --- a/src/librustc_mir/repr.rs +++ b/src/librustc_mir/repr.rs @@ -12,7 +12,7 @@ use rustc::middle::const_eval::ConstVal; use rustc::middle::def_id::DefId; use rustc::middle::region::CodeExtent; use rustc::middle::subst::Substs; -use rustc::middle::ty::{AdtDef, ClosureSubsts, Region, Ty}; +use rustc::middle::ty::{AdtDef, ClosureSubsts, FnOutput, Region, Ty}; use rustc_back::slice; use rustc_data_structures::fnv::FnvHashMap; use rustc_front::hir::InlineAsm; @@ -25,6 +25,8 @@ use std::u32; pub struct Mir<'tcx> { pub basic_blocks: Vec>, + pub return_ty: FnOutput<'tcx>, + // for every node id pub extents: FnvHashMap>, @@ -245,6 +247,27 @@ pub enum Terminator<'tcx> { /// lvalue evaluates to some enum; jump depending on the branch Switch { discr: Lvalue<'tcx>, + adt_def: AdtDef<'tcx>, + targets: Vec, + }, + + /// operand evaluates to an integer; jump depending on its value + /// to one of the targets, and otherwise fallback to `otherwise` + SwitchInt { + /// discriminant value being tested + discr: Lvalue<'tcx>, + + /// type of value being tested + switch_ty: Ty<'tcx>, + + /// Possible values. The locations to branch to in each case + /// are found in the corresponding indices from the `targets` vector. + values: Vec, + + /// Possible branch sites. The length of this vector should be + /// equal to the length of the `values` vector plus 1 -- the + /// extra item is the block to branch to if none of the values + /// fit. targets: Vec, }, @@ -277,12 +300,27 @@ impl<'tcx> Terminator<'tcx> { Goto { target: ref b } => slice::ref_slice(b), Panic { target: ref b } => slice::ref_slice(b), If { cond: _, targets: ref b } => b, - Switch { discr: _, targets: ref b } => b, + Switch { targets: ref b, .. } => b, + SwitchInt { targets: ref b, .. } => b, Diverge => &[], Return => &[], Call { data: _, targets: ref b } => b, } } + + pub fn successors_mut(&mut self) -> &mut [BasicBlock] { + use self::Terminator::*; + match *self { + Goto { target: ref mut b } => slice::mut_ref_slice(b), + Panic { target: ref mut b } => slice::mut_ref_slice(b), + If { cond: _, targets: ref mut b } => b, + Switch { targets: ref mut b, .. } => b, + SwitchInt { targets: ref mut b, .. } => b, + Diverge => &mut [], + Return => &mut [], + Call { data: _, targets: ref mut b } => b, + } + } } #[derive(Debug)] @@ -291,10 +329,10 @@ pub struct CallData<'tcx> { pub destination: Lvalue<'tcx>, /// the fn being called - pub func: Lvalue<'tcx>, + pub func: Operand<'tcx>, /// the arguments - pub args: Vec>, + pub args: Vec>, } impl<'tcx> BasicBlockData<'tcx> { @@ -316,8 +354,10 @@ impl<'tcx> Debug for Terminator<'tcx> { write!(fmt, "panic -> {:?}", target), If { cond: ref lv, ref targets } => write!(fmt, "if({:?}) -> {:?}", lv, targets), - Switch { discr: ref lv, ref targets } => + Switch { discr: ref lv, adt_def: _, ref targets } => write!(fmt, "switch({:?}) -> {:?}", lv, targets), + SwitchInt { discr: ref lv, switch_ty: _, ref values, ref targets } => + write!(fmt, "switchInt({:?}, {:?}) -> {:?}", lv, values, targets), Diverge => write!(fmt, "diverge"), Return => @@ -353,8 +393,8 @@ pub enum StatementKind<'tcx> { #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum DropKind { - Shallow, - Deep, + Free, // free a partially constructed box, should go away eventually + Deep } impl<'tcx> Debug for Statement<'tcx> { @@ -362,7 +402,7 @@ impl<'tcx> Debug for Statement<'tcx> { use self::StatementKind::*; match self.kind { Assign(ref lv, ref rv) => write!(fmt, "{:?} = {:?}", lv, rv), - Drop(DropKind::Shallow, ref lv) => write!(fmt, "shallow_drop {:?}", lv), + Drop(DropKind::Free, ref lv) => write!(fmt, "free {:?}", lv), Drop(DropKind::Deep, ref lv) => write!(fmt, "drop {:?}", lv), } } @@ -441,10 +481,19 @@ pub type LvalueProjection<'tcx> = pub type LvalueElem<'tcx> = ProjectionElem<'tcx,Operand<'tcx>>; +/// Index into the list of fields found in a `VariantDef` #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] -pub enum Field { - Named(Name), - Indexed(usize), +pub struct Field(u32); + +impl Field { + pub fn new(value: usize) -> Field { + assert!(value < (u32::MAX) as usize); + Field(value as u32) + } + + pub fn index(self) -> usize { + self.0 as usize + } } impl<'tcx> Lvalue<'tcx> { @@ -489,10 +538,8 @@ impl<'tcx> Debug for Lvalue<'tcx> { write!(fmt,"({:?} as {:?})", data.base, variant_index), ProjectionElem::Deref => write!(fmt,"(*{:?})", data.base), - ProjectionElem::Field(Field::Named(name)) => - write!(fmt,"{:?}.{:?}", data.base, name), - ProjectionElem::Field(Field::Indexed(index)) => - write!(fmt,"{:?}.{:?}", data.base, index), + ProjectionElem::Field(field) => + write!(fmt,"{:?}.{:?}", data.base, field.index()), ProjectionElem::Index(ref index) => write!(fmt,"{:?}[{:?}]", data.base, index), ProjectionElem::ConstantIndex { offset, min_length, from_end: false } => @@ -536,7 +583,7 @@ pub enum Rvalue<'tcx> { Use(Operand<'tcx>), // [x; 32] - Repeat(Operand<'tcx>, Operand<'tcx>), + Repeat(Operand<'tcx>, Constant<'tcx>), // &x or &mut x Ref(Region, BorrowKind, Lvalue<'tcx>), diff --git a/src/librustc_mir/tcx/mod.rs b/src/librustc_mir/tcx/mod.rs index 92b026e5035b4..4d034ae23b49a 100644 --- a/src/librustc_mir/tcx/mod.rs +++ b/src/librustc_mir/tcx/mod.rs @@ -9,150 +9,182 @@ // except according to those terms. /*! - * This module contains the code to convert from the wacky tcx data - * structures into the hair. The `builder` is generally ignorant of - * the tcx etc, and instead goes through the `Cx` for most of its - * work. + * Methods for the various MIR types. These are intended for use after + * building is complete. */ -use hair::*; use repr::*; - -use rustc::middle::const_eval::ConstVal; -use rustc::middle::def_id::DefId; -use rustc::middle::infer::InferCtxt; -use rustc::middle::subst::{Subst, Substs}; -use rustc::middle::ty::{self, Ty}; -use syntax::codemap::Span; -use syntax::parse::token::{self, special_idents}; - -#[derive(Copy, Clone)] -pub struct Cx<'a, 'tcx: 'a> { - tcx: &'a ty::ctxt<'tcx>, - infcx: &'a InferCtxt<'a, 'tcx>, -} - -impl<'a,'tcx> Cx<'a,'tcx> { - pub fn new(infcx: &'a InferCtxt<'a, 'tcx>) -> Cx<'a, 'tcx> { - Cx { - tcx: infcx.tcx, - infcx: infcx, - } - } +use rustc::middle::subst::Substs; +use rustc::middle::ty::{self, AdtDef, Ty}; +use rustc_front::hir; + +#[derive(Copy, Clone, Debug)] +pub enum LvalueTy<'tcx> { + /// Normal type. + Ty { ty: Ty<'tcx> }, + + /// Downcast to a particular variant of an enum. + Downcast { adt_def: AdtDef<'tcx>, + substs: &'tcx Substs<'tcx>, + variant_index: usize }, } -pub use self::pattern::PatNode; - -impl<'a,'tcx:'a> Cx<'a, 'tcx> { - /// Normalizes `ast` into the appropriate `mirror` type. - pub fn mirror>(&mut self, ast: M) -> M::Output { - ast.make_mirror(self) - } - - pub fn unit_ty(&mut self) -> Ty<'tcx> { - self.tcx.mk_nil() - } - - pub fn usize_ty(&mut self) -> Ty<'tcx> { - self.tcx.types.usize - } - - pub fn usize_literal(&mut self, value: usize) -> Literal<'tcx> { - Literal::Value { value: ConstVal::Uint(value as u64) } - } - - pub fn bool_ty(&mut self) -> Ty<'tcx> { - self.tcx.types.bool - } - - pub fn true_literal(&mut self) -> Literal<'tcx> { - Literal::Value { value: ConstVal::Bool(true) } - } - - pub fn false_literal(&mut self) -> Literal<'tcx> { - Literal::Value { value: ConstVal::Bool(false) } +impl<'tcx> LvalueTy<'tcx> { + pub fn from_ty(ty: Ty<'tcx>) -> LvalueTy<'tcx> { + LvalueTy::Ty { ty: ty } } - pub fn partial_eq(&mut self, ty: Ty<'tcx>) -> ItemRef<'tcx> { - let eq_def_id = self.tcx.lang_items.eq_trait().unwrap(); - self.cmp_method_ref(eq_def_id, "eq", ty) + pub fn to_ty(&self, tcx: &ty::ctxt<'tcx>) -> Ty<'tcx> { + match *self { + LvalueTy::Ty { ty } => + ty, + LvalueTy::Downcast { adt_def, substs, variant_index: _ } => + tcx.mk_enum(adt_def, substs), + } } - pub fn partial_le(&mut self, ty: Ty<'tcx>) -> ItemRef<'tcx> { - let ord_def_id = self.tcx.lang_items.ord_trait().unwrap(); - self.cmp_method_ref(ord_def_id, "le", ty) + pub fn projection_ty(self, + tcx: &ty::ctxt<'tcx>, + elem: &LvalueElem<'tcx>) + -> LvalueTy<'tcx> + { + match *elem { + ProjectionElem::Deref => + LvalueTy::Ty { + ty: self.to_ty(tcx).builtin_deref(true, ty::LvaluePreference::NoPreference) + .unwrap() + .ty + }, + ProjectionElem::Index(_) | ProjectionElem::ConstantIndex { .. } => + LvalueTy::Ty { + ty: self.to_ty(tcx).builtin_index().unwrap() + }, + ProjectionElem::Downcast(adt_def1, index) => + match self.to_ty(tcx).sty { + ty::TyEnum(adt_def, substs) => { + assert!(index < adt_def.variants.len()); + assert_eq!(adt_def, adt_def1); + LvalueTy::Downcast { adt_def: adt_def, + substs: substs, + variant_index: index } + } + _ => { + tcx.sess.bug(&format!("cannot downcast non-enum type: `{:?}`", self)) + } + }, + ProjectionElem::Field(field) => { + let field_ty = match self { + LvalueTy::Ty { ty } => match ty.sty { + ty::TyStruct(adt_def, substs) => + adt_def.struct_variant().fields[field.index()].ty(tcx, substs), + ty::TyTuple(ref tys) => + tys[field.index()], + ty::TyClosure(_, ref closure_substs) => + closure_substs.upvar_tys[field.index()], + _ => + tcx.sess.bug(&format!("cannot get field of type: `{:?}`", ty)), + }, + LvalueTy::Downcast { adt_def, substs, variant_index } => + adt_def.variants[variant_index].fields[field.index()].ty(tcx, substs), + }; + LvalueTy::Ty { ty: field_ty } + } + } } +} - pub fn num_variants(&mut self, adt_def: ty::AdtDef<'tcx>) -> usize { - adt_def.variants.len() +impl<'tcx> Mir<'tcx> { + pub fn operand_ty(&self, + tcx: &ty::ctxt<'tcx>, + operand: &Operand<'tcx>) + -> Ty<'tcx> + { + match *operand { + Operand::Consume(ref l) => self.lvalue_ty(tcx, l).to_ty(tcx), + Operand::Constant(ref c) => c.ty, + } } - pub fn fields(&mut self, adt_def: ty::AdtDef<'tcx>, variant_index: usize) -> Vec { - adt_def.variants[variant_index] - .fields - .iter() - .enumerate() - .map(|(index, field)| { - if field.name == special_idents::unnamed_field.name { - Field::Indexed(index) - } else { - Field::Named(field.name) - } - }) - .collect() + pub fn binop_ty(&self, + tcx: &ty::ctxt<'tcx>, + op: BinOp, + lhs_ty: Ty<'tcx>, + rhs_ty: Ty<'tcx>) + -> Ty<'tcx> + { + // FIXME: handle SIMD correctly + match op { + BinOp::Add | BinOp::Sub | BinOp::Mul | BinOp::Div | BinOp::Rem | + BinOp::BitXor | BinOp::BitAnd | BinOp::BitOr => { + // these should be integers or floats of the same size. + assert_eq!(lhs_ty, rhs_ty); + lhs_ty + } + BinOp::Shl | BinOp::Shr => { + lhs_ty // lhs_ty can be != rhs_ty + } + BinOp::Eq | BinOp::Lt | BinOp::Le | + BinOp::Ne | BinOp::Ge | BinOp::Gt => { + tcx.types.bool + } + } } - pub fn needs_drop(&mut self, ty: Ty<'tcx>, span: Span) -> bool { - if self.infcx.type_moves_by_default(ty, span) { - // FIXME(#21859) we should do an add'l check here to determine if - // any dtor will execute, but the relevant fn - // (`type_needs_drop`) is currently factored into - // `librustc_trans`, so we can't easily do so. - true - } else { - // if type implements Copy, cannot require drop - false + pub fn lvalue_ty(&self, + tcx: &ty::ctxt<'tcx>, + lvalue: &Lvalue<'tcx>) + -> LvalueTy<'tcx> + { + match *lvalue { + Lvalue::Var(index) => + LvalueTy::Ty { ty: self.var_decls[index as usize].ty }, + Lvalue::Temp(index) => + LvalueTy::Ty { ty: self.temp_decls[index as usize].ty }, + Lvalue::Arg(index) => + LvalueTy::Ty { ty: self.arg_decls[index as usize].ty }, + Lvalue::Static(def_id) => + LvalueTy::Ty { ty: tcx.lookup_item_type(def_id).ty }, + Lvalue::ReturnPointer => + LvalueTy::Ty { ty: self.return_ty.unwrap() }, + Lvalue::Projection(ref proj) => + self.lvalue_ty(tcx, &proj.base).projection_ty(tcx, &proj.elem) } } +} - pub fn span_bug(&mut self, span: Span, message: &str) -> ! { - self.tcx.sess.span_bug(span, message) - } +impl BorrowKind { + pub fn to_mutbl_lossy(self) -> hir::Mutability { + match self { + BorrowKind::Mut => hir::MutMutable, + BorrowKind::Shared => hir::MutImmutable, - pub fn tcx(&self) -> &'a ty::ctxt<'tcx> { - self.tcx + // We have no type corresponding to a unique imm borrow, so + // use `&mut`. It gives all the capabilities of an `&uniq` + // and hence is a safe "over approximation". + BorrowKind::Unique => hir::MutMutable, + } } +} - fn cmp_method_ref(&mut self, - trait_def_id: DefId, - method_name: &str, - arg_ty: Ty<'tcx>) - -> ItemRef<'tcx> { - let method_name = token::intern(method_name); - let substs = Substs::new_trait(vec![arg_ty], vec![], arg_ty); - for trait_item in self.tcx.trait_items(trait_def_id).iter() { - match *trait_item { - ty::ImplOrTraitItem::MethodTraitItem(ref method) => { - if method.name == method_name { - let method_ty = self.tcx.lookup_item_type(method.def_id); - let method_ty = method_ty.ty.subst(self.tcx, &substs); - return ItemRef { - ty: method_ty, - def_id: method.def_id, - substs: self.tcx.mk_substs(substs), - }; - } - } - ty::ImplOrTraitItem::ConstTraitItem(..) | - ty::ImplOrTraitItem::TypeTraitItem(..) => {} - } +impl BinOp { + pub fn to_hir_binop(self) -> hir::BinOp_ { + match self { + BinOp::Add => hir::BinOp_::BiAdd, + BinOp::Sub => hir::BinOp_::BiSub, + BinOp::Mul => hir::BinOp_::BiMul, + BinOp::Div => hir::BinOp_::BiDiv, + BinOp::Rem => hir::BinOp_::BiRem, + BinOp::BitXor => hir::BinOp_::BiBitXor, + BinOp::BitAnd => hir::BinOp_::BiBitAnd, + BinOp::BitOr => hir::BinOp_::BiBitOr, + BinOp::Shl => hir::BinOp_::BiShl, + BinOp::Shr => hir::BinOp_::BiShr, + BinOp::Eq => hir::BinOp_::BiEq, + BinOp::Ne => hir::BinOp_::BiNe, + BinOp::Lt => hir::BinOp_::BiLt, + BinOp::Gt => hir::BinOp_::BiGt, + BinOp::Le => hir::BinOp_::BiLe, + BinOp::Ge => hir::BinOp_::BiGe } - - self.tcx.sess.bug(&format!("found no method `{}` in `{:?}`", method_name, trait_def_id)); } } - -mod block; -mod expr; -mod pattern; -mod to_ref; diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs new file mode 100644 index 0000000000000..bee6d4d7ddda8 --- /dev/null +++ b/src/librustc_mir/transform/mod.rs @@ -0,0 +1,18 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +pub mod simplify_cfg; +mod util; + +use repr::Mir; + +pub trait MirPass { + fn run_on_mir(&mut self, mir: &mut Mir); +} diff --git a/src/librustc_mir/transform/simplify_cfg.rs b/src/librustc_mir/transform/simplify_cfg.rs new file mode 100644 index 0000000000000..71dd2f077fec2 --- /dev/null +++ b/src/librustc_mir/transform/simplify_cfg.rs @@ -0,0 +1,135 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use repr::*; +use rustc::middle::const_eval::ConstVal; +use std::mem; +use transform::util; +use transform::MirPass; + +pub struct SimplifyCfg; + +impl SimplifyCfg { + pub fn new() -> SimplifyCfg { + SimplifyCfg + } + + fn remove_dead_blocks(&self, mir: &mut Mir) { + let mut seen = vec![false; mir.basic_blocks.len()]; + + // These blocks are always required. + seen[START_BLOCK.index()] = true; + seen[END_BLOCK.index()] = true; + seen[DIVERGE_BLOCK.index()] = true; + + let mut worklist = vec![START_BLOCK]; + while let Some(bb) = worklist.pop() { + for succ in mir.basic_block_data(bb).terminator.successors() { + if !seen[succ.index()] { + seen[succ.index()] = true; + worklist.push(*succ); + } + } + } + + util::retain_basic_blocks(mir, &seen); + } + + fn remove_goto_chains(&self, mir: &mut Mir) -> bool { + + // Find the target at the end of the jump chain, return None if there is a loop + fn final_target(mir: &Mir, mut target: BasicBlock) -> Option { + // Keep track of already seen blocks to detect loops + let mut seen: Vec = Vec::with_capacity(8); + + while mir.basic_block_data(target).statements.is_empty() { + match mir.basic_block_data(target).terminator { + Terminator::Goto { target: next } => { + if seen.contains(&next) { + return None; + } + seen.push(next); + target = next; + } + _ => break + } + } + + Some(target) + } + + let mut changed = false; + for bb in mir.all_basic_blocks() { + // Temporarily swap out the terminator we're modifying to keep borrowck happy + let mut terminator = Terminator::Diverge; + mem::swap(&mut terminator, &mut mir.basic_block_data_mut(bb).terminator); + + for target in terminator.successors_mut() { + let new_target = match final_target(mir, *target) { + Some(new_target) => new_target, + None if mir.basic_block_data(bb).statements.is_empty() => bb, + None => continue + }; + changed |= *target != new_target; + *target = new_target; + } + + mir.basic_block_data_mut(bb).terminator = terminator; + } + + changed + } + + fn simplify_branches(&self, mir: &mut Mir) -> bool { + let mut changed = false; + + for bb in mir.all_basic_blocks() { + // Temporarily swap out the terminator we're modifying to keep borrowck happy + let mut terminator = Terminator::Diverge; + mem::swap(&mut terminator, &mut mir.basic_block_data_mut(bb).terminator); + + mir.basic_block_data_mut(bb).terminator = match terminator { + Terminator::If { ref targets, .. } if targets[0] == targets[1] => { + changed = true; + Terminator::Goto { target: targets[0] } + } + Terminator::If { ref targets, cond: Operand::Constant(Constant { + literal: Literal::Value { + value: ConstVal::Bool(cond) + }, .. + }) } => { + changed = true; + let target_idx = if cond { 0 } else { 1 }; + Terminator::Goto { target: targets[target_idx] } + } + Terminator::SwitchInt { ref targets, .. } if targets.len() == 1 => { + Terminator::Goto { target: targets[0] } + } + _ => terminator + } + } + + changed + } +} + +impl MirPass for SimplifyCfg { + fn run_on_mir(&mut self, mir: &mut Mir) { + let mut changed = true; + while changed { + changed = self.simplify_branches(mir); + changed |= self.remove_goto_chains(mir); + self.remove_dead_blocks(mir); + } + + // FIXME: Should probably be moved into some kind of pass manager + mir.basic_blocks.shrink_to_fit(); + } +} diff --git a/src/librustc_mir/transform/util.rs b/src/librustc_mir/transform/util.rs new file mode 100644 index 0000000000000..e45cfa8395472 --- /dev/null +++ b/src/librustc_mir/transform/util.rs @@ -0,0 +1,51 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use repr::*; + +/// Update basic block ids in all terminators using the given replacements, +/// useful e.g. after removal of several basic blocks to update all terminators +/// in a single pass +pub fn update_basic_block_ids(mir: &mut Mir, replacements: &[BasicBlock]) { + for bb in mir.all_basic_blocks() { + for target in mir.basic_block_data_mut(bb).terminator.successors_mut() { + *target = replacements[target.index()]; + } + } +} + +/// Mass removal of basic blocks to keep the ID-remapping cheap. +pub fn retain_basic_blocks(mir: &mut Mir, keep: &[bool]) { + let num_blocks = mir.basic_blocks.len(); + + // Check that we have a usage flag for every block + assert_eq!(num_blocks, keep.len()); + + let first_dead = match keep.iter().position(|&k| !k) { + None => return, + Some(first_dead) => first_dead, + }; + + // `replacements` maps the old block ids to the new ones + let mut replacements: Vec<_> = (0..num_blocks).map(BasicBlock::new).collect(); + + let mut dead = 0; + for i in first_dead..num_blocks { + if keep[i] { + replacements[i] = BasicBlock::new(i - dead); + mir.basic_blocks.swap(i, i - dead); + } else { + dead += 1; + } + } + mir.basic_blocks.truncate(num_blocks - dead); + + update_basic_block_ids(mir, &replacements); +} diff --git a/src/librustc_mir/visit.rs b/src/librustc_mir/visit.rs new file mode 100644 index 0000000000000..b3ec2f10cf664 --- /dev/null +++ b/src/librustc_mir/visit.rs @@ -0,0 +1,246 @@ +// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use rustc::middle::ty::Region; +use repr::*; + +pub trait Visitor<'tcx> { + // Override these, and call `self.super_xxx` to revert back to the + // default behavior. + + fn visit_mir(&mut self, mir: &Mir<'tcx>) { + self.super_mir(mir); + } + + fn visit_basic_block_data(&mut self, block: BasicBlock, data: &BasicBlockData<'tcx>) { + self.super_basic_block_data(block, data); + } + + fn visit_statement(&mut self, block: BasicBlock, statement: &Statement<'tcx>) { + self.super_statement(block, statement); + } + + fn visit_assign(&mut self, block: BasicBlock, lvalue: &Lvalue<'tcx>, rvalue: &Rvalue<'tcx>) { + self.super_assign(block, lvalue, rvalue); + } + + fn visit_terminator(&mut self, block: BasicBlock, terminator: &Terminator<'tcx>) { + self.super_terminator(block, terminator); + } + + fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>) { + self.super_rvalue(rvalue); + } + + fn visit_operand(&mut self, operand: &Operand<'tcx>) { + self.super_operand(operand); + } + + fn visit_lvalue(&mut self, lvalue: &Lvalue<'tcx>, context: LvalueContext) { + self.super_lvalue(lvalue, context); + } + + fn visit_branch(&mut self, source: BasicBlock, target: BasicBlock) { + self.super_branch(source, target); + } + + fn visit_constant(&mut self, constant: &Constant<'tcx>) { + self.super_constant(constant); + } + + // The `super_xxx` methods comprise the default behavior and are + // not meant to be overidden. + + fn super_mir(&mut self, mir: &Mir<'tcx>) { + for block in mir.all_basic_blocks() { + let data = mir.basic_block_data(block); + self.visit_basic_block_data(block, data); + } + } + + fn super_basic_block_data(&mut self, block: BasicBlock, data: &BasicBlockData<'tcx>) { + for statement in &data.statements { + self.visit_statement(block, statement); + } + self.visit_terminator(block, &data.terminator); + } + + fn super_statement(&mut self, block: BasicBlock, statement: &Statement<'tcx>) { + match statement.kind { + StatementKind::Assign(ref lvalue, ref rvalue) => { + self.visit_assign(block, lvalue, rvalue); + } + StatementKind::Drop(_, ref lvalue) => { + self.visit_lvalue(lvalue, LvalueContext::Drop); + } + } + } + + fn super_assign(&mut self, _block: BasicBlock, lvalue: &Lvalue<'tcx>, rvalue: &Rvalue<'tcx>) { + self.visit_lvalue(lvalue, LvalueContext::Store); + self.visit_rvalue(rvalue); + } + + fn super_terminator(&mut self, block: BasicBlock, terminator: &Terminator<'tcx>) { + match *terminator { + Terminator::Goto { target } | + Terminator::Panic { target } => { + self.visit_branch(block, target); + } + + Terminator::If { ref cond, ref targets } => { + self.visit_operand(cond); + for &target in &targets[..] { + self.visit_branch(block, target); + } + } + + Terminator::Switch { ref discr, adt_def: _, ref targets } => { + self.visit_lvalue(discr, LvalueContext::Inspect); + for &target in targets { + self.visit_branch(block, target); + } + } + + Terminator::SwitchInt { ref discr, switch_ty: _, values: _, ref targets } => { + self.visit_lvalue(discr, LvalueContext::Inspect); + for &target in targets { + self.visit_branch(block, target); + } + } + + Terminator::Diverge | + Terminator::Return => { + } + + Terminator::Call { ref data, ref targets } => { + self.visit_lvalue(&data.destination, LvalueContext::Store); + self.visit_operand(&data.func); + for arg in &data.args { + self.visit_operand(arg); + } + for &target in &targets[..] { + self.visit_branch(block, target); + } + } + } + } + + fn super_rvalue(&mut self, rvalue: &Rvalue<'tcx>) { + match *rvalue { + Rvalue::Use(ref operand) => { + self.visit_operand(operand); + } + + Rvalue::Repeat(ref value, ref len) => { + self.visit_operand(value); + self.visit_constant(len); + } + + Rvalue::Ref(r, bk, ref path) => { + self.visit_lvalue(path, LvalueContext::Borrow { + region: r, + kind: bk + }); + } + + Rvalue::Len(ref path) => { + self.visit_lvalue(path, LvalueContext::Inspect); + } + + Rvalue::Cast(_, ref operand, _) => { + self.visit_operand(operand); + } + + Rvalue::BinaryOp(_, ref lhs, ref rhs) => { + self.visit_operand(lhs); + self.visit_operand(rhs); + } + + Rvalue::UnaryOp(_, ref op) => { + self.visit_operand(op); + } + + Rvalue::Box(_) => { + } + + Rvalue::Aggregate(_, ref operands) => { + for operand in operands { + self.visit_operand(operand); + } + } + + Rvalue::Slice { ref input, from_start, from_end } => { + self.visit_lvalue(input, LvalueContext::Slice { + from_start: from_start, + from_end: from_end, + }); + } + + Rvalue::InlineAsm(_) => { + } + } + } + + fn super_operand(&mut self, operand: &Operand<'tcx>) { + match *operand { + Operand::Consume(ref lvalue) => { + self.visit_lvalue(lvalue, LvalueContext::Consume); + } + Operand::Constant(ref constant) => { + self.visit_constant(constant); + } + } + } + + fn super_lvalue(&mut self, lvalue: &Lvalue<'tcx>, _context: LvalueContext) { + match *lvalue { + Lvalue::Var(_) | + Lvalue::Temp(_) | + Lvalue::Arg(_) | + Lvalue::Static(_) | + Lvalue::ReturnPointer => { + } + Lvalue::Projection(ref proj) => { + self.visit_lvalue(&proj.base, LvalueContext::Projection); + } + } + } + + fn super_branch(&mut self, _source: BasicBlock, _target: BasicBlock) { + } + + fn super_constant(&mut self, _constant: &Constant<'tcx>) { + } +} + +#[derive(Copy, Clone, Debug)] +pub enum LvalueContext { + // Appears as LHS of an assignment or as dest of a call + Store, + + // Being dropped + Drop, + + // Being inspected in some way, like loading a len + Inspect, + + // Being borrowed + Borrow { region: Region, kind: BorrowKind }, + + // Being sliced -- this should be same as being borrowed, probably + Slice { from_start: usize, from_end: usize }, + + // Used as base for another lvalue, e.g. `x` in `x.y` + Projection, + + // Consumed as part of an operand + Consume, +} diff --git a/src/librustc_platform_intrinsics/lib.rs b/src/librustc_platform_intrinsics/lib.rs old mode 100755 new mode 100644 diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 4fbe3a6833573..a8600d91a2689 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -165,13 +165,6 @@ struct EmbargoVisitor<'a, 'tcx: 'a> { // may jump across private boundaries through reexport statements or type aliases. exported_items: ExportedItems, - // This sets contains all the destination nodes which are publicly - // re-exported. This is *not* a set of all reexported nodes, only a set of - // all nodes which are reexported *and* reachable from external crates. This - // means that the destination of the reexport is exported, and hence the - // destination must also be exported. - reexports: NodeSet, - // Items that are directly public without help of reexports or type aliases. // These two fields are closely related to one another in that they are only // used for generation of the `public_items` set, not for privacy checking at @@ -185,7 +178,9 @@ impl<'a, 'tcx> EmbargoVisitor<'a, 'tcx> { fn is_public_exported_ty(&self, ty: &hir::Ty) -> (bool, bool) { if let hir::TyPath(..) = ty.node { match self.tcx.def_map.borrow().get(&ty.id).unwrap().full_def() { - def::DefPrimTy(..) | def::DefSelfTy(..) => (true, true), + def::DefPrimTy(..) | def::DefSelfTy(..) | def::DefTyParam(..) => { + (true, true) + } def => { if let Some(node_id) = self.tcx.map.as_local_node_id(def.def_id()) { (self.public_items.contains(&node_id), @@ -235,7 +230,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EmbargoVisitor<'a, 'tcx> { _ => { self.prev_public = self.prev_public && item.vis == hir::Public; self.prev_exported = (self.prev_exported && item.vis == hir::Public) || - self.reexports.contains(&item.id); + self.exported_items.contains(&item.id); self.maybe_insert_id(item.id); } @@ -272,25 +267,26 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EmbargoVisitor<'a, 'tcx> { } } - // It's not known until monomorphization if a trait impl item should be reachable - // from external crates or not. So, we conservatively mark all of them exported and - // the reachability pass (middle::reachable) marks all exported items as reachable. - // For example of private trait impl for private type that should be reachable see - // src/test/auxiliary/issue-11225-3.rs + // Trait impl and its items are public/exported if both the self type and the trait + // of this impl are public/exported hir::ItemImpl(_, _, _, Some(ref trait_ref), ref ty, ref impl_items) => { - let (public_ty, _exported_ty) = self.is_public_exported_ty(&ty); - let (public_trait, _exported_trait) = self.is_public_exported_trait(trait_ref); + let (public_ty, exported_ty) = self.is_public_exported_ty(&ty); + let (public_trait, exported_trait) = self.is_public_exported_trait(trait_ref); if public_ty && public_trait { self.public_items.insert(item.id); } - self.exported_items.insert(item.id); + if exported_ty && exported_trait { + self.exported_items.insert(item.id); + } for impl_item in impl_items { if public_ty && public_trait { self.public_items.insert(impl_item.id); } - self.exported_items.insert(impl_item.id); + if exported_ty && exported_trait { + self.exported_items.insert(impl_item.id); + } } } @@ -332,8 +328,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EmbargoVisitor<'a, 'tcx> { match self.tcx.def_map.borrow().get(&ty.id).unwrap().full_def() { def::DefPrimTy(..) | def::DefSelfTy(..) | def::DefTyParam(..) => {}, def => { - let did = def.def_id(); - if let Some(node_id) = self.tcx.map.as_local_node_id(did) { + if let Some(node_id) = self.tcx.map.as_local_node_id(def.def_id()) { self.exported_items.insert(node_id); } } @@ -345,7 +340,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EmbargoVisitor<'a, 'tcx> { for foreign_item in &foreign_mod.items { let public = self.prev_public && foreign_item.vis == hir::Public; let exported = (self.prev_exported && foreign_item.vis == hir::Public) || - self.reexports.contains(&foreign_item.id); + self.exported_items.contains(&foreign_item.id); if public { self.public_items.insert(foreign_item.id); @@ -385,7 +380,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EmbargoVisitor<'a, 'tcx> { assert!(self.export_map.contains_key(&id), "wut {}", id); for export in self.export_map.get(&id).unwrap() { if let Some(node_id) = self.tcx.map.as_local_node_id(export.def_id) { - self.reexports.insert(node_id); + self.exported_items.insert(node_id); } } } @@ -1036,32 +1031,29 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> { struct SanePrivacyVisitor<'a, 'tcx: 'a> { tcx: &'a ty::ctxt<'tcx>, - in_fn: bool, + in_block: bool, } impl<'a, 'tcx, 'v> Visitor<'v> for SanePrivacyVisitor<'a, 'tcx> { fn visit_item(&mut self, item: &hir::Item) { - if self.in_fn { + self.check_sane_privacy(item); + if self.in_block { self.check_all_inherited(item); - } else { - self.check_sane_privacy(item); } - let in_fn = self.in_fn; - let orig_in_fn = replace(&mut self.in_fn, match item.node { - hir::ItemMod(..) => false, // modules turn privacy back on - _ => in_fn, // otherwise we inherit - }); + let orig_in_block = self.in_block; + + // Modules turn privacy back on, otherwise we inherit + self.in_block = if let hir::ItemMod(..) = item.node { false } else { orig_in_block }; + visit::walk_item(self, item); - self.in_fn = orig_in_fn; + self.in_block = orig_in_block; } - fn visit_fn(&mut self, fk: visit::FnKind<'v>, fd: &'v hir::FnDecl, - b: &'v hir::Block, s: Span, _: ast::NodeId) { - // This catches both functions and methods - let orig_in_fn = replace(&mut self.in_fn, true); - visit::walk_fn(self, fk, fd, b, s); - self.in_fn = orig_in_fn; + fn visit_block(&mut self, b: &'v hir::Block) { + let orig_in_block = replace(&mut self.in_block, true); + visit::walk_block(self, b); + self.in_block = orig_in_block; } } @@ -1071,89 +1063,75 @@ impl<'a, 'tcx> SanePrivacyVisitor<'a, 'tcx> { /// anything. In theory these qualifiers wouldn't parse, but that may happen /// later on down the road... fn check_sane_privacy(&self, item: &hir::Item) { - let tcx = self.tcx; - let check_inherited = |sp: Span, vis: hir::Visibility, note: &str| { + let check_inherited = |sp, vis, note: &str| { if vis != hir::Inherited { - span_err!(tcx.sess, sp, E0449, - "unnecessary visibility qualifier"); + span_err!(self.tcx.sess, sp, E0449, "unnecessary visibility qualifier"); if !note.is_empty() { - tcx.sess.span_note(sp, note); + self.tcx.sess.span_note(sp, note); } } }; + match item.node { // implementations of traits don't need visibility qualifiers because // that's controlled by having the trait in scope. hir::ItemImpl(_, _, _, Some(..), _, ref impl_items) => { check_inherited(item.span, item.vis, - "visibility qualifiers have no effect on trait \ - impls"); + "visibility qualifiers have no effect on trait impls"); for impl_item in impl_items { check_inherited(impl_item.span, impl_item.vis, ""); } } - - hir::ItemImpl(..) => { + hir::ItemImpl(_, _, _, None, _, _) => { check_inherited(item.span, item.vis, "place qualifiers on individual methods instead"); } + hir::ItemDefaultImpl(..) => { + check_inherited(item.span, item.vis, + "visibility qualifiers have no effect on trait impls"); + } hir::ItemForeignMod(..) => { check_inherited(item.span, item.vis, - "place qualifiers on individual functions \ - instead"); + "place qualifiers on individual functions instead"); } - - hir::ItemEnum(..) | - hir::ItemTrait(..) | hir::ItemDefaultImpl(..) | - hir::ItemConst(..) | hir::ItemStatic(..) | hir::ItemStruct(..) | - hir::ItemFn(..) | hir::ItemMod(..) | hir::ItemTy(..) | - hir::ItemExternCrate(_) | hir::ItemUse(_) => {} + hir::ItemStruct(..) | hir::ItemEnum(..) | hir::ItemTrait(..) | + hir::ItemConst(..) | hir::ItemStatic(..) | hir::ItemFn(..) | + hir::ItemMod(..) | hir::ItemExternCrate(..) | + hir::ItemUse(..) | hir::ItemTy(..) => {} } } /// When inside of something like a function or a method, visibility has no /// control over anything so this forbids any mention of any visibility fn check_all_inherited(&self, item: &hir::Item) { - let tcx = self.tcx; - fn check_inherited(tcx: &ty::ctxt, sp: Span, vis: hir::Visibility) { + let check_inherited = |sp, vis| { if vis != hir::Inherited { - span_err!(tcx.sess, sp, E0447, - "visibility has no effect inside functions"); - } - } - let check_struct = |def: &hir::VariantData| { - for f in def.fields() { - match f.node.kind { - hir::NamedField(_, p) => check_inherited(tcx, f.span, p), - hir::UnnamedField(..) => {} - } + span_err!(self.tcx.sess, sp, E0447, + "visibility has no effect inside functions or block expressions"); } }; - check_inherited(tcx, item.span, item.vis); + + check_inherited(item.span, item.vis); match item.node { hir::ItemImpl(_, _, _, _, _, ref impl_items) => { for impl_item in impl_items { - match impl_item.node { - hir::MethodImplItem(..) => { - check_inherited(tcx, impl_item.span, impl_item.vis); - } - _ => {} - } + check_inherited(impl_item.span, impl_item.vis); } } hir::ItemForeignMod(ref fm) => { - for i in &fm.items { - check_inherited(tcx, i.span, i.vis); + for fi in &fm.items { + check_inherited(fi.span, fi.vis); } } - - hir::ItemStruct(ref def, _) => check_struct(def), - - hir::ItemEnum(..) | - hir::ItemExternCrate(_) | hir::ItemUse(_) | - hir::ItemTrait(..) | hir::ItemDefaultImpl(..) | - hir::ItemStatic(..) | hir::ItemConst(..) | - hir::ItemFn(..) | hir::ItemMod(..) | hir::ItemTy(..) => {} + hir::ItemStruct(ref vdata, _) => { + for f in vdata.fields() { + check_inherited(f.span, f.node.kind.visibility()); + } + } + hir::ItemDefaultImpl(..) | hir::ItemEnum(..) | hir::ItemTrait(..) | + hir::ItemConst(..) | hir::ItemStatic(..) | hir::ItemFn(..) | + hir::ItemMod(..) | hir::ItemExternCrate(..) | + hir::ItemUse(..) | hir::ItemTy(..) => {} } } } @@ -1497,6 +1475,14 @@ pub fn check_crate(tcx: &ty::ctxt, -> (ExportedItems, PublicItems) { let krate = tcx.map.krate(); + // Sanity check to make sure that all privacy usage and controls are + // reasonable. + let mut visitor = SanePrivacyVisitor { + tcx: tcx, + in_block: false, + }; + visit::walk_crate(&mut visitor, krate); + // Figure out who everyone's parent is let mut visitor = ParentVisitor { parents: NodeMap(), @@ -1514,14 +1500,6 @@ pub fn check_crate(tcx: &ty::ctxt, }; visit::walk_crate(&mut visitor, krate); - // Sanity check to make sure that all privacy usage and controls are - // reasonable. - let mut visitor = SanePrivacyVisitor { - in_fn: false, - tcx: tcx, - }; - visit::walk_crate(&mut visitor, krate); - tcx.sess.abort_if_errors(); // Build up a set of all exported items in the AST. This is a set of all @@ -1530,17 +1508,14 @@ pub fn check_crate(tcx: &ty::ctxt, tcx: tcx, exported_items: NodeSet(), public_items: NodeSet(), - reexports: NodeSet(), export_map: export_map, prev_exported: true, prev_public: true, }; loop { - let before = (visitor.exported_items.len(), visitor.public_items.len(), - visitor.reexports.len()); + let before = (visitor.exported_items.len(), visitor.public_items.len()); visit::walk_crate(&mut visitor, krate); - let after = (visitor.exported_items.len(), visitor.public_items.len(), - visitor.reexports.len()); + let after = (visitor.exported_items.len(), visitor.public_items.len()); if after == before { break } diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 0bbceafa4a85b..3481f1bfd5203 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -66,7 +66,7 @@ enum DuplicateCheckingMode { ForbidDuplicateTypesAndModules, ForbidDuplicateValues, ForbidDuplicateTypesAndValues, - OverwriteDuplicates + OverwriteDuplicates, } #[derive(Copy, Clone, PartialEq)] @@ -74,19 +74,19 @@ enum NamespaceError { NoError, ModuleError, TypeError, - ValueError + ValueError, } fn namespace_error_to_string(ns: NamespaceError) -> &'static str { match ns { - NoError => "", + NoError => "", ModuleError | TypeError => "type or module", - ValueError => "value", + ValueError => "value", } } -struct GraphBuilder<'a, 'b:'a, 'tcx:'b> { - resolver: &'a mut Resolver<'b, 'tcx> +struct GraphBuilder<'a, 'b: 'a, 'tcx: 'b> { + resolver: &'a mut Resolver<'b, 'tcx>, } impl<'a, 'b:'a, 'tcx:'b> Deref for GraphBuilder<'a, 'b, 'tcx> { @@ -109,7 +109,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { let parent = self.graph_root.get_module(); let mut visitor = BuildReducedGraphVisitor { builder: self, - parent: parent + parent: parent, }; visit::walk_crate(&mut visitor, krate); } @@ -135,9 +135,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { // child name directly. Otherwise, we create or reuse an anonymous // module and add the child to that. - self.check_for_conflicts_between_external_crates_and_items(&**parent, - name, - sp); + self.check_for_conflicts_between_external_crates_and_items(&**parent, name, sp); // Add or reuse the child. let child = parent.children.borrow().get(&name).cloned(); @@ -194,14 +192,14 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { n = Some(TypeNS); duplicate_type = TypeError; } - }; + } if child.defined_in_namespace(ValueNS) { duplicate_type = ValueError; n = Some(ValueNS); } n } - OverwriteDuplicates => None + OverwriteDuplicates => None, }; if duplicate_type != NoError { // Return an error here by looking up the namespace that @@ -218,7 +216,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { let r = child.span_for_namespace(ns); if let Some(sp) = r { self.session.span_note(sp, - &format!("first definition of {} `{}` here", + &format!("first definition of {} `{}` here", namespace_error_to_string(duplicate_type), name)); } @@ -278,15 +276,20 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { let module_path = match view_path.node { ViewPathSimple(_, ref full_path) => { full_path.segments - .split_last().unwrap().1 - .iter().map(|seg| seg.identifier.name) - .collect() + .split_last() + .unwrap() + .1 + .iter() + .map(|seg| seg.identifier.name) + .collect() } ViewPathGlob(ref module_ident_path) | ViewPathList(ref module_ident_path, _) => { module_ident_path.segments - .iter().map(|seg| seg.identifier.name).collect() + .iter() + .map(|seg| seg.identifier.name) + .collect() } }; @@ -302,8 +305,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { match view_path.node { ViewPathSimple(binding, ref full_path) => { - let source_name = - full_path.segments.last().unwrap().identifier.name; + let source_name = full_path.segments.last().unwrap().identifier.name; if source_name.as_str() == "mod" || source_name.as_str() == "self" { resolve_error(self, view_path.span, @@ -321,19 +323,21 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { } ViewPathList(_, ref source_items) => { // Make sure there's at most one `mod` import in the list. - let mod_spans = source_items.iter().filter_map(|item| match item.node { - PathListMod { .. } => Some(item.span), - _ => None - }).collect::>(); + let mod_spans = source_items.iter() + .filter_map(|item| { + match item.node { + PathListMod { .. } => Some(item.span), + _ => None, + } + }) + .collect::>(); if mod_spans.len() > 1 { - resolve_error( - self, - mod_spans[0], - ResolutionError::SelfImportCanOnlyAppearOnceInTheList - ); + resolve_error(self, + mod_spans[0], + ResolutionError::SelfImportCanOnlyAppearOnceInTheList); for other_span in mod_spans.iter().skip(1) { - self.session.span_note(*other_span, - "another `self` import appears here"); + self.session + .span_note(*other_span, "another `self` import appears here"); } } @@ -359,14 +363,13 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { (module_path.to_vec(), name, rename) } }; - self.build_import_directive( - &**parent, - module_path, - SingleImport(rename, name), - source_item.span, - source_item.node.id(), - is_public, - shadowable); + self.build_import_directive(&**parent, + module_path, + SingleImport(rename, name), + source_item.span, + source_item.node.id(), + is_public, + shadowable); } } ViewPathGlob(_) => { @@ -383,9 +386,13 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { } ItemExternCrate(_) => { - // n.b. we don't need to look at the path option here, because cstore already did + // n.b. we don't need to look at the path option here, because cstore already + // did if let Some(crate_id) = self.session.cstore.find_extern_mod_stmt_cnum(item.id) { - let def_id = DefId { krate: crate_id, index: CRATE_DEF_INDEX }; + let def_id = DefId { + krate: crate_id, + index: CRATE_DEF_INDEX, + }; self.external_exports.insert(def_id); let parent_link = ModuleParentLink(Rc::downgrade(parent), name); let external_module = Rc::new(Module::new(parent_link, @@ -394,9 +401,10 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { false, true)); debug!("(build reduced graph for item) found extern `{}`", - module_to_string(&*external_module)); + module_to_string(&*external_module)); self.check_for_conflicts_between_external_crates(&**parent, name, sp); - parent.external_module_children.borrow_mut() + parent.external_module_children + .borrow_mut() .insert(name, external_module.clone()); self.build_reduced_graph_for_external_crate(&external_module); } @@ -407,20 +415,19 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { let child = parent.children.borrow().get(&name).cloned(); if let Some(child) = child { // check if there's struct of the same name already defined - if child.defined_in_namespace(TypeNS) - && child.get_module_if_available().is_none() { - self.session.span_warn(sp, &format!( - "duplicate definition of {} `{}`. \ - Defining a module and a struct with \ - the same name will be disallowed \ - soon.", - namespace_error_to_string(TypeError), - name)); + if child.defined_in_namespace(TypeNS) && + child.get_module_if_available().is_none() { + self.session.span_warn(sp, + &format!("duplicate definition of {} `{}`. \ + Defining a module and a struct with \ + the same name will be disallowed soon.", + namespace_error_to_string(TypeError), + name)); { let r = child.span_for_namespace(TypeNS); if let Some(sp) = r { self.session.span_note(sp, - &format!("first definition of {} `{}` here", + &format!("first definition of {} `{}` here", namespace_error_to_string(TypeError), name)); } @@ -468,10 +475,13 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { // These items live in the type namespace. ItemTy(..) => { - let name_bindings = - self.add_child(name, parent, ForbidDuplicateTypesAndModules, sp); + let name_bindings = self.add_child(name, + parent, + ForbidDuplicateTypesAndModules, + sp); - name_bindings.define_type(DefTy(self.ast_map.local_def_id(item.id), false), sp, + name_bindings.define_type(DefTy(self.ast_map.local_def_id(item.id), false), + sp, modifiers); let parent_link = self.get_parent_link(parent, name); @@ -485,8 +495,10 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { } ItemEnum(ref enum_definition, _) => { - let name_bindings = - self.add_child(name, parent, ForbidDuplicateTypesAndModules, sp); + let name_bindings = self.add_child(name, + parent, + ForbidDuplicateTypesAndModules, + sp); name_bindings.define_type(DefTy(self.ast_map.local_def_id(item.id), true), sp, @@ -504,10 +516,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { for variant in &(*enum_definition).variants { let item_def_id = self.ast_map.local_def_id(item.id); - self.build_reduced_graph_for_variant( - &**variant, - item_def_id, - &module); + self.build_reduced_graph_for_variant(&**variant, item_def_id, &module); } parent.clone() } @@ -522,20 +531,21 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { if let Some(child) = child { // check if theres a DefMod if let Some(DefMod(_)) = child.def_for_namespace(TypeNS) { - self.session.span_warn(sp, &format!( - "duplicate definition of {} `{}`. \ - Defining a module and a struct with \ - the same name will be disallowed \ - soon.", - namespace_error_to_string(TypeError), - name)); + self.session.span_warn(sp, + &format!("duplicate definition of {} `{}`. \ + Defining a module and a struct \ + with the same name will be \ + disallowed soon.", + namespace_error_to_string(TypeError), + name)); { let r = child.span_for_namespace(TypeNS); if let Some(sp) = r { - self.session.span_note(sp, - &format!("first definition of {} `{}` here", - namespace_error_to_string(TypeError), - name)); + self.session + .span_note(sp, + &format!("first definition of {} `{}` here", + namespace_error_to_string(TypeError), + name)); } } } @@ -559,12 +569,15 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { } // Record the def ID and fields of this struct. - let named_fields = struct_def.fields().iter().filter_map(|f| { - match f.node.kind { - NamedField(name, _) => Some(name), - UnnamedField(_) => None - } - }).collect(); + let named_fields = struct_def.fields() + .iter() + .filter_map(|f| { + match f.node.kind { + NamedField(name, _) => Some(name), + UnnamedField(_) => None, + } + }) + .collect(); let item_def_id = self.ast_map.local_def_id(item.id); self.structs.insert(item_def_id, named_fields); @@ -575,8 +588,10 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { ItemImpl(..) => parent.clone(), ItemTrait(_, _, _, ref items) => { - let name_bindings = - self.add_child(name, parent, ForbidDuplicateTypesAndModules, sp); + let name_bindings = self.add_child(name, + parent, + ForbidDuplicateTypesAndModules, + sp); // Add all the items within to a new module. let parent_link = self.get_parent_link(parent, name); @@ -593,9 +608,9 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { // Add the names of all the items to the trait info. for trait_item in items { let name_bindings = self.add_child(trait_item.name, - &module_parent, - ForbidDuplicateTypesAndValues, - trait_item.span); + &module_parent, + ForbidDuplicateTypesAndValues, + trait_item.span); match trait_item.node { hir::ConstTraitItem(..) => { @@ -642,19 +657,19 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { false }; - let child = self.add_child(name, parent, - ForbidDuplicateTypesAndValues, - variant.span); + let child = self.add_child(name, parent, ForbidDuplicateTypesAndValues, variant.span); // variants are always treated as importable to allow them to be glob // used child.define_value(DefVariant(item_id, self.ast_map.local_def_id(variant.node.data.id()), is_exported), - variant.span, DefModifiers::PUBLIC | DefModifiers::IMPORTABLE); + variant.span, + DefModifiers::PUBLIC | DefModifiers::IMPORTABLE); child.define_type(DefVariant(item_id, self.ast_map.local_def_id(variant.node.data.id()), is_exported), - variant.span, DefModifiers::PUBLIC | DefModifiers::IMPORTABLE); + variant.span, + DefModifiers::PUBLIC | DefModifiers::IMPORTABLE); } /// Constructs the reduced graph for one foreign item. @@ -668,9 +683,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { } else { DefModifiers::empty() } | DefModifiers::IMPORTABLE; - let name_bindings = - self.add_child(name, parent, ForbidDuplicateValues, - foreign_item.span); + let name_bindings = self.add_child(name, parent, ForbidDuplicateValues, foreign_item.span); let def = match foreign_item.node { ForeignItemFn(..) => { @@ -687,16 +700,15 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { if self.block_needs_anonymous_module(block) { let block_id = block.id; - debug!("(building reduced graph for block) creating a new \ - anonymous module for block {}", + debug!("(building reduced graph for block) creating a new anonymous module for block \ + {}", block_id); - let new_module = Rc::new(Module::new( - BlockParentLink(Rc::downgrade(parent), block_id), - None, - AnonymousModuleKind, - false, - false)); + let new_module = Rc::new(Module::new(BlockParentLink(Rc::downgrade(parent), block_id), + None, + AnonymousModuleKind, + false, + false)); parent.anonymous_children.borrow_mut().insert(block_id, new_module.clone()); new_module } else { @@ -711,18 +723,19 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { final_ident: &str, name: Name, new_parent: &Rc) { - debug!("(building reduced graph for \ - external crate) building external def {}, priv {:?}", - final_ident, vis); + debug!("(building reduced graph for external crate) building external def {}, priv {:?}", + final_ident, + vis); let is_public = vis == hir::Public; let modifiers = if is_public { DefModifiers::PUBLIC } else { DefModifiers::empty() } | DefModifiers::IMPORTABLE; - let is_exported = is_public && match new_parent.def_id.get() { + let is_exported = is_public && + match new_parent.def_id.get() { None => true, - Some(did) => self.external_exports.contains(&did) + Some(did) => self.external_exports.contains(&did), }; if is_exported { self.external_exports.insert(def.def_id()); @@ -731,140 +744,148 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { let kind = match def { DefTy(_, true) => EnumModuleKind, DefTy(_, false) | DefStruct(..) => TypeModuleKind, - _ => NormalModuleKind + _ => NormalModuleKind, }; match def { - DefMod(def_id) | DefForeignMod(def_id) | DefStruct(def_id) | - DefTy(def_id, _) => { - let type_def = child_name_bindings.type_def.borrow().clone(); - match type_def { - Some(TypeNsDef { module_def: Some(module_def), .. }) => { - debug!("(building reduced graph for external crate) \ - already created module"); - module_def.def_id.set(Some(def_id)); - } - Some(_) | None => { - debug!("(building reduced graph for \ - external crate) building module \ - {} {}", final_ident, is_public); - let parent_link = self.get_parent_link(new_parent, name); - - child_name_bindings.define_module(parent_link, - Some(def_id), - kind, - true, - is_public, - DUMMY_SP); - } + DefMod(def_id) | + DefForeignMod(def_id) | + DefStruct(def_id) | + DefTy(def_id, _) => { + let type_def = child_name_bindings.type_def.borrow().clone(); + match type_def { + Some(TypeNsDef { module_def: Some(module_def), .. }) => { + debug!("(building reduced graph for external crate) already created \ + module"); + module_def.def_id.set(Some(def_id)); + } + Some(_) | None => { + debug!("(building reduced graph for external crate) building module {} {}", + final_ident, + is_public); + let parent_link = self.get_parent_link(new_parent, name); + + child_name_bindings.define_module(parent_link, + Some(def_id), + kind, + true, + is_public, + DUMMY_SP); + } + } } - } - _ => {} + _ => {} } match def { - DefMod(_) | DefForeignMod(_) => {} - DefVariant(_, variant_id, is_struct) => { - debug!("(building reduced graph for external crate) building \ - variant {}", - final_ident); - // variants are always treated as importable to allow them to be - // glob used - let modifiers = DefModifiers::PUBLIC | DefModifiers::IMPORTABLE; - if is_struct { - child_name_bindings.define_type(def, DUMMY_SP, modifiers); - // Not adding fields for variants as they are not accessed with a self receiver - self.structs.insert(variant_id, Vec::new()); - } else { - child_name_bindings.define_value(def, DUMMY_SP, modifiers); - } - } - DefFn(ctor_id, true) => { - child_name_bindings.define_value( + DefMod(_) | DefForeignMod(_) => {} + DefVariant(_, variant_id, is_struct) => { + debug!("(building reduced graph for external crate) building variant {}", + final_ident); + // variants are always treated as importable to allow them to be + // glob used + let modifiers = DefModifiers::PUBLIC | DefModifiers::IMPORTABLE; + if is_struct { + child_name_bindings.define_type(def, DUMMY_SP, modifiers); + // Not adding fields for variants as they are not accessed with a self receiver + self.structs.insert(variant_id, Vec::new()); + } else { + child_name_bindings.define_value(def, DUMMY_SP, modifiers); + } + } + DefFn(ctor_id, true) => { + child_name_bindings.define_value( csearch::get_tuple_struct_definition_if_ctor(&self.session.cstore, ctor_id) .map_or(def, |_| DefStruct(ctor_id)), DUMMY_SP, modifiers); - } - DefFn(..) | DefStatic(..) | DefConst(..) | DefAssociatedConst(..) | - DefMethod(..) => { - debug!("(building reduced graph for external \ - crate) building value (fn/static) {}", final_ident); - // impl methods have already been defined with the correct importability modifier - let mut modifiers = match *child_name_bindings.value_def.borrow() { - Some(ref def) => (modifiers & !DefModifiers::IMPORTABLE) | - (def.modifiers & DefModifiers::IMPORTABLE), - None => modifiers - }; - if new_parent.kind.get() != NormalModuleKind { - modifiers = modifiers & !DefModifiers::IMPORTABLE; } - child_name_bindings.define_value(def, DUMMY_SP, modifiers); - } - DefTrait(def_id) => { - debug!("(building reduced graph for external \ - crate) building type {}", final_ident); - - // If this is a trait, add all the trait item names to the trait - // info. - - let trait_item_def_ids = - csearch::get_trait_item_def_ids(&self.session.cstore, def_id); - for trait_item_def in &trait_item_def_ids { - let trait_item_name = csearch::get_trait_name(&self.session.cstore, - trait_item_def.def_id()); - - debug!("(building reduced graph for external crate) ... \ - adding trait item '{}'", - trait_item_name); - - self.trait_item_map.insert((trait_item_name, def_id), - trait_item_def.def_id()); - - if is_exported { - self.external_exports.insert(trait_item_def.def_id()); - } - } - - child_name_bindings.define_type(def, DUMMY_SP, modifiers); - - // Define a module if necessary. - let parent_link = self.get_parent_link(new_parent, name); - child_name_bindings.set_module_kind(parent_link, - Some(def_id), - TraitModuleKind, - true, - is_public, - DUMMY_SP) - } - DefTy(..) | DefAssociatedTy(..) => { - debug!("(building reduced graph for external \ - crate) building type {}", final_ident); - - let modifiers = match new_parent.kind.get() { - NormalModuleKind => modifiers, - _ => modifiers & !DefModifiers::IMPORTABLE - }; - - child_name_bindings.define_type(def, DUMMY_SP, modifiers); - } - DefStruct(def_id) => { - debug!("(building reduced graph for external \ - crate) building type and value for {}", - final_ident); - child_name_bindings.define_type(def, DUMMY_SP, modifiers); - let fields = csearch::get_struct_field_names(&self.session.cstore, def_id); - - if fields.is_empty() { + DefFn(..) | + DefStatic(..) | + DefConst(..) | + DefAssociatedConst(..) | + DefMethod(..) => { + debug!("(building reduced graph for external crate) building value (fn/static) {}", + final_ident); + // impl methods have already been defined with the correct importability + // modifier + let mut modifiers = match *child_name_bindings.value_def.borrow() { + Some(ref def) => (modifiers & !DefModifiers::IMPORTABLE) | + (def.modifiers & DefModifiers::IMPORTABLE), + None => modifiers, + }; + if new_parent.kind.get() != NormalModuleKind { + modifiers = modifiers & !DefModifiers::IMPORTABLE; + } child_name_bindings.define_value(def, DUMMY_SP, modifiers); } + DefTrait(def_id) => { + debug!("(building reduced graph for external crate) building type {}", + final_ident); + + // If this is a trait, add all the trait item names to the trait + // info. + + let trait_item_def_ids = csearch::get_trait_item_def_ids(&self.session.cstore, + def_id); + for trait_item_def in &trait_item_def_ids { + let trait_item_name = csearch::get_trait_name(&self.session.cstore, + trait_item_def.def_id()); + + debug!("(building reduced graph for external crate) ... adding trait item \ + '{}'", + trait_item_name); + + self.trait_item_map.insert((trait_item_name, def_id), trait_item_def.def_id()); + + if is_exported { + self.external_exports.insert(trait_item_def.def_id()); + } + } + + child_name_bindings.define_type(def, DUMMY_SP, modifiers); + + // Define a module if necessary. + let parent_link = self.get_parent_link(new_parent, name); + child_name_bindings.set_module_kind(parent_link, + Some(def_id), + TraitModuleKind, + true, + is_public, + DUMMY_SP) + } + DefTy(..) | DefAssociatedTy(..) => { + debug!("(building reduced graph for external crate) building type {}", + final_ident); - // Record the def ID and fields of this struct. - self.structs.insert(def_id, fields); - } - DefLocal(..) | DefPrimTy(..) | DefTyParam(..) | - DefUse(..) | DefUpvar(..) | - DefLabel(..) | DefSelfTy(..) => { - panic!("didn't expect `{:?}`", def); - } + let modifiers = match new_parent.kind.get() { + NormalModuleKind => modifiers, + _ => modifiers & !DefModifiers::IMPORTABLE, + }; + + child_name_bindings.define_type(def, DUMMY_SP, modifiers); + } + DefStruct(def_id) => { + debug!("(building reduced graph for external crate) building type and value for \ + {}", + final_ident); + child_name_bindings.define_type(def, DUMMY_SP, modifiers); + let fields = csearch::get_struct_field_names(&self.session.cstore, def_id); + + if fields.is_empty() { + child_name_bindings.define_value(def, DUMMY_SP, modifiers); + } + + // Record the def ID and fields of this struct. + self.structs.insert(def_id, fields); + } + DefLocal(..) | + DefPrimTy(..) | + DefTyParam(..) | + DefUse(..) | + DefUpvar(..) | + DefLabel(..) | + DefSelfTy(..) => { + panic!("didn't expect `{:?}`", def); + } } } @@ -894,11 +915,10 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { }); } _ => { - let child_name_bindings = - self.add_child(name, - root, - OverwriteDuplicates, - DUMMY_SP); + let child_name_bindings = self.add_child(name, + root, + OverwriteDuplicates, + DUMMY_SP); self.handle_external_def(def, def_visibility, @@ -910,12 +930,10 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { } } DlImpl(_) => { - debug!("(building reduced graph for external crate) \ - ignoring impl"); + debug!("(building reduced graph for external crate) ignoring impl"); } DlField => { - debug!("(building reduced graph for external crate) \ - ignoring field"); + debug!("(building reduced graph for external crate) ignoring field"); } } } @@ -928,7 +946,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { let def_id = match module.def_id.get() { None => { debug!("(populating external module) ... no def ID!"); - return + return; } Some(def_id) => def_id, }; @@ -936,13 +954,13 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { csearch::each_child_of_item(&self.session.cstore, def_id, |def_like, child_name, visibility| { - debug!("(populating external module) ... found ident: {}", - child_name); - self.build_reduced_graph_for_external_crate_def(module, - def_like, - child_name, - visibility) - }); + debug!("(populating external module) ... found ident: {}", + child_name); + self.build_reduced_graph_for_external_crate_def(module, + def_like, + child_name, + visibility) + }); module.populated.set(true) } @@ -977,12 +995,9 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { id: NodeId, is_public: bool, shadowable: Shadowable) { - module_.imports.borrow_mut().push(ImportDirective::new(module_path, - subclass, - span, - id, - is_public, - shadowable)); + module_.imports + .borrow_mut() + .push(ImportDirective::new(module_path, subclass, span, id, is_public, shadowable)); self.unresolved_imports += 1; if is_public { @@ -1030,9 +1045,9 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { } } -struct BuildReducedGraphVisitor<'a, 'b:'a, 'tcx:'b> { +struct BuildReducedGraphVisitor<'a, 'b: 'a, 'tcx: 'b> { builder: GraphBuilder<'a, 'b, 'tcx>, - parent: Rc + parent: Rc, } impl<'a, 'b, 'v, 'tcx> Visitor<'v> for BuildReducedGraphVisitor<'a, 'b, 'tcx> { @@ -1056,13 +1071,9 @@ impl<'a, 'b, 'v, 'tcx> Visitor<'v> for BuildReducedGraphVisitor<'a, 'b, 'tcx> { } pub fn build_reduced_graph(resolver: &mut Resolver, krate: &hir::Crate) { - GraphBuilder { - resolver: resolver - }.build_reduced_graph(krate); + GraphBuilder { resolver: resolver }.build_reduced_graph(krate); } pub fn populate_module_if_necessary(resolver: &mut Resolver, module: &Rc) { - GraphBuilder { - resolver: resolver - }.populate_module_if_necessary(module); + GraphBuilder { resolver: resolver }.populate_module_if_necessary(module); } diff --git a/src/librustc_resolve/check_unused.rs b/src/librustc_resolve/check_unused.rs index 4ebc1093a0b6b..870990f78607c 100644 --- a/src/librustc_resolve/check_unused.rs +++ b/src/librustc_resolve/check_unused.rs @@ -31,8 +31,8 @@ use rustc_front::hir; use rustc_front::hir::{ViewPathGlob, ViewPathList, ViewPathSimple}; use rustc_front::visit::{self, Visitor}; -struct UnusedImportCheckVisitor<'a, 'b:'a, 'tcx:'b> { - resolver: &'a mut Resolver<'b, 'tcx> +struct UnusedImportCheckVisitor<'a, 'b: 'a, 'tcx: 'b> { + resolver: &'a mut Resolver<'b, 'tcx>, } // Deref and DerefMut impls allow treating UnusedImportCheckVisitor as Resolver. @@ -51,16 +51,16 @@ impl<'a, 'b, 'tcx:'b> DerefMut for UnusedImportCheckVisitor<'a, 'b, 'tcx> { } impl<'a, 'b, 'tcx> UnusedImportCheckVisitor<'a, 'b, 'tcx> { - // We have information about whether `use` (import) directives are actually used now. - // If an import is not used at all, we signal a lint error. If an import is only used - // for a single namespace, we remove the other namespace from the recorded privacy - // information. That means in privacy.rs, we will only check imports and namespaces - // which are used. In particular, this means that if an import could name either a - // public or private item, we will check the correct thing, dependent on how the import - // is used. + // We have information about whether `use` (import) directives are actually + // used now. If an import is not used at all, we signal a lint error. If an + // import is only used for a single namespace, we remove the other namespace + // from the recorded privacy information. That means in privacy.rs, we will + // only check imports and namespaces which are used. In particular, this + // means that if an import could name either a public or private item, we + // will check the correct thing, dependent on how the import is used. fn finalize_import(&mut self, id: ast::NodeId, span: Span) { debug!("finalizing import uses for {:?}", - self.session.codemap().span_to_snippet(span)); + self.session.codemap().span_to_snippet(span)); if !self.used_imports.contains(&(id, TypeNS)) && !self.used_imports.contains(&(id, ValueNS)) { @@ -99,14 +99,14 @@ impl<'a, 'b, 'tcx> UnusedImportCheckVisitor<'a, 'b, 'tcx> { // we might have two LastPrivates pointing at the same thing. There is no point // checking both, so lets not check the value one. (Some(DependsOn(def_v)), Some(DependsOn(def_t))) if def_v == def_t => v_used = Unused, - _ => {}, + _ => {} } path_res.last_private = LastImport { value_priv: v_priv, value_used: v_used, type_priv: t_priv, - type_used: t_used + type_used: t_used, }; } } @@ -132,7 +132,7 @@ impl<'a, 'b, 'v, 'tcx> Visitor<'v> for UnusedImportCheckVisitor<'a, 'b, 'tcx> { "unused extern crate".to_string()); } } - }, + } hir::ItemUse(ref p) => { match p.node { ViewPathSimple(_, _) => { diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index 4147f2bea4850..f35b554d6cf2b 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -10,9 +10,9 @@ #![allow(non_snake_case)] -// Error messages for EXXXX errors. -// Each message should start and end with a new line, and be wrapped to 80 characters. -// In vim you can `:set tw=80` and use `gq` to wrap paragraphs. Use `:set tw=0` to disable. +// Error messages for EXXXX errors. Each message should start and end with a +// new line, and be wrapped to 80 characters. In vim you can `:set tw=80` and +// use `gq` to wrap paragraphs. Use `:set tw=0` to disable. register_long_diagnostics! { E0154: r##" @@ -806,6 +806,15 @@ mod something { pub struct Foo; } ``` + +Or, if you tried to use a module from an external crate, you may have missed +the `extern crate` declaration: + +``` +extern crate homura; // Required to use the `homura` crate + +use homura::Madoka; +``` "##, E0433: r##" diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 106591724a798..a402d8310f96a 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -25,9 +25,13 @@ #![feature(rustc_private)] #![feature(staged_api)] -#[macro_use] extern crate log; -#[macro_use] extern crate syntax; -#[macro_use] #[no_link] extern crate rustc_bitflags; +#[macro_use] +extern crate log; +#[macro_use] +extern crate syntax; +#[macro_use] +#[no_link] +extern crate rustc_bitflags; extern crate rustc_front; extern crate rustc; @@ -53,7 +57,7 @@ use rustc::front::map as hir_map; use rustc::session::Session; use rustc::lint; use rustc::metadata::csearch; -use rustc::metadata::decoder::{DefLike, DlDef, DlField, DlImpl}; +use rustc::metadata::decoder::{DefLike, DlDef}; use rustc::middle::def::*; use rustc::middle::def_id::DefId; use rustc::middle::pat_util::pat_bindings_hygienic; @@ -153,7 +157,7 @@ pub enum ResolutionError<'a> { /// error E0413: declaration shadows an enum variant or unit-like struct in scope DeclarationShadowsEnumVariantOrUnitLikeStruct(Name), /// error E0414: only irrefutable patterns allowed here - OnlyIrrefutablePatternsAllowedHere, + OnlyIrrefutablePatternsAllowedHere(DefId, Name), /// error E0415: identifier is bound more than once in this parameter list IdentifierBoundMoreThanOnceInParameterList(&'a str), /// error E0416: identifier is bound more than once in the same pattern @@ -198,197 +202,279 @@ pub enum ResolutionError<'a> { AttemptToUseNonConstantValueInConstant, } -fn resolve_error<'b, 'a:'b, 'tcx:'a>(resolver: &'b Resolver<'a, 'tcx>, span: syntax::codemap::Span, - resolution_error: ResolutionError<'b>) { +fn resolve_error<'b, 'a: 'b, 'tcx: 'a>(resolver: &'b Resolver<'a, 'tcx>, + span: syntax::codemap::Span, + resolution_error: ResolutionError<'b>) { if !resolver.emit_errors { return; } match resolution_error { ResolutionError::TypeParametersFromOuterFunction => { - span_err!(resolver.session, span, E0401, "can't use type parameters from \ - outer function; try using a local \ - type parameter instead"); - }, + span_err!(resolver.session, + span, + E0401, + "can't use type parameters from outer function; try using a local type \ + parameter instead"); + } ResolutionError::OuterTypeParameterContext => { - span_err!(resolver.session, span, E0402, - "cannot use an outer type parameter in this context"); - }, + span_err!(resolver.session, + span, + E0402, + "cannot use an outer type parameter in this context"); + } ResolutionError::NameAlreadyUsedInTypeParameterList(name) => { - span_err!(resolver.session, span, E0403, - "the name `{}` is already used for a type \ - parameter in this type parameter list", name); - }, + span_err!(resolver.session, + span, + E0403, + "the name `{}` is already used for a type parameter in this type parameter \ + list", + name); + } ResolutionError::IsNotATrait(name) => { - span_err!(resolver.session, span, E0404, - "`{}` is not a trait", - name); - }, + span_err!(resolver.session, span, E0404, "`{}` is not a trait", name); + } ResolutionError::UndeclaredTraitName(name) => { - span_err!(resolver.session, span, E0405, - "use of undeclared trait name `{}`", - name); - }, + span_err!(resolver.session, + span, + E0405, + "use of undeclared trait name `{}`", + name); + } ResolutionError::UndeclaredAssociatedType => { span_err!(resolver.session, span, E0406, "undeclared associated type"); - }, + } ResolutionError::MethodNotMemberOfTrait(method, trait_) => { - span_err!(resolver.session, span, E0407, - "method `{}` is not a member of trait `{}`", - method, - trait_); - }, + span_err!(resolver.session, + span, + E0407, + "method `{}` is not a member of trait `{}`", + method, + trait_); + } ResolutionError::TypeNotMemberOfTrait(type_, trait_) => { - span_err!(resolver.session, span, E0437, - "type `{}` is not a member of trait `{}`", - type_, - trait_); - }, + span_err!(resolver.session, + span, + E0437, + "type `{}` is not a member of trait `{}`", + type_, + trait_); + } ResolutionError::ConstNotMemberOfTrait(const_, trait_) => { - span_err!(resolver.session, span, E0438, - "const `{}` is not a member of trait `{}`", - const_, - trait_); - }, + span_err!(resolver.session, + span, + E0438, + "const `{}` is not a member of trait `{}`", + const_, + trait_); + } ResolutionError::VariableNotBoundInPattern(variable_name, pattern_number) => { - span_err!(resolver.session, span, E0408, - "variable `{}` from pattern #1 is not bound in pattern #{}", - variable_name, - pattern_number); - }, + span_err!(resolver.session, + span, + E0408, + "variable `{}` from pattern #1 is not bound in pattern #{}", + variable_name, + pattern_number); + } ResolutionError::VariableBoundWithDifferentMode(variable_name, pattern_number) => { - span_err!(resolver.session, span, E0409, - "variable `{}` is bound with different \ - mode in pattern #{} than in pattern #1", - variable_name, - pattern_number); - }, + span_err!(resolver.session, + span, + E0409, + "variable `{}` is bound with different mode in pattern #{} than in pattern \ + #1", + variable_name, + pattern_number); + } ResolutionError::VariableNotBoundInParentPattern(variable_name, pattern_number) => { - span_err!(resolver.session, span, E0410, - "variable `{}` from pattern #{} is not bound in pattern #1", - variable_name, - pattern_number); - }, + span_err!(resolver.session, + span, + E0410, + "variable `{}` from pattern #{} is not bound in pattern #1", + variable_name, + pattern_number); + } ResolutionError::SelfUsedOutsideImplOrTrait => { - span_err!(resolver.session, span, E0411, "use of `Self` outside of an impl or trait"); - }, + span_err!(resolver.session, + span, + E0411, + "use of `Self` outside of an impl or trait"); + } ResolutionError::UseOfUndeclared(kind, name) => { - span_err!(resolver.session, span, E0412, - "use of undeclared {} `{}`", - kind, - name); - }, + span_err!(resolver.session, + span, + E0412, + "use of undeclared {} `{}`", + kind, + name); + } ResolutionError::DeclarationShadowsEnumVariantOrUnitLikeStruct(name) => { - span_err!(resolver.session, span, E0413, - "declaration of `{}` shadows an enum variant or unit-like struct in \ - scope", - name); - }, - ResolutionError::OnlyIrrefutablePatternsAllowedHere => { - span_err!(resolver.session, span, E0414, "only irrefutable patterns allowed here"); - }, + span_err!(resolver.session, + span, + E0413, + "declaration of `{}` shadows an enum variant or unit-like struct in scope", + name); + } + ResolutionError::OnlyIrrefutablePatternsAllowedHere(did, name) => { + span_err!(resolver.session, + span, + E0414, + "only irrefutable patterns allowed here"); + resolver.session.span_note(span, + "there already is a constant in scope sharing the same \ + name as this pattern"); + if let Some(sp) = resolver.ast_map.span_if_local(did) { + resolver.session.span_note(sp, "constant defined here"); + } + if let Some(directive) = resolver.current_module + .import_resolutions + .borrow() + .get(&name) { + let item = resolver.ast_map.expect_item(directive.value_id); + resolver.session.span_note(item.span, "constant imported here"); + } + } ResolutionError::IdentifierBoundMoreThanOnceInParameterList(identifier) => { - span_err!(resolver.session, span, E0415, - "identifier `{}` is bound more than once in this parameter list", - identifier); - }, + span_err!(resolver.session, + span, + E0415, + "identifier `{}` is bound more than once in this parameter list", + identifier); + } ResolutionError::IdentifierBoundMoreThanOnceInSamePattern(identifier) => { - span_err!(resolver.session, span, E0416, - "identifier `{}` is bound more than once in the same pattern", - identifier); - }, + span_err!(resolver.session, + span, + E0416, + "identifier `{}` is bound more than once in the same pattern", + identifier); + } ResolutionError::StaticVariableReference => { - span_err!(resolver.session, span, E0417, "static variables cannot be \ - referenced in a pattern, \ - use a `const` instead"); - }, + span_err!(resolver.session, + span, + E0417, + "static variables cannot be referenced in a pattern, use a `const` instead"); + } ResolutionError::NotAnEnumVariantStructOrConst(name) => { - span_err!(resolver.session, span, E0418, - "`{}` is not an enum variant, struct or const", - name); - }, + span_err!(resolver.session, + span, + E0418, + "`{}` is not an enum variant, struct or const", + name); + } ResolutionError::UnresolvedEnumVariantStructOrConst(name) => { - span_err!(resolver.session, span, E0419, - "unresolved enum variant, struct or const `{}`", - name); - }, + span_err!(resolver.session, + span, + E0419, + "unresolved enum variant, struct or const `{}`", + name); + } ResolutionError::NotAnAssociatedConst(name) => { - span_err!(resolver.session, span, E0420, - "`{}` is not an associated const", - name); - }, + span_err!(resolver.session, + span, + E0420, + "`{}` is not an associated const", + name); + } ResolutionError::UnresolvedAssociatedConst(name) => { - span_err!(resolver.session, span, E0421, - "unresolved associated const `{}`", - name); - }, + span_err!(resolver.session, + span, + E0421, + "unresolved associated const `{}`", + name); + } ResolutionError::DoesNotNameAStruct(name) => { - span_err!(resolver.session, span, E0422, "`{}` does not name a structure", name); - }, + span_err!(resolver.session, + span, + E0422, + "`{}` does not name a structure", + name); + } ResolutionError::StructVariantUsedAsFunction(path_name) => { - span_err!(resolver.session, span, E0423, - "`{}` is the name of a struct or struct variant, \ - but this expression \ - uses it like a function name", - path_name); - }, + span_err!(resolver.session, + span, + E0423, + "`{}` is the name of a struct or struct variant, but this expression uses \ + it like a function name", + path_name); + } ResolutionError::SelfNotAvailableInStaticMethod => { - span_err!(resolver.session, span, E0424, "`self` is not available in a static method. \ - Maybe a `self` argument is missing?"); - }, + span_err!(resolver.session, + span, + E0424, + "`self` is not available in a static method. Maybe a `self` argument is \ + missing?"); + } ResolutionError::UnresolvedName(path, name) => { - span_err!(resolver.session, span, E0425, - "unresolved name `{}`{}", - path, - name); - }, + span_err!(resolver.session, + span, + E0425, + "unresolved name `{}`{}", + path, + name); + } ResolutionError::UndeclaredLabel(name) => { - span_err!(resolver.session, span, E0426, - "use of undeclared label `{}`", - name); - }, + span_err!(resolver.session, + span, + E0426, + "use of undeclared label `{}`", + name); + } ResolutionError::CannotUseRefBindingModeWith(descr) => { - span_err!(resolver.session, span, E0427, - "cannot use `ref` binding mode with {}", - descr); - }, + span_err!(resolver.session, + span, + E0427, + "cannot use `ref` binding mode with {}", + descr); + } ResolutionError::DuplicateDefinition(namespace, name) => { - span_err!(resolver.session, span, E0428, - "duplicate definition of {} `{}`", - namespace, - name); - }, + span_err!(resolver.session, + span, + E0428, + "duplicate definition of {} `{}`", + namespace, + name); + } ResolutionError::SelfImportsOnlyAllowedWithin => { - span_err!(resolver.session, span, E0429, "{}", - "`self` imports are only allowed within a { } list"); - }, + span_err!(resolver.session, + span, + E0429, + "{}", + "`self` imports are only allowed within a { } list"); + } ResolutionError::SelfImportCanOnlyAppearOnceInTheList => { - span_err!(resolver.session, span, E0430, - "`self` import can only appear once in the list"); - }, + span_err!(resolver.session, + span, + E0430, + "`self` import can only appear once in the list"); + } ResolutionError::SelfImportOnlyInImportListWithNonEmptyPrefix => { - span_err!(resolver.session, span, E0431, - "`self` import can only appear in an import list with a \ - non-empty prefix"); + span_err!(resolver.session, + span, + E0431, + "`self` import can only appear in an import list with a non-empty prefix"); } ResolutionError::UnresolvedImport(name) => { let msg = match name { Some((n, p)) => format!("unresolved import `{}`{}", n, p), - None => "unresolved import".to_owned() + None => "unresolved import".to_owned(), }; span_err!(resolver.session, span, E0432, "{}", msg); - }, + } ResolutionError::FailedToResolve(msg) => { span_err!(resolver.session, span, E0433, "failed to resolve. {}", msg); - }, + } ResolutionError::CannotCaptureDynamicEnvironmentInFnItem => { - span_err!(resolver.session, span, E0434, "{}", - "can't capture dynamic environment in a fn item; \ - use the || { ... } closure form instead"); - }, - ResolutionError::AttemptToUseNonConstantValueInConstant =>{ - span_err!(resolver.session, span, E0435, - "attempt to use a non-constant value in a constant"); - }, + span_err!(resolver.session, + span, + E0434, + "{}", + "can't capture dynamic environment in a fn item; use the || { ... } \ + closure form instead"); + } + ResolutionError::AttemptToUseNonConstantValueInConstant => { + span_err!(resolver.session, + span, + E0435, + "attempt to use a non-constant value in a constant"); + } } } @@ -411,7 +497,7 @@ enum PatternBindingMode { #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] pub enum Namespace { TypeNS, - ValueNS + ValueNS, } /// A NamespaceResult represents the result of resolving an import in @@ -428,20 +514,20 @@ enum NamespaceResult { UnboundResult, /// Means that resolve has determined that the name is bound in the Module /// argument, and specified by the NameBindings argument. - BoundResult(Rc, Rc) + BoundResult(Rc, Rc), } impl NamespaceResult { fn is_unknown(&self) -> bool { match *self { UnknownResult => true, - _ => false + _ => false, } } fn is_unbound(&self) -> bool { match *self { UnboundResult => true, - _ => false + _ => false, } } } @@ -481,16 +567,19 @@ impl<'a, 'v, 'tcx> Visitor<'v> for Resolver<'a, 'tcx> { fn visit_generics(&mut self, generics: &Generics) { self.resolve_generics(generics); } - fn visit_poly_trait_ref(&mut self, - tref: &hir::PolyTraitRef, - m: &hir::TraitBoundModifier) { + fn visit_poly_trait_ref(&mut self, tref: &hir::PolyTraitRef, m: &hir::TraitBoundModifier) { match self.resolve_trait_reference(tref.trait_ref.ref_id, &tref.trait_ref.path, 0) { Ok(def) => self.record_def(tref.trait_ref.ref_id, def), - Err(_) => { /* error already reported */ } + Err(_) => { + // error already reported + } } visit::walk_poly_trait_ref(self, tref, m); } - fn visit_variant(&mut self, variant: &hir::Variant, generics: &Generics, item_id: ast::NodeId) { + fn visit_variant(&mut self, + variant: &hir::Variant, + generics: &Generics, + item_id: ast::NodeId) { execute_callback!(hir_map::Node::NodeVariant(variant), self); if let Some(ref dis_expr) = variant.node.disr_expr { // resolve the discriminator expr as a constant @@ -500,8 +589,11 @@ impl<'a, 'v, 'tcx> Visitor<'v> for Resolver<'a, 'tcx> { } // `visit::walk_variant` without the discriminant expression. - self.visit_variant_data(&variant.node.data, variant.node.name, - generics, item_id, variant.span); + self.visit_variant_data(&variant.node.data, + variant.node.name, + generics, + item_id, + variant.span); } fn visit_foreign_item(&mut self, foreign_item: &hir::ForeignItem) { execute_callback!(hir_map::Node::NodeForeignItem(foreign_item), self); @@ -509,7 +601,7 @@ impl<'a, 'v, 'tcx> Visitor<'v> for Resolver<'a, 'tcx> { ForeignItemFn(_, ref generics) => { HasTypeParameters(generics, FnSpace, ItemRibKind) } - ForeignItemStatic(..) => NoTypeParameters + ForeignItemStatic(..) => NoTypeParameters, }; self.with_type_parameter_rib(type_parameters, |this| { visit::walk_foreign_item(this, foreign_item); @@ -531,7 +623,7 @@ impl<'a, 'v, 'tcx> Visitor<'v> for Resolver<'a, 'tcx> { self.visit_explicit_self(&sig.explicit_self); MethodRibKind } - FnKind::Closure(..) => ClosureRibKind(node_id) + FnKind::Closure(..) => ClosureRibKind(node_id), }; self.resolve_function(rib_kind, declaration, block); } @@ -540,14 +632,17 @@ impl<'a, 'v, 'tcx> Visitor<'v> for Resolver<'a, 'tcx> { type ErrorMessage = Option<(Span, String)>; enum ResolveResult { - Failed(ErrorMessage), // Failed to resolve the name, optional helpful error message. - Indeterminate, // Couldn't determine due to unresolved globs. - Success(T) // Successfully resolved the import. + Failed(ErrorMessage), // Failed to resolve the name, optional helpful error message. + Indeterminate, // Couldn't determine due to unresolved globs. + Success(T), // Successfully resolved the import. } impl ResolveResult { fn success(&self) -> bool { - match *self { Success(_) => true, _ => false } + match *self { + Success(_) => true, + _ => false, + } } } @@ -563,16 +658,15 @@ enum FallbackSuggestion { #[derive(Copy, Clone)] enum TypeParameters<'a> { NoTypeParameters, - HasTypeParameters( - // Type parameters. - &'a Generics, + HasTypeParameters(// Type parameters. + &'a Generics, - // Identifies the things that these parameters - // were declared on (type, fn, etc) - ParamSpace, + // Identifies the things that these parameters + // were declared on (type, fn, etc) + ParamSpace, - // The kind of the rib used for type parameters. - RibKind) + // The kind of the rib used for type parameters. + RibKind), } // The rib kind controls the translation of local @@ -596,18 +690,18 @@ enum RibKind { ItemRibKind, // We're in a constant item. Can't refer to dynamic stuff. - ConstantItemRibKind + ConstantItemRibKind, } #[derive(Copy, Clone)] enum UseLexicalScopeFlag { DontUseLexicalScope, - UseLexicalScope + UseLexicalScope, } enum ModulePrefixResult { NoPrefixFound, - PrefixFound(Rc, usize) + PrefixFound(Rc, usize), } #[derive(Copy, Clone)] @@ -632,8 +726,8 @@ enum NameSearchType { #[derive(Copy, Clone)] enum BareIdentifierPatternResolution { FoundStructOrEnumVariant(Def, LastPrivate), - FoundConst(Def, LastPrivate), - BareIdentifierPatternUnresolved + FoundConst(Def, LastPrivate, Name), + BareIdentifierPatternUnresolved, } /// One local scope. @@ -647,7 +741,22 @@ impl Rib { fn new(kind: RibKind) -> Rib { Rib { bindings: HashMap::new(), - kind: kind + kind: kind, + } + } +} + +/// A definition along with the index of the rib it was found on +struct LocalDef { + ribs: Option<(Namespace, usize)>, + def: Def, +} + +impl LocalDef { + fn from_def(def: Def) -> Self { + LocalDef { + ribs: None, + def: def, } } } @@ -657,7 +766,7 @@ impl Rib { enum ParentLink { NoParentLink, ModuleParentLink(Weak, Name), - BlockParentLink(Weak, NodeId) + BlockParentLink(Weak, NodeId), } /// The type of module this is. @@ -782,10 +891,15 @@ impl Module { impl fmt::Debug for Module { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{:?}, kind: {:?}, {}", + write!(f, + "{:?}, kind: {:?}, {}", self.def_id, self.kind, - if self.is_public { "public" } else { "private" } ) + if self.is_public { + "public" + } else { + "private" + }) } } @@ -803,7 +917,7 @@ struct TypeNsDef { modifiers: DefModifiers, // see note in ImportResolution about how to use this module_def: Option>, type_def: Option, - type_span: Option + type_span: Option, } // Records a possibly-private value definition. @@ -818,8 +932,8 @@ struct ValueNsDef { // bound to. #[derive(Debug)] pub struct NameBindings { - type_def: RefCell>, //< Meaning in type namespace. - value_def: RefCell>, //< Meaning in value namespace. + type_def: RefCell>, // < Meaning in type namespace. + value_def: RefCell>, // < Meaning in value namespace. } impl NameBindings { @@ -844,11 +958,7 @@ impl NameBindings { } else { DefModifiers::empty() } | DefModifiers::IMPORTABLE; - let module_ = Rc::new(Module::new(parent_link, - def_id, - kind, - external, - is_public)); + let module_ = Rc::new(Module::new(parent_link, def_id, kind, external, is_public)); let type_def = self.type_def.borrow().clone(); match type_def { None => { @@ -856,7 +966,7 @@ impl NameBindings { modifiers: modifiers, module_def: Some(module_), type_def: None, - type_span: Some(sp) + type_span: Some(sp), }); } Some(type_def) => { @@ -864,7 +974,7 @@ impl NameBindings { modifiers: modifiers, module_def: Some(module_), type_span: Some(sp), - type_def: type_def.type_def + type_def: type_def.type_def, }); } } @@ -886,11 +996,7 @@ impl NameBindings { let type_def = self.type_def.borrow().clone(); match type_def { None => { - let module = Module::new(parent_link, - def_id, - kind, - external, - is_public); + let module = Module::new(parent_link, def_id, kind, external, is_public); *self.type_def.borrow_mut() = Some(TypeNsDef { modifiers: modifiers, module_def: Some(Rc::new(module)), @@ -901,11 +1007,7 @@ impl NameBindings { Some(type_def) => { match type_def.module_def { None => { - let module = Module::new(parent_link, - def_id, - kind, - external, - is_public); + let module = Module::new(parent_link, def_id, kind, external, is_public); *self.type_def.borrow_mut() = Some(TypeNsDef { modifiers: modifiers, module_def: Some(Rc::new(module)), @@ -921,7 +1023,9 @@ impl NameBindings { /// Records a type definition. fn define_type(&self, def: Def, sp: Span, modifiers: DefModifiers) { - debug!("defining type for def {:?} with modifiers {:?}", def, modifiers); + debug!("defining type for def {:?} with modifiers {:?}", + def, + modifiers); // Merges the type with the existing type def or creates a new one. let type_def = self.type_def.borrow().clone(); match type_def { @@ -946,7 +1050,9 @@ impl NameBindings { /// Records a value definition. fn define_value(&self, def: Def, sp: Span, modifiers: DefModifiers) { - debug!("defining value for def {:?} with modifiers {:?}", def, modifiers); + debug!("defining value for def {:?} with modifiers {:?}", + def, + modifiers); *self.value_def.borrow_mut() = Some(ValueNsDef { def: def, value_span: Some(sp), @@ -958,7 +1064,7 @@ impl NameBindings { fn get_module_if_available(&self) -> Option> { match *self.type_def.borrow() { Some(ref type_def) => type_def.module_def.clone(), - None => None + None => None, } } @@ -967,17 +1073,16 @@ impl NameBindings { fn get_module(&self) -> Rc { match self.get_module_if_available() { None => { - panic!("get_module called on a node with no module \ - definition!") + panic!("get_module called on a node with no module definition!") } - Some(module_def) => module_def + Some(module_def) => module_def, } } fn defined_in_namespace(&self, namespace: Namespace) -> bool { match namespace { - TypeNS => return self.type_def.borrow().is_some(), - ValueNS => return self.value_def.borrow().is_some() + TypeNS => return self.type_def.borrow().is_some(), + ValueNS => return self.value_def.borrow().is_some(), } } @@ -988,11 +1093,13 @@ impl NameBindings { fn defined_in_namespace_with(&self, namespace: Namespace, modifiers: DefModifiers) -> bool { match namespace { TypeNS => match *self.type_def.borrow() { - Some(ref def) => def.modifiers.contains(modifiers), None => false + Some(ref def) => def.modifiers.contains(modifiers), + None => false, }, ValueNS => match *self.value_def.borrow() { - Some(ref def) => def.modifiers.contains(modifiers), None => false - } + Some(ref def) => def.modifiers.contains(modifiers), + None => false, + }, } } @@ -1022,7 +1129,7 @@ impl NameBindings { ValueNS => { match *self.value_def.borrow() { None => None, - Some(value_def) => Some(value_def.def) + Some(value_def) => Some(value_def.def), } } } @@ -1031,16 +1138,16 @@ impl NameBindings { fn span_for_namespace(&self, namespace: Namespace) -> Option { if self.defined_in_namespace(namespace) { match namespace { - TypeNS => { + TypeNS => { match *self.type_def.borrow() { None => None, - Some(ref type_def) => type_def.type_span + Some(ref type_def) => type_def.type_span, } } ValueNS => { match *self.value_def.borrow() { None => None, - Some(ref value_def) => value_def.value_span + Some(ref value_def) => value_def.value_span, } } } @@ -1051,7 +1158,7 @@ impl NameBindings { fn is_public(&self, namespace: Namespace) -> bool { match namespace { - TypeNS => { + TypeNS => { let type_def = self.type_def.borrow(); type_def.as_ref().unwrap().modifiers.contains(DefModifiers::PUBLIC) } @@ -1070,25 +1177,23 @@ struct PrimitiveTypeTable { impl PrimitiveTypeTable { fn new() -> PrimitiveTypeTable { - let mut table = PrimitiveTypeTable { - primitive_types: HashMap::new() - }; - - table.intern("bool", TyBool); - table.intern("char", TyChar); - table.intern("f32", TyFloat(TyF32)); - table.intern("f64", TyFloat(TyF64)); - table.intern("isize", TyInt(TyIs)); - table.intern("i8", TyInt(TyI8)); - table.intern("i16", TyInt(TyI16)); - table.intern("i32", TyInt(TyI32)); - table.intern("i64", TyInt(TyI64)); - table.intern("str", TyStr); - table.intern("usize", TyUint(TyUs)); - table.intern("u8", TyUint(TyU8)); - table.intern("u16", TyUint(TyU16)); - table.intern("u32", TyUint(TyU32)); - table.intern("u64", TyUint(TyU64)); + let mut table = PrimitiveTypeTable { primitive_types: HashMap::new() }; + + table.intern("bool", TyBool); + table.intern("char", TyChar); + table.intern("f32", TyFloat(TyF32)); + table.intern("f64", TyFloat(TyF64)); + table.intern("isize", TyInt(TyIs)); + table.intern("i8", TyInt(TyI8)); + table.intern("i16", TyInt(TyI16)); + table.intern("i32", TyInt(TyI32)); + table.intern("i64", TyInt(TyI64)); + table.intern("str", TyStr); + table.intern("usize", TyUint(TyUs)); + table.intern("u8", TyUint(TyU8)); + table.intern("u16", TyUint(TyU16)); + table.intern("u32", TyUint(TyU32)); + table.intern("u64", TyUint(TyU64)); table } @@ -1099,7 +1204,7 @@ impl PrimitiveTypeTable { } /// The main resolver class. -pub struct Resolver<'a, 'tcx:'a> { +pub struct Resolver<'a, 'tcx: 'a> { session: &'a Session, ast_map: &'a hir_map::Map<'tcx>, @@ -1135,9 +1240,9 @@ pub struct Resolver<'a, 'tcx:'a> { // The idents for the primitive types. primitive_type_table: PrimitiveTypeTable, - def_map: DefMap, - freevars: RefCell, - freevars_seen: RefCell>>, + def_map: RefCell, + freevars: FreevarMap, + freevars_seen: NodeMap>, export_map: ExportMap, trait_map: TraitMap, external_exports: ExternalExports, @@ -1160,20 +1265,20 @@ pub struct Resolver<'a, 'tcx:'a> { // The intention is that the callback modifies this flag. // Once set, the resolver falls out of the walk, preserving the ribs. resolved: bool, - } #[derive(PartialEq)] enum FallbackChecks { Everything, - OnlyTraitAndStatics + OnlyTraitAndStatics, } impl<'a, 'tcx> Resolver<'a, 'tcx> { fn new(session: &'a Session, ast_map: &'a hir_map::Map<'tcx>, crate_span: Span, - make_glob_map: MakeGlobMap) -> Resolver<'a, 'tcx> { + make_glob_map: MakeGlobMap) + -> Resolver<'a, 'tcx> { let graph_root = NameBindings::new(); let root_def_id = ast_map.local_def_id(CRATE_NODE_ID); @@ -1193,7 +1298,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // The outermost module has def ID 0; this is not reflected in the // AST. - graph_root: graph_root, trait_item_map: FnvHashMap(), @@ -1212,8 +1316,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { primitive_type_table: PrimitiveTypeTable::new(), def_map: RefCell::new(NodeMap()), - freevars: RefCell::new(NodeMap()), - freevars_seen: RefCell::new(NodeMap()), + freevars: NodeMap(), + freevars_seen: NodeMap(), export_map: NodeMap(), trait_map: NodeMap(), used_imports: HashSet::new(), @@ -1226,7 +1330,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { callback: None, resolved: false, - } } @@ -1259,7 +1362,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { modifiers: DefModifiers::IMPORTABLE, module_def: Some(module), type_def: None, - type_span: None + type_span: None, })), value_def: RefCell::new(None), } @@ -1272,10 +1375,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { name: Name, span: Span) { if module.external_module_children.borrow().contains_key(&name) { - span_err!(self.session, span, E0259, - "an external crate named `{}` has already \ - been imported into this module", - name); + span_err!(self.session, + span, + E0259, + "an external crate named `{}` has already been imported into this module", + name); } } @@ -1285,11 +1389,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { name: Name, span: Span) { if module.external_module_children.borrow().contains_key(&name) { - span_err!(self.session, span, E0260, - "the name `{}` conflicts with an external \ - crate that has been imported into this \ - module", - name); + span_err!(self.session, + span, + E0260, + "the name `{}` conflicts with an external crate that has been imported \ + into this module", + name); } } @@ -1301,17 +1406,16 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { span: Span, name_search_type: NameSearchType, lp: LastPrivate) - -> ResolveResult<(Rc, LastPrivate)> { - fn search_parent_externals(needle: Name, module: &Rc) - -> Option> { + -> ResolveResult<(Rc, LastPrivate)> { + fn search_parent_externals(needle: Name, module: &Rc) -> Option> { match module.external_module_children.borrow().get(&needle) { Some(_) => Some(module.clone()), None => match module.parent_link { ModuleParentLink(ref parent, _) => { search_parent_externals(needle, &parent.upgrade().unwrap()) } - _ => None - } + _ => None, + }, } } @@ -1337,13 +1441,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let msg = if "???" == &module_name[..] { span.hi = span.lo + Pos::from_usize(segment_name.len()); - match search_parent_externals(name, - &self.current_module) { + match search_parent_externals(name, &self.current_module) { Some(module) => { let path_str = names_to_string(module_path); let target_mod_str = module_to_string(&*module); - let current_mod_str = - module_to_string(&*self.current_module); + let current_mod_str = module_to_string(&*self.current_module); let prefix = if target_mod_str == current_mod_str { "self::".to_string() @@ -1352,23 +1454,20 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { }; format!("Did you mean `{}{}`?", prefix, path_str) - }, - None => format!("Maybe a missing `extern crate {}`?", - segment_name), + } + None => format!("Maybe a missing `extern crate {}`?", segment_name), } } else { - format!("Could not find `{}` in `{}`", - segment_name, - module_name) + format!("Could not find `{}` in `{}`", segment_name, module_name) }; return Failed(Some((span, msg))); } Failed(err) => return Failed(err), Indeterminate => { - debug!("(resolving module path for import) module \ - resolution is indeterminate: {}", - name); + debug!("(resolving module path for import) module resolution is \ + indeterminate: {}", + name); return Indeterminate; } Success((target, used_proxy)) => { @@ -1378,8 +1477,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { Some(ref type_def) => { match type_def.module_def { None => { - let msg = format!("Not a module `{}`", - name); + let msg = format!("Not a module `{}`", name); return Failed(Some((span, msg))); } @@ -1404,8 +1502,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } None => { // There are no type bindings at all. - let msg = format!("Not a module `{}`", - name); + let msg = format!("Not a module `{}`", name); return Failed(Some((span, msg))); } } @@ -1438,8 +1535,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { module_to_string(&*module_)); // Resolve the module prefix, if any. - let module_prefix_result = self.resolve_module_prefix(module_.clone(), - module_path); + let module_prefix_result = self.resolve_module_prefix(module_.clone(), module_path); let search_module; let start_index; @@ -1451,21 +1547,20 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { match mpath.rfind(':') { Some(idx) => { let msg = format!("Could not find `{}` in `{}`", - // idx +- 1 to account for the - // colons on either side - &mpath[idx + 1..], - &mpath[..idx - 1]); + // idx +- 1 to account for the + // colons on either side + &mpath[idx + 1..], + &mpath[..idx - 1]); return Failed(Some((span, msg))); - }, + } None => { - return Failed(None) + return Failed(None); } } } Failed(err) => return Failed(err), Indeterminate => { - debug!("(resolving module path for import) indeterminate; \ - bailing"); + debug!("(resolving module path for import) indeterminate; bailing"); return Indeterminate; } Success(NoPrefixFound) => { @@ -1484,12 +1579,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // This is not a crate-relative path. We resolve the // first component of the path in the current lexical // scope and then proceed to resolve below that. - match self.resolve_module_in_lexical_scope(module_, - module_path[0]) { + match self.resolve_module_in_lexical_scope(module_, module_path[0]) { Failed(err) => return Failed(err), Indeterminate => { - debug!("(resolving module path for import) \ - indeterminate; bailing"); + debug!("(resolving module path for import) indeterminate; bailing"); return Indeterminate; } Success(containing_module) => { @@ -1524,9 +1617,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { module_: Rc, name: Name, namespace: Namespace) - -> ResolveResult<(Target, bool)> { - debug!("(resolving item in lexical scope) resolving `{}` in \ - namespace {:?} in `{}`", + -> ResolveResult<(Target, bool)> { + debug!("(resolving item in lexical scope) resolving `{}` in namespace {:?} in `{}`", name, namespace, module_to_string(&*module_)); @@ -1536,15 +1628,16 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { build_reduced_graph::populate_module_if_necessary(self, &module_); match module_.children.borrow().get(&name) { - Some(name_bindings) - if name_bindings.defined_in_namespace(namespace) => { + Some(name_bindings) if name_bindings.defined_in_namespace(namespace) => { debug!("top name bindings succeeded"); return Success((Target::new(module_.clone(), name_bindings.clone(), Shadowable::Never), - false)); + false)); + } + Some(_) | None => { + // Not found; continue. } - Some(_) | None => { /* Not found; continue. */ } } // Now check for its import directives. We don't have to have resolved @@ -1555,19 +1648,18 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { match (*import_resolution).target_for_namespace(namespace) { None => { // Not found; continue. - debug!("(resolving item in lexical scope) found \ - import resolution, but not in namespace {:?}", + debug!("(resolving item in lexical scope) found import resolution, but not \ + in namespace {:?}", namespace); } Some(target) => { - debug!("(resolving item in lexical scope) using \ - import resolution"); + debug!("(resolving item in lexical scope) using import resolution"); // track used imports and extern crates as well let id = import_resolution.id(namespace); self.used_imports.insert((id, namespace)); self.record_import_use(id, name); if let Some(DefId{krate: kid, ..}) = target.target_module.def_id.get() { - self.used_crates.insert(kid); + self.used_crates.insert(kid); } return Success((target, false)); } @@ -1579,12 +1671,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // FIXME (21114): In principle unclear `child` *has* to be lifted. let child = module_.external_module_children.borrow().get(&name).cloned(); if let Some(module) = child { - let name_bindings = - Rc::new(Resolver::create_name_bindings_from_module(module)); + let name_bindings = Rc::new(Resolver::create_name_bindings_from_module(module)); debug!("lower name bindings succeeded"); - return Success((Target::new(module_, - name_bindings, - Shadowable::Never), + return Success((Target::new(module_, name_bindings, Shadowable::Never), false)); } } @@ -1596,18 +1685,15 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { match search_module.parent_link.clone() { NoParentLink => { // No more parents. This module was unresolved. - debug!("(resolving item in lexical scope) unresolved \ - module"); + debug!("(resolving item in lexical scope) unresolved module"); return Failed(None); } ModuleParentLink(parent_module_node, _) => { match search_module.kind.get() { NormalModuleKind => { // We stop the search here. - debug!("(resolving item in lexical \ - scope) unresolved module: not \ - searching through module \ - parents"); + debug!("(resolving item in lexical scope) unresolved module: not \ + searching through module parents"); return Failed(None); } TraitModuleKind | @@ -1631,20 +1717,18 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { true) { Failed(Some((span, msg))) => { resolve_error(self, span, ResolutionError::FailedToResolve(&*msg)); - }, + } Failed(None) => (), // Continue up the search chain. Indeterminate => { // We couldn't see through the higher scope because of an // unresolved import higher up. Bail. - debug!("(resolving item in lexical scope) indeterminate \ - higher scope; bailing"); + debug!("(resolving item in lexical scope) indeterminate higher scope; bailing"); return Indeterminate; } Success((target, used_reexport)) => { // We found the module. - debug!("(resolving item in lexical scope) found name \ - in module, done"); + debug!("(resolving item in lexical scope) found name in module, done"); return Success((target, used_reexport)); } } @@ -1655,7 +1739,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { fn resolve_module_in_lexical_scope(&mut self, module_: Rc, name: Name) - -> ResolveResult> { + -> ResolveResult> { // If this module is an anonymous module, resolve the item in the // lexical scope. Otherwise, resolve the item from the crate root. let resolve_result = self.resolve_item_in_lexical_scope(module_, name, TypeNS); @@ -1666,9 +1750,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { Some(ref type_def) => { match type_def.module_def { None => { - debug!("!!! (resolving module in lexical \ - scope) module wasn't actually a \ - module!"); + debug!("!!! (resolving module in lexical scope) module wasn't \ + actually a module!"); return Failed(None); } Some(ref module_def) => { @@ -1678,14 +1761,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } None => { debug!("!!! (resolving module in lexical scope) module + \ wasn't actually a module!"); return Failed(None); } } } Indeterminate => { - debug!("(resolving module in lexical scope) indeterminate; \ - bailing"); + debug!("(resolving module in lexical scope) indeterminate; bailing"); return Indeterminate; } Failed(err) => { @@ -1696,8 +1779,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } /// Returns the nearest normal module parent of the given module. - fn get_nearest_normal_module_parent(&mut self, module_: Rc) - -> Option> { + fn get_nearest_normal_module_parent(&mut self, module_: Rc) -> Option> { let mut module_ = module_; loop { match module_.parent_link.clone() { @@ -1719,8 +1801,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { /// Returns the nearest normal module parent of the given module, or the /// module itself if it is a normal module. - fn get_nearest_normal_module_parent_or_self(&mut self, module_: Rc) - -> Rc { + fn get_nearest_normal_module_parent_or_self(&mut self, module_: Rc) -> Rc { match module_.kind.get() { NormalModuleKind => return module_, TraitModuleKind | @@ -1729,7 +1810,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { AnonymousModuleKind => { match self.get_nearest_normal_module_parent(module_.clone()) { None => module_, - Some(new_module) => new_module + Some(new_module) => new_module, } } } @@ -1741,7 +1822,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { fn resolve_module_prefix(&mut self, module_: Rc, module_path: &[Name]) - -> ResolveResult { + -> ResolveResult { // Start at the current module if we see `self` or `super`, or at the // top of the crate otherwise. let mut i = match &*module_path[0].as_str() { @@ -1791,13 +1872,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { build_reduced_graph::populate_module_if_necessary(self, &module_); match module_.children.borrow().get(&name) { - Some(name_bindings) - if name_bindings.defined_in_namespace(namespace) => { + Some(name_bindings) if name_bindings.defined_in_namespace(namespace) => { debug!("(resolving name in module) found node as child"); return Success((Target::new(module_.clone(), name_bindings.clone(), Shadowable::Never), - false)); + false)); } Some(_) | None => { // Continue. @@ -1814,24 +1894,19 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // Check the list of resolved imports. match module_.import_resolutions.borrow().get(&name) { - Some(import_resolution) if allow_private_imports || - import_resolution.is_public => { + Some(import_resolution) if allow_private_imports || import_resolution.is_public => { - if import_resolution.is_public && - import_resolution.outstanding_references != 0 { - debug!("(resolving name in module) import \ - unresolved; bailing out"); + if import_resolution.is_public && import_resolution.outstanding_references != 0 { + debug!("(resolving name in module) import unresolved; bailing out"); return Indeterminate; } match import_resolution.target_for_namespace(namespace) { None => { - debug!("(resolving name in module) name found, \ - but not in namespace {:?}", + debug!("(resolving name in module) name found, but not in namespace {:?}", namespace); } Some(target) => { - debug!("(resolving name in module) resolved to \ - import"); + debug!("(resolving name in module) resolved to import"); // track used imports and extern crates as well let id = import_resolution.id(namespace); self.used_imports.insert((id, namespace)); @@ -1851,18 +1926,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // FIXME (21114): In principle unclear `child` *has* to be lifted. let child = module_.external_module_children.borrow().get(&name).cloned(); if let Some(module) = child { - let name_bindings = - Rc::new(Resolver::create_name_bindings_from_module(module)); - return Success((Target::new(module_, - name_bindings, - Shadowable::Never), + let name_bindings = Rc::new(Resolver::create_name_bindings_from_module(module)); + return Success((Target::new(module_, name_bindings, Shadowable::Never), false)); } } // We're out of luck. - debug!("(resolving name in module) failed to resolve `{}`", - name); + debug!("(resolving name in module) failed to resolve `{}`", name); return Failed(None); } @@ -1913,8 +1984,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // generate a fake "implementation scope" containing all the // implementations thus found, for compatibility with old resolve pass. - fn with_scope(&mut self, name: Option, f: F) where - F: FnOnce(&mut Resolver), + fn with_scope(&mut self, name: Option, f: F) + where F: FnOnce(&mut Resolver) { let orig_module = self.current_module.clone(); @@ -1935,8 +2006,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { Some(name_bindings) => { match (*name_bindings).get_module_if_available() { None => { - debug!("!!! (with scope) didn't find module \ - for `{}` in `{}`", + debug!("!!! (with scope) didn't find module for `{}` in `{}`", name, module_to_string(&*orig_module)); } @@ -1954,116 +2024,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { self.current_module = orig_module; } - /// Wraps the given definition in the appropriate number of `DefUpvar` - /// wrappers. - fn upvarify(&self, - ribs: &[Rib], - def_like: DefLike, - span: Span) - -> Option { - let mut def = match def_like { - DlDef(def) => def, - _ => return Some(def_like) - }; - match def { - DefUpvar(..) => { - self.session.span_bug(span, - &format!("unexpected {:?} in bindings", def)) - } - DefLocal(_, node_id) => { - for rib in ribs { - match rib.kind { - NormalRibKind => { - // Nothing to do. Continue. - } - ClosureRibKind(function_id) => { - let prev_def = def; - let node_def_id = self.ast_map.local_def_id(node_id); - - let mut seen = self.freevars_seen.borrow_mut(); - let seen = seen.entry(function_id).or_insert_with(|| NodeMap()); - if let Some(&index) = seen.get(&node_id) { - def = DefUpvar(node_def_id, node_id, index, function_id); - continue; - } - let mut freevars = self.freevars.borrow_mut(); - let vec = freevars.entry(function_id) - .or_insert_with(|| vec![]); - let depth = vec.len(); - vec.push(Freevar { def: prev_def, span: span }); - - def = DefUpvar(node_def_id, node_id, depth, function_id); - seen.insert(node_id, depth); - } - ItemRibKind | MethodRibKind => { - // This was an attempt to access an upvar inside a - // named function item. This is not allowed, so we - // report an error. - resolve_error( - self, - span, - ResolutionError::CannotCaptureDynamicEnvironmentInFnItem - ); - return None; - } - ConstantItemRibKind => { - // Still doesn't deal with upvars - resolve_error( - self, - span, - ResolutionError::AttemptToUseNonConstantValueInConstant - ); - return None; - } - } - } - } - DefTyParam(..) | DefSelfTy(..) => { - for rib in ribs { - match rib.kind { - NormalRibKind | MethodRibKind | ClosureRibKind(..) => { - // Nothing to do. Continue. - } - ItemRibKind => { - // This was an attempt to use a type parameter outside - // its scope. - - resolve_error(self, - span, - ResolutionError::TypeParametersFromOuterFunction); - return None; - } - ConstantItemRibKind => { - // see #9186 - resolve_error(self, span, ResolutionError::OuterTypeParameterContext); - return None; - } - } - } - } - _ => {} - } - Some(DlDef(def)) - } - - /// Searches the current set of local scopes and - /// applies translations for closures. - fn search_ribs(&self, - ribs: &[Rib], - name: Name, - span: Span) - -> Option { - // FIXME #4950: Try caching? - - for (i, rib) in ribs.iter().enumerate().rev() { - if let Some(def_like) = rib.bindings.get(&name).cloned() { - return self.upvarify(&ribs[i + 1..], def_like, span); - } - } - - None - } - /// Searches the current set of local scopes for labels. /// Stops after meeting a closure. fn search_label(&self, name: Name) -> Option { @@ -2074,12 +2034,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } _ => { // Do not resolve labels across function boundary - return None + return None; } } let result = rib.bindings.get(&name).cloned(); if result.is_some() { - return result + return result; } } None @@ -2093,16 +2053,17 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { fn check_if_primitive_type_name(&self, name: Name, span: Span) { if let Some(_) = self.primitive_type_table.primitive_types.get(&name) { - span_err!(self.session, span, E0317, - "user-defined types or type parameters cannot shadow the primitive types"); + span_err!(self.session, + span, + E0317, + "user-defined types or type parameters cannot shadow the primitive types"); } } fn resolve_item(&mut self, item: &Item) { let name = item.name; - debug!("(resolving item) resolving {}", - name); + debug!("(resolving item) resolving {}", name); match item.node { ItemEnum(_, ref generics) | @@ -2110,27 +2071,18 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { ItemStruct(_, ref generics) => { self.check_if_primitive_type_name(name, item.span); - self.with_type_parameter_rib(HasTypeParameters(generics, - TypeSpace, - ItemRibKind), + self.with_type_parameter_rib(HasTypeParameters(generics, TypeSpace, ItemRibKind), |this| visit::walk_item(this, item)); } ItemFn(_, _, _, _, ref generics, _) => { - self.with_type_parameter_rib(HasTypeParameters(generics, - FnSpace, - ItemRibKind), + self.with_type_parameter_rib(HasTypeParameters(generics, FnSpace, ItemRibKind), |this| visit::walk_item(this, item)); } ItemDefaultImpl(_, ref trait_ref) => { self.with_optional_trait_ref(Some(trait_ref), |_, _| {}); } - ItemImpl(_, - _, - ref generics, - ref opt_trait_ref, - ref self_type, - ref impl_items) => { + ItemImpl(_, _, ref generics, ref opt_trait_ref, ref self_type, ref impl_items) => { self.resolve_implementation(generics, opt_trait_ref, &**self_type, @@ -2226,8 +2178,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { match self.resolve_crate_relative_path(prefix.span, &prefix.segments, TypeNS) { - Some((def, lp)) => self.record_def(item.id, - PathResolution::new(def, lp, 0)), + Some((def, lp)) => + self.record_def(item.id, PathResolution::new(def, lp, 0)), None => { resolve_error(self, prefix.span, @@ -2247,8 +2199,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } - fn with_type_parameter_rib(&mut self, type_parameters: TypeParameters, f: F) where - F: FnOnce(&mut Resolver), + fn with_type_parameter_rib(&mut self, type_parameters: TypeParameters, f: F) + where F: FnOnce(&mut Resolver) { match type_parameters { HasTypeParameters(generics, space, rib_kind) => { @@ -2261,18 +2213,18 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { if seen_bindings.contains(&name) { resolve_error(self, type_parameter.span, - ResolutionError::NameAlreadyUsedInTypeParameterList( - name) - ); + ResolutionError::NameAlreadyUsedInTypeParameterList(name)); } seen_bindings.insert(name); // plain insert (no renaming) - function_type_rib.bindings.insert(name, - DlDef(DefTyParam(space, - index as u32, - self.ast_map.local_def_id(type_parameter.id), - name))); + function_type_rib.bindings + .insert(name, + DlDef(DefTyParam(space, + index as u32, + self.ast_map + .local_def_id(type_parameter.id), + name))); } self.type_ribs.push(function_type_rib); } @@ -2285,13 +2237,17 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { f(self); match type_parameters { - HasTypeParameters(..) => { if !self.resolved { self.type_ribs.pop(); } } - NoTypeParameters => { } + HasTypeParameters(..) => { + if !self.resolved { + self.type_ribs.pop(); + } + } + NoTypeParameters => {} } } - fn with_label_rib(&mut self, f: F) where - F: FnOnce(&mut Resolver), + fn with_label_rib(&mut self, f: F) + where F: FnOnce(&mut Resolver) { self.label_ribs.push(Rib::new(NormalRibKind)); f(self); @@ -2300,8 +2256,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } - fn with_constant_rib(&mut self, f: F) where - F: FnOnce(&mut Resolver), + fn with_constant_rib(&mut self, f: F) + where F: FnOnce(&mut Resolver) { self.value_ribs.push(Rib::new(ConstantItemRibKind)); self.type_ribs.push(Rib::new(ConstantItemRibKind)); @@ -2312,10 +2268,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } - fn resolve_function(&mut self, - rib_kind: RibKind, - declaration: &FnDecl, - block: &Block) { + fn resolve_function(&mut self, rib_kind: RibKind, declaration: &FnDecl, block: &Block) { // Create a value rib for the function. self.value_ribs.push(Rib::new(rib_kind)); @@ -2325,9 +2278,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // Add each argument to the rib. let mut bindings_list = HashMap::new(); for argument in &declaration.inputs { - self.resolve_pattern(&*argument.pat, - ArgumentIrrefutableMode, - &mut bindings_list); + self.resolve_pattern(&*argument.pat, ArgumentIrrefutableMode, &mut bindings_list); self.visit_ty(&*argument.ty); @@ -2359,22 +2310,20 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { resolve_error(self, trait_path.span, ResolutionError::IsNotATrait(&*path_names_to_string(trait_path, - path_depth)) - ); + path_depth))); // If it's a typedef, give a note if let DefTy(..) = path_res.base_def { - self.session.span_note(trait_path.span, - "`type` aliases cannot be used for traits"); + self.session + .span_note(trait_path.span, "`type` aliases cannot be used for traits"); } Err(()) } } else { resolve_error(self, trait_path.span, - ResolutionError::UndeclaredTraitName( - &*path_names_to_string(trait_path, path_depth)) - ); + ResolutionError::UndeclaredTraitName(&*path_names_to_string(trait_path, + path_depth))); Err(()) } } @@ -2412,17 +2361,15 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { result } - fn with_optional_trait_ref(&mut self, - opt_trait_ref: Option<&TraitRef>, - f: F) - -> T + fn with_optional_trait_ref(&mut self, opt_trait_ref: Option<&TraitRef>, f: F) -> T where F: FnOnce(&mut Resolver, Option) -> T { let mut new_val = None; let mut new_id = None; if let Some(trait_ref) = opt_trait_ref { if let Ok(path_res) = self.resolve_trait_reference(trait_ref.ref_id, - &trait_ref.path, 0) { + &trait_ref.path, + 0) { assert!(path_res.depth == 0); self.record_def(trait_ref.ref_id, path_res); new_val = Some((path_res.base_def.def_id(), trait_ref.clone())); @@ -2519,14 +2466,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } fn check_trait_item(&self, name: Name, span: Span, err: F) - where F: FnOnce(Name, &str) -> ResolutionError { - // If there is a TraitRef in scope for an impl, then the method must be in the trait. + where F: FnOnce(Name, &str) -> ResolutionError + { + // If there is a TraitRef in scope for an impl, then the method must be in the + // trait. if let Some((did, ref trait_ref)) = self.current_trait_ref { if !self.trait_item_map.contains_key(&(name, did)) { let path_str = path_names_to_string(&trait_ref.path, 0); - resolve_error(self, - span, - err(name, &*path_str)); + resolve_error(self, span, err(name, &*path_str)); } } } @@ -2539,9 +2486,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { walk_list!(self, visit_expr, &local.init); // Resolve the pattern. - self.resolve_pattern(&*local.pat, - LocalIrrefutableMode, - &mut HashMap::new()); + self.resolve_pattern(&*local.pat, LocalIrrefutableMode, &mut HashMap::new()); } // build a map from pattern identifiers to binding-info's. @@ -2552,10 +2497,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let mut result = HashMap::new(); pat_bindings_hygienic(&self.def_map, pat, |binding_mode, _id, sp, path1| { let name = mtwt::resolve(path1.node); - result.insert(name, BindingInfo { - span: sp, - binding_mode: binding_mode - }); + result.insert(name, + BindingInfo { + span: sp, + binding_mode: binding_mode, + }); }); return result; } @@ -2564,7 +2510,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // same set of bindings, with the same binding modes for each. fn check_consistent_bindings(&mut self, arm: &Arm) { if arm.pats.is_empty() { - return + return; } let map_0 = self.binding_mode_map(&*arm.pats[0]); for (i, p) in arm.pats.iter().enumerate() { @@ -2572,21 +2518,19 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { for (&key, &binding_0) in &map_0 { match map_i.get(&key) { - None => { - resolve_error(self, - p.span, - ResolutionError::VariableNotBoundInPattern(key, - i + 1)); - } - Some(binding_i) => { - if binding_0.binding_mode != binding_i.binding_mode { + None => { resolve_error(self, - binding_i.span, - ResolutionError::VariableBoundWithDifferentMode(key, - i + 1) - ); + p.span, + ResolutionError::VariableNotBoundInPattern(key, i + 1)); + } + Some(binding_i) => { + if binding_0.binding_mode != binding_i.binding_mode { + resolve_error(self, + binding_i.span, + ResolutionError::VariableBoundWithDifferentMode(key, + i + 1)); + } } - } } } @@ -2594,8 +2538,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { if !map_0.contains_key(&key) { resolve_error(self, binding.span, - ResolutionError::VariableNotBoundInParentPattern(key, - i + 1)); + ResolutionError::VariableNotBoundInParentPattern(key, i + 1)); } } } @@ -2628,10 +2571,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // Move down in the graph, if there's an anonymous module rooted here. let orig_module = self.current_module.clone(); match orig_module.anonymous_children.borrow().get(&block.id) { - None => { /* Nothing to do. */ } + None => { + // Nothing to do. + } Some(anonymous_module) => { - debug!("(resolving block) found anonymous module, moving \ - down"); + debug!("(resolving block) found anonymous module, moving down"); self.current_module = anonymous_module.clone(); } } @@ -2643,8 +2587,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { if let hir::DeclItem(ref i) = declaration.node { match i.node { ItemExternCrate(_) | ItemUse(_) if found_non_item => { - span_err!(self.session, i.span, E0154, - "imports are not allowed after non-item statements"); + span_err!(self.session, + i.span, + E0154, + "imports are not allowed after non-item statements"); } _ => {} } @@ -2670,30 +2616,29 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { fn resolve_type(&mut self, ty: &Ty) { match ty.node { TyPath(ref maybe_qself, ref path) => { - let resolution = - match self.resolve_possibly_assoc_item(ty.id, - maybe_qself.as_ref(), - path, - TypeNS, - true) { - // `::a::b::c` is resolved by typeck alone. - TypecheckRequired => { - // Resolve embedded types. - visit::walk_ty(self, ty); - return; - } - ResolveAttempt(resolution) => resolution, - }; + let resolution = match self.resolve_possibly_assoc_item(ty.id, + maybe_qself.as_ref(), + path, + TypeNS, + true) { + // `::a::b::c` is resolved by typeck alone. + TypecheckRequired => { + // Resolve embedded types. + visit::walk_ty(self, ty); + return; + } + ResolveAttempt(resolution) => resolution, + }; // This is a path in the type namespace. Walk through scopes // looking for it. match resolution { Some(def) => { // Write the result into the def map. - debug!("(resolving type) writing resolution for `{}` \ - (id {}) = {:?}", + debug!("(resolving type) writing resolution for `{}` (id {}) = {:?}", path_names_to_string(path, 0), - ty.id, def); + ty.id, + def); self.record_def(ty.id, def); } None => { @@ -2707,10 +2652,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { }; let self_type_name = special_idents::type_self.name; - let is_invalid_self_type_name = - path.segments.len() > 0 && - maybe_qself.is_none() && - path.segments[0].identifier.name == self_type_name; + let is_invalid_self_type_name = path.segments.len() > 0 && + maybe_qself.is_none() && + path.segments[0].identifier.name == + self_type_name; if is_invalid_self_type_name { resolve_error(self, ty.span, @@ -2758,19 +2703,18 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { match self.resolve_bare_identifier_pattern(ident.name, pattern.span) { FoundStructOrEnumVariant(def, lp) if const_ok => { - debug!("(resolving pattern) resolving `{}` to \ - struct or enum variant", + debug!("(resolving pattern) resolving `{}` to struct or enum variant", renamed); - self.enforce_default_binding_mode( - pattern, - binding_mode, - "an enum variant"); - self.record_def(pattern.id, PathResolution { - base_def: def, - last_private: lp, - depth: 0 - }); + self.enforce_default_binding_mode(pattern, + binding_mode, + "an enum variant"); + self.record_def(pattern.id, + PathResolution { + base_def: def, + last_private: lp, + depth: 0, + }); } FoundStructOrEnumVariant(..) => { resolve_error( @@ -2780,31 +2724,27 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { renamed) ); } - FoundConst(def, lp) if const_ok => { - debug!("(resolving pattern) resolving `{}` to \ - constant", - renamed); - - self.enforce_default_binding_mode( - pattern, - binding_mode, - "a constant"); - self.record_def(pattern.id, PathResolution { - base_def: def, - last_private: lp, - depth: 0 - }); + FoundConst(def, lp, _) if const_ok => { + debug!("(resolving pattern) resolving `{}` to constant", renamed); + + self.enforce_default_binding_mode(pattern, binding_mode, "a constant"); + self.record_def(pattern.id, + PathResolution { + base_def: def, + last_private: lp, + depth: 0, + }); } - FoundConst(..) => { + FoundConst(def, _, name) => { resolve_error( self, pattern.span, - ResolutionError::OnlyIrrefutablePatternsAllowedHere + ResolutionError::OnlyIrrefutablePatternsAllowedHere(def.def_id(), + name) ); } BareIdentifierPatternUnresolved => { - debug!("(resolving pattern) binding `{}`", - renamed); + debug!("(resolving pattern) binding `{}`", renamed); let def_id = self.ast_map.local_def_id(pattern.id); let def = DefLocal(def_id, pattern.id); @@ -2813,11 +2753,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // will be able to distinguish variants from // locals in patterns. - self.record_def(pattern.id, PathResolution { - base_def: def, - last_private: LastMod(AllPublic), - depth: 0 - }); + self.record_def(pattern.id, + PathResolution { + base_def: def, + last_private: LastMod(AllPublic), + depth: 0, + }); // Add the binding to the local ribs, if it // doesn't already exist in the bindings list. (We @@ -2830,7 +2771,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { last_rib.bindings.insert(renamed, DlDef(def)); bindings_list.insert(renamed, pat_id); } else if mode == ArgumentIrrefutableMode && - bindings_list.contains_key(&renamed) { + bindings_list.contains_key(&renamed) { // Forbid duplicate bindings in the same // parameter list. resolve_error( @@ -2839,8 +2780,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { ResolutionError::IdentifierBoundMoreThanOnceInParameterList( &ident.name.as_str()) ); - } else if bindings_list.get(&renamed) == - Some(&pat_id) { + } else if bindings_list.get(&renamed) == Some(&pat_id) { // Then this is a duplicate variable in the // same disjunction, which is an error. resolve_error( @@ -2858,21 +2798,24 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { PatEnum(ref path, _) => { // This must be an enum variant, struct or const. - let resolution = - match self.resolve_possibly_assoc_item(pat_id, None, - path, ValueNS, - false) { - // The below shouldn't happen because all - // qualified paths should be in PatQPath. - TypecheckRequired => - self.session.span_bug( - path.span, - "resolve_possibly_assoc_item claimed - that a path in PatEnum requires typecheck - to resolve, but qualified paths should be - PatQPath"), - ResolveAttempt(resolution) => resolution, - }; + let resolution = match self.resolve_possibly_assoc_item(pat_id, + None, + path, + ValueNS, + false) { + // The below shouldn't happen because all + // qualified paths should be in PatQPath. + TypecheckRequired => + self.session.span_bug(path.span, + "resolve_possibly_assoc_item claimed + \ + that a path in PatEnum requires typecheck + \ + to resolve, but qualified paths should be + \ + PatQPath"), + ResolveAttempt(resolution) => resolution, + }; if let Some(path_res) = resolution { match path_res.base_def { DefVariant(..) | DefStruct(..) | DefConst(..) => { @@ -2901,8 +2844,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { .as_str()) ); } else { - let const_name = path.segments.last().unwrap() - .identifier.name; + let const_name = path.segments + .last() + .unwrap() + .identifier + .name; let traits = self.get_traits_containing_item(const_name); self.trait_map.insert(pattern.id, traits); self.record_def(pattern.id, path_res); @@ -2922,23 +2868,27 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { PatQPath(ref qself, ref path) => { // Associated constants only. - let resolution = - match self.resolve_possibly_assoc_item(pat_id, Some(qself), - path, ValueNS, - false) { - TypecheckRequired => { - // All `::CONST` should end up here, and will - // require use of the trait map to resolve - // during typechecking. - let const_name = path.segments.last().unwrap() - .identifier.name; - let traits = self.get_traits_containing_item(const_name); - self.trait_map.insert(pattern.id, traits); - visit::walk_pat(self, pattern); - return true; - } - ResolveAttempt(resolution) => resolution, - }; + let resolution = match self.resolve_possibly_assoc_item(pat_id, + Some(qself), + path, + ValueNS, + false) { + TypecheckRequired => { + // All `::CONST` should end up here, and will + // require use of the trait map to resolve + // during typechecking. + let const_name = path.segments + .last() + .unwrap() + .identifier + .name; + let traits = self.get_traits_containing_item(const_name); + self.trait_map.insert(pattern.id, traits); + visit::walk_pat(self, pattern); + return true; + } + ResolveAttempt(resolution) => resolution, + }; if let Some(path_res) = resolution { match path_res.base_def { // All `::CONST` should end up here, and @@ -2957,13 +2907,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } } else { - resolve_error( - self, - path.span, - ResolutionError::UnresolvedAssociatedConst( - &path.segments.last().unwrap().identifier.name.as_str() - ) - ); + resolve_error(self, + path.span, + ResolutionError::UnresolvedAssociatedConst(&path.segments + .last() + .unwrap() + .identifier + .name + .as_str())); } visit::walk_pat(self, pattern); } @@ -2974,8 +2925,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { self.record_def(pattern.id, definition); } result => { - debug!("(resolving pattern) didn't find struct \ - def: {:?}", result); + debug!("(resolving pattern) didn't find struct def: {:?}", result); resolve_error( self, path.span, @@ -2999,21 +2949,20 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { }); } - fn resolve_bare_identifier_pattern(&mut self, name: Name, span: Span) + fn resolve_bare_identifier_pattern(&mut self, + name: Name, + span: Span) -> BareIdentifierPatternResolution { let module = self.current_module.clone(); - match self.resolve_item_in_lexical_scope(module, - name, - ValueNS) { + match self.resolve_item_in_lexical_scope(module, name, ValueNS) { Success((target, _)) => { - debug!("(resolve bare identifier pattern) succeeded in \ - finding {} at {:?}", - name, - target.bindings.value_def.borrow()); + debug!("(resolve bare identifier pattern) succeeded in finding {} at {:?}", + name, + target.bindings.value_def.borrow()); match *target.bindings.value_def.borrow() { None => { - panic!("resolved name in the value namespace to a \ - set of name bindings with no def?!"); + panic!("resolved name in the value namespace to a set of name bindings \ + with no def?!"); } Some(def) => { // For the two success cases, this lookup can be @@ -3024,12 +2973,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { return FoundStructOrEnumVariant(def, LastMod(AllPublic)); } def @ DefConst(..) | def @ DefAssociatedConst(..) => { - return FoundConst(def, LastMod(AllPublic)); + return FoundConst(def, LastMod(AllPublic), name); } DefStatic(..) => { - resolve_error(self, - span, - ResolutionError::StaticVariableReference); + resolve_error(self, span, ResolutionError::StaticVariableReference); return BareIdentifierPatternUnresolved; } _ => { @@ -3048,11 +2995,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { Some((span, msg)) => { resolve_error(self, span, ResolutionError::FailedToResolve(&*msg)); } - None => () + None => (), } - debug!("(resolve bare identifier pattern) failed to find {}", - name); + debug!("(resolve bare identifier pattern) failed to find {}", name); return BareIdentifierPatternUnresolved; } } @@ -3065,8 +3011,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { path: &Path, namespace: Namespace, check_ribs: bool) - -> AssocItemResolveResult - { + -> AssocItemResolveResult { let max_assoc_types; match maybe_qself { @@ -3091,8 +3036,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { break; } self.with_no_errors(|this| { - resolution = this.resolve_path(id, path, depth, - TypeNS, true); + resolution = this.resolve_path(id, path, depth, TypeNS, true); }); } if let Some(DefMod(_)) = resolution.map(|r| r.base_def) { @@ -3111,9 +3055,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { path: &Path, path_depth: usize, namespace: Namespace, - check_ribs: bool) -> Option { + check_ribs: bool) + -> Option { let span = path.span; - let segments = &path.segments[..path.segments.len()-path_depth]; + let segments = &path.segments[..path.segments.len() - path_depth]; let mk_res = |(def, lp)| PathResolution::new(def, lp, path_depth); @@ -3123,22 +3068,24 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } // Try to find a path to an item in a module. - let unqualified_def = - self.resolve_identifier(segments.last().unwrap().identifier, - namespace, - check_ribs, - span); + let unqualified_def = self.resolve_identifier(segments.last().unwrap().identifier, + namespace, + check_ribs); if segments.len() <= 1 { - return unqualified_def.map(mk_res); + return unqualified_def.and_then(|def| self.adjust_local_def(def, span)) + .map(|def| { + PathResolution::new(def, LastMod(AllPublic), path_depth) + }); } let def = self.resolve_module_relative_path(span, segments, namespace); match (def, unqualified_def) { - (Some((ref d, _)), Some((ref ud, _))) if *d == *ud => { + (Some((ref d, _)), Some(ref ud)) if *d == ud.def => { self.session .add_lint(lint::builtin::UNUSED_QUALIFICATIONS, - id, span, + id, + span, "unnecessary qualification".to_string()); } _ => {} @@ -3147,31 +3094,117 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { def.map(mk_res) } - // Resolve a single identifier. + // Resolve a single identifier fn resolve_identifier(&mut self, identifier: Ident, namespace: Namespace, - check_ribs: bool, - span: Span) - -> Option<(Def, LastPrivate)> { + check_ribs: bool) + -> Option { // First, check to see whether the name is a primitive type. if namespace == TypeNS { if let Some(&prim_ty) = self.primitive_type_table .primitive_types .get(&identifier.name) { - return Some((DefPrimTy(prim_ty), LastMod(AllPublic))); + return Some(LocalDef::from_def(DefPrimTy(prim_ty))); } } if check_ribs { - if let Some(def) = self.resolve_identifier_in_local_ribs(identifier, - namespace, - span) { - return Some((def, LastMod(AllPublic))); + if let Some(def) = self.resolve_identifier_in_local_ribs(identifier, namespace) { + return Some(def); } } self.resolve_item_by_name_in_lexical_scope(identifier.name, namespace) + .map(LocalDef::from_def) + } + + // Resolve a local definition, potentially adjusting for closures. + fn adjust_local_def(&mut self, local_def: LocalDef, span: Span) -> Option { + let ribs = match local_def.ribs { + Some((TypeNS, i)) => &self.type_ribs[i + 1..], + Some((ValueNS, i)) => &self.value_ribs[i + 1..], + _ => &[] as &[_], + }; + let mut def = local_def.def; + match def { + DefUpvar(..) => { + self.session.span_bug(span, &format!("unexpected {:?} in bindings", def)) + } + DefLocal(_, node_id) => { + for rib in ribs { + match rib.kind { + NormalRibKind => { + // Nothing to do. Continue. + } + ClosureRibKind(function_id) => { + let prev_def = def; + let node_def_id = self.ast_map.local_def_id(node_id); + + let seen = self.freevars_seen + .entry(function_id) + .or_insert_with(|| NodeMap()); + if let Some(&index) = seen.get(&node_id) { + def = DefUpvar(node_def_id, node_id, index, function_id); + continue; + } + let vec = self.freevars + .entry(function_id) + .or_insert_with(|| vec![]); + let depth = vec.len(); + vec.push(Freevar { + def: prev_def, + span: span, + }); + + def = DefUpvar(node_def_id, node_id, depth, function_id); + seen.insert(node_id, depth); + } + ItemRibKind | MethodRibKind => { + // This was an attempt to access an upvar inside a + // named function item. This is not allowed, so we + // report an error. + resolve_error(self, + span, + ResolutionError::CannotCaptureDynamicEnvironmentInFnItem); + return None; + } + ConstantItemRibKind => { + // Still doesn't deal with upvars + resolve_error(self, + span, + ResolutionError::AttemptToUseNonConstantValueInConstant); + return None; + } + } + } + } + DefTyParam(..) | DefSelfTy(..) => { + for rib in ribs { + match rib.kind { + NormalRibKind | MethodRibKind | ClosureRibKind(..) => { + // Nothing to do. Continue. + } + ItemRibKind => { + // This was an attempt to use a type parameter outside + // its scope. + + resolve_error(self, + span, + ResolutionError::TypeParametersFromOuterFunction); + return None; + } + ConstantItemRibKind => { + // see #9186 + resolve_error(self, span, ResolutionError::OuterTypeParameterContext); + return None; + } + } + } + } + _ => {} + } + return Some(def); } // FIXME #4952: Merge me with resolve_name_in_module? @@ -3189,7 +3222,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { Some(def) => { // Found it. Stop the search here. let p = child_name_bindings.defined_in_public_namespace(namespace); - let lp = if p {LastMod(AllPublic)} else { + let lp = if p { + LastMod(AllPublic) + } else { LastMod(DependsOn(def.def_id())) }; return ChildNameDefinition(def, lp); @@ -3214,7 +3249,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { match target.target_module.def_id.get() { Some(DefId{krate: kid, ..}) => { self.used_crates.insert(kid); - }, + } _ => {} } return ImportNameDefinition(def, LastMod(AllPublic)); @@ -3231,12 +3266,16 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // Finally, search through external children. if namespace == TypeNS { - if let Some(module) = containing_module.external_module_children.borrow() - .get(&name).cloned() { + if let Some(module) = containing_module.external_module_children + .borrow() + .get(&name) + .cloned() { if let Some(def_id) = module.def_id.get() { // track used crates self.used_crates.insert(def_id.krate); - let lp = if module.is_public {LastMod(AllPublic)} else { + let lp = if module.is_public { + LastMod(AllPublic) + } else { LastMod(DependsOn(def_id)) }; return ChildNameDefinition(DefMod(def_id), lp); @@ -3253,9 +3292,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { segments: &[hir::PathSegment], namespace: Namespace) -> Option<(Def, LastPrivate)> { - let module_path = segments.split_last().unwrap().1.iter() - .map(|ps| ps.identifier.name) - .collect::>(); + let module_path = segments.split_last() + .unwrap() + .1 + .iter() + .map(|ps| ps.identifier.name) + .collect::>(); let containing_module; let last_private; @@ -3309,10 +3351,13 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { span: Span, segments: &[hir::PathSegment], namespace: Namespace) - -> Option<(Def, LastPrivate)> { - let module_path = segments.split_last().unwrap().1.iter() - .map(|ps| ps.identifier.name) - .collect::>(); + -> Option<(Def, LastPrivate)> { + let module_path = segments.split_last() + .unwrap() + .1 + .iter() + .map(|ps| ps.identifier.name) + .collect::>(); let root_module = self.graph_root.get_module(); @@ -3349,9 +3394,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } let name = segments.last().unwrap().identifier.name; - match self.resolve_definition_of_name_in_module(containing_module, - name, - namespace) { + match self.resolve_definition_of_name_in_module(containing_module, name, namespace) { NoNameDefinition => { // We failed to resolve the name. Report an error. return None; @@ -3364,61 +3407,64 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { fn resolve_identifier_in_local_ribs(&mut self, ident: Ident, - namespace: Namespace, - span: Span) - -> Option { + namespace: Namespace) + -> Option { // Check the local set of ribs. - let search_result = match namespace { - ValueNS => { - let renamed = mtwt::resolve(ident); - self.search_ribs(&self.value_ribs, renamed, span) - } - TypeNS => { - let name = ident.name; - self.search_ribs(&self.type_ribs, name, span) - } + let (name, ribs) = match namespace { + ValueNS => (mtwt::resolve(ident), &self.value_ribs), + TypeNS => (ident.name, &self.type_ribs), }; - match search_result { - Some(DlDef(def)) => { - debug!("(resolving path in local ribs) resolved `{}` to local: {:?}", - ident, - def); - Some(def) - } - Some(DlField) | Some(DlImpl(_)) | None => { - None + for (i, rib) in ribs.iter().enumerate().rev() { + if let Some(def_like) = rib.bindings.get(&name).cloned() { + match def_like { + DlDef(def) => { + debug!("(resolving path in local ribs) resolved `{}` to {:?} at {}", + name, + def, + i); + return Some(LocalDef { + ribs: Some((namespace, i)), + def: def, + }); + } + def_like => { + debug!("(resolving path in local ribs) resolved `{}` to pseudo-def {:?}", + name, + def_like); + return None; + } + } } } + + None } fn resolve_item_by_name_in_lexical_scope(&mut self, name: Name, namespace: Namespace) - -> Option<(Def, LastPrivate)> { + -> Option { // Check the items. let module = self.current_module.clone(); - match self.resolve_item_in_lexical_scope(module, - name, - namespace) { + match self.resolve_item_in_lexical_scope(module, name, namespace) { Success((target, _)) => { match (*target.bindings).def_for_namespace(namespace) { None => { // This can happen if we were looking for a type and // found a module instead. Modules don't have defs. - debug!("(resolving item path by identifier in lexical \ - scope) failed to resolve {} after success...", - name); - return None; + debug!("(resolving item path by identifier in lexical scope) failed to \ + resolve {} after success...", + name); + None } Some(def) => { - debug!("(resolving item path in lexical scope) \ - resolved `{}` to item", + debug!("(resolving item path in lexical scope) resolved `{}` to item", name); // This lookup is "all public" because it only searched // for one identifier in the current module (couldn't // have passed through reexports or anything like that. - return Some((def, LastMod(AllPublic))); + Some(def) } } } @@ -3426,20 +3472,20 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { panic!("unexpected indeterminate result"); } Failed(err) => { - debug!("(resolving item path by identifier in lexical scope) \ - failed to resolve {}", name); + debug!("(resolving item path by identifier in lexical scope) failed to resolve {}", + name); if let Some((span, msg)) = err { resolve_error(self, span, ResolutionError::FailedToResolve(&*msg)) } - return None; + None } } } - fn with_no_errors(&mut self, f: F) -> T where - F: FnOnce(&mut Resolver) -> T, + fn with_no_errors(&mut self, f: F) -> T + where F: FnOnce(&mut Resolver) -> T { self.emit_errors = false; let rs = f(self); @@ -3448,8 +3494,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } fn find_fallback_in_self_type(&mut self, name: Name) -> FallbackSuggestion { - fn extract_path_and_node_id(t: &Ty, allow: FallbackChecks) - -> Option<(Path, NodeId, FallbackChecks)> { + fn extract_path_and_node_id(t: &Ty, + allow: FallbackChecks) + -> Option<(Path, NodeId, FallbackChecks)> { match t.node { TyPath(None, ref path) => Some((path.clone(), t.id, allow)), TyPtr(ref mut_ty) => extract_path_and_node_id(&*mut_ty.ty, OnlyTraitAndStatics), @@ -3461,8 +3508,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } - fn get_module(this: &mut Resolver, span: Span, name_path: &[ast::Name]) - -> Option> { + fn get_module(this: &mut Resolver, + span: Span, + name_path: &[ast::Name]) + -> Option> { let root = this.current_module.clone(); let last_name = name_path.last().unwrap(); @@ -3472,7 +3521,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { None => { match this.current_module.children.borrow().get(last_name) { Some(child) => child.get_module_if_available(), - None => None + None => None, } } } @@ -3483,7 +3532,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { span, PathSearch) { Success((module, _)) => Some(module), - _ => None + _ => None, } } } @@ -3493,13 +3542,13 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let sig = match this.ast_map.get(node_id) { hir_map::NodeTraitItem(trait_item) => match trait_item.node { hir::MethodTraitItem(ref sig, _) => sig, - _ => return false + _ => return false, }, hir_map::NodeImplItem(impl_item) => match impl_item.node { hir::MethodImplItem(ref sig, _) => sig, - _ => return false + _ => return false, }, - _ => return false + _ => return false, }; sig.explicit_self.node == hir::SelfStatic } else { @@ -3539,7 +3588,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { if let Some(binding) = module.children.borrow().get(&name) { if let Some(DefMethod(did)) = binding.def_for_namespace(ValueNS) { if is_static_method(self, did) { - return StaticMethod(path_names_to_string(&path, 0)) + return StaticMethod(path_names_to_string(&path, 0)); } if self.current_trait_ref.is_some() { return TraitItem; @@ -3589,9 +3638,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // the typo'd name's length. let max_distance = std::cmp::max(name.len(), 3) / 3; - if !values.is_empty() && - values[smallest] <= max_distance && - name != &maybes[smallest][..] { + if !values.is_empty() && values[smallest] <= max_distance && name != &maybes[smallest][..] { Some(maybes[smallest].to_string()) @@ -3609,22 +3656,21 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // Next, resolve the node. match expr.node { ExprPath(ref maybe_qself, ref path) => { - let resolution = - match self.resolve_possibly_assoc_item(expr.id, - maybe_qself.as_ref(), - path, - ValueNS, - true) { - // `::a::b::c` is resolved by typeck alone. - TypecheckRequired => { - let method_name = path.segments.last().unwrap().identifier.name; - let traits = self.get_traits_containing_item(method_name); - self.trait_map.insert(expr.id, traits); - visit::walk_expr(self, expr); - return; - } - ResolveAttempt(resolution) => resolution, - }; + let resolution = match self.resolve_possibly_assoc_item(expr.id, + maybe_qself.as_ref(), + path, + ValueNS, + true) { + // `::a::b::c` is resolved by typeck alone. + TypecheckRequired => { + let method_name = path.segments.last().unwrap().identifier.name; + let traits = self.get_traits_containing_item(method_name); + self.trait_map.insert(expr.id, traits); + visit::walk_expr(self, expr); + return; + } + ResolveAttempt(resolution) => resolution, + }; // This is a local path in the value namespace. Walk through // scopes looking for it. @@ -3637,8 +3683,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { expr.span, ResolutionError::StructVariantUsedAsFunction(&*path_name)); - let msg = format!("did you mean to write: \ - `{} {{ /* fields */ }}`?", + let msg = format!("did you mean to write: `{} {{ /* fields */ }}`?", path_name); if self.emit_errors { self.session.fileline_help(expr.span, &msg); @@ -3670,24 +3715,22 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { this.resolve_path(expr.id, path, 0, TypeNS, false) }); match type_res.map(|r| r.base_def) { - Some(DefTy(struct_id, _)) - if self.structs.contains_key(&struct_id) => { - resolve_error( + Some(DefTy(struct_id, _)) if self.structs.contains_key(&struct_id) => { + resolve_error( self, expr.span, ResolutionError::StructVariantUsedAsFunction( &*path_name) ); - let msg = format!("did you mean to write: \ - `{} {{ /* fields */ }}`?", - path_name); - if self.emit_errors { - self.session.fileline_help(expr.span, &msg); - } else { - self.session.span_help(expr.span, &msg); - } + let msg = format!("did you mean to write: `{} {{ /* fields */ }}`?", + path_name); + if self.emit_errors { + self.session.fileline_help(expr.span, &msg); + } else { + self.session.span_help(expr.span, &msg); } + } _ => { // Keep reporting some errors even if they're ignored above. self.resolve_path(expr.id, path, 0, ValueNS, true); @@ -3703,11 +3746,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { }); if method_scope && special_names::self_.as_str() == &path_name[..] { - resolve_error( - self, - expr.span, - ResolutionError::SelfNotAvailableInStaticMethod - ); + resolve_error(self, + expr.span, + ResolutionError::SelfNotAvailableInStaticMethod); } else { let last_name = path.segments.last().unwrap().identifier.name; let mut msg = match self.find_fallback_in_self_type(last_name) { @@ -3715,16 +3756,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // limit search to 5 to reduce the number // of stupid suggestions self.find_best_match_for_name(&path_name) - .map_or("".to_string(), - |x| format!("`{}`", x)) + .map_or("".to_string(), |x| format!("`{}`", x)) } Field => format!("`self.{}`", path_name), Method | - TraitItem => - format!("to call `self.{}`", path_name), + TraitItem => format!("to call `self.{}`", path_name), TraitMethod(path_str) | StaticMethod(path_str) => - format!("to call `{}::{}`", path_str, path_name) + format!("to call `{}::{}`", path_str, path_name), }; if !msg.is_empty() { @@ -3733,8 +3772,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { resolve_error(self, expr.span, - ResolutionError::UnresolvedName(&*path_name, - &*msg)); + ResolutionError::UnresolvedName(&*path_name, &*msg)); } } } @@ -3787,16 +3825,15 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } Some(DlDef(def @ DefLabel(_))) => { // Since this def is a label, it is never read. - self.record_def(expr.id, PathResolution { - base_def: def, - last_private: LastMod(AllPublic), - depth: 0 - }) + self.record_def(expr.id, + PathResolution { + base_def: def, + last_private: LastMod(AllPublic), + depth: 0, + }) } Some(_) => { - self.session.span_bug(expr.span, - "label wasn't mapped to a \ - label def!") + self.session.span_bug(expr.span, "label wasn't mapped to a label def!") } } } @@ -3818,8 +3855,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { self.trait_map.insert(expr.id, traits); } ExprMethodCall(name, _, _) => { - debug!("(recording candidate traits for expr) recording \ - traits for {}", + debug!("(recording candidate traits for expr) recording traits for {}", expr.id); let traits = self.get_traits_containing_item(name.node); self.trait_map.insert(expr.id, traits); @@ -3831,15 +3867,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } fn get_traits_containing_item(&mut self, name: Name) -> Vec { - debug!("(getting traits containing item) looking for '{}'", - name); + debug!("(getting traits containing item) looking for '{}'", name); - fn add_trait_info(found_traits: &mut Vec, - trait_def_id: DefId, - name: Name) { + fn add_trait_info(found_traits: &mut Vec, trait_def_id: DefId, name: Name) { debug!("(adding trait info) found trait {:?} for method '{}'", - trait_def_id, - name); + trait_def_id, + name); found_traits.push(trait_def_id); } @@ -3863,7 +3896,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { for (_, child_names) in search_module.children.borrow().iter() { let def = match child_names.def_for_namespace(TypeNS) { Some(def) => def, - None => continue + None => continue, }; let trait_def_id = match def { DefTrait(trait_def_id) => trait_def_id, @@ -3910,21 +3943,25 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { fn record_def(&mut self, node_id: NodeId, resolution: PathResolution) { debug!("(recording def) recording {:?} for {}", resolution, node_id); - assert!(match resolution.last_private {LastImport{..} => false, _ => true}, + assert!(match resolution.last_private { + LastImport{..} => false, + _ => true, + }, "Import should only be used for `use` directives"); if let Some(prev_res) = self.def_map.borrow_mut().insert(node_id, resolution) { let span = self.ast_map.opt_span(node_id).unwrap_or(codemap::DUMMY_SP); - self.session.span_bug(span, &format!("path resolved multiple times \ - ({:?} before, {:?} now)", - prev_res, resolution)); + self.session.span_bug(span, + &format!("path resolved multiple times ({:?} before, {:?} now)", + prev_res, + resolution)); } } fn enforce_default_binding_mode(&mut self, - pat: &Pat, - pat_binding_mode: BindingMode, - descr: &str) { + pat: &Pat, + pat_binding_mode: BindingMode, + descr: &str) { match pat_binding_mode { BindByValue(_) => {} BindByRef(..) => { @@ -3957,7 +3994,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { for (&name, import_resolution) in import_resolutions.iter() { let value_repr; match import_resolution.target_for_namespace(ValueNS) { - None => { value_repr = "".to_string(); } + None => { + value_repr = "".to_string(); + } Some(_) => { value_repr = " value:?".to_string(); // FIXME #4954 @@ -3966,7 +4005,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let type_repr; match import_resolution.target_for_namespace(TypeNS) { - None => { type_repr = "".to_string(); } + None => { + type_repr = "".to_string(); + } Some(_) => { type_repr = " type:?".to_string(); // FIXME #4954 @@ -3989,12 +4030,12 @@ fn names_to_string(names: &[Name]) -> String { result.push_str("::") } result.push_str(&name.as_str()); - }; + } result } fn path_names_to_string(path: &Path, depth: usize) -> String { - let names: Vec = path.segments[..path.segments.len()-depth] + let names: Vec = path.segments[..path.segments.len() - depth] .iter() .map(|seg| seg.identifier.name) .collect(); @@ -4029,18 +4070,18 @@ fn module_to_string(module: &Module) -> String { pub struct CrateMap { - pub def_map: DefMap, - pub freevars: RefCell, + pub def_map: RefCell, + pub freevars: FreevarMap, pub export_map: ExportMap, pub trait_map: TraitMap, pub external_exports: ExternalExports, - pub glob_map: Option + pub glob_map: Option, } #[derive(PartialEq,Copy, Clone)] pub enum MakeGlobMap { Yes, - No + No, } /// Entry point to crate resolution. @@ -4063,10 +4104,10 @@ pub fn resolve_crate<'a, 'tcx>(session: &'a Session, trait_map: resolver.trait_map, external_exports: resolver.external_exports, glob_map: if resolver.make_glob_map { - Some(resolver.glob_map) - } else { - None - }, + Some(resolver.glob_map) + } else { + None + }, } } diff --git a/src/librustc_resolve/record_exports.rs b/src/librustc_resolve/record_exports.rs index 0eb1e2cc06f61..96fad16536cb8 100644 --- a/src/librustc_resolve/record_exports.rs +++ b/src/librustc_resolve/record_exports.rs @@ -30,8 +30,8 @@ use syntax::ast; use std::ops::{Deref, DerefMut}; use std::rc::Rc; -struct ExportRecorder<'a, 'b:'a, 'tcx:'b> { - resolver: &'a mut Resolver<'b, 'tcx> +struct ExportRecorder<'a, 'b: 'a, 'tcx: 'b> { + resolver: &'a mut Resolver<'b, 'tcx>, } // Deref and DerefMut impls allow treating ExportRecorder as Resolver. @@ -50,28 +50,26 @@ impl<'a, 'b, 'tcx:'b> DerefMut for ExportRecorder<'a, 'b, 'tcx> { } impl<'a, 'b, 'tcx> ExportRecorder<'a, 'b, 'tcx> { - fn record_exports_for_module_subtree(&mut self, - module_: Rc) { + fn record_exports_for_module_subtree(&mut self, module_: Rc) { // If this isn't a local krate, then bail out. We don't need to record // exports for nonlocal crates. match module_.def_id.get() { Some(def_id) if def_id.is_local() => { // OK. Continue. - debug!("(recording exports for module subtree) recording \ - exports for local module `{}`", + debug!("(recording exports for module subtree) recording exports for local \ + module `{}`", module_to_string(&*module_)); } None => { // Record exports for the root module. - debug!("(recording exports for module subtree) recording \ - exports for root module `{}`", + debug!("(recording exports for module subtree) recording exports for root module \ + `{}`", module_to_string(&*module_)); } Some(_) => { // Bail out. - debug!("(recording exports for module subtree) not recording \ - exports for `{}`", + debug!("(recording exports for module subtree) not recording exports for `{}`", module_to_string(&*module_)); return; } @@ -118,10 +116,11 @@ impl<'a, 'b, 'tcx> ExportRecorder<'a, 'b, 'tcx> { match namebindings.def_for_namespace(ns) { Some(d) => { debug!("(computing exports) YES: export '{}' => {:?}", - name, d.def_id()); + name, + d.def_id()); exports.push(Export { name: name, - def_id: d.def_id() + def_id: d.def_id(), }); } d_opt => { @@ -130,25 +129,19 @@ impl<'a, 'b, 'tcx> ExportRecorder<'a, 'b, 'tcx> { } } - fn add_exports_for_module(&mut self, - exports: &mut Vec, - module_: &Module) { + fn add_exports_for_module(&mut self, exports: &mut Vec, module_: &Module) { for (name, import_resolution) in module_.import_resolutions.borrow().iter() { if !import_resolution.is_public { - continue + continue; } let xs = [TypeNS, ValueNS]; for &ns in &xs { match import_resolution.target_for_namespace(ns) { Some(target) => { - debug!("(computing exports) maybe export '{}'", - name); - self.add_exports_of_namebindings(exports, - *name, - &*target.bindings, - ns) + debug!("(computing exports) maybe export '{}'", name); + self.add_exports_of_namebindings(exports, *name, &*target.bindings, ns) } - _ => () + _ => (), } } } diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 99d7685f7c8f2..9a21ec86685c1 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -42,14 +42,14 @@ use std::rc::Rc; #[derive(Copy, Clone,Debug)] pub enum ImportDirectiveSubclass { SingleImport(Name /* target */, Name /* source */), - GlobImport + GlobImport, } /// Whether an import can be shadowed by another import. #[derive(Debug,PartialEq,Clone,Copy)] pub enum Shadowable { Always, - Never + Never, } /// One import directive. @@ -64,13 +64,13 @@ pub struct ImportDirective { } impl ImportDirective { - pub fn new(module_path: Vec , - subclass: ImportDirectiveSubclass, - span: Span, - id: NodeId, - is_public: bool, - shadowable: Shadowable) - -> ImportDirective { + pub fn new(module_path: Vec, + subclass: ImportDirectiveSubclass, + span: Span, + id: NodeId, + is_public: bool, + shadowable: Shadowable) + -> ImportDirective { ImportDirective { module_path: module_path, subclass: subclass, @@ -92,9 +92,9 @@ pub struct Target { impl Target { pub fn new(target_module: Rc, - bindings: Rc, - shadowable: Shadowable) - -> Target { + bindings: Rc, + shadowable: Shadowable) + -> Target { Target { target_module: target_module, bindings: bindings, @@ -144,17 +144,16 @@ impl ImportResolution { } } - pub fn target_for_namespace(&self, namespace: Namespace) - -> Option { + pub fn target_for_namespace(&self, namespace: Namespace) -> Option { match namespace { - TypeNS => self.type_target.clone(), + TypeNS => self.type_target.clone(), ValueNS => self.value_target.clone(), } } pub fn id(&self, namespace: Namespace) -> NodeId { match namespace { - TypeNS => self.type_id, + TypeNS => self.type_id, ValueNS => self.value_id, } } @@ -168,12 +167,9 @@ impl ImportResolution { target.unwrap().shadowable } - pub fn set_target_and_id(&mut self, - namespace: Namespace, - target: Option, - id: NodeId) { + pub fn set_target_and_id(&mut self, namespace: Namespace, target: Option, id: NodeId) { match namespace { - TypeNS => { + TypeNS => { self.type_target = target; self.type_id = id; } @@ -191,8 +187,8 @@ struct ImportResolvingError { help: String, } -struct ImportResolver<'a, 'b:'a, 'tcx:'b> { - resolver: &'a mut Resolver<'b, 'tcx> +struct ImportResolver<'a, 'b: 'a, 'tcx: 'b> { + resolver: &'a mut Resolver<'b, 'tcx>, } impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { @@ -211,7 +207,8 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { let mut prev_unresolved_imports = 0; loop { debug!("(resolving imports) iteration {}, {} imports left", - i, self.resolver.unresolved_imports); + i, + self.resolver.unresolved_imports); let module_root = self.resolver.graph_root.get_module(); let errors = self.resolve_imports_for_module_subtree(module_root.clone()); @@ -246,7 +243,8 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { /// Attempts to resolve imports for the given module and all of its /// submodules. - fn resolve_imports_for_module_subtree(&mut self, module_: Rc) + fn resolve_imports_for_module_subtree(&mut self, + module_: Rc) -> Vec { let mut errors = Vec::new(); debug!("(resolving imports for module subtree) resolving {}", @@ -279,8 +277,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { let mut errors = Vec::new(); if module.all_imports_resolved() { - debug!("(resolving imports for module) all imports resolved for \ - {}", + debug!("(resolving imports for module) all imports resolved for {}", module_to_string(&*module)); return errors; } @@ -290,22 +287,19 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { let mut indeterminate_imports = Vec::new(); while module.resolved_import_count.get() + indeterminate_imports.len() < import_count { let import_index = module.resolved_import_count.get(); - match self.resolve_import_for_module(module.clone(), - &imports[import_index]) { + match self.resolve_import_for_module(module.clone(), &imports[import_index]) { ResolveResult::Failed(err) => { let import_directive = &imports[import_index]; let (span, help) = match err { Some((span, msg)) => (span, format!(". {}", msg)), - None => (import_directive.span, String::new()) + None => (import_directive.span, String::new()), }; errors.push(ImportResolvingError { - span: span, - path: import_path_to_string( - &import_directive.module_path, - import_directive.subclass - ), - help: help - }); + span: span, + path: import_path_to_string(&import_directive.module_path, + import_directive.subclass), + help: help, + }); } ResolveResult::Indeterminate => {} ResolveResult::Success(()) => { @@ -354,7 +348,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { ResolveResult::Failed(err) => { resolution_result = ResolveResult::Failed(err); None - }, + } ResolveResult::Indeterminate => { resolution_result = ResolveResult::Indeterminate; None @@ -371,20 +365,18 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { match import_directive.subclass { SingleImport(target, source) => { - resolution_result = - self.resolve_single_import(&module_, - containing_module, - target, - source, - import_directive, - lp); + resolution_result = self.resolve_single_import(&module_, + containing_module, + target, + source, + import_directive, + lp); } GlobImport => { - resolution_result = - self.resolve_glob_import(&module_, - containing_module, - import_directive, - lp); + resolution_result = self.resolve_glob_import(&module_, + containing_module, + import_directive, + lp); } } } @@ -433,8 +425,8 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { directive: &ImportDirective, lp: LastPrivate) -> ResolveResult<()> { - debug!("(resolving single import) resolving `{}` = `{}::{}` from \ - `{}` id {}, last private {:?}", + debug!("(resolving single import) resolving `{}` = `{}::{}` from `{}` id {}, last \ + private {:?}", target, module_to_string(&*target_module), source, @@ -445,9 +437,9 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { let lp = match lp { LastMod(lp) => lp, LastImport {..} => { - self.resolver.session - .span_bug(directive.span, - "not expecting Import here, must be LastMod") + self.resolver + .session + .span_bug(directive.span, "not expecting Import here, must be LastMod") } }; @@ -472,11 +464,10 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { value_result = BoundResult(target_module.clone(), (*child_name_bindings).clone()); if directive.is_public && !child_name_bindings.is_public(ValueNS) { - let msg = format!("`{}` is private, and cannot be reexported", - source); - let note_msg = - format!("Consider marking `{}` as `pub` in the imported module", - source); + let msg = format!("`{}` is private, and cannot be reexported", source); + let note_msg = format!("Consider marking `{}` as `pub` in the imported \ + module", + source); span_err!(self.resolver.session, directive.span, E0364, "{}", &msg); self.resolver.session.span_note(directive.span, ¬e_msg); pub_err = true; @@ -487,8 +478,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { type_result = BoundResult(target_module.clone(), (*child_name_bindings).clone()); if !pub_err && directive.is_public && !child_name_bindings.is_public(TypeNS) { - let msg = format!("`{}` is private, and cannot be reexported", - source); + let msg = format!("`{}` is private, and cannot be reexported", source); let note_msg = format!("Consider declaring module `{}` as a `pub mod`", source); span_err!(self.resolver.session, directive.span, E0365, "{}", &msg); @@ -510,8 +500,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { // able to resolve this import. if target_module.pub_glob_count.get() > 0 { - debug!("(resolving single import) unresolved pub glob; \ - bailing out"); + debug!("(resolving single import) unresolved pub glob; bailing out"); return ResolveResult::Indeterminate; } @@ -531,14 +520,13 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { type_result = UnboundResult; } } - Some(import_resolution) - if import_resolution.outstanding_references == 0 => { + Some(import_resolution) if import_resolution.outstanding_references == 0 => { fn get_binding(this: &mut Resolver, import_resolution: &ImportResolution, namespace: Namespace, source: Name) - -> NamespaceResult { + -> NamespaceResult { // Import resolutions must be declared with "pub" // in order to be exported. @@ -555,8 +543,8 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { bindings, shadowable: _ }) => { - debug!("(resolving single import) found \ - import in ns {:?}", namespace); + debug!("(resolving single import) found import in ns {:?}", + namespace); let id = import_resolution.id(namespace); // track used imports and extern crates as well this.used_imports.insert((id, namespace)); @@ -564,7 +552,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { match target_module.def_id.get() { Some(DefId{krate: kid, ..}) => { this.used_crates.insert(kid); - }, + } _ => {} } return BoundResult(target_module, bindings); @@ -603,8 +591,8 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { // In this case we continue as if we resolved the import and let the // check_for_conflicts_between_imports_and_items call below handle // the conflict - match (module_.def_id.get(), target_module.def_id.get()) { - (Some(id1), Some(id2)) if id1 == id2 => { + match (module_.def_id.get(), target_module.def_id.get()) { + (Some(id1), Some(id2)) if id1 == id2 => { if value_result.is_unknown() { value_result = UnboundResult; } @@ -612,10 +600,9 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { type_result = UnboundResult; } } - _ => { + _ => { // The import is unresolved. Bail out. - debug!("(resolving single import) unresolved import; \ - bailing out"); + debug!("(resolving single import) unresolved import; bailing out"); return ResolveResult::Indeterminate; } } @@ -668,17 +655,15 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { debug!("(resolving single import) found {:?} target: {:?}", namespace_name, name_bindings.def_for_namespace(namespace)); - self.check_for_conflicting_import( - &import_resolution, - directive.span, - target, - namespace); - - self.check_that_import_is_importable( - &**name_bindings, - directive.span, - target, - namespace); + self.check_for_conflicting_import(&import_resolution, + directive.span, + target, + namespace); + + self.check_that_import_is_importable(&**name_bindings, + directive.span, + target, + namespace); let target = Some(Target::new(target_module.clone(), name_bindings.clone(), @@ -687,7 +672,9 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { import_resolution.is_public = directive.is_public; *used_public = name_bindings.defined_in_public_namespace(namespace); } - UnboundResult => { /* Continue. */ } + UnboundResult => { + // Continue. + } UnknownResult => { panic!("{:?} result should be known at this point", namespace_name); } @@ -697,11 +684,10 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { check_and_write_import(TypeNS, &type_result, &mut type_used_public); } - self.check_for_conflicts_between_imports_and_items( - module_, - import_resolution, - directive.span, - target); + self.check_for_conflicts_between_imports_and_items(module_, + import_resolution, + directive.span, + target); if value_result.is_unbound() && type_result.is_unbound() { let msg = format!("There is no `{}` in `{}`", @@ -720,33 +706,45 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { // purposes it's good enough to just favor one over the other. let value_def_and_priv = import_resolution.value_target.as_ref().map(|target| { let def = target.bindings.def_for_namespace(ValueNS).unwrap(); - (def, if value_used_public { lp } else { DependsOn(def.def_id()) }) + (def, + if value_used_public { + lp + } else { + DependsOn(def.def_id()) + }) }); let type_def_and_priv = import_resolution.type_target.as_ref().map(|target| { let def = target.bindings.def_for_namespace(TypeNS).unwrap(); - (def, if type_used_public { lp } else { DependsOn(def.def_id()) }) + (def, + if type_used_public { + lp + } else { + DependsOn(def.def_id()) + }) }); let import_lp = LastImport { value_priv: value_def_and_priv.map(|(_, p)| p), value_used: Used, type_priv: type_def_and_priv.map(|(_, p)| p), - type_used: Used + type_used: Used, }; if let Some((def, _)) = value_def_and_priv { - self.resolver.def_map.borrow_mut().insert(directive.id, PathResolution { - base_def: def, - last_private: import_lp, - depth: 0 - }); + self.resolver.def_map.borrow_mut().insert(directive.id, + PathResolution { + base_def: def, + last_private: import_lp, + depth: 0, + }); } if let Some((def, _)) = type_def_and_priv { - self.resolver.def_map.borrow_mut().insert(directive.id, PathResolution { - base_def: def, - last_private: import_lp, - depth: 0 - }); + self.resolver.def_map.borrow_mut().insert(directive.id, + PathResolution { + base_def: def, + last_private: import_lp, + depth: 0, + }); } debug!("(resolving single import) successfully resolved import"); @@ -774,8 +772,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { // We must bail out if the node has unresolved imports of any kind // (including globs). if (*target_module).pub_count.get() > 0 { - debug!("(resolving glob import) target module has unresolved \ - pub imports; bailing out"); + debug!("(resolving glob import) target module has unresolved pub imports; bailing out"); return ResolveResult::Indeterminate; } @@ -787,21 +784,18 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { // This means we are trying to glob import a module into itself, // and it is a no-go debug!("(resolving glob imports) target module is current module; giving up"); - return ResolveResult::Failed(Some(( - import_directive.span, - "Cannot glob-import a module into itself.".into() - ))); + return ResolveResult::Failed(Some((import_directive.span, + "Cannot glob-import a module into itself.".into()))); } for (name, target_import_resolution) in import_resolutions.iter() { - debug!("(resolving glob import) writing module resolution \ - {} into `{}`", + debug!("(resolving glob import) writing module resolution {} into `{}`", *name, module_to_string(module_)); if !target_import_resolution.is_public { debug!("(resolving glob import) nevermind, just kidding"); - continue + continue; } // Here we merge two import resolutions. @@ -843,10 +837,8 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { // Simple: just copy the old import resolution. let mut new_import_resolution = ImportResolution::new(id, is_public); - new_import_resolution.value_target = - target_import_resolution.value_target.clone(); - new_import_resolution.type_target = - target_import_resolution.type_target.clone(); + new_import_resolution.value_target = target_import_resolution.value_target.clone(); + new_import_resolution.type_target = target_import_resolution.type_target.clone(); import_resolutions.insert(*name, new_import_resolution); } @@ -865,8 +857,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { // Add external module children from the containing module. for (&name, module) in target_module.external_module_children.borrow().iter() { - let name_bindings = - Rc::new(Resolver::create_name_bindings_from_module(module.clone())); + let name_bindings = Rc::new(Resolver::create_name_bindings_from_module(module.clone())); self.merge_import_resolution(module_, target_module.clone(), import_directive, @@ -876,11 +867,12 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { // Record the destination of this import if let Some(did) = target_module.def_id.get() { - self.resolver.def_map.borrow_mut().insert(id, PathResolution { - base_def: DefMod(did), - last_private: lp, - depth: 0 - }); + self.resolver.def_map.borrow_mut().insert(id, + PathResolution { + base_def: DefMod(did), + last_private: lp, + depth: 0, + }); } debug!("(resolving glob import) successfully resolved import"); @@ -898,10 +890,11 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { let mut import_resolutions = module_.import_resolutions.borrow_mut(); let dest_import_resolution = import_resolutions.entry(name) - .or_insert_with(|| ImportResolution::new(id, is_public)); + .or_insert_with(|| { + ImportResolution::new(id, is_public) + }); - debug!("(resolving glob import) writing resolution `{}` in `{}` \ - to `{}`", + debug!("(resolving glob import) writing resolution `{}` in `{}` to `{}`", name, module_to_string(&*containing_module), module_to_string(module_)); @@ -918,18 +911,20 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { }; debug!("(resolving glob import) ... for {} target", namespace_name); if dest_import_resolution.shadowable(namespace) == Shadowable::Never { - let msg = format!("a {} named `{}` has already been imported \ - in this module", + let msg = format!("a {} named `{}` has already been imported in this \ + module", namespace_name, name); - span_err!(self.resolver.session, import_directive.span, E0251, "{}", msg); + span_err!(self.resolver.session, + import_directive.span, + E0251, + "{}", + msg); } else { let target = Target::new(containing_module.clone(), name_bindings.clone(), import_directive.shadowable); - dest_import_resolution.set_target_and_id(namespace, - Some(target), - id); + dest_import_resolution.set_target_and_id(namespace, Some(target), id); } } }; @@ -939,11 +934,10 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { dest_import_resolution.is_public = is_public; - self.check_for_conflicts_between_imports_and_items( - module_, - dest_import_resolution, - import_directive.span, - name); + self.check_for_conflicts_between_imports_and_items(module_, + dest_import_resolution, + import_directive.span, + name); } /// Checks that imported names and items don't have the same name. @@ -963,28 +957,31 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { TypeNS => { if let Some(ref ty_def) = *target.bindings.type_def.borrow() { match ty_def.module_def { - Some(ref module) - if module.kind.get() == ModuleKind::NormalModuleKind => - "module", - Some(ref module) - if module.kind.get() == ModuleKind::TraitModuleKind => - "trait", + Some(ref module) if module.kind.get() == + ModuleKind::NormalModuleKind => "module", + Some(ref module) if module.kind.get() == + ModuleKind::TraitModuleKind => "trait", _ => "type", } - } else { "type" } - }, + } else { + "type" + } + } ValueNS => "value", }; - span_err!(self.resolver.session, import_span, E0252, - "a {} named `{}` has already been imported \ - in this module", ns_word, - name); + span_err!(self.resolver.session, + import_span, + E0252, + "a {} named `{}` has already been imported in this module", + ns_word, + name); let use_id = import_resolution.id(namespace); let item = self.resolver.ast_map.expect_item(use_id); // item is syntax::ast::Item; - span_note!(self.resolver.session, item.span, - "previous import of `{}` here", - name); + span_note!(self.resolver.session, + item.span, + "previous import of `{}` here", + name); } Some(_) | None => {} } @@ -997,8 +994,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { name: Name, namespace: Namespace) { if !name_bindings.defined_in_namespace_with(namespace, DefModifiers::IMPORTABLE) { - let msg = format!("`{}` is not directly importable", - name); + let msg = format!("`{}` is not directly importable", name); span_err!(self.resolver.session, import_span, E0253, "{}", &msg[..]); } } @@ -1006,8 +1002,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { /// Checks that imported names and items don't have the same name. fn check_for_conflicts_between_imports_and_items(&mut self, module: &Module, - import_resolution: - &ImportResolution, + import_resolution: &ImportResolution, import_span: Span, name: Name) { // First, check for conflicts between imports and `extern crate`s. @@ -1016,8 +1011,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { .contains_key(&name) { match import_resolution.type_target { Some(ref target) if target.shadowable != Shadowable::Always => { - let msg = format!("import `{0}` conflicts with imported \ - crate in this module \ + let msg = format!("import `{0}` conflicts with imported crate in this module \ (maybe you meant `use {0}::*`?)", name); span_err!(self.resolver.session, import_span, E0254, "{}", &msg[..]); @@ -1031,7 +1025,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { let name_bindings = match children.get(&name) { None => { // There can't be any conflicts. - return + return; } Some(ref name_bindings) => (*name_bindings).clone(), }; @@ -1039,7 +1033,9 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { match import_resolution.value_target { Some(ref target) if target.shadowable != Shadowable::Always => { if let Some(ref value) = *name_bindings.value_def.borrow() { - span_err!(self.resolver.session, import_span, E0255, + span_err!(self.resolver.session, + import_span, + E0255, "import `{}` conflicts with value in this module", name); if let Some(span) = value.value_span { @@ -1054,17 +1050,18 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { Some(ref target) if target.shadowable != Shadowable::Always => { if let Some(ref ty) = *name_bindings.type_def.borrow() { let (what, note) = match ty.module_def { - Some(ref module) - if module.kind.get() == ModuleKind::NormalModuleKind => - ("existing submodule", "note conflicting module here"), - Some(ref module) - if module.kind.get() == ModuleKind::TraitModuleKind => - ("trait in this module", "note conflicting trait here"), - _ => ("type in this module", "note conflicting type here"), + Some(ref module) if module.kind.get() == ModuleKind::NormalModuleKind => + ("existing submodule", "note conflicting module here"), + Some(ref module) if module.kind.get() == ModuleKind::TraitModuleKind => + ("trait in this module", "note conflicting trait here"), + _ => ("type in this module", "note conflicting type here"), }; - span_err!(self.resolver.session, import_span, E0256, + span_err!(self.resolver.session, + import_span, + E0256, "import `{}` conflicts with {}", - name, what); + name, + what); if let Some(span) = ty.type_span { self.resolver.session.span_note(span, note); } @@ -1075,28 +1072,25 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { } } -fn import_path_to_string(names: &[Name], - subclass: ImportDirectiveSubclass) - -> String { +fn import_path_to_string(names: &[Name], subclass: ImportDirectiveSubclass) -> String { if names.is_empty() { import_directive_subclass_to_string(subclass) } else { (format!("{}::{}", names_to_string(names), - import_directive_subclass_to_string(subclass))).to_string() + import_directive_subclass_to_string(subclass))) + .to_string() } } fn import_directive_subclass_to_string(subclass: ImportDirectiveSubclass) -> String { match subclass { SingleImport(_, source) => source.to_string(), - GlobImport => "*".to_string() + GlobImport => "*".to_string(), } } pub fn resolve_imports(resolver: &mut Resolver) { - let mut import_resolver = ImportResolver { - resolver: resolver, - }; + let mut import_resolver = ImportResolver { resolver: resolver }; import_resolver.resolve_imports(); } diff --git a/src/librustc_trans/back/msvc/registry.rs b/src/librustc_trans/back/msvc/registry.rs index d178565e18f59..63fb19c9772a8 100644 --- a/src/librustc_trans/back/msvc/registry.rs +++ b/src/librustc_trans/back/msvc/registry.rs @@ -13,8 +13,14 @@ use std::ffi::{OsString, OsStr}; use std::os::windows::prelude::*; use std::ops::RangeFrom; use std::ptr; -use libc::{DWORD, LPCWSTR, LONG, LPDWORD, LPBYTE, ERROR_SUCCESS}; -use libc::c_void; +use libc::{c_void, c_long}; + +type DWORD = u32; +type LPCWSTR = *const u16; +type LONG = c_long; +type LPDWORD = *mut DWORD; +type LPBYTE = *mut u8; + const HKEY_LOCAL_MACHINE: HKEY = 0x80000002 as HKEY; const KEY_WOW64_32KEY: REGSAM = 0x0200; @@ -27,6 +33,7 @@ const KEY_ENUMERATE_SUB_KEYS: REGSAM = 0x0008; const KEY_NOTIFY: REGSAM = 0x0010; const SYNCHRONIZE: REGSAM = 0x00100000; const REG_SZ: DWORD = 1; +const ERROR_SUCCESS: i32 = 0; const ERROR_NO_MORE_ITEMS: DWORD = 259; enum __HKEY__ {} diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs index e02ce49132a7c..84ce458ed14f7 100644 --- a/src/librustc_trans/lib.rs +++ b/src/librustc_trans/lib.rs @@ -37,6 +37,7 @@ #![feature(quote)] #![feature(rustc_diagnostic_macros)] #![feature(rustc_private)] +#![feature(slice_patterns)] #![feature(staged_api)] #![feature(unicode)] #![feature(vec_push_all)] @@ -50,8 +51,10 @@ extern crate graphviz; extern crate libc; extern crate rustc; extern crate rustc_back; +extern crate rustc_data_structures; extern crate rustc_front; extern crate rustc_llvm as llvm; +extern crate rustc_mir; extern crate rustc_platform_intrinsics as intrinsics; extern crate serialize; diff --git a/src/librustc_trans/save/dump_csv.rs b/src/librustc_trans/save/dump_csv.rs index f6f504e27aefc..3ea631bd7fb67 100644 --- a/src/librustc_trans/save/dump_csv.rs +++ b/src/librustc_trans/save/dump_csv.rs @@ -107,8 +107,17 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> { } pub fn dump_crate_info(&mut self, name: &str, krate: &ast::Crate) { + let source_file = self.tcx.sess.local_crate_source_file.as_ref(); + let crate_root = match source_file { + Some(source_file) => match source_file.file_name() { + Some(_) => source_file.parent().unwrap().display().to_string(), + None => source_file.display().to_string(), + }, + None => "".to_owned(), + }; + // The current crate. - self.fmt.crate_str(krate.span, name); + self.fmt.crate_str(krate.span, name, &crate_root); // Dump info about all the external crates referenced from this crate. for c in &self.save_ctxt.get_external_crates() { diff --git a/src/librustc_trans/save/recorder.rs b/src/librustc_trans/save/recorder.rs index a32d8b1b761c5..34eb1d282636e 100644 --- a/src/librustc_trans/save/recorder.rs +++ b/src/librustc_trans/save/recorder.rs @@ -198,7 +198,7 @@ impl<'a, 'tcx: 'a> FmtStrs<'a, 'tcx> { vec!("name", "crate", "file_name"), false, false), - Crate => ("crate", vec!("name"), true, false), + Crate => ("crate", vec!("name", "crate_root"), true, false), FnCall => ("fn_call", vec!("refid", "refidcrate", "qualname", "scopeid"), true, @@ -658,8 +658,8 @@ impl<'a, 'tcx: 'a> FmtStrs<'a, 'tcx> { self.check_and_record(Typedef, span, sub_span, svec!(id, qualname, value)); } - pub fn crate_str(&mut self, span: Span, name: &str) { - self.record_with_span(Crate, span, span, svec!(name)); + pub fn crate_str(&mut self, span: Span, name: &str, crate_root: &str) { + self.record_with_span(Crate, span, span, svec!(name, crate_root)); } pub fn external_crate_str(&mut self, span: Span, name: &str, num: ast::CrateNum) { diff --git a/src/librustc_trans/trans/_match.rs b/src/librustc_trans/trans/_match.rs index 2654ab3339a10..b2e989bc874a3 100644 --- a/src/librustc_trans/trans/_match.rs +++ b/src/librustc_trans/trans/_match.rs @@ -222,11 +222,13 @@ use util::nodemap::FnvHashMap; use util::ppaux; use std; +use std::cell::RefCell; use std::cmp::Ordering; use std::fmt; use std::rc::Rc; use rustc_front::hir; use syntax::ast::{self, DUMMY_NODE_ID, NodeId}; +use syntax::ext::mtwt; use syntax::codemap::Span; use rustc_front::fold::Folder; use syntax::ptr::P; @@ -303,7 +305,7 @@ impl<'a, 'tcx> Opt<'a, 'tcx> { RangeResult(Result::new(bcx, l1), Result::new(bcx, l2)) } Variant(disr_val, ref repr, _, _) => { - adt::trans_case(bcx, &**repr, disr_val) + SingleResult(Result::new(bcx, adt::trans_case(bcx, &**repr, disr_val))) } SliceLengthEqual(length, _) => { SingleResult(Result::new(bcx, C_uint(ccx, length))) @@ -476,7 +478,7 @@ fn expand_nested_bindings<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>, loop { pat = match pat.node { hir::PatIdent(_, ref path, Some(ref inner)) => { - bound_ptrs.push((path.node.name, val.val)); + bound_ptrs.push((mtwt::resolve(path.node), val.val)); &**inner }, _ => break @@ -495,7 +497,7 @@ fn expand_nested_bindings<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>, } fn enter_match<'a, 'b, 'p, 'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>, - dm: &DefMap, + dm: &RefCell, m: &[Match<'a, 'p, 'blk, 'tcx>], col: usize, val: MatchInput, @@ -516,8 +518,8 @@ fn enter_match<'a, 'b, 'p, 'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>, let mut bound_ptrs = br.bound_ptrs.clone(); match this.node { hir::PatIdent(_, ref path, None) => { - if pat_is_binding(dm, &*this) { - bound_ptrs.push((path.node.name, val.val)); + if pat_is_binding(&dm.borrow(), &*this) { + bound_ptrs.push((mtwt::resolve(path.node), val.val)); } } hir::PatVec(ref before, Some(ref slice), ref after) => { @@ -525,7 +527,7 @@ fn enter_match<'a, 'b, 'p, 'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>, let subslice_val = bind_subslice_pat( bcx, this.id, val, before.len(), after.len()); - bound_ptrs.push((path.node.name, subslice_val)); + bound_ptrs.push((mtwt::resolve(path.node), subslice_val)); } } _ => {} @@ -541,7 +543,7 @@ fn enter_match<'a, 'b, 'p, 'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>, } fn enter_default<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>, - dm: &DefMap, + dm: &RefCell, m: &[Match<'a, 'p, 'blk, 'tcx>], col: usize, val: MatchInput) @@ -555,7 +557,7 @@ fn enter_default<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>, // Collect all of the matches that can match against anything. enter_match(bcx, dm, m, col, val, |pats| { - if pat_is_binding_or_wild(dm, &*pats[col]) { + if pat_is_binding_or_wild(&dm.borrow(), &*pats[col]) { let mut r = pats[..col].to_vec(); r.push_all(&pats[col + 1..]); Some(r) @@ -596,7 +598,7 @@ fn enter_default<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>, fn enter_opt<'a, 'p, 'blk, 'tcx>( bcx: Block<'blk, 'tcx>, _: ast::NodeId, - dm: &DefMap, + dm: &RefCell, m: &[Match<'a, 'p, 'blk, 'tcx>], opt: &Opt, col: usize, @@ -842,11 +844,11 @@ impl FailureHandler { } } -fn pick_column_to_specialize(def_map: &DefMap, m: &[Match]) -> Option { - fn pat_score(def_map: &DefMap, pat: &hir::Pat) -> usize { +fn pick_column_to_specialize(def_map: &RefCell, m: &[Match]) -> Option { + fn pat_score(def_map: &RefCell, pat: &hir::Pat) -> usize { match pat.node { hir::PatIdent(_, _, Some(ref inner)) => pat_score(def_map, &**inner), - _ if pat_is_refutable(def_map, pat) => 1, + _ if pat_is_refutable(&def_map.borrow(), pat) => 1, _ => 0 } } @@ -1126,8 +1128,8 @@ fn compile_submatch<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>, } None => { let data = &m[0].data; - for &(ref ident, ref value_ptr) in &m[0].bound_ptrs { - let binfo = *data.bindings_map.get(ident).unwrap(); + for &(ref name, ref value_ptr) in &m[0].bound_ptrs { + let binfo = *data.bindings_map.get(name).unwrap(); call_lifetime_start(bcx, binfo.llmatch); if binfo.trmode == TrByRef && type_is_fat_ptr(bcx.tcx(), binfo.ty) { expr::copy_fat_ptr(bcx, *value_ptr, binfo.llmatch); @@ -1525,8 +1527,8 @@ fn create_bindings_map<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, pat: &hir::Pat, let tcx = bcx.tcx(); let reassigned = is_discr_reassigned(bcx, discr, body); let mut bindings_map = FnvHashMap(); - pat_bindings(&tcx.def_map, &*pat, |bm, p_id, span, path1| { - let name = path1.node; + pat_bindings_hygienic(&tcx.def_map, &*pat, |bm, p_id, span, path1| { + let name = mtwt::resolve(path1.node); let variable_ty = node_id_type(bcx, p_id); let llvariable_ty = type_of::type_of(ccx, variable_ty); let tcx = bcx.tcx(); @@ -1800,7 +1802,7 @@ pub fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let ccx = bcx.ccx(); match pat.node { hir::PatIdent(pat_binding_mode, ref path1, ref inner) => { - if pat_is_binding(&tcx.def_map, &*pat) { + if pat_is_binding(&tcx.def_map.borrow(), &*pat) { // Allocate the stack slot where the value of this // binding will live and place it into the appropriate // map. diff --git a/src/librustc_trans/trans/adt.rs b/src/librustc_trans/trans/adt.rs index de09e33ec1427..a4f66110450df 100644 --- a/src/librustc_trans/trans/adt.rs +++ b/src/librustc_trans/trans/adt.rs @@ -945,15 +945,13 @@ fn load_discr(bcx: Block, ity: IntType, ptr: ValueRef, min: Disr, max: Disr) /// /// This should ideally be less tightly tied to `_match`. pub fn trans_case<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, r: &Repr, discr: Disr) - -> _match::OptResult<'blk, 'tcx> { + -> ValueRef { match *r { CEnum(ity, _, _) => { - _match::SingleResult(Result::new(bcx, C_integral(ll_inttype(bcx.ccx(), ity), - discr as u64, true))) + C_integral(ll_inttype(bcx.ccx(), ity), discr as u64, true) } General(ity, _, _) => { - _match::SingleResult(Result::new(bcx, C_integral(ll_inttype(bcx.ccx(), ity), - discr as u64, true))) + C_integral(ll_inttype(bcx.ccx(), ity), discr as u64, true) } Univariant(..) => { bcx.ccx().sess().bug("no cases for univariants or structs") @@ -961,7 +959,7 @@ pub fn trans_case<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, r: &Repr, discr: Disr) RawNullablePointer { .. } | StructWrappedNullablePointer { .. } => { assert!(discr == 0 || discr == 1); - _match::SingleResult(Result::new(bcx, C_bool(bcx.ccx(), discr != 0))) + C_bool(bcx.ccx(), discr != 0) } } } diff --git a/src/librustc_trans/trans/attributes.rs b/src/librustc_trans/trans/attributes.rs index af4c2205e659b..90a649405cddd 100644 --- a/src/librustc_trans/trans/attributes.rs +++ b/src/librustc_trans/trans/attributes.rs @@ -142,6 +142,7 @@ pub fn from_fn_type<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn_type: ty::Ty<'tcx }; let fn_sig = ccx.tcx().erase_late_bound_regions(fn_sig); + let fn_sig = infer::normalize_associated_type(ccx.tcx(), &fn_sig); let mut attrs = llvm::AttrBuilder::new(); let ret_ty = fn_sig.output; diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs index 46a4cb0c92ee7..ecd4c75c9d35d 100644 --- a/src/librustc_trans/trans/base.rs +++ b/src/librustc_trans/trans/base.rs @@ -38,12 +38,14 @@ use metadata::{csearch, encoder, loader}; use middle::astencode; use middle::cfg; use middle::def_id::DefId; +use middle::infer; use middle::lang_items::{LangItem, ExchangeMallocFnLangItem, StartFnLangItem}; use middle::weak_lang_items; use middle::pat_util::simple_name; use middle::subst::Substs; use middle::ty::{self, Ty, HasTypeFlags}; use rustc::front::map as hir_map; +use rustc_mir::mir_map::MirMap; use session::config::{self, NoDebugInfo, FullDebugInfo}; use session::Session; use trans::_match; @@ -54,7 +56,7 @@ use trans::builder::{Builder, noname}; use trans::callee; use trans::cleanup::{self, CleanupMethods, DropHint}; use trans::closure; -use trans::common::{Block, C_bool, C_bytes_in_context, C_i32, C_int, C_integral}; +use trans::common::{Block, C_bool, C_bytes_in_context, C_i32, C_int, C_uint, C_integral}; use trans::common::{C_null, C_struct_in_context, C_u64, C_u8, C_undef}; use trans::common::{CrateContext, DropFlagHintsMap, Field, FunctionContext}; use trans::common::{Result, NodeIdAndSpan, VariantInfo}; @@ -74,6 +76,7 @@ use trans::intrinsic; use trans::machine; use trans::machine::{llsize_of, llsize_of_real}; use trans::meth; +use trans::mir; use trans::monomorphize; use trans::tvec; use trans::type_::Type; @@ -310,6 +313,49 @@ pub fn bin_op_to_fcmp_predicate(ccx: &CrateContext, op: hir::BinOp_) } } +pub fn compare_fat_ptrs<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, + lhs_addr: ValueRef, + lhs_extra: ValueRef, + rhs_addr: ValueRef, + rhs_extra: ValueRef, + _t: Ty<'tcx>, + op: hir::BinOp_, + debug_loc: DebugLoc) + -> ValueRef { + match op { + hir::BiEq => { + let addr_eq = ICmp(bcx, llvm::IntEQ, lhs_addr, rhs_addr, debug_loc); + let extra_eq = ICmp(bcx, llvm::IntEQ, lhs_extra, rhs_extra, debug_loc); + And(bcx, addr_eq, extra_eq, debug_loc) + } + hir::BiNe => { + let addr_eq = ICmp(bcx, llvm::IntNE, lhs_addr, rhs_addr, debug_loc); + let extra_eq = ICmp(bcx, llvm::IntNE, lhs_extra, rhs_extra, debug_loc); + Or(bcx, addr_eq, extra_eq, debug_loc) + } + hir::BiLe | hir::BiLt | hir::BiGe | hir::BiGt => { + // a OP b ~ a.0 STRICT(OP) b.0 | (a.0 == b.0 && a.1 OP a.1) + let (op, strict_op) = match op { + hir::BiLt => (llvm::IntULT, llvm::IntULT), + hir::BiLe => (llvm::IntULE, llvm::IntULT), + hir::BiGt => (llvm::IntUGT, llvm::IntUGT), + hir::BiGe => (llvm::IntUGE, llvm::IntUGT), + _ => unreachable!() + }; + + let addr_eq = ICmp(bcx, llvm::IntEQ, lhs_addr, rhs_addr, debug_loc); + let extra_op = ICmp(bcx, op, lhs_extra, rhs_extra, debug_loc); + let addr_eq_extra_op = And(bcx, addr_eq, extra_op, debug_loc); + + let addr_strict = ICmp(bcx, strict_op, lhs_addr, rhs_addr, debug_loc); + Or(bcx, addr_strict, addr_eq_extra_op, debug_loc) + } + _ => { + bcx.tcx().sess.bug("unexpected fat ptr binop"); + } + } +} + pub fn compare_scalar_types<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, lhs: ValueRef, rhs: ValueRef, @@ -334,6 +380,17 @@ pub fn compare_scalar_types<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, ty::TyRawPtr(mt) if common::type_is_sized(bcx.tcx(), mt.ty) => { ICmp(bcx, bin_op_to_icmp_predicate(bcx.ccx(), op, false), lhs, rhs, debug_loc) } + ty::TyRawPtr(_) => { + let lhs_addr = Load(bcx, GEPi(bcx, lhs, &[0, abi::FAT_PTR_ADDR])); + let lhs_extra = Load(bcx, GEPi(bcx, lhs, &[0, abi::FAT_PTR_EXTRA])); + + let rhs_addr = Load(bcx, GEPi(bcx, rhs, &[0, abi::FAT_PTR_ADDR])); + let rhs_extra = Load(bcx, GEPi(bcx, rhs, &[0, abi::FAT_PTR_EXTRA])); + compare_fat_ptrs(bcx, + lhs_addr, lhs_extra, + rhs_addr, rhs_extra, + t, op, debug_loc) + } ty::TyInt(_) => { ICmp(bcx, bin_op_to_icmp_predicate(bcx.ccx(), op, true), lhs, rhs, debug_loc) } @@ -497,13 +554,8 @@ pub fn iter_structural_ty<'blk, 'tcx, F>(cx: Block<'blk, 'tcx>, &format!("enum-iter-variant-{}", &variant.disr_val.to_string()) ); - match adt::trans_case(cx, &*repr, variant.disr_val) { - _match::SingleResult(r) => { - AddCase(llswitch, r.val, variant_cx.llbb) - } - _ => ccx.sess().unimpl("value from adt::trans_case \ - in iter_structural_ty") - } + let case_val = adt::trans_case(cx, &*repr, variant.disr_val); + AddCase(llswitch, case_val, variant_cx.llbb); let variant_cx = iter_variant(variant_cx, &*repr, @@ -526,6 +578,129 @@ pub fn iter_structural_ty<'blk, 'tcx, F>(cx: Block<'blk, 'tcx>, return cx; } + +/// Retrieve the information we are losing (making dynamic) in an unsizing +/// adjustment. +/// +/// The `old_info` argument is a bit funny. It is intended for use +/// in an upcast, where the new vtable for an object will be drived +/// from the old one. +pub fn unsized_info<'ccx, 'tcx>(ccx: &CrateContext<'ccx, 'tcx>, + source: Ty<'tcx>, + target: Ty<'tcx>, + old_info: Option, + param_substs: &'tcx Substs<'tcx>) + -> ValueRef { + let (source, target) = ccx.tcx().struct_lockstep_tails(source, target); + match (&source.sty, &target.sty) { + (&ty::TyArray(_, len), &ty::TySlice(_)) => C_uint(ccx, len), + (&ty::TyTrait(_), &ty::TyTrait(_)) => { + // For now, upcasts are limited to changes in marker + // traits, and hence never actually require an actual + // change to the vtable. + old_info.expect("unsized_info: missing old info for trait upcast") + } + (_, &ty::TyTrait(box ty::TraitTy { ref principal, .. })) => { + // Note that we preserve binding levels here: + let substs = principal.0.substs.with_self_ty(source).erase_regions(); + let substs = ccx.tcx().mk_substs(substs); + let trait_ref = ty::Binder(ty::TraitRef { def_id: principal.def_id(), + substs: substs }); + consts::ptrcast(meth::get_vtable(ccx, trait_ref, param_substs), + Type::vtable_ptr(ccx)) + } + _ => ccx.sess().bug(&format!("unsized_info: invalid unsizing {:?} -> {:?}", + source, + target)) + } +} + +/// Coerce `src` to `dst_ty`. `src_ty` must be a thin pointer. +pub fn unsize_thin_ptr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, + src: ValueRef, + src_ty: Ty<'tcx>, + dst_ty: Ty<'tcx>) + -> (ValueRef, ValueRef) { + debug!("unsize_thin_ptr: {:?} => {:?}", src_ty, dst_ty); + match (&src_ty.sty, &dst_ty.sty) { + (&ty::TyBox(a), &ty::TyBox(b)) | + (&ty::TyRef(_, ty::TypeAndMut { ty: a, .. }), + &ty::TyRef(_, ty::TypeAndMut { ty: b, .. })) | + (&ty::TyRef(_, ty::TypeAndMut { ty: a, .. }), + &ty::TyRawPtr(ty::TypeAndMut { ty: b, .. })) | + (&ty::TyRawPtr(ty::TypeAndMut { ty: a, .. }), + &ty::TyRawPtr(ty::TypeAndMut { ty: b, .. })) => { + assert!(common::type_is_sized(bcx.tcx(), a)); + let ptr_ty = type_of::in_memory_type_of(bcx.ccx(), b).ptr_to(); + (PointerCast(bcx, src, ptr_ty), + unsized_info(bcx.ccx(), a, b, None, bcx.fcx.param_substs)) + } + _ => bcx.sess().bug( + &format!("unsize_thin_ptr: called on bad types")) + } +} + +/// Coerce `src`, which is a reference to a value of type `src_ty`, +/// to a value of type `dst_ty` and store the result in `dst` +pub fn coerce_unsized_into<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, + src: ValueRef, + src_ty: Ty<'tcx>, + dst: ValueRef, + dst_ty: Ty<'tcx>) { + match (&src_ty.sty, &dst_ty.sty) { + (&ty::TyBox(..), &ty::TyBox(..)) | + (&ty::TyRef(..), &ty::TyRef(..)) | + (&ty::TyRef(..), &ty::TyRawPtr(..)) | + (&ty::TyRawPtr(..), &ty::TyRawPtr(..)) => { + let (base, info) = if common::type_is_fat_ptr(bcx.tcx(), src_ty) { + // fat-ptr to fat-ptr unsize preserves the vtable + load_fat_ptr(bcx, src, src_ty) + } else { + let base = load_ty(bcx, src, src_ty); + unsize_thin_ptr(bcx, base, src_ty, dst_ty) + }; + store_fat_ptr(bcx, base, info, dst, dst_ty); + } + + // This can be extended to enums and tuples in the future. + // (&ty::TyEnum(def_id_a, _), &ty::TyEnum(def_id_b, _)) | + (&ty::TyStruct(def_a, _), &ty::TyStruct(def_b, _)) => { + assert_eq!(def_a, def_b); + + let src_repr = adt::represent_type(bcx.ccx(), src_ty); + let src_fields = match &*src_repr { + &adt::Repr::Univariant(ref s, _) => &s.fields, + _ => bcx.sess().bug("struct has non-univariant repr") + }; + let dst_repr = adt::represent_type(bcx.ccx(), dst_ty); + let dst_fields = match &*dst_repr { + &adt::Repr::Univariant(ref s, _) => &s.fields, + _ => bcx.sess().bug("struct has non-univariant repr") + }; + + let iter = src_fields.iter().zip(dst_fields).enumerate(); + for (i, (src_fty, dst_fty)) in iter { + if type_is_zero_size(bcx.ccx(), dst_fty) { continue; } + + let src_f = adt::trans_field_ptr(bcx, &src_repr, src, 0, i); + let dst_f = adt::trans_field_ptr(bcx, &dst_repr, dst, 0, i); + if src_fty == dst_fty { + memcpy_ty(bcx, dst_f, src_f, src_fty); + } else { + coerce_unsized_into( + bcx, + src_f, src_fty, + dst_f, dst_fty + ); + } + } + } + _ => bcx.sess().bug(&format!("coerce_unsized_into: invalid coercion {:?} -> {:?}", + src_ty, + dst_ty)) + } +} + pub fn cast_shift_expr_rhs(cx: Block, op: hir::BinOp_, lhs: ValueRef, @@ -831,6 +1006,10 @@ pub fn store_ty<'blk, 'tcx>(cx: Block<'blk, 'tcx>, v: ValueRef, dst: ValueRef, t return; } + debug!("store_ty: {} : {:?} <- {}", + cx.val_to_string(dst), t, + cx.val_to_string(v)); + if common::type_is_fat_ptr(cx.tcx(), t) { Store(cx, ExtractValue(cx, v, abi::FAT_PTR_ADDR), expr::get_dataptr(cx, dst)); Store(cx, ExtractValue(cx, v, abi::FAT_PTR_EXTRA), expr::get_meta(cx, dst)); @@ -842,6 +1021,25 @@ pub fn store_ty<'blk, 'tcx>(cx: Block<'blk, 'tcx>, v: ValueRef, dst: ValueRef, t } } +pub fn store_fat_ptr<'blk, 'tcx>(cx: Block<'blk, 'tcx>, + data: ValueRef, + extra: ValueRef, + dst: ValueRef, + _ty: Ty<'tcx>) { + // FIXME: emit metadata + Store(cx, data, expr::get_dataptr(cx, dst)); + Store(cx, extra, expr::get_meta(cx, dst)); +} + +pub fn load_fat_ptr<'blk, 'tcx>(cx: Block<'blk, 'tcx>, + src: ValueRef, + _ty: Ty<'tcx>) -> (ValueRef, ValueRef) +{ + // FIXME: emit metadata + (Load(cx, expr::get_dataptr(cx, src)), + Load(cx, expr::get_meta(cx, src))) +} + pub fn from_arg_ty(bcx: Block, val: ValueRef, ty: Ty) -> ValueRef { if ty.is_bool() { ZExt(bcx, val, Type::i8(bcx.ccx())) @@ -1235,7 +1433,10 @@ pub fn new_fn_ctxt<'a, 'tcx>(ccx: &'a CrateContext<'a, 'tcx>, false }; + let mir = ccx.mir_map().get(&id); + let mut fcx = FunctionContext { + mir: mir, llfn: llfndecl, llenv: None, llretslotptr: Cell::new(None), @@ -1575,7 +1776,7 @@ pub fn trans_closure<'a, 'b, 'tcx>(ccx: &CrateContext<'a, 'tcx>, llfndecl: ValueRef, param_substs: &'tcx Substs<'tcx>, fn_ast_id: ast::NodeId, - _attributes: &[ast::Attribute], + attributes: &[ast::Attribute], output_type: ty::FnOutput<'tcx>, abi: Abi, closure_env: closure::ClosureEnv<'b>) { @@ -1604,6 +1805,12 @@ pub fn trans_closure<'a, 'b, 'tcx>(ccx: &CrateContext<'a, 'tcx>, &arena); let mut bcx = init_function(&fcx, false, output_type); + if attributes.iter().any(|item| item.check_name("rustc_mir")) { + mir::trans_mir(bcx); + fcx.cleanup(); + return; + } + // cleanup scope for the incoming arguments let fn_cleanup_debug_loc = debuginfo::get_cleanup_debug_loc_for_ast_node(ccx, fn_ast_id, body.span, true); @@ -1699,7 +1906,11 @@ pub fn trans_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, debug!("trans_fn(param_substs={:?})", param_substs); let _icx = push_ctxt("trans_fn"); let fn_ty = ccx.tcx().node_id_to_type(id); - let output_type = ccx.tcx().erase_late_bound_regions(&fn_ty.fn_ret()); + let fn_ty = monomorphize::apply_param_substs(ccx.tcx(), param_substs, &fn_ty); + let sig = fn_ty.fn_sig(); + let sig = ccx.tcx().erase_late_bound_regions(&sig); + let sig = infer::normalize_associated_type(ccx.tcx(), &sig); + let output_type = sig.output; let abi = fn_ty.fn_abi(); trans_closure(ccx, decl, body, llfndecl, param_substs, id, attrs, output_type, abi, closure::ClosureEnv::NotClosure); @@ -1730,15 +1941,9 @@ pub fn trans_named_tuple_constructor<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, let ccx = bcx.fcx.ccx; - let result_ty = match ctor_ty.sty { - ty::TyBareFn(_, ref bft) => { - bcx.tcx().erase_late_bound_regions(&bft.sig.output()).unwrap() - } - _ => ccx.sess().bug( - &format!("trans_enum_variant_constructor: \ - unexpected ctor return type {}", - ctor_ty)) - }; + let sig = ccx.tcx().erase_late_bound_regions(&ctor_ty.fn_sig()); + let sig = infer::normalize_associated_type(ccx.tcx(), &sig); + let result_ty = sig.output.unwrap(); // Get location to store the result. If the user does not care about // the result, just make a stack slot @@ -1820,15 +2025,10 @@ fn trans_enum_variant_or_tuple_like_struct<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx let ctor_ty = ccx.tcx().node_id_to_type(ctor_id); let ctor_ty = monomorphize::apply_param_substs(ccx.tcx(), param_substs, &ctor_ty); - let result_ty = match ctor_ty.sty { - ty::TyBareFn(_, ref bft) => { - ccx.tcx().erase_late_bound_regions(&bft.sig.output()) - } - _ => ccx.sess().bug( - &format!("trans_enum_variant_or_tuple_like_struct: \ - unexpected ctor return type {}", - ctor_ty)) - }; + let sig = ccx.tcx().erase_late_bound_regions(&ctor_ty.fn_sig()); + let sig = infer::normalize_associated_type(ccx.tcx(), &sig); + let arg_tys = sig.inputs; + let result_ty = sig.output; let (arena, fcx): (TypedArena<_>, FunctionContext); arena = TypedArena::new(); @@ -1838,8 +2038,6 @@ fn trans_enum_variant_or_tuple_like_struct<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx assert!(!fcx.needs_ret_allocas); - let arg_tys = ccx.tcx().erase_late_bound_regions(&ctor_ty.fn_args()); - if !type_is_zero_size(fcx.ccx, result_ty.unwrap()) { let dest = fcx.get_ret_slot(bcx, result_ty, "eret_slot"); let repr = adt::represent_type(ccx, result_ty.unwrap()); @@ -2737,7 +2935,10 @@ pub fn filter_reachable_ids(ccx: &SharedCrateContext) -> NodeSet { }).collect() } -pub fn trans_crate(tcx: &ty::ctxt, analysis: ty::CrateAnalysis) -> CrateTranslation { +pub fn trans_crate<'tcx>(tcx: &ty::ctxt<'tcx>, + mir_map: &MirMap<'tcx>, + analysis: ty::CrateAnalysis) + -> CrateTranslation { let ty::CrateAnalysis { export_map, reachable, name, .. } = analysis; let krate = tcx.map.krate(); @@ -2779,6 +2980,7 @@ pub fn trans_crate(tcx: &ty::ctxt, analysis: ty::CrateAnalysis) -> CrateTranslat let shared_ccx = SharedCrateContext::new(&link_meta.crate_name, codegen_units, tcx, + &mir_map, export_map, Sha256::new(), link_meta.clone(), @@ -2865,7 +3067,8 @@ pub fn trans_crate(tcx: &ty::ctxt, analysis: ty::CrateAnalysis) -> CrateTranslat sess.cstore.iter_crate_data(|cnum, _| { let syms = csearch::get_reachable_ids(&sess.cstore, cnum); reachable_symbols.extend(syms.into_iter().filter(|did| { - csearch::is_extern_fn(&sess.cstore, *did, shared_ccx.tcx()) + csearch::is_extern_fn(&sess.cstore, *did, shared_ccx.tcx()) || + csearch::is_static(&sess.cstore, *did) }).map(|did| { csearch::get_symbol(&sess.cstore, did) })); diff --git a/src/librustc_trans/trans/callee.rs b/src/librustc_trans/trans/callee.rs index c8525e33e2667..a52c7f94c3a81 100644 --- a/src/librustc_trans/trans/callee.rs +++ b/src/librustc_trans/trans/callee.rs @@ -25,7 +25,7 @@ use llvm::{self, ValueRef, get_params}; use metadata::cstore::LOCAL_CRATE; use middle::def; use middle::def_id::DefId; -use middle::infer::normalize_associated_type; +use middle::infer; use middle::subst; use middle::subst::{Substs}; use rustc::front::map as hir_map; @@ -304,6 +304,7 @@ pub fn trans_fn_pointer_shim<'a, 'tcx>( } }; let sig = tcx.erase_late_bound_regions(sig); + let sig = infer::normalize_associated_type(ccx.tcx(), &sig); let tuple_input_ty = tcx.mk_tup(sig.inputs.to_vec()); let tuple_fn_ty = tcx.mk_fn(opt_def_id, tcx.mk_bare_fn(ty::BareFnTy { @@ -466,7 +467,7 @@ pub fn trans_fn_ref_with_substs<'a, 'tcx>( // Type scheme of the function item (may have type params) let fn_type_scheme = tcx.lookup_item_type(def_id); - let fn_type = normalize_associated_type(tcx, &fn_type_scheme.ty); + let fn_type = infer::normalize_associated_type(tcx, &fn_type_scheme.ty); // Find the actual function pointer. let mut val = { @@ -605,8 +606,9 @@ pub fn trans_call_inner<'a, 'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>, let (abi, ret_ty) = match callee.ty.sty { ty::TyBareFn(_, ref f) => { - let output = bcx.tcx().erase_late_bound_regions(&f.sig.output()); - (f.abi, output) + let sig = bcx.tcx().erase_late_bound_regions(&f.sig); + let sig = infer::normalize_associated_type(bcx.tcx(), &sig); + (f.abi, sig.output) } _ => panic!("expected bare rust fn or closure in trans_call_inner") }; @@ -826,7 +828,9 @@ fn trans_args_under_call_abi<'blk, 'tcx>( ignore_self: bool) -> Block<'blk, 'tcx> { - let args = bcx.tcx().erase_late_bound_regions(&fn_ty.fn_args()); + let sig = bcx.tcx().erase_late_bound_regions(&fn_ty.fn_sig()); + let sig = infer::normalize_associated_type(bcx.tcx(), &sig); + let args = sig.inputs; // Translate the `self` argument first. if !ignore_self { @@ -887,7 +891,10 @@ fn trans_overloaded_call_args<'blk, 'tcx>( ignore_self: bool) -> Block<'blk, 'tcx> { // Translate the `self` argument first. - let arg_tys = bcx.tcx().erase_late_bound_regions( &fn_ty.fn_args()); + let sig = bcx.tcx().erase_late_bound_regions(&fn_ty.fn_sig()); + let sig = infer::normalize_associated_type(bcx.tcx(), &sig); + let arg_tys = sig.inputs; + if !ignore_self { let arg_datum = unpack_datum!(bcx, expr::trans(bcx, arg_exprs[0])); bcx = trans_arg_datum(bcx, @@ -933,8 +940,10 @@ pub fn trans_args<'a, 'blk, 'tcx>(cx: Block<'blk, 'tcx>, debug!("trans_args(abi={})", abi); let _icx = push_ctxt("trans_args"); - let arg_tys = cx.tcx().erase_late_bound_regions(&fn_ty.fn_args()); - let variadic = fn_ty.fn_sig().0.variadic; + let sig = cx.tcx().erase_late_bound_regions(&fn_ty.fn_sig()); + let sig = infer::normalize_associated_type(cx.tcx(), &sig); + let arg_tys = sig.inputs; + let variadic = sig.variadic; let mut bcx = cx; diff --git a/src/librustc_trans/trans/closure.rs b/src/librustc_trans/trans/closure.rs index d3509c2f8133a..04487a6f2d25d 100644 --- a/src/librustc_trans/trans/closure.rs +++ b/src/librustc_trans/trans/closure.rs @@ -210,6 +210,7 @@ pub fn trans_closure_expr<'a, 'tcx>(dest: Dest<'a, 'tcx>, tcx.with_freevars(id, |fv| fv.iter().cloned().collect()); let sig = tcx.erase_late_bound_regions(&function_type.sig); + let sig = infer::normalize_associated_type(ccx.tcx(), &sig); trans_closure(ccx, decl, @@ -371,6 +372,8 @@ fn trans_fn_once_adapter_shim<'a, 'tcx>( let lloncefn = declare::define_internal_rust_fn(ccx, &function_name, llonce_fn_ty); let sig = tcx.erase_late_bound_regions(&llonce_bare_fn_ty.sig); + let sig = infer::normalize_associated_type(ccx.tcx(), &sig); + let (block_arena, fcx): (TypedArena<_>, FunctionContext); block_arena = TypedArena::new(); fcx = new_fn_ctxt(ccx, diff --git a/src/librustc_trans/trans/common.rs b/src/librustc_trans/trans/common.rs index b39b7818a6350..275f4628788d3 100644 --- a/src/librustc_trans/trans/common.rs +++ b/src/librustc_trans/trans/common.rs @@ -16,7 +16,7 @@ pub use self::ExprOrMethodCall::*; use session::Session; use llvm; -use llvm::{ValueRef, BasicBlockRef, BuilderRef, ContextRef}; +use llvm::{ValueRef, BasicBlockRef, BuilderRef, ContextRef, TypeKind}; use llvm::{True, False, Bool}; use middle::cfg; use middle::def; @@ -40,6 +40,7 @@ use middle::traits; use middle::ty::{self, HasTypeFlags, Ty}; use middle::ty::fold::{TypeFolder, TypeFoldable}; use rustc_front::hir; +use rustc_mir::repr::Mir; use util::nodemap::{FnvHashMap, NodeMap}; use arena::TypedArena; @@ -328,6 +329,11 @@ impl<'tcx> DropFlagHintsMap<'tcx> { // Function context. Every LLVM function we create will have one of // these. pub struct FunctionContext<'a, 'tcx: 'a> { + // The MIR for this function. At present, this is optional because + // we only have MIR available for things that are local to the + // crate. + pub mir: Option<&'a Mir<'tcx>>, + // The ValueRef returned from a call to llvm::LLVMAddFunction; the // address of the first instruction in the sequence of // instructions for this function that will go in the .text @@ -407,6 +413,10 @@ pub struct FunctionContext<'a, 'tcx: 'a> { } impl<'a, 'tcx> FunctionContext<'a, 'tcx> { + pub fn mir(&self) -> &'a Mir<'tcx> { + self.mir.unwrap() + } + pub fn arg_offset(&self) -> usize { self.env_arg_pos() + if self.llenv.is_some() { 1 } else { 0 } } @@ -644,6 +654,10 @@ impl<'blk, 'tcx> BlockS<'blk, 'tcx> { } pub fn sess(&self) -> &'blk Session { self.fcx.ccx.sess() } + pub fn mir(&self) -> &'blk Mir<'tcx> { + self.fcx.mir() + } + pub fn name(&self, name: ast::Name) -> String { name.to_string() } @@ -729,6 +743,12 @@ pub fn C_floating(s: &str, t: Type) -> ValueRef { } } +pub fn C_floating_f64(f: f64, t: Type) -> ValueRef { + unsafe { + llvm::LLVMConstReal(t.to_ref(), f) + } +} + pub fn C_nil(ccx: &CrateContext) -> ValueRef { C_struct(ccx, &[], false) } @@ -1132,3 +1152,75 @@ pub fn inlined_variant_def<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ccx.sess().bug(&format!("no variant for {:?}::{}", adt_def, inlined_vid)) }) } + +// To avoid UB from LLVM, these two functions mask RHS with an +// appropriate mask unconditionally (i.e. the fallback behavior for +// all shifts). For 32- and 64-bit types, this matches the semantics +// of Java. (See related discussion on #1877 and #10183.) + +pub fn build_unchecked_lshift<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, + lhs: ValueRef, + rhs: ValueRef, + binop_debug_loc: DebugLoc) -> ValueRef { + let rhs = base::cast_shift_expr_rhs(bcx, hir::BinOp_::BiShl, lhs, rhs); + // #1877, #10183: Ensure that input is always valid + let rhs = shift_mask_rhs(bcx, rhs, binop_debug_loc); + build::Shl(bcx, lhs, rhs, binop_debug_loc) +} + +pub fn build_unchecked_rshift<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, + lhs_t: Ty<'tcx>, + lhs: ValueRef, + rhs: ValueRef, + binop_debug_loc: DebugLoc) -> ValueRef { + let rhs = base::cast_shift_expr_rhs(bcx, hir::BinOp_::BiShr, lhs, rhs); + // #1877, #10183: Ensure that input is always valid + let rhs = shift_mask_rhs(bcx, rhs, binop_debug_loc); + let is_signed = lhs_t.is_signed(); + if is_signed { + build::AShr(bcx, lhs, rhs, binop_debug_loc) + } else { + build::LShr(bcx, lhs, rhs, binop_debug_loc) + } +} + +fn shift_mask_rhs<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, + rhs: ValueRef, + debug_loc: DebugLoc) -> ValueRef { + let rhs_llty = val_ty(rhs); + build::And(bcx, rhs, shift_mask_val(bcx, rhs_llty, rhs_llty, false), debug_loc) +} + +pub fn shift_mask_val<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, + llty: Type, + mask_llty: Type, + invert: bool) -> ValueRef { + let kind = llty.kind(); + match kind { + TypeKind::Integer => { + // i8/u8 can shift by at most 7, i16/u16 by at most 15, etc. + let val = llty.int_width() - 1; + if invert { + C_integral(mask_llty, !val, true) + } else { + C_integral(mask_llty, val, false) + } + }, + TypeKind::Vector => { + let mask = shift_mask_val(bcx, llty.element_type(), mask_llty.element_type(), invert); + build::VectorSplat(bcx, mask_llty.vector_length(), mask) + }, + _ => panic!("shift_mask_val: expected Integer or Vector, found {:?}", kind), + } +} + +pub fn get_static_val<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, + did: DefId, + ty: Ty<'tcx>) + -> ValueRef { + if let Some(node_id) = ccx.tcx().map.as_local_node_id(did) { + base::get_item_val(ccx, node_id) + } else { + base::get_extern_const(ccx, did, ty) + } +} \ No newline at end of file diff --git a/src/librustc_trans/trans/consts.rs b/src/librustc_trans/trans/consts.rs index 90faef51c2c6c..91f17a50e2c41 100644 --- a/src/librustc_trans/trans/consts.rs +++ b/src/librustc_trans/trans/consts.rs @@ -29,8 +29,8 @@ use middle::const_eval::eval_const_expr_partial; use middle::def_id::DefId; use trans::{adt, closure, debuginfo, expr, inline, machine}; use trans::base::{self, push_ctxt}; +use trans::common::{self, type_is_sized, ExprOrMethodCall, node_id_substs, C_nil, const_get_elt}; use trans::common::{CrateContext, C_integral, C_floating, C_bool, C_str_slice, C_bytes, val_ty}; -use trans::common::{type_is_sized, ExprOrMethodCall, node_id_substs, C_nil, const_get_elt}; use trans::common::{C_struct, C_undef, const_to_opt_int, const_to_opt_uint, VariantInfo, C_uint}; use trans::common::{type_is_fat_ptr, Field, C_vector, C_array, C_null, ExprId, MethodCallKey}; use trans::declare; @@ -410,7 +410,7 @@ pub fn const_expr<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, .expect("consts: unsizing got non-pointer target type").ty; let ptr_ty = type_of::in_memory_type_of(cx, unsized_ty).ptr_to(); let base = ptrcast(base, ptr_ty); - let info = expr::unsized_info(cx, pointee_ty, unsized_ty, + let info = base::unsized_info(cx, pointee_ty, unsized_ty, old_info, param_substs); if old_info.is_none() { @@ -795,7 +795,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, } let opt_def = cx.tcx().def_map.borrow().get(&cur.id).map(|d| d.full_def()); if let Some(def::DefStatic(def_id, _)) = opt_def { - get_static_val(cx, def_id, ety) + common::get_static_val(cx, def_id, ety) } else { // If this isn't the address of a static, then keep going through // normal constant evaluation. @@ -1075,15 +1075,3 @@ pub fn trans_static(ccx: &CrateContext, Ok(g) } } - - -fn get_static_val<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, - did: DefId, - ty: Ty<'tcx>) - -> ValueRef { - if let Some(node_id) = ccx.tcx().map.as_local_node_id(did) { - base::get_item_val(ccx, node_id) - } else { - base::trans_external_path(ccx, did, ty) - } -} diff --git a/src/librustc_trans/trans/context.rs b/src/librustc_trans/trans/context.rs index 01d0c51a08dd9..1f1d43feeb38e 100644 --- a/src/librustc_trans/trans/context.rs +++ b/src/librustc_trans/trans/context.rs @@ -14,6 +14,7 @@ use metadata::common::LinkMeta; use middle::def::ExportMap; use middle::def_id::DefId; use middle::traits; +use rustc_mir::mir_map::MirMap; use trans::adt; use trans::base; use trans::builder::Builder; @@ -70,6 +71,7 @@ pub struct SharedCrateContext<'a, 'tcx: 'a> { stats: Stats, check_overflow: bool, check_drop_flag_for_sanity: bool, + mir_map: &'a MirMap<'tcx>, available_drop_glues: RefCell, String>>, use_dll_storage_attrs: bool, @@ -251,6 +253,7 @@ impl<'b, 'tcx> SharedCrateContext<'b, 'tcx> { pub fn new(crate_name: &str, local_count: usize, tcx: &'b ty::ctxt<'tcx>, + mir_map: &'b MirMap<'tcx>, export_map: ExportMap, symbol_hasher: Sha256, link_meta: LinkMeta, @@ -317,6 +320,7 @@ impl<'b, 'tcx> SharedCrateContext<'b, 'tcx> { link_meta: link_meta, symbol_hasher: RefCell::new(symbol_hasher), tcx: tcx, + mir_map: mir_map, stats: Stats { n_glues_created: Cell::new(0), n_null_glues: Cell::new(0), @@ -803,6 +807,10 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> { pub fn use_dll_storage_attrs(&self) -> bool { self.shared.use_dll_storage_attrs() } + + pub fn mir_map(&self) -> &'b MirMap<'tcx> { + self.shared.mir_map + } } pub struct TypeOfDepthLock<'a, 'tcx: 'a>(&'a LocalCrateContext<'tcx>); diff --git a/src/librustc_trans/trans/debuginfo/create_scope_map.rs b/src/librustc_trans/trans/debuginfo/create_scope_map.rs index 01f5a32b1a3d4..0c424de9e10b8 100644 --- a/src/librustc_trans/trans/debuginfo/create_scope_map.rs +++ b/src/librustc_trans/trans/debuginfo/create_scope_map.rs @@ -167,7 +167,7 @@ fn walk_pattern(cx: &CrateContext, // Check if this is a binding. If so we need to put it on the // scope stack and maybe introduce an artificial scope - if pat_util::pat_is_binding(def_map, &*pat) { + if pat_util::pat_is_binding(&def_map.borrow(), &*pat) { let name = path1.node.name; diff --git a/src/librustc_trans/trans/debuginfo/metadata.rs b/src/librustc_trans/trans/debuginfo/metadata.rs index 2e7b1f31ba9bc..addac528aa25c 100644 --- a/src/librustc_trans/trans/debuginfo/metadata.rs +++ b/src/librustc_trans/trans/debuginfo/metadata.rs @@ -24,6 +24,7 @@ use llvm::{self, ValueRef}; use llvm::debuginfo::{DIType, DIFile, DIScope, DIDescriptor, DICompositeType}; use middle::def_id::DefId; +use middle::infer; use middle::pat_util; use middle::subst::{self, Substs}; use rustc::front::map as hir_map; @@ -262,6 +263,7 @@ impl<'tcx> TypeMap<'tcx> { unique_type_id.push_str(" fn("); let sig = cx.tcx().erase_late_bound_regions(sig); + let sig = infer::normalize_associated_type(cx.tcx(), &sig); for ¶meter_type in &sig.inputs { let parameter_type_id = diff --git a/src/librustc_trans/trans/debuginfo/mod.rs b/src/librustc_trans/trans/debuginfo/mod.rs index a08f33c889994..9e53d72cfb8b9 100644 --- a/src/librustc_trans/trans/debuginfo/mod.rs +++ b/src/librustc_trans/trans/debuginfo/mod.rs @@ -35,6 +35,7 @@ use rustc_front::hir; use trans::common::{NodeIdAndSpan, CrateContext, FunctionContext, Block}; use trans; use trans::{monomorphize, type_of}; +use middle::infer; use middle::ty::{self, Ty}; use session::config::{self, FullDebugInfo, LimitedDebugInfo, NoDebugInfo}; use util::nodemap::{NodeMap, FnvHashMap, FnvHashSet}; @@ -418,19 +419,23 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, // Return type -- llvm::DIBuilder wants this at index 0 assert_type_for_node_id(cx, fn_ast_id, error_reporting_span); let fn_type = cx.tcx().node_id_to_type(fn_ast_id); + let fn_type = monomorphize::apply_param_substs(cx.tcx(), param_substs, &fn_type); let (sig, abi) = match fn_type.sty { ty::TyBareFn(_, ref barefnty) => { - (cx.tcx().erase_late_bound_regions(&barefnty.sig), barefnty.abi) + let sig = cx.tcx().erase_late_bound_regions(&barefnty.sig); + let sig = infer::normalize_associated_type(cx.tcx(), &sig); + (sig, barefnty.abi) } ty::TyClosure(def_id, ref substs) => { let closure_type = cx.tcx().closure_type(def_id, substs); - (cx.tcx().erase_late_bound_regions(&closure_type.sig), closure_type.abi) + let sig = cx.tcx().erase_late_bound_regions(&closure_type.sig); + let sig = infer::normalize_associated_type(cx.tcx(), &sig); + (sig, closure_type.abi) } _ => cx.sess().bug("get_function_metdata: Expected a function type!") }; - let sig = monomorphize::apply_param_substs(cx.tcx(), param_substs, &sig); let mut signature = Vec::with_capacity(sig.inputs.len() + 1); diff --git a/src/librustc_trans/trans/debuginfo/type_names.rs b/src/librustc_trans/trans/debuginfo/type_names.rs index 7400ec3cbcd4a..c6b5ce436835f 100644 --- a/src/librustc_trans/trans/debuginfo/type_names.rs +++ b/src/librustc_trans/trans/debuginfo/type_names.rs @@ -14,6 +14,7 @@ use super::namespace::crate_root_namespace; use trans::common::CrateContext; use middle::def_id::DefId; +use middle::infer; use middle::subst::{self, Substs}; use middle::ty::{self, Ty}; @@ -124,6 +125,7 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, output.push_str("fn("); let sig = cx.tcx().erase_late_bound_regions(sig); + let sig = infer::normalize_associated_type(cx.tcx(), &sig); if !sig.inputs.is_empty() { for ¶meter_type in &sig.inputs { push_debuginfo_type_name(cx, parameter_type, true, output); diff --git a/src/librustc_trans/trans/declare.rs b/src/librustc_trans/trans/declare.rs index ce9f3b4b05da1..b9e74beaf55ae 100644 --- a/src/librustc_trans/trans/declare.rs +++ b/src/librustc_trans/trans/declare.rs @@ -103,9 +103,6 @@ pub fn declare_rust_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, name: &str, fn_type: ty::Ty<'tcx>) -> ValueRef { debug!("declare_rust_fn(name={:?}, fn_type={:?})", name, fn_type); - let fn_type = infer::normalize_associated_type(ccx.tcx(), &fn_type); - debug!("declare_rust_fn (after normalised associated types) fn_type={:?}", - fn_type); let function_type; // placeholder so that the memory ownership works out ok let (sig, abi, env) = match fn_type.sty { @@ -124,14 +121,15 @@ pub fn declare_rust_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, name: &str, _ => ccx.sess().bug("expected closure or fn") }; - let sig = ty::Binder(ccx.tcx().erase_late_bound_regions(sig)); + let sig = ccx.tcx().erase_late_bound_regions(sig); + let sig = infer::normalize_associated_type(ccx.tcx(), &sig); debug!("declare_rust_fn (after region erasure) sig={:?}", sig); let llfty = type_of::type_of_rust_fn(ccx, env, &sig, abi); debug!("declare_rust_fn llfty={}", ccx.tn().type_to_string(llfty)); // it is ok to directly access sig.0.output because we erased all // late-bound-regions above - let llfn = declare_fn(ccx, name, llvm::CCallConv, llfty, sig.0.output); + let llfn = declare_fn(ccx, name, llvm::CCallConv, llfty, sig.output); attributes::from_fn_type(ccx, fn_type).apply_llfn(llfn); llfn } diff --git a/src/librustc_trans/trans/expr.rs b/src/librustc_trans/trans/expr.rs index 6144de7109fba..728b53dcd4aee 100644 --- a/src/librustc_trans/trans/expr.rs +++ b/src/librustc_trans/trans/expr.rs @@ -326,42 +326,6 @@ pub fn copy_fat_ptr(bcx: Block, src_ptr: ValueRef, dst_ptr: ValueRef) { Store(bcx, Load(bcx, get_meta(bcx, src_ptr)), get_meta(bcx, dst_ptr)); } -/// Retrieve the information we are losing (making dynamic) in an unsizing -/// adjustment. -/// -/// The `old_info` argument is a bit funny. It is intended for use -/// in an upcast, where the new vtable for an object will be drived -/// from the old one. -pub fn unsized_info<'ccx, 'tcx>(ccx: &CrateContext<'ccx, 'tcx>, - source: Ty<'tcx>, - target: Ty<'tcx>, - old_info: Option, - param_substs: &'tcx Substs<'tcx>) - -> ValueRef { - let (source, target) = ccx.tcx().struct_lockstep_tails(source, target); - match (&source.sty, &target.sty) { - (&ty::TyArray(_, len), &ty::TySlice(_)) => C_uint(ccx, len), - (&ty::TyTrait(_), &ty::TyTrait(_)) => { - // For now, upcasts are limited to changes in marker - // traits, and hence never actually require an actual - // change to the vtable. - old_info.expect("unsized_info: missing old info for trait upcast") - } - (_, &ty::TyTrait(box ty::TraitTy { ref principal, .. })) => { - // Note that we preserve binding levels here: - let substs = principal.0.substs.with_self_ty(source).erase_regions(); - let substs = ccx.tcx().mk_substs(substs); - let trait_ref = ty::Binder(ty::TraitRef { def_id: principal.def_id(), - substs: substs }); - consts::ptrcast(meth::get_vtable(ccx, trait_ref, param_substs), - Type::vtable_ptr(ccx)) - } - _ => ccx.sess().bug(&format!("unsized_info: invalid unsizing {:?} -> {:?}", - source, - target)) - } -} - fn adjustment_required<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &hir::Expr) -> bool { let adjustment = match bcx.tcx().tables.borrow().adjustments.get(&expr.id).cloned() { @@ -941,29 +905,8 @@ fn trans_def<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, DatumBlock::new(bcx, datum.to_expr_datum()) } def::DefStatic(did, _) => { - // There are two things that may happen here: - // 1) If the static item is defined in this crate, it will be - // translated using `get_item_val`, and we return a pointer to - // the result. - // 2) If the static item is defined in another crate then we add - // (or reuse) a declaration of an external global, and return a - // pointer to that. let const_ty = expr_ty(bcx, ref_expr); - - // For external constants, we don't inline. - let val = if let Some(node_id) = bcx.tcx().map.as_local_node_id(did) { - // Case 1. - - // The LLVM global has the type of its initializer, - // which may not be equal to the enum's type for - // non-C-like enums. - let val = base::get_item_val(bcx.ccx(), node_id); - let pty = type_of::type_of(bcx.ccx(), const_ty).ptr_to(); - PointerCast(bcx, val, pty) - } else { - // Case 2. - base::get_extern_const(bcx.ccx(), did, const_ty) - }; + let val = get_static_val(bcx.ccx(), did, const_ty); let lval = Lvalue::new("expr::trans_def"); DatumBlock::new(bcx, Datum::new(val, const_ty, LvalueExpr(lval))) } @@ -1746,58 +1689,6 @@ fn trans_addr_of<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, } } -fn trans_fat_ptr_binop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, - binop_expr: &hir::Expr, - binop_ty: Ty<'tcx>, - op: hir::BinOp, - lhs: Datum<'tcx, Rvalue>, - rhs: Datum<'tcx, Rvalue>) - -> DatumBlock<'blk, 'tcx, Expr> -{ - let debug_loc = binop_expr.debug_loc(); - - let lhs_addr = Load(bcx, GEPi(bcx, lhs.val, &[0, abi::FAT_PTR_ADDR])); - let lhs_extra = Load(bcx, GEPi(bcx, lhs.val, &[0, abi::FAT_PTR_EXTRA])); - - let rhs_addr = Load(bcx, GEPi(bcx, rhs.val, &[0, abi::FAT_PTR_ADDR])); - let rhs_extra = Load(bcx, GEPi(bcx, rhs.val, &[0, abi::FAT_PTR_EXTRA])); - - let val = match op.node { - hir::BiEq => { - let addr_eq = ICmp(bcx, llvm::IntEQ, lhs_addr, rhs_addr, debug_loc); - let extra_eq = ICmp(bcx, llvm::IntEQ, lhs_extra, rhs_extra, debug_loc); - And(bcx, addr_eq, extra_eq, debug_loc) - } - hir::BiNe => { - let addr_eq = ICmp(bcx, llvm::IntNE, lhs_addr, rhs_addr, debug_loc); - let extra_eq = ICmp(bcx, llvm::IntNE, lhs_extra, rhs_extra, debug_loc); - Or(bcx, addr_eq, extra_eq, debug_loc) - } - hir::BiLe | hir::BiLt | hir::BiGe | hir::BiGt => { - // a OP b ~ a.0 STRICT(OP) b.0 | (a.0 == b.0 && a.1 OP a.1) - let (op, strict_op) = match op.node { - hir::BiLt => (llvm::IntULT, llvm::IntULT), - hir::BiLe => (llvm::IntULE, llvm::IntULT), - hir::BiGt => (llvm::IntUGT, llvm::IntUGT), - hir::BiGe => (llvm::IntUGE, llvm::IntUGT), - _ => unreachable!() - }; - - let addr_eq = ICmp(bcx, llvm::IntEQ, lhs_addr, rhs_addr, debug_loc); - let extra_op = ICmp(bcx, op, lhs_extra, rhs_extra, debug_loc); - let addr_eq_extra_op = And(bcx, addr_eq, extra_op, debug_loc); - - let addr_strict = ICmp(bcx, strict_op, lhs_addr, rhs_addr, debug_loc); - Or(bcx, addr_strict, addr_eq_extra_op, debug_loc) - } - _ => { - bcx.tcx().sess.span_bug(binop_expr.span, "unexpected binop"); - } - }; - - immediate_rvalue_bcx(bcx, val, binop_ty).to_expr_datumblock() -} - fn trans_scalar_binop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, binop_expr: &hir::Expr, binop_ty: Ty<'tcx>, @@ -2026,7 +1917,15 @@ fn trans_binary<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, if type_is_fat_ptr(ccx.tcx(), lhs.ty) { assert!(type_is_fat_ptr(ccx.tcx(), rhs.ty), "built-in binary operators on fat pointers are homogeneous"); - trans_fat_ptr_binop(bcx, expr, binop_ty, op, lhs, rhs) + assert_eq!(binop_ty, bcx.tcx().types.bool); + let val = base::compare_scalar_types( + bcx, + lhs.val, + rhs.val, + lhs.ty, + op.node, + expr.debug_loc()); + immediate_rvalue_bcx(bcx, val, binop_ty).to_expr_datumblock() } else { assert!(!type_is_fat_ptr(ccx.tcx(), rhs.ty), "built-in binary operators on fat pointers are homogeneous"); @@ -2574,29 +2473,6 @@ impl OverflowOpViaInputCheck { } } -fn shift_mask_val<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, - llty: Type, - mask_llty: Type, - invert: bool) -> ValueRef { - let kind = llty.kind(); - match kind { - TypeKind::Integer => { - // i8/u8 can shift by at most 7, i16/u16 by at most 15, etc. - let val = llty.int_width() - 1; - if invert { - C_integral(mask_llty, !val, true) - } else { - C_integral(mask_llty, val, false) - } - }, - TypeKind::Vector => { - let mask = shift_mask_val(bcx, llty.element_type(), mask_llty.element_type(), invert); - VectorSplat(bcx, mask_llty.vector_length(), mask) - }, - _ => panic!("shift_mask_val: expected Integer or Vector, found {:?}", kind), - } -} - // Check if an integer or vector contains a nonzero element. fn build_nonzero_check<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, value: ValueRef, @@ -2616,44 +2492,6 @@ fn build_nonzero_check<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, } } -// To avoid UB from LLVM, these two functions mask RHS with an -// appropriate mask unconditionally (i.e. the fallback behavior for -// all shifts). For 32- and 64-bit types, this matches the semantics -// of Java. (See related discussion on #1877 and #10183.) - -fn build_unchecked_lshift<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, - lhs: ValueRef, - rhs: ValueRef, - binop_debug_loc: DebugLoc) -> ValueRef { - let rhs = base::cast_shift_expr_rhs(bcx, hir::BinOp_::BiShl, lhs, rhs); - // #1877, #10183: Ensure that input is always valid - let rhs = shift_mask_rhs(bcx, rhs, binop_debug_loc); - Shl(bcx, lhs, rhs, binop_debug_loc) -} - -fn build_unchecked_rshift<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, - lhs_t: Ty<'tcx>, - lhs: ValueRef, - rhs: ValueRef, - binop_debug_loc: DebugLoc) -> ValueRef { - let rhs = base::cast_shift_expr_rhs(bcx, hir::BinOp_::BiShr, lhs, rhs); - // #1877, #10183: Ensure that input is always valid - let rhs = shift_mask_rhs(bcx, rhs, binop_debug_loc); - let is_signed = lhs_t.is_signed(); - if is_signed { - AShr(bcx, lhs, rhs, binop_debug_loc) - } else { - LShr(bcx, lhs, rhs, binop_debug_loc) - } -} - -fn shift_mask_rhs<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, - rhs: ValueRef, - debug_loc: DebugLoc) -> ValueRef { - let rhs_llty = val_ty(rhs); - And(bcx, rhs, shift_mask_val(bcx, rhs_llty, rhs_llty, false), debug_loc) -} - fn with_overflow_check<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, oop: OverflowOp, info: NodeIdAndSpan, lhs_t: Ty<'tcx>, lhs: ValueRef, rhs: ValueRef, diff --git a/src/librustc_trans/trans/intrinsic.rs b/src/librustc_trans/trans/intrinsic.rs index 773256a17e4ac..98114da851f91 100644 --- a/src/librustc_trans/trans/intrinsic.rs +++ b/src/librustc_trans/trans/intrinsic.rs @@ -15,6 +15,7 @@ use intrinsics::{self, Intrinsic}; use libc; use llvm; use llvm::{SequentiallyConsistent, Acquire, Release, AtomicXchg, ValueRef, TypeKind}; +use middle::infer; use middle::subst; use middle::subst::FnSpace; use trans::adt; @@ -170,13 +171,10 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, let _icx = push_ctxt("trans_intrinsic_call"); - let (arg_tys, ret_ty) = match callee_ty.sty { - ty::TyBareFn(_, ref f) => { - (bcx.tcx().erase_late_bound_regions(&f.sig.inputs()), - bcx.tcx().erase_late_bound_regions(&f.sig.output())) - } - _ => panic!("expected bare_fn in trans_intrinsic_call") - }; + let sig = ccx.tcx().erase_late_bound_regions(callee_ty.fn_sig()); + let sig = infer::normalize_associated_type(ccx.tcx(), &sig); + let arg_tys = sig.inputs; + let ret_ty = sig.output; let foreign_item = tcx.map.expect_foreign_item(node); let name = foreign_item.name.as_str(); @@ -1330,12 +1328,9 @@ fn generic_simd_intrinsic<'blk, 'tcx, 'a> let tcx = bcx.tcx(); - let arg_tys = match callee_ty.sty { - ty::TyBareFn(_, ref f) => { - bcx.tcx().erase_late_bound_regions(&f.sig.inputs()) - } - _ => unreachable!() - }; + let sig = tcx.erase_late_bound_regions(callee_ty.fn_sig()); + let sig = infer::normalize_associated_type(tcx, &sig); + let arg_tys = sig.inputs; // every intrinsic takes a SIMD vector as its first argument require_simd!(arg_tys[0], "input"); diff --git a/src/librustc_trans/trans/meth.rs b/src/librustc_trans/trans/meth.rs index 2b711be5b07cd..ff94e4feda216 100644 --- a/src/librustc_trans/trans/meth.rs +++ b/src/librustc_trans/trans/meth.rs @@ -12,6 +12,7 @@ use arena::TypedArena; use back::link; use llvm::{ValueRef, get_params}; use middle::def_id::DefId; +use middle::infer; use middle::subst::{Subst, Substs}; use middle::subst::VecPerParamSpace; use middle::subst; @@ -522,6 +523,7 @@ fn trans_object_shim<'a, 'tcx>( let llfn = declare::define_internal_rust_fn(ccx, &function_name, shim_fn_ty); let sig = ccx.tcx().erase_late_bound_regions(&fty.sig); + let sig = infer::normalize_associated_type(ccx.tcx(), &sig); let empty_substs = tcx.mk_substs(Substs::trans_empty()); let (block_arena, fcx): (TypedArena<_>, FunctionContext); diff --git a/src/librustc_trans/trans/mir/analyze.rs b/src/librustc_trans/trans/mir/analyze.rs new file mode 100644 index 0000000000000..fc76d1e787da5 --- /dev/null +++ b/src/librustc_trans/trans/mir/analyze.rs @@ -0,0 +1,115 @@ +// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! An analysis to determine which temporaries require allocas and +//! which do not. + +use rustc_data_structures::fnv::FnvHashSet; +use rustc_mir::repr as mir; +use rustc_mir::visit::{Visitor, LvalueContext}; +use trans::common::{self, Block}; +use super::rvalue; + +pub fn lvalue_temps<'bcx,'tcx>(bcx: Block<'bcx,'tcx>, + mir: &mir::Mir<'tcx>) + -> FnvHashSet { + let mut analyzer = TempAnalyzer::new(); + + analyzer.visit_mir(mir); + + for (index, temp_decl) in mir.temp_decls.iter().enumerate() { + let ty = bcx.monomorphize(&temp_decl.ty); + debug!("temp {:?} has type {:?}", index, ty); + if ty.is_scalar() || + ty.is_unique() || + ty.is_region_ptr() || + ty.is_simd() + { + // These sorts of types are immediates that we can store + // in an ValueRef without an alloca. + assert!(common::type_is_immediate(bcx.ccx(), ty) || + common::type_is_fat_ptr(bcx.tcx(), ty)); + } else { + // These sorts of types require an alloca. Note that + // type_is_immediate() may *still* be true, particularly + // for newtypes, but we currently force some types + // (e.g. structs) into an alloca unconditionally, just so + // that we don't have to deal with having two pathways + // (gep vs extractvalue etc). + analyzer.mark_as_lvalue(index); + } + } + + analyzer.lvalue_temps +} + +struct TempAnalyzer { + lvalue_temps: FnvHashSet, +} + +impl TempAnalyzer { + fn new() -> TempAnalyzer { + TempAnalyzer { lvalue_temps: FnvHashSet() } + } + + fn mark_as_lvalue(&mut self, temp: usize) { + debug!("marking temp {} as lvalue", temp); + self.lvalue_temps.insert(temp); + } +} + +impl<'tcx> Visitor<'tcx> for TempAnalyzer { + fn visit_assign(&mut self, + block: mir::BasicBlock, + lvalue: &mir::Lvalue<'tcx>, + rvalue: &mir::Rvalue<'tcx>) { + debug!("visit_assign(block={:?}, lvalue={:?}, rvalue={:?})", block, lvalue, rvalue); + + match *lvalue { + mir::Lvalue::Temp(index) => { + if !rvalue::rvalue_creates_operand(rvalue) { + self.mark_as_lvalue(index as usize); + } + } + _ => { + self.visit_lvalue(lvalue, LvalueContext::Store); + } + } + + self.visit_rvalue(rvalue); + } + + fn visit_lvalue(&mut self, + lvalue: &mir::Lvalue<'tcx>, + context: LvalueContext) { + debug!("visit_lvalue(lvalue={:?}, context={:?})", lvalue, context); + + match *lvalue { + mir::Lvalue::Temp(index) => { + match context { + LvalueContext::Consume => { + } + LvalueContext::Store | + LvalueContext::Drop | + LvalueContext::Inspect | + LvalueContext::Borrow { .. } | + LvalueContext::Slice { .. } | + LvalueContext::Projection => { + self.mark_as_lvalue(index as usize); + } + } + } + _ => { + } + } + + self.super_lvalue(lvalue, context); + } +} diff --git a/src/librustc_trans/trans/mir/block.rs b/src/librustc_trans/trans/mir/block.rs new file mode 100644 index 0000000000000..181a03790eeec --- /dev/null +++ b/src/librustc_trans/trans/mir/block.rs @@ -0,0 +1,117 @@ +// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use llvm::BasicBlockRef; +use rustc_mir::repr as mir; +use trans::base; +use trans::build; +use trans::common::Block; +use trans::debuginfo::DebugLoc; + +use super::MirContext; + +impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> { + pub fn trans_block(&mut self, bb: mir::BasicBlock) { + debug!("trans_block({:?})", bb); + + let mut bcx = self.bcx(bb); + let data = self.mir.basic_block_data(bb); + + for statement in &data.statements { + bcx = self.trans_statement(bcx, statement); + } + + debug!("trans_block: terminator: {:?}", data.terminator); + + match data.terminator { + mir::Terminator::Goto { target } => { + build::Br(bcx, self.llblock(target), DebugLoc::None) + } + + mir::Terminator::Panic { .. } => { + unimplemented!() + } + + mir::Terminator::If { ref cond, targets: [true_bb, false_bb] } => { + let cond = self.trans_operand(bcx, cond); + let lltrue = self.llblock(true_bb); + let llfalse = self.llblock(false_bb); + build::CondBr(bcx, cond.immediate(), lltrue, llfalse, DebugLoc::None); + } + + mir::Terminator::Switch { .. } => { + unimplemented!() + } + + mir::Terminator::SwitchInt { ref discr, switch_ty, ref values, ref targets } => { + let (otherwise, targets) = targets.split_last().unwrap(); + let discr = build::Load(bcx, self.trans_lvalue(bcx, discr).llval); + let switch = build::Switch(bcx, discr, self.llblock(*otherwise), values.len()); + for (value, target) in values.iter().zip(targets) { + let llval = self.trans_constval(bcx, value, switch_ty).immediate(); + let llbb = self.llblock(*target); + build::AddCase(switch, llval, llbb) + } + } + + mir::Terminator::Diverge => { + if let Some(llpersonalityslot) = self.llpersonalityslot { + let lp = build::Load(bcx, llpersonalityslot); + // FIXME(lifetime) base::call_lifetime_end(bcx, self.personality); + build::Resume(bcx, lp); + } else { + // This fn never encountered anything fallible, so + // a Diverge cannot actually happen. Note that we + // do a total hack to ensure that we visit the + // DIVERGE block last. + build::Unreachable(bcx); + } + } + + mir::Terminator::Return => { + let return_ty = bcx.monomorphize(&self.mir.return_ty); + base::build_return_block(bcx.fcx, bcx, return_ty, DebugLoc::None); + } + + mir::Terminator::Call { .. } => { + unimplemented!() + //let llbb = unimplemented!(); // self.make_landing_pad(panic_bb); + // + //let tr_dest = self.trans_lvalue(bcx, &data.destination); + // + //// Create the callee. This will always be a fn + //// ptr and hence a kind of scalar. + //let callee = self.trans_operand(bcx, &data.func); + // + //// Process the arguments. + // + //let args = unimplemented!(); + // + //callee::trans_call_inner(bcx, + // DebugLoc::None, + // |bcx, _| Callee { + // bcx: bcx, + // data: CalleeData::Fn(callee.llval), + // ty: callee.ty, + // }, + // args, + // Some(Dest::SaveIn(tr_dest.llval))); + } + } + } + + fn bcx(&self, bb: mir::BasicBlock) -> Block<'bcx, 'tcx> { + self.blocks[bb.index()] + } + + fn llblock(&self, bb: mir::BasicBlock) -> BasicBlockRef { + self.blocks[bb.index()].llbb + } +} diff --git a/src/librustc_trans/trans/mir/constant.rs b/src/librustc_trans/trans/mir/constant.rs new file mode 100644 index 0000000000000..8c0d8b10bfe47 --- /dev/null +++ b/src/librustc_trans/trans/mir/constant.rs @@ -0,0 +1,87 @@ +// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use middle::ty::Ty; +use rustc::middle::const_eval::ConstVal; +use rustc_mir::repr as mir; +use trans::consts::{self, TrueConst}; +use trans::common::{self, Block}; +use trans::common::{C_bool, C_bytes, C_floating_f64, C_integral, C_str_slice}; +use trans::type_of; + +use super::operand::OperandRef; +use super::MirContext; + +impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> { + pub fn trans_constval(&mut self, + bcx: Block<'bcx, 'tcx>, + cv: &ConstVal, + ty: Ty<'tcx>) + -> OperandRef<'tcx> + { + use super::operand::OperandValue::{Ref, Immediate}; + + let ccx = bcx.ccx(); + let llty = type_of::type_of(ccx, ty); + let val = match *cv { + ConstVal::Float(v) => Immediate(C_floating_f64(v, llty)), + ConstVal::Bool(v) => Immediate(C_bool(ccx, v)), + ConstVal::Int(v) => Immediate(C_integral(llty, v as u64, true)), + ConstVal::Uint(v) => Immediate(C_integral(llty, v, false)), + ConstVal::Str(ref v) => Immediate(C_str_slice(ccx, v.clone())), + ConstVal::ByteStr(ref v) => { + Immediate(consts::addr_of(ccx, + C_bytes(ccx, v), + 1, + "byte_str")) + } + + ConstVal::Struct(id) | ConstVal::Tuple(id) => { + let expr = bcx.tcx().map.expect_expr(id); + let (llval, _) = match consts::const_expr(ccx, + expr, + bcx.fcx.param_substs, + None, + TrueConst::Yes) { + Ok(v) => v, + Err(_) => panic!("constant eval failure"), + }; + if common::type_is_immediate(bcx.ccx(), ty) { + Immediate(llval) + } else { + Ref(llval) + } + } + ConstVal::Function(_) => { + unimplemented!() + } + }; + OperandRef { + ty: ty, + val: val + } + } + + pub fn trans_constant(&mut self, + bcx: Block<'bcx, 'tcx>, + constant: &mir::Constant<'tcx>) + -> OperandRef<'tcx> + { + let constant_ty = bcx.monomorphize(&constant.ty); + match constant.literal { + mir::Literal::Item { .. } => { + unimplemented!() + } + mir::Literal::Value { ref value } => { + self.trans_constval(bcx, value, constant_ty) + } + } + } +} diff --git a/src/librustc_trans/trans/mir/lvalue.rs b/src/librustc_trans/trans/mir/lvalue.rs new file mode 100644 index 0000000000000..ff80451d2b166 --- /dev/null +++ b/src/librustc_trans/trans/mir/lvalue.rs @@ -0,0 +1,182 @@ +// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use llvm::ValueRef; +use rustc::middle::ty::{self, Ty}; +use rustc_mir::repr as mir; +use rustc_mir::tcx::LvalueTy; +use trans::adt; +use trans::base; +use trans::build; +use trans::common::{self, Block}; +use trans::debuginfo::DebugLoc; +use trans::machine; + +use std::ptr; + +use super::{MirContext, TempRef}; + +#[derive(Copy, Clone)] +pub struct LvalueRef<'tcx> { + /// Pointer to the contents of the lvalue + pub llval: ValueRef, + + /// This lvalue's extra data if it is unsized, or null + pub llextra: ValueRef, + + /// Monomorphized type of this lvalue, including variant information + pub ty: LvalueTy<'tcx>, +} + +impl<'tcx> LvalueRef<'tcx> { + pub fn new_sized(llval: ValueRef, lvalue_ty: LvalueTy<'tcx>) -> LvalueRef<'tcx> { + LvalueRef { llval: llval, llextra: ptr::null_mut(), ty: lvalue_ty } + } + + pub fn alloca<'bcx>(bcx: Block<'bcx, 'tcx>, + ty: Ty<'tcx>, + name: &str) + -> LvalueRef<'tcx> + { + let lltemp = base::alloc_ty(bcx, ty, name); + LvalueRef::new_sized(lltemp, LvalueTy::from_ty(ty)) + } +} + +impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> { + pub fn lvalue_len(&mut self, + bcx: Block<'bcx, 'tcx>, + lvalue: LvalueRef<'tcx>) + -> ValueRef { + match lvalue.ty.to_ty(bcx.tcx()).sty { + ty::TyArray(_, n) => common::C_uint(bcx.ccx(), n), + ty::TySlice(_) | ty::TyStr => { + assert!(lvalue.llextra != ptr::null_mut()); + lvalue.llextra + } + _ => bcx.sess().bug("unexpected type in get_base_and_len"), + } + } + + pub fn trans_lvalue(&mut self, + bcx: Block<'bcx, 'tcx>, + lvalue: &mir::Lvalue<'tcx>) + -> LvalueRef<'tcx> { + debug!("trans_lvalue(lvalue={:?})", lvalue); + + let fcx = bcx.fcx; + let ccx = fcx.ccx; + let tcx = bcx.tcx(); + match *lvalue { + mir::Lvalue::Var(index) => self.vars[index as usize], + mir::Lvalue::Temp(index) => match self.temps[index as usize] { + TempRef::Lvalue(lvalue) => + lvalue, + TempRef::Operand(..) => + tcx.sess.bug(&format!("using operand temp {:?} as lvalue", lvalue)), + }, + mir::Lvalue::Arg(index) => self.args[index as usize], + mir::Lvalue::Static(def_id) => { + let const_ty = self.mir.lvalue_ty(tcx, lvalue); + LvalueRef::new_sized( + common::get_static_val(ccx, def_id, const_ty.to_ty(tcx)), + const_ty) + }, + mir::Lvalue::ReturnPointer => { + let return_ty = bcx.monomorphize(&self.mir.return_ty); + let llval = fcx.get_ret_slot(bcx, return_ty, "return"); + LvalueRef::new_sized(llval, LvalueTy::from_ty(return_ty.unwrap())) + } + mir::Lvalue::Projection(ref projection) => { + let tr_base = self.trans_lvalue(bcx, &projection.base); + let projected_ty = tr_base.ty.projection_ty(tcx, &projection.elem); + let (llprojected, llextra) = match projection.elem { + mir::ProjectionElem::Deref => { + let base_ty = tr_base.ty.to_ty(tcx); + if common::type_is_sized(tcx, projected_ty.to_ty(tcx)) { + (base::load_ty(bcx, tr_base.llval, base_ty), + ptr::null_mut()) + } else { + base::load_fat_ptr(bcx, tr_base.llval, base_ty) + } + } + mir::ProjectionElem::Field(ref field) => { + let base_ty = tr_base.ty.to_ty(tcx); + let base_repr = adt::represent_type(ccx, base_ty); + let discr = match tr_base.ty { + LvalueTy::Ty { .. } => 0, + LvalueTy::Downcast { adt_def: _, substs: _, variant_index: v } => v, + }; + let discr = discr as u64; + (adt::trans_field_ptr(bcx, &base_repr, tr_base.llval, discr, field.index()), + if common::type_is_sized(tcx, projected_ty.to_ty(tcx)) { + ptr::null_mut() + } else { + tr_base.llextra + }) + } + mir::ProjectionElem::Index(ref index) => { + let index = self.trans_operand(bcx, index); + let llindex = self.prepare_index(bcx, index.immediate()); + (build::InBoundsGEP(bcx, tr_base.llval, &[llindex]), + ptr::null_mut()) + } + mir::ProjectionElem::ConstantIndex { offset, + from_end: false, + min_length: _ } => { + let lloffset = common::C_u32(bcx.ccx(), offset); + let llindex = self.prepare_index(bcx, lloffset); + (build::InBoundsGEP(bcx, tr_base.llval, &[llindex]), + ptr::null_mut()) + } + mir::ProjectionElem::ConstantIndex { offset, + from_end: true, + min_length: _ } => { + let lloffset = common::C_u32(bcx.ccx(), offset); + let lllen = self.lvalue_len(bcx, tr_base); + let llindex = build::Sub(bcx, lllen, lloffset, DebugLoc::None); + let llindex = self.prepare_index(bcx, llindex); + (build::InBoundsGEP(bcx, tr_base.llval, &[llindex]), + ptr::null_mut()) + } + mir::ProjectionElem::Downcast(..) => { + (tr_base.llval, tr_base.llextra) + } + }; + LvalueRef { + llval: llprojected, + llextra: llextra, + ty: projected_ty, + } + } + } + } + + /// Adjust the bitwidth of an index since LLVM is less forgiving + /// than we are. + /// + /// nmatsakis: is this still necessary? Not sure. + fn prepare_index(&mut self, + bcx: Block<'bcx, 'tcx>, + llindex: ValueRef) + -> ValueRef + { + let ccx = bcx.ccx(); + let index_size = machine::llbitsize_of_real(bcx.ccx(), common::val_ty(llindex)); + let int_size = machine::llbitsize_of_real(bcx.ccx(), ccx.int_type()); + if index_size < int_size { + build::ZExt(bcx, llindex, ccx.int_type()) + } else if index_size > int_size { + build::Trunc(bcx, llindex, ccx.int_type()) + } else { + llindex + } + } +} diff --git a/src/librustc_trans/trans/mir/mod.rs b/src/librustc_trans/trans/mir/mod.rs new file mode 100644 index 0000000000000..c8eef7ff4487d --- /dev/null +++ b/src/librustc_trans/trans/mir/mod.rs @@ -0,0 +1,194 @@ +// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use libc::c_uint; +use llvm::{self, ValueRef}; +use rustc_mir::repr as mir; +use rustc_mir::tcx::LvalueTy; +use trans::base; +use trans::build; +use trans::common::{self, Block}; +use trans::debuginfo::DebugLoc; +use trans::expr; +use trans::type_of; + +use self::lvalue::LvalueRef; +use self::operand::OperandRef; + +// FIXME DebugLoc is always None right now + +/// Master context for translating MIR. +pub struct MirContext<'bcx, 'tcx:'bcx> { + mir: &'bcx mir::Mir<'tcx>, + + /// When unwinding is initiated, we have to store this personality + /// value somewhere so that we can load it and re-use it in the + /// resume instruction. The personality is (afaik) some kind of + /// value used for C++ unwinding, which must filter by type: we + /// don't really care about it very much. Anyway, this value + /// contains an alloca into which the personality is stored and + /// then later loaded when generating the DIVERGE_BLOCK. + llpersonalityslot: Option, + + /// A `Block` for each MIR `BasicBlock` + blocks: Vec>, + + /// An LLVM alloca for each MIR `VarDecl` + vars: Vec>, + + /// The location where each MIR `TempDecl` is stored. This is + /// usually an `LvalueRef` representing an alloca, but not always: + /// sometimes we can skip the alloca and just store the value + /// directly using an `OperandRef`, which makes for tighter LLVM + /// IR. The conditions for using an `OperandRef` are as follows: + /// + /// - the type of the temporary must be judged "immediate" by `type_is_immediate` + /// - the operand must never be referenced indirectly + /// - we should not take its address using the `&` operator + /// - nor should it appear in an lvalue path like `tmp.a` + /// - the operand must be defined by an rvalue that can generate immediate + /// values + /// + /// Avoiding allocs can also be important for certain intrinsics, + /// notably `expect`. + temps: Vec>, + + /// The arguments to the function; as args are lvalues, these are + /// always indirect, though we try to avoid creating an alloca + /// when we can (and just reuse the pointer the caller provided). + args: Vec>, +} + +enum TempRef<'tcx> { + Lvalue(LvalueRef<'tcx>), + Operand(Option>), +} + +/////////////////////////////////////////////////////////////////////////// + +pub fn trans_mir<'bcx, 'tcx>(bcx: Block<'bcx, 'tcx>) { + let fcx = bcx.fcx; + let mir = bcx.mir(); + + let mir_blocks = bcx.mir().all_basic_blocks(); + + // Analyze the temps to determine which must be lvalues + // FIXME + let lvalue_temps = analyze::lvalue_temps(bcx, mir); + + // Allocate variable and temp allocas + let vars = mir.var_decls.iter() + .map(|decl| (bcx.monomorphize(&decl.ty), decl.name)) + .map(|(mty, name)| LvalueRef::alloca(bcx, mty, &name.as_str())) + .collect(); + let temps = mir.temp_decls.iter() + .map(|decl| bcx.monomorphize(&decl.ty)) + .enumerate() + .map(|(i, mty)| if lvalue_temps.contains(&i) { + TempRef::Lvalue(LvalueRef::alloca(bcx, + mty, + &format!("temp{:?}", i))) + } else { + // If this is an immediate temp, we do not create an + // alloca in advance. Instead we wait until we see the + // definition and update the operand there. + TempRef::Operand(None) + }) + .collect(); + let args = arg_value_refs(bcx, mir); + + // Allocate a `Block` for every basic block + let block_bcxs: Vec> = + mir_blocks.iter() + .map(|&bb| fcx.new_block(false, &format!("{:?}", bb), None)) + .collect(); + + // Branch to the START block + let start_bcx = block_bcxs[mir::START_BLOCK.index()]; + build::Br(bcx, start_bcx.llbb, DebugLoc::None); + + let mut mircx = MirContext { + mir: mir, + llpersonalityslot: None, + blocks: block_bcxs, + vars: vars, + temps: temps, + args: args, + }; + + // Translate the body of each block + for &bb in &mir_blocks { + if bb != mir::DIVERGE_BLOCK { + mircx.trans_block(bb); + } + } + + // Total hack: translate DIVERGE_BLOCK last. This is so that any + // panics which the fn may do can initialize the + // `llpersonalityslot` cell. We don't do this up front because the + // LLVM type of it is (frankly) annoying to compute. + mircx.trans_block(mir::DIVERGE_BLOCK); +} + +/// Produce, for each argument, a `ValueRef` pointing at the +/// argument's value. As arguments are lvalues, these are always +/// indirect. +fn arg_value_refs<'bcx, 'tcx>(bcx: Block<'bcx, 'tcx>, + mir: &mir::Mir<'tcx>) + -> Vec> { + // FIXME tupled_args? I think I'd rather that mapping is done in MIR land though + let fcx = bcx.fcx; + let tcx = bcx.tcx(); + let mut idx = fcx.arg_offset() as c_uint; + mir.arg_decls + .iter() + .enumerate() + .map(|(arg_index, arg_decl)| { + let arg_ty = bcx.monomorphize(&arg_decl.ty); + let llval = if type_of::arg_is_indirect(bcx.ccx(), arg_ty) { + // Don't copy an indirect argument to an alloca, the caller + // already put it in a temporary alloca and gave it up, unless + // we emit extra-debug-info, which requires local allocas :(. + // FIXME: lifetimes, debug info + let llarg = llvm::get_param(fcx.llfn, idx); + idx += 1; + llarg + } else if common::type_is_fat_ptr(tcx, arg_ty) { + // we pass fat pointers as two words, but we want to + // represent them internally as a pointer to two words, + // so make an alloca to store them in. + let lldata = llvm::get_param(fcx.llfn, idx); + let llextra = llvm::get_param(fcx.llfn, idx + 1); + idx += 2; + let lltemp = base::alloc_ty(bcx, arg_ty, &format!("arg{}", arg_index)); + build::Store(bcx, lldata, expr::get_dataptr(bcx, lltemp)); + build::Store(bcx, llextra, expr::get_meta(bcx, lltemp)); + lltemp + } else { + // otherwise, arg is passed by value, so make a + // temporary and store it there + let llarg = llvm::get_param(fcx.llfn, idx); + idx += 1; + let lltemp = base::alloc_ty(bcx, arg_ty, &format!("arg{}", arg_index)); + base::store_ty(bcx, llarg, lltemp, arg_ty); + lltemp + }; + LvalueRef::new_sized(llval, LvalueTy::from_ty(arg_ty)) + }) + .collect() +} + +mod analyze; +mod block; +mod constant; +mod lvalue; +mod rvalue; +mod operand; +mod statement; diff --git a/src/librustc_trans/trans/mir/operand.rs b/src/librustc_trans/trans/mir/operand.rs new file mode 100644 index 0000000000000..63abdfe2dd917 --- /dev/null +++ b/src/librustc_trans/trans/mir/operand.rs @@ -0,0 +1,167 @@ +// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use llvm::ValueRef; +use rustc::middle::ty::Ty; +use rustc_mir::repr as mir; +use trans::base; +use trans::common::{self, Block}; +use trans::datum; + +use super::{MirContext, TempRef}; + +/// The representation of a Rust value. The enum variant is in fact +/// uniquely determined by the value's type, but is kept as a +/// safety check. +#[derive(Copy, Clone)] +pub enum OperandValue { + /// A reference to the actual operand. The data is guaranteed + /// to be valid for the operand's lifetime. + Ref(ValueRef), + /// A single LLVM value. + Immediate(ValueRef), + /// A fat pointer. The first ValueRef is the data and the second + /// is the extra. + FatPtr(ValueRef, ValueRef) +} + +/// An `OperandRef` is an "SSA" reference to a Rust value, along with +/// its type. +/// +/// NOTE: unless you know a value's type exactly, you should not +/// generate LLVM opcodes acting on it and instead act via methods, +/// to avoid nasty edge cases. In particular, using `build::Store` +/// directly is sure to cause problems - use `store_operand` instead. +#[derive(Copy, Clone)] +pub struct OperandRef<'tcx> { + // The value. + pub val: OperandValue, + + // The type of value being returned. + pub ty: Ty<'tcx> +} + +impl<'tcx> OperandRef<'tcx> { + /// Asserts that this operand refers to a scalar and returns + /// a reference to its value. + pub fn immediate(self) -> ValueRef { + match self.val { + OperandValue::Immediate(s) => s, + _ => unreachable!() + } + } + + pub fn repr<'bcx>(self, bcx: Block<'bcx, 'tcx>) -> String { + match self.val { + OperandValue::Ref(r) => { + format!("OperandRef(Ref({}) @ {:?})", + bcx.val_to_string(r), self.ty) + } + OperandValue::Immediate(i) => { + format!("OperandRef(Immediate({}) @ {:?})", + bcx.val_to_string(i), self.ty) + } + OperandValue::FatPtr(a, d) => { + format!("OperandRef(FatPtr({}, {}) @ {:?})", + bcx.val_to_string(a), + bcx.val_to_string(d), + self.ty) + } + } + } +} + +impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> { + pub fn trans_operand(&mut self, + bcx: Block<'bcx, 'tcx>, + operand: &mir::Operand<'tcx>) + -> OperandRef<'tcx> + { + debug!("trans_operand(operand={:?})", operand); + + match *operand { + mir::Operand::Consume(ref lvalue) => { + // watch out for temporaries that do not have an + // alloca; they are handled somewhat differently + if let &mir::Lvalue::Temp(index) = lvalue { + match self.temps[index as usize] { + TempRef::Operand(Some(o)) => { + return o; + } + TempRef::Operand(None) => { + bcx.tcx().sess.bug( + &format!("use of {:?} before def", lvalue)); + } + TempRef::Lvalue(..) => { + // use path below + } + } + } + + // for most lvalues, to consume them we just load them + // out from their home + let tr_lvalue = self.trans_lvalue(bcx, lvalue); + let ty = tr_lvalue.ty.to_ty(bcx.tcx()); + debug!("trans_operand: tr_lvalue={} @ {:?}", + bcx.val_to_string(tr_lvalue.llval), + ty); + let val = match datum::appropriate_rvalue_mode(bcx.ccx(), ty) { + datum::ByValue => { + OperandValue::Immediate(base::load_ty(bcx, tr_lvalue.llval, ty)) + } + datum::ByRef if common::type_is_fat_ptr(bcx.tcx(), ty) => { + let (lldata, llextra) = base::load_fat_ptr(bcx, tr_lvalue.llval, ty); + OperandValue::FatPtr(lldata, llextra) + } + datum::ByRef => OperandValue::Ref(tr_lvalue.llval) + }; + OperandRef { + val: val, + ty: ty + } + } + + mir::Operand::Constant(ref constant) => { + self.trans_constant(bcx, constant) + } + } + } + + pub fn trans_operand_into(&mut self, + bcx: Block<'bcx, 'tcx>, + lldest: ValueRef, + operand: &mir::Operand<'tcx>) + { + debug!("trans_operand_into(lldest={}, operand={:?})", + bcx.val_to_string(lldest), + operand); + + // FIXME: consider not copying constants through the + // stack. + + let o = self.trans_operand(bcx, operand); + self.store_operand(bcx, lldest, o); + } + + pub fn store_operand(&mut self, + bcx: Block<'bcx, 'tcx>, + lldest: ValueRef, + operand: OperandRef<'tcx>) + { + debug!("store_operand: operand={}", operand.repr(bcx)); + match operand.val { + OperandValue::Ref(r) => base::memcpy_ty(bcx, lldest, r, operand.ty), + OperandValue::Immediate(s) => base::store_ty(bcx, s, lldest, operand.ty), + OperandValue::FatPtr(data, extra) => { + base::store_fat_ptr(bcx, data, extra, lldest, operand.ty); + } + } + } +} diff --git a/src/librustc_trans/trans/mir/rvalue.rs b/src/librustc_trans/trans/mir/rvalue.rs new file mode 100644 index 0000000000000..cce71b2570263 --- /dev/null +++ b/src/librustc_trans/trans/mir/rvalue.rs @@ -0,0 +1,421 @@ +// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use llvm::ValueRef; +use rustc::middle::ty::{self, Ty}; +use rustc_mir::repr as mir; + +use trans::asm; +use trans::base; +use trans::build; +use trans::common::{self, Block, Result}; +use trans::debuginfo::DebugLoc; +use trans::declare; +use trans::expr; +use trans::machine; +use trans::type_::Type; +use trans::type_of; +use trans::tvec; + +use super::MirContext; +use super::operand::{OperandRef, OperandValue}; + +impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> { + pub fn trans_rvalue(&mut self, + bcx: Block<'bcx, 'tcx>, + lldest: ValueRef, + rvalue: &mir::Rvalue<'tcx>) + -> Block<'bcx, 'tcx> + { + debug!("trans_rvalue(lldest={}, rvalue={:?})", + bcx.val_to_string(lldest), + rvalue); + + match *rvalue { + mir::Rvalue::Use(ref operand) => { + self.trans_operand_into(bcx, lldest, operand); + bcx + } + + mir::Rvalue::Cast(mir::CastKind::Unsize, ref operand, cast_ty) => { + if common::type_is_fat_ptr(bcx.tcx(), cast_ty) { + // into-coerce of a thin pointer to a fat pointer - just + // use the operand path. + let (bcx, temp) = self.trans_rvalue_operand(bcx, rvalue); + self.store_operand(bcx, lldest, temp); + return bcx; + } + + // Unsize of a nontrivial struct. I would prefer for + // this to be eliminated by MIR translation, but + // `CoerceUnsized` can be passed by a where-clause, + // so the (generic) MIR may not be able to expand it. + let operand = self.trans_operand(bcx, operand); + match operand.val { + OperandValue::FatPtr(..) => unreachable!(), + OperandValue::Immediate(llval) => { + // unsize from an immediate structure. We don't + // really need a temporary alloca here, but + // avoiding it would require us to have + // `coerce_unsized_into` use extractvalue to + // index into the struct, and this case isn't + // important enough for it. + debug!("trans_rvalue: creating ugly alloca"); + let lltemp = base::alloc_ty(bcx, operand.ty, "__unsize_temp"); + base::store_ty(bcx, llval, lltemp, operand.ty); + base::coerce_unsized_into(bcx, + lltemp, operand.ty, + lldest, cast_ty); + } + OperandValue::Ref(llref) => { + base::coerce_unsized_into(bcx, + llref, operand.ty, + lldest, cast_ty); + } + } + bcx + } + + mir::Rvalue::Repeat(ref elem, ref count) => { + let elem = self.trans_operand(bcx, elem); + let size = self.trans_constant(bcx, count).immediate(); + let base = expr::get_dataptr(bcx, lldest); + tvec::iter_vec_raw(bcx, base, elem.ty, size, |bcx, llslot, _| { + self.store_operand(bcx, llslot, elem); + bcx + }) + } + + mir::Rvalue::Aggregate(_, ref operands) => { + for (i, operand) in operands.iter().enumerate() { + // Note: perhaps this should be StructGep, but + // note that in some cases the values here will + // not be structs but arrays. + let lldest_i = build::GEPi(bcx, lldest, &[0, i]); + self.trans_operand_into(bcx, lldest_i, operand); + } + bcx + } + + mir::Rvalue::Slice { ref input, from_start, from_end } => { + let ccx = bcx.ccx(); + let input = self.trans_lvalue(bcx, input); + let (llbase, lllen) = tvec::get_base_and_len(bcx, + input.llval, + input.ty.to_ty(bcx.tcx())); + let llbase1 = build::GEPi(bcx, llbase, &[from_start]); + let adj = common::C_uint(ccx, from_start + from_end); + let lllen1 = build::Sub(bcx, lllen, adj, DebugLoc::None); + let lladdrdest = expr::get_dataptr(bcx, lldest); + build::Store(bcx, llbase1, lladdrdest); + let llmetadest = expr::get_meta(bcx, lldest); + build::Store(bcx, lllen1, llmetadest); + bcx + } + + mir::Rvalue::InlineAsm(inline_asm) => { + asm::trans_inline_asm(bcx, inline_asm) + } + + _ => { + assert!(rvalue_creates_operand(rvalue)); + let (bcx, temp) = self.trans_rvalue_operand(bcx, rvalue); + self.store_operand(bcx, lldest, temp); + bcx + } + } + } + + pub fn trans_rvalue_operand(&mut self, + bcx: Block<'bcx, 'tcx>, + rvalue: &mir::Rvalue<'tcx>) + -> (Block<'bcx, 'tcx>, OperandRef<'tcx>) + { + assert!(rvalue_creates_operand(rvalue), "cannot trans {:?} to operand", rvalue); + + match *rvalue { + mir::Rvalue::Use(ref operand) => { + let operand = self.trans_operand(bcx, operand); + (bcx, operand) + } + + mir::Rvalue::Cast(ref kind, ref operand, cast_ty) => { + let operand = self.trans_operand(bcx, operand); + debug!("cast operand is {}", operand.repr(bcx)); + let cast_ty = bcx.monomorphize(&cast_ty); + + let val = match *kind { + mir::CastKind::ReifyFnPointer | + mir::CastKind::UnsafeFnPointer => { + // these are no-ops at the LLVM level + operand.val + } + mir::CastKind::Unsize => { + // unsize targets other than to a fat pointer currently + // can't be operands. + assert!(common::type_is_fat_ptr(bcx.tcx(), cast_ty)); + + match operand.val { + OperandValue::FatPtr(..) => { + // unsize from a fat pointer - this is a + // "trait-object-to-supertrait" coercion, for + // example, + // &'a fmt::Debug+Send => &'a fmt::Debug, + // and is a no-op at the LLVM level + operand.val + } + OperandValue::Immediate(lldata) => { + // "standard" unsize + let (lldata, llextra) = + base::unsize_thin_ptr(bcx, lldata, + operand.ty, cast_ty); + OperandValue::FatPtr(lldata, llextra) + } + OperandValue::Ref(_) => { + bcx.sess().bug( + &format!("by-ref operand {} in trans_rvalue_operand", + operand.repr(bcx))); + } + } + } + mir::CastKind::Misc => unimplemented!() + }; + (bcx, OperandRef { + val: val, + ty: cast_ty + }) + } + + mir::Rvalue::Ref(_, bk, ref lvalue) => { + let tr_lvalue = self.trans_lvalue(bcx, lvalue); + + let ty = tr_lvalue.ty.to_ty(bcx.tcx()); + let ref_ty = bcx.tcx().mk_ref( + bcx.tcx().mk_region(ty::ReStatic), + ty::TypeAndMut { ty: ty, mutbl: bk.to_mutbl_lossy() } + ); + + // Note: lvalues are indirect, so storing the `llval` into the + // destination effectively creates a reference. + if common::type_is_sized(bcx.tcx(), ty) { + (bcx, OperandRef { + val: OperandValue::Immediate(tr_lvalue.llval), + ty: ref_ty, + }) + } else { + (bcx, OperandRef { + val: OperandValue::FatPtr(tr_lvalue.llval, + tr_lvalue.llextra), + ty: ref_ty, + }) + } + } + + mir::Rvalue::Len(ref lvalue) => { + let tr_lvalue = self.trans_lvalue(bcx, lvalue); + (bcx, OperandRef { + val: OperandValue::Immediate(self.lvalue_len(bcx, tr_lvalue)), + ty: bcx.tcx().types.usize, + }) + } + + mir::Rvalue::BinaryOp(op, ref lhs, ref rhs) => { + let lhs = self.trans_operand(bcx, lhs); + let rhs = self.trans_operand(bcx, rhs); + let llresult = if common::type_is_fat_ptr(bcx.tcx(), lhs.ty) { + match (lhs.val, rhs.val) { + (OperandValue::FatPtr(lhs_addr, lhs_extra), + OperandValue::FatPtr(rhs_addr, rhs_extra)) => { + base::compare_fat_ptrs(bcx, + lhs_addr, lhs_extra, + rhs_addr, rhs_extra, + lhs.ty, op.to_hir_binop(), + DebugLoc::None) + } + _ => unreachable!() + } + + } else { + self.trans_scalar_binop(bcx, op, + lhs.immediate(), rhs.immediate(), + lhs.ty, DebugLoc::None) + }; + (bcx, OperandRef { + val: OperandValue::Immediate(llresult), + ty: self.mir.binop_ty(bcx.tcx(), op, lhs.ty, rhs.ty), + }) + } + + mir::Rvalue::UnaryOp(op, ref operand) => { + let operand = self.trans_operand(bcx, operand); + let lloperand = operand.immediate(); + let is_float = operand.ty.is_fp(); + let debug_loc = DebugLoc::None; + let llval = match op { + mir::UnOp::Not => build::Not(bcx, lloperand, debug_loc), + mir::UnOp::Neg => if is_float { + build::FNeg(bcx, lloperand, debug_loc) + } else { + build::Neg(bcx, lloperand, debug_loc) + } + }; + (bcx, OperandRef { + val: OperandValue::Immediate(llval), + ty: operand.ty, + }) + } + + mir::Rvalue::Box(content_ty) => { + let content_ty: Ty<'tcx> = bcx.monomorphize(&content_ty); + let llty = type_of::type_of(bcx.ccx(), content_ty); + let llsize = machine::llsize_of(bcx.ccx(), llty); + let align = type_of::align_of(bcx.ccx(), content_ty); + let llalign = common::C_uint(bcx.ccx(), align); + let llty_ptr = llty.ptr_to(); + let box_ty = bcx.tcx().mk_box(content_ty); + let Result { bcx, val: llval } = base::malloc_raw_dyn(bcx, + llty_ptr, + box_ty, + llsize, + llalign, + DebugLoc::None); + (bcx, OperandRef { + val: OperandValue::Immediate(llval), + ty: box_ty, + }) + } + + mir::Rvalue::Repeat(..) | + mir::Rvalue::Aggregate(..) | + mir::Rvalue::Slice { .. } | + mir::Rvalue::InlineAsm(..) => { + bcx.tcx().sess.bug(&format!("cannot generate operand from rvalue {:?}", rvalue)); + } + } + } + + pub fn trans_scalar_binop(&mut self, + bcx: Block<'bcx, 'tcx>, + op: mir::BinOp, + lhs: ValueRef, + rhs: ValueRef, + input_ty: Ty<'tcx>, + debug_loc: DebugLoc) -> ValueRef { + let is_float = input_ty.is_fp(); + let is_signed = input_ty.is_signed(); + match op { + mir::BinOp::Add => if is_float { + build::FAdd(bcx, lhs, rhs, debug_loc) + } else { + build::Add(bcx, lhs, rhs, debug_loc) + }, + mir::BinOp::Sub => if is_float { + build::FSub(bcx, lhs, rhs, debug_loc) + } else { + build::Sub(bcx, lhs, rhs, debug_loc) + }, + mir::BinOp::Mul => if is_float { + build::FMul(bcx, lhs, rhs, debug_loc) + } else { + build::Mul(bcx, lhs, rhs, debug_loc) + }, + mir::BinOp::Div => if is_float { + build::FDiv(bcx, lhs, rhs, debug_loc) + } else if is_signed { + build::SDiv(bcx, lhs, rhs, debug_loc) + } else { + build::UDiv(bcx, lhs, rhs, debug_loc) + }, + mir::BinOp::Rem => if is_float { + // LLVM currently always lowers the `frem` instructions appropriate + // library calls typically found in libm. Notably f64 gets wired up + // to `fmod` and f32 gets wired up to `fmodf`. Inconveniently for + // us, 32-bit MSVC does not actually have a `fmodf` symbol, it's + // instead just an inline function in a header that goes up to a + // f64, uses `fmod`, and then comes back down to a f32. + // + // Although LLVM knows that `fmodf` doesn't exist on MSVC, it will + // still unconditionally lower frem instructions over 32-bit floats + // to a call to `fmodf`. To work around this we special case MSVC + // 32-bit float rem instructions and instead do the call out to + // `fmod` ourselves. + // + // Note that this is currently duplicated with src/libcore/ops.rs + // which does the same thing, and it would be nice to perhaps unify + // these two implementations one day! Also note that we call `fmod` + // for both 32 and 64-bit floats because if we emit any FRem + // instruction at all then LLVM is capable of optimizing it into a + // 32-bit FRem (which we're trying to avoid). + let tcx = bcx.tcx(); + let use_fmod = tcx.sess.target.target.options.is_like_msvc && + tcx.sess.target.target.arch == "x86"; + if use_fmod { + let f64t = Type::f64(bcx.ccx()); + let fty = Type::func(&[f64t, f64t], &f64t); + let llfn = declare::declare_cfn(bcx.ccx(), "fmod", fty, + tcx.types.f64); + if input_ty == tcx.types.f32 { + let lllhs = build::FPExt(bcx, lhs, f64t); + let llrhs = build::FPExt(bcx, rhs, f64t); + let llres = build::Call(bcx, llfn, &[lllhs, llrhs], + None, debug_loc); + build::FPTrunc(bcx, llres, Type::f32(bcx.ccx())) + } else { + build::Call(bcx, llfn, &[lhs, rhs], + None, debug_loc) + } + } else { + build::FRem(bcx, lhs, rhs, debug_loc) + } + } else if is_signed { + build::SRem(bcx, lhs, rhs, debug_loc) + } else { + build::URem(bcx, lhs, rhs, debug_loc) + }, + mir::BinOp::BitOr => build::Or(bcx, lhs, rhs, debug_loc), + mir::BinOp::BitAnd => build::And(bcx, lhs, rhs, debug_loc), + mir::BinOp::BitXor => build::Xor(bcx, lhs, rhs, debug_loc), + mir::BinOp::Shl => common::build_unchecked_lshift(bcx, + lhs, + rhs, + debug_loc), + mir::BinOp::Shr => common::build_unchecked_rshift(bcx, + input_ty, + lhs, + rhs, + debug_loc), + mir::BinOp::Eq | mir::BinOp::Lt | mir::BinOp::Gt | + mir::BinOp::Ne | mir::BinOp::Le | mir::BinOp::Ge => { + base::compare_scalar_types(bcx, lhs, rhs, input_ty, + op.to_hir_binop(), debug_loc) + } + } + } +} + +pub fn rvalue_creates_operand<'tcx>(rvalue: &mir::Rvalue<'tcx>) -> bool { + match *rvalue { + mir::Rvalue::Use(..) | // (*) + mir::Rvalue::Ref(..) | + mir::Rvalue::Len(..) | + mir::Rvalue::Cast(..) | // (*) + mir::Rvalue::BinaryOp(..) | + mir::Rvalue::UnaryOp(..) | + mir::Rvalue::Box(..) => + true, + mir::Rvalue::Repeat(..) | + mir::Rvalue::Aggregate(..) | + mir::Rvalue::Slice { .. } | + mir::Rvalue::InlineAsm(..) => + false, + } + + // (*) this is only true if the type is suitable +} diff --git a/src/librustc_trans/trans/mir/statement.rs b/src/librustc_trans/trans/mir/statement.rs new file mode 100644 index 0000000000000..95ff049836eb4 --- /dev/null +++ b/src/librustc_trans/trans/mir/statement.rs @@ -0,0 +1,70 @@ +// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use rustc::middle::ty::LvaluePreference; +use rustc_mir::repr as mir; +use trans::common::Block; +use trans::debuginfo::DebugLoc; +use trans::glue; + +use super::MirContext; +use super::TempRef; + +impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> { + pub fn trans_statement(&mut self, + bcx: Block<'bcx, 'tcx>, + statement: &mir::Statement<'tcx>) + -> Block<'bcx, 'tcx> { + debug!("trans_statement(statement={:?})", statement); + + match statement.kind { + mir::StatementKind::Assign(ref lvalue, ref rvalue) => { + match *lvalue { + mir::Lvalue::Temp(index) => { + let index = index as usize; + match self.temps[index as usize] { + TempRef::Lvalue(tr_dest) => { + self.trans_rvalue(bcx, tr_dest.llval, rvalue) + } + TempRef::Operand(None) => { + let (bcx, operand) = self.trans_rvalue_operand(bcx, rvalue); + self.temps[index] = TempRef::Operand(Some(operand)); + bcx + } + TempRef::Operand(Some(_)) => { + bcx.tcx().sess.span_bug( + statement.span, + &format!("operand {:?} already assigned", rvalue)); + } + } + } + _ => { + let tr_dest = self.trans_lvalue(bcx, lvalue); + self.trans_rvalue(bcx, tr_dest.llval, rvalue) + } + } + } + + mir::StatementKind::Drop(mir::DropKind::Deep, ref lvalue) => { + let tr_lvalue = self.trans_lvalue(bcx, lvalue); + let ty = tr_lvalue.ty.to_ty(bcx.tcx()); + glue::drop_ty(bcx, tr_lvalue.llval, ty, DebugLoc::None) + } + + mir::StatementKind::Drop(mir::DropKind::Free, ref lvalue) => { + let tr_lvalue = self.trans_lvalue(bcx, lvalue); + let ty = tr_lvalue.ty.to_ty(bcx.tcx()); + let content_ty = ty.builtin_deref(true, LvaluePreference::NoPreference); + let content_ty = content_ty.unwrap().ty; + glue::trans_exchange_free_ty(bcx, tr_lvalue.llval, content_ty, DebugLoc::None) + } + } + } +} diff --git a/src/librustc_trans/trans/mod.rs b/src/librustc_trans/trans/mod.rs index 04854501312bf..fa37b00553982 100644 --- a/src/librustc_trans/trans/mod.rs +++ b/src/librustc_trans/trans/mod.rs @@ -52,6 +52,7 @@ mod llrepr; mod machine; mod _match; mod meth; +mod mir; mod monomorphize; mod tvec; mod type_; diff --git a/src/librustc_trans/trans/type_of.rs b/src/librustc_trans/trans/type_of.rs index 1e9183f309b51..1e371a1697010 100644 --- a/src/librustc_trans/trans/type_of.rs +++ b/src/librustc_trans/trans/type_of.rs @@ -11,6 +11,7 @@ #![allow(non_camel_case_types)] use middle::def_id::DefId; +use middle::infer; use middle::subst; use trans::adt; use trans::common::*; @@ -89,7 +90,7 @@ pub fn untuple_arguments<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, pub fn type_of_rust_fn<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, llenvironment_type: Option, - sig: &ty::Binder>, + sig: &ty::FnSig<'tcx>, abi: abi::Abi) -> Type { @@ -97,16 +98,17 @@ pub fn type_of_rust_fn<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, sig, abi); - let sig = cx.tcx().erase_late_bound_regions(sig); assert!(!sig.variadic); // rust fns are never variadic let mut atys: Vec = Vec::new(); // First, munge the inputs, if this has the `rust-call` ABI. - let inputs = &if abi == abi::RustCall { - untuple_arguments(cx, &sig.inputs) + let inputs_temp; + let inputs = if abi == abi::RustCall { + inputs_temp = untuple_arguments(cx, &sig.inputs); + &inputs_temp } else { - sig.inputs + &sig.inputs }; // Arg 0: Output pointer. @@ -155,7 +157,9 @@ pub fn type_of_fn_from_ty<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, fty: Ty<'tcx>) // FIXME(#19925) once fn item types are // zero-sized, we'll need to do something here if f.abi == abi::Rust || f.abi == abi::RustCall { - type_of_rust_fn(cx, None, &f.sig, f.abi) + let sig = cx.tcx().erase_late_bound_regions(&f.sig); + let sig = infer::normalize_associated_type(cx.tcx(), &sig); + type_of_rust_fn(cx, None, &sig, f.abi) } else { foreign::lltype_for_foreign_fn(cx, fty) } diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index 694bb0e15ac79..aaaca48600661 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -25,6 +25,7 @@ use util::nodemap::FnvHashMap; use std::cmp; use std::collections::hash_map::Entry::{Occupied, Vacant}; use syntax::ast; +use syntax::ext::mtwt; use syntax::codemap::{Span, Spanned}; use syntax::ptr::P; @@ -133,7 +134,8 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, // subtyping doesn't matter here, as the value is some kind of scalar demand::eqtype(fcx, pat.span, expected, lhs_ty); } - hir::PatEnum(..) | hir::PatIdent(..) if pat_is_resolved_const(&tcx.def_map, pat) => { + hir::PatEnum(..) | hir::PatIdent(..) + if pat_is_resolved_const(&tcx.def_map.borrow(), pat) => { let const_did = tcx.def_map.borrow().get(&pat.id).unwrap().def_id(); let const_scheme = tcx.lookup_item_type(const_did); assert!(const_scheme.generics.is_empty()); @@ -149,7 +151,7 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, // is good enough. demand::suptype(fcx, pat.span, expected, const_ty); } - hir::PatIdent(bm, ref path, ref sub) if pat_is_binding(&tcx.def_map, pat) => { + hir::PatIdent(bm, ref path, ref sub) if pat_is_binding(&tcx.def_map.borrow(), pat) => { let typ = fcx.local_ty(pat.span, pat.id); match bm { hir::BindByRef(mutbl) => { @@ -178,7 +180,7 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, // if there are multiple arms, make sure they all agree on // what the type of the binding `x` ought to be - let canon_id = *pcx.map.get(&path.node.name).unwrap(); + let canon_id = *pcx.map.get(&mtwt::resolve(path.node)).unwrap(); if canon_id != pat.id { let ct = fcx.local_ty(pat.span, canon_id); demand::eqtype(fcx, pat.span, ct, typ); @@ -410,7 +412,7 @@ pub fn check_dereferencable<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, inner: &hir::Pat) -> bool { let fcx = pcx.fcx; let tcx = pcx.fcx.ccx.tcx; - if pat_is_binding(&tcx.def_map, inner) { + if pat_is_binding(&tcx.def_map.borrow(), inner) { let expected = fcx.infcx().shallow_resolve(expected); expected.builtin_deref(true, ty::NoPreference).map_or(true, |mt| match mt.ty.sty { ty::TyTrait(_) => { diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs index 0ab0f1f9c1de1..b9fec44ec4030 100644 --- a/src/librustc_typeck/check/intrinsic.rs +++ b/src/librustc_typeck/check/intrinsic.rs @@ -458,14 +458,12 @@ fn match_intrinsic_type_to_type<'tcx, 'a>( match_intrinsic_type_to_type(tcx, position, span, structural_to_nominal, inner_expected, ty) } - _ => simple_error(&format!("`{}`", t), - &format!("raw pointer")), + _ => simple_error(&format!("`{}`", t), "raw pointer"), } } Vector(ref inner_expected, ref _llvm_type, len) => { if !t.is_simd() { - simple_error(&format!("non-simd type `{}`", t), - "simd type"); + simple_error(&format!("non-simd type `{}`", t), "simd type"); return; } let t_len = t.simd_size(tcx); diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index 72131627aa5d4..d038890b9080e 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -351,7 +351,8 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { method_types); } else if num_supplied_types != num_method_types { span_err!(self.tcx().sess, self.span, E0036, - "incorrect number of type parameters given for this method"); + "incorrect number of type parameters given for this method: expected {}, found {}", + num_method_types, num_supplied_types); final_substs.types.replace( subst::FnSpace, vec![self.tcx().types.err; num_method_types]); diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index f597820639c24..5c0b35e46b13e 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -92,31 +92,39 @@ pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, // Determine if the field can be used as a function in some way let field_ty = field.ty(cx, substs); - if let Ok(fn_once_trait_did) = cx.lang_items.require(FnOnceTraitLangItem) { - let infcx = fcx.infcx(); - infcx.probe(|_| { - let fn_once_substs = Substs::new_trait(vec![infcx.next_ty_var()], - Vec::new(), - field_ty); - let trait_ref = ty::TraitRef::new(fn_once_trait_did, - cx.mk_substs(fn_once_substs)); - let poly_trait_ref = trait_ref.to_poly_trait_ref(); - let obligation = Obligation::misc(span, - fcx.body_id, - poly_trait_ref.to_predicate()); - let mut selcx = SelectionContext::new(infcx); - - if selcx.evaluate_obligation(&obligation) { - span_stored_function(); + + match field_ty.sty { + // Not all of these (e.g. unsafe fns) implement FnOnce + // so we look for these beforehand + ty::TyClosure(..) | ty::TyBareFn(..) => span_stored_function(), + // If it's not a simple function, look for things which implement FnOnce + _ => { + if let Ok(fn_once_trait_did) = + cx.lang_items.require(FnOnceTraitLangItem) { + let infcx = fcx.infcx(); + infcx.probe(|_| { + let fn_once_substs = Substs::new_trait(vec![ + infcx.next_ty_var()], + Vec::new(), + field_ty); + let trait_ref = ty::TraitRef::new(fn_once_trait_did, + cx.mk_substs(fn_once_substs)); + let poly_trait_ref = trait_ref.to_poly_trait_ref(); + let obligation = Obligation::misc(span, + fcx.body_id, + poly_trait_ref + .to_predicate()); + let mut selcx = SelectionContext::new(infcx); + + if selcx.evaluate_obligation(&obligation) { + span_stored_function(); + } else { + span_did_you_mean(); + } + }); } else { - span_did_you_mean(); + span_did_you_mean() } - }); - } else { - match field_ty.sty { - // fallback to matching a closure or function pointer - ty::TyClosure(..) | ty::TyBareFn(..) => span_stored_function(), - _ => span_did_you_mean(), } } } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index f085ce23e3f0c..cfa32bc073a1f 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -164,11 +164,6 @@ pub struct Inherited<'a, 'tcx: 'a> { tables: &'a RefCell>, - // A mapping from each fn's id to its signature, with all bound - // regions replaced with free ones. Unlike the other tables, this - // one is never copied into the tcx: it is only used by regionck. - fn_sig_map: RefCell>>>, - // When we process a call like `c()` where `c` is a closure type, // we may not have decided yet whether `c` is a `Fn`, `FnMut`, or // `FnOnce` closure. In that case, we defer full resolution of the @@ -314,7 +309,6 @@ impl<'a, 'tcx> Inherited<'a, 'tcx> { infcx: infer::new_infer_ctxt(tcx, tables, Some(param_env), true), locals: RefCell::new(NodeMap()), tables: tables, - fn_sig_map: RefCell::new(NodeMap()), deferred_call_resolutions: RefCell::new(DefIdMap()), deferred_cast_checks: RefCell::new(Vec::new()), } @@ -535,7 +529,7 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx> { // Add pattern bindings. fn visit_pat(&mut self, p: &'tcx hir::Pat) { if let hir::PatIdent(_, ref path1, _) = p.node { - if pat_util::pat_is_binding(&self.fcx.ccx.tcx.def_map, p) { + if pat_util::pat_is_binding(&self.fcx.ccx.tcx.def_map.borrow(), p) { let var_ty = self.assign(p.span, p.id, None); self.fcx.require_type_is_sized(var_ty, p.span, @@ -620,22 +614,13 @@ fn check_fn<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>, ccx: ccx }; - // Remember return type so that regionck can access it later. - let mut fn_sig_tys: Vec = - arg_tys.iter() - .cloned() - .collect(); - if let ty::FnConverging(ret_ty) = ret_ty { fcx.require_type_is_sized(ret_ty, decl.output.span(), traits::ReturnType); - fn_sig_tys.push(ret_ty); // FIXME(#25759) just take implied bounds from the arguments } - debug!("fn-sig-map: fn_id={} fn_sig_tys={:?}", - fn_id, - fn_sig_tys); + debug!("fn-sig-map: fn_id={} fn_sig={:?}", fn_id, fn_sig); - inherited.fn_sig_map.borrow_mut().insert(fn_id, fn_sig_tys); + inherited.tables.borrow_mut().liberated_fn_sigs.insert(fn_id, fn_sig.clone()); { let mut visit = GatherLocalsVisitor { fcx: &fcx, }; diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index 6e60f926b7cc9..3cdc9b559446e 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -284,19 +284,32 @@ impl<'a, 'tcx> Rcx<'a, 'tcx> { // When we enter a function, we can derive debug!("visit_fn_body(id={})", id); - let fn_sig_map = self.fcx.inh.fn_sig_map.borrow(); - let fn_sig = match fn_sig_map.get(&id) { - Some(f) => f, - None => { - self.tcx().sess.bug( - &format!("No fn-sig entry for id={}", id)); + let fn_sig = { + let fn_sig_map = &self.infcx().tables.borrow().liberated_fn_sigs; + match fn_sig_map.get(&id) { + Some(f) => f.clone(), + None => { + self.tcx().sess.bug( + &format!("No fn-sig entry for id={}", id)); + } } }; let old_region_bounds_pairs_len = self.region_bound_pairs.len(); + // Collect the types from which we create inferred bounds. + // For the return type, if diverging, substitute `bool` just + // because it will have no effect. + // + // FIXME(#25759) return types should not be implied bounds + let fn_sig_tys: Vec<_> = + fn_sig.inputs.iter() + .cloned() + .chain(Some(fn_sig.output.unwrap_or(self.tcx().types.bool))) + .collect(); + let old_body_id = self.set_body_id(body.id); - self.relate_free_regions(&fn_sig[..], body.id, span); + self.relate_free_regions(&fn_sig_tys[..], body.id, span); link_fn_args(self, self.tcx().region_maps.node_extent(body.id), &fn_decl.inputs[..]); diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index 2c18a245159cf..5b1fafe09fac9 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -43,6 +43,7 @@ pub fn resolve_type_vars_in_expr(fcx: &FnCtxt, e: &hir::Expr) { wbcx.visit_expr(e); wbcx.visit_upvar_borrow_map(); wbcx.visit_closures(); + wbcx.visit_liberated_fn_sigs(); } pub fn resolve_type_vars_in_fn(fcx: &FnCtxt, @@ -56,13 +57,14 @@ pub fn resolve_type_vars_in_fn(fcx: &FnCtxt, wbcx.visit_pat(&*arg.pat); // Privacy needs the type for the whole pattern, not just each binding - if !pat_util::pat_is_binding(&fcx.tcx().def_map, &*arg.pat) { + if !pat_util::pat_is_binding(&fcx.tcx().def_map.borrow(), &*arg.pat) { wbcx.visit_node_id(ResolvingPattern(arg.pat.span), arg.pat.id); } } wbcx.visit_upvar_borrow_map(); wbcx.visit_closures(); + wbcx.visit_liberated_fn_sigs(); } /////////////////////////////////////////////////////////////////////////// @@ -361,6 +363,13 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { } } + fn visit_liberated_fn_sigs(&self) { + for (&node_id, fn_sig) in self.fcx.inh.tables.borrow().liberated_fn_sigs.iter() { + let fn_sig = self.resolve(fn_sig, ResolvingFnSig(node_id)); + self.tcx().tables.borrow_mut().liberated_fn_sigs.insert(node_id, fn_sig.clone()); + } + } + fn resolve>(&self, t: &T, reason: ResolveReason) -> T { t.fold_with(&mut Resolver::new(self.fcx, reason)) } @@ -376,6 +385,7 @@ enum ResolveReason { ResolvingPattern(Span), ResolvingUpvar(ty::UpvarId), ResolvingClosure(DefId), + ResolvingFnSig(ast::NodeId), } impl ResolveReason { @@ -387,6 +397,9 @@ impl ResolveReason { ResolvingUpvar(upvar_id) => { tcx.expr_span(upvar_id.closure_expr_id) } + ResolvingFnSig(id) => { + tcx.map.span(id) + } ResolvingClosure(did) => { if let Some(node_id) = tcx.map.as_local_node_id(did) { tcx.expr_span(node_id) @@ -463,6 +476,16 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> { span_err!(self.tcx.sess, span, E0196, "cannot determine a type for this closure") } + + ResolvingFnSig(id) => { + // any failures here should also fail when + // resolving the patterns, closure types, or + // something else. + let span = self.reason.span(self.tcx); + self.tcx.sess.delay_span_bug( + span, + &format!("cannot resolve some aspect of fn sig for {:?}", id)); + } } } } diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 30eb468d9f805..185623a440253 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -775,31 +775,33 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) { ref impl_items) => { // Create generics from the generics specified in the impl head. debug!("convert: ast_generics={:?}", generics); + let def_id = ccx.tcx.map.local_def_id(it.id); let ty_generics = ty_generics_for_type_or_impl(ccx, generics); - let ty_predicates = ty_generic_predicates_for_type_or_impl(ccx, generics); + let mut ty_predicates = ty_generic_predicates_for_type_or_impl(ccx, generics); debug!("convert: impl_bounds={:?}", ty_predicates); let selfty = ccx.icx(&ty_predicates).to_ty(&ExplicitRscope, &**selfty); write_ty_to_tcx(tcx, it.id, selfty); - tcx.register_item_type(ccx.tcx.map.local_def_id(it.id), + tcx.register_item_type(def_id, TypeScheme { generics: ty_generics.clone(), ty: selfty }); - tcx.predicates.borrow_mut().insert(ccx.tcx.map.local_def_id(it.id), - ty_predicates.clone()); if let &Some(ref ast_trait_ref) = opt_trait_ref { tcx.impl_trait_refs.borrow_mut().insert( - ccx.tcx.map.local_def_id(it.id), + def_id, Some(astconv::instantiate_mono_trait_ref(&ccx.icx(&ty_predicates), &ExplicitRscope, ast_trait_ref, Some(selfty))) ); } else { - tcx.impl_trait_refs.borrow_mut().insert(ccx.tcx.map.local_def_id(it.id), None); + tcx.impl_trait_refs.borrow_mut().insert(def_id, None); } + enforce_impl_params_are_constrained(tcx, generics, &mut ty_predicates, def_id); + tcx.predicates.borrow_mut().insert(def_id, ty_predicates.clone()); + // If there is a trait reference, treat the methods as always public. // This is to work around some incorrect behavior in privacy checking: @@ -844,7 +846,7 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) { generics: ty_generics.clone(), ty: ty, }); - convert_associated_const(ccx, ImplContainer(ccx.tcx.map.local_def_id(it.id)), + convert_associated_const(ccx, ImplContainer(def_id), impl_item.name, impl_item.id, impl_item.vis.inherit_from(parent_visibility), ty, true /* has_value */); @@ -861,7 +863,7 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) { let typ = ccx.icx(&ty_predicates).to_ty(&ExplicitRscope, ty); - convert_associated_type(ccx, ImplContainer(ccx.tcx.map.local_def_id(it.id)), + convert_associated_type(ccx, ImplContainer(def_id), impl_item.name, impl_item.id, impl_item.vis, Some(typ)); } @@ -880,7 +882,7 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) { } }); convert_methods(ccx, - ImplContainer(ccx.tcx.map.local_def_id(it.id)), + ImplContainer(def_id), methods, selfty, &ty_generics, @@ -898,10 +900,7 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) { } } - enforce_impl_params_are_constrained(tcx, - generics, - ccx.tcx.map.local_def_id(it.id), - impl_items); + enforce_impl_lifetimes_are_constrained(tcx, generics, def_id, impl_items); }, hir::ItemTrait(_, _, _, ref trait_items) => { let trait_def = trait_def_of_item(ccx, it); @@ -2377,13 +2376,15 @@ fn check_method_self_type<'a, 'tcx, RS:RegionScope>( /// Checks that all the type parameters on an impl fn enforce_impl_params_are_constrained<'tcx>(tcx: &ty::ctxt<'tcx>, ast_generics: &hir::Generics, - impl_def_id: DefId, - impl_items: &[P]) + impl_predicates: &mut ty::GenericPredicates<'tcx>, + impl_def_id: DefId) { let impl_scheme = tcx.lookup_item_type(impl_def_id); - let impl_predicates = tcx.lookup_predicates(impl_def_id); let impl_trait_ref = tcx.impl_trait_ref(impl_def_id); + assert!(impl_predicates.predicates.is_empty_in(FnSpace)); + assert!(impl_predicates.predicates.is_empty_in(SelfSpace)); + // The trait reference is an input, so find all type parameters // reachable from there, to start (if this is an inherent impl, // then just examine the self type). @@ -2393,10 +2394,10 @@ fn enforce_impl_params_are_constrained<'tcx>(tcx: &ty::ctxt<'tcx>, input_parameters.extend(ctp::parameters_for_trait_ref(trait_ref)); } - ctp::identify_constrained_type_params(tcx, - impl_predicates.predicates.as_slice(), - impl_trait_ref, - &mut input_parameters); + ctp::setup_constraining_predicates(tcx, + impl_predicates.predicates.get_mut_slice(TypeSpace), + impl_trait_ref, + &mut input_parameters); for (index, ty_param) in ast_generics.ty_params.iter().enumerate() { let param_ty = ty::ParamTy { space: TypeSpace, @@ -2406,8 +2407,25 @@ fn enforce_impl_params_are_constrained<'tcx>(tcx: &ty::ctxt<'tcx>, report_unused_parameter(tcx, ty_param.span, "type", ¶m_ty.to_string()); } } +} +fn enforce_impl_lifetimes_are_constrained<'tcx>(tcx: &ty::ctxt<'tcx>, + ast_generics: &hir::Generics, + impl_def_id: DefId, + impl_items: &[P]) +{ // Every lifetime used in an associated type must be constrained. + let impl_scheme = tcx.lookup_item_type(impl_def_id); + let impl_predicates = tcx.lookup_predicates(impl_def_id); + let impl_trait_ref = tcx.impl_trait_ref(impl_def_id); + + let mut input_parameters: HashSet<_> = + ctp::parameters_for_type(impl_scheme.ty).into_iter().collect(); + if let Some(ref trait_ref) = impl_trait_ref { + input_parameters.extend(ctp::parameters_for_trait_ref(trait_ref)); + } + ctp::identify_constrained_type_params(tcx, + &impl_predicates.predicates.as_slice(), impl_trait_ref, &mut input_parameters); let lifetimes_in_associated_types: HashSet<_> = impl_items.iter() diff --git a/src/librustc_typeck/constrained_type_params.rs b/src/librustc_typeck/constrained_type_params.rs index 7844d71462cfc..39d5872b3dc7a 100644 --- a/src/librustc_typeck/constrained_type_params.rs +++ b/src/librustc_typeck/constrained_type_params.rs @@ -84,40 +84,92 @@ pub fn identify_constrained_type_params<'tcx>(_tcx: &ty::ctxt<'tcx>, impl_trait_ref: Option>, input_parameters: &mut HashSet) { - loop { - let num_inputs = input_parameters.len(); - - let poly_projection_predicates = // : iterator over PolyProjectionPredicate - predicates.iter() - .filter_map(|predicate| { - match *predicate { - ty::Predicate::Projection(ref data) => Some(data.clone()), - _ => None, - } - }); - - for poly_projection in poly_projection_predicates { - // Note that we can skip binder here because the impl - // trait ref never contains any late-bound regions. - let projection = poly_projection.skip_binder(); - - // Special case: watch out for some kind of sneaky attempt - // to project out an associated type defined by this very - // trait. - let unbound_trait_ref = &projection.projection_ty.trait_ref; - if Some(unbound_trait_ref.clone()) == impl_trait_ref { - continue; - } + let mut predicates = predicates.to_owned(); + setup_constraining_predicates(_tcx, &mut predicates, impl_trait_ref, input_parameters); +} + - let inputs = parameters_for_trait_ref(&projection.projection_ty.trait_ref); - let relies_only_on_inputs = inputs.iter().all(|p| input_parameters.contains(&p)); - if relies_only_on_inputs { +/// Order the predicates in `predicates` such that each parameter is +/// constrained before it is used, if that is possible, and add the +/// paramaters so constrained to `input_parameters`. For example, +/// imagine the following impl: +/// +/// impl> Trait for U +/// +/// The impl's predicates are collected from left to right. Ignoring +/// the implicit `Sized` bounds, these are +/// * T: Debug +/// * U: Iterator +/// * ::Item = T -- a desugared ProjectionPredicate +/// +/// When we, for example, try to go over the trait-reference +/// `IntoIter as Trait`, we substitute the impl parameters with fresh +/// variables and match them with the impl trait-ref, so we know that +/// `$U = IntoIter`. +/// +/// However, in order to process the `$T: Debug` predicate, we must first +/// know the value of `$T` - which is only given by processing the +/// projection. As we occasionally want to process predicates in a single +/// pass, we want the projection to come first. In fact, as projections +/// can (acyclically) depend on one another - see RFC447 for details - we +/// need to topologically sort them. +pub fn setup_constraining_predicates<'tcx>(_tcx: &ty::ctxt<'tcx>, + predicates: &mut [ty::Predicate<'tcx>], + impl_trait_ref: Option>, + input_parameters: &mut HashSet) +{ + // The canonical way of doing the needed topological sort + // would be a DFS, but getting the graph and its ownership + // right is annoying, so I am using an in-place fixed-point iteration, + // which is `O(nt)` where `t` is the depth of type-parameter constraints, + // remembering that `t` should be less than 7 in practice. + // + // Basically, I iterate over all projections and swap every + // "ready" projection to the start of the list, such that + // all of the projections before `i` are topologically sorted + // and constrain all the parameters in `input_parameters`. + // + // In the example, `input_parameters` starts by containing `U` - which + // is constrained by the trait-ref - and so on the first pass we + // observe that `::Item = T` is a "ready" projection that + // constrains `T` and swap it to front. As it is the sole projection, + // no more swaps can take place afterwards, with the result being + // * ::Item = T + // * T: Debug + // * U: Iterator + let mut i = 0; + let mut changed = true; + while changed { + changed = false; + + for j in i..predicates.len() { + + if let ty::Predicate::Projection(ref poly_projection) = predicates[j] { + // Note that we can skip binder here because the impl + // trait ref never contains any late-bound regions. + let projection = poly_projection.skip_binder(); + + // Special case: watch out for some kind of sneaky attempt + // to project out an associated type defined by this very + // trait. + let unbound_trait_ref = &projection.projection_ty.trait_ref; + if Some(unbound_trait_ref.clone()) == impl_trait_ref { + continue; + } + + let inputs = parameters_for_trait_ref(&projection.projection_ty.trait_ref); + let relies_only_on_inputs = inputs.iter().all(|p| input_parameters.contains(&p)); + if !relies_only_on_inputs { + continue; + } input_parameters.extend(parameters_for_type(projection.ty)); + } else { + continue; } - } - - if input_parameters.len() == num_inputs { - break; + // fancy control flow to bypass borrow checker + predicates.swap(i, j); + i += 1; + changed = true; } } } diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index 4f39ed43b4481..2d7178bd55c39 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -2677,6 +2677,28 @@ defined. For more information see the [opt-in builtin traits RFC](https://github .com/rust-lang/rfcs/blob/master/text/0019-opt-in-builtin-traits.md). "##, +E0321: r##" +A cross-crate opt-out trait was implemented on something which wasn't a struct +or enum type. Erroneous code example: + +``` +#![feature(optin_builtin_traits)] + +struct Foo; + +impl !Sync for Foo {} + +unsafe impl Send for &'static Foo { +// error: cross-crate traits with a default impl, like `core::marker::Send`, +// can only be implemented for a struct/enum type, not +// `&'static Foo` +``` + +Only structs and enums are permitted to impl Send, Sync, and other opt-out +trait, and the struct or enum must be local to the current crate. So, for +example, `unsafe impl Send for Rc` is not allowed. +"##, + E0322: r##" The `Sized` trait is a special trait built-in to the compiler for types with a constant size known at compile-time. This trait is automatically implemented @@ -3463,7 +3485,6 @@ register_diagnostics! { // E0246, // invalid recursive type // E0319, // trait impls for defaulted traits allowed just for structs/enums E0320, // recursive overflow during dropck - E0321, // extended coherence rules for defaulted traits violated E0328, // cannot implement Unsize explicitly E0374, // the trait `CoerceUnsized` may only be implemented for a coercion // between structures with one field being coerced, none found diff --git a/src/librustc_unicode/char.rs b/src/librustc_unicode/char.rs index 2fb15ff2ac7fe..f73cc6837e363 100644 --- a/src/librustc_unicode/char.rs +++ b/src/librustc_unicode/char.rs @@ -111,7 +111,6 @@ impl Iterator for CaseMappingIter { } } -#[stable(feature = "rust1", since = "1.0.0")] #[lang = "char"] impl char { /// Checks if a `char` is a digit in the given radix. diff --git a/src/librustc_unicode/lib.rs b/src/librustc_unicode/lib.rs index 467c974690062..79ce8aacae815 100644 --- a/src/librustc_unicode/lib.rs +++ b/src/librustc_unicode/lib.rs @@ -31,7 +31,7 @@ html_root_url = "https://doc.rust-lang.org/nightly/", html_playground_url = "https://play.rust-lang.org/", issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/", - test(no_crate_inject))] + test(no_crate_inject, attr(allow(unused_variables), deny(warnings))))] #![no_std] #![feature(core_char_ext)] diff --git a/src/librustc_unicode/u_str.rs b/src/librustc_unicode/u_str.rs index 2347cdebf2292..57d96bf43719e 100644 --- a/src/librustc_unicode/u_str.rs +++ b/src/librustc_unicode/u_str.rs @@ -190,6 +190,7 @@ impl<'a> Iterator for Utf16Items<'a> { /// /// ``` /// #![feature(unicode, decode_utf16)] +/// # #![allow(deprecated)] /// /// extern crate rustc_unicode; /// diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index dbd1106b6a138..34ddd5726d385 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2568,8 +2568,18 @@ fn resolve_type(cx: &DocContext, debug!("resolve_type({:?},{:?})", path, id); let tcx = match cx.tcx_opt() { Some(tcx) => tcx, - // If we're extracting tests, this return value doesn't matter. - None => return Primitive(Bool), + // If we're extracting tests, this return value's accuracy is not + // important, all we want is a string representation to help people + // figure out what doctests are failing. + None => { + let did = DefId::local(DefIndex::from_u32(0)); + return ResolvedPath { + path: path, + typarams: None, + did: did, + is_generic: false + }; + } }; let def = match tcx.def_map.borrow().get(&id) { Some(k) => k.full_def(), diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index ae01d6e542611..f9a138f8fd7af 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -146,7 +146,7 @@ pub fn run_core(search_paths: SearchPaths, cfgs: Vec, externs: Externs, &arenas, &name, resolve::MakeGlobMap::No, - |tcx, analysis| { + |tcx, _, analysis| { let ty::CrateAnalysis { exported_items, public_items, .. } = analysis; // Convert from a NodeId set to a DefId set since we don't always have easy access diff --git a/src/librustdoc/flock.rs b/src/librustdoc/flock.rs index 847e28d2bc510..72a5043178baf 100644 --- a/src/librustdoc/flock.rs +++ b/src/librustdoc/flock.rs @@ -121,7 +121,7 @@ mod imp { let buf = CString::new(os.as_bytes()).unwrap(); let fd = unsafe { libc::open(buf.as_ptr(), libc::O_RDWR | libc::O_CREAT, - libc::S_IRWXU) + libc::S_IRWXU as libc::c_int) }; assert!(fd > 0, "failed to open lockfile: {}", io::Error::last_os_error()); @@ -164,77 +164,55 @@ mod imp { } #[cfg(windows)] +#[allow(bad_style)] mod imp { - use libc; use std::io; use std::mem; - use std::ffi::OsStr; use std::os::windows::prelude::*; + use std::os::windows::raw::HANDLE; use std::path::Path; - use std::ptr; - - const LOCKFILE_EXCLUSIVE_LOCK: libc::DWORD = 0x00000002; + use std::fs::{File, OpenOptions}; + + type DWORD = u32; + type LPOVERLAPPED = *mut OVERLAPPED; + type BOOL = i32; + const LOCKFILE_EXCLUSIVE_LOCK: DWORD = 0x00000002; + + #[repr(C)] + struct OVERLAPPED { + Internal: usize, + InternalHigh: usize, + Pointer: *mut u8, + hEvent: *mut u8, + } - #[allow(non_snake_case)] extern "system" { - fn LockFileEx(hFile: libc::HANDLE, - dwFlags: libc::DWORD, - dwReserved: libc::DWORD, - nNumberOfBytesToLockLow: libc::DWORD, - nNumberOfBytesToLockHigh: libc::DWORD, - lpOverlapped: libc::LPOVERLAPPED) -> libc::BOOL; - fn UnlockFileEx(hFile: libc::HANDLE, - dwReserved: libc::DWORD, - nNumberOfBytesToLockLow: libc::DWORD, - nNumberOfBytesToLockHigh: libc::DWORD, - lpOverlapped: libc::LPOVERLAPPED) -> libc::BOOL; + fn LockFileEx(hFile: HANDLE, + dwFlags: DWORD, + dwReserved: DWORD, + nNumberOfBytesToLockLow: DWORD, + nNumberOfBytesToLockHigh: DWORD, + lpOverlapped: LPOVERLAPPED) -> BOOL; } pub struct Lock { - handle: libc::HANDLE, + _file: File, } impl Lock { pub fn new(p: &Path) -> Lock { - let os: &OsStr = p.as_ref(); - let mut p_16: Vec<_> = os.encode_wide().collect(); - p_16.push(0); - let handle = unsafe { - libc::CreateFileW(p_16.as_ptr(), - libc::FILE_GENERIC_READ | - libc::FILE_GENERIC_WRITE, - libc::FILE_SHARE_READ | - libc::FILE_SHARE_DELETE | - libc::FILE_SHARE_WRITE, - ptr::null_mut(), - libc::CREATE_ALWAYS, - libc::FILE_ATTRIBUTE_NORMAL, - ptr::null_mut()) - }; - if handle == libc::INVALID_HANDLE_VALUE { - panic!("create file error: {}", io::Error::last_os_error()); - } - let mut overlapped: libc::OVERLAPPED = unsafe { mem::zeroed() }; + let f = OpenOptions::new().read(true).write(true).create(true) + .open(p).unwrap(); let ret = unsafe { - LockFileEx(handle, LOCKFILE_EXCLUSIVE_LOCK, 0, 100, 0, + let mut overlapped: OVERLAPPED = mem::zeroed(); + LockFileEx(f.as_raw_handle(), LOCKFILE_EXCLUSIVE_LOCK, 0, 100, 0, &mut overlapped) }; if ret == 0 { let err = io::Error::last_os_error(); - unsafe { libc::CloseHandle(handle); } panic!("could not lock `{}`: {}", p.display(), err); } - Lock { handle: handle } - } - } - - impl Drop for Lock { - fn drop(&mut self) { - let mut overlapped: libc::OVERLAPPED = unsafe { mem::zeroed() }; - unsafe { - UnlockFileEx(self.handle, 0, 100, 0, &mut overlapped); - libc::CloseHandle(self.handle); - } + Lock { _file: f } } } } diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index 5a6d761683224..8844ed82bb5e2 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -101,6 +101,10 @@ if (document.activeElement.tagName == "INPUT") return; + // Don't interfere with browser shortcuts + if (ev.ctrlKey || ev.altKey || ev.metaKey) + return; + switch (getVirtualKey(ev)) { case "Escape": if (!$("#help").hasClass("hidden")) { diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index cbaff95dfddd7..1ea30a8763e40 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -422,22 +422,59 @@ impl Collector { impl DocFolder for Collector { fn fold_item(&mut self, item: clean::Item) -> Option { - let pushed = match item.name { - Some(ref name) if name.is_empty() => false, - Some(ref name) => { self.names.push(name.to_string()); true } - None => false + let current_name = match item.name { + Some(ref name) if !name.is_empty() => Some(name.clone()), + _ => typename_if_impl(&item) }; - match item.doc_value() { - Some(doc) => { - self.cnt = 0; - markdown::find_testable_code(doc, &mut *self); - } - None => {} + + let pushed = if let Some(name) = current_name { + self.names.push(name); + true + } else { + false + }; + + if let Some(doc) = item.doc_value() { + self.cnt = 0; + markdown::find_testable_code(doc, &mut *self); } + let ret = self.fold_item_recur(item); if pushed { self.names.pop(); } + return ret; + + // FIXME: it would be better to not have the escaped version in the first place + fn unescape_for_testname(mut s: String) -> String { + // for refs `&foo` + if s.contains("&") { + s = s.replace("&", "&"); + + // `::&'a mut Foo::` looks weird, let's make it `::<&'a mut Foo>`:: + if let Some('&') = s.chars().nth(0) { + s = format!("<{}>", s); + } + } + + // either `<..>` or `->` + if s.contains(">") { + s.replace(">", ">") + .replace("<", "<") + } else { + s + } + } + + fn typename_if_impl(item: &clean::Item) -> Option { + if let clean::ItemEnum::ImplItem(ref impl_) = item.inner { + let path = impl_.for_.to_string(); + let unescaped_path = unescape_for_testname(path); + Some(unescaped_path) + } else { + None + } + } } } diff --git a/src/libserialize/json.rs b/src/libserialize/json.rs index 452feed3cdb4e..9e1e3c6a55805 100644 --- a/src/libserialize/json.rs +++ b/src/libserialize/json.rs @@ -77,8 +77,9 @@ //! serialization API, using the derived serialization code. //! //! ```rust -//! extern crate serialize; -//! use serialize::json; +//! # #![feature(rustc_private)] +//! extern crate serialize as rustc_serialize; // for the deriving below +//! use rustc_serialize::json; //! //! // Automatically generate `Decodable` and `Encodable` trait implementations //! #[derive(RustcDecodable, RustcEncodable)] @@ -111,6 +112,7 @@ //! ### Simple example of `ToJson` usage //! //! ```rust +//! # #![feature(rustc_private)] //! extern crate serialize; //! use serialize::json::{self, ToJson, Json}; //! @@ -150,6 +152,7 @@ //! ### Verbose example of `ToJson` usage //! //! ```rust +//! # #![feature(rustc_private)] //! extern crate serialize; //! use std::collections::BTreeMap; //! use serialize::json::{self, Json, ToJson}; @@ -185,7 +188,7 @@ //! let json_str: String = json_obj.to_string(); //! //! // Deserialize like before -//! let decoded: TestStruct = json::decode(json_str)).unwrap(); +//! let decoded: TestStruct = json::decode(&json_str).unwrap(); //! } //! ``` diff --git a/src/libserialize/lib.rs b/src/libserialize/lib.rs index 5b7bec41723cd..4a766f1453137 100644 --- a/src/libserialize/lib.rs +++ b/src/libserialize/lib.rs @@ -26,7 +26,8 @@ Core encoding and decoding interfaces. #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "https://doc.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/nightly/", - html_playground_url = "https://play.rust-lang.org/")] + html_playground_url = "https://play.rust-lang.org/", + test(attr(allow(unused_variables), deny(warnings))))] #![feature(box_syntax)] #![feature(collections)] diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index 7c6add80337c0..b8482b3a2dc64 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -601,6 +601,9 @@ impl HashMap /// Returns the number of elements the map can hold without reallocating. /// + /// This number is a lower bound; the `HashMap` might be able to hold + /// more, but is guaranteed to be able to hold at least this many. + /// /// # Examples /// /// ``` @@ -1105,8 +1108,9 @@ impl HashMap /// /// If the map did not have this key present, `None` is returned. /// - /// If the map did have this key present, that value is returned, and the - /// entry is not updated. See the [module-level documentation] for more. + /// If the map did have this key present, the key is not updated, the + /// value is updated and the old value is returned. + /// See the [module-level documentation] for more. /// /// [module-level documentation]: index.html#insert-and-complex-keys /// diff --git a/src/libstd/collections/hash/set.rs b/src/libstd/collections/hash/set.rs index 1f6b349399610..bb7a96bfb4bd6 100644 --- a/src/libstd/collections/hash/set.rs +++ b/src/libstd/collections/hash/set.rs @@ -544,10 +544,7 @@ impl HashSet /// /// If the set did not have a value present, `true` is returned. /// - /// If the set did have this key present, that value is returned, and the - /// entry is not updated. See the [module-level documentation] for more. - /// - /// [module-level documentation]: index.html#insert-and-complex-keys + /// If the set did have this key present, `false` is returned. /// /// # Examples /// @@ -675,7 +672,6 @@ impl Default for HashSet where T: Eq + Hash, S: HashState + Default, { - #[stable(feature = "rust1", since = "1.0.0")] fn default() -> HashSet { HashSet::with_hash_state(Default::default()) } diff --git a/src/libstd/dynamic_lib.rs b/src/libstd/dynamic_lib.rs index 8583631ef58d6..1cb48407f1069 100644 --- a/src/libstd/dynamic_lib.rs +++ b/src/libstd/dynamic_lib.rs @@ -207,11 +207,11 @@ mod dl { unsafe fn open_external(filename: &OsStr) -> *mut u8 { let s = filename.to_cstring().unwrap(); - dlopen(s.as_ptr(), LAZY) as *mut u8 + libc::dlopen(s.as_ptr(), LAZY) as *mut u8 } unsafe fn open_internal() -> *mut u8 { - dlopen(ptr::null(), LAZY) as *mut u8 + libc::dlopen(ptr::null(), LAZY) as *mut u8 } pub fn check_for_errors_in(f: F) -> Result where @@ -223,11 +223,11 @@ mod dl { // dlerror isn't thread safe, so we need to lock around this entire // sequence let _guard = LOCK.lock(); - let _old_error = dlerror(); + let _old_error = libc::dlerror(); let result = f(); - let last_error = dlerror() as *const _; + let last_error = libc::dlerror() as *const _; let ret = if ptr::null() == last_error { Ok(result) } else { @@ -241,19 +241,10 @@ mod dl { pub unsafe fn symbol(handle: *mut u8, symbol: *const libc::c_char) -> *mut u8 { - dlsym(handle as *mut libc::c_void, symbol) as *mut u8 + libc::dlsym(handle as *mut libc::c_void, symbol) as *mut u8 } pub unsafe fn close(handle: *mut u8) { - dlclose(handle as *mut libc::c_void); () - } - - extern { - fn dlopen(filename: *const libc::c_char, - flag: libc::c_int) -> *mut libc::c_void; - fn dlerror() -> *mut libc::c_char; - fn dlsym(handle: *mut libc::c_void, - symbol: *const libc::c_char) -> *mut libc::c_void; - fn dlclose(handle: *mut libc::c_void) -> libc::c_int; + libc::dlclose(handle as *mut libc::c_void); () } } @@ -263,11 +254,10 @@ mod dl { use ffi::OsStr; use libc; - use libc::consts::os::extra::ERROR_CALL_NOT_IMPLEMENTED; - use sys::os; use os::windows::prelude::*; use ptr; - use sys::c::SetThreadErrorMode; + use sys::c; + use sys::os; pub fn open(filename: Option<&OsStr>) -> Result<*mut u8, String> { // disable "dll load failed" error dialog. @@ -277,24 +267,25 @@ mod dl { let new_error_mode = 1; let mut prev_error_mode = 0; // Windows >= 7 supports thread error mode. - let result = SetThreadErrorMode(new_error_mode, &mut prev_error_mode); + let result = c::SetThreadErrorMode(new_error_mode, + &mut prev_error_mode); if result == 0 { let err = os::errno(); - if err as libc::c_int == ERROR_CALL_NOT_IMPLEMENTED { + if err == c::ERROR_CALL_NOT_IMPLEMENTED as i32 { use_thread_mode = false; // SetThreadErrorMode not found. use fallback solution: // SetErrorMode() Note that SetErrorMode is process-wide so // this can cause race condition! However, since even // Windows APIs do not care of such problem (#20650), we // just assume SetErrorMode race is not a great deal. - prev_error_mode = SetErrorMode(new_error_mode); + prev_error_mode = c::SetErrorMode(new_error_mode); } } prev_error_mode }; unsafe { - SetLastError(0); + c::SetLastError(0); } let result = match filename { @@ -302,7 +293,7 @@ mod dl { let filename_str: Vec<_> = filename.encode_wide().chain(Some(0)).collect(); let result = unsafe { - LoadLibraryW(filename_str.as_ptr() as *const libc::c_void) + c::LoadLibraryW(filename_str.as_ptr()) }; // beware: Vec/String may change errno during drop! // so we get error here. @@ -316,9 +307,10 @@ mod dl { None => { let mut handle = ptr::null_mut(); let succeeded = unsafe { - GetModuleHandleExW(0 as libc::DWORD, ptr::null(), &mut handle) + c::GetModuleHandleExW(0 as c::DWORD, ptr::null(), + &mut handle) }; - if succeeded == libc::FALSE { + if succeeded == c::FALSE { let errno = os::errno(); Err(os::error_string(errno)) } else { @@ -329,9 +321,9 @@ mod dl { unsafe { if use_thread_mode { - SetThreadErrorMode(prev_error_mode, ptr::null_mut()); + c::SetThreadErrorMode(prev_error_mode, ptr::null_mut()); } else { - SetErrorMode(prev_error_mode); + c::SetErrorMode(prev_error_mode); } } @@ -342,7 +334,7 @@ mod dl { F: FnOnce() -> T, { unsafe { - SetLastError(0); + c::SetLastError(0); let result = f(); @@ -356,22 +348,10 @@ mod dl { } pub unsafe fn symbol(handle: *mut u8, symbol: *const libc::c_char) -> *mut u8 { - GetProcAddress(handle as *mut libc::c_void, symbol) as *mut u8 + c::GetProcAddress(handle as c::HMODULE, symbol) as *mut u8 } pub unsafe fn close(handle: *mut u8) { - FreeLibrary(handle as *mut libc::c_void); () - } - - #[allow(non_snake_case)] - extern "system" { - fn SetLastError(error: libc::size_t); - fn LoadLibraryW(name: *const libc::c_void) -> *mut libc::c_void; - fn GetModuleHandleExW(dwFlags: libc::DWORD, name: *const u16, - handle: *mut *mut libc::c_void) -> libc::BOOL; - fn GetProcAddress(handle: *mut libc::c_void, - name: *const libc::c_char) -> *mut libc::c_void; - fn FreeLibrary(handle: *mut libc::c_void); - fn SetErrorMode(uMode: libc::c_uint) -> libc::c_uint; + c::FreeLibrary(handle as c::HMODULE); } } diff --git a/src/libstd/env.rs b/src/libstd/env.rs index 6ed9b85a617f8..b81b2a71ad654 100644 --- a/src/libstd/env.rs +++ b/src/libstd/env.rs @@ -23,7 +23,6 @@ use ffi::{OsStr, OsString}; use fmt; use io; use path::{Path, PathBuf}; -use sync::StaticMutex; use sys::os as os_imp; /// Returns the current working directory as a `PathBuf`. @@ -68,8 +67,6 @@ pub fn set_current_dir>(p: P) -> io::Result<()> { os_imp::chdir(p.as_ref()) } -static ENV_LOCK: StaticMutex = StaticMutex::new(); - /// An iterator over a snapshot of the environment variables of this process. /// /// This iterator is created through `std::env::vars()` and yields `(String, @@ -133,7 +130,6 @@ pub fn vars() -> Vars { /// ``` #[stable(feature = "env", since = "1.0.0")] pub fn vars_os() -> VarsOs { - let _g = ENV_LOCK.lock(); VarsOs { inner: os_imp::env() } } @@ -204,8 +200,9 @@ pub fn var_os>(key: K) -> Option { } fn _var_os(key: &OsStr) -> Option { - let _g = ENV_LOCK.lock(); - os_imp::getenv(key) + os_imp::getenv(key).unwrap_or_else(|e| { + panic!("failed to get environment variable `{:?}`: {}", key, e) + }) } /// Possible errors from the `env::var` method. @@ -281,8 +278,10 @@ pub fn set_var, V: AsRef>(k: K, v: V) { } fn _set_var(k: &OsStr, v: &OsStr) { - let _g = ENV_LOCK.lock(); - os_imp::setenv(k, v) + os_imp::setenv(k, v).unwrap_or_else(|e| { + panic!("failed to set environment variable `{:?}` to `{:?}`: {}", + k, v, e) + }) } /// Removes an environment variable from the environment of the currently running process. @@ -322,8 +321,9 @@ pub fn remove_var>(k: K) { } fn _remove_var(k: &OsStr) { - let _g = ENV_LOCK.lock(); - os_imp::unsetenv(k) + os_imp::unsetenv(k).unwrap_or_else(|e| { + panic!("failed to remove environment variable `{:?}`: {}", k, e) + }) } /// An iterator over `Path` instances for parsing an environment variable @@ -421,7 +421,9 @@ impl Error for JoinPathsError { /// # Unix /// /// Returns the value of the 'HOME' environment variable if it is set -/// and not equal to the empty string. +/// and not equal to the empty string. Otherwise, it tries to determine the +/// home directory by invoking the `getpwuid_r` function on the UID of the +/// current user. /// /// # Windows /// diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs index 89427f7851b38..42fd2321f011d 100644 --- a/src/libstd/ffi/c_str.rs +++ b/src/libstd/ffi/c_str.rs @@ -21,6 +21,7 @@ use libc; use mem; use ops::Deref; use option::Option::{self, Some, None}; +use os::raw::c_char; use result::Result::{self, Ok, Err}; use slice; use str::{self, Utf8Error}; @@ -36,23 +37,20 @@ use vec::Vec; /// /// A `CString` is created from either a byte slice or a byte vector. After /// being created, a `CString` predominately inherits all of its methods from -/// the `Deref` implementation to `[libc::c_char]`. Note that the underlying -/// array is represented as an array of `libc::c_char` as opposed to `u8`. A -/// `u8` slice can be obtained with the `as_bytes` method. Slices produced from -/// a `CString` do *not* contain the trailing nul terminator unless otherwise -/// specified. +/// the `Deref` implementation to `[c_char]`. Note that the underlying array +/// is represented as an array of `c_char` as opposed to `u8`. A `u8` slice +/// can be obtained with the `as_bytes` method. Slices produced from a `CString` +/// do *not* contain the trailing nul terminator unless otherwise specified. /// /// # Examples /// /// ```no_run -/// # #![feature(libc)] -/// # extern crate libc; /// # fn main() { /// use std::ffi::CString; -/// use libc; +/// use std::os::raw::c_char; /// /// extern { -/// fn my_printer(s: *const libc::c_char); +/// fn my_printer(s: *const c_char); /// } /// /// let c_to_print = CString::new("Hello, world!").unwrap(); @@ -83,11 +81,10 @@ pub struct CString { /// Inspecting a foreign C string /// /// ```no_run -/// # #![feature(libc)] -/// extern crate libc; /// use std::ffi::CStr; +/// use std::os::raw::c_char; /// -/// extern { fn my_string() -> *const libc::c_char; } +/// extern { fn my_string() -> *const c_char; } /// /// fn main() { /// unsafe { @@ -100,12 +97,11 @@ pub struct CString { /// Passing a Rust-originating C string /// /// ```no_run -/// # #![feature(libc)] -/// extern crate libc; /// use std::ffi::{CString, CStr}; +/// use std::os::raw::c_char; /// /// fn work(data: &CStr) { -/// extern { fn work_with(data: *const libc::c_char); } +/// extern { fn work_with(data: *const c_char); } /// /// unsafe { work_with(data.as_ptr()) } /// } @@ -119,11 +115,10 @@ pub struct CString { /// Converting a foreign C string into a Rust `String` /// /// ```no_run -/// # #![feature(libc)] -/// extern crate libc; /// use std::ffi::CStr; +/// use std::os::raw::c_char; /// -/// extern { fn my_string() -> *const libc::c_char; } +/// extern { fn my_string() -> *const c_char; } /// /// fn my_string_safe() -> String { /// unsafe { @@ -139,10 +134,10 @@ pub struct CString { #[stable(feature = "rust1", since = "1.0.0")] pub struct CStr { // FIXME: this should not be represented with a DST slice but rather with - // just a raw `libc::c_char` along with some form of marker to make + // just a raw `c_char` along with some form of marker to make // this an unsized type. Essentially `sizeof(&CStr)` should be the // same as `sizeof(&c_char)` but `CStr` should be an unsized type. - inner: [libc::c_char] + inner: [c_char] } /// An error returned from `CString::new` to indicate that a nul byte was found @@ -169,11 +164,10 @@ impl CString { /// # Examples /// /// ```no_run - /// # #![feature(libc)] - /// extern crate libc; /// use std::ffi::CString; + /// use std::os::raw::c_char; /// - /// extern { fn puts(s: *const libc::c_char); } + /// extern { fn puts(s: *const c_char); } /// /// fn main() { /// let to_print = CString::new("Hello!").unwrap(); @@ -220,7 +214,7 @@ impl CString { #[unstable(feature = "cstr_memory2", reason = "recently added", issue = "27769")] #[deprecated(since = "1.4.0", reason = "renamed to from_raw")] - pub unsafe fn from_ptr(ptr: *const libc::c_char) -> CString { + pub unsafe fn from_ptr(ptr: *const c_char) -> CString { CString::from_raw(ptr as *mut _) } @@ -230,7 +224,7 @@ impl CString { /// `into_raw`. The length of the string will be recalculated /// using the pointer. #[stable(feature = "cstr_memory", since = "1.4.0")] - pub unsafe fn from_raw(ptr: *mut libc::c_char) -> CString { + pub unsafe fn from_raw(ptr: *mut c_char) -> CString { let len = libc::strlen(ptr) + 1; // Including the NUL byte let slice = slice::from_raw_parts(ptr, len as usize); CString { inner: mem::transmute(slice) } @@ -247,7 +241,7 @@ impl CString { #[unstable(feature = "cstr_memory2", reason = "recently added", issue = "27769")] #[deprecated(since = "1.4.0", reason = "renamed to into_raw")] - pub fn into_ptr(self) -> *const libc::c_char { + pub fn into_ptr(self) -> *const c_char { self.into_raw() as *const _ } @@ -260,8 +254,8 @@ impl CString { /// /// Failure to call `from_raw` will lead to a memory leak. #[stable(feature = "cstr_memory", since = "1.4.0")] - pub fn into_raw(self) -> *mut libc::c_char { - Box::into_raw(self.inner) as *mut libc::c_char + pub fn into_raw(self) -> *mut c_char { + Box::into_raw(self.inner) as *mut c_char } /// Converts the `CString` into a `String` if it contains valid Unicode data. @@ -426,15 +420,13 @@ impl CStr { /// # Examples /// /// ```no_run - /// # #![feature(libc)] - /// # extern crate libc; /// # fn main() { /// use std::ffi::CStr; + /// use std::os::raw::c_char; /// use std::str; - /// use libc; /// /// extern { - /// fn my_string() -> *const libc::c_char; + /// fn my_string() -> *const c_char; /// } /// /// unsafe { @@ -445,7 +437,7 @@ impl CStr { /// # } /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub unsafe fn from_ptr<'a>(ptr: *const libc::c_char) -> &'a CStr { + pub unsafe fn from_ptr<'a>(ptr: *const c_char) -> &'a CStr { let len = libc::strlen(ptr); mem::transmute(slice::from_raw_parts(ptr, len as usize + 1)) } @@ -456,7 +448,7 @@ impl CStr { /// to a contiguous region of memory terminated with a 0 byte to represent /// the end of the string. #[stable(feature = "rust1", since = "1.0.0")] - pub fn as_ptr(&self) -> *const libc::c_char { + pub fn as_ptr(&self) -> *const c_char { self.inner.as_ptr() } @@ -560,14 +552,14 @@ impl ToOwned for CStr { mod tests { use prelude::v1::*; use super::*; - use libc; + use os::raw::c_char; use borrow::Cow::{Borrowed, Owned}; use hash::{SipHasher, Hash, Hasher}; #[test] fn c_to_rust() { let data = b"123\0"; - let ptr = data.as_ptr() as *const libc::c_char; + let ptr = data.as_ptr() as *const c_char; unsafe { assert_eq!(CStr::from_ptr(ptr).to_bytes(), b"123"); assert_eq!(CStr::from_ptr(ptr).to_bytes_with_nul(), b"123\0"); @@ -616,13 +608,13 @@ mod tests { #[test] fn to_str() { let data = b"123\xE2\x80\xA6\0"; - let ptr = data.as_ptr() as *const libc::c_char; + let ptr = data.as_ptr() as *const c_char; unsafe { assert_eq!(CStr::from_ptr(ptr).to_str(), Ok("123…")); assert_eq!(CStr::from_ptr(ptr).to_string_lossy(), Borrowed("123…")); } let data = b"123\xE2\0"; - let ptr = data.as_ptr() as *const libc::c_char; + let ptr = data.as_ptr() as *const c_char; unsafe { assert!(CStr::from_ptr(ptr).to_str().is_err()); assert_eq!(CStr::from_ptr(ptr).to_string_lossy(), Owned::(format!("123\u{FFFD}"))); @@ -632,7 +624,7 @@ mod tests { #[test] fn to_owned() { let data = b"123\0"; - let ptr = data.as_ptr() as *const libc::c_char; + let ptr = data.as_ptr() as *const c_char; let owned = unsafe { CStr::from_ptr(ptr).to_owned() }; assert_eq!(owned.as_bytes_with_nul(), data); @@ -641,7 +633,7 @@ mod tests { #[test] fn equal_hash() { let data = b"123\xE2\xFA\xA6\0"; - let ptr = data.as_ptr() as *const libc::c_char; + let ptr = data.as_ptr() as *const c_char; let cstr: &'static CStr = unsafe { CStr::from_ptr(ptr) }; let mut s = SipHasher::new_with_keys(0, 0); diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs index 6178f1bbb8e12..191c7dc58060a 100644 --- a/src/libstd/fs.rs +++ b/src/libstd/fs.rs @@ -677,7 +677,6 @@ impl Iterator for ReadDir { } } -#[stable(feature = "rust1", since = "1.0.0")] impl DirEntry { /// Returns the full path to the file that this entry represents. /// @@ -1212,7 +1211,8 @@ pub trait PathExt { fn read_dir(&self) -> io::Result; /// Boolean value indicator whether the underlying file exists on the local - /// filesystem. Returns false in exactly the cases where `fs::stat` fails. + /// filesystem. Returns false in exactly the cases where `fs::metadata` + /// fails. fn exists(&self) -> bool; /// Whether the underlying implementation (be it a file path, or something @@ -1732,7 +1732,7 @@ mod tests { let tmpdir = tmpdir(); let mut dirpath = tmpdir.path().to_path_buf(); - dirpath.push(&format!("test-가一ー你好")); + dirpath.push("test-가一ー你好"); check!(fs::create_dir(&dirpath)); assert!(dirpath.is_dir()); diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index ebe50a6e2b8a2..34736f810339c 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -1534,7 +1534,6 @@ pub struct Take { limit: u64, } -#[stable(feature = "rust1", since = "1.0.0")] impl Take { /// Returns the number of bytes that can be read before this instance will /// return EOF. diff --git a/src/libstd/io/stdio.rs b/src/libstd/io/stdio.rs index 31b881bebf05f..985dbdd895f84 100644 --- a/src/libstd/io/stdio.rs +++ b/src/libstd/io/stdio.rs @@ -20,7 +20,7 @@ use sync::{Arc, Mutex, MutexGuard}; use sys::stdio; use sys_common::io::{read_to_end_uninitialized}; use sys_common::remutex::{ReentrantMutex, ReentrantMutexGuard}; -use libc; +use thread::LocalKeyState; /// Stdout used by print! and println! macros thread_local! { @@ -120,9 +120,9 @@ impl io::Read for Maybe { fn handle_ebadf(r: io::Result, default: T) -> io::Result { #[cfg(windows)] - const ERR: libc::c_int = libc::ERROR_INVALID_HANDLE; + const ERR: i32 = ::sys::c::ERROR_INVALID_HANDLE as i32; #[cfg(not(windows))] - const ERR: libc::c_int = libc::EBADF; + const ERR: i32 = ::libc::EBADF as i32; match r { Err(ref e) if e.raw_os_error() == Some(ERR) => Ok(default), @@ -576,14 +576,31 @@ pub fn set_print(sink: Box) -> Option> { issue = "0")] #[doc(hidden)] pub fn _print(args: fmt::Arguments) { - let result = LOCAL_STDOUT.with(|s| { - if s.borrow_state() == BorrowState::Unused { - if let Some(w) = s.borrow_mut().as_mut() { - return w.write_fmt(args); - } + // As an implementation of the `println!` macro, we want to try our best to + // not panic wherever possible and get the output somewhere. There are + // currently two possible vectors for panics we take care of here: + // + // 1. If the TLS key for the local stdout has been destroyed, accessing it + // would cause a panic. Note that we just lump in the uninitialized case + // here for convenience, we're not trying to avoid a panic. + // 2. If the local stdout is currently in use (e.g. we're in the middle of + // already printing) then accessing again would cause a panic. + // + // If, however, the actual I/O causes an error, we do indeed panic. + let result = match LOCAL_STDOUT.state() { + LocalKeyState::Uninitialized | + LocalKeyState::Destroyed => stdout().write_fmt(args), + LocalKeyState::Valid => { + LOCAL_STDOUT.with(|s| { + if s.borrow_state() == BorrowState::Unused { + if let Some(w) = s.borrow_mut().as_mut() { + return w.write_fmt(args); + } + } + stdout().write_fmt(args) + }) } - stdout().write_fmt(args) - }); + }; if let Err(e) = result { panic!("failed printing to stdout: {}", e); } diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 9acf5795fa2c0..a0bb9449806e8 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -76,7 +76,7 @@ //! `i32`](primitive.i32.html) that lists all the methods that can be called on //! 32-bit integers (very useful), and there is a [page for the module //! `std::i32`](i32/index.html) that documents the constant values [`MIN`] and -//! [`MAX`] (rarely useful). +//! [`MAX`](i32/constant.MAX.html) (rarely useful). //! //! Note the documentation for the primitives [`str`] and [`[T]`][slice] (also //! called 'slice'). Many method calls on [`String`] and [`Vec`] are actually @@ -153,7 +153,6 @@ //! //! [I/O]: io/index.html //! [MIN]: i32/constant.MIN.html -//! [MAX]: i32/constant.MAX.html //! [TCP]: net/struct.TcpStream.html //! [The Rust Prelude]: prelude/index.html //! [UDP]: net/struct.UdpSocket.html @@ -214,13 +213,12 @@ test(no_crate_inject, attr(deny(warnings))), test(attr(allow(dead_code, deprecated, unused_variables, unused_mut))))] -// SNAP 1af31d4 -#![allow(unused_features)] -// SNAP 1af31d4 -#![allow(unused_attributes)] +#![cfg_attr(stage0, allow(unused_attributes))] +#![cfg_attr(stage0, allow(improper_ctypes))] #![feature(alloc)] #![feature(allow_internal_unstable)] +#![feature(asm)] #![feature(associated_consts)] #![feature(borrow_state)] #![feature(box_syntax)] @@ -234,49 +232,52 @@ #![feature(core_float)] #![feature(core_intrinsics)] #![feature(core_simd)] +#![feature(decode_utf16)] #![feature(drain)] +#![feature(drop_in_place)] +#![feature(dropck_parametricity)] +#![feature(float_extras)] +#![feature(float_from_str_radix)] #![feature(fnbox)] #![feature(heap_api)] #![feature(int_error_internals)] #![feature(into_cow)] #![feature(lang_items)] #![feature(libc)] -#![feature(linkage, thread_local, asm)] +#![feature(link_args)] +#![feature(linkage)] #![feature(macro_reexport)] -#![feature(slice_concat_ext)] #![feature(no_std)] #![feature(oom)] #![feature(optin_builtin_traits)] #![feature(placement_in_syntax)] #![feature(rand)] +#![feature(range_inclusive)] #![feature(raw)] #![feature(reflect_marker)] #![feature(slice_bytes)] +#![feature(slice_concat_ext)] #![feature(slice_patterns)] #![feature(staged_api)] #![feature(str_char)] #![feature(str_internals)] +#![feature(str_utf16)] +#![feature(test, rustc_private)] +#![feature(thread_local)] #![feature(unboxed_closures)] #![feature(unicode)] #![feature(unique)] -#![feature(dropck_parametricity)] #![feature(unsafe_no_drop_flag, filling_drop)] -#![feature(decode_utf16)] #![feature(unwind_attributes)] #![feature(vec_push_all)] #![feature(wrapping)] #![feature(zero_one)] -#![feature(drop_in_place)] - -#![cfg_attr(windows, feature(str_utf16))] -#![cfg_attr(test, feature(float_from_str_radix, range_inclusive, float_extras))] -#![cfg_attr(test, feature(test, rustc_private))] -#![cfg_attr(target_env = "msvc", feature(link_args))] // Don't link to std. We are std. #![no_std] #![deny(missing_docs)] +#![allow(unused_features)] // std may use features in a platform-specific way #[cfg(test)] extern crate test; #[cfg(test)] #[macro_use] extern crate log; diff --git a/src/libstd/net/addr.rs b/src/libstd/net/addr.rs index cf0ede30dcc7c..66c1ab720b60f 100644 --- a/src/libstd/net/addr.rs +++ b/src/libstd/net/addr.rs @@ -13,10 +13,10 @@ use prelude::v1::*; use fmt; use hash; use io; -use libc::{self, socklen_t, sa_family_t}; use mem; use net::{lookup_host, ntoh, hton, IpAddr, Ipv4Addr, Ipv6Addr}; use option; +use sys::net::netc as c; use sys_common::{FromInner, AsInner, IntoInner}; use vec; @@ -39,12 +39,12 @@ pub enum SocketAddr { /// An IPv4 socket address which is a (ip, port) combination. #[derive(Copy)] #[stable(feature = "rust1", since = "1.0.0")] -pub struct SocketAddrV4 { inner: libc::sockaddr_in } +pub struct SocketAddrV4 { inner: c::sockaddr_in } /// An IPv6 socket address. #[derive(Copy)] #[stable(feature = "rust1", since = "1.0.0")] -pub struct SocketAddrV6 { inner: libc::sockaddr_in6 } +pub struct SocketAddrV6 { inner: c::sockaddr_in6 } impl SocketAddr { /// Creates a new socket address from the (ip, port) pair. @@ -80,8 +80,8 @@ impl SocketAddrV4 { #[stable(feature = "rust1", since = "1.0.0")] pub fn new(ip: Ipv4Addr, port: u16) -> SocketAddrV4 { SocketAddrV4 { - inner: libc::sockaddr_in { - sin_family: libc::AF_INET as sa_family_t, + inner: c::sockaddr_in { + sin_family: c::AF_INET as c::sa_family_t, sin_port: hton(port), sin_addr: *ip.as_inner(), .. unsafe { mem::zeroed() } @@ -93,7 +93,7 @@ impl SocketAddrV4 { #[stable(feature = "rust1", since = "1.0.0")] pub fn ip(&self) -> &Ipv4Addr { unsafe { - &*(&self.inner.sin_addr as *const libc::in_addr as *const Ipv4Addr) + &*(&self.inner.sin_addr as *const c::in_addr as *const Ipv4Addr) } } @@ -109,8 +109,8 @@ impl SocketAddrV6 { pub fn new(ip: Ipv6Addr, port: u16, flowinfo: u32, scope_id: u32) -> SocketAddrV6 { SocketAddrV6 { - inner: libc::sockaddr_in6 { - sin6_family: libc::AF_INET6 as sa_family_t, + inner: c::sockaddr_in6 { + sin6_family: c::AF_INET6 as c::sa_family_t, sin6_port: hton(port), sin6_addr: *ip.as_inner(), sin6_flowinfo: hton(flowinfo), @@ -124,7 +124,7 @@ impl SocketAddrV6 { #[stable(feature = "rust1", since = "1.0.0")] pub fn ip(&self) -> &Ipv6Addr { unsafe { - &*(&self.inner.sin6_addr as *const libc::in6_addr as *const Ipv6Addr) + &*(&self.inner.sin6_addr as *const c::in6_addr as *const Ipv6Addr) } } @@ -143,26 +143,26 @@ impl SocketAddrV6 { pub fn scope_id(&self) -> u32 { ntoh(self.inner.sin6_scope_id) } } -impl FromInner for SocketAddrV4 { - fn from_inner(addr: libc::sockaddr_in) -> SocketAddrV4 { +impl FromInner for SocketAddrV4 { + fn from_inner(addr: c::sockaddr_in) -> SocketAddrV4 { SocketAddrV4 { inner: addr } } } -impl FromInner for SocketAddrV6 { - fn from_inner(addr: libc::sockaddr_in6) -> SocketAddrV6 { +impl FromInner for SocketAddrV6 { + fn from_inner(addr: c::sockaddr_in6) -> SocketAddrV6 { SocketAddrV6 { inner: addr } } } -impl<'a> IntoInner<(*const libc::sockaddr, socklen_t)> for &'a SocketAddr { - fn into_inner(self) -> (*const libc::sockaddr, socklen_t) { +impl<'a> IntoInner<(*const c::sockaddr, c::socklen_t)> for &'a SocketAddr { + fn into_inner(self) -> (*const c::sockaddr, c::socklen_t) { match *self { SocketAddr::V4(ref a) => { - (a as *const _ as *const _, mem::size_of_val(a) as socklen_t) + (a as *const _ as *const _, mem::size_of_val(a) as c::socklen_t) } SocketAddr::V6(ref a) => { - (a as *const _ as *const _, mem::size_of_val(a) as socklen_t) + (a as *const _ as *const _, mem::size_of_val(a) as c::socklen_t) } } } diff --git a/src/libstd/net/ip.rs b/src/libstd/net/ip.rs index 827a3eb9bf600..c657a7aa0bda2 100644 --- a/src/libstd/net/ip.rs +++ b/src/libstd/net/ip.rs @@ -16,11 +16,12 @@ use prelude::v1::*; use cmp::Ordering; -use hash; use fmt; -use libc; -use sys_common::{AsInner, FromInner}; +use hash; +use mem; use net::{hton, ntoh}; +use sys::net::netc as c; +use sys_common::{AsInner, FromInner}; /// An IP address, either an IPv4 or IPv6 address. #[unstable(feature = "ip_addr", reason = "recent addition", issue = "27801")] @@ -36,14 +37,14 @@ pub enum IpAddr { #[derive(Copy)] #[stable(feature = "rust1", since = "1.0.0")] pub struct Ipv4Addr { - inner: libc::in_addr, + inner: c::in_addr, } /// Representation of an IPv6 address. #[derive(Copy)] #[stable(feature = "rust1", since = "1.0.0")] pub struct Ipv6Addr { - inner: libc::in6_addr, + inner: c::in6_addr, } #[allow(missing_docs)] @@ -65,7 +66,7 @@ impl Ipv4Addr { #[stable(feature = "rust1", since = "1.0.0")] pub fn new(a: u8, b: u8, c: u8, d: u8) -> Ipv4Addr { Ipv4Addr { - inner: libc::in_addr { + inner: c::in_addr { s_addr: hton(((a as u32) << 24) | ((b as u32) << 16) | ((c as u32) << 8) | @@ -235,15 +236,15 @@ impl PartialOrd for Ipv4Addr { #[stable(feature = "rust1", since = "1.0.0")] impl Ord for Ipv4Addr { fn cmp(&self, other: &Ipv4Addr) -> Ordering { - self.inner.s_addr.cmp(&other.inner.s_addr) + self.octets().cmp(&other.octets()) } } -impl AsInner for Ipv4Addr { - fn as_inner(&self) -> &libc::in_addr { &self.inner } +impl AsInner for Ipv4Addr { + fn as_inner(&self) -> &c::in_addr { &self.inner } } -impl FromInner for Ipv4Addr { - fn from_inner(addr: libc::in_addr) -> Ipv4Addr { +impl FromInner for Ipv4Addr { + fn from_inner(addr: c::in_addr) -> Ipv4Addr { Ipv4Addr { inner: addr } } } @@ -270,25 +271,32 @@ impl Ipv6Addr { #[stable(feature = "rust1", since = "1.0.0")] pub fn new(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16, h: u16) -> Ipv6Addr { - Ipv6Addr { - inner: libc::in6_addr { - s6_addr: [hton(a), hton(b), hton(c), hton(d), - hton(e), hton(f), hton(g), hton(h)] - } - } + let mut addr: c::in6_addr = unsafe { mem::zeroed() }; + addr.s6_addr = [(a >> 8) as u8, a as u8, + (b >> 8) as u8, b as u8, + (c >> 8) as u8, c as u8, + (d >> 8) as u8, d as u8, + (e >> 8) as u8, e as u8, + (f >> 8) as u8, f as u8, + (g >> 8) as u8, g as u8, + (h >> 8) as u8, h as u8]; + Ipv6Addr { inner: addr } } /// Returns the eight 16-bit segments that make up this address. #[stable(feature = "rust1", since = "1.0.0")] pub fn segments(&self) -> [u16; 8] { - [ntoh(self.inner.s6_addr[0]), - ntoh(self.inner.s6_addr[1]), - ntoh(self.inner.s6_addr[2]), - ntoh(self.inner.s6_addr[3]), - ntoh(self.inner.s6_addr[4]), - ntoh(self.inner.s6_addr[5]), - ntoh(self.inner.s6_addr[6]), - ntoh(self.inner.s6_addr[7])] + let arr = &self.inner.s6_addr; + [ + (arr[0] as u16) << 8 | (arr[1] as u16), + (arr[2] as u16) << 8 | (arr[3] as u16), + (arr[4] as u16) << 8 | (arr[5] as u16), + (arr[6] as u16) << 8 | (arr[7] as u16), + (arr[8] as u16) << 8 | (arr[9] as u16), + (arr[10] as u16) << 8 | (arr[11] as u16), + (arr[12] as u16) << 8 | (arr[13] as u16), + (arr[14] as u16) << 8 | (arr[15] as u16), + ] } /// Returns true for the special 'unspecified' address ::. @@ -498,15 +506,15 @@ impl PartialOrd for Ipv6Addr { #[stable(feature = "rust1", since = "1.0.0")] impl Ord for Ipv6Addr { fn cmp(&self, other: &Ipv6Addr) -> Ordering { - self.inner.s6_addr.cmp(&other.inner.s6_addr) + self.segments().cmp(&other.segments()) } } -impl AsInner for Ipv6Addr { - fn as_inner(&self) -> &libc::in6_addr { &self.inner } +impl AsInner for Ipv6Addr { + fn as_inner(&self) -> &c::in6_addr { &self.inner } } -impl FromInner for Ipv6Addr { - fn from_inner(addr: libc::in6_addr) -> Ipv6Addr { +impl FromInner for Ipv6Addr { + fn from_inner(addr: c::in6_addr) -> Ipv6Addr { Ipv6Addr { inner: addr } } } @@ -786,4 +794,11 @@ mod tests { let a = Ipv4Addr::new(127, 0, 0, 1); assert_eq!(Ipv4Addr::from(2130706433), a); } + + #[test] + fn ord() { + assert!(Ipv4Addr::new(100, 64, 3, 3) < Ipv4Addr::new(192, 0, 2, 2)); + assert!("2001:db8:f00::1002".parse::().unwrap() < + "2001:db8:f00::2001".parse::().unwrap()); + } } diff --git a/src/libstd/num/f32.rs b/src/libstd/num/f32.rs index a04dfbeebe8e6..439ed40648900 100644 --- a/src/libstd/num/f32.rs +++ b/src/libstd/num/f32.rs @@ -120,7 +120,6 @@ mod cmath { #[cfg(not(test))] #[lang = "f32"] -#[stable(feature = "rust1", since = "1.0.0")] impl f32 { /// Parses a float as with a given radix #[unstable(feature = "float_from_str_radix", reason = "recently moved API", diff --git a/src/libstd/num/f64.rs b/src/libstd/num/f64.rs index 329d3329be649..aa0e7df76ab77 100644 --- a/src/libstd/num/f64.rs +++ b/src/libstd/num/f64.rs @@ -77,7 +77,6 @@ mod cmath { #[cfg(not(test))] #[lang = "f64"] -#[stable(feature = "rust1", since = "1.0.0")] impl f64 { /// Parses a float as with a given radix #[unstable(feature = "float_from_str_radix", reason = "recently moved API", diff --git a/src/libstd/os/raw.rs b/src/libstd/os/raw.rs index db487d041b7c1..17d6b2605c628 100644 --- a/src/libstd/os/raw.rs +++ b/src/libstd/os/raw.rs @@ -12,9 +12,13 @@ #![stable(feature = "raw_os", since = "1.1.0")] -#[cfg(target_arch = "aarch64")] +#[cfg(any(target_os = "android", + all(target_os = "linux", any(target_arch = "aarch64", + target_arch = "arm"))))] #[stable(feature = "raw_os", since = "1.1.0")] pub type c_char = u8; -#[cfg(not(target_arch = "aarch64"))] +#[cfg(not(any(target_os = "android", + all(target_os = "linux", any(target_arch = "aarch64", + target_arch = "arm")))))] #[stable(feature = "raw_os", since = "1.1.0")] pub type c_char = i8; #[stable(feature = "raw_os", since = "1.1.0")] pub type c_schar = i8; #[stable(feature = "raw_os", since = "1.1.0")] pub type c_uchar = u8; diff --git a/src/libstd/path.rs b/src/libstd/path.rs index 0559849f6a647..f97ad5b88356c 100644 --- a/src/libstd/path.rs +++ b/src/libstd/path.rs @@ -48,7 +48,8 @@ //! The path APIs are built around the notion of "components", which roughly //! correspond to the substrings between path separators (`/` and, on Windows, //! `\`). The APIs for path parsing are largely specified in terms of the path's -//! components, so it's important to clearly understand how those are determined. +//! components, so it's important to clearly understand how those are +//! determined. //! //! A path can always be reconstructed into an *equivalent* path by //! putting together its components via `push`. Syntactically, the @@ -191,10 +192,9 @@ mod platform { // \\?\UNC\server\share path = &path[4..]; let (server, share) = match parse_two_comps(path, is_verbatim_sep) { - Some((server, share)) => (u8_slice_as_os_str(server), - u8_slice_as_os_str(share)), - None => (u8_slice_as_os_str(path), - u8_slice_as_os_str(&[])), + Some((server, share)) => + (u8_slice_as_os_str(server), u8_slice_as_os_str(share)), + None => (u8_slice_as_os_str(path), u8_slice_as_os_str(&[])), }; return Some(VerbatimUNC(server, share)); } else { @@ -207,7 +207,7 @@ mod platform { return Some(VerbatimDisk(c.to_ascii_uppercase())); } } - let slice = &path[.. idx.unwrap_or(path.len())]; + let slice = &path[..idx.unwrap_or(path.len())]; return Some(Verbatim(u8_slice_as_os_str(slice))); } } else if path.starts_with(b".\\") { @@ -220,10 +220,9 @@ mod platform { match parse_two_comps(path, is_sep_byte) { Some((server, share)) if !server.is_empty() && !share.is_empty() => { // \\server\share - return Some(UNC(u8_slice_as_os_str(server), - u8_slice_as_os_str(share))); + return Some(UNC(u8_slice_as_os_str(server), u8_slice_as_os_str(share))); } - _ => () + _ => (), } } else if path.len() > 1 && path[1] == b':' { // C: @@ -238,11 +237,11 @@ mod platform { fn parse_two_comps(mut path: &[u8], f: fn(u8) -> bool) -> Option<(&[u8], &[u8])> { let first = match path.iter().position(|x| f(*x)) { None => return None, - Some(x) => &path[.. x] + Some(x) => &path[..x], }; - path = &path[(first.len()+1)..]; + path = &path[(first.len() + 1)..]; let idx = path.iter().position(|x| f(*x)); - let second = &path[.. idx.unwrap_or(path.len())]; + let second = &path[..idx.unwrap_or(path.len())]; Some((first, second)) } } @@ -299,15 +298,25 @@ impl<'a> Prefix<'a> { } match *self { Verbatim(x) => 4 + os_str_len(x), - VerbatimUNC(x,y) => 8 + os_str_len(x) + - if os_str_len(y) > 0 { 1 + os_str_len(y) } - else { 0 }, + VerbatimUNC(x, y) => { + 8 + os_str_len(x) + + if os_str_len(y) > 0 { + 1 + os_str_len(y) + } else { + 0 + } + }, VerbatimDisk(_) => 6, - UNC(x,y) => 2 + os_str_len(x) + - if os_str_len(y) > 0 { 1 + os_str_len(y) } - else { 0 }, + UNC(x, y) => { + 2 + os_str_len(x) + + if os_str_len(y) > 0 { + 1 + os_str_len(y) + } else { + 0 + } + }, DeviceNS(x) => 4 + os_str_len(x), - Disk(_) => 2 + Disk(_) => 2, } } @@ -368,14 +377,18 @@ pub const MAIN_SEPARATOR: char = platform::MAIN_SEP; // Iterate through `iter` while it matches `prefix`; return `None` if `prefix` // is not a prefix of `iter`, otherwise return `Some(iter_after_prefix)` giving // `iter` after having exhausted `prefix`. -fn iter_after(mut iter: I, mut prefix: J) -> Option where - I: Iterator + Clone, J: Iterator, A: PartialEq +fn iter_after(mut iter: I, mut prefix: J) -> Option + where I: Iterator + Clone, + J: Iterator, + A: PartialEq { loop { let mut iter_next = iter.clone(); match (iter_next.next(), prefix.next()) { (Some(x), Some(y)) => { - if x != y { return None } + if x != y { + return None; + } } (Some(_), None) => return Some(iter), (None, None) => return Some(iter), @@ -399,14 +412,20 @@ unsafe fn u8_slice_as_os_str(s: &[u8]) -> &OsStr { /// Says whether the first byte after the prefix is a separator. fn has_physical_root(s: &[u8], prefix: Option) -> bool { - let path = if let Some(p) = prefix { &s[p.len()..] } else { s }; + let path = if let Some(p) = prefix { + &s[p.len()..] + } else { + s + }; !path.is_empty() && is_sep_byte(path[0]) } // basic workhorse for splitting stem and extension fn split_file_at_dot(file: &OsStr) -> (Option<&OsStr>, Option<&OsStr>) { unsafe { - if os_str_as_u8_slice(file) == b".." { return (Some(file), None) } + if os_str_as_u8_slice(file) == b".." { + return (Some(file), None); + } // The unsafety here stems from converting between &OsStr and &[u8] // and back. This is safe to do because (1) we only look at ASCII @@ -589,7 +608,7 @@ pub struct Components<'a> { #[derive(Clone)] #[stable(feature = "rust1", since = "1.0.0")] pub struct Iter<'a> { - inner: Components<'a> + inner: Components<'a>, } impl<'a> Components<'a> { @@ -617,8 +636,16 @@ impl<'a> Components<'a> { // Given the iteration so far, how much of the pre-State::Body path is left? #[inline] fn len_before_body(&self) -> usize { - let root = if self.front <= State::StartDir && self.has_physical_root { 1 } else { 0 }; - let cur_dir = if self.front <= State::StartDir && self.include_cur_dir() { 1 } else { 0 }; + let root = if self.front <= State::StartDir && self.has_physical_root { + 1 + } else { + 0 + }; + let cur_dir = if self.front <= State::StartDir && self.include_cur_dir() { + 1 + } else { + 0 + }; self.prefix_remaining() + root + cur_dir } @@ -653,28 +680,38 @@ impl<'a> Components<'a> { #[stable(feature = "rust1", since = "1.0.0")] pub fn as_path(&self) -> &'a Path { let mut comps = self.clone(); - if comps.front == State::Body { comps.trim_left(); } - if comps.back == State::Body { comps.trim_right(); } + if comps.front == State::Body { + comps.trim_left(); + } + if comps.back == State::Body { + comps.trim_right(); + } unsafe { Path::from_u8_slice(comps.path) } } /// Is the *original* path rooted? fn has_root(&self) -> bool { - if self.has_physical_root { return true } + if self.has_physical_root { + return true; + } if let Some(p) = self.prefix { - if p.has_implicit_root() { return true } + if p.has_implicit_root() { + return true; + } } false } /// Should the normalized path include a leading . ? fn include_cur_dir(&self) -> bool { - if self.has_root() { return false } + if self.has_root() { + return false; + } let mut iter = self.path[self.prefix_len()..].iter(); match (iter.next(), iter.next()) { (Some(&b'.'), None) => true, (Some(&b'.'), Some(&b)) => self.is_sep_byte(b), - _ => false + _ => false, } } @@ -687,7 +724,7 @@ impl<'a> Components<'a> { // separately via `include_cur_dir` b".." => Some(Component::ParentDir), b"" => None, - _ => Some(Component::Normal(unsafe { u8_slice_as_os_str(comp) })) + _ => Some(Component::Normal(unsafe { u8_slice_as_os_str(comp) })), } } @@ -697,7 +734,7 @@ impl<'a> Components<'a> { debug_assert!(self.front == State::Body); let (extra, comp) = match self.path.iter().position(|b| self.is_sep_byte(*b)) { None => (0, self.path), - Some(i) => (1, &self.path[.. i]), + Some(i) => (1, &self.path[..i]), }; (comp.len() + extra, self.parse_single_component(comp)) } @@ -708,8 +745,8 @@ impl<'a> Components<'a> { debug_assert!(self.back == State::Body); let start = self.len_before_body(); let (extra, comp) = match self.path[start..].iter().rposition(|b| self.is_sep_byte(*b)) { - None => (0, &self.path[start ..]), - Some(i) => (1, &self.path[start + i + 1 ..]), + None => (0, &self.path[start..]), + Some(i) => (1, &self.path[start + i + 1..]), }; (comp.len() + extra, self.parse_single_component(comp)) } @@ -721,7 +758,7 @@ impl<'a> Components<'a> { if comp.is_some() { return; } else { - self.path = &self.path[size ..]; + self.path = &self.path[size..]; } } } @@ -733,7 +770,7 @@ impl<'a> Components<'a> { if comp.is_some() { return; } else { - self.path = &self.path[.. self.path.len() - size]; + self.path = &self.path[..self.path.len() - size]; } } } @@ -807,12 +844,12 @@ impl<'a> Iterator for Components<'a> { State::Prefix if self.prefix_len() > 0 => { self.front = State::StartDir; debug_assert!(self.prefix_len() <= self.path.len()); - let raw = &self.path[.. self.prefix_len()]; - self.path = &self.path[self.prefix_len() .. ]; + let raw = &self.path[..self.prefix_len()]; + self.path = &self.path[self.prefix_len()..]; return Some(Component::Prefix(PrefixComponent { raw: unsafe { u8_slice_as_os_str(raw) }, - parsed: self.prefix.unwrap() - })) + parsed: self.prefix.unwrap(), + })); } State::Prefix => { self.front = State::StartDir; @@ -822,26 +859,28 @@ impl<'a> Iterator for Components<'a> { if self.has_physical_root { debug_assert!(!self.path.is_empty()); self.path = &self.path[1..]; - return Some(Component::RootDir) + return Some(Component::RootDir); } else if let Some(p) = self.prefix { if p.has_implicit_root() && !p.is_verbatim() { - return Some(Component::RootDir) + return Some(Component::RootDir); } } else if self.include_cur_dir() { debug_assert!(!self.path.is_empty()); self.path = &self.path[1..]; - return Some(Component::CurDir) + return Some(Component::CurDir); } } State::Body if !self.path.is_empty() => { let (size, comp) = self.parse_next_component(); - self.path = &self.path[size ..]; - if comp.is_some() { return comp } + self.path = &self.path[size..]; + if comp.is_some() { + return comp; + } } State::Body => { self.front = State::Done; } - State::Done => unreachable!() + State::Done => unreachable!(), } } None @@ -855,8 +894,10 @@ impl<'a> DoubleEndedIterator for Components<'a> { match self.back { State::Body if self.path.len() > self.len_before_body() => { let (size, comp) = self.parse_next_component_back(); - self.path = &self.path[.. self.path.len() - size]; - if comp.is_some() { return comp } + self.path = &self.path[..self.path.len() - size]; + if comp.is_some() { + return comp; + } } State::Body => { self.back = State::StartDir; @@ -864,29 +905,29 @@ impl<'a> DoubleEndedIterator for Components<'a> { State::StartDir => { self.back = State::Prefix; if self.has_physical_root { - self.path = &self.path[.. self.path.len() - 1]; - return Some(Component::RootDir) + self.path = &self.path[..self.path.len() - 1]; + return Some(Component::RootDir); } else if let Some(p) = self.prefix { if p.has_implicit_root() && !p.is_verbatim() { - return Some(Component::RootDir) + return Some(Component::RootDir); } } else if self.include_cur_dir() { - self.path = &self.path[.. self.path.len() - 1]; - return Some(Component::CurDir) + self.path = &self.path[..self.path.len() - 1]; + return Some(Component::CurDir); } } State::Prefix if self.prefix_len() > 0 => { self.back = State::Done; return Some(Component::Prefix(PrefixComponent { raw: unsafe { u8_slice_as_os_str(self.path) }, - parsed: self.prefix.unwrap() - })) + parsed: self.prefix.unwrap(), + })); } State::Prefix => { self.back = State::Done; - return None + return None; } - State::Done => unreachable!() + State::Done => unreachable!(), } } None @@ -943,7 +984,7 @@ impl<'a> cmp::Ord for Components<'a> { #[derive(Clone)] #[stable(feature = "rust1", since = "1.0.0")] pub struct PathBuf { - inner: OsString + inner: OsString, } impl PathBuf { @@ -972,6 +1013,21 @@ impl PathBuf { /// * if `path` has a root but no prefix (e.g. `\windows`), it /// replaces everything except for the prefix (if any) of `self`. /// * if `path` has a prefix but no root, it replaces `self`. + /// + /// # Examples + /// + /// ``` + /// use std::path::PathBuf; + /// + /// let mut path = PathBuf::new(); + /// path.push("/tmp"); + /// path.push("file.bk"); + /// assert_eq!(path, PathBuf::from("/tmp/file.bk")); + /// + /// // Pushing an absolute path replaces the current path + /// path.push("/etc/passwd"); + /// assert_eq!(path, PathBuf::from("/etc/passwd")); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn push>(&mut self, path: P) { self._push(path.as_ref()) @@ -984,10 +1040,8 @@ impl PathBuf { // in the special case of `C:` on Windows, do *not* add a separator { let comps = self.components(); - if comps.prefix_len() > 0 && - comps.prefix_len() == comps.path.len() && - comps.prefix.unwrap().is_drive() - { + if comps.prefix_len() > 0 && comps.prefix_len() == comps.path.len() && + comps.prefix.unwrap().is_drive() { need_sep = false } } @@ -1020,7 +1074,7 @@ impl PathBuf { self.as_mut_vec().truncate(len); true } - None => false + None => false, } } @@ -1067,7 +1121,9 @@ impl PathBuf { } fn _set_extension(&mut self, extension: &OsStr) -> bool { - if self.file_name().is_none() { return false; } + if self.file_name().is_none() { + return false; + } let mut stem = match self.file_stem() { Some(stem) => stem.to_os_string(), @@ -1166,10 +1222,28 @@ impl<'a> IntoCow<'a, Path> for &'a Path { } } +#[stable(feature = "cow_from_path", since = "1.6.0")] +impl<'a> From<&'a Path> for Cow<'a, Path> { + #[inline] + fn from(s: &'a Path) -> Cow<'a, Path> { + Cow::Borrowed(s) + } +} + +#[stable(feature = "cow_from_path", since = "1.6.0")] +impl<'a> From for Cow<'a, Path> { + #[inline] + fn from(s: PathBuf) -> Cow<'a, Path> { + Cow::Owned(s) + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl ToOwned for Path { type Owned = PathBuf; - fn to_owned(&self) -> PathBuf { self.to_path_buf() } + fn to_owned(&self) -> PathBuf { + self.to_path_buf() + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -1241,7 +1315,7 @@ impl Into for PathBuf { /// #[stable(feature = "rust1", since = "1.0.0")] pub struct Path { - inner: OsStr + inner: OsStr, } impl Path { @@ -1364,8 +1438,7 @@ impl Path { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn is_absolute(&self) -> bool { - self.has_root() && - (cfg!(unix) || self.prefix().is_some()) + self.has_root() && (cfg!(unix) || self.prefix().is_some()) } /// A path is *relative* if it is not absolute. @@ -1412,7 +1485,7 @@ impl Path { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn has_root(&self) -> bool { - self.components().has_root() + self.components().has_root() } /// The path without its final component, if any. @@ -1436,11 +1509,13 @@ impl Path { pub fn parent(&self) -> Option<&Path> { let mut comps = self.components(); let comp = comps.next_back(); - comp.and_then(|p| match p { - Component::Normal(_) | - Component::CurDir | - Component::ParentDir => Some(comps.as_path()), - _ => None + comp.and_then(|p| { + match p { + Component::Normal(_) | + Component::CurDir | + Component::ParentDir => Some(comps.as_path()), + _ => None, + } }) } @@ -1462,9 +1537,11 @@ impl Path { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn file_name(&self) -> Option<&OsStr> { - self.components().next_back().and_then(|p| match p { - Component::Normal(p) => Some(p.as_ref()), - _ => None + self.components().next_back().and_then(|p| { + match p { + Component::Normal(p) => Some(p.as_ref()), + _ => None, + } }) } @@ -1474,8 +1551,7 @@ impl Path { /// returns false), then `relative_from` returns `None`. #[unstable(feature = "path_relative_from", reason = "see #23284", issue = "23284")] - pub fn relative_from<'a, P: ?Sized + AsRef>(&'a self, base: &'a P) -> Option<&Path> - { + pub fn relative_from<'a, P: ?Sized + AsRef>(&'a self, base: &'a P) -> Option<&Path> { self._relative_from(base.as_ref()) } @@ -1756,7 +1832,8 @@ impl Path { } /// Boolean value indicator whether the underlying file exists on the local - /// filesystem. Returns false in exactly the cases where `fs::stat` fails. + /// filesystem. Returns false in exactly the cases where `fs::metadata` + /// fails. #[stable(feature = "path_ext", since = "1.5.0")] pub fn exists(&self) -> bool { fs::metadata(self).is_ok() @@ -1799,7 +1876,7 @@ impl fmt::Debug for Path { /// Helper struct for safely printing paths with `format!()` and `{}` #[stable(feature = "rust1", since = "1.0.0")] pub struct Display<'a> { - path: &'a Path + path: &'a Path, } #[stable(feature = "rust1", since = "1.0.0")] @@ -1851,32 +1928,44 @@ impl cmp::Ord for Path { #[stable(feature = "rust1", since = "1.0.0")] impl AsRef for Path { - fn as_ref(&self) -> &Path { self } + fn as_ref(&self) -> &Path { + self + } } #[stable(feature = "rust1", since = "1.0.0")] impl AsRef for OsStr { - fn as_ref(&self) -> &Path { Path::new(self) } + fn as_ref(&self) -> &Path { + Path::new(self) + } } #[stable(feature = "rust1", since = "1.0.0")] impl AsRef for OsString { - fn as_ref(&self) -> &Path { Path::new(self) } + fn as_ref(&self) -> &Path { + Path::new(self) + } } #[stable(feature = "rust1", since = "1.0.0")] impl AsRef for str { - fn as_ref(&self) -> &Path { Path::new(self) } + fn as_ref(&self) -> &Path { + Path::new(self) + } } #[stable(feature = "rust1", since = "1.0.0")] impl AsRef for String { - fn as_ref(&self) -> &Path { Path::new(self) } + fn as_ref(&self) -> &Path { + Path::new(self) + } } #[stable(feature = "rust1", since = "1.0.0")] impl AsRef for PathBuf { - fn as_ref(&self) -> &Path { self } + fn as_ref(&self) -> &Path { + self + } } #[stable(feature = "path_into_iter", since = "1.6.0")] @@ -1893,6 +1982,29 @@ impl<'a> IntoIterator for &'a Path { fn into_iter(self) -> Iter<'a> { self.iter() } } +macro_rules! impl_eq { + ($lhs:ty, $rhs: ty) => { + #[stable(feature = "partialeq_path", since = "1.6.0")] + impl<'a, 'b> PartialEq<$rhs> for $lhs { + #[inline] + fn eq(&self, other: &$rhs) -> bool { ::eq(self, other) } + } + + #[stable(feature = "partialeq_path", since = "1.6.0")] + impl<'a, 'b> PartialEq<$lhs> for $rhs { + #[inline] + fn eq(&self, other: &$lhs) -> bool { ::eq(self, other) } + } + + } +} + +impl_eq!(PathBuf, Path); +impl_eq!(PathBuf, &'a Path); +impl_eq!(Cow<'a, Path>, Path); +impl_eq!(Cow<'a, Path>, &'b Path); +impl_eq!(Cow<'a, Path>, PathBuf); + #[cfg(test)] mod tests { use super::*; @@ -2002,6 +2114,26 @@ mod tests { assert_eq!(static_cow_path, owned_cow_path); } + #[test] + fn into() { + use borrow::Cow; + + let static_path = Path::new("/home/foo"); + let static_cow_path: Cow<'static, Path> = static_path.into(); + let pathbuf = PathBuf::from("/home/foo"); + + { + let path: &Path = &pathbuf; + let borrowed_cow_path: Cow = path.into(); + + assert_eq!(static_cow_path, borrowed_cow_path); + } + + let owned_cow_path: Cow<'static, Path> = pathbuf.into(); + + assert_eq!(static_cow_path, owned_cow_path); + } + #[test] #[cfg(unix)] pub fn test_decompositions_unix() { @@ -2931,20 +3063,26 @@ mod tests { tp!("C:a\\b\\c", "C:d", "C:d"); tp!("C:", r"a\b\c", r"C:a\b\c"); tp!("C:", r"..\a", r"C:..\a"); - tp!("\\\\server\\share\\foo", "bar", "\\\\server\\share\\foo\\bar"); + tp!("\\\\server\\share\\foo", + "bar", + "\\\\server\\share\\foo\\bar"); tp!("\\\\server\\share\\foo", "C:baz", "C:baz"); tp!("\\\\?\\C:\\a\\b", "C:c\\d", "C:c\\d"); tp!("\\\\?\\C:a\\b", "C:c\\d", "C:c\\d"); tp!("\\\\?\\C:\\a\\b", "C:\\c\\d", "C:\\c\\d"); tp!("\\\\?\\foo\\bar", "baz", "\\\\?\\foo\\bar\\baz"); - tp!("\\\\?\\UNC\\server\\share\\foo", "bar", "\\\\?\\UNC\\server\\share\\foo\\bar"); + tp!("\\\\?\\UNC\\server\\share\\foo", + "bar", + "\\\\?\\UNC\\server\\share\\foo\\bar"); tp!("\\\\?\\UNC\\server\\share", "C:\\a", "C:\\a"); tp!("\\\\?\\UNC\\server\\share", "C:a", "C:a"); // Note: modified from old path API tp!("\\\\?\\UNC\\server", "foo", "\\\\?\\UNC\\server\\foo"); - tp!("C:\\a", "\\\\?\\UNC\\server\\share", "\\\\?\\UNC\\server\\share"); + tp!("C:\\a", + "\\\\?\\UNC\\server\\share", + "\\\\?\\UNC\\server\\share"); tp!("\\\\.\\foo\\bar", "baz", "\\\\.\\foo\\bar\\baz"); tp!("\\\\.\\foo\\bar", "C:a", "C:a"); // again, not sure about the following, but I'm assuming \\.\ should be verbatim @@ -2997,9 +3135,15 @@ mod tests { tp!("\\\\?\\C:\\a\\b", "\\\\?\\C:\\a", true); tp!("\\\\?\\C:\\a", "\\\\?\\C:\\", true); tp!("\\\\?\\C:\\", "\\\\?\\C:\\", false); - tp!("\\\\?\\UNC\\server\\share\\a\\b", "\\\\?\\UNC\\server\\share\\a", true); - tp!("\\\\?\\UNC\\server\\share\\a", "\\\\?\\UNC\\server\\share\\", true); - tp!("\\\\?\\UNC\\server\\share", "\\\\?\\UNC\\server\\share", false); + tp!("\\\\?\\UNC\\server\\share\\a\\b", + "\\\\?\\UNC\\server\\share\\a", + true); + tp!("\\\\?\\UNC\\server\\share\\a", + "\\\\?\\UNC\\server\\share\\", + true); + tp!("\\\\?\\UNC\\server\\share", + "\\\\?\\UNC\\server\\share", + false); tp!("\\\\.\\a\\b\\c", "\\\\.\\a\\b", true); tp!("\\\\.\\a\\b", "\\\\.\\a\\", true); tp!("\\\\.\\a", "\\\\.\\a", false); @@ -3065,11 +3209,36 @@ mod tests { tfe!(".", "foo", ".", false); tfe!("foo/", "bar", "foo.bar", true); tfe!("foo/.", "bar", "foo.bar", true); - tfe!("..", "foo", "..", false); + tfe!("..", "foo", "..", false); tfe!("foo/..", "bar", "foo/..", false); tfe!("/", "foo", "/", false); } + #[test] + fn test_eq_recievers() { + use borrow::Cow; + + let borrowed: &Path = Path::new("foo/bar"); + let mut owned: PathBuf = PathBuf::new(); + owned.push("foo"); + owned.push("bar"); + let borrowed_cow: Cow = borrowed.into(); + let owned_cow: Cow = owned.clone().into(); + + macro_rules! t { + ($($current:expr),+) => { + $( + assert_eq!($current, borrowed); + assert_eq!($current, owned); + assert_eq!($current, borrowed_cow); + assert_eq!($current, owned_cow); + )+ + } + } + + t!(borrowed, owned, borrowed_cow, owned_cow); + } + #[test] pub fn test_compare() { use hash::{Hash, Hasher, SipHasher}; diff --git a/src/libstd/prelude/mod.rs b/src/libstd/prelude/mod.rs index 08227cfb35322..bda4cdfb43733 100644 --- a/src/libstd/prelude/mod.rs +++ b/src/libstd/prelude/mod.rs @@ -10,119 +10,136 @@ //! The Rust Prelude //! -//! Because `std` is required by most serious Rust software, it is -//! imported at the topmost level of every crate by default, as if -//! each crate contains the following: +//! Rust comes with a variety of things in its standard library. However, if +//! you had to manually import every single thing that you used, it would be +//! very verbose. But importing a lot of things that a program never uses isn't +//! good either. A balance needs to be struck. +//! +//! The *prelude* is the list of things that Rust automatically imports into +//! every Rust program. It's kept as small as possible, and is focused on +//! things, particuarly traits, which are used in almost every single Rust +//! program. +//! +//! On a technical level, Rust inserts //! //! ```ignore //! extern crate std; //! ``` //! -//! This means that the contents of std can be accessed from any context -//! with the `std::` path prefix, as in `use std::vec`, `use std::thread::spawn`, -//! etc. -//! -//! Additionally, `std` contains a versioned *prelude* that reexports many of the -//! most common traits, types, and functions. *The contents of the prelude are -//! imported into every module by default*. Implicitly, all modules behave as if -//! they contained the following [`use` statement][book-use]: -//! -//! [book-use]: ../../book/crates-and-modules.html#importing-modules-with-use +//! into the crate root of every crate, and //! //! ```ignore //! use std::prelude::v1::*; //! ``` //! -//! The prelude is primarily concerned with exporting *traits* that -//! are so pervasive that they would be onerous to import for every use, -//! particularly those that are commonly mentioned in [generic type -//! bounds][book-traits]. +//! into every module. +//! +//! # Other preludes +//! +//! Preludes can be seen as a pattern to make using multiple types more +//! convenient. As such, you'll find other preludes in the standard library, +//! such as [`std::io::prelude`]. Various libraries in the Rust ecosystem may +//! also define their own preludes. +//! +//! [`std::io::prelude`]: ../io/prelude/index.html +//! +//! The differece between 'the prelude' and these other preludes is that they +//! are not automatically `use`'d, and must be imported manually. This is still +//! easier than importing all of their consitutent components. +//! +//! # Prelude contents //! //! The current version of the prelude (version 1) lives in -//! [`std::prelude::v1`](v1/index.html), and reexports the following. +//! [`std::prelude::v1`], and reexports the following. //! -//! * `std::marker::`{ -//! [`Copy`](../marker/trait.Copy.html), -//! [`Send`](../marker/trait.Send.html), -//! [`Sized`](../marker/trait.Sized.html), -//! [`Sync`](../marker/trait.Sync.html) -//! }. -//! The marker traits indicate fundamental properties of types. -//! * `std::ops::`{ -//! [`Drop`](../ops/trait.Drop.html), -//! [`Fn`](../ops/trait.Fn.html), -//! [`FnMut`](../ops/trait.FnMut.html), -//! [`FnOnce`](../ops/trait.FnOnce.html) -//! }. -//! The [destructor][book-dtor] trait and the -//! [closure][book-closures] traits, reexported from the same -//! [module that also defines overloaded -//! operators](../ops/index.html). -//! * `std::mem::`[`drop`](../mem/fn.drop.html). -//! A convenience function for explicitly dropping a value. -//! * `std::boxed::`[`Box`](../boxed/struct.Box.html). -//! The owned heap pointer. -//! * `std::borrow::`[`ToOwned`](../borrow/trait.ToOwned.html). -//! The conversion trait that defines `to_owned`, the generic method -//! for creating an owned type from a borrowed type. -//! * `std::clone::`[`Clone`](../clone/trait.Clone.html). -//! The ubiquitous trait that defines `clone`, the method for -//! producing copies of values that are consider expensive to copy. -//! * `std::cmp::`{ -//! [`PartialEq`](../cmp/trait.PartialEq.html), -//! [`PartialOrd`](../cmp/trait.PartialOrd.html), -//! [`Eq`](../cmp/trait.Eq.html), -//! [`Ord`](../cmp/trait.Ord.html) -//! }. -//! The comparison traits, which implement the comparison operators -//! and are often seen in trait bounds. -//! * `std::convert::`{ -//! [`AsRef`](../convert/trait.AsRef.html), -//! [`AsMut`](../convert/trait.AsMut.html), -//! [`Into`](../convert/trait.Into.html), -//! [`From`](../convert/trait.From.html) -//! }. -//! Generic conversions, used by savvy API authors to create -//! overloaded methods. -//! * `std::default::`[`Default`](../default/trait.Default.html). -//! Types that have default values. -//! * `std::iter::`{ -//! [`Iterator`](../iter/trait.Iterator.html), -//! [`Extend`](../iter/trait.Extend.html), -//! [`IntoIterator`](../iter/trait.IntoIterator.html), -//! [`DoubleEndedIterator`](../iter/trait.DoubleEndedIterator.html), -//! [`ExactSizeIterator`](../iter/trait.ExactSizeIterator.html) -//! }. -//! [Iterators][book-iter]. -//! * `std::option::Option::`{ -//! [`self`](../option/enum.Option.html), -//! [`Some`](../option/enum.Option.html), -//! [`None`](../option/enum.Option.html) -//! }. -//! The ubiquitous `Option` type and its two [variants][book-enums], -//! `Some` and `None`. -//! * `std::result::Result::`{ -//! [`self`](../result/enum.Result.html), -//! [`Ok`](../result/enum.Result.html), -//! [`Err`](../result/enum.Result.html) -//! }. -//! The ubiquitous `Result` type and its two [variants][book-enums], -//! `Ok` and `Err`. -//! * `std::slice::`[`SliceConcatExt`](../slice/trait.SliceConcatExt.html). -//! An unstable extension to slices that shouldn't have to exist. -//! * `std::string::`{ -//! [`String`](../string/struct.String.html), -//! [`ToString`](../string/trait.ToString.html) -//! }. -//! Heap allocated strings. -//! * `std::vec::`[`Vec`](../vec/struct.Vec.html). -//! Heap allocated vectors. +//! * [`std::marker`]::{[`Copy`], [`Send`], [`Sized`], [`Sync`]}. The marker +//! traits indicate fundamental properties of types. +//! * [`std::ops`]::{[`Drop`], [`Fn`], [`FnMut`], [`FnOnce`]}. Various +//! operations for both destuctors and overloading `()`. +//! * [`std::mem`]::[`drop`], a convenience function for explicitly dropping a +//! value. +//! * [`std::boxed`]::[`Box`], a way to allocate values on the heap. +//! * [`std::borrow`]::[`ToOwned`], The conversion trait that defines +//! [`to_owned()`], the generic method for creating an owned type from a +//! borrowed type. +//! * [`std::clone`]::[`Clone`], the ubiquitous trait that defines [`clone()`], +//! the method for producing a copy of a value. +//! * [`std::cmp`]::{[`PartialEq`], [`PartialOrd`], [`Eq`], [`Ord`] }. The +//! comparison traits, which implement the comparison operators and are often +//! seen in trait bounds. +//! * [`std::convert`]::{[`AsRef`], [`AsMut`], [`Into`], [`From`]}. Generic +//! conversions, used by savvy API authors to create overloaded methods. +//! * [`std::default`]::[`Default`], types that have default values. +//! * [`std::iter`]::{[`Iterator`], [`Extend`], [`IntoIterator`], +//! [`DoubleEndedIterator`], [`ExactSizeIterator`]}. Iterators of various +//! kinds. +//! * [`std::option`]::[`Option`]::{`self`, `Some`, `None`}. A type which +//! expresses the presence or absence of a value. This type is so commonly +//! used, its variants are also exported. +//! * [`std::result`]::[`Result`]::{`self`, `Ok`, `Err`}. A type for functions +//! that may succeed or fail. Like [`Option`], its variants are exported as +//! well. +//! * [`std::slice`]::[`SliceConcatExt`], a trait that exists for technical +//! reasons, but shouldn't have to exist. It provides a few useful methods on +//! slices. +//! * [`std::string`]::{[`String`], [`ToString`]}, heap allocated strings. +//! * [`std::vec`]::[`Vec`](../vec/struct.Vec.html), a growable, heap-allocated +//! vector. //! -//! [book-traits]: ../../book/traits.html +//! [`AsMut`]: ../convert/trait.AsMut.html +//! [`AsRef`]: ../convert/trait.AsRef.html +//! [`Box`]: ../boxed/struct.Box.html +//! [`Clone`]: ../clone/trait.Clone.html +//! [`Copy`]: ../marker/trait.Copy.html +//! [`Default`]: ../default/trait.Default.html +//! [`DoubleEndedIterator`]: ../iter/trait.DoubleEndedIterator.html +//! [`Drop`]: ../ops/trait.Drop.html +//! [`Eq`]: ../cmp/trait.Eq.html +//! [`ExactSizeIterator`]: ../iter/trait.ExactSizeIterator.html +//! [`Extend`]: ../iter/trait.Extend.html +//! [`FnMut`]: ../ops/trait.FnMut.html +//! [`FnOnce`]: ../ops/trait.FnOnce.html +//! [`Fn`]: ../ops/trait.Fn.html +//! [`From`]: ../convert/trait.From.html +//! [`IntoIterator`]: ../iter/trait.IntoIterator.html +//! [`Into`]: ../convert/trait.Into.html +//! [`Iterator`]: ../iter/trait.Iterator.html +//! [`Option`]: ../option/enum.Option.html +//! [`Ord`]: ../cmp/trait.Ord.html +//! [`PartialEq`]: ../cmp/trait.PartialEq.html +//! [`PartialOrd`]: ../cmp/trait.PartialOrd.html +//! [`Result`]: ../result/enum.Result.html +//! [`Send`]: ../marker/trait.Send.html +//! [`Sized`]: ../marker/trait.Sized.html +//! [`SliceConcatExt`]: ../slice/trait.SliceConcatExt.html +//! [`String`]: ../string/struct.String.html +//! [`Sync`]: ../marker/trait.Sync.html +//! [`ToOwned`]: ../borrow/trait.ToOwned.html +//! [`ToString`]: ../string/trait.ToString.html +//! [`Vec`]: ../vec/struct.Vec.html +//! [`clone()`]: ../clone/trait.Clone.html#tymethod.clone +//! [`drop`]: ../mem/fn.drop.html +//! [`std::borrow`]: ../borrow/index.html +//! [`std::boxed`]: ../boxed/index.html +//! [`std::clone`]: ../clone/index.html +//! [`std::cmp`]: ../cmp/index.html +//! [`std::convert`]: ../convert/index.html +//! [`std::default`]: ../default/index.html +//! [`std::iter`]: ../iter/index.html +//! [`std::marker`]: ../marker/index.html +//! [`std::mem`]: ../mem/index.html +//! [`std::ops`]: ../ops/index.html +//! [`std::option`]: ../option/index.html +//! [`std::prelude::v1`]: v1/index.html +//! [`std::result`]: ../result/index.html +//! [`std::slice`]: ../slice/index.html +//! [`std::string`]: ../string/index.html +//! [`std::vec`]: ../vec/index.html +//! [`to_owned()`]: ../borrow/trait.ToOwned.html#tymethod.to_owned //! [book-closures]: ../../book/closures.html //! [book-dtor]: ../../book/drop.html -//! [book-iter]: ../../book/iterators.html //! [book-enums]: ../../book/enums.html +//! [book-iter]: ../../book/iterators.html #![stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libstd/prelude/v1.rs b/src/libstd/prelude/v1.rs index 46c0103e08764..9ca5b445c86a9 100644 --- a/src/libstd/prelude/v1.rs +++ b/src/libstd/prelude/v1.rs @@ -9,6 +9,8 @@ // except according to those terms. //! The first version of the prelude of The Rust Standard Library. +//! +//! See the [module-level documentation](../index.html) for more. #![stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libstd/primitive_docs.rs b/src/libstd/primitive_docs.rs index 7d62d477a0a52..df12952fc324f 100644 --- a/src/libstd/primitive_docs.rs +++ b/src/libstd/primitive_docs.rs @@ -165,12 +165,14 @@ mod prim_pointer { } /// Arrays of sizes from 0 to 32 (inclusive) implement the following traits /// if the element type allows it: /// -/// - `Clone` +/// - `Clone` (only if `T: Copy`) /// - `Debug` /// - `IntoIterator` (implemented for `&[T; N]` and `&mut [T; N]`) /// - `PartialEq`, `PartialOrd`, `Ord`, `Eq` /// - `Hash` /// - `AsRef`, `AsMut` +/// - `Borrow`, `BorrowMut` +/// - `Default` /// /// Arrays dereference to [slices (`[T]`)][slice], so their methods can be called /// on arrays. diff --git a/src/libstd/rand/os.rs b/src/libstd/rand/os.rs index 1df9642d3bb74..d1bd013e67b79 100644 --- a/src/libstd/rand/os.rs +++ b/src/libstd/rand/os.rs @@ -252,10 +252,7 @@ mod imp { use io; use mem; use rand::Rng; - use libc::types::os::arch::extra::{LONG_PTR}; - use libc::{DWORD, BYTE, LPCSTR, BOOL}; - - type HCRYPTPROV = LONG_PTR; + use sys::c; /// A random number generator that retrieves randomness straight from /// the operating system. Platform sources: @@ -268,25 +265,7 @@ mod imp { /// /// This does not block. pub struct OsRng { - hcryptprov: HCRYPTPROV - } - - const PROV_RSA_FULL: DWORD = 1; - const CRYPT_SILENT: DWORD = 64; - const CRYPT_VERIFYCONTEXT: DWORD = 0xF0000000; - - #[allow(non_snake_case)] - #[link(name = "advapi32")] - extern "system" { - fn CryptAcquireContextA(phProv: *mut HCRYPTPROV, - pszContainer: LPCSTR, - pszProvider: LPCSTR, - dwProvType: DWORD, - dwFlags: DWORD) -> BOOL; - fn CryptGenRandom(hProv: HCRYPTPROV, - dwLen: DWORD, - pbBuffer: *mut BYTE) -> BOOL; - fn CryptReleaseContext(hProv: HCRYPTPROV, dwFlags: DWORD) -> BOOL; + hcryptprov: c::HCRYPTPROV } impl OsRng { @@ -294,9 +273,9 @@ mod imp { pub fn new() -> io::Result { let mut hcp = 0; let ret = unsafe { - CryptAcquireContextA(&mut hcp, 0 as LPCSTR, 0 as LPCSTR, - PROV_RSA_FULL, - CRYPT_VERIFYCONTEXT | CRYPT_SILENT) + c::CryptAcquireContextA(&mut hcp, 0 as c::LPCSTR, 0 as c::LPCSTR, + c::PROV_RSA_FULL, + c::CRYPT_VERIFYCONTEXT | c::CRYPT_SILENT) }; if ret == 0 { @@ -320,8 +299,8 @@ mod imp { } fn fill_bytes(&mut self, v: &mut [u8]) { let ret = unsafe { - CryptGenRandom(self.hcryptprov, v.len() as DWORD, - v.as_mut_ptr()) + c::CryptGenRandom(self.hcryptprov, v.len() as c::DWORD, + v.as_mut_ptr()) }; if ret == 0 { panic!("couldn't generate random bytes: {}", @@ -333,7 +312,7 @@ mod imp { impl Drop for OsRng { fn drop(&mut self) { let ret = unsafe { - CryptReleaseContext(self.hcryptprov, 0) + c::CryptReleaseContext(self.hcryptprov, 0) }; if ret == 0 { panic!("couldn't release context: {}", diff --git a/src/libstd/sync/condvar.rs b/src/libstd/sync/condvar.rs index 1b32515e9f72e..a18370dc68e18 100644 --- a/src/libstd/sync/condvar.rs +++ b/src/libstd/sync/condvar.rs @@ -12,10 +12,10 @@ use prelude::v1::*; use sync::atomic::{AtomicUsize, Ordering}; use sync::{mutex, MutexGuard, PoisonError}; +use sys::time::SteadyTime; use sys_common::condvar as sys; use sys_common::mutex as sys_mutex; use sys_common::poison::{self, LockResult}; -use sys::time::SteadyTime; use time::Duration; /// A type indicating whether a timed wait on a condition variable returned @@ -167,6 +167,8 @@ impl Condvar { /// Like `wait`, the lock specified will be re-acquired when this function /// returns, regardless of whether the timeout elapsed or not. #[stable(feature = "rust1", since = "1.0.0")] + #[deprecated(since = "1.6.0", reason = "replaced by `std::sync::Condvar::wait_timeout`")] + #[allow(deprecated)] pub fn wait_timeout_ms<'a, T>(&self, guard: MutexGuard<'a, T>, ms: u32) -> LockResult<(MutexGuard<'a, T>, bool)> { unsafe { @@ -289,6 +291,7 @@ impl StaticCondvar { #[unstable(feature = "static_condvar", reason = "may be merged with Condvar in the future", issue = "27717")] + #[deprecated(since = "1.6.0", reason = "replaced by `std::sync::StaticCondvar::wait_timeout`")] pub fn wait_timeout_ms<'a, T>(&'static self, guard: MutexGuard<'a, T>, ms: u32) -> LockResult<(MutexGuard<'a, T>, bool)> { match self.wait_timeout(guard, Duration::from_millis(ms as u64)) { diff --git a/src/libstd/sync/mutex.rs b/src/libstd/sync/mutex.rs index c0cd6d127d285..48631bfc5f9de 100644 --- a/src/libstd/sync/mutex.rs +++ b/src/libstd/sync/mutex.rs @@ -66,7 +66,7 @@ use sys_common::poison::{self, TryLockError, TryLockResult, LockResult}; /// for _ in 0..10 { /// let (data, tx) = (data.clone(), tx.clone()); /// thread::spawn(move || { -/// // The shared static can only be accessed once the lock is held. +/// // The shared state can only be accessed once the lock is held. /// // Our non-atomic increment is safe because we're the only thread /// // which can access the shared state when the lock is held. /// // diff --git a/src/libstd/sys/common/net.rs b/src/libstd/sys/common/net.rs index 37379596251de..449cd9d8c97a1 100644 --- a/src/libstd/sys/common/net.rs +++ b/src/libstd/sys/common/net.rs @@ -13,13 +13,13 @@ use prelude::v1::*; use ffi::{CStr, CString}; use fmt; use io::{self, Error, ErrorKind}; -use libc::{self, c_int, c_char, c_void, socklen_t}; +use libc::{c_int, c_char, c_void}; use mem; use net::{SocketAddr, Shutdown, IpAddr}; use ptr; use str::from_utf8; -use sys::c; use sys::net::{cvt, cvt_r, cvt_gai, Socket, init, wrlen_t}; +use sys::net::netc as c; use sys_common::{AsInner, FromInner, IntoInner}; use time::Duration; @@ -31,8 +31,8 @@ pub fn setsockopt(sock: &Socket, opt: c_int, val: c_int, payload: T) -> io::Result<()> { unsafe { let payload = &payload as *const T as *const c_void; - try!(cvt(libc::setsockopt(*sock.as_inner(), opt, val, payload, - mem::size_of::() as socklen_t))); + try!(cvt(c::setsockopt(*sock.as_inner(), opt, val, payload, + mem::size_of::() as c::socklen_t))); Ok(()) } } @@ -41,7 +41,7 @@ pub fn getsockopt(sock: &Socket, opt: c_int, val: c_int) -> io::Result { unsafe { let mut slot: T = mem::zeroed(); - let mut len = mem::size_of::() as socklen_t; + let mut len = mem::size_of::() as c::socklen_t; try!(cvt(c::getsockopt(*sock.as_inner(), opt, val, &mut slot as *mut _ as *mut _, &mut len))); @@ -51,29 +51,29 @@ pub fn getsockopt(sock: &Socket, opt: c_int, } fn sockname(f: F) -> io::Result - where F: FnOnce(*mut libc::sockaddr, *mut socklen_t) -> c_int + where F: FnOnce(*mut c::sockaddr, *mut c::socklen_t) -> c_int { unsafe { - let mut storage: libc::sockaddr_storage = mem::zeroed(); - let mut len = mem::size_of_val(&storage) as socklen_t; + let mut storage: c::sockaddr_storage = mem::zeroed(); + let mut len = mem::size_of_val(&storage) as c::socklen_t; try!(cvt(f(&mut storage as *mut _ as *mut _, &mut len))); sockaddr_to_addr(&storage, len as usize) } } -fn sockaddr_to_addr(storage: &libc::sockaddr_storage, +fn sockaddr_to_addr(storage: &c::sockaddr_storage, len: usize) -> io::Result { - match storage.ss_family as libc::c_int { - libc::AF_INET => { - assert!(len as usize >= mem::size_of::()); + match storage.ss_family as c_int { + c::AF_INET => { + assert!(len as usize >= mem::size_of::()); Ok(SocketAddr::V4(FromInner::from_inner(unsafe { - *(storage as *const _ as *const libc::sockaddr_in) + *(storage as *const _ as *const c::sockaddr_in) }))) } - libc::AF_INET6 => { - assert!(len as usize >= mem::size_of::()); + c::AF_INET6 => { + assert!(len as usize >= mem::size_of::()); Ok(SocketAddr::V6(FromInner::from_inner(unsafe { - *(storage as *const _ as *const libc::sockaddr_in6) + *(storage as *const _ as *const c::sockaddr_in6) }))) } _ => { @@ -86,16 +86,9 @@ fn sockaddr_to_addr(storage: &libc::sockaddr_storage, // get_host_addresses //////////////////////////////////////////////////////////////////////////////// -extern "system" { - fn getaddrinfo(node: *const c_char, service: *const c_char, - hints: *const libc::addrinfo, - res: *mut *mut libc::addrinfo) -> c_int; - fn freeaddrinfo(res: *mut libc::addrinfo); -} - pub struct LookupHost { - original: *mut libc::addrinfo, - cur: *mut libc::addrinfo, + original: *mut c::addrinfo, + cur: *mut c::addrinfo, } impl Iterator for LookupHost { @@ -105,7 +98,7 @@ impl Iterator for LookupHost { if self.cur.is_null() { return None } let ret = sockaddr_to_addr(mem::transmute((*self.cur).ai_addr), (*self.cur).ai_addrlen as usize); - self.cur = (*self.cur).ai_next as *mut libc::addrinfo; + self.cur = (*self.cur).ai_next as *mut c::addrinfo; Some(ret) } } @@ -116,7 +109,7 @@ unsafe impl Send for LookupHost {} impl Drop for LookupHost { fn drop(&mut self) { - unsafe { freeaddrinfo(self.original) } + unsafe { c::freeaddrinfo(self.original) } } } @@ -126,8 +119,8 @@ pub fn lookup_host(host: &str) -> io::Result { let c_host = try!(CString::new(host)); let mut res = ptr::null_mut(); unsafe { - try!(cvt_gai(getaddrinfo(c_host.as_ptr(), ptr::null(), ptr::null(), - &mut res))); + try!(cvt_gai(c::getaddrinfo(c_host.as_ptr(), ptr::null(), ptr::null(), + &mut res))); Ok(LookupHost { original: res, cur: res }) } } @@ -136,26 +129,18 @@ pub fn lookup_host(host: &str) -> io::Result { // lookup_addr //////////////////////////////////////////////////////////////////////////////// -extern "system" { - fn getnameinfo(sa: *const libc::sockaddr, salen: socklen_t, - host: *mut c_char, hostlen: libc::size_t, - serv: *mut c_char, servlen: libc::size_t, - flags: c_int) -> c_int; -} - -const NI_MAXHOST: usize = 1025; - pub fn lookup_addr(addr: &IpAddr) -> io::Result { init(); let saddr = SocketAddr::new(*addr, 0); let (inner, len) = saddr.into_inner(); - let mut hostbuf = [0 as c_char; NI_MAXHOST]; + let mut hostbuf = [0 as c_char; c::NI_MAXHOST as usize]; let data = unsafe { - try!(cvt_gai(getnameinfo(inner, len, - hostbuf.as_mut_ptr(), NI_MAXHOST as libc::size_t, - ptr::null_mut(), 0, 0))); + try!(cvt_gai(c::getnameinfo(inner, len, + hostbuf.as_mut_ptr(), + c::NI_MAXHOST, + ptr::null_mut(), 0, 0))); CStr::from_ptr(hostbuf.as_ptr()) }; @@ -179,10 +164,10 @@ impl TcpStream { pub fn connect(addr: &SocketAddr) -> io::Result { init(); - let sock = try!(Socket::new(addr, libc::SOCK_STREAM)); + let sock = try!(Socket::new(addr, c::SOCK_STREAM)); let (addrp, len) = addr.into_inner(); - try!(cvt_r(|| unsafe { libc::connect(*sock.as_inner(), addrp, len) })); + try!(cvt_r(|| unsafe { c::connect(*sock.as_inner(), addrp, len) })); Ok(TcpStream { inner: sock }) } @@ -191,19 +176,19 @@ impl TcpStream { pub fn into_socket(self) -> Socket { self.inner } pub fn set_read_timeout(&self, dur: Option) -> io::Result<()> { - self.inner.set_timeout(dur, libc::SO_RCVTIMEO) + self.inner.set_timeout(dur, c::SO_RCVTIMEO) } pub fn set_write_timeout(&self, dur: Option) -> io::Result<()> { - self.inner.set_timeout(dur, libc::SO_SNDTIMEO) + self.inner.set_timeout(dur, c::SO_SNDTIMEO) } pub fn read_timeout(&self) -> io::Result> { - self.inner.timeout(libc::SO_RCVTIMEO) + self.inner.timeout(c::SO_RCVTIMEO) } pub fn write_timeout(&self) -> io::Result> { - self.inner.timeout(libc::SO_SNDTIMEO) + self.inner.timeout(c::SO_SNDTIMEO) } pub fn read(&self, buf: &mut [u8]) -> io::Result { @@ -212,36 +197,28 @@ impl TcpStream { pub fn write(&self, buf: &[u8]) -> io::Result { let ret = try!(cvt(unsafe { - libc::send(*self.inner.as_inner(), - buf.as_ptr() as *const c_void, - buf.len() as wrlen_t, - 0) + c::send(*self.inner.as_inner(), + buf.as_ptr() as *const c_void, + buf.len() as wrlen_t, + 0) })); Ok(ret as usize) } pub fn peer_addr(&self) -> io::Result { sockname(|buf, len| unsafe { - libc::getpeername(*self.inner.as_inner(), buf, len) + c::getpeername(*self.inner.as_inner(), buf, len) }) } pub fn socket_addr(&self) -> io::Result { sockname(|buf, len| unsafe { - libc::getsockname(*self.inner.as_inner(), buf, len) + c::getsockname(*self.inner.as_inner(), buf, len) }) } pub fn shutdown(&self, how: Shutdown) -> io::Result<()> { - use libc::consts::os::bsd44::SHUT_RDWR; - - let how = match how { - Shutdown::Write => libc::SHUT_WR, - Shutdown::Read => libc::SHUT_RD, - Shutdown::Both => SHUT_RDWR, - }; - try!(cvt(unsafe { libc::shutdown(*self.inner.as_inner(), how) })); - Ok(()) + self.inner.shutdown(how) } pub fn duplicate(&self) -> io::Result { @@ -285,22 +262,22 @@ impl TcpListener { pub fn bind(addr: &SocketAddr) -> io::Result { init(); - let sock = try!(Socket::new(addr, libc::SOCK_STREAM)); + let sock = try!(Socket::new(addr, c::SOCK_STREAM)); // On platforms with Berkeley-derived sockets, this allows // to quickly rebind a socket, without needing to wait for // the OS to clean up the previous one. if !cfg!(windows) { - try!(setsockopt(&sock, libc::SOL_SOCKET, libc::SO_REUSEADDR, + try!(setsockopt(&sock, c::SOL_SOCKET, c::SO_REUSEADDR, 1 as c_int)); } // Bind our new socket let (addrp, len) = addr.into_inner(); - try!(cvt(unsafe { libc::bind(*sock.as_inner(), addrp, len) })); + try!(cvt(unsafe { c::bind(*sock.as_inner(), addrp, len) })); // Start listening - try!(cvt(unsafe { libc::listen(*sock.as_inner(), 128) })); + try!(cvt(unsafe { c::listen(*sock.as_inner(), 128) })); Ok(TcpListener { inner: sock }) } @@ -310,13 +287,13 @@ impl TcpListener { pub fn socket_addr(&self) -> io::Result { sockname(|buf, len| unsafe { - libc::getsockname(*self.inner.as_inner(), buf, len) + c::getsockname(*self.inner.as_inner(), buf, len) }) } pub fn accept(&self) -> io::Result<(TcpStream, SocketAddr)> { - let mut storage: libc::sockaddr_storage = unsafe { mem::zeroed() }; - let mut len = mem::size_of_val(&storage) as socklen_t; + let mut storage: c::sockaddr_storage = unsafe { mem::zeroed() }; + let mut len = mem::size_of_val(&storage) as c::socklen_t; let sock = try!(self.inner.accept(&mut storage as *mut _ as *mut _, &mut len)); let addr = try!(sockaddr_to_addr(&storage, len as usize)); @@ -360,9 +337,9 @@ impl UdpSocket { pub fn bind(addr: &SocketAddr) -> io::Result { init(); - let sock = try!(Socket::new(addr, libc::SOCK_DGRAM)); + let sock = try!(Socket::new(addr, c::SOCK_DGRAM)); let (addrp, len) = addr.into_inner(); - try!(cvt(unsafe { libc::bind(*sock.as_inner(), addrp, len) })); + try!(cvt(unsafe { c::bind(*sock.as_inner(), addrp, len) })); Ok(UdpSocket { inner: sock }) } @@ -372,19 +349,19 @@ impl UdpSocket { pub fn socket_addr(&self) -> io::Result { sockname(|buf, len| unsafe { - libc::getsockname(*self.inner.as_inner(), buf, len) + c::getsockname(*self.inner.as_inner(), buf, len) }) } pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> { - let mut storage: libc::sockaddr_storage = unsafe { mem::zeroed() }; - let mut addrlen = mem::size_of_val(&storage) as socklen_t; + let mut storage: c::sockaddr_storage = unsafe { mem::zeroed() }; + let mut addrlen = mem::size_of_val(&storage) as c::socklen_t; let n = try!(cvt(unsafe { - libc::recvfrom(*self.inner.as_inner(), - buf.as_mut_ptr() as *mut c_void, - buf.len() as wrlen_t, 0, - &mut storage as *mut _ as *mut _, &mut addrlen) + c::recvfrom(*self.inner.as_inner(), + buf.as_mut_ptr() as *mut c_void, + buf.len() as wrlen_t, 0, + &mut storage as *mut _ as *mut _, &mut addrlen) })); Ok((n as usize, try!(sockaddr_to_addr(&storage, addrlen as usize)))) } @@ -392,9 +369,9 @@ impl UdpSocket { pub fn send_to(&self, buf: &[u8], dst: &SocketAddr) -> io::Result { let (dstp, dstlen) = dst.into_inner(); let ret = try!(cvt(unsafe { - libc::sendto(*self.inner.as_inner(), - buf.as_ptr() as *const c_void, buf.len() as wrlen_t, - 0, dstp, dstlen) + c::sendto(*self.inner.as_inner(), + buf.as_ptr() as *const c_void, buf.len() as wrlen_t, + 0, dstp, dstlen) })); Ok(ret as usize) } @@ -404,19 +381,19 @@ impl UdpSocket { } pub fn set_read_timeout(&self, dur: Option) -> io::Result<()> { - self.inner.set_timeout(dur, libc::SO_RCVTIMEO) + self.inner.set_timeout(dur, c::SO_RCVTIMEO) } pub fn set_write_timeout(&self, dur: Option) -> io::Result<()> { - self.inner.set_timeout(dur, libc::SO_SNDTIMEO) + self.inner.set_timeout(dur, c::SO_SNDTIMEO) } pub fn read_timeout(&self) -> io::Result> { - self.inner.timeout(libc::SO_RCVTIMEO) + self.inner.timeout(c::SO_RCVTIMEO) } pub fn write_timeout(&self) -> io::Result> { - self.inner.timeout(libc::SO_SNDTIMEO) + self.inner.timeout(c::SO_SNDTIMEO) } } diff --git a/src/libstd/sys/common/unwind/seh.rs b/src/libstd/sys/common/unwind/seh.rs index a89e8b499acce..7296194efda5e 100644 --- a/src/libstd/sys/common/unwind/seh.rs +++ b/src/libstd/sys/common/unwind/seh.rs @@ -52,45 +52,14 @@ use prelude::v1::*; use any::Any; -use libc::{c_ulong, DWORD, c_void}; use ptr; use sys_common::thread_local::StaticKey; +use sys::c; -// 0x R U S T -const RUST_PANIC: DWORD = 0x52555354; +// 0x R U S T +const RUST_PANIC: c::DWORD = 0x52555354; static PANIC_DATA: StaticKey = StaticKey::new(None); -// This function is provided by kernel32.dll -extern "system" { - #[unwind] - fn RaiseException(dwExceptionCode: DWORD, - dwExceptionFlags: DWORD, - nNumberOfArguments: DWORD, - lpArguments: *const c_ulong); -} - -#[repr(C)] -pub struct EXCEPTION_POINTERS { - ExceptionRecord: *mut EXCEPTION_RECORD, - ContextRecord: *mut CONTEXT, -} - -enum CONTEXT {} - -#[repr(C)] -struct EXCEPTION_RECORD { - ExceptionCode: DWORD, - ExceptionFlags: DWORD, - ExceptionRecord: *mut _EXCEPTION_RECORD, - ExceptionAddress: *mut c_void, - NumberParameters: DWORD, - ExceptionInformation: [*mut c_ulong; EXCEPTION_MAXIMUM_PARAMETERS], -} - -enum _EXCEPTION_RECORD {} - -const EXCEPTION_MAXIMUM_PARAMETERS: usize = 15; - pub unsafe fn panic(data: Box) -> ! { // See module docs above for an explanation of why `data` is stored in a // thread local instead of being passed as an argument to the @@ -100,14 +69,14 @@ pub unsafe fn panic(data: Box) -> ! { rtassert!(PANIC_DATA.get().is_null()); PANIC_DATA.set(Box::into_raw(exception) as *mut u8); - RaiseException(RUST_PANIC, 0, 0, ptr::null()); + c::RaiseException(RUST_PANIC, 0, 0, ptr::null()); rtabort!("could not unwind stack"); } pub unsafe fn cleanup(ptr: *mut u8) -> Box { // The `ptr` here actually corresponds to the code of the exception, and our // real data is stored in our thread local. - rtassert!(ptr as DWORD == RUST_PANIC); + rtassert!(ptr as c::DWORD == RUST_PANIC); let data = PANIC_DATA.get() as *mut Box; PANIC_DATA.set(ptr::null_mut()); @@ -139,7 +108,7 @@ fn rust_eh_personality() { #[lang = "msvc_try_filter"] #[linkage = "external"] #[allow(private_no_mangle_fns)] -extern fn __rust_try_filter(eh_ptrs: *mut EXCEPTION_POINTERS, +extern fn __rust_try_filter(eh_ptrs: *mut c::EXCEPTION_POINTERS, _rbp: *mut u8) -> i32 { unsafe { ((*(*eh_ptrs).ExceptionRecord).ExceptionCode == RUST_PANIC) as i32 diff --git a/src/libstd/sys/common/unwind/seh64_gnu.rs b/src/libstd/sys/common/unwind/seh64_gnu.rs index 92f059d68e1a3..26c2cee9222db 100644 --- a/src/libstd/sys/common/unwind/seh64_gnu.rs +++ b/src/libstd/sys/common/unwind/seh64_gnu.rs @@ -17,12 +17,10 @@ use prelude::v1::*; use any::Any; -use self::EXCEPTION_DISPOSITION::*; use sys_common::dwarf::eh; use core::mem; use core::ptr; -use libc::{c_void, c_ulonglong, DWORD, LPVOID}; -type ULONG_PTR = c_ulonglong; +use sys::c; // Define our exception codes: // according to http://msdn.microsoft.com/en-us/library/het71c37(v=VS.80).aspx, @@ -32,80 +30,10 @@ type ULONG_PTR = c_ulonglong; // we define bits: // [24:27] = type // [0:23] = magic -const ETYPE: DWORD = 0b1110_u32 << 28; -const MAGIC: DWORD = 0x525354; // "RST" +const ETYPE: c::DWORD = 0b1110_u32 << 28; +const MAGIC: c::DWORD = 0x525354; // "RST" -const RUST_PANIC: DWORD = ETYPE | (1 << 24) | MAGIC; - -const EXCEPTION_NONCONTINUABLE: DWORD = 0x1; // Noncontinuable exception -const EXCEPTION_UNWINDING: DWORD = 0x2; // Unwind is in progress -const EXCEPTION_EXIT_UNWIND: DWORD = 0x4; // Exit unwind is in progress -const EXCEPTION_STACK_INVALID: DWORD = 0x8; // Stack out of limits or unaligned -const EXCEPTION_NESTED_CALL: DWORD = 0x10; // Nested exception handler call -const EXCEPTION_TARGET_UNWIND: DWORD = 0x20; // Target unwind in progress -const EXCEPTION_COLLIDED_UNWIND: DWORD = 0x40; // Collided exception handler call -const EXCEPTION_UNWIND: DWORD = EXCEPTION_UNWINDING | - EXCEPTION_EXIT_UNWIND | - EXCEPTION_TARGET_UNWIND | - EXCEPTION_COLLIDED_UNWIND; - -#[repr(C)] -pub struct EXCEPTION_RECORD { - ExceptionCode: DWORD, - ExceptionFlags: DWORD, - ExceptionRecord: *const EXCEPTION_RECORD, - ExceptionAddress: LPVOID, - NumberParameters: DWORD, - ExceptionInformation: [ULONG_PTR; 15], -} - -pub enum CONTEXT {} -pub enum UNWIND_HISTORY_TABLE {} - -#[repr(C)] -pub struct RUNTIME_FUNCTION { - BeginAddress: DWORD, - EndAddress: DWORD, - UnwindData: DWORD, -} - -#[repr(C)] -pub struct DISPATCHER_CONTEXT { - ControlPc: LPVOID, - ImageBase: LPVOID, - FunctionEntry: *const RUNTIME_FUNCTION, - EstablisherFrame: LPVOID, - TargetIp: LPVOID, - ContextRecord: *const CONTEXT, - LanguageHandler: LPVOID, - HandlerData: *const u8, - HistoryTable: *const UNWIND_HISTORY_TABLE, -} - -#[repr(C)] -#[derive(Copy, Clone)] -pub enum EXCEPTION_DISPOSITION { - ExceptionContinueExecution, - ExceptionContinueSearch, - ExceptionNestedException, - ExceptionCollidedUnwind -} - -// From kernel32.dll -extern "system" { - #[unwind] - fn RaiseException(dwExceptionCode: DWORD, - dwExceptionFlags: DWORD, - nNumberOfArguments: DWORD, - lpArguments: *const ULONG_PTR); - - fn RtlUnwindEx(TargetFrame: LPVOID, - TargetIp: LPVOID, - ExceptionRecord: *const EXCEPTION_RECORD, - ReturnValue: LPVOID, - OriginalContext: *const CONTEXT, - HistoryTable: *const UNWIND_HISTORY_TABLE); -} +const RUST_PANIC: c::DWORD = ETYPE | (1 << 24) | MAGIC; #[repr(C)] struct PanicData { @@ -114,11 +42,11 @@ struct PanicData { pub unsafe fn panic(data: Box) -> ! { let panic_ctx = Box::new(PanicData { data: data }); - let params = [Box::into_raw(panic_ctx) as ULONG_PTR]; - RaiseException(RUST_PANIC, - EXCEPTION_NONCONTINUABLE, - params.len() as DWORD, - ¶ms as *const ULONG_PTR); + let params = [Box::into_raw(panic_ctx) as c::ULONG_PTR]; + c::RaiseException(RUST_PANIC, + c::EXCEPTION_NONCONTINUABLE, + params.len() as c::DWORD, + ¶ms as *const c::ULONG_PTR); rtabort!("could not unwind stack"); } @@ -152,11 +80,11 @@ pub unsafe fn cleanup(ptr: *mut u8) -> Box { #[lang = "eh_personality_catch"] #[cfg(not(test))] unsafe extern fn rust_eh_personality_catch( - exceptionRecord: *mut EXCEPTION_RECORD, - establisherFrame: LPVOID, - contextRecord: *mut CONTEXT, - dispatcherContext: *mut DISPATCHER_CONTEXT -) -> EXCEPTION_DISPOSITION + exceptionRecord: *mut c::EXCEPTION_RECORD, + establisherFrame: c::LPVOID, + contextRecord: *mut c::CONTEXT, + dispatcherContext: *mut c::DISPATCHER_CONTEXT +) -> c::EXCEPTION_DISPOSITION { rust_eh_personality(exceptionRecord, establisherFrame, contextRecord, dispatcherContext) @@ -165,44 +93,44 @@ unsafe extern fn rust_eh_personality_catch( #[lang = "eh_personality"] #[cfg(not(test))] unsafe extern fn rust_eh_personality( - exceptionRecord: *mut EXCEPTION_RECORD, - establisherFrame: LPVOID, - contextRecord: *mut CONTEXT, - dispatcherContext: *mut DISPATCHER_CONTEXT -) -> EXCEPTION_DISPOSITION + exceptionRecord: *mut c::EXCEPTION_RECORD, + establisherFrame: c::LPVOID, + contextRecord: *mut c::CONTEXT, + dispatcherContext: *mut c::DISPATCHER_CONTEXT +) -> c::EXCEPTION_DISPOSITION { let er = &*exceptionRecord; let dc = &*dispatcherContext; - if er.ExceptionFlags & EXCEPTION_UNWIND == 0 { // we are in the dispatch phase + if er.ExceptionFlags & c::EXCEPTION_UNWIND == 0 { // we are in the dispatch phase if er.ExceptionCode == RUST_PANIC { if let Some(lpad) = find_landing_pad(dc) { - RtlUnwindEx(establisherFrame, - lpad as LPVOID, - exceptionRecord, - er.ExceptionInformation[0] as LPVOID, // pointer to PanicData - contextRecord, - dc.HistoryTable); + c::RtlUnwindEx(establisherFrame, + lpad as c::LPVOID, + exceptionRecord, + er.ExceptionInformation[0] as c::LPVOID, // pointer to PanicData + contextRecord, + dc.HistoryTable); rtabort!("could not unwind"); } } } - ExceptionContinueSearch + c::ExceptionContinueSearch } #[cfg(not(test))] #[lang = "eh_unwind_resume"] #[unwind] -unsafe extern fn rust_eh_unwind_resume(panic_ctx: LPVOID) -> ! { - let params = [panic_ctx as ULONG_PTR]; - RaiseException(RUST_PANIC, - EXCEPTION_NONCONTINUABLE, - params.len() as DWORD, - ¶ms as *const ULONG_PTR); +unsafe extern fn rust_eh_unwind_resume(panic_ctx: c::LPVOID) -> ! { + let params = [panic_ctx as c::ULONG_PTR]; + c::RaiseException(RUST_PANIC, + c::EXCEPTION_NONCONTINUABLE, + params.len() as c::DWORD, + ¶ms as *const c::ULONG_PTR); rtabort!("could not resume unwind"); } -unsafe fn find_landing_pad(dc: &DISPATCHER_CONTEXT) -> Option { +unsafe fn find_landing_pad(dc: &c::DISPATCHER_CONTEXT) -> Option { let eh_ctx = eh::EHContext { ip: dc.ControlPc as usize, func_start: dc.ImageBase as usize + (*dc.FunctionEntry).BeginAddress as usize, diff --git a/src/libstd/sys/unix/c.rs b/src/libstd/sys/unix/c.rs deleted file mode 100644 index fc6af6447d2fd..0000000000000 --- a/src/libstd/sys/unix/c.rs +++ /dev/null @@ -1,452 +0,0 @@ -// Copyright 2014-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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! C definitions used by std::sys that don't belong in liblibc - -// These are definitions sufficient for the users in this directory. -// This is not a general-purpose binding to this functionality, and in -// some cases (notably the definition of siginfo_t), we intentionally -// have incomplete bindings so that we don't need to fight with unions. -// -// Note that these types need to match the definitions from the platform -// libc (currently glibc on Linux), not the kernel definitions / the -// syscall interface. This has a few weirdnesses, like glibc's sigset_t -// being 1024 bits on all platforms. If you're adding a new GNU/Linux -// port, check glibc's sysdeps/unix/sysv/linux, not the kernel headers. - -#![allow(dead_code)] -#![allow(non_camel_case_types)] - -pub use self::signal_os::*; -use libc; - -#[cfg(any(target_os = "macos", - target_os = "ios", - target_os = "freebsd", - target_os = "dragonfly", - target_os = "bitrig", - target_os = "netbsd", - target_os = "openbsd"))] -pub const FIOCLEX: libc::c_ulong = 0x20006601; - -#[cfg(any(all(target_os = "linux", - any(target_arch = "x86", - target_arch = "x86_64", - target_arch = "arm", - target_arch = "aarch64")), - target_os = "android"))] -pub const FIOCLEX: libc::c_ulong = 0x5451; - -#[cfg(all(target_os = "linux", - any(target_arch = "mips", - target_arch = "mipsel", - target_arch = "powerpc")))] -pub const FIOCLEX: libc::c_ulong = 0x6601; - -#[cfg(target_env = "newlib")] -pub const FD_CLOEXEC: libc::c_int = 1; -#[cfg(target_env = "newlib")] -pub const F_GETFD: libc::c_int = 1; -#[cfg(target_env = "newlib")] -pub const F_SETFD: libc::c_int = 2; - -pub const WNOHANG: libc::c_int = 1; - -#[cfg(target_os = "linux")] -pub const _SC_GETPW_R_SIZE_MAX: libc::c_int = 70; -#[cfg(any(target_os = "macos", - target_os = "freebsd", - target_os = "dragonfly"))] -pub const _SC_GETPW_R_SIZE_MAX: libc::c_int = 71; -#[cfg(any(target_os = "bitrig", - target_os = "openbsd"))] -pub const _SC_GETPW_R_SIZE_MAX: libc::c_int = 101; -#[cfg(target_os = "netbsd")] -pub const _SC_GETPW_R_SIZE_MAX: libc::c_int = 48; -#[cfg(target_os = "android")] -pub const _SC_GETPW_R_SIZE_MAX: libc::c_int = 0x0048; - -#[repr(C)] -#[cfg(target_os = "linux")] -pub struct passwd { - pub pw_name: *mut libc::c_char, - pub pw_passwd: *mut libc::c_char, - pub pw_uid: libc::uid_t, - pub pw_gid: libc::gid_t, - pub pw_gecos: *mut libc::c_char, - pub pw_dir: *mut libc::c_char, - pub pw_shell: *mut libc::c_char, -} -#[repr(C)] -#[cfg(target_env = "newlib")] -pub struct passwd { - pub pw_name: *mut libc::c_char, - pub pw_passwd: *mut libc::c_char, - pub pw_uid: libc::uid_t, - pub pw_gid: libc::gid_t, - pub pw_comment: *mut libc::c_char, - pub pw_gecos: *mut libc::c_char, - pub pw_dir: *mut libc::c_char, - pub pw_shell: *mut libc::c_char, -} - -#[repr(C)] -#[cfg(any(target_os = "macos", - target_os = "freebsd", - target_os = "dragonfly", - target_os = "bitrig", - target_os = "netbsd", - target_os = "openbsd"))] -pub struct passwd { - pub pw_name: *mut libc::c_char, - pub pw_passwd: *mut libc::c_char, - pub pw_uid: libc::uid_t, - pub pw_gid: libc::gid_t, - pub pw_change: libc::time_t, - pub pw_class: *mut libc::c_char, - pub pw_gecos: *mut libc::c_char, - pub pw_dir: *mut libc::c_char, - pub pw_shell: *mut libc::c_char, - pub pw_expire: libc::time_t, -} - -#[repr(C)] -#[cfg(target_os = "android")] -pub struct passwd { - pub pw_name: *mut libc::c_char, - pub pw_passwd: *mut libc::c_char, - pub pw_uid: libc::uid_t, - pub pw_gid: libc::gid_t, - pub pw_dir: *mut libc::c_char, - pub pw_shell: *mut libc::c_char, -} - -// This is really a function pointer (or a union of multiple function -// pointers), except for constants like SIG_DFL. -pub type sighandler_t = *mut libc::c_void; - -pub const SIG_DFL: sighandler_t = 0 as sighandler_t; -pub const SIG_ERR: sighandler_t = !0 as sighandler_t; - -extern { - pub fn getsockopt(sockfd: libc::c_int, - level: libc::c_int, - optname: libc::c_int, - optval: *mut libc::c_void, - optlen: *mut libc::socklen_t) -> libc::c_int; - #[cfg(not(target_env = "newlib"))] - pub fn ioctl(fd: libc::c_int, req: libc::c_ulong, ...) -> libc::c_int; - #[cfg(target_env = "newlib")] - pub fn fnctl(fd: libc::c_int, req: libc::c_int, ...) -> libc::c_int; - - - pub fn waitpid(pid: libc::pid_t, status: *mut libc::c_int, - options: libc::c_int) -> libc::pid_t; - - pub fn raise(signum: libc::c_int) -> libc::c_int; - - #[cfg_attr(target_os = "netbsd", link_name = "__sigaction14")] - pub fn sigaction(signum: libc::c_int, - act: *const sigaction, - oldact: *mut sigaction) -> libc::c_int; - - #[cfg_attr(target_os = "netbsd", link_name = "__sigaltstack14")] - #[cfg(not(target_env = "newlib"))] - pub fn sigaltstack(ss: *const sigaltstack, - oss: *mut sigaltstack) -> libc::c_int; - - #[cfg(not(target_os = "android"))] - #[cfg_attr(target_os = "netbsd", link_name = "__sigemptyset14")] - pub fn sigemptyset(set: *mut sigset_t) -> libc::c_int; - - pub fn pthread_sigmask(how: libc::c_int, set: *const sigset_t, - oldset: *mut sigset_t) -> libc::c_int; - - #[cfg(not(target_os = "ios"))] - #[cfg_attr(target_os = "netbsd", link_name = "__getpwuid_r50")] - pub fn getpwuid_r(uid: libc::uid_t, - pwd: *mut passwd, - buf: *mut libc::c_char, - buflen: libc::size_t, - result: *mut *mut passwd) -> libc::c_int; - - #[cfg_attr(target_os = "netbsd", link_name = "__utimes50")] - pub fn utimes(filename: *const libc::c_char, - times: *const libc::timeval) -> libc::c_int; - pub fn gai_strerror(errcode: libc::c_int) -> *const libc::c_char; - /// Newlib has this, but only for Cygwin. - #[cfg(not(target_os = "nacl"))] - pub fn setgroups(ngroups: libc::c_int, - ptr: *const libc::c_void) -> libc::c_int; - pub fn realpath(pathname: *const libc::c_char, resolved: *mut libc::c_char) - -> *mut libc::c_char; -} - -// Ugh. This is only available as an inline until Android API 21. -#[cfg(target_os = "android")] -pub unsafe fn sigemptyset(set: *mut sigset_t) -> libc::c_int { - use intrinsics; - intrinsics::write_bytes(set, 0, 1); - return 0; -} - -#[cfg(any(target_os = "linux", - target_os = "android"))] -mod signal_os { - pub use self::arch::{SA_ONSTACK, SA_SIGINFO, SIGBUS, SIG_SETMASK, - sigaction, sigaltstack}; - use libc; - - #[cfg(any(target_arch = "x86", - target_arch = "x86_64", - target_arch = "arm", - target_arch = "mips", - target_arch = "mipsel"))] - pub const SIGSTKSZ: libc::size_t = 8192; - - // This is smaller on musl and Android, but no harm in being generous. - #[cfg(any(target_arch = "aarch64", - target_arch = "powerpc"))] - pub const SIGSTKSZ: libc::size_t = 16384; - - // This definition is intentionally a subset of the C structure: the - // fields after si_code are actually a giant union. We're only - // interested in si_addr for this module, though. - #[repr(C)] - pub struct siginfo { - _signo: libc::c_int, - _errno: libc::c_int, - _code: libc::c_int, - // This structure will need extra padding here for MIPS64. - pub si_addr: *mut libc::c_void - } - - #[cfg(all(target_os = "linux", target_pointer_width = "32"))] - #[repr(C)] - pub struct sigset_t { - __val: [libc::c_ulong; 32], - } - - #[cfg(all(target_os = "linux", target_pointer_width = "64"))] - #[repr(C)] - pub struct sigset_t { - __val: [libc::c_ulong; 16], - } - - // Android for MIPS has a 128-bit sigset_t, but we don't currently - // support it. Android for AArch64 technically has a structure of a - // single ulong. - #[cfg(target_os = "android")] - pub type sigset_t = libc::c_ulong; - - #[cfg(any(target_arch = "x86", - target_arch = "x86_64", - target_arch = "powerpc", - target_arch = "arm", - target_arch = "aarch64"))] - mod arch { - use libc; - use super::super::sighandler_t; - use super::sigset_t; - - pub const SA_ONSTACK: libc::c_ulong = 0x08000000; - pub const SA_SIGINFO: libc::c_ulong = 0x00000004; - - pub const SIGBUS: libc::c_int = 7; - - pub const SIG_SETMASK: libc::c_int = 2; - - #[cfg(target_os = "linux")] - #[repr(C)] - pub struct sigaction { - pub sa_sigaction: sighandler_t, - pub sa_mask: sigset_t, - pub sa_flags: libc::c_ulong, - _restorer: *mut libc::c_void, - } - - #[cfg(all(target_os = "android", target_pointer_width = "32"))] - #[repr(C)] - pub struct sigaction { - pub sa_sigaction: sighandler_t, - pub sa_flags: libc::c_ulong, - _restorer: *mut libc::c_void, - pub sa_mask: sigset_t, - } - - #[cfg(all(target_os = "android", target_pointer_width = "64"))] - #[repr(C)] - pub struct sigaction { - pub sa_flags: libc::c_uint, - pub sa_sigaction: sighandler_t, - pub sa_mask: sigset_t, - _restorer: *mut libc::c_void, - } - - #[repr(C)] - pub struct sigaltstack { - pub ss_sp: *mut libc::c_void, - pub ss_flags: libc::c_int, - pub ss_size: libc::size_t - } - } - - #[cfg(any(target_arch = "mips", - target_arch = "mipsel"))] - mod arch { - use libc; - use super::super::sighandler_t; - use super::sigset_t; - - pub const SA_ONSTACK: libc::c_ulong = 0x08000000; - pub const SA_SIGINFO: libc::c_ulong = 0x00000008; - - pub const SIGBUS: libc::c_int = 10; - - pub const SIG_SETMASK: libc::c_int = 3; - - #[cfg(all(target_os = "linux", not(target_env = "musl")))] - #[repr(C)] - pub struct sigaction { - pub sa_flags: libc::c_uint, - pub sa_sigaction: sighandler_t, - pub sa_mask: sigset_t, - _restorer: *mut libc::c_void, - _resv: [libc::c_int; 1], - } - - #[cfg(target_env = "musl")] - #[repr(C)] - pub struct sigaction { - pub sa_sigaction: sighandler_t, - pub sa_mask: sigset_t, - pub sa_flags: libc::c_ulong, - _restorer: *mut libc::c_void, - } - - #[cfg(target_os = "android")] - #[repr(C)] - pub struct sigaction { - pub sa_flags: libc::c_uint, - pub sa_sigaction: sighandler_t, - pub sa_mask: sigset_t, - } - - #[repr(C)] - pub struct sigaltstack { - pub ss_sp: *mut libc::c_void, - pub ss_size: libc::size_t, - pub ss_flags: libc::c_int, - } - } -} - -/// Note: Although the signal functions are defined on NaCl, they always fail. -/// Also, this could be cfg-ed on newlib instead of nacl, but these structures -/// can differ depending on the platform, so I've played it safe here. -#[cfg(target_os = "nacl")] -mod signal_os { - use libc; - - pub static SA_NOCLDSTOP: libc::c_ulong = 1; - pub static SA_SIGINFO: libc::c_ulong = 2; - - pub type sigset_t = libc::c_ulong; - #[repr(C)] - pub struct sigaction { - pub sa_flags: libc::c_int, - pub sa_mask: sigset_t, - pub handler: extern fn(libc::c_int), - } -} - -#[cfg(any(target_os = "macos", - target_os = "ios", - target_os = "freebsd", - target_os = "dragonfly", - target_os = "bitrig", - target_os = "netbsd", - target_os = "openbsd"))] -mod signal_os { - use libc; - use super::sighandler_t; - - pub const SA_ONSTACK: libc::c_int = 0x0001; - pub const SA_SIGINFO: libc::c_int = 0x0040; - - pub const SIGBUS: libc::c_int = 10; - - #[cfg(any(target_os = "macos", target_os = "ios"))] - pub const SIGSTKSZ: libc::size_t = 131072; - // FreeBSD's is actually arch-dependent, but never more than 40960. - // No harm in being generous. - #[cfg(not(any(target_os = "macos", target_os = "ios")))] - pub const SIGSTKSZ: libc::size_t = 40960; - - pub const SIG_SETMASK: libc::c_int = 3; - - #[cfg(any(target_os = "macos", - target_os = "ios"))] - pub type sigset_t = u32; - #[cfg(any(target_os = "freebsd", target_os = "dragonfly", target_os = "netbsd"))] - #[repr(C)] - pub struct sigset_t { - bits: [u32; 4], - } - #[cfg(any(target_os = "bitrig", target_os = "openbsd"))] - pub type sigset_t = libc::c_uint; - - // This structure has more fields, but we're not all that interested in - // them. - #[cfg(any(target_os = "macos", target_os = "ios", - target_os = "freebsd", target_os = "dragonfly"))] - #[repr(C)] - pub struct siginfo { - pub _signo: libc::c_int, - pub _errno: libc::c_int, - pub _code: libc::c_int, - pub _pid: libc::pid_t, - pub _uid: libc::uid_t, - pub _status: libc::c_int, - pub si_addr: *mut libc::c_void - } - #[cfg(any(target_os = "bitrig", target_os = "netbsd", target_os = "openbsd"))] - #[repr(C)] - pub struct siginfo { - pub si_signo: libc::c_int, - pub si_code: libc::c_int, - pub si_errno: libc::c_int, - pub si_addr: *mut libc::c_void - } - - #[cfg(any(target_os = "macos", target_os = "ios", - target_os = "bitrig", target_os = "netbsd", target_os = "openbsd"))] - #[repr(C)] - pub struct sigaction { - pub sa_sigaction: sighandler_t, - pub sa_mask: sigset_t, - pub sa_flags: libc::c_int, - } - - #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))] - #[repr(C)] - pub struct sigaction { - pub sa_sigaction: sighandler_t, - pub sa_flags: libc::c_int, - pub sa_mask: sigset_t, - } - - #[repr(C)] - pub struct sigaltstack { - pub ss_sp: *mut libc::c_void, - pub ss_size: libc::size_t, - pub ss_flags: libc::c_int, - } -} diff --git a/src/libstd/sys/unix/condvar.rs b/src/libstd/sys/unix/condvar.rs index b9538867b252d..3e0f41933e641 100644 --- a/src/libstd/sys/unix/condvar.rs +++ b/src/libstd/sys/unix/condvar.rs @@ -13,10 +13,9 @@ use libc; use ptr; use sys::mutex::{self, Mutex}; use sys::time; -use sys::sync as ffi; use time::Duration; -pub struct Condvar { inner: UnsafeCell } +pub struct Condvar { inner: UnsafeCell } unsafe impl Send for Condvar {} unsafe impl Sync for Condvar {} @@ -25,24 +24,24 @@ impl Condvar { pub const fn new() -> Condvar { // Might be moved and address is changing it is better to avoid // initialization of potentially opaque OS data before it landed - Condvar { inner: UnsafeCell::new(ffi::PTHREAD_COND_INITIALIZER) } + Condvar { inner: UnsafeCell::new(libc::PTHREAD_COND_INITIALIZER) } } #[inline] pub unsafe fn notify_one(&self) { - let r = ffi::pthread_cond_signal(self.inner.get()); + let r = libc::pthread_cond_signal(self.inner.get()); debug_assert_eq!(r, 0); } #[inline] pub unsafe fn notify_all(&self) { - let r = ffi::pthread_cond_broadcast(self.inner.get()); + let r = libc::pthread_cond_broadcast(self.inner.get()); debug_assert_eq!(r, 0); } #[inline] pub unsafe fn wait(&self, mutex: &Mutex) { - let r = ffi::pthread_cond_wait(self.inner.get(), mutex::raw(mutex)); + let r = libc::pthread_cond_wait(self.inner.get(), mutex::raw(mutex)); debug_assert_eq!(r, 0); } @@ -55,7 +54,7 @@ impl Condvar { // report timeout based on stable time. let mut sys_now = libc::timeval { tv_sec: 0, tv_usec: 0 }; let stable_now = time::SteadyTime::now(); - let r = ffi::gettimeofday(&mut sys_now, ptr::null_mut()); + let r = libc::gettimeofday(&mut sys_now, ptr::null_mut()); debug_assert_eq!(r, 0); let nsec = dur.subsec_nanos() as libc::c_long + @@ -76,7 +75,7 @@ impl Condvar { }); // And wait! - let r = ffi::pthread_cond_timedwait(self.inner.get(), mutex::raw(mutex), + let r = libc::pthread_cond_timedwait(self.inner.get(), mutex::raw(mutex), &timeout); debug_assert!(r == libc::ETIMEDOUT || r == 0); @@ -88,17 +87,17 @@ impl Condvar { #[inline] #[cfg(not(target_os = "dragonfly"))] pub unsafe fn destroy(&self) { - let r = ffi::pthread_cond_destroy(self.inner.get()); + let r = libc::pthread_cond_destroy(self.inner.get()); debug_assert_eq!(r, 0); } #[inline] #[cfg(target_os = "dragonfly")] pub unsafe fn destroy(&self) { - let r = ffi::pthread_cond_destroy(self.inner.get()); + let r = libc::pthread_cond_destroy(self.inner.get()); // On DragonFly pthread_cond_destroy() returns EINVAL if called on // a condvar that was just initialized with - // ffi::PTHREAD_COND_INITIALIZER. Once it is used or + // libc::PTHREAD_COND_INITIALIZER. Once it is used or // pthread_cond_init() is called, this behaviour no longer occurs. debug_assert!(r == 0 || r == libc::EINVAL); } diff --git a/src/libstd/sys/unix/ext/process.rs b/src/libstd/sys/unix/ext/process.rs index dcfa376c81e3b..3e7260f07571d 100644 --- a/src/libstd/sys/unix/ext/process.rs +++ b/src/libstd/sys/unix/ext/process.rs @@ -75,10 +75,7 @@ pub trait ExitStatusExt { #[stable(feature = "rust1", since = "1.0.0")] impl ExitStatusExt for process::ExitStatus { fn signal(&self) -> Option { - match *self.as_inner() { - sys::process::ExitStatus::Signal(s) => Some(s), - _ => None - } + self.as_inner().signal() } } diff --git a/src/libstd/sys/unix/fd.rs b/src/libstd/sys/unix/fd.rs index e9f442a22ccee..d42c15a97ac8c 100644 --- a/src/libstd/sys/unix/fd.rs +++ b/src/libstd/sys/unix/fd.rs @@ -11,7 +11,6 @@ use io; use libc::{self, c_int, size_t, c_void}; use mem; -use sys::c; use sys::cvt; use sys_common::AsInner; @@ -54,15 +53,15 @@ impl FileDesc { #[cfg(not(target_env = "newlib"))] pub fn set_cloexec(&self) { unsafe { - let ret = c::ioctl(self.fd, c::FIOCLEX); + let ret = libc::ioctl(self.fd, libc::FIOCLEX); debug_assert_eq!(ret, 0); } } #[cfg(target_env = "newlib")] pub fn set_cloexec(&self) { unsafe { - let previous = c::fnctl(self.fd, c::F_GETFD); - let ret = c::fnctl(self.fd, c::F_SETFD, previous | c::FD_CLOEXEC); + let previous = libc::fnctl(self.fd, libc::F_GETFD); + let ret = libc::fnctl(self.fd, libc::F_SETFD, previous | libc::FD_CLOEXEC); debug_assert_eq!(ret, 0); } } diff --git a/src/libstd/sys/unix/fs.rs b/src/libstd/sys/unix/fs.rs index c2145ac875ac3..018c91002880f 100644 --- a/src/libstd/sys/unix/fs.rs +++ b/src/libstd/sys/unix/fs.rs @@ -21,7 +21,7 @@ use ptr; use sync::Arc; use sys::fd::FileDesc; use sys::platform::raw; -use sys::{c, cvt, cvt_r}; +use sys::{cvt, cvt_r}; use sys_common::{AsInner, FromInner}; use vec::Vec; @@ -43,7 +43,7 @@ unsafe impl Send for Dir {} unsafe impl Sync for Dir {} pub struct DirEntry { - buf: Vec, // actually *mut libc::dirent_t + buf: Vec, // actually *mut libc::dirent root: Arc, } @@ -133,7 +133,7 @@ impl Iterator for ReadDir { let mut buf: Vec = Vec::with_capacity(unsafe { rust_dirent_t_size() as usize }); - let ptr = buf.as_mut_ptr() as *mut libc::dirent_t; + let ptr = buf.as_mut_ptr() as *mut libc::dirent; let mut entry_ptr = ptr::null_mut(); loop { @@ -179,7 +179,7 @@ impl DirEntry { pub fn file_type(&self) -> io::Result { extern { - fn rust_dir_get_mode(ptr: *mut libc::dirent_t) -> c_int; + fn rust_dir_get_mode(ptr: *mut libc::dirent) -> c_int; } unsafe { match rust_dir_get_mode(self.dirent()) { @@ -191,21 +191,21 @@ impl DirEntry { pub fn ino(&self) -> raw::ino_t { extern { - fn rust_dir_get_ino(ptr: *mut libc::dirent_t) -> raw::ino_t; + fn rust_dir_get_ino(ptr: *mut libc::dirent) -> raw::ino_t; } unsafe { rust_dir_get_ino(self.dirent()) } } fn name_bytes(&self) -> &[u8] { extern { - fn rust_list_dir_val(ptr: *mut libc::dirent_t) -> *const c_char; + fn rust_list_dir_val(ptr: *mut libc::dirent) -> *const c_char; } unsafe { CStr::from_ptr(rust_list_dir_val(self.dirent())).to_bytes() } } - fn dirent(&self) -> *mut libc::dirent_t { + fn dirent(&self) -> *mut libc::dirent { self.buf.as_ptr() as *mut _ } } @@ -267,7 +267,7 @@ impl File { (false, false) => libc::O_RDONLY, }; let fd = try!(cvt_r(|| unsafe { - libc::open(path.as_ptr(), flags, opts.mode) + libc::open(path.as_ptr(), flags, opts.mode as c_int) })); let fd = FileDesc::new(fd); // Even though we open with the O_CLOEXEC flag, still set CLOEXEC here, @@ -532,7 +532,7 @@ pub fn canonicalize(p: &Path) -> io::Result { let path = try!(CString::new(p.as_os_str().as_bytes())); let buf; unsafe { - let r = c::realpath(path.as_ptr(), ptr::null_mut()); + let r = libc::realpath(path.as_ptr(), ptr::null_mut()); if r.is_null() { return Err(io::Error::last_os_error()) } diff --git a/src/libstd/sys/unix/mod.rs b/src/libstd/sys/unix/mod.rs index 26b6b17cbe41a..68b0c3d6b0ee7 100644 --- a/src/libstd/sys/unix/mod.rs +++ b/src/libstd/sys/unix/mod.rs @@ -28,7 +28,6 @@ use ops::Neg; #[cfg(target_os = "openbsd")] pub use os::openbsd as platform; pub mod backtrace; -pub mod c; pub mod condvar; pub mod ext; pub mod fd; @@ -41,7 +40,6 @@ pub mod pipe; pub mod process; pub mod rwlock; pub mod stack_overflow; -pub mod sync; pub mod thread; pub mod thread_local; pub mod time; @@ -49,7 +47,7 @@ pub mod stdio; #[cfg(not(target_os = "nacl"))] pub fn init() { - use libc::funcs::posix01::signal::signal; + use libc::signal; // By default, some platforms will send a *signal* when an EPIPE error // would otherwise be delivered. This runtime doesn't install a SIGPIPE // handler, causing it to kill the program, which isn't exactly what we @@ -78,7 +76,7 @@ pub fn decode_error_kind(errno: i32) -> ErrorKind { libc::EINTR => ErrorKind::Interrupted, libc::EINVAL => ErrorKind::InvalidInput, libc::ETIMEDOUT => ErrorKind::TimedOut, - libc::consts::os::posix88::EEXIST => ErrorKind::AlreadyExists, + libc::EEXIST => ErrorKind::AlreadyExists, // These two constants can have the same value on some systems, // but different values on others, so we can't use a match diff --git a/src/libstd/sys/unix/mutex.rs b/src/libstd/sys/unix/mutex.rs index e4c231ff971d3..4e4abcfbeee4d 100644 --- a/src/libstd/sys/unix/mutex.rs +++ b/src/libstd/sys/unix/mutex.rs @@ -9,13 +9,13 @@ // except according to those terms. use cell::UnsafeCell; -use sys::sync as ffi; +use libc; use mem; -pub struct Mutex { inner: UnsafeCell } +pub struct Mutex { inner: UnsafeCell } #[inline] -pub unsafe fn raw(m: &Mutex) -> *mut ffi::pthread_mutex_t { +pub unsafe fn raw(m: &Mutex) -> *mut libc::pthread_mutex_t { m.inner.get() } @@ -27,42 +27,42 @@ impl Mutex { pub const fn new() -> Mutex { // Might be moved and address is changing it is better to avoid // initialization of potentially opaque OS data before it landed - Mutex { inner: UnsafeCell::new(ffi::PTHREAD_MUTEX_INITIALIZER) } + Mutex { inner: UnsafeCell::new(libc::PTHREAD_MUTEX_INITIALIZER) } } #[inline] pub unsafe fn lock(&self) { - let r = ffi::pthread_mutex_lock(self.inner.get()); + let r = libc::pthread_mutex_lock(self.inner.get()); debug_assert_eq!(r, 0); } #[inline] pub unsafe fn unlock(&self) { - let r = ffi::pthread_mutex_unlock(self.inner.get()); + let r = libc::pthread_mutex_unlock(self.inner.get()); debug_assert_eq!(r, 0); } #[inline] pub unsafe fn try_lock(&self) -> bool { - ffi::pthread_mutex_trylock(self.inner.get()) == 0 + libc::pthread_mutex_trylock(self.inner.get()) == 0 } #[inline] #[cfg(not(target_os = "dragonfly"))] pub unsafe fn destroy(&self) { - let r = ffi::pthread_mutex_destroy(self.inner.get()); + let r = libc::pthread_mutex_destroy(self.inner.get()); debug_assert_eq!(r, 0); } #[inline] #[cfg(target_os = "dragonfly")] pub unsafe fn destroy(&self) { use libc; - let r = ffi::pthread_mutex_destroy(self.inner.get()); + let r = libc::pthread_mutex_destroy(self.inner.get()); // On DragonFly pthread_mutex_destroy() returns EINVAL if called on a - // mutex that was just initialized with ffi::PTHREAD_MUTEX_INITIALIZER. + // mutex that was just initialized with libc::PTHREAD_MUTEX_INITIALIZER. // Once it is used (locked/unlocked) or pthread_mutex_init() is called, // this behaviour no longer occurs. debug_assert!(r == 0 || r == libc::EINVAL); } } -pub struct ReentrantMutex { inner: UnsafeCell } +pub struct ReentrantMutex { inner: UnsafeCell } unsafe impl Send for ReentrantMutex {} unsafe impl Sync for ReentrantMutex {} @@ -73,35 +73,35 @@ impl ReentrantMutex { } pub unsafe fn init(&mut self) { - let mut attr: ffi::pthread_mutexattr_t = mem::uninitialized(); - let result = ffi::pthread_mutexattr_init(&mut attr as *mut _); + let mut attr: libc::pthread_mutexattr_t = mem::uninitialized(); + let result = libc::pthread_mutexattr_init(&mut attr as *mut _); debug_assert_eq!(result, 0); - let result = ffi::pthread_mutexattr_settype(&mut attr as *mut _, - ffi::PTHREAD_MUTEX_RECURSIVE); + let result = libc::pthread_mutexattr_settype(&mut attr as *mut _, + libc::PTHREAD_MUTEX_RECURSIVE); debug_assert_eq!(result, 0); - let result = ffi::pthread_mutex_init(self.inner.get(), &attr as *const _); + let result = libc::pthread_mutex_init(self.inner.get(), &attr as *const _); debug_assert_eq!(result, 0); - let result = ffi::pthread_mutexattr_destroy(&mut attr as *mut _); + let result = libc::pthread_mutexattr_destroy(&mut attr as *mut _); debug_assert_eq!(result, 0); } pub unsafe fn lock(&self) { - let result = ffi::pthread_mutex_lock(self.inner.get()); + let result = libc::pthread_mutex_lock(self.inner.get()); debug_assert_eq!(result, 0); } #[inline] pub unsafe fn try_lock(&self) -> bool { - ffi::pthread_mutex_trylock(self.inner.get()) == 0 + libc::pthread_mutex_trylock(self.inner.get()) == 0 } pub unsafe fn unlock(&self) { - let result = ffi::pthread_mutex_unlock(self.inner.get()); + let result = libc::pthread_mutex_unlock(self.inner.get()); debug_assert_eq!(result, 0); } pub unsafe fn destroy(&self) { - let result = ffi::pthread_mutex_destroy(self.inner.get()); + let result = libc::pthread_mutex_destroy(self.inner.get()); debug_assert_eq!(result, 0); } } diff --git a/src/libstd/sys/unix/net.rs b/src/libstd/sys/unix/net.rs index 6d65cb838f67a..bcda1d651d69d 100644 --- a/src/libstd/sys/unix/net.rs +++ b/src/libstd/sys/unix/net.rs @@ -13,16 +13,16 @@ use prelude::v1::*; use ffi::CStr; use io; use libc::{self, c_int, size_t}; -use net::SocketAddr; +use net::{SocketAddr, Shutdown}; use str; -use sync::atomic::{self, AtomicBool}; -use sys::c; +use sync::atomic::{AtomicBool, Ordering}; use sys::fd::FileDesc; use sys_common::{AsInner, FromInner, IntoInner}; use sys_common::net::{getsockopt, setsockopt}; use time::Duration; pub use sys::{cvt, cvt_r}; +pub use libc as netc; pub type wrlen_t = size_t; @@ -34,7 +34,7 @@ pub fn cvt_gai(err: c_int) -> io::Result<()> { if err == 0 { return Ok(()) } let detail = unsafe { - str::from_utf8(CStr::from_ptr(c::gai_strerror(err)).to_bytes()).unwrap() + str::from_utf8(CStr::from_ptr(libc::gai_strerror(err)).to_bytes()).unwrap() .to_owned() }; Err(io::Error::new(io::ErrorKind::Other, @@ -67,29 +67,44 @@ impl Socket { } pub fn duplicate(&self) -> io::Result { - use libc::funcs::posix88::fcntl::fcntl; + // We want to atomically duplicate this file descriptor and set the + // CLOEXEC flag, and currently that's done via F_DUPFD_CLOEXEC. This + // flag, however, isn't supported on older Linux kernels (earlier than + // 2.6.24). + // + // To detect this and ensure that CLOEXEC is still set, we + // follow a strategy similar to musl [1] where if passing + // F_DUPFD_CLOEXEC causes `fcntl` to return EINVAL it means it's not + // supported (the third parameter, 0, is always valid), so we stop + // trying that. We also *still* call the `set_cloexec` method as + // apparently some kernel at some point stopped setting CLOEXEC even + // though it reported doing so on F_DUPFD_CLOEXEC. + // + // Also note that Android doesn't have F_DUPFD_CLOEXEC, but get it to + // resolve so we at least compile this. + // + // [1]: http://comments.gmane.org/gmane.linux.lib.musl.general/2963 + #[cfg(target_os = "android")] + use libc::F_DUPFD as F_DUPFD_CLOEXEC; + #[cfg(not(target_os = "android"))] + use libc::F_DUPFD_CLOEXEC; + let make_socket = |fd| { let fd = FileDesc::new(fd); fd.set_cloexec(); Socket(fd) }; - static EMULATE_F_DUPFD_CLOEXEC: AtomicBool = AtomicBool::new(false); - if !EMULATE_F_DUPFD_CLOEXEC.load(atomic::Ordering::Relaxed) { - match cvt(unsafe { fcntl(self.0.raw(), libc::F_DUPFD_CLOEXEC, 0) }) { - // `EINVAL` can only be returned on two occasions: Invalid - // command (second parameter) or invalid third parameter. 0 is - // always a valid third parameter, so it must be the second - // parameter. - // - // Store the result in a global variable so we don't try each - // syscall twice. + static TRY_CLOEXEC: AtomicBool = AtomicBool::new(true); + let fd = self.0.raw(); + if !cfg!(target_os = "android") && TRY_CLOEXEC.load(Ordering::Relaxed) { + match cvt(unsafe { libc::fcntl(fd, F_DUPFD_CLOEXEC, 0) }) { Err(ref e) if e.raw_os_error() == Some(libc::EINVAL) => { - EMULATE_F_DUPFD_CLOEXEC.store(true, atomic::Ordering::Relaxed); + TRY_CLOEXEC.store(false, Ordering::Relaxed); } res => return res.map(make_socket), } } - cvt(unsafe { fcntl(self.0.raw(), libc::F_DUPFD, 0) }).map(make_socket) + cvt(unsafe { libc::fcntl(fd, libc::F_DUPFD, 0) }).map(make_socket) } pub fn read(&self, buf: &mut [u8]) -> io::Result { @@ -138,6 +153,16 @@ impl Socket { Ok(Some(Duration::new(sec, nsec))) } } + + pub fn shutdown(&self, how: Shutdown) -> io::Result<()> { + let how = match how { + Shutdown::Write => libc::SHUT_WR, + Shutdown::Read => libc::SHUT_RD, + Shutdown::Both => libc::SHUT_RDWR, + }; + try!(cvt(unsafe { libc::shutdown(self.0.raw(), how) })); + Ok(()) + } } impl AsInner for Socket { diff --git a/src/libstd/sys/unix/os.rs b/src/libstd/sys/unix/os.rs index c328c84f62ae5..3c53db53f85f1 100644 --- a/src/libstd/sys/unix/os.rs +++ b/src/libstd/sys/unix/os.rs @@ -26,11 +26,13 @@ use path::{self, PathBuf}; use ptr; use slice; use str; -use sys::c; +use sync::StaticMutex; +use sys::cvt; use sys::fd; use vec; const TMPBUF_SZ: usize = 128; +static ENV_LOCK: StaticMutex = StaticMutex::new(); /// Returns the platform-specific value of errno pub fn errno() -> i32 { @@ -227,8 +229,11 @@ pub fn current_exe() -> io::Result { #[cfg(any(target_os = "macos", target_os = "ios"))] pub fn current_exe() -> io::Result { + extern { + fn _NSGetExecutablePath(buf: *mut libc::c_char, + bufsize: *mut u32) -> libc::c_int; + } unsafe { - use libc::funcs::extra::_NSGetExecutablePath; let mut sz: u32 = 0; _NSGetExecutablePath(ptr::null_mut(), &mut sz); if sz == 0 { return Err(io::Error::last_os_error()); } @@ -378,6 +383,7 @@ pub unsafe fn environ() -> *mut *const *const c_char { /// Returns a vector of (variable, value) byte-vector pairs for all the /// environment variables of the current process. pub fn env() -> Env { + let _g = ENV_LOCK.lock(); return unsafe { let mut environ = *environ(); if environ as usize == 0 { @@ -401,35 +407,36 @@ pub fn env() -> Env { } } -pub fn getenv(k: &OsStr) -> Option { - unsafe { - let s = k.to_cstring().unwrap(); - let s = libc::getenv(s.as_ptr()) as *const _; +pub fn getenv(k: &OsStr) -> io::Result> { + // environment variables with a nul byte can't be set, so their value is + // always None as well + let k = try!(CString::new(k.as_bytes())); + let _g = ENV_LOCK.lock(); + Ok(unsafe { + let s = libc::getenv(k.as_ptr()) as *const _; if s.is_null() { None } else { Some(OsStringExt::from_vec(CStr::from_ptr(s).to_bytes().to_vec())) } - } + }) } -pub fn setenv(k: &OsStr, v: &OsStr) { - unsafe { - let k = k.to_cstring().unwrap(); - let v = v.to_cstring().unwrap(); - if libc::funcs::posix01::unistd::setenv(k.as_ptr(), v.as_ptr(), 1) != 0 { - panic!("failed setenv: {}", io::Error::last_os_error()); - } - } +pub fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> { + let k = try!(CString::new(k.as_bytes())); + let v = try!(CString::new(v.as_bytes())); + let _g = ENV_LOCK.lock(); + cvt(unsafe { + libc::setenv(k.as_ptr(), v.as_ptr(), 1) + }).map(|_| ()) } -pub fn unsetenv(n: &OsStr) { - unsafe { - let nbuf = n.to_cstring().unwrap(); - if libc::funcs::posix01::unistd::unsetenv(nbuf.as_ptr()) != 0 { - panic!("failed unsetenv: {}", io::Error::last_os_error()); - } - } +pub fn unsetenv(n: &OsStr) -> io::Result<()> { + let nbuf = try!(CString::new(n.as_bytes())); + let _g = ENV_LOCK.lock(); + cvt(unsafe { + libc::unsetenv(nbuf.as_ptr()) + }).map(|_| ()) } pub fn page_size() -> usize { @@ -439,7 +446,7 @@ pub fn page_size() -> usize { } pub fn temp_dir() -> PathBuf { - getenv("TMPDIR".as_ref()).map(PathBuf::from).unwrap_or_else(|| { + ::env::var_os("TMPDIR").map(PathBuf::from).unwrap_or_else(|| { if cfg!(target_os = "android") { PathBuf::from("/data/local/tmp") } else { @@ -449,7 +456,7 @@ pub fn temp_dir() -> PathBuf { } pub fn home_dir() -> Option { - return getenv("HOME".as_ref()).or_else(|| unsafe { + return ::env::var_os("HOME").or_else(|| unsafe { fallback() }).map(PathBuf::from); @@ -461,18 +468,18 @@ pub fn home_dir() -> Option { target_os = "ios", target_os = "nacl")))] unsafe fn fallback() -> Option { - let amt = match libc::sysconf(c::_SC_GETPW_R_SIZE_MAX) { + let amt = match libc::sysconf(libc::_SC_GETPW_R_SIZE_MAX) { n if n < 0 => 512 as usize, n => n as usize, }; let me = libc::getuid(); loop { let mut buf = Vec::with_capacity(amt); - let mut passwd: c::passwd = mem::zeroed(); + let mut passwd: libc::passwd = mem::zeroed(); let mut result = ptr::null_mut(); - match c::getpwuid_r(me, &mut passwd, buf.as_mut_ptr(), - buf.capacity() as libc::size_t, - &mut result) { + match libc::getpwuid_r(me, &mut passwd, buf.as_mut_ptr(), + buf.capacity() as libc::size_t, + &mut result) { 0 if !result.is_null() => {} _ => return None } diff --git a/src/libstd/sys/unix/process.rs b/src/libstd/sys/unix/process.rs index 75ae9310b21ba..8d80296ab035a 100644 --- a/src/libstd/sys/unix/process.rs +++ b/src/libstd/sys/unix/process.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(non_snake_case)] + use prelude::v1::*; use os::unix::prelude::*; @@ -21,7 +23,7 @@ use ptr; use sys::fd::FileDesc; use sys::fs::{File, OpenOptions}; use sys::pipe::AnonPipe; -use sys::{self, c, cvt, cvt_r}; +use sys::{self, cvt, cvt_r}; //////////////////////////////////////////////////////////////////////////////// // Command @@ -84,33 +86,62 @@ impl Command { /// Unix exit statuses #[derive(PartialEq, Eq, Clone, Copy, Debug)] -pub enum ExitStatus { - /// Normal termination with an exit code. - Code(i32), - - /// Termination by signal, with the signal number. - /// - /// Never generated on Windows. - Signal(i32), +pub struct ExitStatus(c_int); + +#[cfg(any(target_os = "linux", target_os = "android", + target_os = "nacl"))] +mod status_imp { + pub fn WIFEXITED(status: i32) -> bool { (status & 0xff) == 0 } + pub fn WEXITSTATUS(status: i32) -> i32 { (status >> 8) & 0xff } + pub fn WTERMSIG(status: i32) -> i32 { status & 0x7f } +} + +#[cfg(any(target_os = "macos", + target_os = "ios", + target_os = "freebsd", + target_os = "dragonfly", + target_os = "bitrig", + target_os = "netbsd", + target_os = "openbsd"))] +mod status_imp { + pub fn WIFEXITED(status: i32) -> bool { (status & 0x7f) == 0 } + pub fn WEXITSTATUS(status: i32) -> i32 { status >> 8 } + pub fn WTERMSIG(status: i32) -> i32 { status & 0o177 } } impl ExitStatus { + fn exited(&self) -> bool { + status_imp::WIFEXITED(self.0) + } + pub fn success(&self) -> bool { - *self == ExitStatus::Code(0) + self.code() == Some(0) } + pub fn code(&self) -> Option { - match *self { - ExitStatus::Code(c) => Some(c), - _ => None + if self.exited() { + Some(status_imp::WEXITSTATUS(self.0)) + } else { + None + } + } + + pub fn signal(&self) -> Option { + if !self.exited() { + Some(status_imp::WTERMSIG(self.0)) + } else { + None } } } impl fmt::Display for ExitStatus { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - ExitStatus::Code(code) => write!(f, "exit code: {}", code), - ExitStatus::Signal(code) => write!(f, "signal: {}", code), + if let Some(code) = self.code() { + write!(f, "exit code: {}", code) + } else { + let signal = self.signal().unwrap(); + write!(f, "signal: {}", signal) } } } @@ -132,7 +163,7 @@ const CLOEXEC_MSG_FOOTER: &'static [u8] = b"NOEX"; impl Process { pub unsafe fn kill(&self) -> io::Result<()> { - try!(cvt(libc::funcs::posix88::signal::kill(self.pid, libc::SIGKILL))); + try!(cvt(libc::kill(self.pid, libc::SIGKILL))); Ok(()) } @@ -295,7 +326,7 @@ impl Process { // fail if we aren't root, so don't bother checking the // return value, this is just done as an optimistic // privilege dropping function. - let _ = c::setgroups(0, ptr::null()); + let _ = libc::setgroups(0, ptr::null()); if libc::setuid(u as libc::uid_t) != 0 { fail(&mut output); @@ -324,12 +355,12 @@ impl Process { // UNIX programs do not reset these things on their own, so we // need to clean things up now to avoid confusing the program // we're about to run. - let mut set: c::sigset_t = mem::uninitialized(); - if c::sigemptyset(&mut set) != 0 || - c::pthread_sigmask(c::SIG_SETMASK, &set, ptr::null_mut()) != 0 || - libc::funcs::posix01::signal::signal( - libc::SIGPIPE, mem::transmute(c::SIG_DFL) - ) == mem::transmute(c::SIG_ERR) + let mut set: libc::sigset_t = mem::uninitialized(); + if libc::sigemptyset(&mut set) != 0 || + libc::pthread_sigmask(libc::SIG_SETMASK, &set, ptr::null_mut()) != 0 || + libc::signal( + libc::SIGPIPE, mem::transmute(libc::SIG_DFL) + ) == mem::transmute(libc::SIG_ERR) { fail(output); } @@ -350,17 +381,17 @@ impl Process { pub fn wait(&self) -> io::Result { let mut status = 0 as c_int; - try!(cvt_r(|| unsafe { c::waitpid(self.pid, &mut status, 0) })); - Ok(translate_status(status)) + try!(cvt_r(|| unsafe { libc::waitpid(self.pid, &mut status, 0) })); + Ok(ExitStatus(status)) } pub fn try_wait(&self) -> Option { let mut status = 0 as c_int; match cvt_r(|| unsafe { - c::waitpid(self.pid, &mut status, c::WNOHANG) + libc::waitpid(self.pid, &mut status, libc::WNOHANG) }) { Ok(0) => None, - Ok(n) if n == self.pid => Some(translate_status(status)), + Ok(n) if n == self.pid => Some(ExitStatus(status)), Ok(n) => panic!("unknown pid: {}", n), Err(e) => panic!("unknown waitpid error: {}", e), } @@ -418,36 +449,6 @@ fn make_envp(env: Option<&HashMap>) } } -fn translate_status(status: c_int) -> ExitStatus { - #![allow(non_snake_case)] - #[cfg(any(target_os = "linux", target_os = "android", - target_os = "nacl"))] - mod imp { - pub fn WIFEXITED(status: i32) -> bool { (status & 0xff) == 0 } - pub fn WEXITSTATUS(status: i32) -> i32 { (status >> 8) & 0xff } - pub fn WTERMSIG(status: i32) -> i32 { status & 0x7f } - } - - #[cfg(any(target_os = "macos", - target_os = "ios", - target_os = "freebsd", - target_os = "dragonfly", - target_os = "bitrig", - target_os = "netbsd", - target_os = "openbsd"))] - mod imp { - pub fn WIFEXITED(status: i32) -> bool { (status & 0x7f) == 0 } - pub fn WEXITSTATUS(status: i32) -> i32 { status >> 8 } - pub fn WTERMSIG(status: i32) -> i32 { status & 0o177 } - } - - if imp::WIFEXITED(status) { - ExitStatus::Code(imp::WEXITSTATUS(status)) - } else { - ExitStatus::Signal(imp::WTERMSIG(status)) - } -} - #[cfg(test)] mod tests { use super::*; @@ -458,7 +459,7 @@ mod tests { use ptr; use libc; use slice; - use sys::{self, c, cvt, pipe}; + use sys::{self, cvt, pipe}; macro_rules! t { ($e:expr) => { @@ -472,12 +473,12 @@ mod tests { #[cfg(not(target_os = "android"))] extern { #[cfg_attr(target_os = "netbsd", link_name = "__sigaddset14")] - fn sigaddset(set: *mut c::sigset_t, signum: libc::c_int) -> libc::c_int; + fn sigaddset(set: *mut libc::sigset_t, signum: libc::c_int) -> libc::c_int; } #[cfg(target_os = "android")] - unsafe fn sigaddset(set: *mut c::sigset_t, signum: libc::c_int) -> libc::c_int { - let raw = slice::from_raw_parts_mut(set as *mut u8, mem::size_of::()); + unsafe fn sigaddset(set: *mut libc::sigset_t, signum: libc::c_int) -> libc::c_int { + let raw = slice::from_raw_parts_mut(set as *mut u8, mem::size_of::()); let bit = (signum - 1) as usize; raw[bit / 8] |= 1 << (bit % 8); return 0; @@ -496,11 +497,11 @@ mod tests { let (stdin_read, stdin_write) = t!(sys::pipe::anon_pipe()); let (stdout_read, stdout_write) = t!(sys::pipe::anon_pipe()); - let mut set: c::sigset_t = mem::uninitialized(); - let mut old_set: c::sigset_t = mem::uninitialized(); - t!(cvt(c::sigemptyset(&mut set))); + let mut set: libc::sigset_t = mem::uninitialized(); + let mut old_set: libc::sigset_t = mem::uninitialized(); + t!(cvt(libc::sigemptyset(&mut set))); t!(cvt(sigaddset(&mut set, libc::SIGINT))); - t!(cvt(c::pthread_sigmask(c::SIG_SETMASK, &set, &mut old_set))); + t!(cvt(libc::pthread_sigmask(libc::SIG_SETMASK, &set, &mut old_set))); let cat = t!(Process::spawn(&cmd, Stdio::Raw(stdin_read.raw()), Stdio::Raw(stdout_write.raw()), @@ -508,11 +509,10 @@ mod tests { drop(stdin_read); drop(stdout_write); - t!(cvt(c::pthread_sigmask(c::SIG_SETMASK, &old_set, - ptr::null_mut()))); + t!(cvt(libc::pthread_sigmask(libc::SIG_SETMASK, &old_set, + ptr::null_mut()))); - t!(cvt(libc::funcs::posix88::signal::kill(cat.id() as libc::pid_t, - libc::SIGINT))); + t!(cvt(libc::kill(cat.id() as libc::pid_t, libc::SIGINT))); // We need to wait until SIGINT is definitely delivered. The // easiest way is to write something to cat, and try to read it // back: if SIGINT is unmasked, it'll get delivered when cat is diff --git a/src/libstd/sys/unix/rwlock.rs b/src/libstd/sys/unix/rwlock.rs index 788bff6243018..44bd5d895f2e4 100644 --- a/src/libstd/sys/unix/rwlock.rs +++ b/src/libstd/sys/unix/rwlock.rs @@ -10,20 +10,19 @@ use libc; use cell::UnsafeCell; -use sys::sync as ffi; -pub struct RWLock { inner: UnsafeCell } +pub struct RWLock { inner: UnsafeCell } unsafe impl Send for RWLock {} unsafe impl Sync for RWLock {} impl RWLock { pub const fn new() -> RWLock { - RWLock { inner: UnsafeCell::new(ffi::PTHREAD_RWLOCK_INITIALIZER) } + RWLock { inner: UnsafeCell::new(libc::PTHREAD_RWLOCK_INITIALIZER) } } #[inline] pub unsafe fn read(&self) { - let r = ffi::pthread_rwlock_rdlock(self.inner.get()); + let r = libc::pthread_rwlock_rdlock(self.inner.get()); // According to the pthread_rwlock_rdlock spec, this function **may** // fail with EDEADLK if a deadlock is detected. On the other hand @@ -44,11 +43,11 @@ impl RWLock { } #[inline] pub unsafe fn try_read(&self) -> bool { - ffi::pthread_rwlock_tryrdlock(self.inner.get()) == 0 + libc::pthread_rwlock_tryrdlock(self.inner.get()) == 0 } #[inline] pub unsafe fn write(&self) { - let r = ffi::pthread_rwlock_wrlock(self.inner.get()); + let r = libc::pthread_rwlock_wrlock(self.inner.get()); // see comments above for why we check for EDEADLK if r == libc::EDEADLK { panic!("rwlock write lock would result in deadlock"); @@ -58,21 +57,21 @@ impl RWLock { } #[inline] pub unsafe fn try_write(&self) -> bool { - ffi::pthread_rwlock_trywrlock(self.inner.get()) == 0 + libc::pthread_rwlock_trywrlock(self.inner.get()) == 0 } #[inline] pub unsafe fn read_unlock(&self) { - let r = ffi::pthread_rwlock_unlock(self.inner.get()); + let r = libc::pthread_rwlock_unlock(self.inner.get()); debug_assert_eq!(r, 0); } #[inline] pub unsafe fn write_unlock(&self) { self.read_unlock() } #[inline] pub unsafe fn destroy(&self) { - let r = ffi::pthread_rwlock_destroy(self.inner.get()); + let r = libc::pthread_rwlock_destroy(self.inner.get()); // On DragonFly pthread_rwlock_destroy() returns EINVAL if called on a // rwlock that was just initialized with - // ffi::PTHREAD_RWLOCK_INITIALIZER. Once it is used (locked/unlocked) + // libc::PTHREAD_RWLOCK_INITIALIZER. Once it is used (locked/unlocked) // or pthread_rwlock_init() is called, this behaviour no longer occurs. if cfg!(target_os = "dragonfly") { debug_assert!(r == 0 || r == libc::EINVAL); diff --git a/src/libstd/sys/unix/stack_overflow.rs b/src/libstd/sys/unix/stack_overflow.rs index 5f624bc76b3e8..9a7f98d24cd5d 100644 --- a/src/libstd/sys/unix/stack_overflow.rs +++ b/src/libstd/sys/unix/stack_overflow.rs @@ -43,11 +43,11 @@ mod imp { use sys_common::util::report_overflow; use mem; use ptr; - use sys::c::{siginfo, sigaction, SIGBUS, SIG_DFL, - SA_SIGINFO, SA_ONSTACK, sigaltstack, - SIGSTKSZ, sighandler_t}; + use libc::{sigaction, SIGBUS, SIG_DFL, + SA_SIGINFO, SA_ONSTACK, sigaltstack, + SIGSTKSZ, sighandler_t}; use libc; - use libc::funcs::posix88::mman::{mmap, munmap}; + use libc::{mmap, munmap}; use libc::{SIGSEGV, PROT_READ, PROT_WRITE, MAP_PRIVATE, MAP_ANON}; use libc::MAP_FAILED; @@ -57,6 +57,22 @@ mod imp { // This is initialized in init() and only read from after static mut PAGE_SIZE: usize = 0; + #[cfg(any(target_os = "linux", target_os = "android"))] + unsafe fn siginfo_si_addr(info: *mut libc::siginfo_t) -> *mut libc::c_void { + #[repr(C)] + struct siginfo_t { + a: [libc::c_int; 3], // si_signo, si_code, si_errno, + si_addr: *mut libc::c_void, + } + + (*(info as *const siginfo_t)).si_addr + } + + #[cfg(not(any(target_os = "linux", target_os = "android")))] + unsafe fn siginfo_si_addr(info: *mut libc::siginfo_t) -> *mut libc::c_void { + (*info).si_addr + } + // Signal handler for the SIGSEGV and SIGBUS handlers. We've got guard pages // (unmapped pages) at the end of every thread's stack, so if a thread ends // up running into the guard page it'll trigger this handler. We want to @@ -76,10 +92,10 @@ mod imp { // handler to work. For a more detailed explanation see the comments on // #26458. unsafe extern fn signal_handler(signum: libc::c_int, - info: *mut siginfo, + info: *mut libc::siginfo_t, _data: *mut libc::c_void) { let guard = thread_info::stack_guard().unwrap_or(0); - let addr = (*info).si_addr as usize; + let addr = siginfo_si_addr(info) as usize; // If the faulting address is within the guard page, then we print a // message saying so. @@ -126,7 +142,7 @@ mod imp { panic!("failed to allocate an alternative stack"); } - let mut stack: sigaltstack = mem::zeroed(); + let mut stack: libc::stack_t = mem::zeroed(); stack.ss_sp = alt_stack; stack.ss_flags = 0; diff --git a/src/libstd/sys/unix/sync.rs b/src/libstd/sys/unix/sync.rs deleted file mode 100644 index 6f6acc2560e0c..0000000000000 --- a/src/libstd/sys/unix/sync.rs +++ /dev/null @@ -1,374 +0,0 @@ -// Copyright 2014-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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#![allow(bad_style)] - -use libc; - -pub use self::os::{PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_RECURSIVE, pthread_mutex_t, - pthread_mutexattr_t}; -pub use self::os::{PTHREAD_COND_INITIALIZER, pthread_cond_t}; -pub use self::os::{PTHREAD_RWLOCK_INITIALIZER, pthread_rwlock_t}; - -extern { - // mutexes - pub fn pthread_mutex_init(lock: *mut pthread_mutex_t, attr: *const pthread_mutexattr_t) - -> libc::c_int; - pub fn pthread_mutex_destroy(lock: *mut pthread_mutex_t) -> libc::c_int; - pub fn pthread_mutex_lock(lock: *mut pthread_mutex_t) -> libc::c_int; - pub fn pthread_mutex_trylock(lock: *mut pthread_mutex_t) -> libc::c_int; - pub fn pthread_mutex_unlock(lock: *mut pthread_mutex_t) -> libc::c_int; - - pub fn pthread_mutexattr_init(attr: *mut pthread_mutexattr_t) -> libc::c_int; - pub fn pthread_mutexattr_destroy(attr: *mut pthread_mutexattr_t) -> libc::c_int; - pub fn pthread_mutexattr_settype(attr: *mut pthread_mutexattr_t, _type: libc::c_int) - -> libc::c_int; - - // cvars - pub fn pthread_cond_wait(cond: *mut pthread_cond_t, - lock: *mut pthread_mutex_t) -> libc::c_int; - #[cfg_attr(target_os = "nacl", link_name = "pthread_cond_timedwait_abs")] - pub fn pthread_cond_timedwait(cond: *mut pthread_cond_t, - lock: *mut pthread_mutex_t, - abstime: *const libc::timespec) -> libc::c_int; - pub fn pthread_cond_signal(cond: *mut pthread_cond_t) -> libc::c_int; - pub fn pthread_cond_broadcast(cond: *mut pthread_cond_t) -> libc::c_int; - pub fn pthread_cond_destroy(cond: *mut pthread_cond_t) -> libc::c_int; - #[cfg_attr(target_os = "netbsd", link_name = "__gettimeofday50")] - pub fn gettimeofday(tp: *mut libc::timeval, - tz: *mut libc::c_void) -> libc::c_int; - - // rwlocks - pub fn pthread_rwlock_destroy(lock: *mut pthread_rwlock_t) -> libc::c_int; - pub fn pthread_rwlock_rdlock(lock: *mut pthread_rwlock_t) -> libc::c_int; - pub fn pthread_rwlock_tryrdlock(lock: *mut pthread_rwlock_t) -> libc::c_int; - pub fn pthread_rwlock_wrlock(lock: *mut pthread_rwlock_t) -> libc::c_int; - pub fn pthread_rwlock_trywrlock(lock: *mut pthread_rwlock_t) -> libc::c_int; - pub fn pthread_rwlock_unlock(lock: *mut pthread_rwlock_t) -> libc::c_int; -} - -#[cfg(any(target_os = "freebsd", - target_os = "dragonfly", - target_os = "bitrig", - target_os = "openbsd"))] -mod os { - use libc; - use ptr; - - pub type pthread_mutex_t = *mut libc::c_void; - pub type pthread_mutexattr_t = *mut libc::c_void; - pub type pthread_cond_t = *mut libc::c_void; - pub type pthread_rwlock_t = *mut libc::c_void; - - pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = ptr::null_mut(); - pub const PTHREAD_COND_INITIALIZER: pthread_cond_t = ptr::null_mut(); - pub const PTHREAD_RWLOCK_INITIALIZER: pthread_rwlock_t = ptr::null_mut(); - pub const PTHREAD_MUTEX_RECURSIVE: libc::c_int = 2; -} - -#[cfg(any(target_os = "macos", target_os = "ios"))] -mod os { - use libc; - - #[cfg(any(target_arch = "x86_64", - target_arch = "aarch64"))] - const __PTHREAD_MUTEX_SIZE__: usize = 56; - #[cfg(any(target_arch = "x86", - target_arch = "arm"))] - const __PTHREAD_MUTEX_SIZE__: usize = 40; - - #[cfg(any(target_arch = "x86_64", - target_arch = "aarch64"))] - const __PTHREAD_COND_SIZE__: usize = 40; - #[cfg(any(target_arch = "x86", - target_arch = "arm"))] - const __PTHREAD_COND_SIZE__: usize = 24; - - #[cfg(any(target_arch = "x86_64", - target_arch = "aarch64"))] - const __PTHREAD_RWLOCK_SIZE__: usize = 192; - #[cfg(any(target_arch = "x86", - target_arch = "arm"))] - const __PTHREAD_RWLOCK_SIZE__: usize = 124; - - const _PTHREAD_MUTEX_SIG_INIT: libc::c_long = 0x32AAABA7; - const _PTHREAD_COND_SIG_INIT: libc::c_long = 0x3CB0B1BB; - const _PTHREAD_RWLOCK_SIG_INIT: libc::c_long = 0x2DA8B3B4; - - #[repr(C)] - pub struct pthread_mutex_t { - __sig: libc::c_long, - __opaque: [u8; __PTHREAD_MUTEX_SIZE__], - } - #[repr(C)] - pub struct pthread_mutexattr_t { - __sig: libc::c_long, - // note, that this is 16 bytes just to be safe, the actual struct might be smaller. - __opaque: [u8; 16], - } - #[repr(C)] - pub struct pthread_cond_t { - __sig: libc::c_long, - __opaque: [u8; __PTHREAD_COND_SIZE__], - } - #[repr(C)] - pub struct pthread_rwlock_t { - __sig: libc::c_long, - __opaque: [u8; __PTHREAD_RWLOCK_SIZE__], - } - - pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = pthread_mutex_t { - __sig: _PTHREAD_MUTEX_SIG_INIT, - __opaque: [0; __PTHREAD_MUTEX_SIZE__], - }; - pub const PTHREAD_COND_INITIALIZER: pthread_cond_t = pthread_cond_t { - __sig: _PTHREAD_COND_SIG_INIT, - __opaque: [0; __PTHREAD_COND_SIZE__], - }; - pub const PTHREAD_RWLOCK_INITIALIZER: pthread_rwlock_t = pthread_rwlock_t { - __sig: _PTHREAD_RWLOCK_SIG_INIT, - __opaque: [0; __PTHREAD_RWLOCK_SIZE__], - }; - - pub const PTHREAD_MUTEX_RECURSIVE: libc::c_int = 2; -} - -#[cfg(target_os = "linux")] -mod os { - use libc; - - // minus 8 because we have an 'align' field - #[cfg(target_arch = "x86_64")] - const __SIZEOF_PTHREAD_MUTEX_T: usize = 40 - 8; - #[cfg(any(target_arch = "x86", - target_arch = "arm", - target_arch = "mips", - target_arch = "mipsel", - target_arch = "powerpc"))] - const __SIZEOF_PTHREAD_MUTEX_T: usize = 24 - 8; - #[cfg(target_arch = "aarch64")] - const __SIZEOF_PTHREAD_MUTEX_T: usize = 48 - 8; - - #[cfg(any(target_arch = "x86_64", - target_arch = "x86", - target_arch = "arm", - target_arch = "aarch64", - target_arch = "mips", - target_arch = "mipsel", - target_arch = "powerpc"))] - const __SIZEOF_PTHREAD_COND_T: usize = 48 - 8; - - #[cfg(any(target_arch = "x86_64", - target_arch = "aarch64"))] - const __SIZEOF_PTHREAD_RWLOCK_T: usize = 56 - 8; - - #[cfg(any(target_arch = "x86", - target_arch = "arm", - target_arch = "mips", - target_arch = "mipsel", - target_arch = "powerpc"))] - const __SIZEOF_PTHREAD_RWLOCK_T: usize = 32 - 8; - - #[repr(C)] - pub struct pthread_mutex_t { - __align: libc::c_longlong, - size: [u8; __SIZEOF_PTHREAD_MUTEX_T], - } - #[repr(C)] - pub struct pthread_mutexattr_t { - __align: libc::c_longlong, - // note, that this is 16 bytes just to be safe, the actual struct might be smaller. - size: [u8; 16], - } - #[repr(C)] - pub struct pthread_cond_t { - __align: libc::c_longlong, - size: [u8; __SIZEOF_PTHREAD_COND_T], - } - #[repr(C)] - pub struct pthread_rwlock_t { - __align: libc::c_longlong, - size: [u8; __SIZEOF_PTHREAD_RWLOCK_T], - } - - pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = pthread_mutex_t { - __align: 0, - size: [0; __SIZEOF_PTHREAD_MUTEX_T], - }; - pub const PTHREAD_COND_INITIALIZER: pthread_cond_t = pthread_cond_t { - __align: 0, - size: [0; __SIZEOF_PTHREAD_COND_T], - }; - pub const PTHREAD_RWLOCK_INITIALIZER: pthread_rwlock_t = pthread_rwlock_t { - __align: 0, - size: [0; __SIZEOF_PTHREAD_RWLOCK_T], - }; - pub const PTHREAD_MUTEX_RECURSIVE: libc::c_int = 1; -} -#[cfg(target_os = "android")] -mod os { - use libc; - use ptr; - - #[repr(C)] - pub struct pthread_mutex_t { value: libc::c_int } - pub type pthread_mutexattr_t = libc::c_long; - #[repr(C)] - pub struct pthread_cond_t { value: libc::c_int } - #[repr(C)] - pub struct pthread_rwlock_t { - lock: pthread_mutex_t, - cond: pthread_cond_t, - numLocks: libc::c_int, - writerThreadId: libc::c_int, - pendingReaders: libc::c_int, - pendingWriters: libc::c_int, - reserved: [*mut libc::c_void; 4], - } - - pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = pthread_mutex_t { - value: 0, - }; - pub const PTHREAD_COND_INITIALIZER: pthread_cond_t = pthread_cond_t { - value: 0, - }; - pub const PTHREAD_RWLOCK_INITIALIZER: pthread_rwlock_t = pthread_rwlock_t { - lock: PTHREAD_MUTEX_INITIALIZER, - cond: PTHREAD_COND_INITIALIZER, - numLocks: 0, - writerThreadId: 0, - pendingReaders: 0, - pendingWriters: 0, - reserved: [ptr::null_mut(); 4], - }; - pub const PTHREAD_MUTEX_RECURSIVE: libc::c_int = 1; -} - -#[cfg(target_os = "netbsd")] -mod os { - use libc; - - // size of the type minus width of the magic and alignment field - #[cfg(target_arch = "x86_64")] - const __PTHREAD_MUTEX_SIZE__: usize = 48 - 4 - 8; - - #[cfg(target_arch = "x86_64")] - const __PTHREAD_MUTEXATTR_SIZE__: usize = 16 - 8; // no magic field - - #[cfg(target_arch = "x86_64")] - const __PTHREAD_COND_SIZE__: usize = 40 - 4 - 8; - - #[cfg(target_arch = "x86_64")] - const __PTHREAD_RWLOCK_SIZE__: usize = 64 - 4 - 8; - - const _PTHREAD_MUTEX_MAGIC_INIT: libc::c_uint = 0x33330003; - const _PTHREAD_COND_MAGIC_INIT: libc::c_uint = 0x55550005; - const _PTHREAD_RWLOCK_MAGIC_INIT: libc::c_uint = 0x99990009; - - #[repr(C)] - pub struct pthread_mutex_t { - __magic: libc::c_uint, - __opaque: [u8; __PTHREAD_MUTEX_SIZE__], - __align: libc::c_longlong, - } - #[repr(C)] - pub struct pthread_mutexattr_t { - __opaque: [u8; __PTHREAD_MUTEXATTR_SIZE__], - __align: libc::c_longlong, - } - #[repr(C)] - pub struct pthread_cond_t { - __magic: libc::c_uint, - __opaque: [u8; __PTHREAD_COND_SIZE__], - __align: libc::c_longlong, - } - #[repr(C)] - pub struct pthread_rwlock_t { - __magic: libc::c_uint, - __opaque: [u8; __PTHREAD_RWLOCK_SIZE__], - __align: libc::c_longlong, - } - - pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = pthread_mutex_t { - __magic: _PTHREAD_MUTEX_MAGIC_INIT, - __opaque: [0; __PTHREAD_MUTEX_SIZE__], - __align: 0, - }; - pub const PTHREAD_COND_INITIALIZER: pthread_cond_t = pthread_cond_t { - __magic: _PTHREAD_COND_MAGIC_INIT, - __opaque: [0; __PTHREAD_COND_SIZE__], - __align: 0, - }; - pub const PTHREAD_RWLOCK_INITIALIZER: pthread_rwlock_t = pthread_rwlock_t { - __magic: _PTHREAD_RWLOCK_MAGIC_INIT, - __opaque: [0; __PTHREAD_RWLOCK_SIZE__], - __align: 0, - }; - - pub const PTHREAD_MUTEX_RECURSIVE: libc::c_int = 2; -} -#[cfg(target_os = "nacl")] -mod os { - use libc; - - pub type __nc_basic_thread_data = libc::c_void; - - #[repr(C)] - pub struct pthread_mutex_t { - mutex_state: libc::c_int, - mutex_type: libc::c_int, - owner_thread_id: *mut __nc_basic_thread_data, - recursion_counter: libc::uint32_t, - _unused: libc::c_int, - } - #[repr(C)] - pub struct pthread_mutexattr_t { - kind: libc::c_int, - } - #[repr(C)] - pub struct pthread_cond_t { - sequence_number: libc::c_int, - _unused: libc::c_int, - } - #[repr(C)] - pub struct pthread_rwlock_t { - mutex: pthread_mutex_t, - reader_count: libc::c_int, - writers_waiting: libc::c_int, - writer_thread_id: *mut __nc_basic_thread_data, - read_possible: pthread_cond_t, - write_possible: pthread_cond_t, - } - - const NC_INVALID_HANDLE: libc::c_int = -1; - const NACL_PTHREAD_ILLEGAL_THREAD_ID: *mut __nc_basic_thread_data - = 0 as *mut __nc_basic_thread_data; - - pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = pthread_mutex_t { - mutex_state: 0, - mutex_type: 0, - owner_thread_id: NACL_PTHREAD_ILLEGAL_THREAD_ID, - recursion_counter: 0, - _unused: NC_INVALID_HANDLE, - }; - pub const PTHREAD_COND_INITIALIZER: pthread_cond_t = pthread_cond_t { - sequence_number: 0, - _unused: NC_INVALID_HANDLE, - }; - pub const PTHREAD_RWLOCK_INITIALIZER: pthread_rwlock_t = pthread_rwlock_t { - mutex: PTHREAD_MUTEX_INITIALIZER, - reader_count: 0, - writers_waiting: 0, - writer_thread_id: NACL_PTHREAD_ILLEGAL_THREAD_ID, - read_possible: PTHREAD_COND_INITIALIZER, - write_possible: PTHREAD_COND_INITIALIZER, - }; - pub const PTHREAD_MUTEX_RECURSIVE: libc::c_int = 1; -} diff --git a/src/libstd/sys/unix/thread.rs b/src/libstd/sys/unix/thread.rs index 3eedb76c21b72..f111f97be60a0 100644 --- a/src/libstd/sys/unix/thread.rs +++ b/src/libstd/sys/unix/thread.rs @@ -17,7 +17,7 @@ use cmp; #[cfg(not(target_env = "newlib"))] use ffi::CString; use io; -use libc::consts::os::posix01::PTHREAD_STACK_MIN; +use libc::PTHREAD_STACK_MIN; use libc; use mem; use ptr; @@ -41,10 +41,11 @@ impl Thread { let p = box p; let mut native: libc::pthread_t = mem::zeroed(); let mut attr: libc::pthread_attr_t = mem::zeroed(); - assert_eq!(pthread_attr_init(&mut attr), 0); + assert_eq!(libc::pthread_attr_init(&mut attr), 0); let stack_size = cmp::max(stack, min_stack_size(&attr)); - match pthread_attr_setstacksize(&mut attr, stack_size as libc::size_t) { + match libc::pthread_attr_setstacksize(&mut attr, + stack_size as libc::size_t) { 0 => {} n => { assert_eq!(n, libc::EINVAL); @@ -56,13 +57,14 @@ impl Thread { let stack_size = (stack_size + page_size - 1) & (-(page_size as isize - 1) as usize - 1); let stack_size = stack_size as libc::size_t; - assert_eq!(pthread_attr_setstacksize(&mut attr, stack_size), 0); + assert_eq!(libc::pthread_attr_setstacksize(&mut attr, + stack_size), 0); } }; - let ret = pthread_create(&mut native, &attr, thread_start, - &*p as *const _ as *mut _); - assert_eq!(pthread_attr_destroy(&mut attr), 0); + let ret = libc::pthread_create(&mut native, &attr, thread_start, + &*p as *const _ as *mut _); + assert_eq!(libc::pthread_attr_destroy(&mut attr), 0); return if ret != 0 { Err(io::Error::from_raw_os_error(ret)) @@ -78,25 +80,20 @@ impl Thread { } pub fn yield_now() { - let ret = unsafe { sched_yield() }; + let ret = unsafe { libc::sched_yield() }; debug_assert_eq!(ret, 0); } #[cfg(any(target_os = "linux", target_os = "android"))] pub fn set_name(name: &str) { - // pthread wrapper only appeared in glibc 2.12, so we use syscall - // directly. - extern { - fn prctl(option: libc::c_int, arg2: libc::c_ulong, - arg3: libc::c_ulong, arg4: libc::c_ulong, - arg5: libc::c_ulong) -> libc::c_int; - } const PR_SET_NAME: libc::c_int = 15; let cname = CString::new(name).unwrap_or_else(|_| { panic!("thread name may not contain interior null bytes") }); + // pthread wrapper only appeared in glibc 2.12, so we use syscall + // directly. unsafe { - prctl(PR_SET_NAME, cname.as_ptr() as libc::c_ulong, 0, 0, 0); + libc::prctl(PR_SET_NAME, cname.as_ptr() as libc::c_ulong, 0, 0, 0); } } @@ -105,39 +102,27 @@ impl Thread { target_os = "bitrig", target_os = "openbsd"))] pub fn set_name(name: &str) { - extern { - fn pthread_set_name_np(tid: libc::pthread_t, - name: *const libc::c_char); - } let cname = CString::new(name).unwrap(); unsafe { - pthread_set_name_np(pthread_self(), cname.as_ptr()); + libc::pthread_set_name_np(libc::pthread_self(), cname.as_ptr()); } } #[cfg(any(target_os = "macos", target_os = "ios"))] pub fn set_name(name: &str) { - extern { - fn pthread_setname_np(name: *const libc::c_char) -> libc::c_int; - } let cname = CString::new(name).unwrap(); unsafe { - pthread_setname_np(cname.as_ptr()); + libc::pthread_setname_np(cname.as_ptr()); } } #[cfg(target_os = "netbsd")] pub fn set_name(name: &str) { - extern { - fn pthread_setname_np(thread: libc::pthread_t, - name: *const libc::c_char, - arg: *mut libc::c_void) -> libc::c_int; - } let cname = CString::new(&b"%s"[..]).unwrap(); let carg = CString::new(name).unwrap(); unsafe { - pthread_setname_np(pthread_self(), cname.as_ptr(), - carg.as_ptr() as *mut libc::c_void); + libc::pthread_setname_np(libc::pthread_self(), cname.as_ptr(), + carg.as_ptr() as *mut libc::c_void); } } #[cfg(target_env = "newlib")] @@ -162,7 +147,7 @@ impl Thread { pub fn join(self) { unsafe { - let ret = pthread_join(self.id, ptr::null_mut()); + let ret = libc::pthread_join(self.id, ptr::null_mut()); mem::forget(self); debug_assert_eq!(ret, 0); } @@ -171,7 +156,7 @@ impl Thread { impl Drop for Thread { fn drop(&mut self) { - let ret = unsafe { pthread_detach(self.id) }; + let ret = unsafe { libc::pthread_detach(self.id) }; debug_assert_eq!(ret, 0); } } @@ -197,15 +182,10 @@ pub mod guard { use prelude::v1::*; use libc::{self, pthread_t}; - use libc::funcs::posix88::mman::mmap; - use libc::consts::os::posix88::{PROT_NONE, - MAP_PRIVATE, - MAP_ANON, - MAP_FAILED, - MAP_FIXED}; + use libc::mmap; + use libc::{PROT_NONE, MAP_PRIVATE, MAP_ANON, MAP_FAILED, MAP_FIXED}; use mem; use ptr; - use super::{pthread_self, pthread_attr_destroy}; use sys::os; #[cfg(any(target_os = "macos", @@ -217,19 +197,17 @@ pub mod guard { #[cfg(any(target_os = "linux", target_os = "android", target_os = "netbsd"))] unsafe fn get_stack_start() -> Option<*mut libc::c_void> { - use super::pthread_attr_init; - let mut ret = None; let mut attr: libc::pthread_attr_t = mem::zeroed(); - assert_eq!(pthread_attr_init(&mut attr), 0); - if pthread_getattr_np(pthread_self(), &mut attr) == 0 { + assert_eq!(libc::pthread_attr_init(&mut attr), 0); + if libc::pthread_getattr_np(libc::pthread_self(), &mut attr) == 0 { let mut stackaddr = ptr::null_mut(); let mut stacksize = 0; - assert_eq!(pthread_attr_getstack(&attr, &mut stackaddr, - &mut stacksize), 0); + assert_eq!(libc::pthread_attr_getstack(&attr, &mut stackaddr, + &mut stacksize), 0); ret = Some(stackaddr); } - assert_eq!(pthread_attr_destroy(&mut attr), 0); + assert_eq!(libc::pthread_attr_destroy(&mut attr), 0); ret } @@ -273,33 +251,18 @@ pub mod guard { #[cfg(target_os = "macos")] pub unsafe fn current() -> Option { - extern { - fn pthread_get_stackaddr_np(thread: pthread_t) -> *mut libc::c_void; - fn pthread_get_stacksize_np(thread: pthread_t) -> libc::size_t; - } - Some((pthread_get_stackaddr_np(pthread_self()) as libc::size_t - - pthread_get_stacksize_np(pthread_self())) as usize) + Some((libc::pthread_get_stackaddr_np(libc::pthread_self()) as libc::size_t - + libc::pthread_get_stacksize_np(libc::pthread_self())) as usize) } #[cfg(any(target_os = "openbsd", target_os = "bitrig"))] pub unsafe fn current() -> Option { - #[repr(C)] - struct stack_t { - ss_sp: *mut libc::c_void, - ss_size: libc::size_t, - ss_flags: libc::c_int, - } - extern { - fn pthread_main_np() -> libc::c_uint; - fn pthread_stackseg_np(thread: pthread_t, - sinfo: *mut stack_t) -> libc::c_uint; - } - - let mut current_stack: stack_t = mem::zeroed(); - assert_eq!(pthread_stackseg_np(pthread_self(), &mut current_stack), 0); + let mut current_stack: libc::stack_t = mem::zeroed(); + assert_eq!(libc::pthread_stackseg_np(libc::pthread_self(), + &mut current_stack), 0); let extra = if cfg!(target_os = "bitrig") {3} else {1} * os::page_size(); - Some(if pthread_main_np() == 1 { + Some(if libc::pthread_main_np() == 1 { // main thread current_stack.ss_sp as usize - current_stack.ss_size as usize + extra } else { @@ -310,20 +273,19 @@ pub mod guard { #[cfg(any(target_os = "linux", target_os = "android", target_os = "netbsd"))] pub unsafe fn current() -> Option { - use super::pthread_attr_init; - let mut ret = None; let mut attr: libc::pthread_attr_t = mem::zeroed(); - assert_eq!(pthread_attr_init(&mut attr), 0); - if pthread_getattr_np(pthread_self(), &mut attr) == 0 { + assert_eq!(libc::pthread_attr_init(&mut attr), 0); + if libc::pthread_getattr_np(libc::pthread_self(), &mut attr) == 0 { let mut guardsize = 0; - assert_eq!(pthread_attr_getguardsize(&attr, &mut guardsize), 0); + assert_eq!(libc::pthread_attr_getguardsize(&attr, &mut guardsize), 0); if guardsize == 0 { panic!("there is no guard page"); } let mut stackaddr = ptr::null_mut(); let mut size = 0; - assert_eq!(pthread_attr_getstack(&attr, &mut stackaddr, &mut size), 0); + assert_eq!(libc::pthread_attr_getstack(&attr, &mut stackaddr, + &mut size), 0); ret = if cfg!(target_os = "netbsd") { Some(stackaddr as usize) @@ -331,20 +293,9 @@ pub mod guard { Some(stackaddr as usize + guardsize as usize) }; } - assert_eq!(pthread_attr_destroy(&mut attr), 0); + assert_eq!(libc::pthread_attr_destroy(&mut attr), 0); ret } - - #[cfg(any(target_os = "linux", target_os = "android", target_os = "netbsd"))] - extern { - fn pthread_getattr_np(native: libc::pthread_t, - attr: *mut libc::pthread_attr_t) -> libc::c_int; - fn pthread_attr_getguardsize(attr: *const libc::pthread_attr_t, - guardsize: *mut libc::size_t) -> libc::c_int; - fn pthread_attr_getstack(attr: *const libc::pthread_attr_t, - stackaddr: *mut *mut libc::c_void, - stacksize: *mut libc::size_t) -> libc::c_int; - } } // glibc >= 2.15 has a __pthread_get_minstack() function that returns @@ -394,21 +345,3 @@ fn min_stack_size(attr: *const libc::pthread_attr_t) -> usize { fn min_stack_size(_: *const libc::pthread_attr_t) -> usize { PTHREAD_STACK_MIN as usize } - -extern { - fn pthread_self() -> libc::pthread_t; - fn pthread_create(native: *mut libc::pthread_t, - attr: *const libc::pthread_attr_t, - f: extern fn(*mut libc::c_void) -> *mut libc::c_void, - value: *mut libc::c_void) -> libc::c_int; - fn pthread_join(native: libc::pthread_t, - value: *mut *mut libc::c_void) -> libc::c_int; - fn pthread_attr_init(attr: *mut libc::pthread_attr_t) -> libc::c_int; - fn pthread_attr_destroy(attr: *mut libc::pthread_attr_t) -> libc::c_int; - fn pthread_attr_setstacksize(attr: *mut libc::pthread_attr_t, - stack_size: libc::size_t) -> libc::c_int; - fn pthread_attr_setdetachstate(attr: *mut libc::pthread_attr_t, - state: libc::c_int) -> libc::c_int; - fn pthread_detach(thread: libc::pthread_t) -> libc::c_int; - fn sched_yield() -> libc::c_int; -} diff --git a/src/libstd/sys/unix/thread_local.rs b/src/libstd/sys/unix/thread_local.rs index e9bf214e8161c..d22118d4d793e 100644 --- a/src/libstd/sys/unix/thread_local.rs +++ b/src/libstd/sys/unix/thread_local.rs @@ -8,62 +8,33 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![allow(dead_code)] // sys isn't exported yet +#![allow(dead_code)] // not used on all platforms -use libc::c_int; +use mem; +use libc; -pub type Key = pthread_key_t; +pub type Key = libc::pthread_key_t; #[inline] pub unsafe fn create(dtor: Option) -> Key { let mut key = 0; - assert_eq!(pthread_key_create(&mut key, dtor), 0); + assert_eq!(libc::pthread_key_create(&mut key, mem::transmute(dtor)), 0); key } #[inline] pub unsafe fn set(key: Key, value: *mut u8) { - let r = pthread_setspecific(key, value); + let r = libc::pthread_setspecific(key, value as *mut _); debug_assert_eq!(r, 0); } #[inline] pub unsafe fn get(key: Key) -> *mut u8 { - pthread_getspecific(key) + libc::pthread_getspecific(key) as *mut u8 } #[inline] pub unsafe fn destroy(key: Key) { - let r = pthread_key_delete(key); + let r = libc::pthread_key_delete(key); debug_assert_eq!(r, 0); } - -#[cfg(any(target_os = "macos", - target_os = "ios"))] -type pthread_key_t = ::libc::c_ulong; - -#[cfg(any(target_os = "freebsd", - target_os = "dragonfly", - target_os = "bitrig", - target_os = "netbsd", - target_os = "openbsd", - target_os = "nacl"))] -type pthread_key_t = ::libc::c_int; - -#[cfg(not(any(target_os = "macos", - target_os = "ios", - target_os = "freebsd", - target_os = "dragonfly", - target_os = "bitrig", - target_os = "netbsd", - target_os = "openbsd", - target_os = "nacl")))] -type pthread_key_t = ::libc::c_uint; - -extern { - fn pthread_key_create(key: *mut pthread_key_t, - dtor: Option) -> c_int; - fn pthread_key_delete(key: pthread_key_t) -> c_int; - fn pthread_getspecific(key: pthread_key_t) -> *mut u8; - fn pthread_setspecific(key: pthread_key_t, value: *mut u8) -> c_int; -} diff --git a/src/libstd/sys/unix/time.rs b/src/libstd/sys/unix/time.rs index 35d55902f9c8b..5192f01269d0c 100644 --- a/src/libstd/sys/unix/time.rs +++ b/src/libstd/sys/unix/time.rs @@ -24,15 +24,10 @@ mod inner { t: u64 } - extern { - pub fn mach_absolute_time() -> u64; - pub fn mach_timebase_info(info: *mut libc::mach_timebase_info) -> libc::c_int; - } - impl SteadyTime { pub fn now() -> SteadyTime { SteadyTime { - t: unsafe { mach_absolute_time() }, + t: unsafe { libc::mach_absolute_time() }, } } } @@ -46,7 +41,7 @@ mod inner { unsafe { ONCE.call_once(|| { - mach_timebase_info(&mut INFO); + libc::mach_timebase_info(&mut INFO); }); &INFO } @@ -87,11 +82,6 @@ mod inner { #[link(name = "rt")] extern {} - extern { - #[cfg_attr(target_os = "netbsd", link_name = "__clock_gettime50")] - fn clock_gettime(clk_id: libc::c_int, tp: *mut libc::timespec) -> libc::c_int; - } - impl SteadyTime { pub fn now() -> SteadyTime { let mut t = SteadyTime { @@ -101,7 +91,8 @@ mod inner { } }; unsafe { - assert_eq!(0, clock_gettime(libc::CLOCK_MONOTONIC, &mut t.t)); + assert_eq!(0, libc::clock_gettime(libc::CLOCK_MONOTONIC, + &mut t.t)); } t } diff --git a/src/libstd/sys/windows/backtrace.rs b/src/libstd/sys/windows/backtrace.rs index b562e772b9c2c..d106bc3285cb1 100644 --- a/src/libstd/sys/windows/backtrace.rs +++ b/src/libstd/sys/windows/backtrace.rs @@ -27,12 +27,13 @@ use io::prelude::*; use dynamic_lib::DynamicLibrary; -use intrinsics; use io; -use libc; +use libc::c_void; +use mem; use path::Path; use ptr; use sync::StaticMutex; +use sys::c; macro_rules! sym{ ($lib:expr, $e:expr, $t:ident) => (unsafe { let lib = $lib; @@ -50,264 +51,50 @@ mod printing; #[path = "printing/gnu.rs"] mod printing; -#[allow(non_snake_case)] -extern "system" { - fn GetCurrentProcess() -> libc::HANDLE; - fn GetCurrentThread() -> libc::HANDLE; - fn RtlCaptureContext(ctx: *mut arch::CONTEXT); -} - type SymFromAddrFn = - extern "system" fn(libc::HANDLE, u64, *mut u64, - *mut SYMBOL_INFO) -> libc::BOOL; + extern "system" fn(c::HANDLE, u64, *mut u64, + *mut c::SYMBOL_INFO) -> c::BOOL; type SymGetLineFromAddr64Fn = - extern "system" fn(libc::HANDLE, u64, *mut u32, - *mut IMAGEHLP_LINE64) -> libc::BOOL; + extern "system" fn(c::HANDLE, u64, *mut u32, + *mut c::IMAGEHLP_LINE64) -> c::BOOL; type SymInitializeFn = - extern "system" fn(libc::HANDLE, *mut libc::c_void, - libc::BOOL) -> libc::BOOL; + extern "system" fn(c::HANDLE, *mut c_void, + c::BOOL) -> c::BOOL; type SymCleanupFn = - extern "system" fn(libc::HANDLE) -> libc::BOOL; + extern "system" fn(c::HANDLE) -> c::BOOL; type StackWalk64Fn = - extern "system" fn(libc::DWORD, libc::HANDLE, libc::HANDLE, - *mut STACKFRAME64, *mut arch::CONTEXT, - *mut libc::c_void, *mut libc::c_void, - *mut libc::c_void, *mut libc::c_void) -> libc::BOOL; - -const MAX_SYM_NAME: usize = 2000; -const IMAGE_FILE_MACHINE_I386: libc::DWORD = 0x014c; -const IMAGE_FILE_MACHINE_IA64: libc::DWORD = 0x0200; -const IMAGE_FILE_MACHINE_AMD64: libc::DWORD = 0x8664; - -#[repr(C)] -struct SYMBOL_INFO { - SizeOfStruct: libc::c_ulong, - TypeIndex: libc::c_ulong, - Reserved: [u64; 2], - Index: libc::c_ulong, - Size: libc::c_ulong, - ModBase: u64, - Flags: libc::c_ulong, - Value: u64, - Address: u64, - Register: libc::c_ulong, - Scope: libc::c_ulong, - Tag: libc::c_ulong, - NameLen: libc::c_ulong, - MaxNameLen: libc::c_ulong, - // note that windows has this as 1, but it basically just means that - // the name is inline at the end of the struct. For us, we just bump - // the struct size up to MAX_SYM_NAME. - Name: [libc::c_char; MAX_SYM_NAME], -} - -#[repr(C)] -struct IMAGEHLP_LINE64 { - SizeOfStruct: u32, - Key: *const libc::c_void, - LineNumber: u32, - Filename: *const libc::c_char, - Address: u64, -} - -#[repr(C)] -enum ADDRESS_MODE { - AddrMode1616, - AddrMode1632, - AddrModeReal, - AddrModeFlat, -} - -struct ADDRESS64 { - Offset: u64, - Segment: u16, - Mode: ADDRESS_MODE, -} - -pub struct STACKFRAME64 { - AddrPC: ADDRESS64, - AddrReturn: ADDRESS64, - AddrFrame: ADDRESS64, - AddrStack: ADDRESS64, - AddrBStore: ADDRESS64, - FuncTableEntry: *mut libc::c_void, - Params: [u64; 4], - Far: libc::BOOL, - Virtual: libc::BOOL, - Reserved: [u64; 3], - KdHelp: KDHELP64, -} - -struct KDHELP64 { - Thread: u64, - ThCallbackStack: libc::DWORD, - ThCallbackBStore: libc::DWORD, - NextCallback: libc::DWORD, - FramePointer: libc::DWORD, - KiCallUserMode: u64, - KeUserCallbackDispatcher: u64, - SystemRangeStart: u64, - KiUserExceptionDispatcher: u64, - StackBase: u64, - StackLimit: u64, - Reserved: [u64; 5], -} + extern "system" fn(c::DWORD, c::HANDLE, c::HANDLE, + *mut c::STACKFRAME64, *mut c::CONTEXT, + *mut c_void, *mut c_void, + *mut c_void, *mut c_void) -> c::BOOL; #[cfg(target_arch = "x86")] -mod arch { - use libc; - - const MAXIMUM_SUPPORTED_EXTENSION: usize = 512; - - #[repr(C)] - pub struct CONTEXT { - ContextFlags: libc::DWORD, - Dr0: libc::DWORD, - Dr1: libc::DWORD, - Dr2: libc::DWORD, - Dr3: libc::DWORD, - Dr6: libc::DWORD, - Dr7: libc::DWORD, - FloatSave: FLOATING_SAVE_AREA, - SegGs: libc::DWORD, - SegFs: libc::DWORD, - SegEs: libc::DWORD, - SegDs: libc::DWORD, - Edi: libc::DWORD, - Esi: libc::DWORD, - Ebx: libc::DWORD, - Edx: libc::DWORD, - Ecx: libc::DWORD, - Eax: libc::DWORD, - Ebp: libc::DWORD, - Eip: libc::DWORD, - SegCs: libc::DWORD, - EFlags: libc::DWORD, - Esp: libc::DWORD, - SegSs: libc::DWORD, - ExtendedRegisters: [u8; MAXIMUM_SUPPORTED_EXTENSION], - } - - #[repr(C)] - pub struct FLOATING_SAVE_AREA { - ControlWord: libc::DWORD, - StatusWord: libc::DWORD, - TagWord: libc::DWORD, - ErrorOffset: libc::DWORD, - ErrorSelector: libc::DWORD, - DataOffset: libc::DWORD, - DataSelector: libc::DWORD, - RegisterArea: [u8; 80], - Cr0NpxState: libc::DWORD, - } - - pub fn init_frame(frame: &mut super::STACKFRAME64, - ctx: &CONTEXT) -> libc::DWORD { - frame.AddrPC.Offset = ctx.Eip as u64; - frame.AddrPC.Mode = super::ADDRESS_MODE::AddrModeFlat; - frame.AddrStack.Offset = ctx.Esp as u64; - frame.AddrStack.Mode = super::ADDRESS_MODE::AddrModeFlat; - frame.AddrFrame.Offset = ctx.Ebp as u64; - frame.AddrFrame.Mode = super::ADDRESS_MODE::AddrModeFlat; - super::IMAGE_FILE_MACHINE_I386 - } +pub fn init_frame(frame: &mut c::STACKFRAME64, + ctx: &c::CONTEXT) -> c::DWORD { + frame.AddrPC.Offset = ctx.Eip as u64; + frame.AddrPC.Mode = c::ADDRESS_MODE::AddrModeFlat; + frame.AddrStack.Offset = ctx.Esp as u64; + frame.AddrStack.Mode = c::ADDRESS_MODE::AddrModeFlat; + frame.AddrFrame.Offset = ctx.Ebp as u64; + frame.AddrFrame.Mode = c::ADDRESS_MODE::AddrModeFlat; + c::IMAGE_FILE_MACHINE_I386 } #[cfg(target_arch = "x86_64")] -mod arch { - #![allow(deprecated)] - - use libc::{c_longlong, c_ulonglong}; - use libc::types::os::arch::extra::{WORD, DWORD, DWORDLONG}; - use simd; - - #[repr(C)] - pub struct CONTEXT { - _align_hack: [simd::u64x2; 0], // FIXME align on 16-byte - P1Home: DWORDLONG, - P2Home: DWORDLONG, - P3Home: DWORDLONG, - P4Home: DWORDLONG, - P5Home: DWORDLONG, - P6Home: DWORDLONG, - - ContextFlags: DWORD, - MxCsr: DWORD, - - SegCs: WORD, - SegDs: WORD, - SegEs: WORD, - SegFs: WORD, - SegGs: WORD, - SegSs: WORD, - EFlags: DWORD, - - Dr0: DWORDLONG, - Dr1: DWORDLONG, - Dr2: DWORDLONG, - Dr3: DWORDLONG, - Dr6: DWORDLONG, - Dr7: DWORDLONG, - - Rax: DWORDLONG, - Rcx: DWORDLONG, - Rdx: DWORDLONG, - Rbx: DWORDLONG, - Rsp: DWORDLONG, - Rbp: DWORDLONG, - Rsi: DWORDLONG, - Rdi: DWORDLONG, - R8: DWORDLONG, - R9: DWORDLONG, - R10: DWORDLONG, - R11: DWORDLONG, - R12: DWORDLONG, - R13: DWORDLONG, - R14: DWORDLONG, - R15: DWORDLONG, - - Rip: DWORDLONG, - - FltSave: FLOATING_SAVE_AREA, - - VectorRegister: [M128A; 26], - VectorControl: DWORDLONG, - - DebugControl: DWORDLONG, - LastBranchToRip: DWORDLONG, - LastBranchFromRip: DWORDLONG, - LastExceptionToRip: DWORDLONG, - LastExceptionFromRip: DWORDLONG, - } - - #[repr(C)] - pub struct M128A { - _align_hack: [simd::u64x2; 0], // FIXME align on 16-byte - Low: c_ulonglong, - High: c_longlong - } - - #[repr(C)] - pub struct FLOATING_SAVE_AREA { - _align_hack: [simd::u64x2; 0], // FIXME align on 16-byte - _Dummy: [u8; 512] // FIXME: Fill this out - } - - pub fn init_frame(frame: &mut super::STACKFRAME64, - ctx: &CONTEXT) -> DWORD { - frame.AddrPC.Offset = ctx.Rip as u64; - frame.AddrPC.Mode = super::ADDRESS_MODE::AddrModeFlat; - frame.AddrStack.Offset = ctx.Rsp as u64; - frame.AddrStack.Mode = super::ADDRESS_MODE::AddrModeFlat; - frame.AddrFrame.Offset = ctx.Rbp as u64; - frame.AddrFrame.Mode = super::ADDRESS_MODE::AddrModeFlat; - super::IMAGE_FILE_MACHINE_AMD64 - } +pub fn init_frame(frame: &mut c::STACKFRAME64, + ctx: &c::CONTEXT) -> c::DWORD { + frame.AddrPC.Offset = ctx.Rip as u64; + frame.AddrPC.Mode = c::ADDRESS_MODE::AddrModeFlat; + frame.AddrStack.Offset = ctx.Rsp as u64; + frame.AddrStack.Mode = c::ADDRESS_MODE::AddrModeFlat; + frame.AddrFrame.Offset = ctx.Rbp as u64; + frame.AddrFrame.Mode = c::ADDRESS_MODE::AddrModeFlat; + c::IMAGE_FILE_MACHINE_AMD64 } struct Cleanup { - handle: libc::HANDLE, + handle: c::HANDLE, SymCleanup: SymCleanupFn, } @@ -335,16 +122,16 @@ pub fn write(w: &mut Write) -> io::Result<()> { let StackWalk64 = sym!(&dbghelp, "StackWalk64", StackWalk64Fn); // Allocate necessary structures for doing the stack walk - let process = unsafe { GetCurrentProcess() }; - let thread = unsafe { GetCurrentThread() }; - let mut context: arch::CONTEXT = unsafe { intrinsics::init() }; - unsafe { RtlCaptureContext(&mut context); } - let mut frame: STACKFRAME64 = unsafe { intrinsics::init() }; - let image = arch::init_frame(&mut frame, &context); + let process = unsafe { c::GetCurrentProcess() }; + let thread = unsafe { c::GetCurrentThread() }; + let mut context: c::CONTEXT = unsafe { mem::zeroed() }; + unsafe { c::RtlCaptureContext(&mut context); } + let mut frame: c::STACKFRAME64 = unsafe { mem::zeroed() }; + let image = init_frame(&mut frame, &context); // Initialize this process's symbols - let ret = SymInitialize(process, ptr::null_mut(), libc::TRUE); - if ret != libc::TRUE { return Ok(()) } + let ret = SymInitialize(process, ptr::null_mut(), c::TRUE); + if ret != c::TRUE { return Ok(()) } let _c = Cleanup { handle: process, SymCleanup: SymCleanup }; // And now that we're done with all the setup, do the stack walking! @@ -356,7 +143,7 @@ pub fn write(w: &mut Write) -> io::Result<()> { ptr::null_mut(), ptr::null_mut(), ptr::null_mut(), - ptr::null_mut()) == libc::TRUE{ + ptr::null_mut()) == c::TRUE { let addr = frame.AddrPC.Offset; if addr == frame.AddrReturn.Offset || addr == 0 || frame.AddrReturn.Offset == 0 { break } diff --git a/src/libstd/sys/windows/c.rs b/src/libstd/sys/windows/c.rs index b168081ff8a2e..42f182eb01066 100644 --- a/src/libstd/sys/windows/c.rs +++ b/src/libstd/sys/windows/c.rs @@ -10,86 +10,336 @@ //! C definitions used by libnative that don't belong in liblibc -#![allow(bad_style, dead_code, overflowing_literals)] +#![allow(bad_style, overflowing_literals, dead_code, deprecated, unused_imports)] -use libc; -use libc::{c_uint, c_ulong}; -use libc::{DWORD, BOOL, BOOLEAN, ERROR_CALL_NOT_IMPLEMENTED, LPVOID, HANDLE}; -use libc::{LPCWSTR, LONG}; +use os::raw::{c_int, c_uint, c_ulong, c_long, c_longlong, c_ushort}; +use os::raw::{c_char, c_short, c_ulonglong}; +use libc::{wchar_t, size_t, c_void}; use ptr; +use simd; pub use self::GET_FILEEX_INFO_LEVELS::*; pub use self::FILE_INFO_BY_HANDLE_CLASS::*; -pub use libc::consts::os::extra::{ - FILE_ATTRIBUTE_READONLY, - FILE_ATTRIBUTE_DIRECTORY, - WSAPROTOCOL_LEN, -}; -pub use libc::types::os::arch::extra::{GROUP, GUID, WSAPROTOCOLCHAIN}; +pub use self::EXCEPTION_DISPOSITION::*; -pub const WSADESCRIPTION_LEN: usize = 256; -pub const WSASYS_STATUS_LEN: usize = 128; -pub const FIONBIO: libc::c_long = 0x8004667e; +pub type DWORD = c_ulong; +pub type HANDLE = LPVOID; +pub type HINSTANCE = HANDLE; +pub type HMODULE = HINSTANCE; +pub type BOOL = c_int; +pub type BYTE = u8; +pub type BOOLEAN = BYTE; +pub type GROUP = c_uint; +pub type LONG_PTR = isize; +pub type LARGE_INTEGER = c_longlong; +pub type LONG = c_long; +pub type UINT = c_uint; +pub type WCHAR = u16; +pub type USHORT = c_ushort; +pub type SIZE_T = usize; +pub type WORD = u16; +pub type CHAR = c_char; +pub type HCRYPTPROV = LONG_PTR; +pub type ULONG_PTR = c_ulonglong; +pub type ULONG = c_ulong; +pub type ULONGLONG = u64; +pub type DWORDLONG = ULONGLONG; + +pub type LPBOOL = *mut BOOL; +pub type LPBYTE = *mut BYTE; +pub type LPBY_HANDLE_FILE_INFORMATION = *mut BY_HANDLE_FILE_INFORMATION; +pub type LPCSTR = *const CHAR; +pub type LPCVOID = *const c_void; +pub type LPCWSTR = *const WCHAR; +pub type LPDWORD = *mut DWORD; +pub type LPHANDLE = *mut HANDLE; +pub type LPOVERLAPPED = *mut OVERLAPPED; +pub type LPPROCESS_INFORMATION = *mut PROCESS_INFORMATION; +pub type LPSECURITY_ATTRIBUTES = *mut SECURITY_ATTRIBUTES; +pub type LPSTARTUPINFO = *mut STARTUPINFO; +pub type LPVOID = *mut c_void; +pub type LPWCH = *mut WCHAR; +pub type LPWIN32_FIND_DATAW = *mut WIN32_FIND_DATAW; +pub type LPWSADATA = *mut WSADATA; +pub type LPWSANETWORKEVENTS = *mut WSANETWORKEVENTS; +pub type LPWSAPROTOCOLCHAIN = *mut WSAPROTOCOLCHAIN; +pub type LPWSAPROTOCOL_INFO = *mut WSAPROTOCOL_INFO; +pub type LPWSTR = *mut WCHAR; + +pub type PCONDITION_VARIABLE = *mut CONDITION_VARIABLE; +pub type PLARGE_INTEGER = *mut c_longlong; +pub type PSRWLOCK = *mut SRWLOCK; + +pub type SOCKET = ::os::windows::raw::SOCKET; +pub type socklen_t = c_int; +pub type ADDRESS_FAMILY = USHORT; + +pub const TRUE: BOOL = 1; +pub const FALSE: BOOL = 0; + +pub const FILE_ATTRIBUTE_READONLY: DWORD = 0x1; +pub const FILE_ATTRIBUTE_DIRECTORY: DWORD = 0x10; +pub const FILE_ATTRIBUTE_NORMAL: DWORD = 0x80; +pub const FILE_ATTRIBUTE_REPARSE_POINT: DWORD = 0x400; +pub const FILE_SHARE_DELETE: DWORD = 0x4; +pub const FILE_SHARE_READ: DWORD = 0x1; +pub const FILE_SHARE_WRITE: DWORD = 0x2; +pub const CREATE_ALWAYS: DWORD = 2; +pub const CREATE_NEW: DWORD = 1; +pub const OPEN_ALWAYS: DWORD = 4; +pub const OPEN_EXISTING: DWORD = 3; +pub const TRUNCATE_EXISTING: DWORD = 5; +pub const FILE_APPEND_DATA: DWORD = 0x00000004; +pub const FILE_READ_DATA: DWORD = 0x00000001; +pub const FILE_WRITE_DATA: DWORD = 0x00000002; +pub const STANDARD_RIGHTS_READ: DWORD = 0x20000; +pub const STANDARD_RIGHTS_WRITE: DWORD = 0x20000; +pub const FILE_WRITE_EA: DWORD = 0x00000010; +pub const FILE_READ_EA: DWORD = 0x00000008; +pub const SYNCHRONIZE: DWORD = 0x00100000; +pub const FILE_WRITE_ATTRIBUTES: DWORD = 0x00000100; +pub const FILE_READ_ATTRIBUTES: DWORD = 0x00000080; +pub const FILE_GENERIC_READ: DWORD = STANDARD_RIGHTS_READ | FILE_READ_DATA | + FILE_READ_ATTRIBUTES | + FILE_READ_EA | + SYNCHRONIZE; +pub const FILE_GENERIC_WRITE: DWORD = STANDARD_RIGHTS_WRITE | FILE_WRITE_DATA | + FILE_WRITE_ATTRIBUTES | + FILE_WRITE_EA | + FILE_APPEND_DATA | + SYNCHRONIZE; + +#[repr(C)] +#[derive(Copy)] +pub struct WIN32_FIND_DATAW { + pub dwFileAttributes: DWORD, + pub ftCreationTime: FILETIME, + pub ftLastAccessTime: FILETIME, + pub ftLastWriteTime: FILETIME, + pub nFileSizeHigh: DWORD, + pub nFileSizeLow: DWORD, + pub dwReserved0: DWORD, + pub dwReserved1: DWORD, + pub cFileName: [wchar_t; 260], // #define MAX_PATH 260 + pub cAlternateFileName: [wchar_t; 14], +} +impl Clone for WIN32_FIND_DATAW { + fn clone(&self) -> Self { *self } +} + +pub const FIONBIO: c_long = 0x8004667e; pub const FD_SETSIZE: usize = 64; -pub const MSG_DONTWAIT: libc::c_int = 0; -pub const ERROR_ILLEGAL_CHARACTER: libc::c_int = 582; -pub const ENABLE_ECHO_INPUT: libc::DWORD = 0x4; -pub const ENABLE_EXTENDED_FLAGS: libc::DWORD = 0x80; -pub const ENABLE_INSERT_MODE: libc::DWORD = 0x20; -pub const ENABLE_LINE_INPUT: libc::DWORD = 0x2; -pub const ENABLE_PROCESSED_INPUT: libc::DWORD = 0x1; -pub const ENABLE_QUICK_EDIT_MODE: libc::DWORD = 0x40; -pub const WSA_INVALID_EVENT: WSAEVENT = 0 as WSAEVENT; +pub const MSG_DONTWAIT: c_int = 0; +pub const ENABLE_ECHO_INPUT: DWORD = 0x4; +pub const ENABLE_EXTENDED_FLAGS: DWORD = 0x80; +pub const ENABLE_INSERT_MODE: DWORD = 0x20; +pub const ENABLE_LINE_INPUT: DWORD = 0x2; +pub const ENABLE_PROCESSED_INPUT: DWORD = 0x1; +pub const ENABLE_QUICK_EDIT_MODE: DWORD = 0x40; -pub const FD_ACCEPT: libc::c_long = 0x08; +pub const FD_ACCEPT: c_long = 0x08; pub const FD_MAX_EVENTS: usize = 10; -pub const WSA_INFINITE: libc::DWORD = libc::INFINITE; -pub const WSA_WAIT_TIMEOUT: libc::DWORD = libc::consts::os::extra::WAIT_TIMEOUT; -pub const WSA_WAIT_EVENT_0: libc::DWORD = libc::consts::os::extra::WAIT_OBJECT_0; -pub const WSA_WAIT_FAILED: libc::DWORD = libc::consts::os::extra::WAIT_FAILED; -pub const WSAESHUTDOWN: libc::c_int = 10058; -pub const WSA_FLAG_OVERLAPPED: libc::DWORD = 0x01; -pub const WSA_FLAG_NO_HANDLE_INHERIT: libc::DWORD = 0x80; - -pub const ERROR_NO_MORE_FILES: libc::DWORD = 18; -pub const TOKEN_READ: libc::DWORD = 0x20008; -pub const FILE_FLAG_OPEN_REPARSE_POINT: libc::DWORD = 0x00200000; -pub const FILE_FLAG_BACKUP_SEMANTICS: libc::DWORD = 0x02000000; + +pub const WSA_INVALID_EVENT: WSAEVENT = 0 as WSAEVENT; +pub const WSA_INFINITE: DWORD = INFINITE; +pub const WSA_WAIT_TIMEOUT: DWORD = WAIT_TIMEOUT; +pub const WSA_WAIT_EVENT_0: DWORD = WAIT_OBJECT_0; +pub const WSA_WAIT_FAILED: DWORD = WAIT_FAILED; +pub const WSA_FLAG_OVERLAPPED: DWORD = 0x01; +pub const WSA_FLAG_NO_HANDLE_INHERIT: DWORD = 0x80; + +pub const WSADESCRIPTION_LEN: usize = 256; +pub const WSASYS_STATUS_LEN: usize = 128; +pub const WSAPROTOCOL_LEN: DWORD = 255; +pub const INVALID_SOCKET: SOCKET = !0; + +pub const WSAEINTR: c_int = 10004; +pub const WSAEBADF: c_int = 10009; +pub const WSAEACCES: c_int = 10013; +pub const WSAEFAULT: c_int = 10014; +pub const WSAEINVAL: c_int = 10022; +pub const WSAEMFILE: c_int = 10024; +pub const WSAEWOULDBLOCK: c_int = 10035; +pub const WSAEINPROGRESS: c_int = 10036; +pub const WSAEALREADY: c_int = 10037; +pub const WSAENOTSOCK: c_int = 10038; +pub const WSAEDESTADDRREQ: c_int = 10039; +pub const WSAEMSGSIZE: c_int = 10040; +pub const WSAEPROTOTYPE: c_int = 10041; +pub const WSAENOPROTOOPT: c_int = 10042; +pub const WSAEPROTONOSUPPORT: c_int = 10043; +pub const WSAESOCKTNOSUPPORT: c_int = 10044; +pub const WSAEOPNOTSUPP: c_int = 10045; +pub const WSAEPFNOSUPPORT: c_int = 10046; +pub const WSAEAFNOSUPPORT: c_int = 10047; +pub const WSAEADDRINUSE: c_int = 10048; +pub const WSAEADDRNOTAVAIL: c_int = 10049; +pub const WSAENETDOWN: c_int = 10050; +pub const WSAENETUNREACH: c_int = 10051; +pub const WSAENETRESET: c_int = 10052; +pub const WSAECONNABORTED: c_int = 10053; +pub const WSAECONNRESET: c_int = 10054; +pub const WSAENOBUFS: c_int = 10055; +pub const WSAEISCONN: c_int = 10056; +pub const WSAENOTCONN: c_int = 10057; +pub const WSAESHUTDOWN: c_int = 10058; +pub const WSAETOOMANYREFS: c_int = 10059; +pub const WSAETIMEDOUT: c_int = 10060; +pub const WSAECONNREFUSED: c_int = 10061; +pub const WSAELOOP: c_int = 10062; +pub const WSAENAMETOOLONG: c_int = 10063; +pub const WSAEHOSTDOWN: c_int = 10064; +pub const WSAEHOSTUNREACH: c_int = 10065; +pub const WSAENOTEMPTY: c_int = 10066; +pub const WSAEPROCLIM: c_int = 10067; +pub const WSAEUSERS: c_int = 10068; +pub const WSAEDQUOT: c_int = 10069; +pub const WSAESTALE: c_int = 10070; +pub const WSAEREMOTE: c_int = 10071; +pub const WSASYSNOTREADY: c_int = 10091; +pub const WSAVERNOTSUPPORTED: c_int = 10092; +pub const WSANOTINITIALISED: c_int = 10093; +pub const WSAEDISCON: c_int = 10101; +pub const WSAENOMORE: c_int = 10102; +pub const WSAECANCELLED: c_int = 10103; +pub const WSAEINVALIDPROCTABLE: c_int = 10104; +pub const NI_MAXHOST: DWORD = 1025; + +pub const MAX_PROTOCOL_CHAIN: DWORD = 7; + +pub const TOKEN_READ: DWORD = 0x20008; +pub const FILE_FLAG_OPEN_REPARSE_POINT: DWORD = 0x00200000; +pub const FILE_FLAG_BACKUP_SEMANTICS: DWORD = 0x02000000; pub const MAXIMUM_REPARSE_DATA_BUFFER_SIZE: usize = 16 * 1024; -pub const FSCTL_GET_REPARSE_POINT: libc::DWORD = 0x900a8; -pub const IO_REPARSE_TAG_SYMLINK: libc::DWORD = 0xa000000c; -pub const IO_REPARSE_TAG_MOUNT_POINT: libc::DWORD = 0xa0000003; -pub const FSCTL_SET_REPARSE_POINT: libc::DWORD = 0x900a4; -pub const FSCTL_DELETE_REPARSE_POINT: libc::DWORD = 0x900ac; +pub const FSCTL_GET_REPARSE_POINT: DWORD = 0x900a8; +pub const IO_REPARSE_TAG_SYMLINK: DWORD = 0xa000000c; +pub const IO_REPARSE_TAG_MOUNT_POINT: DWORD = 0xa0000003; +pub const FSCTL_SET_REPARSE_POINT: DWORD = 0x900a4; +pub const FSCTL_DELETE_REPARSE_POINT: DWORD = 0x900ac; -pub const SYMBOLIC_LINK_FLAG_DIRECTORY: libc::DWORD = 0x1; +pub const SYMBOLIC_LINK_FLAG_DIRECTORY: DWORD = 0x1; // Note that these are not actually HANDLEs, just values to pass to GetStdHandle -pub const STD_INPUT_HANDLE: libc::DWORD = -10i32 as libc::DWORD; -pub const STD_OUTPUT_HANDLE: libc::DWORD = -11i32 as libc::DWORD; -pub const STD_ERROR_HANDLE: libc::DWORD = -12i32 as libc::DWORD; +pub const STD_INPUT_HANDLE: DWORD = -10i32 as DWORD; +pub const STD_OUTPUT_HANDLE: DWORD = -11i32 as DWORD; +pub const STD_ERROR_HANDLE: DWORD = -12i32 as DWORD; + +pub const HANDLE_FLAG_INHERIT: DWORD = 0x00000001; + +pub const PROGRESS_CONTINUE: DWORD = 0; +pub const PROGRESS_CANCEL: DWORD = 1; +pub const PROGRESS_STOP: DWORD = 2; +pub const PROGRESS_QUIET: DWORD = 3; + +pub const TOKEN_ADJUST_PRIVILEGES: DWORD = 0x0020; +pub const SE_PRIVILEGE_ENABLED: DWORD = 2; + -pub const HANDLE_FLAG_INHERIT: libc::DWORD = 0x00000001; +pub const ERROR_SUCCESS: DWORD = 0; +pub const ERROR_INVALID_FUNCTION: DWORD = 1; +pub const ERROR_FILE_NOT_FOUND: DWORD = 2; +pub const ERROR_PATH_NOT_FOUND: DWORD = 3; +pub const ERROR_ACCESS_DENIED: DWORD = 5; +pub const ERROR_INVALID_HANDLE: DWORD = 6; +pub const ERROR_NO_MORE_FILES: DWORD = 18; +pub const ERROR_BROKEN_PIPE: DWORD = 109; +pub const ERROR_DISK_FULL: DWORD = 112; +pub const ERROR_CALL_NOT_IMPLEMENTED: DWORD = 120; +pub const ERROR_INSUFFICIENT_BUFFER: DWORD = 122; +pub const ERROR_INVALID_NAME: DWORD = 123; +pub const ERROR_ALREADY_EXISTS: DWORD = 183; +pub const ERROR_PIPE_BUSY: DWORD = 231; +pub const ERROR_NO_DATA: DWORD = 232; +pub const ERROR_INVALID_ADDRESS: DWORD = 487; +pub const ERROR_PIPE_CONNECTED: DWORD = 535; +pub const ERROR_ILLEGAL_CHARACTER: DWORD = 582; +pub const ERROR_ENVVAR_NOT_FOUND: DWORD = 203; +pub const ERROR_NOTHING_TO_TERMINATE: DWORD = 758; +pub const ERROR_OPERATION_ABORTED: DWORD = 995; +pub const ERROR_IO_PENDING: DWORD = 997; +pub const ERROR_FILE_INVALID: DWORD = 1006; +pub const ERROR_NOT_FOUND: DWORD = 1168; +pub const ERROR_TIMEOUT: DWORD = 0x5B4; + +pub const INVALID_HANDLE_VALUE: HANDLE = !0 as HANDLE; + +pub const FORMAT_MESSAGE_FROM_SYSTEM: DWORD = 0x00001000; +pub const FORMAT_MESSAGE_IGNORE_INSERTS: DWORD = 0x00000200; + +pub const TLS_OUT_OF_INDEXES: DWORD = 0xFFFFFFFF; + +pub const DLL_THREAD_DETACH: DWORD = 3; +pub const DLL_PROCESS_DETACH: DWORD = 0; + +pub const INFINITE: DWORD = !0; + +pub const DUPLICATE_SAME_ACCESS: DWORD = 0x00000002; + +pub const CONDITION_VARIABLE_INIT: CONDITION_VARIABLE = CONDITION_VARIABLE { + ptr: ptr::null_mut(), +}; +pub const SRWLOCK_INIT: SRWLOCK = SRWLOCK { ptr: ptr::null_mut() }; -pub const PROGRESS_CONTINUE: libc::DWORD = 0; -pub const PROGRESS_CANCEL: libc::DWORD = 1; -pub const PROGRESS_STOP: libc::DWORD = 2; -pub const PROGRESS_QUIET: libc::DWORD = 3; +pub const STILL_ACTIVE: DWORD = 259; -pub const TOKEN_ADJUST_PRIVILEGES: libc::DWORD = 0x0020; -pub const SE_PRIVILEGE_ENABLED: libc::DWORD = 2; +pub const DETACHED_PROCESS: DWORD = 0x00000008; +pub const CREATE_NEW_PROCESS_GROUP: DWORD = 0x00000200; +pub const CREATE_UNICODE_ENVIRONMENT: DWORD = 0x00000400; +pub const STARTF_USESTDHANDLES: DWORD = 0x00000100; + +pub const AF_INET: c_int = 2; +pub const AF_INET6: c_int = 23; +pub const SD_BOTH: c_int = 2; +pub const SD_RECEIVE: c_int = 0; +pub const SD_SEND: c_int = 1; +pub const SOCK_DGRAM: c_int = 2; +pub const SOCK_STREAM: c_int = 1; +pub const SOL_SOCKET: c_int = 0xffff; +pub const SO_RCVTIMEO: c_int = 0x1006; +pub const SO_SNDTIMEO: c_int = 0x1005; +pub const SO_REUSEADDR: c_int = 0x0004; + +pub const VOLUME_NAME_DOS: DWORD = 0x0; +pub const MOVEFILE_REPLACE_EXISTING: DWORD = 1; + +pub const FILE_BEGIN: DWORD = 0; +pub const FILE_CURRENT: DWORD = 1; +pub const FILE_END: DWORD = 2; + +pub const WAIT_ABANDONED: DWORD = 0x00000080; +pub const WAIT_OBJECT_0: DWORD = 0x00000000; +pub const WAIT_TIMEOUT: DWORD = 0x00000102; +pub const WAIT_FAILED: DWORD = !0; + +pub const MAX_SYM_NAME: usize = 2000; +pub const IMAGE_FILE_MACHINE_I386: DWORD = 0x014c; +pub const IMAGE_FILE_MACHINE_IA64: DWORD = 0x0200; +pub const IMAGE_FILE_MACHINE_AMD64: DWORD = 0x8664; + +pub const PROV_RSA_FULL: DWORD = 1; +pub const CRYPT_SILENT: DWORD = 64; +pub const CRYPT_VERIFYCONTEXT: DWORD = 0xF0000000; pub const EXCEPTION_CONTINUE_SEARCH: LONG = 0; -pub const EXCEPTION_MAXIMUM_PARAMETERS: usize = 15; pub const EXCEPTION_STACK_OVERFLOW: DWORD = 0xc00000fd; - -pub const ERROR_PATH_NOT_FOUND: libc::c_int = 3; +pub const EXCEPTION_MAXIMUM_PARAMETERS: usize = 15; +pub const EXCEPTION_NONCONTINUABLE: DWORD = 0x1; // Noncontinuable exception +pub const EXCEPTION_UNWINDING: DWORD = 0x2; // Unwind is in progress +pub const EXCEPTION_EXIT_UNWIND: DWORD = 0x4; // Exit unwind is in progress +pub const EXCEPTION_STACK_INVALID: DWORD = 0x8; // Stack out of limits or unaligned +pub const EXCEPTION_NESTED_CALL: DWORD = 0x10; // Nested exception handler call +pub const EXCEPTION_TARGET_UNWIND: DWORD = 0x20; // Target unwind in progress +pub const EXCEPTION_COLLIDED_UNWIND: DWORD = 0x40; // Collided exception handler call +pub const EXCEPTION_UNWIND: DWORD = EXCEPTION_UNWINDING | + EXCEPTION_EXIT_UNWIND | + EXCEPTION_TARGET_UNWIND | + EXCEPTION_COLLIDED_UNWIND; #[repr(C)] #[cfg(target_arch = "x86")] pub struct WSADATA { - pub wVersion: libc::WORD, - pub wHighVersion: libc::WORD, + pub wVersion: WORD, + pub wHighVersion: WORD, pub szDescription: [u8; WSADESCRIPTION_LEN + 1], pub szSystemStatus: [u8; WSASYS_STATUS_LEN + 1], pub iMaxSockets: u16, @@ -99,8 +349,8 @@ pub struct WSADATA { #[repr(C)] #[cfg(target_arch = "x86_64")] pub struct WSADATA { - pub wVersion: libc::WORD, - pub wHighVersion: libc::WORD, + pub wVersion: WORD, + pub wHighVersion: WORD, pub iMaxSockets: u16, pub iMaxUdpDg: u16, pub lpVendorInfo: *mut u8, @@ -108,56 +358,50 @@ pub struct WSADATA { pub szSystemStatus: [u8; WSASYS_STATUS_LEN + 1], } -pub type LPWSADATA = *mut WSADATA; - #[repr(C)] pub struct WSANETWORKEVENTS { - pub lNetworkEvents: libc::c_long, - pub iErrorCode: [libc::c_int; FD_MAX_EVENTS], + pub lNetworkEvents: c_long, + pub iErrorCode: [c_int; FD_MAX_EVENTS], } -pub type LPWSANETWORKEVENTS = *mut WSANETWORKEVENTS; - -pub type WSAEVENT = libc::HANDLE; +pub type WSAEVENT = HANDLE; #[repr(C)] pub struct WSAPROTOCOL_INFO { - pub dwServiceFlags1: libc::DWORD, - pub dwServiceFlags2: libc::DWORD, - pub dwServiceFlags3: libc::DWORD, - pub dwServiceFlags4: libc::DWORD, - pub dwProviderFlags: libc::DWORD, + pub dwServiceFlags1: DWORD, + pub dwServiceFlags2: DWORD, + pub dwServiceFlags3: DWORD, + pub dwServiceFlags4: DWORD, + pub dwProviderFlags: DWORD, pub ProviderId: GUID, - pub dwCatalogEntryId: libc::DWORD, + pub dwCatalogEntryId: DWORD, pub ProtocolChain: WSAPROTOCOLCHAIN, - pub iVersion: libc::c_int, - pub iAddressFamily: libc::c_int, - pub iMaxSockAddr: libc::c_int, - pub iMinSockAddr: libc::c_int, - pub iSocketType: libc::c_int, - pub iProtocol: libc::c_int, - pub iProtocolMaxOffset: libc::c_int, - pub iNetworkByteOrder: libc::c_int, - pub iSecurityScheme: libc::c_int, - pub dwMessageSize: libc::DWORD, - pub dwProviderReserved: libc::DWORD, + pub iVersion: c_int, + pub iAddressFamily: c_int, + pub iMaxSockAddr: c_int, + pub iMinSockAddr: c_int, + pub iSocketType: c_int, + pub iProtocol: c_int, + pub iProtocolMaxOffset: c_int, + pub iNetworkByteOrder: c_int, + pub iSecurityScheme: c_int, + pub dwMessageSize: DWORD, + pub dwProviderReserved: DWORD, pub szProtocol: [u16; (WSAPROTOCOL_LEN as usize) + 1], } -pub type LPWSAPROTOCOL_INFO = *mut WSAPROTOCOL_INFO; - #[repr(C)] pub struct fd_set { - fd_count: libc::c_uint, - fd_array: [libc::SOCKET; FD_SETSIZE], + fd_count: c_uint, + fd_array: [SOCKET; FD_SETSIZE], } -pub fn fd_set(set: &mut fd_set, s: libc::SOCKET) { +pub fn fd_set(set: &mut fd_set, s: SOCKET) { set.fd_array[set.fd_count as usize] = s; set.fd_count += 1; } -pub type SHORT = libc::c_short; +pub type SHORT = c_short; #[repr(C)] pub struct COORD { @@ -177,39 +421,37 @@ pub struct SMALL_RECT { pub struct CONSOLE_SCREEN_BUFFER_INFO { pub dwSize: COORD, pub dwCursorPosition: COORD, - pub wAttributes: libc::WORD, + pub wAttributes: WORD, pub srWindow: SMALL_RECT, pub dwMaximumWindowSize: COORD, } pub type PCONSOLE_SCREEN_BUFFER_INFO = *mut CONSOLE_SCREEN_BUFFER_INFO; #[repr(C)] -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct WIN32_FILE_ATTRIBUTE_DATA { - pub dwFileAttributes: libc::DWORD, - pub ftCreationTime: libc::FILETIME, - pub ftLastAccessTime: libc::FILETIME, - pub ftLastWriteTime: libc::FILETIME, - pub nFileSizeHigh: libc::DWORD, - pub nFileSizeLow: libc::DWORD, + pub dwFileAttributes: DWORD, + pub ftCreationTime: FILETIME, + pub ftLastAccessTime: FILETIME, + pub ftLastWriteTime: FILETIME, + pub nFileSizeHigh: DWORD, + pub nFileSizeLow: DWORD, } #[repr(C)] pub struct BY_HANDLE_FILE_INFORMATION { - pub dwFileAttributes: libc::DWORD, - pub ftCreationTime: libc::FILETIME, - pub ftLastAccessTime: libc::FILETIME, - pub ftLastWriteTime: libc::FILETIME, - pub dwVolumeSerialNumber: libc::DWORD, - pub nFileSizeHigh: libc::DWORD, - pub nFileSizeLow: libc::DWORD, - pub nNumberOfLinks: libc::DWORD, - pub nFileIndexHigh: libc::DWORD, - pub nFileIndexLow: libc::DWORD, + pub dwFileAttributes: DWORD, + pub ftCreationTime: FILETIME, + pub ftLastAccessTime: FILETIME, + pub ftLastWriteTime: FILETIME, + pub dwVolumeSerialNumber: DWORD, + pub nFileSizeHigh: DWORD, + pub nFileSizeLow: DWORD, + pub nNumberOfLinks: DWORD, + pub nFileIndexHigh: DWORD, + pub nFileIndexLow: DWORD, } -pub type LPBY_HANDLE_FILE_INFORMATION = *mut BY_HANDLE_FILE_INFORMATION; - #[repr(C)] pub enum GET_FILEEX_INFO_LEVELS { GetFileExInfoStandard, @@ -244,38 +486,32 @@ pub enum FILE_INFO_BY_HANDLE_CLASS { #[repr(C)] pub struct FILE_END_OF_FILE_INFO { - pub EndOfFile: libc::LARGE_INTEGER, + pub EndOfFile: LARGE_INTEGER, } #[repr(C)] pub struct REPARSE_DATA_BUFFER { - pub ReparseTag: libc::c_uint, - pub ReparseDataLength: libc::c_ushort, - pub Reserved: libc::c_ushort, + pub ReparseTag: c_uint, + pub ReparseDataLength: c_ushort, + pub Reserved: c_ushort, pub rest: (), } #[repr(C)] pub struct SYMBOLIC_LINK_REPARSE_BUFFER { - pub SubstituteNameOffset: libc::c_ushort, - pub SubstituteNameLength: libc::c_ushort, - pub PrintNameOffset: libc::c_ushort, - pub PrintNameLength: libc::c_ushort, - pub Flags: libc::c_ulong, - pub PathBuffer: libc::WCHAR, + pub SubstituteNameOffset: c_ushort, + pub SubstituteNameLength: c_ushort, + pub PrintNameOffset: c_ushort, + pub PrintNameLength: c_ushort, + pub Flags: c_ulong, + pub PathBuffer: WCHAR, } -pub type PCONDITION_VARIABLE = *mut CONDITION_VARIABLE; -pub type PSRWLOCK = *mut SRWLOCK; -pub type ULONG = c_ulong; -pub type ULONG_PTR = c_ulong; -pub type LPBOOL = *mut BOOL; - pub type LPPROGRESS_ROUTINE = ::option::Option LONG; +#[repr(C)] +pub struct GUID { + pub Data1: DWORD, + pub Data2: WORD, + pub Data3: WORD, + pub Data4: [BYTE; 8], +} + +#[repr(C)] +pub struct WSAPROTOCOLCHAIN { + pub ChainLen: c_int, + pub ChainEntries: [DWORD; MAX_PROTOCOL_CHAIN as usize], +} + +#[repr(C)] +pub struct SECURITY_ATTRIBUTES { + pub nLength: DWORD, + pub lpSecurityDescriptor: LPVOID, + pub bInheritHandle: BOOL, +} + +#[repr(C)] +pub struct PROCESS_INFORMATION { + pub hProcess: HANDLE, + pub hThread: HANDLE, + pub dwProcessId: DWORD, + pub dwThreadId: DWORD, +} + +#[repr(C)] +pub struct STARTUPINFO { + pub cb: DWORD, + pub lpReserved: LPWSTR, + pub lpDesktop: LPWSTR, + pub lpTitle: LPWSTR, + pub dwX: DWORD, + pub dwY: DWORD, + pub dwXSize: DWORD, + pub dwYSize: DWORD, + pub dwXCountChars: DWORD, + pub dwYCountCharts: DWORD, + pub dwFillAttribute: DWORD, + pub dwFlags: DWORD, + pub wShowWindow: WORD, + pub cbReserved2: WORD, + pub lpReserved2: LPBYTE, + pub hStdInput: HANDLE, + pub hStdOutput: HANDLE, + pub hStdError: HANDLE, +} + +#[repr(C)] +pub struct SOCKADDR { + pub sa_family: ADDRESS_FAMILY, + pub sa_data: [CHAR; 14], +} + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct FILETIME { + pub dwLowDateTime: DWORD, + pub dwHighDateTime: DWORD, +} + +#[repr(C)] +pub struct OVERLAPPED { + pub Internal: *mut c_ulong, + pub InternalHigh: *mut c_ulong, + pub Offset: DWORD, + pub OffsetHigh: DWORD, + pub hEvent: HANDLE, +} + +#[repr(C)] +pub struct SYMBOL_INFO { + pub SizeOfStruct: c_ulong, + pub TypeIndex: c_ulong, + pub Reserved: [u64; 2], + pub Index: c_ulong, + pub Size: c_ulong, + pub ModBase: u64, + pub Flags: c_ulong, + pub Value: u64, + pub Address: u64, + pub Register: c_ulong, + pub Scope: c_ulong, + pub Tag: c_ulong, + pub NameLen: c_ulong, + pub MaxNameLen: c_ulong, + // note that windows has this as 1, but it basically just means that + // the name is inline at the end of the struct. For us, we just bump + // the struct size up to MAX_SYM_NAME. + pub Name: [c_char; MAX_SYM_NAME], +} + +#[repr(C)] +pub struct IMAGEHLP_LINE64 { + pub SizeOfStruct: u32, + pub Key: *const c_void, + pub LineNumber: u32, + pub Filename: *const c_char, + pub Address: u64, +} + +#[repr(C)] +pub enum ADDRESS_MODE { + AddrMode1616, + AddrMode1632, + AddrModeReal, + AddrModeFlat, +} + +#[repr(C)] +pub struct ADDRESS64 { + pub Offset: u64, + pub Segment: u16, + pub Mode: ADDRESS_MODE, +} + +#[repr(C)] +pub struct STACKFRAME64 { + pub AddrPC: ADDRESS64, + pub AddrReturn: ADDRESS64, + pub AddrFrame: ADDRESS64, + pub AddrStack: ADDRESS64, + pub AddrBStore: ADDRESS64, + pub FuncTableEntry: *mut c_void, + pub Params: [u64; 4], + pub Far: BOOL, + pub Virtual: BOOL, + pub Reserved: [u64; 3], + pub KdHelp: KDHELP64, +} + +#[repr(C)] +pub struct KDHELP64 { + pub Thread: u64, + pub ThCallbackStack: DWORD, + pub ThCallbackBStore: DWORD, + pub NextCallback: DWORD, + pub FramePointer: DWORD, + pub KiCallUserMode: u64, + pub KeUserCallbackDispatcher: u64, + pub SystemRangeStart: u64, + pub KiUserExceptionDispatcher: u64, + pub StackBase: u64, + pub StackLimit: u64, + pub Reserved: [u64; 5], +} + +#[cfg(target_arch = "x86")] +#[repr(C)] +pub struct CONTEXT { + pub ContextFlags: DWORD, + pub Dr0: DWORD, + pub Dr1: DWORD, + pub Dr2: DWORD, + pub Dr3: DWORD, + pub Dr6: DWORD, + pub Dr7: DWORD, + pub FloatSave: FLOATING_SAVE_AREA, + pub SegGs: DWORD, + pub SegFs: DWORD, + pub SegEs: DWORD, + pub SegDs: DWORD, + pub Edi: DWORD, + pub Esi: DWORD, + pub Ebx: DWORD, + pub Edx: DWORD, + pub Ecx: DWORD, + pub Eax: DWORD, + pub Ebp: DWORD, + pub Eip: DWORD, + pub SegCs: DWORD, + pub EFlags: DWORD, + pub Esp: DWORD, + pub SegSs: DWORD, + pub ExtendedRegisters: [u8; 512], +} + +#[cfg(target_arch = "x86")] +#[repr(C)] +pub struct FLOATING_SAVE_AREA { + pub ControlWord: DWORD, + pub StatusWord: DWORD, + pub TagWord: DWORD, + pub ErrorOffset: DWORD, + pub ErrorSelector: DWORD, + pub DataOffset: DWORD, + pub DataSelector: DWORD, + pub RegisterArea: [u8; 80], + pub Cr0NpxState: DWORD, +} + +#[cfg(target_arch = "x86_64")] +#[repr(C)] +pub struct CONTEXT { + _align_hack: [simd::u64x2; 0], // FIXME align on 16-byte + pub P1Home: DWORDLONG, + pub P2Home: DWORDLONG, + pub P3Home: DWORDLONG, + pub P4Home: DWORDLONG, + pub P5Home: DWORDLONG, + pub P6Home: DWORDLONG, + + pub ContextFlags: DWORD, + pub MxCsr: DWORD, + + pub SegCs: WORD, + pub SegDs: WORD, + pub SegEs: WORD, + pub SegFs: WORD, + pub SegGs: WORD, + pub SegSs: WORD, + pub EFlags: DWORD, + + pub Dr0: DWORDLONG, + pub Dr1: DWORDLONG, + pub Dr2: DWORDLONG, + pub Dr3: DWORDLONG, + pub Dr6: DWORDLONG, + pub Dr7: DWORDLONG, + + pub Rax: DWORDLONG, + pub Rcx: DWORDLONG, + pub Rdx: DWORDLONG, + pub Rbx: DWORDLONG, + pub Rsp: DWORDLONG, + pub Rbp: DWORDLONG, + pub Rsi: DWORDLONG, + pub Rdi: DWORDLONG, + pub R8: DWORDLONG, + pub R9: DWORDLONG, + pub R10: DWORDLONG, + pub R11: DWORDLONG, + pub R12: DWORDLONG, + pub R13: DWORDLONG, + pub R14: DWORDLONG, + pub R15: DWORDLONG, + + pub Rip: DWORDLONG, + + pub FltSave: FLOATING_SAVE_AREA, + + pub VectorRegister: [M128A; 26], + pub VectorControl: DWORDLONG, + + pub DebugControl: DWORDLONG, + pub LastBranchToRip: DWORDLONG, + pub LastBranchFromRip: DWORDLONG, + pub LastExceptionToRip: DWORDLONG, + pub LastExceptionFromRip: DWORDLONG, +} + +#[cfg(target_arch = "x86_64")] +#[repr(C)] +pub struct M128A { + _align_hack: [simd::u64x2; 0], // FIXME align on 16-byte + pub Low: c_ulonglong, + pub High: c_longlong +} + +#[cfg(target_arch = "x86_64")] +#[repr(C)] +pub struct FLOATING_SAVE_AREA { + _align_hack: [simd::u64x2; 0], // FIXME align on 16-byte + _Dummy: [u8; 512] // FIXME: Fill this out +} + +#[repr(C)] +pub struct SOCKADDR_STORAGE_LH { + pub ss_family: ADDRESS_FAMILY, + pub __ss_pad1: [CHAR; 6], + pub __ss_align: i64, + pub __ss_pad2: [CHAR; 112], +} + +#[repr(C)] +pub struct ADDRINFOA { + pub ai_flags: c_int, + pub ai_family: c_int, + pub ai_socktype: c_int, + pub ai_protocol: c_int, + pub ai_addrlen: size_t, + pub ai_canonname: *mut c_char, + pub ai_addr: *mut SOCKADDR, + pub ai_next: *mut ADDRINFOA, +} + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct sockaddr_in { + pub sin_family: ADDRESS_FAMILY, + pub sin_port: USHORT, + pub sin_addr: in_addr, + pub sin_zero: [CHAR; 8], +} + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct sockaddr_in6 { + pub sin6_family: ADDRESS_FAMILY, + pub sin6_port: USHORT, + pub sin6_flowinfo: c_ulong, + pub sin6_addr: in6_addr, + pub sin6_scope_id: c_ulong, +} + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct in_addr { + pub s_addr: u32, +} + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct in6_addr { + pub s6_addr: [u8; 16], +} + +pub enum UNWIND_HISTORY_TABLE {} + +#[repr(C)] +pub struct RUNTIME_FUNCTION { + pub BeginAddress: DWORD, + pub EndAddress: DWORD, + pub UnwindData: DWORD, +} + +#[repr(C)] +pub struct DISPATCHER_CONTEXT { + pub ControlPc: LPVOID, + pub ImageBase: LPVOID, + pub FunctionEntry: *const RUNTIME_FUNCTION, + pub EstablisherFrame: LPVOID, + pub TargetIp: LPVOID, + pub ContextRecord: *const CONTEXT, + pub LanguageHandler: LPVOID, + pub HandlerData: *const u8, + pub HistoryTable: *const UNWIND_HISTORY_TABLE, +} + +#[repr(C)] +#[derive(Copy, Clone)] +pub enum EXCEPTION_DISPOSITION { + ExceptionContinueExecution, + ExceptionContinueSearch, + ExceptionNestedException, + ExceptionCollidedUnwind +} + #[link(name = "ws2_32")] #[link(name = "userenv")] #[link(name = "shell32")] +#[link(name = "advapi32")] extern "system" { - pub fn WSAStartup(wVersionRequested: libc::WORD, - lpWSAData: LPWSADATA) -> libc::c_int; - pub fn WSACleanup() -> libc::c_int; - pub fn WSAGetLastError() -> libc::c_int; - pub fn WSACloseEvent(hEvent: WSAEVENT) -> libc::BOOL; - pub fn WSACreateEvent() -> WSAEVENT; - pub fn WSAEventSelect(s: libc::SOCKET, - hEventObject: WSAEVENT, - lNetworkEvents: libc::c_long) -> libc::c_int; - pub fn WSASetEvent(hEvent: WSAEVENT) -> libc::BOOL; - pub fn WSAWaitForMultipleEvents(cEvents: libc::DWORD, - lphEvents: *const WSAEVENT, - fWaitAll: libc::BOOL, - dwTimeout: libc::DWORD, - fAltertable: libc::BOOL) -> libc::DWORD; - pub fn WSAEnumNetworkEvents(s: libc::SOCKET, - hEventObject: WSAEVENT, - lpNetworkEvents: LPWSANETWORKEVENTS) - -> libc::c_int; - pub fn WSADuplicateSocketW(s: libc::SOCKET, - dwProcessId: libc::DWORD, + pub fn WSAStartup(wVersionRequested: WORD, + lpWSAData: LPWSADATA) -> c_int; + pub fn WSACleanup() -> c_int; + pub fn WSAGetLastError() -> c_int; + pub fn WSADuplicateSocketW(s: SOCKET, + dwProcessId: DWORD, lpProtocolInfo: LPWSAPROTOCOL_INFO) - -> libc::c_int; - pub fn GetCurrentProcessId() -> libc::DWORD; - pub fn WSASocketW(af: libc::c_int, - kind: libc::c_int, - protocol: libc::c_int, + -> c_int; + pub fn GetCurrentProcessId() -> DWORD; + pub fn WSASocketW(af: c_int, + kind: c_int, + protocol: c_int, lpProtocolInfo: LPWSAPROTOCOL_INFO, g: GROUP, - dwFlags: libc::DWORD) -> libc::SOCKET; - - pub fn ioctlsocket(s: libc::SOCKET, cmd: libc::c_long, - argp: *mut libc::c_ulong) -> libc::c_int; - pub fn select(nfds: libc::c_int, - readfds: *mut fd_set, - writefds: *mut fd_set, - exceptfds: *mut fd_set, - timeout: *mut libc::timeval) -> libc::c_int; - pub fn getsockopt(sockfd: libc::SOCKET, - level: libc::c_int, - optname: libc::c_int, - optval: *mut libc::c_char, - optlen: *mut libc::c_int) -> libc::c_int; - - pub fn SetEvent(hEvent: libc::HANDLE) -> libc::BOOL; - pub fn WaitForMultipleObjects(nCount: libc::DWORD, - lpHandles: *const libc::HANDLE, - bWaitAll: libc::BOOL, - dwMilliseconds: libc::DWORD) -> libc::DWORD; - - pub fn CancelIo(hFile: libc::HANDLE) -> libc::BOOL; - pub fn CancelIoEx(hFile: libc::HANDLE, - lpOverlapped: libc::LPOVERLAPPED) -> libc::BOOL; - + dwFlags: DWORD) -> SOCKET; pub fn InitializeCriticalSection(CriticalSection: *mut CRITICAL_SECTION); pub fn EnterCriticalSection(CriticalSection: *mut CRITICAL_SECTION); pub fn TryEnterCriticalSection(CriticalSection: *mut CRITICAL_SECTION) -> BOOLEAN; @@ -419,104 +963,274 @@ extern "system" { pub fn DeleteCriticalSection(CriticalSection: *mut CRITICAL_SECTION); // FIXME - pInputControl should be PCONSOLE_READCONSOLE_CONTROL - pub fn ReadConsoleW(hConsoleInput: libc::HANDLE, - lpBuffer: libc::LPVOID, - nNumberOfCharsToRead: libc::DWORD, - lpNumberOfCharsRead: libc::LPDWORD, - pInputControl: libc::LPVOID) -> libc::BOOL; - - pub fn WriteConsoleW(hConsoleOutput: libc::HANDLE, - lpBuffer: libc::types::os::arch::extra::LPCVOID, - nNumberOfCharsToWrite: libc::DWORD, - lpNumberOfCharsWritten: libc::LPDWORD, - lpReserved: libc::LPVOID) -> libc::BOOL; - - pub fn GetConsoleMode(hConsoleHandle: libc::HANDLE, - lpMode: libc::LPDWORD) -> libc::BOOL; - - pub fn SetConsoleMode(hConsoleHandle: libc::HANDLE, - lpMode: libc::DWORD) -> libc::BOOL; - pub fn GetConsoleScreenBufferInfo( - hConsoleOutput: libc::HANDLE, - lpConsoleScreenBufferInfo: PCONSOLE_SCREEN_BUFFER_INFO, - ) -> libc::BOOL; - - pub fn GetFileAttributesExW(lpFileName: libc::LPCWSTR, + pub fn ReadConsoleW(hConsoleInput: HANDLE, + lpBuffer: LPVOID, + nNumberOfCharsToRead: DWORD, + lpNumberOfCharsRead: LPDWORD, + pInputControl: LPVOID) -> BOOL; + + pub fn WriteConsoleW(hConsoleOutput: HANDLE, + lpBuffer: LPCVOID, + nNumberOfCharsToWrite: DWORD, + lpNumberOfCharsWritten: LPDWORD, + lpReserved: LPVOID) -> BOOL; + + pub fn GetConsoleMode(hConsoleHandle: HANDLE, + lpMode: LPDWORD) -> BOOL; + pub fn GetFileAttributesExW(lpFileName: LPCWSTR, fInfoLevelId: GET_FILEEX_INFO_LEVELS, - lpFileInformation: libc::LPVOID) -> libc::BOOL; - pub fn RemoveDirectoryW(lpPathName: libc::LPCWSTR) -> libc::BOOL; - pub fn SetFileAttributesW(lpFileName: libc::LPCWSTR, - dwFileAttributes: libc::DWORD) -> libc::BOOL; - pub fn GetFileAttributesW(lpFileName: libc::LPCWSTR) -> libc::DWORD; - pub fn GetFileInformationByHandle(hFile: libc::HANDLE, + lpFileInformation: LPVOID) -> BOOL; + pub fn RemoveDirectoryW(lpPathName: LPCWSTR) -> BOOL; + pub fn SetFileAttributesW(lpFileName: LPCWSTR, + dwFileAttributes: DWORD) -> BOOL; + pub fn GetFileInformationByHandle(hFile: HANDLE, lpFileInformation: LPBY_HANDLE_FILE_INFORMATION) - -> libc::BOOL; - - pub fn SetLastError(dwErrCode: libc::DWORD); - pub fn GetCommandLineW() -> *mut libc::LPCWSTR; - pub fn LocalFree(ptr: *mut libc::c_void); - pub fn CommandLineToArgvW(lpCmdLine: *mut libc::LPCWSTR, - pNumArgs: *mut libc::c_int) -> *mut *mut u16; - pub fn SetFileTime(hFile: libc::HANDLE, - lpCreationTime: *const libc::FILETIME, - lpLastAccessTime: *const libc::FILETIME, - lpLastWriteTime: *const libc::FILETIME) -> libc::BOOL; - pub fn GetTempPathW(nBufferLength: libc::DWORD, - lpBuffer: libc::LPCWSTR) -> libc::DWORD; - pub fn OpenProcessToken(ProcessHandle: libc::HANDLE, - DesiredAccess: libc::DWORD, - TokenHandle: *mut libc::HANDLE) -> libc::BOOL; - pub fn GetCurrentProcess() -> libc::HANDLE; - pub fn GetStdHandle(which: libc::DWORD) -> libc::HANDLE; - pub fn ExitProcess(uExitCode: libc::c_uint) -> !; - pub fn DeviceIoControl(hDevice: libc::HANDLE, - dwIoControlCode: libc::DWORD, - lpInBuffer: libc::LPVOID, - nInBufferSize: libc::DWORD, - lpOutBuffer: libc::LPVOID, - nOutBufferSize: libc::DWORD, - lpBytesReturned: libc::LPDWORD, - lpOverlapped: libc::LPOVERLAPPED) -> libc::BOOL; - pub fn CreatePipe(hReadPipe: libc::LPHANDLE, - hWritePipe: libc::LPHANDLE, - lpPipeAttributes: libc::LPSECURITY_ATTRIBUTES, - nSize: libc::DWORD) -> libc::BOOL; - pub fn CreateThread(lpThreadAttributes: libc::LPSECURITY_ATTRIBUTES, - dwStackSize: libc::SIZE_T, - lpStartAddress: extern "system" fn(*mut libc::c_void) - -> libc::DWORD, - lpParameter: libc::LPVOID, - dwCreationFlags: libc::DWORD, - lpThreadId: libc::LPDWORD) -> libc::HANDLE; - pub fn WaitForSingleObject(hHandle: libc::HANDLE, - dwMilliseconds: libc::DWORD) -> libc::DWORD; - pub fn SwitchToThread() -> libc::BOOL; - pub fn Sleep(dwMilliseconds: libc::DWORD); - pub fn GetProcessId(handle: libc::HANDLE) -> libc::DWORD; - pub fn GetUserProfileDirectoryW(hToken: libc::HANDLE, - lpProfileDir: libc::LPCWSTR, - lpcchSize: *mut libc::DWORD) -> libc::BOOL; - pub fn SetHandleInformation(hObject: libc::HANDLE, - dwMask: libc::DWORD, - dwFlags: libc::DWORD) -> libc::BOOL; - pub fn CopyFileExW(lpExistingFileName: libc::LPCWSTR, - lpNewFileName: libc::LPCWSTR, + -> BOOL; + + pub fn SetLastError(dwErrCode: DWORD); + pub fn GetCommandLineW() -> *mut LPCWSTR; + pub fn LocalFree(ptr: *mut c_void); + pub fn CommandLineToArgvW(lpCmdLine: *mut LPCWSTR, + pNumArgs: *mut c_int) -> *mut *mut u16; + pub fn GetTempPathW(nBufferLength: DWORD, + lpBuffer: LPCWSTR) -> DWORD; + pub fn OpenProcessToken(ProcessHandle: HANDLE, + DesiredAccess: DWORD, + TokenHandle: *mut HANDLE) -> BOOL; + pub fn GetCurrentProcess() -> HANDLE; + pub fn GetCurrentThread() -> HANDLE; + pub fn GetStdHandle(which: DWORD) -> HANDLE; + pub fn ExitProcess(uExitCode: c_uint) -> !; + pub fn DeviceIoControl(hDevice: HANDLE, + dwIoControlCode: DWORD, + lpInBuffer: LPVOID, + nInBufferSize: DWORD, + lpOutBuffer: LPVOID, + nOutBufferSize: DWORD, + lpBytesReturned: LPDWORD, + lpOverlapped: LPOVERLAPPED) -> BOOL; + pub fn CreatePipe(hReadPipe: LPHANDLE, + hWritePipe: LPHANDLE, + lpPipeAttributes: LPSECURITY_ATTRIBUTES, + nSize: DWORD) -> BOOL; + pub fn CreateThread(lpThreadAttributes: LPSECURITY_ATTRIBUTES, + dwStackSize: SIZE_T, + lpStartAddress: extern "system" fn(*mut c_void) + -> DWORD, + lpParameter: LPVOID, + dwCreationFlags: DWORD, + lpThreadId: LPDWORD) -> HANDLE; + pub fn WaitForSingleObject(hHandle: HANDLE, + dwMilliseconds: DWORD) -> DWORD; + pub fn SwitchToThread() -> BOOL; + pub fn Sleep(dwMilliseconds: DWORD); + pub fn GetProcessId(handle: HANDLE) -> DWORD; + pub fn GetUserProfileDirectoryW(hToken: HANDLE, + lpProfileDir: LPCWSTR, + lpcchSize: *mut DWORD) -> BOOL; + pub fn SetHandleInformation(hObject: HANDLE, + dwMask: DWORD, + dwFlags: DWORD) -> BOOL; + pub fn CopyFileExW(lpExistingFileName: LPCWSTR, + lpNewFileName: LPCWSTR, lpProgressRoutine: LPPROGRESS_ROUTINE, - lpData: libc::LPVOID, + lpData: LPVOID, pbCancel: LPBOOL, - dwCopyFlags: libc::DWORD) -> libc::BOOL; - pub fn LookupPrivilegeValueW(lpSystemName: libc::LPCWSTR, - lpName: libc::LPCWSTR, - lpLuid: PLUID) -> libc::BOOL; - pub fn AdjustTokenPrivileges(TokenHandle: libc::HANDLE, - DisableAllPrivileges: libc::BOOL, + dwCopyFlags: DWORD) -> BOOL; + pub fn LookupPrivilegeValueW(lpSystemName: LPCWSTR, + lpName: LPCWSTR, + lpLuid: PLUID) -> BOOL; + pub fn AdjustTokenPrivileges(TokenHandle: HANDLE, + DisableAllPrivileges: BOOL, NewState: PTOKEN_PRIVILEGES, - BufferLength: libc::DWORD, + BufferLength: DWORD, PreviousState: PTOKEN_PRIVILEGES, - ReturnLength: *mut libc::DWORD) -> libc::BOOL; + ReturnLength: *mut DWORD) -> BOOL; pub fn AddVectoredExceptionHandler(FirstHandler: ULONG, VectoredHandler: PVECTORED_EXCEPTION_HANDLER) -> LPVOID; + pub fn FormatMessageW(flags: DWORD, + lpSrc: LPVOID, + msgId: DWORD, + langId: DWORD, + buf: LPWSTR, + nsize: DWORD, + args: *const c_void) + -> DWORD; + pub fn TlsAlloc() -> DWORD; + pub fn TlsFree(dwTlsIndex: DWORD) -> BOOL; + pub fn TlsGetValue(dwTlsIndex: DWORD) -> LPVOID; + pub fn TlsSetValue(dwTlsIndex: DWORD, lpTlsvalue: LPVOID) -> BOOL; + pub fn GetLastError() -> DWORD; + pub fn QueryPerformanceFrequency(lpFrequency: *mut LARGE_INTEGER) -> BOOL; + pub fn QueryPerformanceCounter(lpPerformanceCount: *mut LARGE_INTEGER) + -> BOOL; + pub fn GetExitCodeProcess(hProcess: HANDLE, lpExitCode: LPDWORD) -> BOOL; + pub fn TerminateProcess(hProcess: HANDLE, uExitCode: UINT) -> BOOL; + pub fn CreateProcessW(lpApplicationName: LPCWSTR, + lpCommandLine: LPWSTR, + lpProcessAttributes: LPSECURITY_ATTRIBUTES, + lpThreadAttributes: LPSECURITY_ATTRIBUTES, + bInheritHandles: BOOL, + dwCreationFlags: DWORD, + lpEnvironment: LPVOID, + lpCurrentDirectory: LPCWSTR, + lpStartupInfo: LPSTARTUPINFO, + lpProcessInformation: LPPROCESS_INFORMATION) + -> BOOL; + pub fn GetEnvironmentVariableW(n: LPCWSTR, v: LPWSTR, nsize: DWORD) -> DWORD; + pub fn SetEnvironmentVariableW(n: LPCWSTR, v: LPCWSTR) -> BOOL; + pub fn GetEnvironmentStringsW() -> LPWCH; + pub fn FreeEnvironmentStringsW(env_ptr: LPWCH) -> BOOL; + pub fn GetModuleFileNameW(hModule: HMODULE, + lpFilename: LPWSTR, + nSize: DWORD) + -> DWORD; + pub fn CreateDirectoryW(lpPathName: LPCWSTR, + lpSecurityAttributes: LPSECURITY_ATTRIBUTES) + -> BOOL; + pub fn DeleteFileW(lpPathName: LPCWSTR) -> BOOL; + pub fn GetCurrentDirectoryW(nBufferLength: DWORD, lpBuffer: LPWSTR) -> DWORD; + pub fn SetCurrentDirectoryW(lpPathName: LPCWSTR) -> BOOL; + + pub fn closesocket(socket: SOCKET) -> c_int; + pub fn recv(socket: SOCKET, buf: *mut c_void, len: c_int, + flags: c_int) -> c_int; + pub fn send(socket: SOCKET, buf: *const c_void, len: c_int, + flags: c_int) -> c_int; + pub fn recvfrom(socket: SOCKET, + buf: *mut c_void, + len: c_int, + flags: c_int, + addr: *mut SOCKADDR, + addrlen: *mut c_int) + -> c_int; + pub fn sendto(socket: SOCKET, + buf: *const c_void, + len: c_int, + flags: c_int, + addr: *const SOCKADDR, + addrlen: c_int) + -> c_int; + pub fn shutdown(socket: SOCKET, how: c_int) -> c_int; + pub fn accept(socket: SOCKET, + address: *mut SOCKADDR, + address_len: *mut c_int) + -> SOCKET; + pub fn DuplicateHandle(hSourceProcessHandle: HANDLE, + hSourceHandle: HANDLE, + hTargetProcessHandle: HANDLE, + lpTargetHandle: LPHANDLE, + dwDesiredAccess: DWORD, + bInheritHandle: BOOL, + dwOptions: DWORD) + -> BOOL; + pub fn ReadFile(hFile: HANDLE, + lpBuffer: LPVOID, + nNumberOfBytesToRead: DWORD, + lpNumberOfBytesRead: LPDWORD, + lpOverlapped: LPOVERLAPPED) + -> BOOL; + pub fn WriteFile(hFile: HANDLE, + lpBuffer: LPVOID, + nNumberOfBytesToWrite: DWORD, + lpNumberOfBytesWritten: LPDWORD, + lpOverlapped: LPOVERLAPPED) + -> BOOL; + pub fn CloseHandle(hObject: HANDLE) -> BOOL; + pub fn CreateHardLinkW(lpSymlinkFileName: LPCWSTR, + lpTargetFileName: LPCWSTR, + lpSecurityAttributes: LPSECURITY_ATTRIBUTES) + -> BOOL; + pub fn MoveFileExW(lpExistingFileName: LPCWSTR, + lpNewFileName: LPCWSTR, + dwFlags: DWORD) + -> BOOL; + pub fn SetFilePointerEx(hFile: HANDLE, + liDistanceToMove: LARGE_INTEGER, + lpNewFilePointer: PLARGE_INTEGER, + dwMoveMethod: DWORD) + -> BOOL; + pub fn FlushFileBuffers(hFile: HANDLE) -> BOOL; + pub fn CreateFileW(lpFileName: LPCWSTR, + dwDesiredAccess: DWORD, + dwShareMode: DWORD, + lpSecurityAttributes: LPSECURITY_ATTRIBUTES, + dwCreationDisposition: DWORD, + dwFlagsAndAttributes: DWORD, + hTemplateFile: HANDLE) + -> HANDLE; + + pub fn FindFirstFileW(fileName: LPCWSTR, + findFileData: LPWIN32_FIND_DATAW) + -> HANDLE; + pub fn FindNextFileW(findFile: HANDLE, findFileData: LPWIN32_FIND_DATAW) + -> BOOL; + pub fn FindClose(findFile: HANDLE) -> BOOL; + pub fn RtlCaptureContext(ctx: *mut CONTEXT); + pub fn getsockopt(s: SOCKET, + level: c_int, + optname: c_int, + optval: *mut c_char, + optlen: *mut c_int) + -> c_int; + pub fn setsockopt(s: SOCKET, + level: c_int, + optname: c_int, + optval: *const c_void, + optlen: c_int) + -> c_int; + pub fn getsockname(socket: SOCKET, + address: *mut SOCKADDR, + address_len: *mut c_int) + -> c_int; + pub fn getpeername(socket: SOCKET, + address: *mut SOCKADDR, + address_len: *mut c_int) + -> c_int; + pub fn bind(socket: SOCKET, address: *const SOCKADDR, + address_len: socklen_t) -> c_int; + pub fn listen(socket: SOCKET, backlog: c_int) -> c_int; + pub fn connect(socket: SOCKET, address: *const SOCKADDR, len: c_int) + -> c_int; + pub fn getaddrinfo(node: *const c_char, service: *const c_char, + hints: *const ADDRINFOA, + res: *mut *mut ADDRINFOA) -> c_int; + pub fn freeaddrinfo(res: *mut ADDRINFOA); + pub fn getnameinfo(sa: *const SOCKADDR, salen: c_int, + host: *mut c_char, hostlen: DWORD, + serv: *mut c_char, servlen: DWORD, + flags: c_int) -> c_int; + + pub fn LoadLibraryW(name: LPCWSTR) -> HMODULE; + pub fn GetModuleHandleExW(dwFlags: DWORD, name: LPCWSTR, + handle: *mut HMODULE) -> BOOL; + pub fn GetProcAddress(handle: HMODULE, + name: LPCSTR) -> *mut c_void; + pub fn FreeLibrary(handle: HMODULE) -> BOOL; + pub fn SetErrorMode(uMode: c_uint) -> c_uint; + pub fn GetModuleHandleW(lpModuleName: LPCWSTR) -> HMODULE; + pub fn CryptAcquireContextA(phProv: *mut HCRYPTPROV, + pszContainer: LPCSTR, + pszProvider: LPCSTR, + dwProvType: DWORD, + dwFlags: DWORD) -> BOOL; + pub fn CryptGenRandom(hProv: HCRYPTPROV, + dwLen: DWORD, + pbBuffer: *mut BYTE) -> BOOL; + pub fn CryptReleaseContext(hProv: HCRYPTPROV, dwFlags: DWORD) -> BOOL; + + #[unwind] + pub fn RaiseException(dwExceptionCode: DWORD, + dwExceptionFlags: DWORD, + nNumberOfArguments: DWORD, + lpArguments: *const ULONG_PTR); + pub fn RtlUnwindEx(TargetFrame: LPVOID, + TargetIp: LPVOID, + ExceptionRecord: *const EXCEPTION_RECORD, + ReturnValue: LPVOID, + OriginalContext: *const CONTEXT, + HistoryTable: *const UNWIND_HISTORY_TABLE); } // Functions that aren't available on Windows XP, but we still use them and just diff --git a/src/libstd/sys/windows/compat.rs b/src/libstd/sys/windows/compat.rs index 3a03b91f24ed3..780a0d9427d59 100644 --- a/src/libstd/sys/windows/compat.rs +++ b/src/libstd/sys/windows/compat.rs @@ -24,21 +24,16 @@ use prelude::v1::*; use ffi::CString; -use libc::{LPVOID, LPCWSTR, HMODULE, LPCSTR}; use sync::atomic::{AtomicUsize, Ordering}; - -extern "system" { - fn GetModuleHandleW(lpModuleName: LPCWSTR) -> HMODULE; - fn GetProcAddress(hModule: HMODULE, lpProcName: LPCSTR) -> LPVOID; -} +use sys::c; pub fn lookup(module: &str, symbol: &str) -> Option { let mut module: Vec = module.utf16_units().collect(); module.push(0); let symbol = CString::new(symbol).unwrap(); unsafe { - let handle = GetModuleHandleW(module.as_ptr()); - match GetProcAddress(handle, symbol.as_ptr()) as usize { + let handle = c::GetModuleHandleW(module.as_ptr()); + match c::GetProcAddress(handle, symbol.as_ptr()) as usize { 0 => None, n => Some(n), } diff --git a/src/libstd/sys/windows/condvar.rs b/src/libstd/sys/windows/condvar.rs index ac76479d7dbd0..8075374d42bdd 100644 --- a/src/libstd/sys/windows/condvar.rs +++ b/src/libstd/sys/windows/condvar.rs @@ -9,7 +9,6 @@ // except according to those terms. use cell::UnsafeCell; -use libc::{self, DWORD}; use sys::c; use sys::mutex::{self, Mutex}; use sys::os; @@ -29,7 +28,7 @@ impl Condvar { pub unsafe fn wait(&self, mutex: &Mutex) { let r = c::SleepConditionVariableSRW(self.inner.get(), mutex::raw(mutex), - libc::INFINITE, + c::INFINITE, 0); debug_assert!(r != 0); } @@ -40,8 +39,7 @@ impl Condvar { super::dur2timeout(dur), 0); if r == 0 { - const ERROR_TIMEOUT: DWORD = 0x5B4; - debug_assert_eq!(os::errno() as usize, ERROR_TIMEOUT as usize); + debug_assert_eq!(os::errno() as usize, c::ERROR_TIMEOUT as usize); false } else { true diff --git a/src/libstd/sys/windows/ext/io.rs b/src/libstd/sys/windows/ext/io.rs index 9f10b0e856370..2ddb6c65fd357 100644 --- a/src/libstd/sys/windows/ext/io.rs +++ b/src/libstd/sys/windows/ext/io.rs @@ -15,6 +15,7 @@ use os::windows::raw; use net; use sys_common::{self, AsInner, FromInner, IntoInner}; use sys; +use sys::c; /// Raw HANDLEs. #[stable(feature = "rust1", since = "1.0.0")] @@ -73,7 +74,7 @@ impl AsRawHandle for fs::File { #[stable(feature = "from_raw_os", since = "1.1.0")] impl FromRawHandle for fs::File { unsafe fn from_raw_handle(handle: RawHandle) -> fs::File { - let handle = handle as ::libc::HANDLE; + let handle = handle as c::HANDLE; fs::File::from_inner(sys::fs::File::from_inner(handle)) } } diff --git a/src/libstd/sys/windows/fs.rs b/src/libstd/sys/windows/fs.rs index fb2456564eb8d..0b0e1a1ece70c 100644 --- a/src/libstd/sys/windows/fs.rs +++ b/src/libstd/sys/windows/fs.rs @@ -14,7 +14,6 @@ use os::windows::prelude::*; use ffi::OsString; use fmt; use io::{self, Error, SeekFrom}; -use libc::{self, HANDLE}; use mem; use path::{Path, PathBuf}; use ptr; @@ -30,7 +29,7 @@ pub struct File { handle: Handle } #[derive(Clone)] pub struct FileAttr { data: c::WIN32_FILE_ATTRIBUTE_DATA, - reparse_tag: libc::DWORD, + reparse_tag: c::DWORD, } #[derive(Copy, Clone, PartialEq, Eq, Hash)] @@ -41,17 +40,17 @@ pub enum FileType { pub struct ReadDir { handle: FindNextFileHandle, root: Arc, - first: Option, + first: Option, } -struct FindNextFileHandle(libc::HANDLE); +struct FindNextFileHandle(c::HANDLE); unsafe impl Send for FindNextFileHandle {} unsafe impl Sync for FindNextFileHandle {} pub struct DirEntry { root: Arc, - data: libc::WIN32_FIND_DATAW, + data: c::WIN32_FIND_DATAW, } #[derive(Clone, Default)] @@ -61,15 +60,15 @@ pub struct OpenOptions { read: bool, write: bool, truncate: bool, - desired_access: Option, - share_mode: Option, - creation_disposition: Option, - flags_and_attributes: Option, + desired_access: Option, + share_mode: Option, + creation_disposition: Option, + flags_and_attributes: Option, security_attributes: usize, // *mut T doesn't have a Default impl } #[derive(Clone, PartialEq, Eq, Debug)] -pub struct FilePermissions { attrs: libc::DWORD } +pub struct FilePermissions { attrs: c::DWORD } pub struct DirBuilder; @@ -84,9 +83,8 @@ impl Iterator for ReadDir { unsafe { let mut wfd = mem::zeroed(); loop { - if libc::FindNextFileW(self.handle.0, &mut wfd) == 0 { - if libc::GetLastError() == - c::ERROR_NO_MORE_FILES as libc::DWORD { + if c::FindNextFileW(self.handle.0, &mut wfd) == 0 { + if c::GetLastError() == c::ERROR_NO_MORE_FILES { return None } else { return Some(Err(Error::last_os_error())) @@ -102,13 +100,13 @@ impl Iterator for ReadDir { impl Drop for FindNextFileHandle { fn drop(&mut self) { - let r = unsafe { libc::FindClose(self.0) }; + let r = unsafe { c::FindClose(self.0) }; debug_assert!(r != 0); } } impl DirEntry { - fn new(root: &Arc, wfd: &libc::WIN32_FIND_DATAW) -> Option { + fn new(root: &Arc, wfd: &c::WIN32_FIND_DATAW) -> Option { match &wfd.cFileName[0..3] { // check for '.' and '..' [46, 0, ..] | @@ -170,50 +168,50 @@ impl OpenOptions { pub fn share_mode(&mut self, val: u32) { self.share_mode = Some(val); } - pub fn security_attributes(&mut self, attrs: libc::LPSECURITY_ATTRIBUTES) { + pub fn security_attributes(&mut self, attrs: c::LPSECURITY_ATTRIBUTES) { self.security_attributes = attrs as usize; } - fn get_desired_access(&self) -> libc::DWORD { + fn get_desired_access(&self) -> c::DWORD { self.desired_access.unwrap_or({ - let mut base = if self.read {libc::FILE_GENERIC_READ} else {0} | - if self.write {libc::FILE_GENERIC_WRITE} else {0}; + let mut base = if self.read {c::FILE_GENERIC_READ} else {0} | + if self.write {c::FILE_GENERIC_WRITE} else {0}; if self.append { - base &= !libc::FILE_WRITE_DATA; - base |= libc::FILE_APPEND_DATA; + base &= !c::FILE_WRITE_DATA; + base |= c::FILE_APPEND_DATA; } base }) } - fn get_share_mode(&self) -> libc::DWORD { + fn get_share_mode(&self) -> c::DWORD { // libuv has a good comment about this, but the basic idea is that // we try to emulate unix semantics by enabling all sharing by // allowing things such as deleting a file while it's still open. - self.share_mode.unwrap_or(libc::FILE_SHARE_READ | - libc::FILE_SHARE_WRITE | - libc::FILE_SHARE_DELETE) + self.share_mode.unwrap_or(c::FILE_SHARE_READ | + c::FILE_SHARE_WRITE | + c::FILE_SHARE_DELETE) } - fn get_creation_disposition(&self) -> libc::DWORD { + fn get_creation_disposition(&self) -> c::DWORD { self.creation_disposition.unwrap_or({ match (self.create, self.truncate) { - (true, true) => libc::CREATE_ALWAYS, - (true, false) => libc::OPEN_ALWAYS, - (false, false) => libc::OPEN_EXISTING, + (true, true) => c::CREATE_ALWAYS, + (true, false) => c::OPEN_ALWAYS, + (false, false) => c::OPEN_EXISTING, (false, true) => { if self.write && !self.append { - libc::CREATE_ALWAYS + c::CREATE_ALWAYS } else { - libc::TRUNCATE_EXISTING + c::TRUNCATE_EXISTING } } } }) } - fn get_flags_and_attributes(&self) -> libc::DWORD { - self.flags_and_attributes.unwrap_or(libc::FILE_ATTRIBUTE_NORMAL) + fn get_flags_and_attributes(&self) -> c::DWORD { + self.flags_and_attributes.unwrap_or(c::FILE_ATTRIBUTE_NORMAL) } } @@ -230,15 +228,15 @@ impl File { pub fn open(path: &Path, opts: &OpenOptions) -> io::Result { let path = to_utf16(path); let handle = unsafe { - libc::CreateFileW(path.as_ptr(), - opts.get_desired_access(), - opts.get_share_mode(), - opts.security_attributes as *mut _, - opts.get_creation_disposition(), - opts.get_flags_and_attributes(), - ptr::null_mut()) + c::CreateFileW(path.as_ptr(), + opts.get_desired_access(), + opts.get_share_mode(), + opts.security_attributes as *mut _, + opts.get_creation_disposition(), + opts.get_flags_and_attributes(), + ptr::null_mut()) }; - if handle == libc::INVALID_HANDLE_VALUE { + if handle == c::INVALID_HANDLE_VALUE { Err(Error::last_os_error()) } else { Ok(File { handle: Handle::new(handle) }) @@ -246,7 +244,7 @@ impl File { } pub fn fsync(&self) -> io::Result<()> { - try!(cvt(unsafe { libc::FlushFileBuffers(self.handle.raw()) })); + try!(cvt(unsafe { c::FlushFileBuffers(self.handle.raw()) })); Ok(()) } @@ -254,14 +252,14 @@ impl File { pub fn truncate(&self, size: u64) -> io::Result<()> { let mut info = c::FILE_END_OF_FILE_INFO { - EndOfFile: size as libc::LARGE_INTEGER, + EndOfFile: size as c::LARGE_INTEGER, }; let size = mem::size_of_val(&info); try!(cvt(unsafe { c::SetFileInformationByHandle(self.handle.raw(), c::FileEndOfFileInfo, &mut info as *mut _ as *mut _, - size as libc::DWORD) + size as c::DWORD) })); Ok(()) } @@ -304,15 +302,15 @@ impl File { pub fn seek(&self, pos: SeekFrom) -> io::Result { let (whence, pos) = match pos { - SeekFrom::Start(n) => (libc::FILE_BEGIN, n as i64), - SeekFrom::End(n) => (libc::FILE_END, n), - SeekFrom::Current(n) => (libc::FILE_CURRENT, n), + SeekFrom::Start(n) => (c::FILE_BEGIN, n as i64), + SeekFrom::End(n) => (c::FILE_END, n), + SeekFrom::Current(n) => (c::FILE_CURRENT, n), }; - let pos = pos as libc::LARGE_INTEGER; + let pos = pos as c::LARGE_INTEGER; let mut newpos = 0; try!(cvt(unsafe { - libc::SetFilePointerEx(self.handle.raw(), pos, - &mut newpos, whence) + c::SetFilePointerEx(self.handle.raw(), pos, + &mut newpos, whence) })); Ok(newpos as u64) } @@ -323,7 +321,7 @@ impl File { fn reparse_point<'a>(&self, space: &'a mut [u8; c::MAXIMUM_REPARSE_DATA_BUFFER_SIZE]) - -> io::Result<(libc::DWORD, &'a c::REPARSE_DATA_BUFFER)> { + -> io::Result<(c::DWORD, &'a c::REPARSE_DATA_BUFFER)> { unsafe { let mut bytes = 0; try!(cvt({ @@ -332,7 +330,7 @@ impl File { ptr::null_mut(), 0, space.as_mut_ptr() as *mut _, - space.len() as libc::DWORD, + space.len() as c::DWORD, &mut bytes, ptr::null_mut()) })); @@ -361,8 +359,8 @@ impl File { } } -impl FromInner for File { - fn from_inner(handle: libc::HANDLE) -> File { +impl FromInner for File { + fn from_inner(handle: c::HANDLE) -> File { File { handle: Handle::new(handle) } } } @@ -402,12 +400,12 @@ impl FileAttr { pub fn accessed(&self) -> u64 { self.to_u64(&self.data.ftLastAccessTime) } pub fn modified(&self) -> u64 { self.to_u64(&self.data.ftLastWriteTime) } - fn to_u64(&self, ft: &libc::FILETIME) -> u64 { + fn to_u64(&self, ft: &c::FILETIME) -> u64 { (ft.dwLowDateTime as u64) | ((ft.dwHighDateTime as u64) << 32) } fn is_reparse_point(&self) -> bool { - self.data.dwFileAttributes & libc::FILE_ATTRIBUTE_REPARSE_POINT != 0 + self.data.dwFileAttributes & c::FILE_ATTRIBUTE_REPARSE_POINT != 0 } } @@ -426,8 +424,8 @@ impl FilePermissions { } impl FileType { - fn new(attrs: libc::DWORD, reparse_tag: libc::DWORD) -> FileType { - if attrs & libc::FILE_ATTRIBUTE_REPARSE_POINT != 0 { + fn new(attrs: c::DWORD, reparse_tag: c::DWORD) -> FileType { + if attrs & c::FILE_ATTRIBUTE_REPARSE_POINT != 0 { match reparse_tag { c::IO_REPARSE_TAG_SYMLINK => FileType::Symlink, c::IO_REPARSE_TAG_MOUNT_POINT => FileType::MountPoint, @@ -453,7 +451,7 @@ impl DirBuilder { pub fn mkdir(&self, p: &Path) -> io::Result<()> { let p = to_utf16(p); try!(cvt(unsafe { - libc::CreateDirectoryW(p.as_ptr(), ptr::null_mut()) + c::CreateDirectoryW(p.as_ptr(), ptr::null_mut()) })); Ok(()) } @@ -466,8 +464,8 @@ pub fn readdir(p: &Path) -> io::Result { unsafe { let mut wfd = mem::zeroed(); - let find_handle = libc::FindFirstFileW(path.as_ptr(), &mut wfd); - if find_handle != libc::INVALID_HANDLE_VALUE { + let find_handle = c::FindFirstFileW(path.as_ptr(), &mut wfd); + if find_handle != c::INVALID_HANDLE_VALUE { Ok(ReadDir { handle: FindNextFileHandle(find_handle), root: Arc::new(root), @@ -481,7 +479,7 @@ pub fn readdir(p: &Path) -> io::Result { pub fn unlink(p: &Path) -> io::Result<()> { let p_utf16 = to_utf16(p); - try!(cvt(unsafe { libc::DeleteFileW(p_utf16.as_ptr()) })); + try!(cvt(unsafe { c::DeleteFileW(p_utf16.as_ptr()) })); Ok(()) } @@ -489,8 +487,7 @@ pub fn rename(old: &Path, new: &Path) -> io::Result<()> { let old = to_utf16(old); let new = to_utf16(new); try!(cvt(unsafe { - libc::MoveFileExW(old.as_ptr(), new.as_ptr(), - libc::MOVEFILE_REPLACE_EXISTING) + c::MoveFileExW(old.as_ptr(), new.as_ptr(), c::MOVEFILE_REPLACE_EXISTING) })); Ok(()) } @@ -515,7 +512,7 @@ pub fn symlink_inner(src: &Path, dst: &Path, dir: bool) -> io::Result<()> { let dst = to_utf16(dst); let flags = if dir { c::SYMBOLIC_LINK_FLAG_DIRECTORY } else { 0 }; try!(cvt(unsafe { - c::CreateSymbolicLinkW(dst.as_ptr(), src.as_ptr(), flags) as libc::BOOL + c::CreateSymbolicLinkW(dst.as_ptr(), src.as_ptr(), flags) as c::BOOL })); Ok(()) } @@ -524,7 +521,7 @@ pub fn link(src: &Path, dst: &Path) -> io::Result<()> { let src = to_utf16(src); let dst = to_utf16(dst); try!(cvt(unsafe { - libc::CreateHardLinkW(dst.as_ptr(), src.as_ptr(), ptr::null_mut()) + c::CreateHardLinkW(dst.as_ptr(), src.as_ptr(), ptr::null_mut()) })); Ok(()) } @@ -575,7 +572,7 @@ pub fn set_perm(p: &Path, perm: FilePermissions) -> io::Result<()> { fn get_path(f: &File) -> io::Result { super::fill_utf16_buf(|buf, sz| unsafe { c::GetFinalPathNameByHandleW(f.handle.raw(), buf, sz, - libc::VOLUME_NAME_DOS) + c::VOLUME_NAME_DOS) }, |buf| { PathBuf::from(OsString::from_wide(buf)) }) @@ -592,16 +589,16 @@ pub fn canonicalize(p: &Path) -> io::Result { pub fn copy(from: &Path, to: &Path) -> io::Result { unsafe extern "system" fn callback( - _TotalFileSize: libc::LARGE_INTEGER, - TotalBytesTransferred: libc::LARGE_INTEGER, - _StreamSize: libc::LARGE_INTEGER, - _StreamBytesTransferred: libc::LARGE_INTEGER, - _dwStreamNumber: libc::DWORD, - _dwCallbackReason: libc::DWORD, - _hSourceFile: HANDLE, - _hDestinationFile: HANDLE, - lpData: libc::LPVOID, - ) -> libc::DWORD { + _TotalFileSize: c::LARGE_INTEGER, + TotalBytesTransferred: c::LARGE_INTEGER, + _StreamSize: c::LARGE_INTEGER, + _StreamBytesTransferred: c::LARGE_INTEGER, + _dwStreamNumber: c::DWORD, + _dwCallbackReason: c::DWORD, + _hSourceFile: c::HANDLE, + _hDestinationFile: c::HANDLE, + lpData: c::LPVOID, + ) -> c::DWORD { *(lpData as *mut i64) = TotalBytesTransferred; c::PROGRESS_CONTINUE } @@ -673,10 +670,10 @@ fn directory_junctions_are_directories() { *buf.offset(i) = 0; i += 1; (*db).ReparseTag = c::IO_REPARSE_TAG_MOUNT_POINT; - (*db).ReparseTargetMaximumLength = (i * 2) as libc::WORD; - (*db).ReparseTargetLength = ((i - 1) * 2) as libc::WORD; + (*db).ReparseTargetMaximumLength = (i * 2) as c::WORD; + (*db).ReparseTargetLength = ((i - 1) * 2) as c::WORD; (*db).ReparseDataLength = - (*db).ReparseTargetLength as libc::DWORD + 12; + (*db).ReparseTargetLength as c::DWORD + 12; let mut ret = 0; cvt(c::DeviceIoControl(h as *mut _, @@ -707,10 +704,10 @@ fn directory_junctions_are_directories() { &mut tp.Privileges[0].Luid))); tp.PrivilegeCount = 1; tp.Privileges[0].Attributes = c::SE_PRIVILEGE_ENABLED; - let size = mem::size_of::() as libc::DWORD; - try!(cvt(c::AdjustTokenPrivileges(token, libc::FALSE, &mut tp, size, + let size = mem::size_of::() as c::DWORD; + try!(cvt(c::AdjustTokenPrivileges(token, c::FALSE, &mut tp, size, ptr::null_mut(), ptr::null_mut()))); - try!(cvt(libc::CloseHandle(token))); + try!(cvt(c::CloseHandle(token))); File::open_reparse_point(p, write) } diff --git a/src/libstd/sys/windows/handle.rs b/src/libstd/sys/windows/handle.rs index a9e9b0e252077..cb41b05daaea2 100644 --- a/src/libstd/sys/windows/handle.rs +++ b/src/libstd/sys/windows/handle.rs @@ -10,11 +10,10 @@ use io::ErrorKind; use io; -use libc::funcs::extra::kernel32::{GetCurrentProcess, DuplicateHandle}; -use libc::{self, HANDLE}; use mem; use ops::Deref; use ptr; +use sys::c; use sys::cvt; /// An owned container for `HANDLE` object, closing them on Drop. @@ -28,17 +27,17 @@ pub struct Handle(RawHandle); /// This does **not** drop the handle when it goes out of scope, use `Handle` /// instead for that. #[derive(Copy, Clone)] -pub struct RawHandle(HANDLE); +pub struct RawHandle(c::HANDLE); unsafe impl Send for RawHandle {} unsafe impl Sync for RawHandle {} impl Handle { - pub fn new(handle: HANDLE) -> Handle { + pub fn new(handle: c::HANDLE) -> Handle { Handle(RawHandle::new(handle)) } - pub fn into_raw(self) -> HANDLE { + pub fn into_raw(self) -> c::HANDLE { let ret = self.raw(); mem::forget(self); return ret; @@ -52,22 +51,22 @@ impl Deref for Handle { impl Drop for Handle { fn drop(&mut self) { - unsafe { let _ = libc::CloseHandle(self.raw()); } + unsafe { let _ = c::CloseHandle(self.raw()); } } } impl RawHandle { - pub fn new(handle: HANDLE) -> RawHandle { + pub fn new(handle: c::HANDLE) -> RawHandle { RawHandle(handle) } - pub fn raw(&self) -> HANDLE { self.0 } + pub fn raw(&self) -> c::HANDLE { self.0 } pub fn read(&self, buf: &mut [u8]) -> io::Result { let mut read = 0; let res = cvt(unsafe { - libc::ReadFile(self.0, buf.as_ptr() as libc::LPVOID, - buf.len() as libc::DWORD, &mut read, + c::ReadFile(self.0, buf.as_ptr() as c::LPVOID, + buf.len() as c::DWORD, &mut read, ptr::null_mut()) }); @@ -87,20 +86,20 @@ impl RawHandle { pub fn write(&self, buf: &[u8]) -> io::Result { let mut amt = 0; try!(cvt(unsafe { - libc::WriteFile(self.0, buf.as_ptr() as libc::LPVOID, - buf.len() as libc::DWORD, &mut amt, + c::WriteFile(self.0, buf.as_ptr() as c::LPVOID, + buf.len() as c::DWORD, &mut amt, ptr::null_mut()) })); Ok(amt as usize) } - pub fn duplicate(&self, access: libc::DWORD, inherit: bool, - options: libc::DWORD) -> io::Result { - let mut ret = 0 as libc::HANDLE; + pub fn duplicate(&self, access: c::DWORD, inherit: bool, + options: c::DWORD) -> io::Result { + let mut ret = 0 as c::HANDLE; try!(cvt(unsafe { - let cur_proc = GetCurrentProcess(); - DuplicateHandle(cur_proc, self.0, cur_proc, &mut ret, - access, inherit as libc::BOOL, + let cur_proc = c::GetCurrentProcess(); + c::DuplicateHandle(cur_proc, self.0, cur_proc, &mut ret, + access, inherit as c::BOOL, options) })); Ok(Handle::new(ret)) diff --git a/src/libstd/sys/windows/mod.rs b/src/libstd/sys/windows/mod.rs index 4df3c561ab1c3..3f76218eafee6 100644 --- a/src/libstd/sys/windows/mod.rs +++ b/src/libstd/sys/windows/mod.rs @@ -16,7 +16,6 @@ use prelude::v1::*; use ffi::{OsStr, OsString}; use io::{self, ErrorKind}; -use libc; use num::Zero; use os::windows::ffi::{OsStrExt, OsStringExt}; use path::PathBuf; @@ -46,25 +45,28 @@ pub mod stdio; pub fn init() {} pub fn decode_error_kind(errno: i32) -> ErrorKind { - match errno as libc::c_int { - libc::ERROR_ACCESS_DENIED => ErrorKind::PermissionDenied, - libc::ERROR_ALREADY_EXISTS => ErrorKind::AlreadyExists, - libc::ERROR_BROKEN_PIPE => ErrorKind::BrokenPipe, - libc::ERROR_FILE_NOT_FOUND => ErrorKind::NotFound, - c::ERROR_PATH_NOT_FOUND => ErrorKind::NotFound, - libc::ERROR_NO_DATA => ErrorKind::BrokenPipe, - libc::ERROR_OPERATION_ABORTED => ErrorKind::TimedOut, - - libc::WSAEACCES => ErrorKind::PermissionDenied, - libc::WSAEADDRINUSE => ErrorKind::AddrInUse, - libc::WSAEADDRNOTAVAIL => ErrorKind::AddrNotAvailable, - libc::WSAECONNABORTED => ErrorKind::ConnectionAborted, - libc::WSAECONNREFUSED => ErrorKind::ConnectionRefused, - libc::WSAECONNRESET => ErrorKind::ConnectionReset, - libc::WSAEINVAL => ErrorKind::InvalidInput, - libc::WSAENOTCONN => ErrorKind::NotConnected, - libc::WSAEWOULDBLOCK => ErrorKind::WouldBlock, - libc::WSAETIMEDOUT => ErrorKind::TimedOut, + match errno as c::DWORD { + c::ERROR_ACCESS_DENIED => return ErrorKind::PermissionDenied, + c::ERROR_ALREADY_EXISTS => return ErrorKind::AlreadyExists, + c::ERROR_BROKEN_PIPE => return ErrorKind::BrokenPipe, + c::ERROR_FILE_NOT_FOUND => return ErrorKind::NotFound, + c::ERROR_PATH_NOT_FOUND => return ErrorKind::NotFound, + c::ERROR_NO_DATA => return ErrorKind::BrokenPipe, + c::ERROR_OPERATION_ABORTED => return ErrorKind::TimedOut, + _ => {} + } + + match errno { + c::WSAEACCES => ErrorKind::PermissionDenied, + c::WSAEADDRINUSE => ErrorKind::AddrInUse, + c::WSAEADDRNOTAVAIL => ErrorKind::AddrNotAvailable, + c::WSAECONNABORTED => ErrorKind::ConnectionAborted, + c::WSAECONNREFUSED => ErrorKind::ConnectionRefused, + c::WSAECONNRESET => ErrorKind::ConnectionReset, + c::WSAEINVAL => ErrorKind::InvalidInput, + c::WSAENOTCONN => ErrorKind::NotConnected, + c::WSAEWOULDBLOCK => ErrorKind::WouldBlock, + c::WSAETIMEDOUT => ErrorKind::TimedOut, _ => ErrorKind::Other, } @@ -91,7 +93,7 @@ fn to_utf16_os(s: &OsStr) -> Vec { // yielded the data which has been read from the syscall. The return value // from this closure is then the return value of the function. fn fill_utf16_buf(mut f1: F1, f2: F2) -> io::Result - where F1: FnMut(*mut u16, libc::DWORD) -> libc::DWORD, + where F1: FnMut(*mut u16, c::DWORD) -> c::DWORD, F2: FnOnce(&[u16]) -> T { // Start off with a stack buf but then spill over to the heap if we end up @@ -120,13 +122,12 @@ fn fill_utf16_buf(mut f1: F1, f2: F2) -> io::Result // error" is still 0 then we interpret it as a 0 length buffer and // not an actual error. c::SetLastError(0); - let k = match f1(buf.as_mut_ptr(), n as libc::DWORD) { - 0 if libc::GetLastError() == 0 => 0, + let k = match f1(buf.as_mut_ptr(), n as c::DWORD) { + 0 if c::GetLastError() == 0 => 0, 0 => return Err(io::Error::last_os_error()), n => n, } as usize; - if k == n && libc::GetLastError() == - libc::ERROR_INSUFFICIENT_BUFFER as libc::DWORD { + if k == n && c::GetLastError() == c::ERROR_INSUFFICIENT_BUFFER { n *= 2; } else if k >= n { n = k; @@ -157,7 +158,7 @@ fn cvt(i: I) -> io::Result { } } -fn dur2timeout(dur: Duration) -> libc::DWORD { +fn dur2timeout(dur: Duration) -> c::DWORD { // Note that a duration is a (u64, u32) (seconds, nanoseconds) pair, and the // timeouts in windows APIs are typically u32 milliseconds. To translate, we // have two pieces to take care of: @@ -170,10 +171,10 @@ fn dur2timeout(dur: Duration) -> libc::DWORD { }).and_then(|ms| { ms.checked_add(if dur.subsec_nanos() % 1_000_000 > 0 {1} else {0}) }).map(|ms| { - if ms > ::max_value() as u64 { - libc::INFINITE + if ms > ::max_value() as u64 { + c::INFINITE } else { - ms as libc::DWORD + ms as c::DWORD } - }).unwrap_or(libc::INFINITE) + }).unwrap_or(c::INFINITE) } diff --git a/src/libstd/sys/windows/net.rs b/src/libstd/sys/windows/net.rs index 998b4fcb1a121..3e69902dcb6bd 100644 --- a/src/libstd/sys/windows/net.rs +++ b/src/libstd/sys/windows/net.rs @@ -9,23 +9,30 @@ // except according to those terms. use io; -use libc::consts::os::extra::INVALID_SOCKET; -use libc::{self, c_int, c_void}; +use libc::{c_int, c_void}; use mem; -use net::SocketAddr; +use net::{SocketAddr, Shutdown}; use num::One; use ops::Neg; use ptr; use sync::Once; -use sys; use sys::c; +use sys; use sys_common::{self, AsInner, FromInner, IntoInner}; -use sys_common::net::{setsockopt, getsockopt}; +use sys_common::net; use time::Duration; pub type wrlen_t = i32; -pub struct Socket(libc::SOCKET); +pub mod netc { + pub use sys::c::*; + pub use sys::c::SOCKADDR as sockaddr; + pub use sys::c::SOCKADDR_STORAGE_LH as sockaddr_storage; + pub use sys::c::ADDRINFOA as addrinfo; + pub use sys::c::ADDRESS_FAMILY as sa_family_t; +} + +pub struct Socket(c::SOCKET); /// Checks whether the Windows socket interface has been started already, and /// if not, starts it. @@ -76,13 +83,13 @@ pub fn cvt_r(mut f: F) -> io::Result impl Socket { pub fn new(addr: &SocketAddr, ty: c_int) -> io::Result { let fam = match *addr { - SocketAddr::V4(..) => libc::AF_INET, - SocketAddr::V6(..) => libc::AF_INET6, + SocketAddr::V4(..) => c::AF_INET, + SocketAddr::V6(..) => c::AF_INET6, }; let socket = try!(unsafe { match c::WSASocketW(fam, ty, 0, ptr::null_mut(), 0, c::WSA_FLAG_OVERLAPPED) { - INVALID_SOCKET => Err(last_error()), + c::INVALID_SOCKET => Err(last_error()), n => Ok(Socket(n)), } }); @@ -90,11 +97,11 @@ impl Socket { Ok(socket) } - pub fn accept(&self, storage: *mut libc::sockaddr, - len: *mut libc::socklen_t) -> io::Result { + pub fn accept(&self, storage: *mut c::SOCKADDR, + len: *mut c_int) -> io::Result { let socket = try!(unsafe { - match libc::accept(self.0, storage, len) { - INVALID_SOCKET => Err(last_error()), + match c::accept(self.0, storage, len) { + c::INVALID_SOCKET => Err(last_error()), n => Ok(Socket(n)), } }); @@ -113,7 +120,7 @@ impl Socket { info.iProtocol, &mut info, 0, c::WSA_FLAG_OVERLAPPED) { - INVALID_SOCKET => Err(last_error()), + c::INVALID_SOCKET => Err(last_error()), n => Ok(Socket(n)), } }); @@ -125,7 +132,7 @@ impl Socket { // On unix when a socket is shut down all further reads return 0, so we // do the same on windows to map a shut down socket to returning EOF. unsafe { - match libc::recv(self.0, buf.as_mut_ptr() as *mut c_void, + match c::recv(self.0, buf.as_mut_ptr() as *mut c_void, buf.len() as i32, 0) { -1 if c::WSAGetLastError() == c::WSAESHUTDOWN => Ok(0), -1 => Err(last_error()), @@ -134,7 +141,8 @@ impl Socket { } } - pub fn set_timeout(&self, dur: Option, kind: libc::c_int) -> io::Result<()> { + pub fn set_timeout(&self, dur: Option, + kind: c_int) -> io::Result<()> { let timeout = match dur { Some(dur) => { let timeout = sys::dur2timeout(dur); @@ -146,11 +154,11 @@ impl Socket { } None => 0 }; - setsockopt(self, libc::SOL_SOCKET, kind, timeout) + net::setsockopt(self, c::SOL_SOCKET, kind, timeout) } - pub fn timeout(&self, kind: libc::c_int) -> io::Result> { - let raw: libc::DWORD = try!(getsockopt(self, libc::SOL_SOCKET, kind)); + pub fn timeout(&self, kind: c_int) -> io::Result> { + let raw: c::DWORD = try!(net::getsockopt(self, c::SOL_SOCKET, kind)); if raw == 0 { Ok(None) } else { @@ -162,28 +170,38 @@ impl Socket { fn set_no_inherit(&self) -> io::Result<()> { sys::cvt(unsafe { - c::SetHandleInformation(self.0 as libc::HANDLE, + c::SetHandleInformation(self.0 as c::HANDLE, c::HANDLE_FLAG_INHERIT, 0) }).map(|_| ()) } + + pub fn shutdown(&self, how: Shutdown) -> io::Result<()> { + let how = match how { + Shutdown::Write => c::SD_SEND, + Shutdown::Read => c::SD_RECEIVE, + Shutdown::Both => c::SD_BOTH, + }; + try!(cvt(unsafe { c::shutdown(self.0, how) })); + Ok(()) + } } impl Drop for Socket { fn drop(&mut self) { - let _ = unsafe { libc::closesocket(self.0) }; + let _ = unsafe { c::closesocket(self.0) }; } } -impl AsInner for Socket { - fn as_inner(&self) -> &libc::SOCKET { &self.0 } +impl AsInner for Socket { + fn as_inner(&self) -> &c::SOCKET { &self.0 } } -impl FromInner for Socket { - fn from_inner(sock: libc::SOCKET) -> Socket { Socket(sock) } +impl FromInner for Socket { + fn from_inner(sock: c::SOCKET) -> Socket { Socket(sock) } } -impl IntoInner for Socket { - fn into_inner(self) -> libc::SOCKET { +impl IntoInner for Socket { + fn into_inner(self) -> c::SOCKET { let ret = self.0; mem::forget(self); ret diff --git a/src/libstd/sys/windows/os.rs b/src/libstd/sys/windows/os.rs index 1680ea88d0bdb..52740b2cad4f0 100644 --- a/src/libstd/sys/windows/os.rs +++ b/src/libstd/sys/windows/os.rs @@ -19,62 +19,36 @@ use error::Error as StdError; use ffi::{OsString, OsStr}; use fmt; use io; -use libc::types::os::arch::extra::LPWCH; -use libc::{self, c_int, c_void}; +use libc::{c_int, c_void}; use ops::Range; use os::windows::ffi::EncodeWide; use path::{self, PathBuf}; use ptr; use slice; -use sys::c; +use sys::{c, cvt}; use sys::handle::Handle; -use libc::funcs::extra::kernel32::{ - GetEnvironmentStringsW, - FreeEnvironmentStringsW -}; - pub fn errno() -> i32 { - unsafe { libc::GetLastError() as i32 } + unsafe { c::GetLastError() as i32 } } /// Gets a detailed string description for the given error number. pub fn error_string(errnum: i32) -> String { - use libc::types::os::arch::extra::DWORD; - use libc::types::os::arch::extra::LPWSTR; - use libc::types::os::arch::extra::LPVOID; - use libc::types::os::arch::extra::WCHAR; - - #[link_name = "kernel32"] - extern "system" { - fn FormatMessageW(flags: DWORD, - lpSrc: LPVOID, - msgId: DWORD, - langId: DWORD, - buf: LPWSTR, - nsize: DWORD, - args: *const c_void) - -> DWORD; - } - - const FORMAT_MESSAGE_FROM_SYSTEM: DWORD = 0x00001000; - const FORMAT_MESSAGE_IGNORE_INSERTS: DWORD = 0x00000200; - // This value is calculated from the macro // MAKELANGID(LANG_SYSTEM_DEFAULT, SUBLANG_SYS_DEFAULT) - let langId = 0x0800 as DWORD; + let langId = 0x0800 as c::DWORD; - let mut buf = [0 as WCHAR; 2048]; + let mut buf = [0 as c::WCHAR; 2048]; unsafe { - let res = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - ptr::null_mut(), - errnum as DWORD, - langId, - buf.as_mut_ptr(), - buf.len() as DWORD, - ptr::null()) as usize; + let res = c::FormatMessageW(c::FORMAT_MESSAGE_FROM_SYSTEM | + c::FORMAT_MESSAGE_IGNORE_INSERTS, + ptr::null_mut(), + errnum as c::DWORD, + langId, + buf.as_mut_ptr(), + buf.len() as c::DWORD, + ptr::null()) as usize; if res == 0 { // Sometimes FormatMessageW can fail e.g. system doesn't like langId, let fm_err = errno(); @@ -96,8 +70,8 @@ pub fn error_string(errnum: i32) -> String { } pub struct Env { - base: LPWCH, - cur: LPWCH, + base: c::LPWCH, + cur: c::LPWCH, } impl Iterator for Env { @@ -126,13 +100,13 @@ impl Iterator for Env { impl Drop for Env { fn drop(&mut self) { - unsafe { FreeEnvironmentStringsW(self.base); } + unsafe { c::FreeEnvironmentStringsW(self.base); } } } pub fn env() -> Env { unsafe { - let ch = GetEnvironmentStringsW(); + let ch = c::GetEnvironmentStringsW(); if ch as usize == 0 { panic!("failure getting env string from OS: {}", io::Error::last_os_error()); @@ -233,13 +207,13 @@ impl StdError for JoinPathsError { pub fn current_exe() -> io::Result { super::fill_utf16_buf(|buf, sz| unsafe { - libc::GetModuleFileNameW(ptr::null_mut(), buf, sz) + c::GetModuleFileNameW(ptr::null_mut(), buf, sz) }, super::os2path) } pub fn getcwd() -> io::Result { super::fill_utf16_buf(|buf, sz| unsafe { - libc::GetCurrentDirectoryW(sz, buf) + c::GetCurrentDirectoryW(sz, buf) }, super::os2path) } @@ -248,41 +222,44 @@ pub fn chdir(p: &path::Path) -> io::Result<()> { let mut p = p.encode_wide().collect::>(); p.push(0); - unsafe { - match libc::SetCurrentDirectoryW(p.as_ptr()) != (0 as libc::BOOL) { - true => Ok(()), - false => Err(io::Error::last_os_error()), - } - } + cvt(unsafe { + c::SetCurrentDirectoryW(p.as_ptr()) + }).map(|_| ()) } -pub fn getenv(k: &OsStr) -> Option { +pub fn getenv(k: &OsStr) -> io::Result> { let k = super::to_utf16_os(k); - super::fill_utf16_buf(|buf, sz| unsafe { - libc::GetEnvironmentVariableW(k.as_ptr(), buf, sz) + let res = super::fill_utf16_buf(|buf, sz| unsafe { + c::GetEnvironmentVariableW(k.as_ptr(), buf, sz) }, |buf| { OsStringExt::from_wide(buf) - }).ok() + }); + match res { + Ok(value) => Ok(Some(value)), + Err(e) => { + if e.raw_os_error() == Some(c::ERROR_ENVVAR_NOT_FOUND as i32) { + Ok(None) + } else { + Err(e) + } + } + } } -pub fn setenv(k: &OsStr, v: &OsStr) { +pub fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> { let k = super::to_utf16_os(k); let v = super::to_utf16_os(v); - unsafe { - if libc::SetEnvironmentVariableW(k.as_ptr(), v.as_ptr()) == 0 { - panic!("failed to set env: {}", io::Error::last_os_error()); - } - } + cvt(unsafe { + c::SetEnvironmentVariableW(k.as_ptr(), v.as_ptr()) + }).map(|_| ()) } -pub fn unsetenv(n: &OsStr) { +pub fn unsetenv(n: &OsStr) -> io::Result<()> { let v = super::to_utf16_os(n); - unsafe { - if libc::SetEnvironmentVariableW(v.as_ptr(), ptr::null()) == 0 { - panic!("failed to unset env: {}", io::Error::last_os_error()); - } - } + cvt(unsafe { + c::SetEnvironmentVariableW(v.as_ptr(), ptr::null()) + }).map(|_| ()) } pub struct Args { @@ -339,8 +316,8 @@ pub fn temp_dir() -> PathBuf { } pub fn home_dir() -> Option { - getenv("HOME".as_ref()).or_else(|| { - getenv("USERPROFILE".as_ref()) + ::env::var_os("HOME").or_else(|| { + ::env::var_os("USERPROFILE") }).map(PathBuf::from).or_else(|| unsafe { let me = c::GetCurrentProcess(); let mut token = ptr::null_mut(); @@ -350,14 +327,14 @@ pub fn home_dir() -> Option { let _handle = Handle::new(token); super::fill_utf16_buf(|buf, mut sz| { match c::GetUserProfileDirectoryW(token, buf, &mut sz) { - 0 if libc::GetLastError() != 0 => 0, + 0 if c::GetLastError() != 0 => 0, 0 => sz, - n => n as libc::DWORD, + n => n as c::DWORD, } }, super::os2path).ok() }) } pub fn exit(code: i32) -> ! { - unsafe { c::ExitProcess(code as libc::c_uint) } + unsafe { c::ExitProcess(code as c::UINT) } } diff --git a/src/libstd/sys/windows/pipe.rs b/src/libstd/sys/windows/pipe.rs index 3e2f442f073f6..a6e69c789d098 100644 --- a/src/libstd/sys/windows/pipe.rs +++ b/src/libstd/sys/windows/pipe.rs @@ -9,7 +9,6 @@ // except according to those terms. use io; -use libc; use ptr; use sys::cvt; use sys::c; @@ -24,8 +23,8 @@ pub struct AnonPipe { } pub fn anon_pipe() -> io::Result<(AnonPipe, AnonPipe)> { - let mut reader = libc::INVALID_HANDLE_VALUE; - let mut writer = libc::INVALID_HANDLE_VALUE; + let mut reader = c::INVALID_HANDLE_VALUE; + let mut writer = c::INVALID_HANDLE_VALUE; try!(cvt(unsafe { c::CreatePipe(&mut reader, &mut writer, ptr::null_mut(), 0) })); @@ -38,7 +37,7 @@ impl AnonPipe { pub fn handle(&self) -> &Handle { &self.inner } pub fn into_handle(self) -> Handle { self.inner } - pub fn raw(&self) -> libc::HANDLE { self.inner.raw() } + pub fn raw(&self) -> c::HANDLE { self.inner.raw() } pub fn read(&self, buf: &mut [u8]) -> io::Result { self.inner.read(buf) diff --git a/src/libstd/sys/windows/printing/gnu.rs b/src/libstd/sys/windows/printing/gnu.rs index e27bef0b1e989..c1367d5381da1 100644 --- a/src/libstd/sys/windows/printing/gnu.rs +++ b/src/libstd/sys/windows/printing/gnu.rs @@ -11,14 +11,15 @@ #![allow(deprecated)] use dynamic_lib::DynamicLibrary; -use io; use io::prelude::*; -use libc; +use io; +use sys::c; +use libc::c_void; use sys_common::gnu::libbacktrace; -pub fn print(w: &mut Write, i: isize, addr: u64, _: &DynamicLibrary, _: libc::HANDLE) +pub fn print(w: &mut Write, i: isize, addr: u64, _: &DynamicLibrary, _: c::HANDLE) -> io::Result<()> { - let addr = addr as usize as *mut libc::c_void; + let addr = addr as usize as *mut c_void; libbacktrace::print(w, i, addr, addr) } diff --git a/src/libstd/sys/windows/printing/msvc.rs b/src/libstd/sys/windows/printing/msvc.rs index 6f1db5df7db2a..d04691a6a4783 100644 --- a/src/libstd/sys/windows/printing/msvc.rs +++ b/src/libstd/sys/windows/printing/msvc.rs @@ -10,22 +10,23 @@ #![allow(deprecated)] -use sys_common::backtrace::{output, output_fileline}; -use ffi::CStr; use dynamic_lib::DynamicLibrary; -use super::{SymFromAddrFn, SymGetLineFromAddr64Fn, SYMBOL_INFO, MAX_SYM_NAME, IMAGEHLP_LINE64}; -use io; +use ffi::CStr; use io::prelude::*; -use intrinsics; -use libc; +use io; +use libc::{c_ulong, c_int, c_char, c_void}; +use mem; +use super::{SymFromAddrFn, SymGetLineFromAddr64Fn}; +use sys::c; +use sys_common::backtrace::{output, output_fileline}; -pub fn print(w: &mut Write, i: isize, addr: u64, dbghelp: &DynamicLibrary, process: libc::HANDLE) - -> io::Result<()> { +pub fn print(w: &mut Write, i: isize, addr: u64, dbghelp: &DynamicLibrary, + process: c::HANDLE) -> io::Result<()> { let SymFromAddr = sym!(dbghelp, "SymFromAddr", SymFromAddrFn); let SymGetLineFromAddr64 = sym!(dbghelp, "SymGetLineFromAddr64", SymGetLineFromAddr64Fn); - let mut info: SYMBOL_INFO = unsafe { intrinsics::init() }; - info.MaxNameLen = MAX_SYM_NAME as libc::c_ulong; + let mut info: c::SYMBOL_INFO = unsafe { mem::zeroed() }; + info.MaxNameLen = c::MAX_SYM_NAME as c_ulong; // the struct size in C. the value is different to // `size_of::() - MAX_SYM_NAME + 1` (== 81) // due to struct alignment. @@ -34,25 +35,25 @@ pub fn print(w: &mut Write, i: isize, addr: u64, dbghelp: &DynamicLibrary, proce let mut displacement = 0u64; let ret = SymFromAddr(process, addr, &mut displacement, &mut info); - let name = if ret == libc::TRUE { - let ptr = info.Name.as_ptr() as *const libc::c_char; + let name = if ret == c::TRUE { + let ptr = info.Name.as_ptr() as *const c_char; Some(unsafe { CStr::from_ptr(ptr).to_bytes() }) } else { None }; - try!(output(w, i, addr as usize as *mut libc::c_void, name)); + try!(output(w, i, addr as usize as *mut c_void, name)); // Now find out the filename and line number - let mut line: IMAGEHLP_LINE64 = unsafe { intrinsics::init() }; - line.SizeOfStruct = ::mem::size_of::() as u32; + let mut line: c::IMAGEHLP_LINE64 = unsafe { mem::zeroed() }; + line.SizeOfStruct = ::mem::size_of::() as u32; let mut displacement = 0u32; let ret = SymGetLineFromAddr64(process, addr, &mut displacement, &mut line); - if ret == libc::TRUE { + if ret == c::TRUE { output_fileline(w, unsafe { CStr::from_ptr(line.Filename).to_bytes() }, - line.LineNumber as libc::c_int, + line.LineNumber as c_int, false) } else { Ok(()) diff --git a/src/libstd/sys/windows/process.rs b/src/libstd/sys/windows/process.rs index ca33e11eea059..e0f8d6f9df963 100644 --- a/src/libstd/sys/windows/process.rs +++ b/src/libstd/sys/windows/process.rs @@ -19,13 +19,14 @@ use ffi::{OsString, OsStr}; use fmt; use fs; use io::{self, Error}; -use libc::{self, c_void}; +use libc::c_void; use mem; use os::windows::ffi::OsStrExt; use path::Path; use ptr; use sync::StaticMutex; use sys::c; + use sys::fs::{OpenOptions, File}; use sys::handle::{Handle, RawHandle}; use sys::stdio; @@ -107,7 +108,7 @@ pub struct Process { pub enum Stdio { Inherit, None, - Raw(libc::HANDLE), + Raw(c::HANDLE), } pub type RawStdio = Handle; @@ -118,9 +119,6 @@ impl Process { out_handle: Stdio, err_handle: Stdio) -> io::Result { - use libc::{TRUE, STARTF_USESTDHANDLES}; - use libc::{DWORD, STARTUPINFO, CreateProcessW}; - // To have the spawning semantics of unix/windows stay the same, we need // to read the *child's* PATH if one is provided. See #15149 for more // details. @@ -143,8 +141,8 @@ impl Process { }); let mut si = zeroed_startupinfo(); - si.cb = mem::size_of::() as DWORD; - si.dwFlags = STARTF_USESTDHANDLES; + si.cb = mem::size_of::() as c::DWORD; + si.dwFlags = c::STARTF_USESTDHANDLES; let stdin = try!(in_handle.to_handle(c::STD_INPUT_HANDLE)); let stdout = try!(out_handle.to_handle(c::STD_OUTPUT_HANDLE)); @@ -159,9 +157,9 @@ impl Process { cmd_str.push(0); // add null terminator // stolen from the libuv code. - let mut flags = libc::CREATE_UNICODE_ENVIRONMENT; + let mut flags = c::CREATE_UNICODE_ENVIRONMENT; if cfg.detach { - flags |= libc::DETACHED_PROCESS | libc::CREATE_NEW_PROCESS_GROUP; + flags |= c::DETACHED_PROCESS | c::CREATE_NEW_PROCESS_GROUP; } let (envp, _data) = make_envp(cfg.env.as_ref()); @@ -173,12 +171,12 @@ impl Process { static CREATE_PROCESS_LOCK: StaticMutex = StaticMutex::new(); let _lock = CREATE_PROCESS_LOCK.lock(); - cvt(CreateProcessW(ptr::null(), - cmd_str.as_mut_ptr(), - ptr::null_mut(), - ptr::null_mut(), - TRUE, flags, envp, dirp, - &mut si, &mut pi)) + cvt(c::CreateProcessW(ptr::null(), + cmd_str.as_mut_ptr(), + ptr::null_mut(), + ptr::null_mut(), + c::TRUE, flags, envp, dirp, + &mut si, &mut pi)) }); // We close the thread handle because we don't care about keeping @@ -190,7 +188,7 @@ impl Process { } pub unsafe fn kill(&self) -> io::Result<()> { - try!(cvt(libc::TerminateProcess(self.handle.raw(), 1))); + try!(cvt(c::TerminateProcess(self.handle.raw(), 1))); Ok(()) } @@ -201,21 +199,14 @@ impl Process { } pub fn wait(&self) -> io::Result { - use libc::{STILL_ACTIVE, INFINITE, WAIT_OBJECT_0}; - use libc::{GetExitCodeProcess, WaitForSingleObject}; - unsafe { - loop { - let mut status = 0; - try!(cvt(GetExitCodeProcess(self.handle.raw(), &mut status))); - if status != STILL_ACTIVE { - return Ok(ExitStatus(status as i32)); - } - match WaitForSingleObject(self.handle.raw(), INFINITE) { - WAIT_OBJECT_0 => {} - _ => return Err(Error::last_os_error()), - } + let res = c::WaitForSingleObject(self.handle.raw(), c::INFINITE); + if res != c::WAIT_OBJECT_0 { + return Err(Error::last_os_error()) } + let mut status = 0; + try!(cvt(c::GetExitCodeProcess(self.handle.raw(), &mut status))); + Ok(ExitStatus(status)) } } @@ -225,14 +216,14 @@ impl Process { } #[derive(PartialEq, Eq, Clone, Copy, Debug)] -pub struct ExitStatus(i32); +pub struct ExitStatus(c::DWORD); impl ExitStatus { pub fn success(&self) -> bool { self.0 == 0 } pub fn code(&self) -> Option { - Some(self.0) + Some(self.0 as i32) } } @@ -242,8 +233,8 @@ impl fmt::Display for ExitStatus { } } -fn zeroed_startupinfo() -> libc::types::os::arch::extra::STARTUPINFO { - libc::types::os::arch::extra::STARTUPINFO { +fn zeroed_startupinfo() -> c::STARTUPINFO { + c::STARTUPINFO { cb: 0, lpReserved: ptr::null_mut(), lpDesktop: ptr::null_mut(), @@ -259,14 +250,14 @@ fn zeroed_startupinfo() -> libc::types::os::arch::extra::STARTUPINFO { wShowWindow: 0, cbReserved2: 0, lpReserved2: ptr::null_mut(), - hStdInput: libc::INVALID_HANDLE_VALUE, - hStdOutput: libc::INVALID_HANDLE_VALUE, - hStdError: libc::INVALID_HANDLE_VALUE, + hStdInput: c::INVALID_HANDLE_VALUE, + hStdOutput: c::INVALID_HANDLE_VALUE, + hStdError: c::INVALID_HANDLE_VALUE, } } -fn zeroed_process_information() -> libc::types::os::arch::extra::PROCESS_INFORMATION { - libc::types::os::arch::extra::PROCESS_INFORMATION { +fn zeroed_process_information() -> c::PROCESS_INFORMATION { + c::PROCESS_INFORMATION { hProcess: ptr::null_mut(), hThread: ptr::null_mut(), dwProcessId: 0, @@ -358,17 +349,15 @@ fn make_dirp(d: Option<&OsString>) -> (*const u16, Vec) { } impl Stdio { - fn to_handle(&self, stdio_id: libc::DWORD) -> io::Result { - use libc::DUPLICATE_SAME_ACCESS; - + fn to_handle(&self, stdio_id: c::DWORD) -> io::Result { match *self { Stdio::Inherit => { stdio::get(stdio_id).and_then(|io| { - io.handle().duplicate(0, true, DUPLICATE_SAME_ACCESS) + io.handle().duplicate(0, true, c::DUPLICATE_SAME_ACCESS) }) } Stdio::Raw(handle) => { - RawHandle::new(handle).duplicate(0, true, DUPLICATE_SAME_ACCESS) + RawHandle::new(handle).duplicate(0, true, c::DUPLICATE_SAME_ACCESS) } // Similarly to unix, we don't actually leave holes for the @@ -376,9 +365,9 @@ impl Stdio { // equivalents. These equivalents are drawn from libuv's // windows process spawning. Stdio::None => { - let size = mem::size_of::(); - let mut sa = libc::SECURITY_ATTRIBUTES { - nLength: size as libc::DWORD, + let size = mem::size_of::(); + let mut sa = c::SECURITY_ATTRIBUTES { + nLength: size as c::DWORD, lpSecurityDescriptor: ptr::null_mut(), bInheritHandle: 1, }; diff --git a/src/libstd/sys/windows/stack_overflow.rs b/src/libstd/sys/windows/stack_overflow.rs index d1c2144ef0d78..01317bec0de88 100644 --- a/src/libstd/sys/windows/stack_overflow.rs +++ b/src/libstd/sys/windows/stack_overflow.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use libc::{self, LONG}; use sys_common::util::report_overflow; use sys::c; @@ -19,7 +18,7 @@ impl Handler { // This API isn't available on XP, so don't panic in that case and just // pray it works out ok. if c::SetThreadStackGuarantee(&mut 0x5000) == 0 { - if libc::GetLastError() as u32 != libc::ERROR_CALL_NOT_IMPLEMENTED as u32 { + if c::GetLastError() as u32 != c::ERROR_CALL_NOT_IMPLEMENTED as u32 { panic!("failed to reserve stack space for exception handling"); } } @@ -28,7 +27,7 @@ impl Handler { } extern "system" fn vectored_handler(ExceptionInfo: *mut c::EXCEPTION_POINTERS) - -> LONG { + -> c::LONG { unsafe { let rec = &(*(*ExceptionInfo).ExceptionRecord); let code = rec.ExceptionCode; diff --git a/src/libstd/sys/windows/stdio.rs b/src/libstd/sys/windows/stdio.rs index 356787d5bf01a..8f37dc02e87af 100644 --- a/src/libstd/sys/windows/stdio.rs +++ b/src/libstd/sys/windows/stdio.rs @@ -12,7 +12,6 @@ use prelude::v1::*; use io::prelude::*; use io::{self, Cursor}; -use libc; use ptr; use str; use sync::Mutex; @@ -34,9 +33,9 @@ pub struct Stdin { pub struct Stdout(Output); pub struct Stderr(Output); -pub fn get(handle: libc::DWORD) -> io::Result { +pub fn get(handle: c::DWORD) -> io::Result { let handle = unsafe { c::GetStdHandle(handle) }; - if handle == libc::INVALID_HANDLE_VALUE { + if handle == c::INVALID_HANDLE_VALUE { Err(io::Error::last_os_error()) } else if handle.is_null() { Err(io::Error::new(io::ErrorKind::Other, @@ -63,7 +62,7 @@ fn write(out: &Output, data: &[u8]) -> io::Result { let mut written = 0; try!(cvt(unsafe { c::WriteConsoleW(handle, - utf16.as_ptr() as libc::LPCVOID, + utf16.as_ptr() as c::LPCVOID, utf16.len() as u32, &mut written, ptr::null_mut()) @@ -97,7 +96,7 @@ impl Stdin { let mut num = 0; try!(cvt(unsafe { c::ReadConsoleW(handle, - utf16.as_mut_ptr() as libc::LPVOID, + utf16.as_mut_ptr() as c::LPVOID, utf16.len() as u32, &mut num, ptr::null_mut()) @@ -147,7 +146,7 @@ impl io::Write for Stderr { } impl NoClose { - fn new(handle: libc::HANDLE) -> NoClose { + fn new(handle: c::HANDLE) -> NoClose { NoClose(Some(Handle::new(handle))) } diff --git a/src/libstd/sys/windows/thread.rs b/src/libstd/sys/windows/thread.rs index cf1b3ebddb97b..a6e6cc94b7679 100644 --- a/src/libstd/sys/windows/thread.rs +++ b/src/libstd/sys/windows/thread.rs @@ -12,8 +12,8 @@ use prelude::v1::*; use alloc::boxed::FnBox; use io; -use libc::{self, c_void, DWORD}; use mem; +use libc::c_void; use ptr; use sys::c; use sys::handle::Handle; @@ -37,7 +37,7 @@ impl Thread { // Round up to the next 64 kB because that's what the NT kernel does, // might as well make it explicit. let stack_size = (stack + 0xfffe) & (!0xfffe); - let ret = c::CreateThread(ptr::null_mut(), stack_size as libc::size_t, + let ret = c::CreateThread(ptr::null_mut(), stack_size, thread_start, &*p as *const _ as *mut _, 0, ptr::null_mut()); @@ -48,7 +48,7 @@ impl Thread { Ok(Thread { handle: Handle::new(ret) }) }; - extern "system" fn thread_start(main: *mut libc::c_void) -> DWORD { + extern "system" fn thread_start(main: *mut c_void) -> c::DWORD { unsafe { start_thread(main); } 0 } @@ -62,8 +62,7 @@ impl Thread { } pub fn join(self) { - use libc::consts::os::extra::INFINITE; - unsafe { c::WaitForSingleObject(self.handle.raw(), INFINITE); } + unsafe { c::WaitForSingleObject(self.handle.raw(), c::INFINITE); } } pub fn yield_now() { diff --git a/src/libstd/sys/windows/thread_local.rs b/src/libstd/sys/windows/thread_local.rs index c544eec7fce85..db2ad1d89c4d8 100644 --- a/src/libstd/sys/windows/thread_local.rs +++ b/src/libstd/sys/windows/thread_local.rs @@ -10,13 +10,12 @@ use prelude::v1::*; -use libc::types::os::arch::extra::{DWORD, LPVOID, BOOL}; - use ptr; -use sys_common; +use sys::c; use sys_common::mutex::Mutex; +use sys_common; -pub type Key = DWORD; +pub type Key = c::DWORD; pub type Dtor = unsafe extern fn(*mut u8); // Turns out, like pretty much everything, Windows is pretty close the @@ -68,9 +67,8 @@ static mut DTORS: *mut Vec<(Key, Dtor)> = ptr::null_mut(); #[inline] pub unsafe fn create(dtor: Option) -> Key { - const TLS_OUT_OF_INDEXES: DWORD = 0xFFFFFFFF; - let key = TlsAlloc(); - assert!(key != TLS_OUT_OF_INDEXES); + let key = c::TlsAlloc(); + assert!(key != c::TLS_OUT_OF_INDEXES); match dtor { Some(f) => register_dtor(key, f), None => {} @@ -80,13 +78,13 @@ pub unsafe fn create(dtor: Option) -> Key { #[inline] pub unsafe fn set(key: Key, value: *mut u8) { - let r = TlsSetValue(key, value as LPVOID); + let r = c::TlsSetValue(key, value as c::LPVOID); debug_assert!(r != 0); } #[inline] pub unsafe fn get(key: Key) -> *mut u8 { - TlsGetValue(key) as *mut u8 + c::TlsGetValue(key) as *mut u8 } #[inline] @@ -107,18 +105,11 @@ pub unsafe fn destroy(key: Key) { // Note that source [2] above shows precedent for this sort // of strategy. } else { - let r = TlsFree(key); + let r = c::TlsFree(key); debug_assert!(r != 0); } } -extern "system" { - fn TlsAlloc() -> DWORD; - fn TlsFree(dwTlsIndex: DWORD) -> BOOL; - fn TlsGetValue(dwTlsIndex: DWORD) -> LPVOID; - fn TlsSetValue(dwTlsIndex: DWORD, lpTlsvalue: LPVOID) -> BOOL; -} - // ------------------------------------------------------------------------- // Dtor registration // @@ -243,17 +234,15 @@ unsafe fn unregister_dtor(key: Key) -> bool { #[link_section = ".CRT$XLB"] #[linkage = "external"] #[allow(warnings)] -pub static p_thread_callback: unsafe extern "system" fn(LPVOID, DWORD, - LPVOID) = +pub static p_thread_callback: unsafe extern "system" fn(c::LPVOID, c::DWORD, + c::LPVOID) = on_tls_callback; #[allow(warnings)] -unsafe extern "system" fn on_tls_callback(h: LPVOID, - dwReason: DWORD, - pv: LPVOID) { - const DLL_THREAD_DETACH: DWORD = 3; - const DLL_PROCESS_DETACH: DWORD = 0; - if dwReason == DLL_THREAD_DETACH || dwReason == DLL_PROCESS_DETACH { +unsafe extern "system" fn on_tls_callback(h: c::LPVOID, + dwReason: c::DWORD, + pv: c::LPVOID) { + if dwReason == c::DLL_THREAD_DETACH || dwReason == c::DLL_PROCESS_DETACH { run_dtors(); } @@ -286,9 +275,9 @@ unsafe fn run_dtors() { ret }; for &(key, dtor) in &dtors { - let ptr = TlsGetValue(key); + let ptr = c::TlsGetValue(key); if !ptr.is_null() { - TlsSetValue(key, ptr::null_mut()); + c::TlsSetValue(key, ptr::null_mut()); dtor(ptr as *mut _); any_run = true; } diff --git a/src/libstd/sys/windows/time.rs b/src/libstd/sys/windows/time.rs index f5a70ccc90743..4dc7997d22e85 100644 --- a/src/libstd/sys/windows/time.rs +++ b/src/libstd/sys/windows/time.rs @@ -7,32 +7,33 @@ // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. -use libc; + use ops::Sub; -use time::Duration; use sync::Once; +use sys::c; +use time::Duration; const NANOS_PER_SEC: u64 = 1_000_000_000; pub struct SteadyTime { - t: libc::LARGE_INTEGER, + t: c::LARGE_INTEGER, } impl SteadyTime { pub fn now() -> SteadyTime { let mut t = SteadyTime { t: 0 }; - unsafe { libc::QueryPerformanceCounter(&mut t.t); } + unsafe { c::QueryPerformanceCounter(&mut t.t); } t } } -fn frequency() -> libc::LARGE_INTEGER { - static mut FREQUENCY: libc::LARGE_INTEGER = 0; +fn frequency() -> c::LARGE_INTEGER { + static mut FREQUENCY: c::LARGE_INTEGER = 0; static ONCE: Once = Once::new(); unsafe { ONCE.call_once(|| { - libc::QueryPerformanceFrequency(&mut FREQUENCY); + c::QueryPerformanceFrequency(&mut FREQUENCY); }); FREQUENCY } diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs index 9b8f63997b642..75e3a52feea65 100644 --- a/src/libstd/thread/mod.rs +++ b/src/libstd/thread/mod.rs @@ -390,6 +390,7 @@ pub fn catch_panic(f: F) -> Result /// this function will not return early due to a signal being received or a /// spurious wakeup. #[stable(feature = "rust1", since = "1.0.0")] +#[deprecated(since = "1.6.0", reason = "replaced by `std::thread::sleep`")] pub fn sleep_ms(ms: u32) { sleep(Duration::from_millis(ms as u64)) } @@ -456,6 +457,7 @@ pub fn park() { /// /// See the module doc for more detail. #[stable(feature = "rust1", since = "1.0.0")] +#[deprecated(since = "1.6.0", reason = "replaced by `std::thread::park_timeout`")] pub fn park_timeout_ms(ms: u32) { park_timeout(Duration::from_millis(ms as u64)) } diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index e56e49c4f4902..1f34af617d588 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -36,7 +36,6 @@ pub use self::Sign::*; pub use self::Stmt_::*; pub use self::StrStyle::*; pub use self::StructFieldKind::*; -pub use self::TokenTree::*; pub use self::TraitItem_::*; pub use self::Ty_::*; pub use self::TyParamBound::*; @@ -909,13 +908,15 @@ pub enum Expr_ { /// separately. `position` represents the index of the associated /// item qualified with this Self type. /// -/// as a::b::Trait>::AssociatedItem -/// ^~~~~ ~~~~~~~~~~~~~~^ -/// ty position = 3 +/// ```ignore +/// as a::b::Trait>::AssociatedItem +/// ^~~~~ ~~~~~~~~~~~~~~^ +/// ty position = 3 /// -/// >::AssociatedItem -/// ^~~~~ ^ -/// ty position = 0 +/// >::AssociatedItem +/// ^~~~~ ^ +/// ty position = 0 +/// ``` #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub struct QSelf { pub ty: P, @@ -954,12 +955,12 @@ impl Delimited { /// Returns the opening delimiter as a token tree. pub fn open_tt(&self) -> TokenTree { - TtToken(self.open_span, self.open_token()) + TokenTree::Token(self.open_span, self.open_token()) } /// Returns the closing delimiter as a token tree. pub fn close_tt(&self) -> TokenTree { - TtToken(self.close_span, self.close_token()) + TokenTree::Token(self.close_span, self.close_token()) } } @@ -999,61 +1000,61 @@ pub enum KleeneOp { #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub enum TokenTree { /// A single token - TtToken(Span, token::Token), + Token(Span, token::Token), /// A delimited sequence of token trees - TtDelimited(Span, Rc), + Delimited(Span, Rc), // This only makes sense in MBE macros. /// A kleene-style repetition sequence with a span // FIXME(eddyb) #12938 Use DST. - TtSequence(Span, Rc), + Sequence(Span, Rc), } impl TokenTree { pub fn len(&self) -> usize { match *self { - TtToken(_, token::DocComment(name)) => { + TokenTree::Token(_, token::DocComment(name)) => { match doc_comment_style(&name.as_str()) { AttrStyle::Outer => 2, AttrStyle::Inner => 3 } } - TtToken(_, token::SpecialVarNt(..)) => 2, - TtToken(_, token::MatchNt(..)) => 3, - TtDelimited(_, ref delimed) => { + TokenTree::Token(_, token::SpecialVarNt(..)) => 2, + TokenTree::Token(_, token::MatchNt(..)) => 3, + TokenTree::Delimited(_, ref delimed) => { delimed.tts.len() + 2 } - TtSequence(_, ref seq) => { + TokenTree::Sequence(_, ref seq) => { seq.tts.len() } - TtToken(..) => 0 + TokenTree::Token(..) => 0 } } pub fn get_tt(&self, index: usize) -> TokenTree { match (self, index) { - (&TtToken(sp, token::DocComment(_)), 0) => { - TtToken(sp, token::Pound) + (&TokenTree::Token(sp, token::DocComment(_)), 0) => { + TokenTree::Token(sp, token::Pound) } - (&TtToken(sp, token::DocComment(name)), 1) + (&TokenTree::Token(sp, token::DocComment(name)), 1) if doc_comment_style(&name.as_str()) == AttrStyle::Inner => { - TtToken(sp, token::Not) + TokenTree::Token(sp, token::Not) } - (&TtToken(sp, token::DocComment(name)), _) => { + (&TokenTree::Token(sp, token::DocComment(name)), _) => { let stripped = strip_doc_comment_decoration(&name.as_str()); - TtDelimited(sp, Rc::new(Delimited { + TokenTree::Delimited(sp, Rc::new(Delimited { delim: token::Bracket, open_span: sp, - tts: vec![TtToken(sp, token::Ident(token::str_to_ident("doc"), - token::Plain)), - TtToken(sp, token::Eq), - TtToken(sp, token::Literal( + tts: vec![TokenTree::Token(sp, token::Ident(token::str_to_ident("doc"), + token::Plain)), + TokenTree::Token(sp, token::Eq), + TokenTree::Token(sp, token::Literal( token::StrRaw(token::intern(&stripped), 0), None))], close_span: sp, })) } - (&TtDelimited(_, ref delimed), _) => { + (&TokenTree::Delimited(_, ref delimed), _) => { if index == 0 { return delimed.open_tt(); } @@ -1062,19 +1063,19 @@ impl TokenTree { } delimed.tts[index - 1].clone() } - (&TtToken(sp, token::SpecialVarNt(var)), _) => { - let v = [TtToken(sp, token::Dollar), - TtToken(sp, token::Ident(token::str_to_ident(var.as_str()), + (&TokenTree::Token(sp, token::SpecialVarNt(var)), _) => { + let v = [TokenTree::Token(sp, token::Dollar), + TokenTree::Token(sp, token::Ident(token::str_to_ident(var.as_str()), token::Plain))]; v[index].clone() } - (&TtToken(sp, token::MatchNt(name, kind, name_st, kind_st)), _) => { - let v = [TtToken(sp, token::SubstNt(name, name_st)), - TtToken(sp, token::Colon), - TtToken(sp, token::Ident(kind, kind_st))]; + (&TokenTree::Token(sp, token::MatchNt(name, kind, name_st, kind_st)), _) => { + let v = [TokenTree::Token(sp, token::SubstNt(name, name_st)), + TokenTree::Token(sp, token::Colon), + TokenTree::Token(sp, token::Ident(kind, kind_st))]; v[index].clone() } - (&TtSequence(_, ref seq), _) => { + (&TokenTree::Sequence(_, ref seq), _) => { seq.tts[index].clone() } _ => panic!("Cannot expand a token tree") @@ -1084,9 +1085,9 @@ impl TokenTree { /// Returns the `Span` corresponding to this token tree. pub fn get_span(&self) -> Span { match *self { - TtToken(span, _) => span, - TtDelimited(span, _) => span, - TtSequence(span, _) => span, + TokenTree::Token(span, _) => span, + TokenTree::Delimited(span, _) => span, + TokenTree::Sequence(span, _) => span, } } diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs index eeb832d48b0d8..571f950643792 100644 --- a/src/libsyntax/attr.rs +++ b/src/libsyntax/attr.rs @@ -67,7 +67,7 @@ pub trait AttrMetaMethods { /// containing a string, otherwise None. fn value_str(&self) -> Option; /// Gets a list of inner meta items from a list MetaItem type. - fn meta_item_list<'a>(&'a self) -> Option<&'a [P]>; + fn meta_item_list(&self) -> Option<&[P]>; fn span(&self) -> Span; } @@ -84,7 +84,7 @@ impl AttrMetaMethods for Attribute { fn value_str(&self) -> Option { self.meta().value_str() } - fn meta_item_list<'a>(&'a self) -> Option<&'a [P]> { + fn meta_item_list(&self) -> Option<&[P]> { self.node.value.meta_item_list() } fn span(&self) -> Span { self.meta().span } @@ -111,7 +111,7 @@ impl AttrMetaMethods for MetaItem { } } - fn meta_item_list<'a>(&'a self) -> Option<&'a [P]> { + fn meta_item_list(&self) -> Option<&[P]> { match self.node { MetaList(_, ref l) => Some(&l[..]), _ => None @@ -124,7 +124,7 @@ impl AttrMetaMethods for MetaItem { impl AttrMetaMethods for P { fn name(&self) -> InternedString { (**self).name() } fn value_str(&self) -> Option { (**self).value_str() } - fn meta_item_list<'a>(&'a self) -> Option<&'a [P]> { + fn meta_item_list(&self) -> Option<&[P]> { (**self).meta_item_list() } fn span(&self) -> Span { (**self).span() } @@ -132,14 +132,14 @@ impl AttrMetaMethods for P { pub trait AttributeMethods { - fn meta<'a>(&'a self) -> &'a MetaItem; + fn meta(&self) -> &MetaItem; fn with_desugared_doc(&self, f: F) -> T where F: FnOnce(&Attribute) -> T; } impl AttributeMethods for Attribute { /// Extract the MetaItem from inside this Attribute. - fn meta<'a>(&'a self) -> &'a MetaItem { + fn meta(&self) -> &MetaItem { &*self.node.value } diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs index a73fd4534c96c..db011265c7379 100644 --- a/src/libsyntax/codemap.rs +++ b/src/libsyntax/codemap.rs @@ -559,6 +559,10 @@ impl FileMap { pub fn is_imported(&self) -> bool { self.src.is_none() } + + fn count_lines(&self) -> usize { + self.lines.borrow().len() + } } /// An abstraction over the fs operations used by the Parser. @@ -1021,6 +1025,10 @@ impl CodeMap { debug!("span_allows_unstable? {}", allows_unstable); allows_unstable } + + pub fn count_lines(&self) -> usize { + self.files.borrow().iter().fold(0, |a, f| a + f.count_lines()) + } } // _____________________________________________________________________________ diff --git a/src/libsyntax/config.rs b/src/libsyntax/config.rs index aa674bdbcf3a4..10731178c0610 100644 --- a/src/libsyntax/config.rs +++ b/src/libsyntax/config.rs @@ -86,7 +86,7 @@ fn filter_foreign_item(cx: &mut Context, -> Option> where F: FnMut(&[ast::Attribute]) -> bool { - if foreign_item_in_cfg(cx, &*item) { + if foreign_item_in_cfg(cx, &item) { Some(item) } else { None @@ -109,7 +109,7 @@ fn fold_foreign_mod(cx: &mut Context, fn fold_item(cx: &mut Context, item: P) -> SmallVector> where F: FnMut(&[ast::Attribute]) -> bool { - if item_in_cfg(cx, &*item) { + if item_in_cfg(cx, &item) { SmallVector::one(item.map(|i| cx.fold_item_simple(i))) } else { SmallVector::zero() @@ -189,7 +189,7 @@ fn retain_stmt(cx: &mut Context, stmt: &ast::Stmt) -> bool where ast::StmtDecl(ref decl, _) => { match decl.node { ast::DeclItem(ref item) => { - item_in_cfg(cx, &**item) + item_in_cfg(cx, item) } _ => true } @@ -203,7 +203,7 @@ fn fold_block(cx: &mut Context, b: P) -> P where { b.map(|ast::Block {id, stmts, expr, rules, span}| { let resulting_stmts: Vec> = - stmts.into_iter().filter(|a| retain_stmt(cx, &**a)).collect(); + stmts.into_iter().filter(|a| retain_stmt(cx, a)).collect(); let resulting_stmts = resulting_stmts.into_iter() .flat_map(|stmt| cx.fold_stmt(stmt).into_iter()) .collect(); @@ -263,7 +263,7 @@ fn in_cfg(diagnostic: &SpanHandler, cfg: &[P], attrs: &[ast::Attr return true; } - attr::cfg_matches(diagnostic, cfg, &*mis[0], + attr::cfg_matches(diagnostic, cfg, &mis[0], feature_gated_cfgs) }) } diff --git a/src/libsyntax/diagnostic.rs b/src/libsyntax/diagnostic.rs index 2b34db3f6eafb..f1fd8be472830 100644 --- a/src/libsyntax/diagnostic.rs +++ b/src/libsyntax/diagnostic.rs @@ -21,7 +21,6 @@ use std::{cmp, error, fmt}; use std::io::prelude::*; use std::io; use term::{self, WriterWrapper}; -use libc; /// maximum number of lines we will print for each error; arbitrary. const MAX_LINES: usize = 6; @@ -767,15 +766,19 @@ impl EmitterWriter { #[cfg(unix)] fn stderr_isatty() -> bool { + use libc; unsafe { libc::isatty(libc::STDERR_FILENO) != 0 } } #[cfg(windows)] fn stderr_isatty() -> bool { - const STD_ERROR_HANDLE: libc::DWORD = -12i32 as libc::DWORD; + type DWORD = u32; + type BOOL = i32; + type HANDLE = *mut u8; + const STD_ERROR_HANDLE: DWORD = -12i32 as DWORD; extern "system" { - fn GetStdHandle(which: libc::DWORD) -> libc::HANDLE; - fn GetConsoleMode(hConsoleHandle: libc::HANDLE, - lpMode: libc::LPDWORD) -> libc::BOOL; + fn GetStdHandle(which: DWORD) -> HANDLE; + fn GetConsoleMode(hConsoleHandle: HANDLE, + lpMode: *mut DWORD) -> BOOL; } unsafe { let handle = GetStdHandle(STD_ERROR_HANDLE); diff --git a/src/libsyntax/diagnostics/plugin.rs b/src/libsyntax/diagnostics/plugin.rs index a276765e21616..be0d5729c7009 100644 --- a/src/libsyntax/diagnostics/plugin.rs +++ b/src/libsyntax/diagnostics/plugin.rs @@ -54,7 +54,7 @@ pub fn expand_diagnostic_used<'cx>(ecx: &'cx mut ExtCtxt, token_tree: &[TokenTree]) -> Box { let code = match (token_tree.len(), token_tree.get(0)) { - (1, Some(&ast::TtToken(_, token::Ident(code, _)))) => code, + (1, Some(&TokenTree::Token(_, token::Ident(code, _)))) => code, _ => unreachable!() }; @@ -92,12 +92,12 @@ pub fn expand_register_diagnostic<'cx>(ecx: &'cx mut ExtCtxt, token_tree.get(1), token_tree.get(2) ) { - (1, Some(&ast::TtToken(_, token::Ident(ref code, _))), None, None) => { + (1, Some(&TokenTree::Token(_, token::Ident(ref code, _))), None, None) => { (code, None) }, - (3, Some(&ast::TtToken(_, token::Ident(ref code, _))), - Some(&ast::TtToken(_, token::Comma)), - Some(&ast::TtToken(_, token::Literal(token::StrRaw(description, _), None)))) => { + (3, Some(&TokenTree::Token(_, token::Ident(ref code, _))), + Some(&TokenTree::Token(_, token::Comma)), + Some(&TokenTree::Token(_, token::Literal(token::StrRaw(description, _), None)))) => { (code, Some(description)) } _ => unreachable!() @@ -160,9 +160,9 @@ pub fn expand_build_diagnostic_array<'cx>(ecx: &'cx mut ExtCtxt, let (crate_name, name) = match (&token_tree[0], &token_tree[2]) { ( // Crate name. - &ast::TtToken(_, token::Ident(ref crate_name, _)), + &TokenTree::Token(_, token::Ident(ref crate_name, _)), // DIAGNOSTICS ident. - &ast::TtToken(_, token::Ident(ref name, _)) + &TokenTree::Token(_, token::Ident(ref name, _)) ) => (*&crate_name, name), _ => unreachable!() }; diff --git a/src/libsyntax/ext/asm.rs b/src/libsyntax/ext/asm.rs index 984e73f85f610..ac18b9c0e4940 100644 --- a/src/libsyntax/ext/asm.rs +++ b/src/libsyntax/ext/asm.rs @@ -79,7 +79,7 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) cx.span_err(sp, "malformed inline assembly"); return DummyResult::expr(sp); } - let (s, style) = match expr_to_string(cx, panictry!(p.parse_expr_nopanic()), + let (s, style) = match expr_to_string(cx, panictry!(p.parse_expr()), "inline assembly must be a string literal") { Some((s, st)) => (s, st), // let compilation continue @@ -102,7 +102,7 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) let span = p.last_span; panictry!(p.expect(&token::OpenDelim(token::Paren))); - let out = panictry!(p.parse_expr_nopanic()); + let out = panictry!(p.parse_expr()); panictry!(p.expect(&token::CloseDelim(token::Paren))); // Expands a read+write operand into two operands. @@ -139,14 +139,14 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) let (constraint, _str_style) = panictry!(p.parse_str()); - if constraint.starts_with("=") { + if constraint.starts_with("=") && !constraint.contains("*") { cx.span_err(p.last_span, "input operand constraint contains '='"); - } else if constraint.starts_with("+") { + } else if constraint.starts_with("+") && !constraint.contains("*") { cx.span_err(p.last_span, "input operand constraint contains '+'"); } panictry!(p.expect(&token::OpenDelim(token::Paren))); - let input = panictry!(p.parse_expr_nopanic()); + let input = panictry!(p.parse_expr()); panictry!(p.expect(&token::CloseDelim(token::Paren))); inputs.push((constraint, input)); diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index e0ef8701cdff9..18db028b60b4c 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -512,6 +512,18 @@ fn initial_syntax_expander_table<'feat>(ecfg: &expand::ExpansionConfig<'feat>) syntax_expanders.insert(intern("quote_attr"), builtin_normal_expander( ext::quote::expand_quote_attr)); + syntax_expanders.insert(intern("quote_arg"), + builtin_normal_expander( + ext::quote::expand_quote_arg)); + syntax_expanders.insert(intern("quote_block"), + builtin_normal_expander( + ext::quote::expand_quote_block)); + syntax_expanders.insert(intern("quote_meta_item"), + builtin_normal_expander( + ext::quote::expand_quote_meta_item)); + syntax_expanders.insert(intern("quote_path"), + builtin_normal_expander( + ext::quote::expand_quote_path)); } syntax_expanders.insert(intern("line"), @@ -809,7 +821,7 @@ pub fn get_single_str_from_tts(cx: &mut ExtCtxt, cx.span_err(sp, &format!("{} takes 1 argument", name)); return None } - let ret = cx.expander().fold_expr(panictry!(p.parse_expr_nopanic())); + let ret = cx.expander().fold_expr(panictry!(p.parse_expr())); if p.token != token::Eof { cx.span_err(sp, &format!("{} takes 1 argument", name)); } @@ -826,7 +838,7 @@ pub fn get_exprs_from_tts(cx: &mut ExtCtxt, let mut p = cx.new_parser_from_tts(tts); let mut es = Vec::new(); while p.token != token::Eof { - es.push(cx.expander().fold_expr(panictry!(p.parse_expr_nopanic()))); + es.push(cx.expander().fold_expr(panictry!(p.parse_expr()))); if panictry!(p.eat(&token::Comma)){ continue; } @@ -881,7 +893,7 @@ impl SyntaxEnv { self.chain.pop(); } - fn find_escape_frame<'a>(&'a mut self) -> &'a mut MapChainFrame { + fn find_escape_frame(&mut self) -> &mut MapChainFrame { for (i, frame) in self.chain.iter_mut().enumerate().rev() { if !frame.info.macros_escape || i == 0 { return frame @@ -904,7 +916,7 @@ impl SyntaxEnv { self.find_escape_frame().map.insert(k, Rc::new(v)); } - pub fn info<'a>(&'a mut self) -> &'a mut BlockInfo { + pub fn info(&mut self) -> &mut BlockInfo { let last_chain_index = self.chain.len() - 1; &mut self.chain[last_chain_index].info } diff --git a/src/libsyntax/ext/cfg.rs b/src/libsyntax/ext/cfg.rs index d354a4ae21527..48199026204c8 100644 --- a/src/libsyntax/ext/cfg.rs +++ b/src/libsyntax/ext/cfg.rs @@ -33,7 +33,7 @@ pub fn expand_cfg<'cx>(cx: &mut ExtCtxt, return DummyResult::expr(sp); } - let matches_cfg = attr::cfg_matches(&cx.parse_sess.span_diagnostic, &cx.cfg, &*cfg, + let matches_cfg = attr::cfg_matches(&cx.parse_sess.span_diagnostic, &cx.cfg, &cfg, cx.feature_gated_cfgs); MacEager::expr(cx.expr_bool(sp, matches_cfg)) } diff --git a/src/libsyntax/ext/concat_idents.rs b/src/libsyntax/ext/concat_idents.rs index c31a767300cf4..e9e36546ad6db 100644 --- a/src/libsyntax/ext/concat_idents.rs +++ b/src/libsyntax/ext/concat_idents.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use ast; +use ast::{self, TokenTree}; use codemap::Span; use ext::base::*; use ext::base; @@ -17,7 +17,7 @@ use parse::token; use parse::token::str_to_ident; use ptr::P; -pub fn expand_syntax_ext<'cx>(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) +pub fn expand_syntax_ext<'cx>(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree]) -> Box { if !cx.ecfg.enable_concat_idents() { feature_gate::emit_feature_err(&cx.parse_sess.span_diagnostic, @@ -32,7 +32,7 @@ pub fn expand_syntax_ext<'cx>(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree] for (i, e) in tts.iter().enumerate() { if i & 1 == 1 { match *e { - ast::TtToken(_, token::Comma) => {}, + TokenTree::Token(_, token::Comma) => {}, _ => { cx.span_err(sp, "concat_idents! expecting comma."); return DummyResult::expr(sp); @@ -40,7 +40,7 @@ pub fn expand_syntax_ext<'cx>(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree] } } else { match *e { - ast::TtToken(_, token::Ident(ident, _)) => { + TokenTree::Token(_, token::Ident(ident, _)) => { res_str.push_str(&ident.name.as_str()) }, _ => { diff --git a/src/libsyntax/ext/deriving/debug.rs b/src/libsyntax/ext/deriving/debug.rs index 537375f70845d..2b2e530988387 100644 --- a/src/libsyntax/ext/deriving/debug.rs +++ b/src/libsyntax/ext/deriving/debug.rs @@ -9,8 +9,8 @@ // except according to those terms. use ast; -use ast::{MetaItem, Expr,}; -use codemap::Span; +use ast::{MetaItem, Expr}; +use codemap::{Span, respan}; use ext::base::{ExtCtxt, Annotatable}; use ext::build::AstBuilder; use ext::deriving::generic::*; @@ -72,34 +72,43 @@ fn show_substructure(cx: &mut ExtCtxt, span: Span, let span = Span { expn_id: cx.backtrace(), .. span }; let name = cx.expr_lit(span, ast::Lit_::LitStr(ident.name.as_str(), ast::StrStyle::CookedStr)); - let mut expr = substr.nonself_args[0].clone(); + let builder = token::str_to_ident("builder"); + let builder_expr = cx.expr_ident(span, builder.clone()); - match *substr.fields { - Struct(ref fields) | EnumMatching(_, _, ref fields) => { + let fmt = substr.nonself_args[0].clone(); + let stmts = match *substr.fields { + Struct(ref fields) | EnumMatching(_, _, ref fields) => { + let mut stmts = vec![]; if fields.is_empty() || fields[0].name.is_none() { // tuple struct/"normal" variant - expr = cx.expr_method_call(span, - expr, - token::str_to_ident("debug_tuple"), - vec![name]); + let expr = cx.expr_method_call(span, + fmt, + token::str_to_ident("debug_tuple"), + vec![name]); + stmts.push(cx.stmt_let(span, true, builder, expr)); for field in fields { // Use double indirection to make sure this works for unsized types let field = cx.expr_addr_of(field.span, field.self_.clone()); let field = cx.expr_addr_of(field.span, field); - expr = cx.expr_method_call(span, - expr, - token::str_to_ident("field"), - vec![field]); + let expr = cx.expr_method_call(span, + builder_expr.clone(), + token::str_to_ident("field"), + vec![field]); + + // Use `let _ = expr;` to avoid triggering the + // unused_results lint. + stmts.push(stmt_let_undescore(cx, span, expr)); } } else { // normal struct/struct variant - expr = cx.expr_method_call(span, - expr, - token::str_to_ident("debug_struct"), - vec![name]); + let expr = cx.expr_method_call(span, + fmt, + token::str_to_ident("debug_struct"), + vec![name]); + stmts.push(cx.stmt_let(span, true, builder, expr)); for field in fields { let name = cx.expr_lit(field.span, ast::Lit_::LitStr( @@ -109,18 +118,37 @@ fn show_substructure(cx: &mut ExtCtxt, span: Span, // Use double indirection to make sure this works for unsized types let field = cx.expr_addr_of(field.span, field.self_.clone()); let field = cx.expr_addr_of(field.span, field); - expr = cx.expr_method_call(span, - expr, - token::str_to_ident("field"), - vec![name, field]); + let expr = cx.expr_method_call(span, + builder_expr.clone(), + token::str_to_ident("field"), + vec![name, field]); + stmts.push(stmt_let_undescore(cx, span, expr)); } } + stmts } _ => unreachable!() - } + }; + + let expr = cx.expr_method_call(span, + builder_expr, + token::str_to_ident("finish"), + vec![]); + + let block = cx.block(span, stmts, Some(expr)); + cx.expr_block(block) +} - cx.expr_method_call(span, - expr, - token::str_to_ident("finish"), - vec![]) +fn stmt_let_undescore(cx: &mut ExtCtxt, + sp: Span, + expr: P) -> P { + let local = P(ast::Local { + pat: cx.pat_wild(sp), + ty: None, + init: Some(expr), + id: ast::DUMMY_NODE_ID, + span: sp, + }); + let decl = respan(sp, ast::DeclLocal(local)); + P(respan(sp, ast::StmtDecl(P(decl), ast::DUMMY_NODE_ID))) } diff --git a/src/libsyntax/ext/deriving/generic/mod.rs b/src/libsyntax/ext/deriving/generic/mod.rs index 5c6e2fce8adce..5a0fc4fda0cca 100644 --- a/src/libsyntax/ext/deriving/generic/mod.rs +++ b/src/libsyntax/ext/deriving/generic/mod.rs @@ -54,6 +54,7 @@ //! following snippet //! //! ```rust +//! # #![allow(dead_code)] //! struct A { x : i32 } //! //! struct B(i32); @@ -88,7 +89,7 @@ //! //! ```rust //! trait PartialEq { -//! fn eq(&self, other: &Self); +//! fn eq(&self, other: &Self) -> bool; //! } //! impl PartialEq for i32 { //! fn eq(&self, other: &i32) -> bool { @@ -905,7 +906,7 @@ impl<'a> MethodDef<'a> { }) } - /// ``` + /// ```ignore /// #[derive(PartialEq)] /// struct A { x: i32, y: i32 } /// @@ -1010,7 +1011,7 @@ impl<'a> MethodDef<'a> { &StaticStruct(struct_def, summary)) } - /// ``` + /// ```ignore /// #[derive(PartialEq)] /// enum A { /// A1, @@ -1596,7 +1597,7 @@ pub fn cs_fold(use_foldl: bool, /// Call the method that is being derived on all the fields, and then /// process the collected results. i.e. /// -/// ``` +/// ```ignore /// f(cx, span, vec![self_1.method(__arg_1_1, __arg_2_1), /// self_2.method(__arg_1_2, __arg_2_2)]) /// ``` diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index b1b4605d5ec65..ba07c452e2a59 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -400,9 +400,7 @@ pub fn expand_item_mac(it: P, } MacroRulesTT => { if ident.name == parse::token::special_idents::invalid.name { - fld.cx.span_err(path_span, - &format!("macro_rules! expects an ident argument") - ); + fld.cx.span_err(path_span, "macro_rules! expects an ident argument"); return SmallVector::zero(); } @@ -549,7 +547,7 @@ fn expand_non_macro_stmt(Spanned {node, span: stmt_span}: Stmt, fld: &mut MacroE // names, as well... but that should be okay, as long as // the new names are gensyms for the old ones. // generate fresh names, push them to a new pending list - let idents = pattern_bindings(&*expanded_pat); + let idents = pattern_bindings(&expanded_pat); let mut new_pending_renames = idents.iter().map(|ident| (*ident, fresh_name(*ident))).collect(); // rewrite the pattern using the new names (the old @@ -636,7 +634,7 @@ fn rename_in_scope(pats: Vec>, { // all of the pats must have the same set of bindings, so use the // first one to extract them and generate new names: - let idents = pattern_bindings(&*pats[0]); + let idents = pattern_bindings(&pats[0]); let new_renames = idents.into_iter().map(|id| (id, fresh_name(id))).collect(); // apply the renaming, but only to the PatIdents: let mut rename_pats_fld = PatIdentRenamer{renames:&new_renames}; @@ -661,7 +659,7 @@ impl<'v> Visitor<'v> for PatIdentFinder { self.ident_accumulator.push(path1.node); // visit optional subpattern of PatIdent: if let Some(ref subpat) = *inner { - self.visit_pat(&**subpat) + self.visit_pat(subpat) } } // use the default traversal for non-PatIdents @@ -681,7 +679,7 @@ fn pattern_bindings(pat: &ast::Pat) -> Vec { fn fn_decl_arg_bindings(fn_decl: &ast::FnDecl) -> Vec { let mut pat_idents = PatIdentFinder{ident_accumulator:Vec::new()}; for arg in &fn_decl.inputs { - pat_idents.visit_pat(&*arg.pat); + pat_idents.visit_pat(&arg.pat); } pat_idents.ident_accumulator } @@ -1080,7 +1078,7 @@ fn expand_and_rename_fn_decl_and_block(fn_decl: P, block: P (P, P) { let expanded_decl = fld.fold_fn_decl(fn_decl); - let idents = fn_decl_arg_bindings(&*expanded_decl); + let idents = fn_decl_arg_bindings(&expanded_decl); let renames = idents.iter().map(|id| (*id,fresh_name(*id))).collect(); // first, a renamer for the PatIdents, for the fn_decl: @@ -1809,7 +1807,7 @@ foo_module!(); fn pat_idents(){ let pat = string_to_pat( "(a,Foo{x:c @ (b,9),y:Bar(4,d)})".to_string()); - let idents = pattern_bindings(&*pat); + let idents = pattern_bindings(&pat); assert_eq!(idents, strs_to_idents(vec!("a","c","b","d"))); } diff --git a/src/libsyntax/ext/format.rs b/src/libsyntax/ext/format.rs index c56342371c84e..904cf0c47768e 100644 --- a/src/libsyntax/ext/format.rs +++ b/src/libsyntax/ext/format.rs @@ -77,9 +77,10 @@ struct Context<'a, 'b:'a> { /// expressions. /// /// If parsing succeeds, the return value is: -/// -/// Some((fmtstr, unnamed arguments, ordering of named arguments, -/// named arguments)) +/// ```ignore +/// Some((fmtstr, unnamed arguments, ordering of named arguments, +/// named arguments)) +/// ``` fn parse_args(ecx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) -> Option<(P, Vec>, Vec, HashMap>)> { @@ -93,7 +94,7 @@ fn parse_args(ecx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) ecx.span_err(sp, "requires at least a format string argument"); return None; } - let fmtstr = panictry!(p.parse_expr_nopanic()); + let fmtstr = panictry!(p.parse_expr()); let mut named = false; while p.token != token::Eof { if !panictry!(p.eat(&token::Comma)) { @@ -124,7 +125,7 @@ fn parse_args(ecx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) let name: &str = &ident.name.as_str(); panictry!(p.expect(&token::Eq)); - let e = panictry!(p.parse_expr_nopanic()); + let e = panictry!(p.parse_expr()); match names.get(name) { None => {} Some(prev) => { @@ -138,7 +139,7 @@ fn parse_args(ecx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) order.push(name.to_string()); names.insert(name.to_string(), e); } else { - args.push(panictry!(p.parse_expr_nopanic())); + args.push(panictry!(p.parse_expr())); } } Some((fmtstr, args, order, names)) diff --git a/src/libsyntax/ext/quote.rs b/src/libsyntax/ext/quote.rs index 59e8533a83d31..d743a601bbb4b 100644 --- a/src/libsyntax/ext/quote.rs +++ b/src/libsyntax/ext/quote.rs @@ -8,11 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use ast; +use ast::{self, Arg, Arm, Block, Expr, Item, Pat, Path, Stmt, TokenTree, Ty}; use codemap::Span; use ext::base::ExtCtxt; use ext::base; use ext::build::AstBuilder; +use parse::parser::{Parser, PathParsingMode}; use parse::token::*; use parse::token; use ptr::P; @@ -71,67 +72,69 @@ pub mod rt { impl ToTokens for ast::Ident { fn to_tokens(&self, _cx: &ExtCtxt) -> Vec { - vec![ast::TtToken(DUMMY_SP, token::Ident(*self, token::Plain))] + vec![TokenTree::Token(DUMMY_SP, token::Ident(*self, token::Plain))] } } impl ToTokens for ast::Path { fn to_tokens(&self, _cx: &ExtCtxt) -> Vec { - vec![ast::TtToken(DUMMY_SP, token::Interpolated(token::NtPath(Box::new(self.clone()))))] + vec![TokenTree::Token(DUMMY_SP, + token::Interpolated(token::NtPath(Box::new(self.clone()))))] } } impl ToTokens for ast::Ty { fn to_tokens(&self, _cx: &ExtCtxt) -> Vec { - vec![ast::TtToken(self.span, token::Interpolated(token::NtTy(P(self.clone()))))] + vec![TokenTree::Token(self.span, token::Interpolated(token::NtTy(P(self.clone()))))] } } impl ToTokens for ast::Block { fn to_tokens(&self, _cx: &ExtCtxt) -> Vec { - vec![ast::TtToken(self.span, token::Interpolated(token::NtBlock(P(self.clone()))))] + vec![TokenTree::Token(self.span, token::Interpolated(token::NtBlock(P(self.clone()))))] } } impl ToTokens for ast::Generics { fn to_tokens(&self, _cx: &ExtCtxt) -> Vec { - vec![ast::TtToken(DUMMY_SP, token::Interpolated(token::NtGenerics(self.clone())))] + vec![TokenTree::Token(DUMMY_SP, token::Interpolated(token::NtGenerics(self.clone())))] } } impl ToTokens for ast::WhereClause { fn to_tokens(&self, _cx: &ExtCtxt) -> Vec { - vec![ast::TtToken(DUMMY_SP, token::Interpolated(token::NtWhereClause(self.clone())))] + vec![TokenTree::Token(DUMMY_SP, + token::Interpolated(token::NtWhereClause(self.clone())))] } } impl ToTokens for P { fn to_tokens(&self, _cx: &ExtCtxt) -> Vec { - vec![ast::TtToken(self.span, token::Interpolated(token::NtItem(self.clone())))] + vec![TokenTree::Token(self.span, token::Interpolated(token::NtItem(self.clone())))] } } impl ToTokens for P { fn to_tokens(&self, _cx: &ExtCtxt) -> Vec { - vec![ast::TtToken(self.span, token::Interpolated(token::NtImplItem(self.clone())))] + vec![TokenTree::Token(self.span, token::Interpolated(token::NtImplItem(self.clone())))] } } impl ToTokens for P { fn to_tokens(&self, _cx: &ExtCtxt) -> Vec { - vec![ast::TtToken(self.span, token::Interpolated(token::NtTraitItem(self.clone())))] + vec![TokenTree::Token(self.span, token::Interpolated(token::NtTraitItem(self.clone())))] } } impl ToTokens for P { fn to_tokens(&self, _cx: &ExtCtxt) -> Vec { let mut tts = vec![ - ast::TtToken(self.span, token::Interpolated(token::NtStmt(self.clone()))) + TokenTree::Token(self.span, token::Interpolated(token::NtStmt(self.clone()))) ]; // Some statements require a trailing semicolon. if classify::stmt_ends_with_semi(&self.node) { - tts.push(ast::TtToken(self.span, token::Semi)); + tts.push(TokenTree::Token(self.span, token::Semi)); } tts @@ -140,19 +143,31 @@ pub mod rt { impl ToTokens for P { fn to_tokens(&self, _cx: &ExtCtxt) -> Vec { - vec![ast::TtToken(self.span, token::Interpolated(token::NtExpr(self.clone())))] + vec![TokenTree::Token(self.span, token::Interpolated(token::NtExpr(self.clone())))] } } impl ToTokens for P { fn to_tokens(&self, _cx: &ExtCtxt) -> Vec { - vec![ast::TtToken(self.span, token::Interpolated(token::NtPat(self.clone())))] + vec![TokenTree::Token(self.span, token::Interpolated(token::NtPat(self.clone())))] } } impl ToTokens for ast::Arm { fn to_tokens(&self, _cx: &ExtCtxt) -> Vec { - vec![ast::TtToken(DUMMY_SP, token::Interpolated(token::NtArm(self.clone())))] + vec![TokenTree::Token(DUMMY_SP, token::Interpolated(token::NtArm(self.clone())))] + } + } + + impl ToTokens for ast::Arg { + fn to_tokens(&self, _cx: &ExtCtxt) -> Vec { + vec![TokenTree::Token(DUMMY_SP, token::Interpolated(token::NtArg(self.clone())))] + } + } + + impl ToTokens for P { + fn to_tokens(&self, _cx: &ExtCtxt) -> Vec { + vec![TokenTree::Token(DUMMY_SP, token::Interpolated(token::NtBlock(self.clone())))] } } @@ -173,12 +188,13 @@ pub mod rt { }; } - impl_to_tokens_slice! { ast::Ty, [ast::TtToken(DUMMY_SP, token::Comma)] } + impl_to_tokens_slice! { ast::Ty, [TokenTree::Token(DUMMY_SP, token::Comma)] } impl_to_tokens_slice! { P, [] } + impl_to_tokens_slice! { ast::Arg, [TokenTree::Token(DUMMY_SP, token::Comma)] } impl ToTokens for P { fn to_tokens(&self, _cx: &ExtCtxt) -> Vec { - vec![ast::TtToken(DUMMY_SP, token::Interpolated(token::NtMeta(self.clone())))] + vec![TokenTree::Token(DUMMY_SP, token::Interpolated(token::NtMeta(self.clone())))] } } @@ -186,11 +202,11 @@ pub mod rt { fn to_tokens(&self, cx: &ExtCtxt) -> Vec { let mut r = vec![]; // FIXME: The spans could be better - r.push(ast::TtToken(self.span, token::Pound)); + r.push(TokenTree::Token(self.span, token::Pound)); if self.node.style == ast::AttrStyle::Inner { - r.push(ast::TtToken(self.span, token::Not)); + r.push(TokenTree::Token(self.span, token::Not)); } - r.push(ast::TtDelimited(self.span, Rc::new(ast::Delimited { + r.push(TokenTree::Delimited(self.span, Rc::new(ast::Delimited { delim: token::Bracket, open_span: self.span, tts: self.node.value.to_tokens(cx), @@ -210,7 +226,7 @@ pub mod rt { impl ToTokens for () { fn to_tokens(&self, _cx: &ExtCtxt) -> Vec { - vec![ast::TtDelimited(DUMMY_SP, Rc::new(ast::Delimited { + vec![TokenTree::Delimited(DUMMY_SP, Rc::new(ast::Delimited { delim: token::Paren, open_span: DUMMY_SP, tts: vec![], @@ -278,7 +294,7 @@ pub mod rt { fn parse_item(&self, s: String) -> P; fn parse_expr(&self, s: String) -> P; fn parse_stmt(&self, s: String) -> P; - fn parse_tts(&self, s: String) -> Vec; + fn parse_tts(&self, s: String) -> Vec; } impl<'a> ExtParseUtils for ExtCtxt<'a> { @@ -305,7 +321,7 @@ pub mod rt { self.parse_sess()) } - fn parse_tts(&self, s: String) -> Vec { + fn parse_tts(&self, s: String) -> Vec { parse::parse_tts_from_source_str("".to_string(), s, self.cfg(), @@ -314,9 +330,55 @@ pub mod rt { } } +// These panicking parsing functions are used by the quote_*!() syntax extensions, +// but shouldn't be used otherwise. +pub fn parse_expr_panic(parser: &mut Parser) -> P { + panictry!(parser.parse_expr()) +} + +pub fn parse_item_panic(parser: &mut Parser) -> Option> { + panictry!(parser.parse_item()) +} + +pub fn parse_pat_panic(parser: &mut Parser) -> P { + panictry!(parser.parse_pat()) +} + +pub fn parse_arm_panic(parser: &mut Parser) -> Arm { + panictry!(parser.parse_arm()) +} + +pub fn parse_ty_panic(parser: &mut Parser) -> P { + panictry!(parser.parse_ty()) +} + +pub fn parse_stmt_panic(parser: &mut Parser) -> Option> { + panictry!(parser.parse_stmt()) +} + +pub fn parse_attribute_panic(parser: &mut Parser, permit_inner: bool) -> ast::Attribute { + panictry!(parser.parse_attribute(permit_inner)) +} + +pub fn parse_arg_panic(parser: &mut Parser) -> Arg { + panictry!(parser.parse_arg()) +} + +pub fn parse_block_panic(parser: &mut Parser) -> P { + panictry!(parser.parse_block()) +} + +pub fn parse_meta_item_panic(parser: &mut Parser) -> P { + panictry!(parser.parse_meta_item()) +} + +pub fn parse_path_panic(parser: &mut Parser, mode: PathParsingMode) -> ast::Path { + panictry!(parser.parse_path(mode)) +} + pub fn expand_quote_tokens<'cx>(cx: &'cx mut ExtCtxt, sp: Span, - tts: &[ast::TokenTree]) + tts: &[TokenTree]) -> Box { let (cx_expr, expr) = expand_tts(cx, sp, tts); let expanded = expand_wrapper(cx, sp, cx_expr, expr, &[&["syntax", "ext", "quote", "rt"]]); @@ -325,7 +387,7 @@ pub fn expand_quote_tokens<'cx>(cx: &'cx mut ExtCtxt, pub fn expand_quote_expr<'cx>(cx: &'cx mut ExtCtxt, sp: Span, - tts: &[ast::TokenTree]) + tts: &[TokenTree]) -> Box { let expanded = expand_parse_call(cx, sp, "parse_expr_panic", vec!(), tts); base::MacEager::expr(expanded) @@ -333,7 +395,7 @@ pub fn expand_quote_expr<'cx>(cx: &'cx mut ExtCtxt, pub fn expand_quote_item<'cx>(cx: &mut ExtCtxt, sp: Span, - tts: &[ast::TokenTree]) + tts: &[TokenTree]) -> Box { let expanded = expand_parse_call(cx, sp, "parse_item_panic", vec!(), tts); base::MacEager::expr(expanded) @@ -341,7 +403,7 @@ pub fn expand_quote_item<'cx>(cx: &mut ExtCtxt, pub fn expand_quote_pat<'cx>(cx: &'cx mut ExtCtxt, sp: Span, - tts: &[ast::TokenTree]) + tts: &[TokenTree]) -> Box { let expanded = expand_parse_call(cx, sp, "parse_pat_panic", vec!(), tts); base::MacEager::expr(expanded) @@ -349,7 +411,7 @@ pub fn expand_quote_pat<'cx>(cx: &'cx mut ExtCtxt, pub fn expand_quote_arm(cx: &mut ExtCtxt, sp: Span, - tts: &[ast::TokenTree]) + tts: &[TokenTree]) -> Box { let expanded = expand_parse_call(cx, sp, "parse_arm_panic", vec!(), tts); base::MacEager::expr(expanded) @@ -357,7 +419,7 @@ pub fn expand_quote_arm(cx: &mut ExtCtxt, pub fn expand_quote_ty(cx: &mut ExtCtxt, sp: Span, - tts: &[ast::TokenTree]) + tts: &[TokenTree]) -> Box { let expanded = expand_parse_call(cx, sp, "parse_ty_panic", vec!(), tts); base::MacEager::expr(expanded) @@ -365,7 +427,7 @@ pub fn expand_quote_ty(cx: &mut ExtCtxt, pub fn expand_quote_stmt(cx: &mut ExtCtxt, sp: Span, - tts: &[ast::TokenTree]) + tts: &[TokenTree]) -> Box { let expanded = expand_parse_call(cx, sp, "parse_stmt_panic", vec!(), tts); base::MacEager::expr(expanded) @@ -373,7 +435,7 @@ pub fn expand_quote_stmt(cx: &mut ExtCtxt, pub fn expand_quote_attr(cx: &mut ExtCtxt, sp: Span, - tts: &[ast::TokenTree]) + tts: &[TokenTree]) -> Box { let expanded = expand_parse_call(cx, sp, "parse_attribute_panic", vec!(cx.expr_bool(sp, true)), tts); @@ -381,9 +443,42 @@ pub fn expand_quote_attr(cx: &mut ExtCtxt, base::MacEager::expr(expanded) } +pub fn expand_quote_arg(cx: &mut ExtCtxt, + sp: Span, + tts: &[TokenTree]) + -> Box { + let expanded = expand_parse_call(cx, sp, "parse_arg_panic", vec!(), tts); + base::MacEager::expr(expanded) +} + +pub fn expand_quote_block(cx: &mut ExtCtxt, + sp: Span, + tts: &[TokenTree]) + -> Box { + let expanded = expand_parse_call(cx, sp, "parse_block_panic", vec!(), tts); + base::MacEager::expr(expanded) +} + +pub fn expand_quote_meta_item(cx: &mut ExtCtxt, + sp: Span, + tts: &[TokenTree]) + -> Box { + let expanded = expand_parse_call(cx, sp, "parse_meta_item_panic", vec!(), tts); + base::MacEager::expr(expanded) +} + +pub fn expand_quote_path(cx: &mut ExtCtxt, + sp: Span, + tts: &[TokenTree]) + -> Box { + let mode = mk_parser_path(cx, sp, "LifetimeAndTypesWithoutColons"); + let expanded = expand_parse_call(cx, sp, "parse_path_panic", vec!(mode), tts); + base::MacEager::expr(expanded) +} + pub fn expand_quote_matcher(cx: &mut ExtCtxt, sp: Span, - tts: &[ast::TokenTree]) + tts: &[TokenTree]) -> Box { let (cx_expr, tts) = parse_arguments_to_quote(cx, tts); let mut vector = mk_stmts_let(cx, sp); @@ -423,6 +518,11 @@ fn mk_name(cx: &ExtCtxt, sp: Span, ident: ast::Ident) -> P { vec!(e_str)) } +fn mk_tt_path(cx: &ExtCtxt, sp: Span, name: &str) -> P { + let idents = vec!(id_ext("syntax"), id_ext("ast"), id_ext("TokenTree"), id_ext(name)); + cx.expr_path(cx.path_global(sp, idents)) +} + fn mk_ast_path(cx: &ExtCtxt, sp: Span, name: &str) -> P { let idents = vec!(id_ext("syntax"), id_ext("ast"), id_ext(name)); cx.expr_path(cx.path_global(sp, idents)) @@ -433,6 +533,11 @@ fn mk_token_path(cx: &ExtCtxt, sp: Span, name: &str) -> P { cx.expr_path(cx.path_global(sp, idents)) } +fn mk_parser_path(cx: &ExtCtxt, sp: Span, name: &str) -> P { + let idents = vec!(id_ext("syntax"), id_ext("parse"), id_ext("parser"), id_ext(name)); + cx.expr_path(cx.path_global(sp, idents)) +} + fn mk_binop(cx: &ExtCtxt, sp: Span, bop: token::BinOpToken) -> P { let name = match bop { token::Plus => "Plus", @@ -591,9 +696,9 @@ fn expr_mk_token(cx: &ExtCtxt, sp: Span, tok: &token::Token) -> P { mk_token_path(cx, sp, name) } -fn statements_mk_tt(cx: &ExtCtxt, tt: &ast::TokenTree, matcher: bool) -> Vec> { +fn statements_mk_tt(cx: &ExtCtxt, tt: &TokenTree, matcher: bool) -> Vec> { match *tt { - ast::TtToken(sp, SubstNt(ident, _)) => { + TokenTree::Token(sp, SubstNt(ident, _)) => { // tt.extend($ident.to_tokens(ext_cx)) let e_to_toks = @@ -612,17 +717,17 @@ fn statements_mk_tt(cx: &ExtCtxt, tt: &ast::TokenTree, matcher: bool) -> Vec { + ref tt @ TokenTree::Token(_, MatchNt(..)) if !matcher => { let mut seq = vec![]; for i in 0..tt.len() { seq.push(tt.get_tt(i)); } statements_mk_tts(cx, &seq[..], matcher) } - ast::TtToken(sp, ref tok) => { + TokenTree::Token(sp, ref tok) => { let e_sp = cx.expr_ident(sp, id_ext("_sp")); let e_tok = cx.expr_call(sp, - mk_ast_path(cx, sp, "TtToken"), + mk_tt_path(cx, sp, "Token"), vec!(e_sp, expr_mk_token(cx, sp, tok))); let e_push = cx.expr_method_call(sp, @@ -631,16 +736,16 @@ fn statements_mk_tt(cx: &ExtCtxt, tt: &ast::TokenTree, matcher: bool) -> Vec { + TokenTree::Delimited(_, ref delimed) => { statements_mk_tt(cx, &delimed.open_tt(), matcher).into_iter() .chain(delimed.tts.iter() .flat_map(|tt| statements_mk_tt(cx, tt, matcher))) .chain(statements_mk_tt(cx, &delimed.close_tt(), matcher)) .collect() }, - ast::TtSequence(sp, ref seq) => { + TokenTree::Sequence(sp, ref seq) => { if !matcher { - panic!("TtSequence in quote!"); + panic!("TokenTree::Sequence in quote!"); } let e_sp = cx.expr_ident(sp, id_ext("_sp")); @@ -671,7 +776,7 @@ fn statements_mk_tt(cx: &ExtCtxt, tt: &ast::TokenTree, matcher: bool) -> Vec Vec (P, Vec) { +fn parse_arguments_to_quote(cx: &ExtCtxt, tts: &[TokenTree]) + -> (P, Vec) { // NB: It appears that the main parser loses its mind if we consider // $foo as a SubstNt during the main parse, so we have to re-parse // under quote_depth > 0. This is silly and should go away; the _guess_ is @@ -694,7 +799,7 @@ fn parse_arguments_to_quote(cx: &ExtCtxt, tts: &[ast::TokenTree]) let mut p = cx.new_parser_from_tts(tts); p.quote_depth += 1; - let cx_expr = panictry!(p.parse_expr_nopanic()); + let cx_expr = panictry!(p.parse_expr()); if !panictry!(p.eat(&token::Comma)) { panic!(p.fatal("expected token `,`")); } @@ -746,7 +851,7 @@ fn mk_stmts_let(cx: &ExtCtxt, sp: Span) -> Vec> { vec!(stmt_let_sp, stmt_let_tt) } -fn statements_mk_tts(cx: &ExtCtxt, tts: &[ast::TokenTree], matcher: bool) -> Vec> { +fn statements_mk_tts(cx: &ExtCtxt, tts: &[TokenTree], matcher: bool) -> Vec> { let mut ss = Vec::new(); for tt in tts { ss.extend(statements_mk_tt(cx, tt, matcher)); @@ -754,7 +859,7 @@ fn statements_mk_tts(cx: &ExtCtxt, tts: &[ast::TokenTree], matcher: bool) -> Vec ss } -fn expand_tts(cx: &ExtCtxt, sp: Span, tts: &[ast::TokenTree]) +fn expand_tts(cx: &ExtCtxt, sp: Span, tts: &[TokenTree]) -> (P, P) { let (cx_expr, tts) = parse_arguments_to_quote(cx, tts); @@ -790,7 +895,7 @@ fn expand_parse_call(cx: &ExtCtxt, sp: Span, parse_method: &str, arg_exprs: Vec> , - tts: &[ast::TokenTree]) -> P { + tts: &[TokenTree]) -> P { let (cx_expr, tts_expr) = expand_tts(cx, sp, tts); let cfg_call = || cx.expr_method_call( @@ -806,8 +911,10 @@ fn expand_parse_call(cx: &ExtCtxt, cx.expr_ident(sp, id_ext("new_parser_from_tts")), vec!(parse_sess_call(), cfg_call(), tts_expr)); - let expr = cx.expr_method_call(sp, new_parser_call, id_ext(parse_method), - arg_exprs); + let path = vec![id_ext("syntax"), id_ext("ext"), id_ext("quote"), id_ext(parse_method)]; + let mut args = vec![cx.expr_mut_addr_of(sp, new_parser_call)]; + args.extend(arg_exprs); + let expr = cx.expr_call_global(sp, path, args); if parse_method == "parse_attribute" { expand_wrapper(cx, sp, cx_expr, expr, &[&["syntax", "ext", "quote", "rt"], diff --git a/src/libsyntax/ext/source_util.rs b/src/libsyntax/ext/source_util.rs index 72ba7359d4d94..7899e170ecf19 100644 --- a/src/libsyntax/ext/source_util.rs +++ b/src/libsyntax/ext/source_util.rs @@ -109,13 +109,13 @@ pub fn expand_include<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenTree } impl<'a> base::MacResult for ExpandResult<'a> { fn make_expr(mut self: Box>) -> Option> { - Some(panictry!(self.p.parse_expr_nopanic())) + Some(panictry!(self.p.parse_expr())) } fn make_items(mut self: Box>) -> Option>> { let mut ret = SmallVector::zero(); while self.p.token != token::Eof { - match panictry!(self.p.parse_item_nopanic()) { + match panictry!(self.p.parse_item()) { Some(item) => ret.push(item), None => panic!(self.p.span_fatal( self.p.span, diff --git a/src/libsyntax/ext/trace_macros.rs b/src/libsyntax/ext/trace_macros.rs index ab34f41d932d5..628b88d13537a 100644 --- a/src/libsyntax/ext/trace_macros.rs +++ b/src/libsyntax/ext/trace_macros.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use ast; +use ast::TokenTree; use codemap::Span; use ext::base::ExtCtxt; use ext::base; @@ -18,7 +18,7 @@ use parse::token::keywords; pub fn expand_trace_macros(cx: &mut ExtCtxt, sp: Span, - tt: &[ast::TokenTree]) + tt: &[TokenTree]) -> Box { if !cx.ecfg.enable_trace_macros() { feature_gate::emit_feature_err(&cx.parse_sess.span_diagnostic, @@ -30,10 +30,10 @@ pub fn expand_trace_macros(cx: &mut ExtCtxt, } match (tt.len(), tt.first()) { - (1, Some(&ast::TtToken(_, ref tok))) if tok.is_keyword(keywords::True) => { + (1, Some(&TokenTree::Token(_, ref tok))) if tok.is_keyword(keywords::True) => { cx.set_trace_macros(true); } - (1, Some(&ast::TtToken(_, ref tok))) if tok.is_keyword(keywords::False) => { + (1, Some(&TokenTree::Token(_, ref tok))) if tok.is_keyword(keywords::False) => { cx.set_trace_macros(false); } _ => cx.span_err(sp, "trace_macros! accepts only `true` or `false`"), diff --git a/src/libsyntax/ext/tt/macro_parser.rs b/src/libsyntax/ext/tt/macro_parser.rs index a4c99018bb9cc..dded634882dc1 100644 --- a/src/libsyntax/ext/tt/macro_parser.rs +++ b/src/libsyntax/ext/tt/macro_parser.rs @@ -80,7 +80,6 @@ use self::TokenTreeOrTokenTreeVec::*; use ast; use ast::{TokenTree, Name}; -use ast::{TtDelimited, TtSequence, TtToken}; use codemap::{BytePos, mk_sp, Span}; use codemap; use parse::lexer::*; //resolve bug? @@ -146,16 +145,16 @@ pub struct MatcherPos { pub fn count_names(ms: &[TokenTree]) -> usize { ms.iter().fold(0, |count, elt| { count + match elt { - &TtSequence(_, ref seq) => { + &TokenTree::Sequence(_, ref seq) => { seq.num_captures } - &TtDelimited(_, ref delim) => { + &TokenTree::Delimited(_, ref delim) => { count_names(&delim.tts) } - &TtToken(_, MatchNt(..)) => { + &TokenTree::Token(_, MatchNt(..)) => { 1 } - &TtToken(_, _) => 0, + &TokenTree::Token(_, _) => 0, } }) } @@ -205,17 +204,17 @@ pub fn nameize(p_s: &ParseSess, ms: &[TokenTree], res: &[Rc]) fn n_rec(p_s: &ParseSess, m: &TokenTree, res: &[Rc], ret_val: &mut HashMap>, idx: &mut usize) { match m { - &TtSequence(_, ref seq) => { + &TokenTree::Sequence(_, ref seq) => { for next_m in &seq.tts { n_rec(p_s, next_m, res, ret_val, idx) } } - &TtDelimited(_, ref delim) => { + &TokenTree::Delimited(_, ref delim) => { for next_m in &delim.tts { n_rec(p_s, next_m, res, ret_val, idx) } } - &TtToken(sp, MatchNt(bind_name, _, _, _)) => { + &TokenTree::Token(sp, MatchNt(bind_name, _, _, _)) => { match ret_val.entry(bind_name.name) { Vacant(spot) => { spot.insert(res[*idx].clone()); @@ -229,8 +228,8 @@ pub fn nameize(p_s: &ParseSess, ms: &[TokenTree], res: &[Rc]) } } } - &TtToken(_, SubstNt(..)) => panic!("Cannot fill in a NT"), - &TtToken(_, _) => (), + &TokenTree::Token(_, SubstNt(..)) => panic!("Cannot fill in a NT"), + &TokenTree::Token(_, _) => (), } } let mut ret_val = HashMap::new(); @@ -362,7 +361,7 @@ pub fn parse(sess: &ParseSess, } else { match ei.top_elts.get_tt(idx) { /* need to descend into sequence */ - TtSequence(sp, seq) => { + TokenTree::Sequence(sp, seq) => { if seq.op == ast::ZeroOrMore { let mut new_ei = ei.clone(); new_ei.match_cur += seq.num_captures; @@ -388,10 +387,10 @@ pub fn parse(sess: &ParseSess, match_hi: ei_t.match_cur + seq.num_captures, up: Some(ei_t), sp_lo: sp.lo, - top_elts: Tt(TtSequence(sp, seq)), + top_elts: Tt(TokenTree::Sequence(sp, seq)), })); } - TtToken(_, MatchNt(..)) => { + TokenTree::Token(_, MatchNt(..)) => { // Built-in nonterminals never start with these tokens, // so we can eliminate them from consideration. match tok { @@ -399,10 +398,10 @@ pub fn parse(sess: &ParseSess, _ => bb_eis.push(ei), } } - TtToken(sp, SubstNt(..)) => { + TokenTree::Token(sp, SubstNt(..)) => { return Error(sp, "missing fragment specifier".to_string()) } - seq @ TtDelimited(..) | seq @ TtToken(_, DocComment(..)) => { + seq @ TokenTree::Delimited(..) | seq @ TokenTree::Token(_, DocComment(..)) => { let lower_elts = mem::replace(&mut ei.top_elts, Tt(seq)); let idx = ei.idx; ei.stack.push(MatcherTtFrame { @@ -412,7 +411,7 @@ pub fn parse(sess: &ParseSess, ei.idx = 0; cur_eis.push(ei); } - TtToken(_, ref t) => { + TokenTree::Token(_, ref t) => { let mut ei_t = ei.clone(); if token_name_eq(t,&tok) { ei_t.idx += 1; @@ -440,7 +439,7 @@ pub fn parse(sess: &ParseSess, if (!bb_eis.is_empty() && !next_eis.is_empty()) || bb_eis.len() > 1 { let nts = bb_eis.iter().map(|ei| match ei.top_elts.get_tt(ei.idx) { - TtToken(_, MatchNt(bind, name, _, _)) => { + TokenTree::Token(_, MatchNt(bind, name, _, _)) => { format!("{} ('{}')", name, bind) } _ => panic!() @@ -468,7 +467,7 @@ pub fn parse(sess: &ParseSess, let mut ei = bb_eis.pop().unwrap(); match ei.top_elts.get_tt(ei.idx) { - TtToken(span, MatchNt(_, ident, _, _)) => { + TokenTree::Token(span, MatchNt(_, ident, _, _)) => { let match_cur = ei.match_cur; (&mut ei.matches[match_cur]).push(Rc::new(MatchedNonterminal( parse_nt(&mut rust_parser, span, &ident.name.as_str())))); @@ -502,18 +501,18 @@ pub fn parse_nt(p: &mut Parser, sp: Span, name: &str) -> Nonterminal { // check at the beginning and the parser checks after each bump panictry!(p.check_unknown_macro_variable()); match name { - "item" => match panictry!(p.parse_item_nopanic()) { + "item" => match panictry!(p.parse_item()) { Some(i) => token::NtItem(i), None => panic!(p.fatal("expected an item keyword")) }, "block" => token::NtBlock(panictry!(p.parse_block())), - "stmt" => match panictry!(p.parse_stmt_nopanic()) { + "stmt" => match panictry!(p.parse_stmt()) { Some(s) => token::NtStmt(s), None => panic!(p.fatal("expected a statement")) }, - "pat" => token::NtPat(panictry!(p.parse_pat_nopanic())), - "expr" => token::NtExpr(panictry!(p.parse_expr_nopanic())), - "ty" => token::NtTy(panictry!(p.parse_ty_nopanic())), + "pat" => token::NtPat(panictry!(p.parse_pat())), + "expr" => token::NtExpr(panictry!(p.parse_expr())), + "ty" => token::NtTy(panictry!(p.parse_ty())), // this could be handled like a token, since it is one "ident" => match p.token { token::Ident(sn,b) => { panictry!(p.bump()); token::NtIdent(Box::new(sn),b) } diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index a98c001dc0e60..43647ea4a2e17 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -8,12 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use ast::{self, TokenTree, TtDelimited, TtSequence, TtToken}; +use ast::{self, TokenTree}; use codemap::{Span, DUMMY_SP}; -use ext::base::{ExtCtxt, MacResult, SyntaxExtension}; +use ext::base::{DummyResult, ExtCtxt, MacResult, SyntaxExtension}; use ext::base::{NormalTT, TTMacroExpander}; use ext::tt::macro_parser::{Success, Error, Failure}; -use ext::tt::macro_parser::{NamedMatch, MatchedSeq, MatchedNonterminal}; +use ext::tt::macro_parser::{MatchedSeq, MatchedNonterminal}; use ext::tt::macro_parser::parse; use parse::lexer::new_tt_reader; use parse::parser::Parser; @@ -26,6 +26,7 @@ use util::small_vector::SmallVector; use std::cell::RefCell; use std::rc::Rc; +use std::iter::once; struct ParserAnyMacro<'a> { parser: RefCell>, @@ -66,18 +67,18 @@ impl<'a> ParserAnyMacro<'a> { impl<'a> MacResult for ParserAnyMacro<'a> { fn make_expr(self: Box>) -> Option> { - let ret = panictry!(self.parser.borrow_mut().parse_expr_nopanic()); + let ret = panictry!(self.parser.borrow_mut().parse_expr()); self.ensure_complete_parse(true); Some(ret) } fn make_pat(self: Box>) -> Option> { - let ret = panictry!(self.parser.borrow_mut().parse_pat_nopanic()); + let ret = panictry!(self.parser.borrow_mut().parse_pat()); self.ensure_complete_parse(false); Some(ret) } fn make_items(self: Box>) -> Option>> { let mut ret = SmallVector::zero(); - while let Some(item) = panictry!(self.parser.borrow_mut().parse_item_nopanic()) { + while let Some(item) = panictry!(self.parser.borrow_mut().parse_item()) { ret.push(item); } self.ensure_complete_parse(false); @@ -105,7 +106,7 @@ impl<'a> MacResult for ParserAnyMacro<'a> { let mut parser = self.parser.borrow_mut(); match parser.token { token::Eof => break, - _ => match parser.parse_stmt_nopanic() { + _ => match parser.parse_stmt() { Ok(maybe_stmt) => match maybe_stmt { Some(stmt) => ret.push(stmt), None => (), @@ -119,7 +120,7 @@ impl<'a> MacResult for ParserAnyMacro<'a> { } fn make_ty(self: Box>) -> Option> { - let ret = panictry!(self.parser.borrow_mut().parse_ty_nopanic()); + let ret = panictry!(self.parser.borrow_mut().parse_ty()); self.ensure_complete_parse(true); Some(ret) } @@ -128,16 +129,20 @@ impl<'a> MacResult for ParserAnyMacro<'a> { struct MacroRulesMacroExpander { name: ast::Ident, imported_from: Option, - lhses: Vec>, - rhses: Vec>, + lhses: Vec, + rhses: Vec, + valid: bool, } impl TTMacroExpander for MacroRulesMacroExpander { fn expand<'cx>(&self, cx: &'cx mut ExtCtxt, sp: Span, - arg: &[ast::TokenTree]) + arg: &[TokenTree]) -> Box { + if !self.valid { + return DummyResult::any(sp); + } generic_extension(cx, sp, self.name, @@ -153,9 +158,9 @@ fn generic_extension<'cx>(cx: &'cx ExtCtxt, sp: Span, name: ast::Ident, imported_from: Option, - arg: &[ast::TokenTree], - lhses: &[Rc], - rhses: &[Rc]) + arg: &[TokenTree], + lhses: &[TokenTree], + rhses: &[TokenTree]) -> Box { if cx.trace_macros() { println!("{}! {{ {} }}", @@ -168,25 +173,17 @@ fn generic_extension<'cx>(cx: &'cx ExtCtxt, let mut best_fail_msg = "internal error: ran no matchers".to_string(); for (i, lhs) in lhses.iter().enumerate() { // try each arm's matchers - match **lhs { - MatchedNonterminal(NtTT(ref lhs_tt)) => { - let lhs_tt = match **lhs_tt { - TtDelimited(_, ref delim) => &delim.tts[..], - _ => panic!(cx.span_fatal(sp, "malformed macro lhs")) - }; - - match TokenTree::parse(cx, lhs_tt, arg) { - Success(named_matches) => { - let rhs = match *rhses[i] { - // okay, what's your transcriber? - MatchedNonterminal(NtTT(ref tt)) => { - match **tt { - // ignore delimiters - TtDelimited(_, ref delimed) => delimed.tts.clone(), - _ => panic!(cx.span_fatal(sp, "macro rhs must be delimited")), - } - }, - _ => cx.span_bug(sp, "bad thing in rhs") + let lhs_tt = match *lhs { + TokenTree::Delimited(_, ref delim) => &delim.tts[..], + _ => cx.span_bug(sp, "malformed macro lhs") + }; + + match TokenTree::parse(cx, lhs_tt, arg) { + Success(named_matches) => { + let rhs = match rhses[i] { + // ignore delimiters + TokenTree::Delimited(_, ref delimed) => delimed.tts.clone(), + _ => cx.span_bug(sp, "malformed macro rhs"), }; // rhs has holes ( `$id` and `$(...)` that need filled) let trncbr = new_tt_reader(&cx.parse_sess().span_diagnostic, @@ -206,17 +203,14 @@ fn generic_extension<'cx>(cx: &'cx ExtCtxt, site_span: sp, macro_ident: name }) - } - Failure(sp, ref msg) => if sp.lo >= best_fail_spot.lo { + } + Failure(sp, ref msg) => if sp.lo >= best_fail_spot.lo { best_fail_spot = sp; best_fail_msg = (*msg).clone(); - }, - Error(err_sp, ref msg) => { + }, + Error(err_sp, ref msg) => { panic!(cx.span_fatal(err_sp.substitute_dummy(sp), &msg[..])) - } } - } - _ => cx.bug("non-matcher found in parsed lhses") } } @@ -243,21 +237,21 @@ pub fn compile<'cx>(cx: &'cx mut ExtCtxt, let match_lhs_tok = MatchNt(lhs_nm, special_idents::tt, token::Plain, token::Plain); let match_rhs_tok = MatchNt(rhs_nm, special_idents::tt, token::Plain, token::Plain); let argument_gram = vec!( - TtSequence(DUMMY_SP, + TokenTree::Sequence(DUMMY_SP, Rc::new(ast::SequenceRepetition { tts: vec![ - TtToken(DUMMY_SP, match_lhs_tok), - TtToken(DUMMY_SP, token::FatArrow), - TtToken(DUMMY_SP, match_rhs_tok)], + TokenTree::Token(DUMMY_SP, match_lhs_tok), + TokenTree::Token(DUMMY_SP, token::FatArrow), + TokenTree::Token(DUMMY_SP, match_rhs_tok)], separator: Some(token::Semi), op: ast::OneOrMore, num_captures: 2 })), //to phase into semicolon-termination instead of //semicolon-separation - TtSequence(DUMMY_SP, + TokenTree::Sequence(DUMMY_SP, Rc::new(ast::SequenceRepetition { - tts: vec![TtToken(DUMMY_SP, token::Semi)], + tts: vec![TokenTree::Token(DUMMY_SP, token::Semi)], separator: None, op: ast::ZeroOrMore, num_captures: 0 @@ -281,53 +275,74 @@ pub fn compile<'cx>(cx: &'cx mut ExtCtxt, } }; + let mut valid = true; + // Extract the arguments: let lhses = match **argument_map.get(&lhs_nm.name).unwrap() { - MatchedSeq(ref s, _) => /* FIXME (#2543) */ (*s).clone(), + MatchedSeq(ref s, _) => { + s.iter().map(|m| match **m { + MatchedNonterminal(NtTT(ref tt)) => (**tt).clone(), + _ => cx.span_bug(def.span, "wrong-structured lhs") + }).collect() + } _ => cx.span_bug(def.span, "wrong-structured lhs") }; for lhs in &lhses { - check_lhs_nt_follows(cx, &**lhs, def.span); + check_lhs_nt_follows(cx, lhs, def.span); } let rhses = match **argument_map.get(&rhs_nm.name).unwrap() { - MatchedSeq(ref s, _) => /* FIXME (#2543) */ (*s).clone(), + MatchedSeq(ref s, _) => { + s.iter().map(|m| match **m { + MatchedNonterminal(NtTT(ref tt)) => (**tt).clone(), + _ => cx.span_bug(def.span, "wrong-structured rhs") + }).collect() + } _ => cx.span_bug(def.span, "wrong-structured rhs") }; + for rhs in &rhses { + valid &= check_rhs(cx, rhs); + } + let exp: Box<_> = Box::new(MacroRulesMacroExpander { name: def.ident, imported_from: def.imported_from, lhses: lhses, rhses: rhses, + valid: valid, }); NormalTT(exp, Some(def.span), def.allow_internal_unstable) } -fn check_lhs_nt_follows(cx: &mut ExtCtxt, lhs: &NamedMatch, sp: Span) { - // lhs is going to be like MatchedNonterminal(NtTT(TtDelimited(...))), where the entire lhs is - // those tts. Or, it can be a "bare sequence", not wrapped in parens. +fn check_lhs_nt_follows(cx: &mut ExtCtxt, lhs: &TokenTree, sp: Span) { + // lhs is going to be like TokenTree::Delimited(...), where the + // entire lhs is those tts. Or, it can be a "bare sequence", not wrapped in parens. match lhs { - &MatchedNonterminal(NtTT(ref inner)) => match &**inner { - &TtDelimited(_, ref tts) => { - check_matcher(cx, tts.tts.iter(), &Eof); - }, - tt @ &TtSequence(..) => { - check_matcher(cx, Some(tt).into_iter(), &Eof); - }, - _ => cx.span_err(sp, "Invalid macro matcher; matchers must be contained \ - in balanced delimiters or a repetition indicator") + &TokenTree::Delimited(_, ref tts) => { + check_matcher(cx, tts.tts.iter(), &Eof); + }, + tt @ &TokenTree::Sequence(..) => { + check_matcher(cx, Some(tt).into_iter(), &Eof); }, - _ => cx.span_bug(sp, "wrong-structured lhs for follow check (didn't find a \ - MatchedNonterminal)") + _ => cx.span_err(sp, "Invalid macro matcher; matchers must be contained \ + in balanced delimiters or a repetition indicator") }; // we don't abort on errors on rejection, the driver will do that for us // after parsing/expansion. we can report every error in every macro this way. } -// returns the last token that was checked, for TtSequence. this gets used later on. +fn check_rhs(cx: &mut ExtCtxt, rhs: &TokenTree) -> bool { + match *rhs { + TokenTree::Delimited(..) => return true, + _ => cx.span_err(rhs.get_span(), "macro rhs must be delimited") + } + false +} + +// returns the last token that was checked, for TokenTree::Sequence. this gets used later on. fn check_matcher<'a, I>(cx: &mut ExtCtxt, matcher: I, follow: &Token) -> Option<(Span, Token)> where I: Iterator { use print::pprust::token_to_string; @@ -338,7 +353,7 @@ fn check_matcher<'a, I>(cx: &mut ExtCtxt, matcher: I, follow: &Token) let mut tokens = matcher.peekable(); while let Some(token) = tokens.next() { last = match *token { - TtToken(sp, MatchNt(ref name, ref frag_spec, _, _)) => { + TokenTree::Token(sp, MatchNt(ref name, ref frag_spec, _, _)) => { // ii. If T is a simple NT, look ahead to the next token T' in // M. If T' is in the set FOLLOW(NT), continue. Else; reject. if can_be_followed_by_any(&frag_spec.name.as_str()) { @@ -346,9 +361,9 @@ fn check_matcher<'a, I>(cx: &mut ExtCtxt, matcher: I, follow: &Token) } else { let next_token = match tokens.peek() { // If T' closes a complex NT, replace T' with F - Some(&&TtToken(_, CloseDelim(_))) => follow.clone(), - Some(&&TtToken(_, ref tok)) => tok.clone(), - Some(&&TtSequence(sp, _)) => { + Some(&&TokenTree::Token(_, CloseDelim(_))) => follow.clone(), + Some(&&TokenTree::Token(_, ref tok)) => tok.clone(), + Some(&&TokenTree::Sequence(sp, _)) => { // Be conservative around sequences: to be // more specific, we would need to // consider FIRST sets, but also the @@ -366,12 +381,16 @@ fn check_matcher<'a, I>(cx: &mut ExtCtxt, matcher: I, follow: &Token) Eof }, // die next iteration - Some(&&TtDelimited(_, ref delim)) => delim.close_token(), + Some(&&TokenTree::Delimited(_, ref delim)) => delim.close_token(), // else, we're at the end of the macro or sequence None => follow.clone() }; - let tok = if let TtToken(_, ref tok) = *token { tok } else { unreachable!() }; + let tok = if let TokenTree::Token(_, ref tok) = *token { + tok + } else { + unreachable!() + }; // If T' is in the set FOLLOW(NT), continue. Else, reject. match (&next_token, is_in_follow(cx, &next_token, &frag_spec.name.as_str())) { @@ -391,7 +410,7 @@ fn check_matcher<'a, I>(cx: &mut ExtCtxt, matcher: I, follow: &Token) } } }, - TtSequence(sp, ref seq) => { + TokenTree::Sequence(sp, ref seq) => { // iii. Else, T is a complex NT. match seq.separator { // If T has the form $(...)U+ or $(...)U* for some token U, @@ -408,8 +427,9 @@ fn check_matcher<'a, I>(cx: &mut ExtCtxt, matcher: I, follow: &Token) // but conservatively correct. Some((span, tok)) => { let fol = match tokens.peek() { - Some(&&TtToken(_, ref tok)) => tok.clone(), - Some(&&TtDelimited(_, ref delim)) => delim.close_token(), + Some(&&TokenTree::Token(_, ref tok)) => tok.clone(), + Some(&&TokenTree::Delimited(_, ref delim)) => + delim.close_token(), Some(_) => { cx.span_err(sp, "sequence repetition followed by \ another sequence repetition, which is not allowed"); @@ -417,7 +437,7 @@ fn check_matcher<'a, I>(cx: &mut ExtCtxt, matcher: I, follow: &Token) }, None => Eof }; - check_matcher(cx, Some(&TtToken(span, tok.clone())).into_iter(), + check_matcher(cx, once(&TokenTree::Token(span, tok.clone())), &fol) }, None => last, @@ -428,8 +448,8 @@ fn check_matcher<'a, I>(cx: &mut ExtCtxt, matcher: I, follow: &Token) // sequence. If it accepts, continue, else, reject. None => { let fol = match tokens.peek() { - Some(&&TtToken(_, ref tok)) => tok.clone(), - Some(&&TtDelimited(_, ref delim)) => delim.close_token(), + Some(&&TokenTree::Token(_, ref tok)) => tok.clone(), + Some(&&TokenTree::Delimited(_, ref delim)) => delim.close_token(), Some(_) => { cx.span_err(sp, "sequence repetition followed by another \ sequence repetition, which is not allowed"); @@ -441,11 +461,11 @@ fn check_matcher<'a, I>(cx: &mut ExtCtxt, matcher: I, follow: &Token) } } }, - TtToken(..) => { + TokenTree::Token(..) => { // i. If T is not an NT, continue. continue }, - TtDelimited(_, ref tts) => { + TokenTree::Delimited(_, ref tts) => { // if we don't pass in that close delimiter, we'll incorrectly consider the matcher // `{ $foo:ty }` as having a follow that isn't `RBrace` check_matcher(cx, tts.tts.iter(), &tts.close_token()) diff --git a/src/libsyntax/ext/tt/transcribe.rs b/src/libsyntax/ext/tt/transcribe.rs index d1e48eda4ffd2..0fc31f3fd08af 100644 --- a/src/libsyntax/ext/tt/transcribe.rs +++ b/src/libsyntax/ext/tt/transcribe.rs @@ -10,7 +10,7 @@ use self::LockstepIterSize::*; use ast; -use ast::{TokenTree, TtDelimited, TtToken, TtSequence, Ident, Name}; +use ast::{TokenTree, Ident, Name}; use codemap::{Span, DUMMY_SP}; use diagnostic::SpanHandler; use ext::tt::macro_parser::{NamedMatch, MatchedSeq, MatchedNonterminal}; @@ -53,7 +53,7 @@ pub struct TtReader<'a> { } /// This can do Macro-By-Example transcription. On the other hand, if -/// `src` contains no `TtSequence`s, `MatchNt`s or `SubstNt`s, `interp` can +/// `src` contains no `TokenTree::Sequence`s, `MatchNt`s or `SubstNt`s, `interp` can /// (and should) be None. pub fn new_tt_reader<'a>(sp_diag: &'a SpanHandler, interp: Option>>, @@ -67,7 +67,7 @@ pub fn new_tt_reader<'a>(sp_diag: &'a SpanHandler, /// like any other attribute which consists of `meta` and surrounding #[ ] tokens. /// /// This can do Macro-By-Example transcription. On the other hand, if -/// `src` contains no `TtSequence`s, `MatchNt`s or `SubstNt`s, `interp` can +/// `src` contains no `TokenTree::Sequence`s, `MatchNt`s or `SubstNt`s, `interp` can /// (and should) be None. pub fn new_tt_reader_with_doc_flag<'a>(sp_diag: &'a SpanHandler, interp: Option>>, @@ -78,7 +78,7 @@ pub fn new_tt_reader_with_doc_flag<'a>(sp_diag: &'a SpanHandler, let mut r = TtReader { sp_diag: sp_diag, stack: vec!(TtFrame { - forest: TtSequence(DUMMY_SP, Rc::new(ast::SequenceRepetition { + forest: TokenTree::Sequence(DUMMY_SP, Rc::new(ast::SequenceRepetition { tts: src, // doesn't matter. This merely holds the root unzipping. separator: None, op: ast::ZeroOrMore, num_captures: 0 @@ -151,17 +151,17 @@ impl Add for LockstepIterSize { fn lockstep_iter_size(t: &TokenTree, r: &TtReader) -> LockstepIterSize { match *t { - TtDelimited(_, ref delimed) => { + TokenTree::Delimited(_, ref delimed) => { delimed.tts.iter().fold(LisUnconstrained, |size, tt| { size + lockstep_iter_size(tt, r) }) }, - TtSequence(_, ref seq) => { + TokenTree::Sequence(_, ref seq) => { seq.tts.iter().fold(LisUnconstrained, |size, tt| { size + lockstep_iter_size(tt, r) }) }, - TtToken(_, SubstNt(name, _)) | TtToken(_, MatchNt(name, _, _, _)) => + TokenTree::Token(_, SubstNt(name, _)) | TokenTree::Token(_, MatchNt(name, _, _, _)) => match lookup_cur_matched(r, name) { Some(matched) => match *matched { MatchedNonterminal(_) => LisUnconstrained, @@ -169,7 +169,7 @@ fn lockstep_iter_size(t: &TokenTree, r: &TtReader) -> LockstepIterSize { }, _ => LisUnconstrained }, - TtToken(..) => LisUnconstrained, + TokenTree::Token(..) => LisUnconstrained, } } @@ -232,17 +232,17 @@ pub fn tt_next_token(r: &mut TtReader) -> TokenAndSpan { } } } - loop { /* because it's easiest, this handles `TtDelimited` not starting - with a `TtToken`, even though it won't happen */ + loop { /* because it's easiest, this handles `TokenTree::Delimited` not starting + with a `TokenTree::Token`, even though it won't happen */ let t = { let frame = r.stack.last().unwrap(); // FIXME(pcwalton): Bad copy. frame.forest.get_tt(frame.idx) }; match t { - TtSequence(sp, seq) => { + TokenTree::Sequence(sp, seq) => { // FIXME(pcwalton): Bad copy. - match lockstep_iter_size(&TtSequence(sp, seq.clone()), + match lockstep_iter_size(&TokenTree::Sequence(sp, seq.clone()), r) { LisUnconstrained => { panic!(r.sp_diag.span_fatal( @@ -272,20 +272,20 @@ pub fn tt_next_token(r: &mut TtReader) -> TokenAndSpan { idx: 0, dotdotdoted: true, sep: seq.separator.clone(), - forest: TtSequence(sp, seq), + forest: TokenTree::Sequence(sp, seq), }); } } } // FIXME #2887: think about span stuff here - TtToken(sp, SubstNt(ident, namep)) => { + TokenTree::Token(sp, SubstNt(ident, namep)) => { r.stack.last_mut().unwrap().idx += 1; match lookup_cur_matched(r, ident) { None => { r.cur_span = sp; r.cur_tok = SubstNt(ident, namep); return ret_val; - // this can't be 0 length, just like TtDelimited + // this can't be 0 length, just like TokenTree::Delimited } Some(cur_matched) => { match *cur_matched { @@ -313,8 +313,8 @@ pub fn tt_next_token(r: &mut TtReader) -> TokenAndSpan { } } } - // TtDelimited or any token that can be unzipped - seq @ TtDelimited(..) | seq @ TtToken(_, MatchNt(..)) => { + // TokenTree::Delimited or any token that can be unzipped + seq @ TokenTree::Delimited(..) | seq @ TokenTree::Token(_, MatchNt(..)) => { // do not advance the idx yet r.stack.push(TtFrame { forest: seq, @@ -324,15 +324,15 @@ pub fn tt_next_token(r: &mut TtReader) -> TokenAndSpan { }); // if this could be 0-length, we'd need to potentially recur here } - TtToken(sp, DocComment(name)) if r.desugar_doc_comments => { + TokenTree::Token(sp, DocComment(name)) if r.desugar_doc_comments => { r.stack.push(TtFrame { - forest: TtToken(sp, DocComment(name)), + forest: TokenTree::Token(sp, DocComment(name)), idx: 0, dotdotdoted: false, sep: None }); } - TtToken(sp, token::SpecialVarNt(SpecialMacroVar::CrateMacroVar)) => { + TokenTree::Token(sp, token::SpecialVarNt(SpecialMacroVar::CrateMacroVar)) => { r.stack.last_mut().unwrap().idx += 1; if r.imported_from.is_some() { @@ -344,7 +344,7 @@ pub fn tt_next_token(r: &mut TtReader) -> TokenAndSpan { // otherwise emit nothing and proceed to the next token } - TtToken(sp, tok) => { + TokenTree::Token(sp, tok) => { r.cur_span = sp; r.cur_tok = tok; r.stack.last_mut().unwrap().idx += 1; diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index a0c089aff2172..64429336562c5 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -51,53 +51,59 @@ const KNOWN_FEATURES: &'static [(&'static str, &'static str, Option, Status ("globs", "1.0.0", None, Accepted), ("macro_rules", "1.0.0", None, Accepted), ("struct_variant", "1.0.0", None, Accepted), - ("asm", "1.0.0", None, Active), + ("asm", "1.0.0", Some(29722), Active), ("managed_boxes", "1.0.0", None, Removed), - ("non_ascii_idents", "1.0.0", None, Active), - ("thread_local", "1.0.0", None, Active), - ("link_args", "1.0.0", None, Active), - ("plugin_registrar", "1.0.0", None, Active), - ("log_syntax", "1.0.0", None, Active), - ("trace_macros", "1.0.0", None, Active), - ("concat_idents", "1.0.0", None, Active), + ("non_ascii_idents", "1.0.0", Some(28979), Active), + ("thread_local", "1.0.0", Some(29594), Active), + ("link_args", "1.0.0", Some(29596), Active), + ("plugin_registrar", "1.0.0", Some(29597), Active), + ("log_syntax", "1.0.0", Some(29598), Active), + ("trace_macros", "1.0.0", Some(29598), Active), + ("concat_idents", "1.0.0", Some(29599), Active), + + // rustc internal, for now: ("intrinsics", "1.0.0", None, Active), ("lang_items", "1.0.0", None, Active), ("simd", "1.0.0", Some(27731), Active), ("default_type_params", "1.0.0", None, Accepted), - ("quote", "1.0.0", None, Active), - ("link_llvm_intrinsics", "1.0.0", None, Active), - ("linkage", "1.0.0", None, Active), + ("quote", "1.0.0", Some(29601), Active), + ("link_llvm_intrinsics", "1.0.0", Some(29602), Active), + ("linkage", "1.0.0", Some(29603), Active), ("struct_inherit", "1.0.0", None, Removed), ("quad_precision_float", "1.0.0", None, Removed), + // rustc internal ("rustc_diagnostic_macros", "1.0.0", None, Active), - ("unboxed_closures", "1.0.0", None, Active), - ("reflect", "1.0.0", None, Active), + ("unboxed_closures", "1.0.0", Some(29625), Active), + ("reflect", "1.0.0", Some(27749), Active), ("import_shadowing", "1.0.0", None, Removed), - ("advanced_slice_patterns", "1.0.0", None, Active), + ("advanced_slice_patterns", "1.0.0", Some(23121), Active), ("tuple_indexing", "1.0.0", None, Accepted), ("associated_types", "1.0.0", None, Accepted), - ("visible_private_types", "1.0.0", None, Active), + ("visible_private_types", "1.0.0", Some(29627), Active), ("slicing_syntax", "1.0.0", None, Accepted), ("box_syntax", "1.0.0", Some(27779), Active), ("placement_in_syntax", "1.0.0", Some(27779), Active), + + // rustc internal. ("pushpop_unsafe", "1.2.0", None, Active), - ("on_unimplemented", "1.0.0", None, Active), - ("simd_ffi", "1.0.0", None, Active), - ("allocator", "1.0.0", None, Active), - ("needs_allocator", "1.4.0", None, Active), - ("linked_from", "1.3.0", None, Active), + + ("on_unimplemented", "1.0.0", Some(29628), Active), + ("simd_ffi", "1.0.0", Some(27731), Active), + ("allocator", "1.0.0", Some(27389), Active), + ("needs_allocator", "1.4.0", Some(27389), Active), + ("linked_from", "1.3.0", Some(29629), Active), ("if_let", "1.0.0", None, Accepted), ("while_let", "1.0.0", None, Accepted), - ("plugin", "1.0.0", None, Active), - ("start", "1.0.0", None, Active), - ("main", "1.0.0", None, Active), + ("plugin", "1.0.0", Some(29597), Active), + ("start", "1.0.0", Some(29633), Active), + ("main", "1.0.0", Some(29634), Active), - ("fundamental", "1.0.0", None, Active), + ("fundamental", "1.0.0", Some(29635), Active), // A temporary feature gate used to enable parser extensions needed // to bootstrap fix for #5723. @@ -107,10 +113,10 @@ const KNOWN_FEATURES: &'static [(&'static str, &'static str, Option, Status ("opt_out_copy", "1.0.0", None, Removed), // OIBIT specific features - ("optin_builtin_traits", "1.0.0", None, Active), + ("optin_builtin_traits", "1.0.0", Some(13231), Active), // macro reexport needs more discussion and stabilization - ("macro_reexport", "1.0.0", None, Active), + ("macro_reexport", "1.0.0", Some(29638), Active), // These are used to test this portion of the compiler, they don't actually // mean anything @@ -118,19 +124,21 @@ const KNOWN_FEATURES: &'static [(&'static str, &'static str, Option, Status ("test_removed_feature", "1.0.0", None, Removed), // Allows use of #[staged_api] + // rustc internal ("staged_api", "1.0.0", None, Active), // Allows using items which are missing stability attributes + // rustc internal ("unmarked_api", "1.0.0", None, Active), // Allows using #![no_std] - ("no_std", "1.0.0", None, Active), + ("no_std", "1.0.0", Some(27701), Active), // Allows using #![no_core] - ("no_core", "1.3.0", None, Active), + ("no_core", "1.3.0", Some(29639), Active), // Allows using `box` in patterns; RFC 469 - ("box_patterns", "1.0.0", None, Active), + ("box_patterns", "1.0.0", Some(29641), Active), // Allows using the unsafe_no_drop_flag attribute (unlikely to // switch to Accepted; see RFC 320) @@ -141,75 +149,81 @@ const KNOWN_FEATURES: &'static [(&'static str, &'static str, Option, Status ("dropck_parametricity", "1.3.0", Some(28498), Active), // Allows the use of custom attributes; RFC 572 - ("custom_attribute", "1.0.0", None, Active), + ("custom_attribute", "1.0.0", Some(29642), Active), // Allows the use of #[derive(Anything)] as sugar for // #[derive_Anything]. - ("custom_derive", "1.0.0", None, Active), + ("custom_derive", "1.0.0", Some(29644), Active), // Allows the use of rustc_* attributes; RFC 572 - ("rustc_attrs", "1.0.0", None, Active), + ("rustc_attrs", "1.0.0", Some(29642), Active), // Allows the use of #[allow_internal_unstable]. This is an // attribute on macro_rules! and can't use the attribute handling // below (it has to be checked before expansion possibly makes // macros disappear). + // + // rustc internal ("allow_internal_unstable", "1.0.0", None, Active), // #23121. Array patterns have some hazards yet. - ("slice_patterns", "1.0.0", None, Active), + ("slice_patterns", "1.0.0", Some(23121), Active), // Allows use of unary negate on unsigned integers, e.g. -e for e: u8 - ("negate_unsigned", "1.0.0", None, Active), + ("negate_unsigned", "1.0.0", Some(29645), Active), // Allows the definition of associated constants in `trait` or `impl` // blocks. - ("associated_consts", "1.0.0", None, Active), + ("associated_consts", "1.0.0", Some(29646), Active), // Allows the definition of `const fn` functions. - ("const_fn", "1.2.0", None, Active), + ("const_fn", "1.2.0", Some(24111), Active), // Allows using #[prelude_import] on glob `use` items. + // + // rustc internal ("prelude_import", "1.2.0", None, Active), // Allows the definition recursive static items. - ("static_recursion", "1.3.0", None, Active), + ("static_recursion", "1.3.0", Some(29719), Active), // Allows default type parameters to influence type inference. - ("default_type_parameter_fallback", "1.3.0", None, Active), + ("default_type_parameter_fallback", "1.3.0", Some(27336), Active), // Allows associated type defaults - ("associated_type_defaults", "1.2.0", None, Active), - // Allows macros to appear in the type position. + ("associated_type_defaults", "1.2.0", Some(29661), Active), + // Allows macros to appear in the type position. ("type_macros", "1.3.0", Some(27336), Active), // allow `repr(simd)`, and importing the various simd intrinsics ("repr_simd", "1.4.0", Some(27731), Active), // Allows cfg(target_feature = "..."). - ("cfg_target_feature", "1.4.0", None, Active), + ("cfg_target_feature", "1.4.0", Some(29717), Active), // allow `extern "platform-intrinsic" { ... }` ("platform_intrinsics", "1.4.0", Some(27731), Active), // allow `#[unwind]` + // rust runtime internal ("unwind_attributes", "1.4.0", None, Active), // allow empty structs and enum variants with braces - ("braced_empty_structs", "1.5.0", None, Active), + ("braced_empty_structs", "1.5.0", Some(29720), Active), // allow overloading augmented assignment operations like `a += b` - ("augmented_assignments", "1.5.0", None, Active), + ("augmented_assignments", "1.5.0", Some(28235), Active), // allow `#[no_debug]` - ("no_debug", "1.5.0", None, Active), + ("no_debug", "1.5.0", Some(29721), Active), // allow `#[omit_gdb_pretty_printer_section]` + // rustc internal. ("omit_gdb_pretty_printer_section", "1.5.0", None, Active), // Allows cfg(target_vendor = "..."). - ("cfg_target_vendor", "1.5.0", None, Active), + ("cfg_target_vendor", "1.5.0", Some(29718), Active), ]; // (changing above list without updating src/doc/reference.md makes @cmr sad) @@ -867,6 +881,8 @@ impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> { self.context.span_handler.span_err(span, "empty tuple structs and enum variants \ are not allowed, use unit structs and \ enum variants instead"); + self.context.span_handler.span_help(span, "remove trailing `()` to make a unit \ + struct or unit enum variant"); } } visit::walk_struct_def(self, s) diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index d637343de04e8..66ee5aa12ca88 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -586,10 +586,10 @@ pub fn noop_fold_arg(Arg {id, pat, ty}: Arg, fld: &mut T) -> Arg { pub fn noop_fold_tt(tt: &TokenTree, fld: &mut T) -> TokenTree { match *tt { - TtToken(span, ref tok) => - TtToken(span, fld.fold_token(tok.clone())), - TtDelimited(span, ref delimed) => { - TtDelimited(span, Rc::new( + TokenTree::Token(span, ref tok) => + TokenTree::Token(span, fld.fold_token(tok.clone())), + TokenTree::Delimited(span, ref delimed) => { + TokenTree::Delimited(span, Rc::new( Delimited { delim: delimed.delim, open_span: delimed.open_span, @@ -598,8 +598,8 @@ pub fn noop_fold_tt(tt: &TokenTree, fld: &mut T) -> TokenTree { } )) }, - TtSequence(span, ref seq) => - TtSequence(span, + TokenTree::Sequence(span, ref seq) => + TokenTree::Sequence(span, Rc::new(SequenceRepetition { tts: fld.fold_tts(&seq.tts), separator: seq.separator.clone().map(|tok| fld.fold_token(tok)), @@ -673,7 +673,7 @@ pub fn noop_fold_interpolated(nt: token::Nonterminal, fld: &mut T) token::NtIdent(Box::new(fld.fold_ident(*id)), is_mod_name), token::NtMeta(meta_item) => token::NtMeta(fld.fold_meta_item(meta_item)), token::NtPath(path) => token::NtPath(Box::new(fld.fold_path(*path))), - token::NtTT(tt) => token::NtTT(P(fld.fold_tt(&*tt))), + token::NtTT(tt) => token::NtTT(P(fld.fold_tt(&tt))), token::NtArm(arm) => token::NtArm(fld.fold_arm(arm)), token::NtImplItem(arm) => token::NtImplItem(fld.fold_impl_item(arm) @@ -684,6 +684,7 @@ pub fn noop_fold_interpolated(nt: token::Nonterminal, fld: &mut T) token::NtGenerics(generics) => token::NtGenerics(fld.fold_generics(generics)), token::NtWhereClause(where_clause) => token::NtWhereClause(fld.fold_where_clause(where_clause)), + token::NtArg(arg) => token::NtArg(fld.fold_arg(arg)), } } diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index 8b001f2419c56..0cd27d1b0ccc3 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -23,7 +23,8 @@ #![crate_type = "rlib"] #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "https://doc.rust-lang.org/favicon.ico", - html_root_url = "https://doc.rust-lang.org/nightly/")] + html_root_url = "https://doc.rust-lang.org/nightly/", + test(attr(deny(warnings))))] #![feature(associated_consts)] #![feature(drain)] @@ -62,10 +63,11 @@ macro_rules! panictry { pub mod util { pub mod interner; + pub mod node_count; + pub mod parser; #[cfg(test)] pub mod parser_testing; pub mod small_vector; - pub mod parser; } pub mod diagnostics { diff --git a/src/libsyntax/parse/classify.rs b/src/libsyntax/parse/classify.rs index d46d078c776be..8b3faaaca146a 100644 --- a/src/libsyntax/parse/classify.rs +++ b/src/libsyntax/parse/classify.rs @@ -53,7 +53,7 @@ pub fn stmt_ends_with_semi(stmt: &ast::Stmt_) -> bool { ast::DeclItem(_) => false } } - ast::StmtExpr(ref e, _) => { expr_requires_semi_to_be_stmt(&**e) } + ast::StmtExpr(ref e, _) => { expr_requires_semi_to_be_stmt(e) } ast::StmtSemi(..) => { false } ast::StmtMac(..) => { false } } diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs index 9e38ffe7f0dc4..e1d8a4d8c5423 100644 --- a/src/libsyntax/parse/lexer/mod.rs +++ b/src/libsyntax/parse/lexer/mod.rs @@ -1081,11 +1081,12 @@ impl<'a> StringReader<'a> { if !self.curr_is('\'') { let last_bpos = self.last_pos; panic!(self.fatal_span_verbose( - // Byte offsetting here is okay because the - // character before position `start` is an - // ascii single quote. - start - BytePos(1), last_bpos, - "unterminated character constant".to_string())); + // Byte offsetting here is okay because the + // character before position `start` is an + // ascii single quote. + start - BytePos(1), last_bpos, + + String::from("character literal may only contain one codepoint"))); } let id = if valid { self.name_from(start) } else { token::intern("0") }; self.bump(); // advance curr past token diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index a468f0d1d98f1..7e2fd09a37316 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -116,7 +116,7 @@ pub fn parse_expr_from_source_str(name: String, sess: &ParseSess) -> P { let mut p = new_parser_from_source_str(sess, cfg, name, source); - maybe_aborted(panictry!(p.parse_expr_nopanic()), p) + maybe_aborted(panictry!(p.parse_expr()), p) } pub fn parse_item_from_source_str(name: String, @@ -125,7 +125,7 @@ pub fn parse_item_from_source_str(name: String, sess: &ParseSess) -> Option> { let mut p = new_parser_from_source_str(sess, cfg, name, source); - maybe_aborted(panictry!(p.parse_item_nopanic()), p) + maybe_aborted(panictry!(p.parse_item()), p) } pub fn parse_meta_from_source_str(name: String, @@ -148,7 +148,7 @@ pub fn parse_stmt_from_source_str(name: String, name, source ); - maybe_aborted(panictry!(p.parse_stmt_nopanic()), p) + maybe_aborted(panictry!(p.parse_stmt()), p) } // Warning: This parses with quote_depth > 0, which is not the default. @@ -446,10 +446,10 @@ fn filtered_float_lit(data: token::InternedString, suffix: Option<&str>, Some(suf) => { if suf.len() >= 2 && looks_like_width_suffix(&['f'], suf) { // if it looks like a width, lets try to be helpful. - sd.span_err(sp, &*format!("invalid width `{}` for float literal", &suf[1..])); + sd.span_err(sp, &format!("invalid width `{}` for float literal", &suf[1..])); sd.fileline_help(sp, "valid widths are 32 and 64"); } else { - sd.span_err(sp, &*format!("invalid suffix `{}` for float literal", suf)); + sd.span_err(sp, &format!("invalid suffix `{}` for float literal", suf)); sd.fileline_help(sp, "valid suffixes are `f32` and `f64`"); } @@ -619,11 +619,11 @@ pub fn integer_lit(s: &str, // i and u look like widths, so lets // give an error message along those lines if looks_like_width_suffix(&['i', 'u'], suf) { - sd.span_err(sp, &*format!("invalid width `{}` for integer literal", - &suf[1..])); + sd.span_err(sp, &format!("invalid width `{}` for integer literal", + &suf[1..])); sd.fileline_help(sp, "valid widths are 8, 16, 32 and 64"); } else { - sd.span_err(sp, &*format!("invalid suffix `{}` for numeric literal", suf)); + sd.span_err(sp, &format!("invalid suffix `{}` for numeric literal", suf)); sd.fileline_help(sp, "the suffix must be one of the integral types \ (`u32`, `isize`, etc)"); } @@ -669,7 +669,7 @@ mod tests { use std::rc::Rc; use codemap::{Span, BytePos, Pos, Spanned, NO_EXPANSION}; use owned_slice::OwnedSlice; - use ast; + use ast::{self, TokenTree}; use abi; use attr::{first_attr_value_str_by_name, AttrMetaMethods}; use parse; @@ -739,10 +739,10 @@ mod tests { match (tts.len(), tts.get(0), tts.get(1), tts.get(2), tts.get(3)) { ( 4, - Some(&ast::TtToken(_, token::Ident(name_macro_rules, token::Plain))), - Some(&ast::TtToken(_, token::Not)), - Some(&ast::TtToken(_, token::Ident(name_zip, token::Plain))), - Some(&ast::TtDelimited(_, ref macro_delimed)), + Some(&TokenTree::Token(_, token::Ident(name_macro_rules, token::Plain))), + Some(&TokenTree::Token(_, token::Not)), + Some(&TokenTree::Token(_, token::Ident(name_zip, token::Plain))), + Some(&TokenTree::Delimited(_, ref macro_delimed)), ) if name_macro_rules.name.as_str() == "macro_rules" && name_zip.name.as_str() == "zip" => { @@ -750,17 +750,17 @@ mod tests { match (tts.len(), tts.get(0), tts.get(1), tts.get(2)) { ( 3, - Some(&ast::TtDelimited(_, ref first_delimed)), - Some(&ast::TtToken(_, token::FatArrow)), - Some(&ast::TtDelimited(_, ref second_delimed)), + Some(&TokenTree::Delimited(_, ref first_delimed)), + Some(&TokenTree::Token(_, token::FatArrow)), + Some(&TokenTree::Delimited(_, ref second_delimed)), ) if macro_delimed.delim == token::Paren => { let tts = &first_delimed.tts[..]; match (tts.len(), tts.get(0), tts.get(1)) { ( 2, - Some(&ast::TtToken(_, token::Dollar)), - Some(&ast::TtToken(_, token::Ident(ident, token::Plain))), + Some(&TokenTree::Token(_, token::Dollar)), + Some(&TokenTree::Token(_, token::Ident(ident, token::Plain))), ) if first_delimed.delim == token::Paren && ident.name.as_str() == "a" => {}, @@ -770,8 +770,8 @@ mod tests { match (tts.len(), tts.get(0), tts.get(1)) { ( 2, - Some(&ast::TtToken(_, token::Dollar)), - Some(&ast::TtToken(_, token::Ident(ident, token::Plain))), + Some(&TokenTree::Token(_, token::Dollar)), + Some(&TokenTree::Token(_, token::Ident(ident, token::Plain))), ) if second_delimed.delim == token::Paren && ident.name.as_str() == "a" => {}, @@ -790,39 +790,39 @@ mod tests { let tts = string_to_tts("fn a (b : i32) { b; }".to_string()); let expected = vec![ - ast::TtToken(sp(0, 2), + TokenTree::Token(sp(0, 2), token::Ident(str_to_ident("fn"), token::IdentStyle::Plain)), - ast::TtToken(sp(3, 4), + TokenTree::Token(sp(3, 4), token::Ident(str_to_ident("a"), token::IdentStyle::Plain)), - ast::TtDelimited( + TokenTree::Delimited( sp(5, 14), Rc::new(ast::Delimited { delim: token::DelimToken::Paren, open_span: sp(5, 6), tts: vec![ - ast::TtToken(sp(6, 7), + TokenTree::Token(sp(6, 7), token::Ident(str_to_ident("b"), token::IdentStyle::Plain)), - ast::TtToken(sp(8, 9), + TokenTree::Token(sp(8, 9), token::Colon), - ast::TtToken(sp(10, 13), + TokenTree::Token(sp(10, 13), token::Ident(str_to_ident("i32"), token::IdentStyle::Plain)), ], close_span: sp(13, 14), })), - ast::TtDelimited( + TokenTree::Delimited( sp(15, 21), Rc::new(ast::Delimited { delim: token::DelimToken::Brace, open_span: sp(15, 16), tts: vec![ - ast::TtToken(sp(17, 18), + TokenTree::Token(sp(17, 18), token::Ident(str_to_ident("b"), token::IdentStyle::Plain)), - ast::TtToken(sp(18, 19), + TokenTree::Token(sp(18, 19), token::Semi) ], close_span: sp(20, 21), @@ -882,7 +882,7 @@ mod tests { #[test] fn parse_ident_pat () { let sess = ParseSess::new(); let mut parser = string_to_parser(&sess, "b".to_string()); - assert!(panictry!(parser.parse_pat_nopanic()) + assert!(panictry!(parser.parse_pat()) == P(ast::Pat{ id: ast::DUMMY_NODE_ID, node: ast::PatIdent(ast::BindByValue(ast::MutImmutable), diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 2401f6be78f9c..bde910838cbae 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -48,7 +48,6 @@ use ast::{StmtExpr, StmtSemi, StmtMac, VariantData, StructField}; use ast::{BiSub, StrStyle}; use ast::{SelfExplicit, SelfRegion, SelfStatic, SelfValue}; use ast::{Delimited, SequenceRepetition, TokenTree, TraitItem, TraitRef}; -use ast::{TtDelimited, TtSequence, TtToken}; use ast::{Ty, Ty_, TypeBinding, TyMac}; use ast::{TyFixedLengthVec, TyBareFn, TyTypeof, TyInfer}; use ast::{TyParam, TyParamBound, TyParen, TyPath, TyPolyTraitRef, TyPtr}; @@ -114,6 +113,13 @@ pub enum BoundParsingMode { Modified, } +/// `pub` should be parsed in struct fields and not parsed in variant fields +#[derive(Clone, Copy, PartialEq)] +pub enum ParsePub { + Yes, + No, +} + /// Possibly accept an `token::Interpolated` expression (a pre-parsed expression /// dropped into the token stream, which happens while parsing the result of /// macro expansion). Placement of these is not as complex as I feared it would @@ -356,37 +362,6 @@ impl<'a> Parser<'a> { } } - // Panicing fns (for now!) - // These functions are used by the quote_*!() syntax extensions, but shouldn't - // be used otherwise. - pub fn parse_expr_panic(&mut self) -> P { - panictry!(self.parse_expr_nopanic()) - } - - pub fn parse_item_panic(&mut self) -> Option> { - panictry!(self.parse_item_nopanic()) - } - - pub fn parse_pat_panic(&mut self) -> P { - panictry!(self.parse_pat_nopanic()) - } - - pub fn parse_arm_panic(&mut self) -> Arm { - panictry!(self.parse_arm_nopanic()) - } - - pub fn parse_ty_panic(&mut self) -> P { - panictry!(self.parse_ty_nopanic()) - } - - pub fn parse_stmt_panic(&mut self) -> Option> { - panictry!(self.parse_stmt_nopanic()) - } - - pub fn parse_attribute_panic(&mut self, permit_inner: bool) -> ast::Attribute { - panictry!(self.parse_attribute(permit_inner)) - } - /// Convert a token to a string using self's reader pub fn token_to_string(token: &token::Token) -> String { pprust::token_to_string(token) @@ -1191,7 +1166,7 @@ impl<'a> Parser<'a> { let ty = try!(p.parse_ty_sum()); let default = if p.check(&token::Eq) { try!(p.bump()); - let expr = try!(p.parse_expr_nopanic()); + let expr = try!(p.parse_expr()); try!(p.commit_expr_expecting(&expr, token::Semi)); Some(expr) } else { @@ -1258,7 +1233,7 @@ impl<'a> Parser<'a> { /// Parse a possibly mutable type pub fn parse_mt(&mut self) -> PResult { let mutbl = try!(self.parse_mutability()); - let t = try!(self.parse_ty_nopanic()); + let t = try!(self.parse_ty()); Ok(MutTy { ty: t, mutbl: mutbl }) } @@ -1268,7 +1243,7 @@ impl<'a> Parser<'a> { if try!(self.eat(&token::Not) ){ Ok(NoReturn(self.last_span)) } else { - Ok(Return(try!(self.parse_ty_nopanic()))) + Ok(Return(try!(self.parse_ty()))) } } else { let pos = self.span.lo; @@ -1279,7 +1254,7 @@ impl<'a> Parser<'a> { /// Parse a type in a context where `T1+T2` is allowed. pub fn parse_ty_sum(&mut self) -> PResult> { let lo = self.span.lo; - let lhs = try!(self.parse_ty_nopanic()); + let lhs = try!(self.parse_ty()); if !try!(self.eat(&token::BinOp(token::Plus)) ){ return Ok(lhs); @@ -1302,7 +1277,7 @@ impl<'a> Parser<'a> { } /// Parse a type. - pub fn parse_ty_nopanic(&mut self) -> PResult> { + pub fn parse_ty(&mut self) -> PResult> { maybe_whole!(no_clone self, NtTy); let lo = self.span.lo; @@ -1363,7 +1338,7 @@ impl<'a> Parser<'a> { // TYPEOF // In order to not be ambiguous, the type must be surrounded by parens. try!(self.expect(&token::OpenDelim(token::Paren))); - let e = try!(self.parse_expr_nopanic()); + let e = try!(self.parse_expr()); try!(self.expect(&token::CloseDelim(token::Paren))); TyTypeof(e) } else if try!(self.eat_lt()) { @@ -1423,7 +1398,7 @@ impl<'a> Parser<'a> { known as `*const T`"); MutImmutable }; - let t = try!(self.parse_ty_nopanic()); + let t = try!(self.parse_ty()); Ok(MutTy { ty: t, mutbl: mutbl }) } @@ -1449,10 +1424,12 @@ impl<'a> Parser<'a> { /// This version of parse arg doesn't necessarily require /// identifier names. pub fn parse_arg_general(&mut self, require_name: bool) -> PResult { + maybe_whole!(no_clone self, NtArg); + let pat = if require_name || self.is_named_argument() { debug!("parse_arg_general parse_pat (require_name:{})", require_name); - let pat = try!(self.parse_pat_nopanic()); + let pat = try!(self.parse_pat()); try!(self.expect(&token::Colon)); pat @@ -1479,7 +1456,7 @@ impl<'a> Parser<'a> { /// Parse an argument in a lambda header e.g. |arg, arg| pub fn parse_fn_block_arg(&mut self) -> PResult { - let pat = try!(self.parse_pat_nopanic()); + let pat = try!(self.parse_pat()); let t = if try!(self.eat(&token::Colon) ){ try!(self.parse_ty_sum()) } else { @@ -1499,7 +1476,7 @@ impl<'a> Parser<'a> { pub fn maybe_parse_fixed_length_of_vec(&mut self) -> PResult>> { if self.check(&token::Semi) { try!(self.bump()); - Ok(Some(try!(self.parse_expr_nopanic()))) + Ok(Some(try!(self.parse_expr()))) } else { Ok(None) } @@ -1724,7 +1701,7 @@ impl<'a> Parser<'a> { |p| p.parse_ty_sum())); let output_ty = if try!(self.eat(&token::RArrow) ){ - Some(try!(self.parse_ty_nopanic())) + Some(try!(self.parse_ty())) } else { None }; @@ -1843,7 +1820,7 @@ impl<'a> Parser<'a> { }); } _ => { - return Err(self.fatal(&format!("expected a lifetime name"))); + return Err(self.fatal("expected a lifetime name")); } } } @@ -1929,7 +1906,7 @@ impl<'a> Parser<'a> { let i = try!(self.parse_ident()); let hi = self.last_span.hi; try!(self.expect(&token::Colon)); - let e = try!(self.parse_expr_nopanic()); + let e = try!(self.parse_expr()); Ok(ast::Field { ident: spanned(lo, hi, i), span: mk_sp(lo, e.span.hi), @@ -2043,7 +2020,7 @@ impl<'a> Parser<'a> { let mut es = vec![]; let mut trailing_comma = false; while self.token != token::CloseDelim(token::Paren) { - es.push(try!(self.parse_expr_nopanic())); + es.push(try!(self.parse_expr())); try!(self.commit_expr(&**es.last().unwrap(), &[], &[token::Comma, token::CloseDelim(token::Paren)])); if self.check(&token::Comma) { @@ -2089,11 +2066,11 @@ impl<'a> Parser<'a> { ex = ExprVec(Vec::new()); } else { // Nonempty vector. - let first_expr = try!(self.parse_expr_nopanic()); + let first_expr = try!(self.parse_expr()); if self.check(&token::Semi) { // Repeating array syntax: [ 0; 512 ] try!(self.bump()); - let count = try!(self.parse_expr_nopanic()); + let count = try!(self.parse_expr()); try!(self.expect(&token::CloseDelim(token::Bracket))); ex = ExprRepeat(first_expr, count); } else if self.check(&token::Comma) { @@ -2102,7 +2079,7 @@ impl<'a> Parser<'a> { let remaining_exprs = try!(self.parse_seq_to_end( &token::CloseDelim(token::Bracket), seq_sep_trailing_allowed(token::Comma), - |p| Ok(try!(p.parse_expr_nopanic())) + |p| Ok(try!(p.parse_expr())) )); let mut exprs = vec!(first_expr); exprs.extend(remaining_exprs); @@ -2181,7 +2158,7 @@ impl<'a> Parser<'a> { } if try!(self.eat_keyword(keywords::Return) ){ if self.token.can_begin_expr() { - let e = try!(self.parse_expr_nopanic()); + let e = try!(self.parse_expr()); hi = e.span.hi; ex = ExprRet(Some(e)); } else { @@ -2235,7 +2212,7 @@ impl<'a> Parser<'a> { while self.token != token::CloseDelim(token::Brace) { if try!(self.eat(&token::DotDot) ){ - base = Some(try!(self.parse_expr_nopanic())); + base = Some(try!(self.parse_expr())); break; } @@ -2311,7 +2288,7 @@ impl<'a> Parser<'a> { &token::OpenDelim(token::Paren), &token::CloseDelim(token::Paren), seq_sep_trailing_allowed(token::Comma), - |p| Ok(try!(p.parse_expr_nopanic())) + |p| Ok(try!(p.parse_expr())) )); hi = self.last_span.hi; @@ -2388,7 +2365,7 @@ impl<'a> Parser<'a> { &token::OpenDelim(token::Paren), &token::CloseDelim(token::Paren), seq_sep_trailing_allowed(token::Comma), - |p| Ok(try!(p.parse_expr_nopanic())) + |p| Ok(try!(p.parse_expr())) )); hi = self.last_span.hi; @@ -2400,7 +2377,7 @@ impl<'a> Parser<'a> { // Could be either an index expression or a slicing expression. token::OpenDelim(token::Bracket) => { try!(self.bump()); - let ix = try!(self.parse_expr_nopanic()); + let ix = try!(self.parse_expr()); hi = self.span.hi; try!(self.commit_expr_expecting(&*ix, token::CloseDelim(token::Bracket))); let index = self.mk_index(e, ix); @@ -2428,7 +2405,7 @@ impl<'a> Parser<'a> { )); let (sep, repeat) = try!(self.parse_sep_and_kleene_op()); let name_num = macro_parser::count_names(&seq); - return Ok(TtSequence(mk_sp(sp.lo, seq_span.hi), + return Ok(TokenTree::Sequence(mk_sp(sp.lo, seq_span.hi), Rc::new(SequenceRepetition { tts: seq, separator: sep, @@ -2437,7 +2414,7 @@ impl<'a> Parser<'a> { }))); } else if self.token.is_keyword_allow_following_colon(keywords::Crate) { try!(self.bump()); - return Ok(TtToken(sp, SpecialVarNt(SpecialMacroVar::CrateMacroVar))); + return Ok(TokenTree::Token(sp, SpecialVarNt(SpecialMacroVar::CrateMacroVar))); } else { sp = mk_sp(sp.lo, self.span.hi); let namep = match self.token { token::Ident(_, p) => p, _ => token::Plain }; @@ -2459,9 +2436,9 @@ impl<'a> Parser<'a> { sp = mk_sp(sp.lo, self.span.hi); let kindp = match self.token { token::Ident(_, p) => p, _ => token::Plain }; let nt_kind = try!(self.parse_ident()); - Ok(TtToken(sp, MatchNt(name, nt_kind, namep, kindp))) + Ok(TokenTree::Token(sp, MatchNt(name, nt_kind, namep, kindp))) } else { - Ok(TtToken(sp, SubstNt(name, namep))) + Ok(TokenTree::Token(sp, SubstNt(name, namep))) } } @@ -2509,7 +2486,7 @@ impl<'a> Parser<'a> { /// parse a single token tree from the input. pub fn parse_token_tree(&mut self) -> PResult { // FIXME #6994: currently, this is too eager. It - // parses token trees but also identifies TtSequence's + // parses token trees but also identifies TokenType::Sequence's // and token::SubstNt's; it's too early to know yet // whether something will be a nonterminal or a seq // yet. @@ -2540,7 +2517,7 @@ impl<'a> Parser<'a> { p.parse_unquoted() } _ => { - Ok(TtToken(p.span, try!(p.bump_and_get()))) + Ok(TokenTree::Token(p.span, try!(p.bump_and_get()))) } } } @@ -2579,7 +2556,7 @@ impl<'a> Parser<'a> { // Expand to cover the entire delimited token tree let span = Span { hi: close_span.hi, ..pre_span }; - Ok(TtDelimited(span, Rc::new(Delimited { + Ok(TokenTree::Delimited(span, Rc::new(Delimited { delim: delim, open_span: open_span, tts: tts, @@ -2675,9 +2652,9 @@ impl<'a> Parser<'a> { // Semi-statement forms are odd. See https://github.com/rust-lang/rust/issues/29071 return Ok(lhs); } - let cur_op_span = self.span; self.expected_tokens.push(TokenType::Operator); while let Some(op) = AssocOp::from_token(&self.token) { + let cur_op_span = self.span; let restrictions = if op.is_assign_like() { self.restrictions & Restrictions::RESTRICTION_NO_STRUCT_LITERAL } else { @@ -2692,7 +2669,7 @@ impl<'a> Parser<'a> { } // Special cases: if op == AssocOp::As { - let rhs = try!(self.parse_ty_nopanic()); + let rhs = try!(self.parse_ty()); lhs = self.mk_expr(lhs.span.lo, rhs.span.hi, ExprCast(lhs, rhs)); continue } else if op == AssocOp::DotDot { @@ -2845,7 +2822,7 @@ impl<'a> Parser<'a> { pub fn parse_if_let_expr(&mut self) -> PResult> { let lo = self.last_span.lo; try!(self.expect_keyword(keywords::Let)); - let pat = try!(self.parse_pat_nopanic()); + let pat = try!(self.parse_pat()); try!(self.expect(&token::Eq)); let expr = try!(self.parse_expr_res(Restrictions::RESTRICTION_NO_STRUCT_LITERAL)); let thn = try!(self.parse_block()); @@ -2867,7 +2844,7 @@ impl<'a> Parser<'a> { DefaultReturn(_) => { // If no explicit return type is given, parse any // expr and wrap it up in a dummy block: - let body_expr = try!(self.parse_expr_nopanic()); + let body_expr = try!(self.parse_expr()); P(ast::Block { id: ast::DUMMY_NODE_ID, stmts: vec![], @@ -2903,7 +2880,7 @@ impl<'a> Parser<'a> { span_lo: BytePos) -> PResult> { // Parse: `for in ` - let pat = try!(self.parse_pat_nopanic()); + let pat = try!(self.parse_pat()); try!(self.expect_keyword(keywords::In)); let expr = try!(self.parse_expr_res(Restrictions::RESTRICTION_NO_STRUCT_LITERAL)); let loop_block = try!(self.parse_block()); @@ -2928,7 +2905,7 @@ impl<'a> Parser<'a> { pub fn parse_while_let_expr(&mut self, opt_ident: Option, span_lo: BytePos) -> PResult> { try!(self.expect_keyword(keywords::Let)); - let pat = try!(self.parse_pat_nopanic()); + let pat = try!(self.parse_pat()); try!(self.expect(&token::Eq)); let expr = try!(self.parse_expr_res(Restrictions::RESTRICTION_NO_STRUCT_LITERAL)); let body = try!(self.parse_block()); @@ -2955,21 +2932,21 @@ impl<'a> Parser<'a> { } let mut arms: Vec = Vec::new(); while self.token != token::CloseDelim(token::Brace) { - arms.push(try!(self.parse_arm_nopanic())); + arms.push(try!(self.parse_arm())); } let hi = self.span.hi; try!(self.bump()); return Ok(self.mk_expr(lo, hi, ExprMatch(discriminant, arms))); } - pub fn parse_arm_nopanic(&mut self) -> PResult { + pub fn parse_arm(&mut self) -> PResult { maybe_whole!(no_clone self, NtArm); let attrs = try!(self.parse_outer_attributes()); let pats = try!(self.parse_pats()); let mut guard = None; if try!(self.eat_keyword(keywords::If) ){ - guard = Some(try!(self.parse_expr_nopanic())); + guard = Some(try!(self.parse_expr())); } try!(self.expect(&token::FatArrow)); let expr = try!(self.parse_expr_res(Restrictions::RESTRICTION_STMT_EXPR)); @@ -2993,7 +2970,7 @@ impl<'a> Parser<'a> { } /// Parse an expression - pub fn parse_expr_nopanic(&mut self) -> PResult> { + pub fn parse_expr(&mut self) -> PResult> { self.parse_expr_res(Restrictions::empty()) } @@ -3019,7 +2996,7 @@ impl<'a> Parser<'a> { fn parse_initializer(&mut self) -> PResult>> { if self.check(&token::Eq) { try!(self.bump()); - Ok(Some(try!(self.parse_expr_nopanic()))) + Ok(Some(try!(self.parse_expr()))) } else { Ok(None) } @@ -3029,7 +3006,7 @@ impl<'a> Parser<'a> { fn parse_pats(&mut self) -> PResult>> { let mut pats = Vec::new(); loop { - pats.push(try!(self.parse_pat_nopanic())); + pats.push(try!(self.parse_pat())); if self.check(&token::BinOp(token::Or)) { try!(self.bump());} else { return Ok(pats); } }; @@ -3038,11 +3015,11 @@ impl<'a> Parser<'a> { fn parse_pat_tuple_elements(&mut self) -> PResult>> { let mut fields = vec![]; if !self.check(&token::CloseDelim(token::Paren)) { - fields.push(try!(self.parse_pat_nopanic())); + fields.push(try!(self.parse_pat())); if self.look_ahead(1, |t| *t != token::CloseDelim(token::Paren)) { while try!(self.eat(&token::Comma)) && !self.check(&token::CloseDelim(token::Paren)) { - fields.push(try!(self.parse_pat_nopanic())); + fields.push(try!(self.parse_pat())); } } if fields.len() == 1 { @@ -3090,7 +3067,7 @@ impl<'a> Parser<'a> { } } - let subpat = try!(self.parse_pat_nopanic()); + let subpat = try!(self.parse_pat()); if before_slice && self.check(&token::DotDot) { try!(self.bump()); slice = Some(subpat); @@ -3138,7 +3115,7 @@ impl<'a> Parser<'a> { // Parsing a pattern of the form "fieldname: pat" let fieldname = try!(self.parse_ident()); try!(self.bump()); - let pat = try!(self.parse_pat_nopanic()); + let pat = try!(self.parse_pat()); hi = pat.span.hi; (pat, fieldname, false) } else { @@ -3209,7 +3186,7 @@ impl<'a> Parser<'a> { } /// Parse a pattern. - pub fn parse_pat_nopanic(&mut self) -> PResult> { + pub fn parse_pat(&mut self) -> PResult> { maybe_whole!(self, NtPat); let lo = self.span.lo; @@ -3228,7 +3205,7 @@ impl<'a> Parser<'a> { return Err(self.fatal(&format!("unexpected lifetime `{}` in pattern", ident))); } - let subpat = try!(self.parse_pat_nopanic()); + let subpat = try!(self.parse_pat()); pat = PatRegion(subpat, mutbl); } token::OpenDelim(token::Paren) => { @@ -3256,7 +3233,7 @@ impl<'a> Parser<'a> { pat = try!(self.parse_pat_ident(BindByRef(mutbl))); } else if try!(self.eat_keyword(keywords::Box)) { // Parse box pat - let subpat = try!(self.parse_pat_nopanic()); + let subpat = try!(self.parse_pat()); pat = PatBox(subpat); } else if self.is_path_start() { // Parse pattern starting with a path @@ -3328,7 +3305,7 @@ impl<'a> Parser<'a> { &token::OpenDelim(token::Paren), &token::CloseDelim(token::Paren), seq_sep_trailing_allowed(token::Comma), - |p| p.parse_pat_nopanic())); + |p| p.parse_pat())); pat = PatEnum(path, Some(args)); } } @@ -3379,7 +3356,7 @@ impl<'a> Parser<'a> { let last_span = self.last_span; let name = codemap::Spanned{span: last_span, node: ident}; let sub = if try!(self.eat(&token::At) ){ - Some(try!(self.parse_pat_nopanic())) + Some(try!(self.parse_pat())) } else { None }; @@ -3403,7 +3380,7 @@ impl<'a> Parser<'a> { /// Parse a local variable declaration fn parse_local(&mut self) -> PResult> { let lo = self.span.lo; - let pat = try!(self.parse_pat_nopanic()); + let pat = try!(self.parse_pat()); let mut ty = None; if try!(self.eat(&token::Colon) ){ @@ -3460,7 +3437,7 @@ impl<'a> Parser<'a> { } /// Parse a statement. may include decl. - pub fn parse_stmt_nopanic(&mut self) -> PResult>> { + pub fn parse_stmt(&mut self) -> PResult>> { Ok(try!(self.parse_stmt_()).map(P)) } @@ -3891,7 +3868,7 @@ impl<'a> Parser<'a> { self.span_err(self.span, &msg); let span_hi = self.span.hi; - let span_hi = if self.parse_ty_nopanic().is_ok() { + let span_hi = if self.parse_ty().is_ok() { self.span.hi } else { span_hi @@ -3935,7 +3912,7 @@ impl<'a> Parser<'a> { let span = p.span; p.span_warn(span, "whoops, no =?"); } - let ty = try!(p.parse_ty_nopanic()); + let ty = try!(p.parse_ty()); let hi = ty.span.hi; let span = mk_sp(lo, hi); return Ok(P(TypeBinding{id: ast::DUMMY_NODE_ID, @@ -3959,7 +3936,7 @@ impl<'a> Parser<'a> { /// Parses an optional `where` clause and places it in `generics`. /// - /// ``` + /// ```ignore /// where T : Trait + 'b, 'a : 'b /// ``` pub fn parse_where_clause(&mut self) -> PResult { @@ -4016,7 +3993,7 @@ impl<'a> Parser<'a> { vec![] }; - let bounded_ty = try!(self.parse_ty_nopanic()); + let bounded_ty = try!(self.parse_ty()); if try!(self.eat(&token::Colon) ){ let bounds = try!(self.parse_ty_param_bounds(BoundParsingMode::Bare)); @@ -4039,7 +4016,7 @@ impl<'a> Parser<'a> { parsed_something = true; } else if try!(self.eat(&token::Eq) ){ - // let ty = try!(self.parse_ty_nopanic()); + // let ty = try!(self.parse_ty()); let hi = self.last_span.hi; let span = mk_sp(lo, hi); // where_clause.predicates.push( @@ -4455,7 +4432,7 @@ impl<'a> Parser<'a> { try!(self.expect(&token::Colon)); let typ = try!(self.parse_ty_sum()); try!(self.expect(&token::Eq)); - let expr = try!(self.parse_expr_nopanic()); + let expr = try!(self.parse_expr()); try!(self.commit_expr_expecting(&expr, token::Semi)); (name, ConstImplItem(typ, expr)) } else { @@ -4687,18 +4664,23 @@ impl<'a> Parser<'a> { VariantData::Unit(ast::DUMMY_NODE_ID) } else { // If we see: `struct Foo where T: Copy { ... }` - VariantData::Struct(try!(self.parse_record_struct_body()), ast::DUMMY_NODE_ID) + VariantData::Struct(try!(self.parse_record_struct_body(ParsePub::Yes)), + ast::DUMMY_NODE_ID) } // No `where` so: `struct Foo;` } else if try!(self.eat(&token::Semi) ){ VariantData::Unit(ast::DUMMY_NODE_ID) // Record-style struct definition } else if self.token == token::OpenDelim(token::Brace) { - VariantData::Struct(try!(self.parse_record_struct_body()), ast::DUMMY_NODE_ID) + VariantData::Struct(try!(self.parse_record_struct_body(ParsePub::Yes)), + ast::DUMMY_NODE_ID) // Tuple-style struct definition with optional where-clause. } else if self.token == token::OpenDelim(token::Paren) { - VariantData::Tuple(try!(self.parse_tuple_struct_body(&mut generics)), - ast::DUMMY_NODE_ID) + let body = VariantData::Tuple(try!(self.parse_tuple_struct_body(ParsePub::Yes)), + ast::DUMMY_NODE_ID); + generics.where_clause = try!(self.parse_where_clause()); + try!(self.expect(&token::Semi)); + body } else { let token_str = self.this_token_to_string(); return Err(self.fatal(&format!("expected `where`, `{{`, `(`, or `;` after struct \ @@ -4708,11 +4690,11 @@ impl<'a> Parser<'a> { Ok((class_name, ItemStruct(vdata, generics), None)) } - pub fn parse_record_struct_body(&mut self) -> PResult> { + pub fn parse_record_struct_body(&mut self, parse_pub: ParsePub) -> PResult> { let mut fields = Vec::new(); if try!(self.eat(&token::OpenDelim(token::Brace)) ){ while self.token != token::CloseDelim(token::Brace) { - fields.push(try!(self.parse_struct_decl_field(true))); + fields.push(try!(self.parse_struct_decl_field(parse_pub))); } try!(self.bump()); @@ -4726,9 +4708,7 @@ impl<'a> Parser<'a> { Ok(fields) } - pub fn parse_tuple_struct_body(&mut self, - generics: &mut ast::Generics) - -> PResult> { + pub fn parse_tuple_struct_body(&mut self, parse_pub: ParsePub) -> PResult> { // This is the case where we find `struct Foo(T) where T: Copy;` // Unit like structs are handled in parse_item_struct function let fields = try!(self.parse_unspanned_seq( @@ -4739,7 +4719,13 @@ impl<'a> Parser<'a> { let attrs = try!(p.parse_outer_attributes()); let lo = p.span.lo; let struct_field_ = ast::StructField_ { - kind: UnnamedField(try!(p.parse_visibility())), + kind: UnnamedField ( + if parse_pub == ParsePub::Yes { + try!(p.parse_visibility()) + } else { + Inherited + } + ), id: ast::DUMMY_NODE_ID, ty: try!(p.parse_ty_sum()), attrs: attrs, @@ -4747,8 +4733,6 @@ impl<'a> Parser<'a> { Ok(spanned(lo, p.span.hi, struct_field_)) })); - generics.where_clause = try!(self.parse_where_clause()); - try!(self.expect(&token::Semi)); Ok(fields) } @@ -4776,12 +4760,12 @@ impl<'a> Parser<'a> { } /// Parse an element of a struct definition - fn parse_struct_decl_field(&mut self, allow_pub: bool) -> PResult { + fn parse_struct_decl_field(&mut self, parse_pub: ParsePub) -> PResult { let attrs = try!(self.parse_outer_attributes()); if try!(self.eat_keyword(keywords::Pub) ){ - if !allow_pub { + if parse_pub == ParsePub::No { let span = self.last_span; self.span_err(span, "`pub` is not allowed here"); } @@ -4800,7 +4784,7 @@ impl<'a> Parser<'a> { /// Given a termination token, parse all of the items in a module fn parse_mod_items(&mut self, term: &token::Token, inner_lo: BytePos) -> PResult { let mut items = vec![]; - while let Some(item) = try!(self.parse_item_nopanic()) { + while let Some(item) = try!(self.parse_item()) { items.push(item); } @@ -4826,7 +4810,7 @@ impl<'a> Parser<'a> { try!(self.expect(&token::Colon)); let ty = try!(self.parse_ty_sum()); try!(self.expect(&token::Eq)); - let e = try!(self.parse_expr_nopanic()); + let e = try!(self.parse_expr()); try!(self.commit_expr_expecting(&*e, token::Semi)); let item = match m { Some(m) => ItemStatic(ty, m, e), @@ -5134,18 +5118,6 @@ impl<'a> Parser<'a> { Ok((ident, ItemTy(ty, tps), None)) } - /// Parse a structure-like enum variant definition - /// this should probably be renamed or refactored... - fn parse_struct_def(&mut self) -> PResult { - let mut fields: Vec = Vec::new(); - while self.token != token::CloseDelim(token::Brace) { - fields.push(try!(self.parse_struct_decl_field(false))); - } - try!(self.bump()); - - Ok(VariantData::Struct(fields, ast::DUMMY_NODE_ID)) - } - /// Parse the part of an "enum" decl following the '{' fn parse_enum_def(&mut self, _generics: &ast::Generics) -> PResult { let mut variants = Vec::new(); @@ -5158,34 +5130,21 @@ impl<'a> Parser<'a> { let struct_def; let mut disr_expr = None; let ident = try!(self.parse_ident()); - if try!(self.eat(&token::OpenDelim(token::Brace)) ){ + if self.check(&token::OpenDelim(token::Brace)) { // Parse a struct variant. all_nullary = false; - struct_def = try!(self.parse_struct_def()); + struct_def = VariantData::Struct(try!(self.parse_record_struct_body(ParsePub::No)), + ast::DUMMY_NODE_ID); } else if self.check(&token::OpenDelim(token::Paren)) { all_nullary = false; - let arg_tys = try!(self.parse_enum_variant_seq( - &token::OpenDelim(token::Paren), - &token::CloseDelim(token::Paren), - seq_sep_trailing_allowed(token::Comma), - |p| p.parse_ty_sum() - )); - let mut fields = Vec::new(); - for ty in arg_tys { - fields.push(Spanned { span: ty.span, node: ast::StructField_ { - ty: ty, - kind: ast::UnnamedField(ast::Inherited), - attrs: Vec::new(), - id: ast::DUMMY_NODE_ID, - }}); - } - struct_def = ast::VariantData::Tuple(fields, ast::DUMMY_NODE_ID); + struct_def = VariantData::Tuple(try!(self.parse_tuple_struct_body(ParsePub::No)), + ast::DUMMY_NODE_ID); } else if try!(self.eat(&token::Eq) ){ - disr_expr = Some(try!(self.parse_expr_nopanic())); + disr_expr = Some(try!(self.parse_expr())); any_disr = disr_expr.as_ref().map(|expr| expr.span); - struct_def = ast::VariantData::Unit(ast::DUMMY_NODE_ID); + struct_def = VariantData::Unit(ast::DUMMY_NODE_ID); } else { - struct_def = ast::VariantData::Unit(ast::DUMMY_NODE_ID); + struct_def = VariantData::Unit(ast::DUMMY_NODE_ID); } let vr = ast::Variant_ { @@ -5613,7 +5572,7 @@ impl<'a> Parser<'a> { Ok(None) } - pub fn parse_item_nopanic(&mut self) -> PResult>> { + pub fn parse_item(&mut self) -> PResult>> { let attrs = try!(self.parse_outer_attributes()); self.parse_item_(attrs, true) } diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index ba24dc3c0a74e..5e4449af60405 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -381,12 +381,13 @@ pub enum Nonterminal { NtMeta(P), NtPath(Box), NtTT(P), // needs P'ed to break a circularity - // These is not exposed to macros, but is used by quasiquote. + // These are not exposed to macros, but are used by quasiquote. NtArm(ast::Arm), NtImplItem(P), NtTraitItem(P), NtGenerics(ast::Generics), NtWhereClause(ast::WhereClause), + NtArg(ast::Arg), } impl fmt::Debug for Nonterminal { @@ -407,6 +408,7 @@ impl fmt::Debug for Nonterminal { NtTraitItem(..) => f.pad("NtTraitItem(..)"), NtGenerics(..) => f.pad("NtGenerics(..)"), NtWhereClause(..) => f.pad("NtWhereClause(..)"), + NtArg(..) => f.pad("NtArg(..)"), } } } diff --git a/src/libsyntax/print/pp.rs b/src/libsyntax/print/pp.rs index 7c5a46465f513..cbbd5289a5a2d 100644 --- a/src/libsyntax/print/pp.rs +++ b/src/libsyntax/print/pp.rs @@ -11,8 +11,10 @@ //! This pretty-printer is a direct reimplementation of Philip Karlton's //! Mesa pretty-printer, as described in appendix A of //! -//! STAN-CS-79-770: "Pretty Printing", by Derek C. Oppen. -//! Stanford Department of Computer Science, 1979. +//! ````ignore +//! STAN-CS-79-770: "Pretty Printing", by Derek C. Oppen. +//! Stanford Department of Computer Science, 1979. +//! ```` //! //! The algorithm's aim is to break a stream into as few lines as possible //! while respecting the indentation-consistency requirements of the enclosing diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 2ab94b41c74a2..5b8f5c0aef6f7 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -11,7 +11,7 @@ pub use self::AnnNode::*; use abi; -use ast; +use ast::{self, TokenTree}; use ast::{RegionTyParamBound, TraitTyParamBound, TraitBoundModifier}; use ast_util; use util::parser::AssocOp; @@ -305,6 +305,7 @@ pub fn token_to_string(tok: &Token) -> String { token::NtTraitItem(ref e) => trait_item_to_string(&**e), token::NtGenerics(ref e) => generics_to_string(&*e), token::NtWhereClause(ref e) => where_clause_to_string(&*e), + token::NtArg(ref e) => arg_to_string(&*e), } } } @@ -1452,7 +1453,7 @@ impl<'a> State<'a> { /// expression arguments as expressions). It can be done! I think. pub fn print_tt(&mut self, tt: &ast::TokenTree) -> io::Result<()> { match *tt { - ast::TtToken(_, ref tk) => { + TokenTree::Token(_, ref tk) => { try!(word(&mut self.s, &token_to_string(tk))); match *tk { parse::token::DocComment(..) => { @@ -1461,14 +1462,14 @@ impl<'a> State<'a> { _ => Ok(()) } } - ast::TtDelimited(_, ref delimed) => { + TokenTree::Delimited(_, ref delimed) => { try!(word(&mut self.s, &token_to_string(&delimed.open_token()))); try!(space(&mut self.s)); try!(self.print_tts(&delimed.tts)); try!(space(&mut self.s)); word(&mut self.s, &token_to_string(&delimed.close_token())) }, - ast::TtSequence(_, ref seq) => { + TokenTree::Sequence(_, ref seq) => { try!(word(&mut self.s, "$(")); for tt_elt in &seq.tts { try!(self.print_tt(tt_elt)); @@ -1499,9 +1500,9 @@ impl<'a> State<'a> { // There should be no space between the module name and the following `::` in paths, // otherwise imported macros get re-parsed from crate metadata incorrectly (#20701) suppress_space = match tt { - &ast::TtToken(_, token::Ident(_, token::ModName)) | - &ast::TtToken(_, token::MatchNt(_, _, _, token::ModName)) | - &ast::TtToken(_, token::SubstNt(_, token::ModName)) => true, + &TokenTree::Token(_, token::Ident(_, token::ModName)) | + &TokenTree::Token(_, token::MatchNt(_, _, _, token::ModName)) | + &TokenTree::Token(_, token::SubstNt(_, token::ModName)) => true, _ => false } } diff --git a/src/libsyntax/util/node_count.rs b/src/libsyntax/util/node_count.rs new file mode 100644 index 0000000000000..e692ec4452cdd --- /dev/null +++ b/src/libsyntax/util/node_count.rs @@ -0,0 +1,164 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Simply gives a rought count of the number of nodes in an AST. + +use visit::*; +use ast::*; +use codemap::Span; + +pub struct NodeCounter { + pub count: usize, +} + +impl NodeCounter { + pub fn new() -> NodeCounter { + NodeCounter { + count: 0, + } + } +} + +impl<'v> Visitor<'v> for NodeCounter { + fn visit_ident(&mut self, span: Span, ident: Ident) { + self.count += 1; + walk_ident(self, span, ident); + } + fn visit_mod(&mut self, m: &'v Mod, _s: Span, _n: NodeId) { + self.count += 1; + walk_mod(self, m) + } + fn visit_foreign_item(&mut self, i: &'v ForeignItem) { + self.count += 1; + walk_foreign_item(self, i) + } + fn visit_item(&mut self, i: &'v Item) { + self.count += 1; + walk_item(self, i) + } + fn visit_local(&mut self, l: &'v Local) { + self.count += 1; + walk_local(self, l) + } + fn visit_block(&mut self, b: &'v Block) { + self.count += 1; + walk_block(self, b) + } + fn visit_stmt(&mut self, s: &'v Stmt) { + self.count += 1; + walk_stmt(self, s) + } + fn visit_arm(&mut self, a: &'v Arm) { + self.count += 1; + walk_arm(self, a) + } + fn visit_pat(&mut self, p: &'v Pat) { + self.count += 1; + walk_pat(self, p) + } + fn visit_decl(&mut self, d: &'v Decl) { + self.count += 1; + walk_decl(self, d) + } + fn visit_expr(&mut self, ex: &'v Expr) { + self.count += 1; + walk_expr(self, ex) + } + fn visit_ty(&mut self, t: &'v Ty) { + self.count += 1; + walk_ty(self, t) + } + fn visit_generics(&mut self, g: &'v Generics) { + self.count += 1; + walk_generics(self, g) + } + fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v FnDecl, b: &'v Block, s: Span, _: NodeId) { + self.count += 1; + walk_fn(self, fk, fd, b, s) + } + fn visit_trait_item(&mut self, ti: &'v TraitItem) { + self.count += 1; + walk_trait_item(self, ti) + } + fn visit_impl_item(&mut self, ii: &'v ImplItem) { + self.count += 1; + walk_impl_item(self, ii) + } + fn visit_trait_ref(&mut self, t: &'v TraitRef) { + self.count += 1; + walk_trait_ref(self, t) + } + fn visit_ty_param_bound(&mut self, bounds: &'v TyParamBound) { + self.count += 1; + walk_ty_param_bound(self, bounds) + } + fn visit_poly_trait_ref(&mut self, t: &'v PolyTraitRef, m: &'v TraitBoundModifier) { + self.count += 1; + walk_poly_trait_ref(self, t, m) + } + fn visit_variant_data(&mut self, s: &'v VariantData, _: Ident, + _: &'v Generics, _: NodeId, _: Span) { + self.count += 1; + walk_struct_def(self, s) + } + fn visit_struct_field(&mut self, s: &'v StructField) { + self.count += 1; + walk_struct_field(self, s) + } + fn visit_enum_def(&mut self, enum_definition: &'v EnumDef, + generics: &'v Generics, item_id: NodeId, _: Span) { + self.count += 1; + walk_enum_def(self, enum_definition, generics, item_id) + } + fn visit_variant(&mut self, v: &'v Variant, g: &'v Generics, item_id: NodeId) { + self.count += 1; + walk_variant(self, v, g, item_id) + } + fn visit_lifetime(&mut self, lifetime: &'v Lifetime) { + self.count += 1; + walk_lifetime(self, lifetime) + } + fn visit_lifetime_def(&mut self, lifetime: &'v LifetimeDef) { + self.count += 1; + walk_lifetime_def(self, lifetime) + } + fn visit_explicit_self(&mut self, es: &'v ExplicitSelf) { + self.count += 1; + walk_explicit_self(self, es) + } + fn visit_mac(&mut self, _mac: &'v Mac) { + self.count += 1; + walk_mac(self, _mac) + } + fn visit_path(&mut self, path: &'v Path, _id: NodeId) { + self.count += 1; + walk_path(self, path) + } + fn visit_path_list_item(&mut self, prefix: &'v Path, item: &'v PathListItem) { + self.count += 1; + walk_path_list_item(self, prefix, item) + } + fn visit_path_parameters(&mut self, path_span: Span, path_parameters: &'v PathParameters) { + self.count += 1; + walk_path_parameters(self, path_span, path_parameters) + } + fn visit_assoc_type_binding(&mut self, type_binding: &'v TypeBinding) { + self.count += 1; + walk_assoc_type_binding(self, type_binding) + } + fn visit_attribute(&mut self, _attr: &'v Attribute) { + self.count += 1; + } + fn visit_macro_def(&mut self, macro_def: &'v MacroDef) { + self.count += 1; + walk_macro_def(self, macro_def) + } + +} diff --git a/src/libsyntax/util/parser_testing.rs b/src/libsyntax/util/parser_testing.rs index 57138bf26ee06..a462dbeb6e4ed 100644 --- a/src/libsyntax/util/parser_testing.rs +++ b/src/libsyntax/util/parser_testing.rs @@ -50,21 +50,21 @@ pub fn string_to_crate (source_str : String) -> ast::Crate { /// Parse a string, return an expr pub fn string_to_expr (source_str : String) -> P { with_error_checking_parse(source_str, |p| { - p.parse_expr_nopanic() + p.parse_expr() }) } /// Parse a string, return an item pub fn string_to_item (source_str : String) -> Option> { with_error_checking_parse(source_str, |p| { - p.parse_item_nopanic() + p.parse_item() }) } /// Parse a string, return a stmt pub fn string_to_stmt(source_str : String) -> Option> { with_error_checking_parse(source_str, |p| { - p.parse_stmt_nopanic() + p.parse_stmt() }) } @@ -72,7 +72,7 @@ pub fn string_to_stmt(source_str : String) -> Option> { /// (currently) affect parsing. pub fn string_to_pat(source_str: String) -> P { with_error_checking_parse(source_str, |p| { - p.parse_pat_nopanic() + p.parse_pat() }) } diff --git a/src/libsyntax/util/small_vector.rs b/src/libsyntax/util/small_vector.rs index d65e37fd2abc1..9d53cb969269f 100644 --- a/src/libsyntax/util/small_vector.rs +++ b/src/libsyntax/util/small_vector.rs @@ -58,7 +58,7 @@ impl SmallVector { SmallVector { repr: Many(vs) } } - pub fn as_slice<'a>(&'a self) -> &'a [T] { + pub fn as_slice(&self) -> &[T] { match self.repr { Zero => { let result: &[T] = &[]; @@ -105,7 +105,7 @@ impl SmallVector { } } - pub fn get<'a>(&'a self, idx: usize) -> &'a T { + pub fn get(&self, idx: usize) -> &T { match self.repr { One(ref v) if idx == 0 => v, Many(ref vs) => &vs[idx], diff --git a/src/libterm/lib.rs b/src/libterm/lib.rs index ced3a7d47d7b6..99bbd951766c6 100644 --- a/src/libterm/lib.rs +++ b/src/libterm/lib.rs @@ -53,7 +53,8 @@ #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "https://doc.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/nightly/", - html_playground_url = "https://play.rust-lang.org/")] + html_playground_url = "https://play.rust-lang.org/", + test(attr(deny(warnings))))] #![deny(missing_docs)] #![feature(box_syntax)] diff --git a/src/libterm/win.rs b/src/libterm/win.rs index 66ef5e8661797..28ddc56793832 100644 --- a/src/libterm/win.rs +++ b/src/libterm/win.rs @@ -30,12 +30,17 @@ pub struct WinConsole { background: color::Color, } +type WORD = u16; +type DWORD = u32; +type BOOL = i32; +type HANDLE = *mut u8; + #[allow(non_snake_case)] #[repr(C)] struct CONSOLE_SCREEN_BUFFER_INFO { dwSize: [libc::c_short; 2], dwCursorPosition: [libc::c_short; 2], - wAttributes: libc::WORD, + wAttributes: WORD, srWindow: [libc::c_short; 4], dwMaximumWindowSize: [libc::c_short; 2], } @@ -43,10 +48,10 @@ struct CONSOLE_SCREEN_BUFFER_INFO { #[allow(non_snake_case)] #[link(name = "kernel32")] extern "system" { - fn SetConsoleTextAttribute(handle: libc::HANDLE, attr: libc::WORD) -> libc::BOOL; - fn GetStdHandle(which: libc::DWORD) -> libc::HANDLE; - fn GetConsoleScreenBufferInfo(handle: libc::HANDLE, - info: *mut CONSOLE_SCREEN_BUFFER_INFO) -> libc::BOOL; + fn SetConsoleTextAttribute(handle: HANDLE, attr: WORD) -> BOOL; + fn GetStdHandle(which: DWORD) -> HANDLE; + fn GetConsoleScreenBufferInfo(handle: HANDLE, + info: *mut CONSOLE_SCREEN_BUFFER_INFO) -> BOOL; } fn color_to_bits(color: color::Color) -> u16 { @@ -90,7 +95,7 @@ fn bits_to_color(bits: u16) -> color::Color { impl WinConsole { fn apply(&mut self) { let _unused = self.buf.flush(); - let mut accum: libc::WORD = 0; + let mut accum: WORD = 0; accum |= color_to_bits(self.foreground); accum |= color_to_bits(self.background) << 4; @@ -104,7 +109,7 @@ impl WinConsole { // terminal! Admittedly, this is fragile, since stderr could be // redirected to a different console. This is good enough for // rustc though. See #13400. - let out = GetStdHandle(-11i32 as libc::DWORD); + let out = GetStdHandle(-11i32 as DWORD); SetConsoleTextAttribute(out, accum); } } @@ -116,7 +121,7 @@ impl WinConsole { let bg; unsafe { let mut buffer_info = ::std::mem::uninitialized(); - if GetConsoleScreenBufferInfo(GetStdHandle(-11i32 as libc::DWORD), + if GetConsoleScreenBufferInfo(GetStdHandle(-11i32 as DWORD), &mut buffer_info) != 0 { fg = bits_to_color(buffer_info.wAttributes); bg = bits_to_color(buffer_info.wAttributes >> 4); diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index 12541dc010bcf..89442fe1096fe 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -32,7 +32,8 @@ #![crate_type = "dylib"] #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "https://doc.rust-lang.org/favicon.ico", - html_root_url = "https://doc.rust-lang.org/nightly/")] + html_root_url = "https://doc.rust-lang.org/nightly/", + test(attr(deny(warnings))))] #![feature(asm)] #![feature(box_syntax)] @@ -777,11 +778,14 @@ fn stdout_isatty() -> bool { } #[cfg(windows)] fn stdout_isatty() -> bool { - const STD_OUTPUT_HANDLE: libc::DWORD = -11i32 as libc::DWORD; + type DWORD = u32; + type BOOL = i32; + type HANDLE = *mut u8; + type LPDWORD = *mut u32; + const STD_OUTPUT_HANDLE: DWORD = -11i32 as DWORD; extern "system" { - fn GetStdHandle(which: libc::DWORD) -> libc::HANDLE; - fn GetConsoleMode(hConsoleHandle: libc::HANDLE, - lpMode: libc::LPDWORD) -> libc::BOOL; + fn GetStdHandle(which: DWORD) -> HANDLE; + fn GetConsoleMode(hConsoleHandle: HANDLE, lpMode: LPDWORD) -> BOOL; } unsafe { let handle = GetStdHandle(STD_OUTPUT_HANDLE); @@ -882,10 +886,28 @@ fn get_concurrency() -> usize { }; #[cfg(windows)] + #[allow(bad_style)] fn num_cpus() -> usize { + #[repr(C)] + struct SYSTEM_INFO { + wProcessorArchitecture: u16, + wReserved: u16, + dwPageSize: u32, + lpMinimumApplicationAddress: *mut u8, + lpMaximumApplicationAddress: *mut u8, + dwActiveProcessorMask: *mut u8, + dwNumberOfProcessors: u32, + dwProcessorType: u32, + dwAllocationGranularity: u32, + wProcessorLevel: u16, + wProcessorRevision: u16, + } + extern "system" { + fn GetSystemInfo(info: *mut SYSTEM_INFO) -> i32; + } unsafe { let mut sysinfo = std::mem::zeroed(); - libc::GetSystemInfo(&mut sysinfo); + GetSystemInfo(&mut sysinfo); sysinfo.dwNumberOfProcessors as usize } } diff --git a/src/test/auxiliary/issue-11225-1.rs b/src/test/auxiliary/issue-11225-1.rs index 37543ea1d3c5e..e1ec15be9279f 100644 --- a/src/test/auxiliary/issue-11225-1.rs +++ b/src/test/auxiliary/issue-11225-1.rs @@ -11,13 +11,18 @@ mod inner { pub trait Trait { fn f(&self) { f(); } + fn f_ufcs(&self) { f_ufcs(); } } impl Trait for isize {} fn f() {} + fn f_ufcs() {} } pub fn foo(t: T) { t.f(); } +pub fn foo_ufcs(t: T) { + T::f_ufcs(&t); +} diff --git a/src/test/auxiliary/issue-11225-2.rs b/src/test/auxiliary/issue-11225-2.rs index f12e4c9b6e7ea..25110edda2706 100644 --- a/src/test/auxiliary/issue-11225-2.rs +++ b/src/test/auxiliary/issue-11225-2.rs @@ -14,15 +14,18 @@ mod inner { pub struct Foo; pub trait Trait { fn f(&self); + fn f_ufcs(&self); } impl Trait for Foo { fn f(&self) { } + fn f_ufcs(&self) { } } } pub trait Outer { fn foo(&self, t: T) { t.f(); } + fn foo_ufcs(&self, t: T) { T::f(&t); } } impl Outer for isize {} @@ -30,3 +33,6 @@ impl Outer for isize {} pub fn foo(t: T) { t.foo(inner::Foo); } +pub fn foo_ufcs(t: T) { + T::foo_ufcs(&t, inner::Foo) +} diff --git a/src/test/auxiliary/issue-11225-3.rs b/src/test/auxiliary/issue-11225-3.rs index 51d73925dff21..d48fb68ba0ffd 100644 --- a/src/test/auxiliary/issue-11225-3.rs +++ b/src/test/auxiliary/issue-11225-3.rs @@ -10,20 +10,29 @@ trait PrivateTrait { fn private_trait_method(&self); + fn private_trait_method_ufcs(&self); } struct PrivateStruct; impl PrivateStruct { fn private_inherent_method(&self) { } + fn private_inherent_method_ufcs(&self) { } } impl PrivateTrait for PrivateStruct { fn private_trait_method(&self) { } + fn private_trait_method_ufcs(&self) { } } #[inline] -pub fn public_generic_function() { +pub fn public_inlinable_function() { PrivateStruct.private_trait_method(); PrivateStruct.private_inherent_method(); } + +#[inline] +pub fn public_inlinable_function_ufcs() { + PrivateStruct::private_trait_method(&PrivateStruct); + PrivateStruct::private_inherent_method(&PrivateStruct); +} diff --git a/src/test/auxiliary/issue-28927-1.rs b/src/test/auxiliary/issue-28927-1.rs new file mode 100644 index 0000000000000..7d6b448df43fd --- /dev/null +++ b/src/test/auxiliary/issue-28927-1.rs @@ -0,0 +1,12 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +extern crate issue_28927_2 as inner2; +pub use inner2 as bar; diff --git a/src/test/auxiliary/issue-28927-2.rs b/src/test/auxiliary/issue-28927-2.rs new file mode 100644 index 0000000000000..c511700504960 --- /dev/null +++ b/src/test/auxiliary/issue-28927-2.rs @@ -0,0 +1,11 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +pub struct Baz; diff --git a/src/test/auxiliary/macro_crate_test.rs b/src/test/auxiliary/macro_crate_test.rs index 0bb5c05aaf5ba..7ce80a5647c3a 100644 --- a/src/test/auxiliary/macro_crate_test.rs +++ b/src/test/auxiliary/macro_crate_test.rs @@ -54,7 +54,7 @@ fn expand_identity(cx: &mut ExtCtxt, _span: Span, tts: &[TokenTree]) // Parse an expression and emit it unchanged. let mut parser = parse::new_parser_from_tts(cx.parse_sess(), cx.cfg(), tts.to_vec()); - let expr = parser.parse_expr_panic(); + let expr = parser.parse_expr().unwrap(); MacEager::expr(quote_expr!(&mut *cx, $expr)) } diff --git a/src/test/auxiliary/procedural_mbe_matching.rs b/src/test/auxiliary/procedural_mbe_matching.rs index 296d1e431f4ca..a92361b8106d7 100644 --- a/src/test/auxiliary/procedural_mbe_matching.rs +++ b/src/test/auxiliary/procedural_mbe_matching.rs @@ -18,7 +18,7 @@ extern crate rustc; use syntax::codemap::Span; use syntax::parse::token::{self, str_to_ident, NtExpr, NtPat}; -use syntax::ast::{TokenTree, TtToken, Pat}; +use syntax::ast::{TokenTree, Pat}; use syntax::ext::base::{ExtCtxt, MacResult, DummyResult, MacEager}; use syntax::ext::build::AstBuilder; use syntax::ext::tt::macro_parser::{MatchedSeq, MatchedNonterminal}; diff --git a/src/test/auxiliary/roman_numerals.rs b/src/test/auxiliary/roman_numerals.rs index e6f375354aa3a..3abc6f4a9f5d8 100644 --- a/src/test/auxiliary/roman_numerals.rs +++ b/src/test/auxiliary/roman_numerals.rs @@ -18,7 +18,7 @@ extern crate syntax; extern crate rustc; use syntax::codemap::Span; -use syntax::ast::{TokenTree, TtToken}; +use syntax::ast::TokenTree; use syntax::parse::token; use syntax::ext::base::{ExtCtxt, MacResult, DummyResult, MacEager}; use syntax::ext::build::AstBuilder; // trait for expr_usize @@ -40,7 +40,7 @@ fn expand_rn(cx: &mut ExtCtxt, sp: Span, args: &[TokenTree]) ("I", 1)]; let text = match args { - [TtToken(_, token::Ident(s, _))] => s.to_string(), + [TokenTree::Token(_, token::Ident(s, _))] => s.to_string(), _ => { cx.span_err(sp, "argument should be a single identifier"); return DummyResult::any(sp); diff --git a/src/test/compile-fail-fulldeps/gated-quote.rs b/src/test/compile-fail-fulldeps/gated-quote.rs index 6a5cd88a59156..cd801fbcd889b 100644 --- a/src/test/compile-fail-fulldeps/gated-quote.rs +++ b/src/test/compile-fail-fulldeps/gated-quote.rs @@ -37,14 +37,18 @@ impl ParseSess { pub fn main() { let ecx = &ParseSess; - let x = quote_tokens!(ecx, 3); //~ ERROR macro undefined: 'quote_tokens!' - let x = quote_expr!(ecx, 3); //~ ERROR macro undefined: 'quote_expr!' - let x = quote_ty!(ecx, 3); //~ ERROR macro undefined: 'quote_ty!' - let x = quote_method!(ecx, 3); //~ ERROR macro undefined: 'quote_method!' - let x = quote_item!(ecx, 3); //~ ERROR macro undefined: 'quote_item!' - let x = quote_pat!(ecx, 3); //~ ERROR macro undefined: 'quote_pat!' - let x = quote_arm!(ecx, 3); //~ ERROR macro undefined: 'quote_arm!' - let x = quote_stmt!(ecx, 3); //~ ERROR macro undefined: 'quote_stmt!' - let x = quote_matcher!(ecx, 3); //~ ERROR macro undefined: 'quote_matcher!' - let x = quote_attr!(ecx, 3); //~ ERROR macro undefined: 'quote_attr!' + let x = quote_tokens!(ecx, 3); //~ ERROR macro undefined: 'quote_tokens!' + let x = quote_expr!(ecx, 3); //~ ERROR macro undefined: 'quote_expr!' + let x = quote_ty!(ecx, 3); //~ ERROR macro undefined: 'quote_ty!' + let x = quote_method!(ecx, 3); //~ ERROR macro undefined: 'quote_method!' + let x = quote_item!(ecx, 3); //~ ERROR macro undefined: 'quote_item!' + let x = quote_pat!(ecx, 3); //~ ERROR macro undefined: 'quote_pat!' + let x = quote_arm!(ecx, 3); //~ ERROR macro undefined: 'quote_arm!' + let x = quote_stmt!(ecx, 3); //~ ERROR macro undefined: 'quote_stmt!' + let x = quote_matcher!(ecx, 3); //~ ERROR macro undefined: 'quote_matcher!' + let x = quote_attr!(ecx, 3); //~ ERROR macro undefined: 'quote_attr!' + let x = quote_arg!(ecx, 3); //~ ERROR macro undefined: 'quote_arg!' + let x = quote_block!(ecx, 3); //~ ERROR macro undefined: 'quote_block!' + let x = quote_meta_item!(ecx, 3); //~ ERROR macro undefined: 'quote_meta_item!' + let x = quote_path!(ecx, 3); //~ ERROR macro undefined: 'quote_path!' } diff --git a/src/test/compile-fail/cast-rfc0401.rs b/src/test/compile-fail/cast-rfc0401.rs index 4603ed0034734..d14b0fa9e6602 100644 --- a/src/test/compile-fail/cast-rfc0401.rs +++ b/src/test/compile-fail/cast-rfc0401.rs @@ -37,6 +37,7 @@ fn main() let f: f32 = 1.2; let v = 0 as *const u8; let fat_v : *const [u8] = unsafe { &*(0 as *const [u8; 1])}; + let fat_sv : *const [i8] = unsafe { &*(0 as *const [i8; 1])}; let foo: &Foo = &f; let _ = v as &u8; //~ ERROR non-scalar @@ -94,7 +95,7 @@ fn main() let _ = main as *mut str; //~ ERROR casting let _ = &f as *mut f32; //~ ERROR casting let _ = &f as *const f64; //~ ERROR casting - let _ = fat_v as usize; + let _ = fat_sv as usize; //~^ ERROR casting //~^^ HELP through a thin pointer first @@ -106,7 +107,7 @@ fn main() let _ = main.f as *const u32; //~ ERROR attempted access of field let cf: *const Foo = &0; - let _ = cf as *const [u8]; + let _ = cf as *const [u16]; //~^ ERROR casting //~^^ NOTE vtable kinds let _ = cf as *const Bar; diff --git a/src/test/compile-fail/const-pattern-irrefutable.rs b/src/test/compile-fail/const-pattern-irrefutable.rs new file mode 100644 index 0000000000000..2d345d9142b0b --- /dev/null +++ b/src/test/compile-fail/const-pattern-irrefutable.rs @@ -0,0 +1,28 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +mod foo { + const b: u8 = 2; //~ NOTE constant defined here + const d: u8 = 2; //~ NOTE constant defined here +} + +use foo::b as c; //~ NOTE constant imported here +use foo::d; //~ NOTE constant imported here + +const a: u8 = 2; //~ NOTE constant defined here + +fn main() { + let a = 4; //~ ERROR only irrefutable + //~^ NOTE there already is a constant in scope + let c = 4; //~ ERROR only irrefutable + //~^ NOTE there already is a constant in scope + let d = 4; //~ ERROR only irrefutable + //~^ NOTE there already is a constant in scope +} diff --git a/src/test/compile-fail/feature-gate-fundamental.rs b/src/test/compile-fail/feature-gate-fundamental.rs new file mode 100644 index 0000000000000..18718a0d0be93 --- /dev/null +++ b/src/test/compile-fail/feature-gate-fundamental.rs @@ -0,0 +1,14 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[fundamental] //~ ERROR the `#[fundamental]` attribute is an experimental feature +struct Fundamental; + +fn main() { } diff --git a/src/test/compile-fail/infinite-instantiation.rs b/src/test/compile-fail/infinite-instantiation.rs index 9b02bf4cb85a8..28806b6e2ab8c 100644 --- a/src/test/compile-fail/infinite-instantiation.rs +++ b/src/test/compile-fail/infinite-instantiation.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//~^^^^^^^^^^ ERROR overflow // // We get an error message at the top of file (dummy span). // This is not helpful, but also kind of annoying to prevent, @@ -32,6 +31,7 @@ impl ToOpt for Option { } fn function(counter: usize, t: T) { +//~^ ERROR reached the recursion limit during monomorphization if counter > 0 { function(counter - 1, t.to_option()); // FIXME(#4287) Error message should be here. It should be diff --git a/src/test/compile-fail/internal-unstable.rs b/src/test/compile-fail/internal-unstable.rs old mode 100755 new mode 100644 diff --git a/src/test/parse-fail/issue-12560-1.rs b/src/test/compile-fail/issue-12560-1.rs similarity index 70% rename from src/test/parse-fail/issue-12560-1.rs rename to src/test/compile-fail/issue-12560-1.rs index 96a17a8fb45e6..e005de01649a5 100644 --- a/src/test/parse-fail/issue-12560-1.rs +++ b/src/test/compile-fail/issue-12560-1.rs @@ -8,15 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags: -Z parse-only - // For style and consistency reasons, non-parametrized enum variants must // be used simply as `ident` instead of `ident ()`. // This test-case covers enum declaration. enum Foo { - Bar(), //~ ERROR nullary enum variants are written with no trailing `( )` - Baz(), //~ ERROR nullary enum variants are written with no trailing `( )` + Bar(), //~ ERROR empty tuple structs and enum variants are not allowed + //~^ HELP remove trailing `()` to make a unit struct or unit enum variant + Baz(), //~ ERROR empty tuple structs and enum variants are not allowed + //~^ HELP remove trailing `()` to make a unit struct or unit enum variant Bazar } diff --git a/src/test/compile-fail/issue-16819.rs b/src/test/compile-fail/issue-16819.rs index 065b29d29aca5..b229b91c7cd14 100644 --- a/src/test/compile-fail/issue-16819.rs +++ b/src/test/compile-fail/issue-16819.rs @@ -10,9 +10,17 @@ struct TS ( //~ ERROR empty tuple structs and enum variants are not allowed #[cfg(untrue)] - int, + i32, ); +enum E { + TV ( //~ ERROR empty tuple structs and enum variants are not allowed + #[cfg(untrue)] + i32, + ) +} + fn main() { - let s = S; + let s = TS; + let tv = E::TV; } diff --git a/src/test/compile-fail/issue-2392.rs b/src/test/compile-fail/issue-2392.rs index c5598e8785cbd..47d50eb9d5379 100644 --- a/src/test/compile-fail/issue-2392.rs +++ b/src/test/compile-fail/issue-2392.rs @@ -11,6 +11,16 @@ #![feature(core)] use std::boxed::FnBox; +struct FuncContainer { + f1: fn(data: u8), + f2: extern "C" fn(data: u8), + f3: unsafe fn(data: u8), +} + +struct FuncContainerOuter { + container: Box +} + struct Obj where F: FnOnce() -> u32 { closure: F, not_closure: usize, @@ -66,3 +76,16 @@ fn main() { check_expression().closure();//~ ERROR no method named `closure` found //~^ NOTE use `(check_expression().closure)(...)` if you meant to call the function stored } + +impl FuncContainerOuter { + fn run(&self) { + unsafe { + (*self.container).f1(1); //~ ERROR no method named `f1` found + //~^ NOTE use `(*self.container.f1)(...)` + (*self.container).f2(1); //~ ERROR no method named `f2` found + //~^ NOTE use `(*self.container.f2)(...)` + (*self.container).f3(1); //~ ERROR no method named `f3` found + //~^ NOTE use `(*self.container.f3)(...)` + } + } +} diff --git a/src/test/compile-fail/issue-29147.rs b/src/test/compile-fail/issue-29147.rs new file mode 100644 index 0000000000000..64bfa232f3ffd --- /dev/null +++ b/src/test/compile-fail/issue-29147.rs @@ -0,0 +1,32 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![recursion_limit="1024"] + +pub struct S0(T,T); +pub struct S1(Option>>>,Option>>>); +pub struct S2(Option>>>,Option>>>); +pub struct S3(Option>>>,Option>>>); +pub struct S4(Option>>>,Option>>>); +pub struct S5(Option>>>,Option>>>,Option); + +trait Foo { fn xxx(&self); } +trait Bar {} // anything local or #[fundamental] + +impl Foo for T where T: Bar, T: Sync { + fn xxx(&self) {} +} + +impl Foo for S5 { fn xxx(&self) {} } +impl Foo for S5 { fn xxx(&self) {} } + +fn main() { + let _ = >::xxx; //~ ERROR cannot resolve `S5<_> : Foo` +} diff --git a/src/test/compile-fail/lint-dead-code-3.rs b/src/test/compile-fail/lint-dead-code-3.rs index ba1b7f03b0f41..28475b1ef8a03 100644 --- a/src/test/compile-fail/lint-dead-code-3.rs +++ b/src/test/compile-fail/lint-dead-code-3.rs @@ -30,7 +30,7 @@ impl Foo { } fn bar() { //~ ERROR: function is never used - fn baz() {} //~ ERROR: function is never used + fn baz() {} Foo.foo(); baz(); diff --git a/src/test/compile-fail/lint-dead-code-4.rs b/src/test/compile-fail/lint-dead-code-4.rs index 8e37dd805d56d..20cd13c1875d6 100644 --- a/src/test/compile-fail/lint-dead-code-4.rs +++ b/src/test/compile-fail/lint-dead-code-4.rs @@ -25,12 +25,41 @@ enum XYZ { X, //~ ERROR variant is never used Y { //~ ERROR variant is never used a: String, - b: i32, //~ ERROR: struct field is never used - c: i32, //~ ERROR: struct field is never used + b: i32, + c: i32, }, Z } +enum ABC { //~ ERROR enum is never used + A, + B { + a: String, + b: i32, + c: i32, + }, + C +} + +// ensure struct variants get warning for their fields +enum IJK { + I, //~ ERROR variant is never used + J { + a: String, + b: i32, //~ ERROR struct field is never used + c: i32, //~ ERROR struct field is never used + }, + K //~ ERROR variant is never used + +} + +fn struct_variant_partial_use(b: IJK) -> String { + match b { + IJK::J { a, b: _, .. } => a, + _ => "".to_string() + } +} + fn field_match_in_patterns(b: XYZ) -> String { match b { XYZ::Y { a, b: _, .. } => a, @@ -58,6 +87,7 @@ fn field_match_in_let(f: Bar) -> bool { fn main() { field_read(Foo { x: 1, b: false }); field_match_in_patterns(XYZ::Z); + struct_variant_partial_use(IJK::J { a: "".into(), b: 1, c: -1 }); field_match_in_let(Bar { x: 42, b: true, c: false, _guard: () }); let _ = Baz { x: 0 }; } diff --git a/src/test/compile-fail/liveness-dead.rs b/src/test/compile-fail/liveness-dead.rs index dc7b0fc4fd0f2..ddd8fc68c43a3 100644 --- a/src/test/compile-fail/liveness-dead.rs +++ b/src/test/compile-fail/liveness-dead.rs @@ -27,4 +27,14 @@ fn f3() { x = 4; //~ ERROR: value assigned to `x` is never read } +fn f4(mut x: i32) { //~ ERROR: value passed to `x` is never read + x = 4; + x.clone(); +} + +fn f5(mut x: i32) { + x.clone(); + x = 4; //~ ERROR: value assigned to `x` is never read +} + fn main() {} diff --git a/src/test/compile-fail/macro-error.rs b/src/test/compile-fail/macro-error.rs new file mode 100644 index 0000000000000..817b675aedfe8 --- /dev/null +++ b/src/test/compile-fail/macro-error.rs @@ -0,0 +1,19 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Check that we report errors at macro definition, not expansion. + +macro_rules! foo { + ($a:expr) => $a; //~ ERROR macro rhs must be delimited +} + +fn main() { + foo!(0); +} diff --git a/src/test/compile-fail/mut-suggestion.rs b/src/test/compile-fail/mut-suggestion.rs new file mode 100644 index 0000000000000..efd796e11958b --- /dev/null +++ b/src/test/compile-fail/mut-suggestion.rs @@ -0,0 +1,30 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[derive(Copy, Clone)] +struct S; + +impl S { + fn mutate(&mut self) { + } +} + +fn func(arg: S) { + //~^ HELP use `mut` as shown + //~| SUGGESTION fn func(mut arg: S) { + arg.mutate(); //~ ERROR cannot borrow immutable argument +} + +fn main() { + let local = S; + //~^ HELP use `mut` as shown + //~| SUGGESTION let mut local = S; + local.mutate(); //~ ERROR cannot borrow immutable local variable +} diff --git a/src/test/compile-fail/privacy-sanity.rs b/src/test/compile-fail/privacy-sanity.rs new file mode 100644 index 0000000000000..336913b877271 --- /dev/null +++ b/src/test/compile-fail/privacy-sanity.rs @@ -0,0 +1,113 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(associated_consts)] +#![feature(optin_builtin_traits)] + +trait MarkerTr {} +pub trait Tr { + fn f(); + const C: u8; + type T; +} +pub struct S { + pub a: u8 +} +struct Ts(pub u8); + +pub impl MarkerTr for .. {} //~ ERROR unnecessary visibility qualifier +pub impl Tr for S { //~ ERROR unnecessary visibility qualifier + pub fn f() {} //~ ERROR unnecessary visibility qualifier + pub const C: u8 = 0; //~ ERROR unnecessary visibility qualifier + pub type T = u8; //~ ERROR unnecessary visibility qualifier +} +pub impl S { //~ ERROR unnecessary visibility qualifier + pub fn f() {} + pub const C: u8 = 0; + // pub type T = u8; +} +pub extern "C" { //~ ERROR unnecessary visibility qualifier + pub fn f(); + pub static St: u8; +} + +const MAIN: u8 = { + trait MarkerTr {} + pub trait Tr { //~ ERROR visibility has no effect inside functions or block + fn f(); + const C: u8; + type T; + } + pub struct S { //~ ERROR visibility has no effect inside functions or block + pub a: u8 //~ ERROR visibility has no effect inside functions or block + } + struct Ts(pub u8); //~ ERROR visibility has no effect inside functions or block + + pub impl MarkerTr for .. {} //~ ERROR unnecessary visibility qualifier + //~^ ERROR visibility has no effect inside functions or block + pub impl Tr for S { //~ ERROR unnecessary visibility qualifier + //~^ ERROR visibility has no effect inside functions or block + pub fn f() {} //~ ERROR unnecessary visibility qualifier + //~^ ERROR visibility has no effect inside functions or block + pub const C: u8 = 0; //~ ERROR unnecessary visibility qualifier + //~^ ERROR visibility has no effect inside functions or block + pub type T = u8; //~ ERROR unnecessary visibility qualifier + //~^ ERROR visibility has no effect inside functions or block + } + pub impl S { //~ ERROR unnecessary visibility qualifier + //~^ ERROR visibility has no effect inside functions or block + pub fn f() {} //~ ERROR visibility has no effect inside functions or block + pub const C: u8 = 0; //~ ERROR visibility has no effect inside functions or block + // pub type T = u8; // ERROR visibility has no effect inside functions or block + } + pub extern "C" { //~ ERROR unnecessary visibility qualifier + //~^ ERROR visibility has no effect inside functions or block + pub fn f(); //~ ERROR visibility has no effect inside functions or block + pub static St: u8; //~ ERROR visibility has no effect inside functions or block + } + + 0 +}; + +fn main() { + trait MarkerTr {} + pub trait Tr { //~ ERROR visibility has no effect inside functions or block + fn f(); + const C: u8; + type T; + } + pub struct S { //~ ERROR visibility has no effect inside functions or block + pub a: u8 //~ ERROR visibility has no effect inside functions or block + } + struct Ts(pub u8); //~ ERROR visibility has no effect inside functions or block + + pub impl MarkerTr for .. {} //~ ERROR unnecessary visibility qualifier + //~^ ERROR visibility has no effect inside functions or block + pub impl Tr for S { //~ ERROR unnecessary visibility qualifier + //~^ ERROR visibility has no effect inside functions or block + pub fn f() {} //~ ERROR unnecessary visibility qualifier + //~^ ERROR visibility has no effect inside functions or block + pub const C: u8 = 0; //~ ERROR unnecessary visibility qualifier + //~^ ERROR visibility has no effect inside functions or block + pub type T = u8; //~ ERROR unnecessary visibility qualifier + //~^ ERROR visibility has no effect inside functions or block + } + pub impl S { //~ ERROR unnecessary visibility qualifier + //~^ ERROR visibility has no effect inside functions or block + pub fn f() {} //~ ERROR visibility has no effect inside functions or block + pub const C: u8 = 0; //~ ERROR visibility has no effect inside functions or block + // pub type T = u8; // ERROR visibility has no effect inside functions or block + } + pub extern "C" { //~ ERROR unnecessary visibility qualifier + //~^ ERROR visibility has no effect inside functions or block + pub fn f(); //~ ERROR visibility has no effect inside functions or block + pub static St: u8; //~ ERROR visibility has no effect inside functions or block + } +} diff --git a/src/test/compile-fail/recursion.rs b/src/test/compile-fail/recursion.rs index 55f3b99533653..b1d45a82276a8 100644 --- a/src/test/compile-fail/recursion.rs +++ b/src/test/compile-fail/recursion.rs @@ -8,12 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//~^^^^^^^^^^ ERROR overflow -// -// We get an error message at the top of file (dummy span). -// This is not helpful, but also kind of annoying to prevent, -// so for now just live with it. - enum Nil {NilValue} struct Cons {head:isize, tail:T} trait Dot {fn dot(&self, other:Self) -> isize;} @@ -26,7 +20,7 @@ impl Dot for Cons { } } fn test (n:isize, i:isize, first:T, second:T) ->isize { - match n { 0 => {first.dot(second)} + match n { 0 => {first.dot(second)} //~ ERROR overflow // FIXME(#4287) Error message should be here. It should be // a type error to instantiate `test` at a type other than T. _ => {test (n-1, i+1, Cons {head:2*i+1, tail:first}, Cons{head:i*i, tail:second})} diff --git a/src/test/compile-fail/trait-test-2.rs b/src/test/compile-fail/trait-test-2.rs index 13fe314fbcdd1..73be7cf0dc032 100644 --- a/src/test/compile-fail/trait-test-2.rs +++ b/src/test/compile-fail/trait-test-2.rs @@ -16,7 +16,8 @@ impl bar for u32 { fn dup(&self) -> u32 { *self } fn blah(&self) {} } fn main() { 10.dup::(); //~ ERROR does not take type parameters - 10.blah::(); //~ ERROR incorrect number of type parameters + 10.blah::(); + //~^ ERROR incorrect number of type parameters given for this method: expected 1, found 2 (box 10 as Box).dup(); //~^ ERROR E0038 //~| ERROR E0038 diff --git a/src/test/compile-fail/type-macros-fail.rs b/src/test/compile-fail/type-macros-fail.rs index d51176a925d07..756f5d4547a16 100644 --- a/src/test/compile-fail/type-macros-fail.rs +++ b/src/test/compile-fail/type-macros-fail.rs @@ -9,7 +9,7 @@ // except according to those terms. macro_rules! Id { - { $T:tt } => $T + ($T:tt) => ($T); } struct Foo { diff --git a/src/test/parse-fail/lex-bad-char-literals.rs b/src/test/parse-fail/lex-bad-char-literals.rs index 33fb1e14eb3b9..6335632455fbd 100644 --- a/src/test/parse-fail/lex-bad-char-literals.rs +++ b/src/test/parse-fail/lex-bad-char-literals.rs @@ -25,8 +25,8 @@ static s: &'static str = "\●" //~ ERROR: unknown character escape ; -// THIS MUST BE LAST, since unterminated character constants kill the lexer +// THIS MUST BE LAST, since it kills the lexer static c: char = - '● //~ ERROR: unterminated character constant + '● //~ ERROR: character literal may only contain one codepoint ; diff --git a/src/test/run-make/compiler-rt-works-on-mingw/Makefile b/src/test/run-make/compiler-rt-works-on-mingw/Makefile new file mode 100644 index 0000000000000..4ec54f73e67a5 --- /dev/null +++ b/src/test/run-make/compiler-rt-works-on-mingw/Makefile @@ -0,0 +1,17 @@ +-include ../tools.mk + +ifneq (,$(findstring MINGW,$(UNAME))) +ifndef IS_MSVC +all: + g++ foo.cpp -c -o $(TMPDIR)/foo.o + ar crus $(TMPDIR)/libfoo.a $(TMPDIR)/foo.o + $(RUSTC) foo.rs -lfoo -lstdc++ + $(call RUN,foo) +else +all: + +endif +else +all: + +endif diff --git a/src/test/run-make/compiler-rt-works-on-mingw/foo.cpp b/src/test/run-make/compiler-rt-works-on-mingw/foo.cpp new file mode 100644 index 0000000000000..aac3ba4220101 --- /dev/null +++ b/src/test/run-make/compiler-rt-works-on-mingw/foo.cpp @@ -0,0 +1,5 @@ +// ignore-license +extern "C" void foo() { + int *a = new int(3); + delete a; +} diff --git a/src/test/run-make/compiler-rt-works-on-mingw/foo.rs b/src/test/run-make/compiler-rt-works-on-mingw/foo.rs new file mode 100644 index 0000000000000..293f9d582945e --- /dev/null +++ b/src/test/run-make/compiler-rt-works-on-mingw/foo.rs @@ -0,0 +1,16 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +extern { fn foo(); } + +pub fn main() { + unsafe { foo(); } + assert_eq!(7f32.powi(3), 343f32); +} diff --git a/src/test/run-make/execution-engine/test.rs b/src/test/run-make/execution-engine/test.rs index f4031a3aaae1c..f2dd155595ac4 100644 --- a/src/test/run-make/execution-engine/test.rs +++ b/src/test/run-make/execution-engine/test.rs @@ -229,9 +229,9 @@ fn compile_program(input: &str, sysroot: PathBuf) let ast_map = driver::make_map(&sess, &mut hir_forest); driver::phase_3_run_analysis_passes( - &sess, ast_map, &arenas, &id, MakeGlobMap::No, |tcx, analysis| { + &sess, ast_map, &arenas, &id, MakeGlobMap::No, |tcx, mir_map, analysis| { - let trans = driver::phase_4_translate_to_llvm(tcx, analysis); + let trans = driver::phase_4_translate_to_llvm(tcx, &mir_map, analysis); let crates = tcx.sess.cstore.get_used_crates(RequireDynamic); diff --git a/src/test/run-make/issue-14500/foo.c b/src/test/run-make/issue-14500/foo.c index 25098ac479d06..e84b5509c5036 100644 --- a/src/test/run-make/issue-14500/foo.c +++ b/src/test/run-make/issue-14500/foo.c @@ -9,8 +9,9 @@ // except according to those terms. extern void foo(); +extern char FOO_STATIC; int main() { foo(); - return 0; + return (int)FOO_STATIC; } diff --git a/src/test/run-make/issue-14500/foo.rs b/src/test/run-make/issue-14500/foo.rs index ceca907403f91..a91d8d6a21df4 100644 --- a/src/test/run-make/issue-14500/foo.rs +++ b/src/test/run-make/issue-14500/foo.rs @@ -10,3 +10,6 @@ #[no_mangle] pub extern fn foo() {} + +#[no_mangle] +pub static FOO_STATIC: u8 = 0; diff --git a/src/test/run-pass-fulldeps/qquote.rs b/src/test/run-pass-fulldeps/qquote.rs index ba713bb98f854..edaa88452c485 100644 --- a/src/test/run-pass-fulldeps/qquote.rs +++ b/src/test/run-pass-fulldeps/qquote.rs @@ -63,4 +63,41 @@ fn main() { let attr = quote_attr!(cx, #![cfg(foo = "bar")]); check!(attribute_to_string, attr, quote_attr!(cx, $attr); r#"#![cfg(foo = "bar")]"#); + + // quote_arg! + + let arg = quote_arg!(cx, foo: i32); + check!(arg_to_string, arg, quote_arg!(cx, $arg); "foo: i32"); + + let function = quote_item!(cx, fn f($arg) { }).unwrap(); + check!(item_to_string, function; "fn f(foo: i32) { }"); + + let args = vec![arg, quote_arg!(cx, bar: u32)]; + let args = &args[..]; + let function = quote_item!(cx, fn f($args) { }).unwrap(); + check!(item_to_string, function; "fn f(foo: i32, bar: u32) { }"); + + // quote_block! + + let block = quote_block!(cx, { $stmt let y = 40u32; }); + check!(block_to_string, block, *quote_block!(cx, $block); "{ let x = 20u16; let y = 40u32; }"); + + let function = quote_item!(cx, fn f() $block).unwrap(); + check!(item_to_string, function; "fn f() { let x = 20u16; let y = 40u32; }"); + + // quote_path! + + let path = quote_path!(cx, ::syntax::ptr::P); + check!(path_to_string, path, quote_path!(cx, $path); "::syntax::ptr::P"); + + let ty = quote_ty!(cx, $path); + check!(ty_to_string, ty; "::syntax::ptr::P"); + + // quote_meta_item! + + let meta = quote_meta_item!(cx, cfg(foo = "bar")); + check!(meta_item_to_string, meta, *quote_meta_item!(cx, $meta); r#"cfg(foo = "bar")"#); + + let attr = quote_attr!(cx, #![$meta]); + check!(attribute_to_string, attr; r#"#![cfg(foo = "bar")]"#); } diff --git a/src/test/run-pass/down-with-thread-dtors.rs b/src/test/run-pass-valgrind/down-with-thread-dtors.rs similarity index 100% rename from src/test/run-pass/down-with-thread-dtors.rs rename to src/test/run-pass-valgrind/down-with-thread-dtors.rs diff --git a/src/test/run-pass/exit-flushes.rs b/src/test/run-pass-valgrind/exit-flushes.rs similarity index 100% rename from src/test/run-pass/exit-flushes.rs rename to src/test/run-pass-valgrind/exit-flushes.rs diff --git a/src/test/run-pass/osx-frameworks.rs b/src/test/run-pass-valgrind/osx-frameworks.rs similarity index 100% rename from src/test/run-pass/osx-frameworks.rs rename to src/test/run-pass-valgrind/osx-frameworks.rs diff --git a/src/test/run-pass/asm-indirect-memory.rs b/src/test/run-pass/asm-indirect-memory.rs new file mode 100644 index 0000000000000..80fd548dfe354 --- /dev/null +++ b/src/test/run-pass/asm-indirect-memory.rs @@ -0,0 +1,39 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(asm)] + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +fn read(ptr: &u32) -> u32 { + let out: u32; + unsafe { + asm!("mov $1, $0" : "=r" (out) : "*m" (ptr)); + } + out +} + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +fn write(ptr: &mut u32, val: u32) { + unsafe { + asm!("mov $1, $0" :: "=*m" (ptr), "r" (val)); + } +} + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +pub fn main() { + let a = 1; + let mut b = 2; + assert_eq!(read(&a), 1); + write(&mut b, 3); + assert_eq!(b, 3); +} + +#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] +pub fn main() {} diff --git a/src/test/run-pass/assert-eq-macro-unsized.rs b/src/test/run-pass/assert-eq-macro-unsized.rs new file mode 100644 index 0000000000000..e21d3ef0ed068 --- /dev/null +++ b/src/test/run-pass/assert-eq-macro-unsized.rs @@ -0,0 +1,13 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +pub fn main() { + assert_eq!([1, 2, 3][..], vec![1, 2, 3][..]); +} diff --git a/src/test/run-pass/atomic-print.rs b/src/test/run-pass/atomic-print.rs index ae0a358ac4e3f..aa1ef2025a015 100644 --- a/src/test/run-pass/atomic-print.rs +++ b/src/test/run-pass/atomic-print.rs @@ -41,7 +41,7 @@ fn main(){ match line.chars().next().unwrap() { '1' => assert_eq!(line, "11111"), '2' => assert_eq!(line, "22222"), - _ => panic!("Unexpected character") + chr => panic!("unexpected character {:?}", chr) } } } diff --git a/src/test/run-pass/coherence-rfc447-constrained.rs b/src/test/run-pass/coherence-rfc447-constrained.rs new file mode 100644 index 0000000000000..4b52378e50889 --- /dev/null +++ b/src/test/run-pass/coherence-rfc447-constrained.rs @@ -0,0 +1,31 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// check that trait matching can handle impls whose types are only +// constrained by a projection. + +trait IsU32 {} +impl IsU32 for u32 {} + +trait Mirror { type Image: ?Sized; } +impl Mirror for T { type Image = T; } + +trait Bar {} +impl, L: Mirror> Bar for V + where U::Image: IsU32 {} + +trait Foo { fn name() -> &'static str; } +impl Foo for u64 { fn name() -> &'static str { "u64" } } +impl Foo for T { fn name() -> &'static str { "Bar" }} + +fn main() { + assert_eq!(::name(), "u64"); + assert_eq!(::name(), "Bar"); +} diff --git a/src/test/run-pass/const-block-item.rs b/src/test/run-pass/const-block-item.rs index b616b1f610325..51ebc240e7288 100644 --- a/src/test/run-pass/const-block-item.rs +++ b/src/test/run-pass/const-block-item.rs @@ -20,11 +20,6 @@ static BLOCK_USE: usize = { 100 }; -static BLOCK_PUB_USE: usize = { - pub use foo::Value; - 200 -}; - static BLOCK_STRUCT_DEF: usize = { struct Foo { a: usize @@ -48,7 +43,6 @@ static BLOCK_MACRO_RULES: usize = { pub fn main() { assert_eq!(BLOCK_USE, 100); - assert_eq!(BLOCK_PUB_USE, 200); assert_eq!(BLOCK_STRUCT_DEF, 300); assert_eq!(BLOCK_FN_DEF(390), 400); assert_eq!(BLOCK_MACRO_RULES, 412); diff --git a/src/test/run-pass/issue-11225-1.rs b/src/test/run-pass/issue-11225-1.rs index a74fdbe3de472..60789be62b353 100644 --- a/src/test/run-pass/issue-11225-1.rs +++ b/src/test/run-pass/issue-11225-1.rs @@ -16,4 +16,5 @@ extern crate issue_11225_1 as foo; pub fn main() { foo::foo(1); + foo::foo_ufcs(1); } diff --git a/src/test/run-pass/issue-11225-2.rs b/src/test/run-pass/issue-11225-2.rs index c6fc5e8b484e0..540183b7ef432 100644 --- a/src/test/run-pass/issue-11225-2.rs +++ b/src/test/run-pass/issue-11225-2.rs @@ -16,4 +16,5 @@ extern crate issue_11225_2 as foo; pub fn main() { foo::foo(1); + foo::foo_ufcs(1); } diff --git a/src/test/run-pass/issue-11225-3.rs b/src/test/run-pass/issue-11225-3.rs index 046c145e70e78..317c3d3222d34 100644 --- a/src/test/run-pass/issue-11225-3.rs +++ b/src/test/run-pass/issue-11225-3.rs @@ -15,5 +15,6 @@ extern crate issue_11225_3; pub fn main() { - issue_11225_3::public_generic_function(); + issue_11225_3::public_inlinable_function(); + issue_11225_3::public_inlinable_function_ufcs(); } diff --git a/src/test/run-pass/issue-13259-windows-tcb-trash.rs b/src/test/run-pass/issue-13259-windows-tcb-trash.rs index 2e03a9a724420..cca27aebfa44f 100644 --- a/src/test/run-pass/issue-13259-windows-tcb-trash.rs +++ b/src/test/run-pass/issue-13259-windows-tcb-trash.rs @@ -14,8 +14,9 @@ extern crate libc; #[cfg(windows)] mod imp { - use libc::{c_void, LPVOID, DWORD}; - use libc::types::os::arch::extra::LPWSTR; + type LPVOID = *mut u8; + type DWORD = u32; + type LPWSTR = *mut u16; extern "system" { fn FormatMessageW(flags: DWORD, @@ -24,15 +25,15 @@ mod imp { langId: DWORD, buf: LPWSTR, nsize: DWORD, - args: *const c_void) + args: *const u8) -> DWORD; } pub fn test() { let mut buf: [u16; 50] = [0; 50]; let ret = unsafe { - FormatMessageW(0x1000, 0 as *mut c_void, 1, 0x400, - buf.as_mut_ptr(), buf.len() as u32, 0 as *const c_void) + FormatMessageW(0x1000, 0 as *mut _, 1, 0x400, + buf.as_mut_ptr(), buf.len() as u32, 0 as *const _) }; // On some 32-bit Windowses (Win7-8 at least) this will panic with segmented // stacks taking control of pvArbitrary diff --git a/src/test/run-pass/issue-23338-ensure-param-drop-order.rs b/src/test/run-pass/issue-23338-ensure-param-drop-order.rs index 0815ff084fb51..507d482febfd9 100644 --- a/src/test/run-pass/issue-23338-ensure-param-drop-order.rs +++ b/src/test/run-pass/issue-23338-ensure-param-drop-order.rs @@ -19,7 +19,7 @@ use self::d::D; pub fn main() { let log = RefCell::new(vec![]); - d::println(&format!("created empty log")); + d::println("created empty log"); test(&log); assert_eq!(&log.borrow()[..], @@ -59,19 +59,19 @@ pub fn main() { fn test<'a>(log: d::Log<'a>) { let da = D::new("da", 0, log); let de = D::new("de", 1, log); - d::println(&format!("calling foo")); + d::println("calling foo"); let result = foo(da, de); d::println(&format!("result {}", result)); } fn foo<'a>(da0: D<'a>, de1: D<'a>) -> D<'a> { - d::println(&format!("entered foo")); + d::println("entered foo"); let de2 = de1.incr(); // creates D(de_2, 2) let de4 = { let _da1 = da0.incr(); // creates D(da_1, 3) de2.incr().incr() // creates D(de_3, 4) and D(de_4, 5) }; - d::println(&format!("eval tail of foo")); + d::println("eval tail of foo"); de4.incr().incr() // creates D(de_5, 6) and D(de_6, 7) } diff --git a/src/test/run-pass/issue-23406.rs b/src/test/run-pass/issue-23406.rs new file mode 100644 index 0000000000000..c3c1b755af833 --- /dev/null +++ b/src/test/run-pass/issue-23406.rs @@ -0,0 +1,23 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +trait Inner { + type T; +} + +impl<'a> Inner for &'a i32 { + type T = i32; +} + +fn f<'a>(x: &'a i32) -> <&'a i32 as Inner>::T { + *x +} + +fn main() {} diff --git a/src/test/run-pass/issue-23598.rs b/src/test/run-pass/issue-23598.rs new file mode 100644 index 0000000000000..5f1c79a3c1542 --- /dev/null +++ b/src/test/run-pass/issue-23598.rs @@ -0,0 +1,22 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +trait Collection where for<'a> &'a Self: IntoIterator { + fn my_iter(&self) -> <&Self as IntoIterator>::IntoIter { + self.into_iter() + } +} + +impl Collection for [T] { } + +fn main() { + let v = [0usize]; + let _ = v.my_iter(); +} diff --git a/src/test/run-pass/issue-23611-enum-swap-in-drop.rs b/src/test/run-pass/issue-23611-enum-swap-in-drop.rs index 540cbd50e9d57..09bc3fd0214e7 100644 --- a/src/test/run-pass/issue-23611-enum-swap-in-drop.rs +++ b/src/test/run-pass/issue-23611-enum-swap-in-drop.rs @@ -20,7 +20,7 @@ use self::d::D; pub fn main() { let log = RefCell::new(vec![]); - d::println(&format!("created empty log")); + d::println("created empty log"); test(&log); // println!("log: {:?}", &log.borrow()[..]); diff --git a/src/test/run-pass/issue-24954.rs b/src/test/run-pass/issue-24954.rs new file mode 100644 index 0000000000000..f525274a1dfca --- /dev/null +++ b/src/test/run-pass/issue-24954.rs @@ -0,0 +1,22 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +macro_rules! foo { + ($y:expr) => ({ + $y = 2; + }) +} + +#[allow(unused_variables)] +#[allow(unused_assignments)] +fn main() { + let mut x = 1; + foo!(x); +} diff --git a/src/test/run-pass/issue-29147.rs b/src/test/run-pass/issue-29147.rs new file mode 100644 index 0000000000000..026b98905d099 --- /dev/null +++ b/src/test/run-pass/issue-29147.rs @@ -0,0 +1,36 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![recursion_limit="1024"] + +use std::mem; + +pub struct S0(T,T); +pub struct S1(Option>>>,Option>>>); +pub struct S2(Option>>>,Option>>>); +pub struct S3(Option>>>,Option>>>); +pub struct S4(Option>>>,Option>>>); +pub struct S5(Option>>>,Option>>>,Option); + +trait Foo { fn xxx(&self); } +/// some local of #[fundamental] trait +trait Bar {} + +impl Foo for T where T: Bar, T: Sync { + fn xxx(&self) {} +} + +impl Foo for S5 { fn xxx(&self) {} } + +fn main() { + let s = S5(None,None,None); + s.xxx(); + assert_eq!(mem::size_of_val(&s.2), mem::size_of::>()); +} diff --git a/src/test/run-pass/issue-29227.rs b/src/test/run-pass/issue-29227.rs new file mode 100644 index 0000000000000..7e27f7093ad6b --- /dev/null +++ b/src/test/run-pass/issue-29227.rs @@ -0,0 +1,151 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// ignore-tidy-linelength + +// Regression test for #29227. The problem here was that MIR +// construction for these gigantic match expressions was very +// inefficient. + +pub trait CharExt : Sized + Copy { + fn is_unicode_uppercase_letter(self) -> bool { false } + fn is_unicode_lowercase_letter(self) -> bool { false } + fn is_unicode_titlecase_letter(self) -> bool { false } + fn is_unicode_modifier_letter(self) -> bool { false } + fn is_unicode_other_letter(self) -> bool { false } + fn is_unicode_letter_number(self) -> bool { false } + fn is_unicode_nonspacing_mark(self) -> bool { false } + fn is_unicode_combining_spacing_mark(self) -> bool { false } + fn is_unicode_decimal_number(self) -> bool{ false } + fn is_unicode_connector_punctiation(self) -> bool { false } + fn is_unicode_space_separator(self) -> bool { false } + + fn is_es_identifier_start(self) -> bool { false } + fn is_es_identifier_part(self) -> bool { false } + fn is_es_whitespace(self) -> bool { false } + fn is_es_line_terminator(self) -> bool { false } + + fn is_unicode_letter(self) -> bool { + self.is_unicode_uppercase_letter() + || self.is_unicode_lowercase_letter() + || self.is_unicode_titlecase_letter() + || self.is_unicode_modifier_letter() + || self.is_unicode_modifier_letter() + || self.is_unicode_letter_number() + } + +} + + +macro_rules! match_char_class { + ($thing:expr, $($c:expr),*) => { + match $thing { + $($c)|* => true, + _ => false + } + } +} + +impl CharExt for char { + fn is_unicode_uppercase_letter(self) -> bool { + match_char_class!(self, + '\u{0041}', '\u{0042}', '\u{0043}', '\u{0044}', '\u{0045}', '\u{0046}', '\u{0047}', '\u{0048}', '\u{0049}', '\u{004A}', '\u{004B}', '\u{004C}', '\u{004D}', '\u{004E}', '\u{004F}', '\u{0050}', '\u{0051}', '\u{0052}', '\u{0053}', '\u{0054}', '\u{0055}', '\u{0056}', '\u{0057}', '\u{0058}', '\u{0059}', '\u{005A}', '\u{00C0}', '\u{00C1}', '\u{00C2}', '\u{00C3}', '\u{00C4}', '\u{00C5}', '\u{00C6}', '\u{00C7}', '\u{00C8}', '\u{00C9}', '\u{00CA}', '\u{00CB}', '\u{00CC}', '\u{00CD}', '\u{00CE}', '\u{00CF}', '\u{00D0}', '\u{00D1}', '\u{00D2}', '\u{00D3}', '\u{00D4}', '\u{00D5}', '\u{00D6}', '\u{00D8}', '\u{00D9}', '\u{00DA}', '\u{00DB}', '\u{00DC}', '\u{00DD}', '\u{00DE}', '\u{0100}', '\u{0102}', '\u{0104}', '\u{0106}', '\u{0108}', '\u{010A}', '\u{010C}', '\u{010E}', '\u{0110}', '\u{0112}', '\u{0114}', '\u{0116}', '\u{0118}', '\u{011A}', '\u{011C}', '\u{011E}', '\u{0120}', '\u{0122}', '\u{0124}', '\u{0126}', '\u{0128}', '\u{012A}', '\u{012C}', '\u{012E}', '\u{0130}', '\u{0132}', '\u{0134}', '\u{0136}', '\u{0139}', '\u{013B}', '\u{013D}', '\u{013F}', '\u{0141}', '\u{0143}', '\u{0145}', '\u{0147}', '\u{014A}', '\u{014C}', '\u{014E}', '\u{0150}', '\u{0152}', '\u{0154}', '\u{0156}', '\u{0158}', '\u{015A}', '\u{015C}', '\u{015E}', '\u{0160}', '\u{0162}', '\u{0164}', '\u{0166}', '\u{0168}', '\u{016A}', '\u{016C}', '\u{016E}', '\u{0170}', '\u{0172}', '\u{0174}', '\u{0176}', '\u{0178}', '\u{0179}', '\u{017B}', '\u{017D}', '\u{0181}', '\u{0182}', '\u{0184}', '\u{0186}', '\u{0187}', '\u{0189}', '\u{018A}', '\u{018B}', '\u{018E}', '\u{018F}', '\u{0190}', '\u{0191}', '\u{0193}', '\u{0194}', '\u{0196}', '\u{0197}', '\u{0198}', '\u{019C}', '\u{019D}', '\u{019F}', '\u{01A0}', '\u{01A2}', '\u{01A4}', '\u{01A6}', '\u{01A7}', '\u{01A9}', '\u{01AC}', '\u{01AE}', '\u{01AF}', '\u{01B1}', '\u{01B2}', '\u{01B3}', '\u{01B5}', '\u{01B7}', '\u{01B8}', '\u{01BC}', '\u{01C4}', '\u{01C7}', '\u{01CA}', '\u{01CD}', '\u{01CF}', '\u{01D1}', '\u{01D3}', '\u{01D5}', '\u{01D7}', '\u{01D9}', '\u{01DB}', '\u{01DE}', '\u{01E0}', '\u{01E2}', '\u{01E4}', '\u{01E6}', '\u{01E8}', '\u{01EA}', '\u{01EC}', '\u{01EE}', '\u{01F1}', '\u{01F4}', '\u{01F6}', '\u{01F7}', '\u{01F8}', '\u{01FA}', '\u{01FC}', '\u{01FE}', '\u{0200}', '\u{0202}', '\u{0204}', '\u{0206}', '\u{0208}', '\u{020A}', '\u{020C}', '\u{020E}', '\u{0210}', '\u{0212}', '\u{0214}', '\u{0216}', '\u{0218}', '\u{021A}', '\u{021C}', '\u{021E}', '\u{0220}', '\u{0222}', '\u{0224}', '\u{0226}', '\u{0228}', '\u{022A}', '\u{022C}', '\u{022E}', '\u{0230}', '\u{0232}', '\u{023A}', '\u{023B}', '\u{023D}', '\u{023E}', '\u{0241}', '\u{0243}', '\u{0244}', '\u{0245}', '\u{0246}', '\u{0248}', '\u{024A}', '\u{024C}', '\u{024E}', '\u{0370}', '\u{0372}', '\u{0376}', '\u{0386}', '\u{0388}', '\u{0389}', '\u{038A}', '\u{038C}', '\u{038E}', '\u{038F}', '\u{0391}', '\u{0392}', '\u{0393}', '\u{0394}', '\u{0395}', '\u{0396}', '\u{0397}', '\u{0398}', '\u{0399}', '\u{039A}', '\u{039B}', '\u{039C}', '\u{039D}', '\u{039E}', '\u{039F}', '\u{03A0}', '\u{03A1}', '\u{03A3}', '\u{03A4}', '\u{03A5}', '\u{03A6}', '\u{03A7}', '\u{03A8}', '\u{03A9}', '\u{03AA}', '\u{03AB}', '\u{03CF}', '\u{03D2}', '\u{03D3}', '\u{03D4}', '\u{03D8}', '\u{03DA}', '\u{03DC}', '\u{03DE}', '\u{03E0}', '\u{03E2}', '\u{03E4}', '\u{03E6}', '\u{03E8}', '\u{03EA}', '\u{03EC}', '\u{03EE}', '\u{03F4}', '\u{03F7}', '\u{03F9}', '\u{03FA}', '\u{03FD}', '\u{03FE}', '\u{03FF}', '\u{0400}', '\u{0401}', '\u{0402}', '\u{0403}', '\u{0404}', '\u{0405}', '\u{0406}', '\u{0407}', '\u{0408}', '\u{0409}', '\u{040A}', '\u{040B}', '\u{040C}', '\u{040D}', '\u{040E}', '\u{040F}', '\u{0410}', '\u{0411}', '\u{0412}', '\u{0413}', '\u{0414}', '\u{0415}', '\u{0416}', '\u{0417}', '\u{0418}', '\u{0419}', '\u{041A}', '\u{041B}', '\u{041C}', '\u{041D}', '\u{041E}', '\u{041F}', '\u{0420}', '\u{0421}', '\u{0422}', '\u{0423}', '\u{0424}', '\u{0425}', '\u{0426}', '\u{0427}', '\u{0428}', '\u{0429}', '\u{042A}', '\u{042B}', '\u{042C}', '\u{042D}', '\u{042E}', '\u{042F}', '\u{0460}', '\u{0462}', '\u{0464}', '\u{0466}', '\u{0468}', '\u{046A}', '\u{046C}', '\u{046E}', '\u{0470}', '\u{0472}', '\u{0474}', '\u{0476}', '\u{0478}', '\u{047A}', '\u{047C}', '\u{047E}', '\u{0480}', '\u{048A}', '\u{048C}', '\u{048E}', '\u{0490}', '\u{0492}', '\u{0494}', '\u{0496}', '\u{0498}', '\u{049A}', '\u{049C}', '\u{049E}', '\u{04A0}', '\u{04A2}', '\u{04A4}', '\u{04A6}', '\u{04A8}', '\u{04AA}', '\u{04AC}', '\u{04AE}', '\u{04B0}', '\u{04B2}', '\u{04B4}', '\u{04B6}', '\u{04B8}', '\u{04BA}', '\u{04BC}', '\u{04BE}', '\u{04C0}', '\u{04C1}', '\u{04C3}', '\u{04C5}', '\u{04C7}', '\u{04C9}', '\u{04CB}', '\u{04CD}', '\u{04D0}', '\u{04D2}', '\u{04D4}', '\u{04D6}', '\u{04D8}', '\u{04DA}', '\u{04DC}', '\u{04DE}', '\u{04E0}', '\u{04E2}', '\u{04E4}', '\u{04E6}', '\u{04E8}', '\u{04EA}', '\u{04EC}', '\u{04EE}', '\u{04F0}', '\u{04F2}', '\u{04F4}', '\u{04F6}', '\u{04F8}', '\u{04FA}', '\u{04FC}', '\u{04FE}', '\u{0500}', '\u{0502}', '\u{0504}', '\u{0506}', '\u{0508}', '\u{050A}', '\u{050C}', '\u{050E}', '\u{0510}', '\u{0512}', '\u{0514}', '\u{0516}', '\u{0518}', '\u{051A}', '\u{051C}', '\u{051E}', '\u{0520}', '\u{0522}', '\u{0531}', '\u{0532}', '\u{0533}', '\u{0534}', '\u{0535}', '\u{0536}', '\u{0537}', '\u{0538}', '\u{0539}', '\u{053A}', '\u{053B}', '\u{053C}', '\u{053D}', '\u{053E}', '\u{053F}', '\u{0540}', '\u{0541}', '\u{0542}', '\u{0543}', '\u{0544}', '\u{0545}', '\u{0546}', '\u{0547}', '\u{0548}', '\u{0549}', '\u{054A}', '\u{054B}', '\u{054C}', '\u{054D}', '\u{054E}', '\u{054F}', '\u{0550}', '\u{0551}', '\u{0552}', '\u{0553}', '\u{0554}', '\u{0555}', '\u{0556}', '\u{10A0}', '\u{10A1}', '\u{10A2}', '\u{10A3}', '\u{10A4}', '\u{10A5}', '\u{10A6}', '\u{10A7}', '\u{10A8}', '\u{10A9}', '\u{10AA}', '\u{10AB}', '\u{10AC}', '\u{10AD}', '\u{10AE}', '\u{10AF}', '\u{10B0}', '\u{10B1}', '\u{10B2}', '\u{10B3}', '\u{10B4}', '\u{10B5}', '\u{10B6}', '\u{10B7}', '\u{10B8}', '\u{10B9}', '\u{10BA}', '\u{10BB}', '\u{10BC}', '\u{10BD}', '\u{10BE}', '\u{10BF}', '\u{10C0}', '\u{10C1}', '\u{10C2}', '\u{10C3}', '\u{10C4}', '\u{10C5}', '\u{1E00}', '\u{1E02}', '\u{1E04}', '\u{1E06}', '\u{1E08}', '\u{1E0A}', '\u{1E0C}', '\u{1E0E}', '\u{1E10}', '\u{1E12}', '\u{1E14}', '\u{1E16}', '\u{1E18}', '\u{1E1A}', '\u{1E1C}', '\u{1E1E}', '\u{1E20}', '\u{1E22}', '\u{1E24}', '\u{1E26}', '\u{1E28}', '\u{1E2A}', '\u{1E2C}', '\u{1E2E}', '\u{1E30}', '\u{1E32}', '\u{1E34}', '\u{1E36}', '\u{1E38}', '\u{1E3A}', '\u{1E3C}', '\u{1E3E}', '\u{1E40}', '\u{1E42}', '\u{1E44}', '\u{1E46}', '\u{1E48}', '\u{1E4A}', '\u{1E4C}', '\u{1E4E}', '\u{1E50}', '\u{1E52}', '\u{1E54}', '\u{1E56}', '\u{1E58}', '\u{1E5A}', '\u{1E5C}', '\u{1E5E}', '\u{1E60}', '\u{1E62}', '\u{1E64}', '\u{1E66}', '\u{1E68}', '\u{1E6A}', '\u{1E6C}', '\u{1E6E}', '\u{1E70}', '\u{1E72}', '\u{1E74}', '\u{1E76}', '\u{1E78}', '\u{1E7A}', '\u{1E7C}', '\u{1E7E}', '\u{1E80}', '\u{1E82}', '\u{1E84}', '\u{1E86}', '\u{1E88}', '\u{1E8A}', '\u{1E8C}', '\u{1E8E}', '\u{1E90}', '\u{1E92}', '\u{1E94}', '\u{1E9E}', '\u{1EA0}', '\u{1EA2}', '\u{1EA4}', '\u{1EA6}', '\u{1EA8}', '\u{1EAA}', '\u{1EAC}', '\u{1EAE}', '\u{1EB0}', '\u{1EB2}', '\u{1EB4}', '\u{1EB6}', '\u{1EB8}', '\u{1EBA}', '\u{1EBC}', '\u{1EBE}', '\u{1EC0}', '\u{1EC2}', '\u{1EC4}', '\u{1EC6}', '\u{1EC8}', '\u{1ECA}', '\u{1ECC}', '\u{1ECE}', '\u{1ED0}', '\u{1ED2}', '\u{1ED4}', '\u{1ED6}', '\u{1ED8}', '\u{1EDA}', '\u{1EDC}', '\u{1EDE}', '\u{1EE0}', '\u{1EE2}', '\u{1EE4}', '\u{1EE6}', '\u{1EE8}', '\u{1EEA}', '\u{1EEC}', '\u{1EEE}', '\u{1EF0}', '\u{1EF2}', '\u{1EF4}', '\u{1EF6}', '\u{1EF8}', '\u{1EFA}', '\u{1EFC}', '\u{1EFE}', '\u{1F08}', '\u{1F09}', '\u{1F0A}', '\u{1F0B}', '\u{1F0C}', '\u{1F0D}', '\u{1F0E}', '\u{1F0F}', '\u{1F18}', '\u{1F19}', '\u{1F1A}', '\u{1F1B}', '\u{1F1C}', '\u{1F1D}', '\u{1F28}', '\u{1F29}', '\u{1F2A}', '\u{1F2B}', '\u{1F2C}', '\u{1F2D}', '\u{1F2E}', '\u{1F2F}', '\u{1F38}', '\u{1F39}', '\u{1F3A}', '\u{1F3B}', '\u{1F3C}', '\u{1F3D}', '\u{1F3E}', '\u{1F3F}', '\u{1F48}', '\u{1F49}', '\u{1F4A}', '\u{1F4B}', '\u{1F4C}', '\u{1F4D}', '\u{1F59}', '\u{1F5B}', '\u{1F5D}', '\u{1F5F}', '\u{1F68}', '\u{1F69}', '\u{1F6A}', '\u{1F6B}', '\u{1F6C}', '\u{1F6D}', '\u{1F6E}', '\u{1F6F}', '\u{1FB8}', '\u{1FB9}', '\u{1FBA}', '\u{1FBB}', '\u{1FC8}', '\u{1FC9}', '\u{1FCA}', '\u{1FCB}', '\u{1FD8}', '\u{1FD9}', '\u{1FDA}', '\u{1FDB}', '\u{1FE8}', '\u{1FE9}', '\u{1FEA}', '\u{1FEB}', '\u{1FEC}', '\u{1FF8}', '\u{1FF9}', '\u{1FFA}', '\u{1FFB}', '\u{2102}', '\u{2107}', '\u{210B}', '\u{210C}', '\u{210D}', '\u{2110}', '\u{2111}', '\u{2112}', '\u{2115}', '\u{2119}', '\u{211A}', '\u{211B}', '\u{211C}', '\u{211D}', '\u{2124}', '\u{2126}', '\u{2128}', '\u{212A}', '\u{212B}', '\u{212C}', '\u{212D}', '\u{2130}', '\u{2131}', '\u{2132}', '\u{2133}', '\u{213E}', '\u{213F}', '\u{2145}', '\u{2183}', '\u{2C00}', '\u{2C01}', '\u{2C02}', '\u{2C03}', '\u{2C04}', '\u{2C05}', '\u{2C06}', '\u{2C07}', '\u{2C08}', '\u{2C09}', '\u{2C0A}', '\u{2C0B}', '\u{2C0C}', '\u{2C0D}', '\u{2C0E}', '\u{2C0F}', '\u{2C10}', '\u{2C11}', '\u{2C12}', '\u{2C13}', '\u{2C14}', '\u{2C15}', '\u{2C16}', '\u{2C17}', '\u{2C18}', '\u{2C19}', '\u{2C1A}', '\u{2C1B}', '\u{2C1C}', '\u{2C1D}', '\u{2C1E}', '\u{2C1F}', '\u{2C20}', '\u{2C21}', '\u{2C22}', '\u{2C23}', '\u{2C24}', '\u{2C25}', '\u{2C26}', '\u{2C27}', '\u{2C28}', '\u{2C29}', '\u{2C2A}', '\u{2C2B}', '\u{2C2C}', '\u{2C2D}', '\u{2C2E}', '\u{2C60}', '\u{2C62}', '\u{2C63}', '\u{2C64}', '\u{2C67}', '\u{2C69}', '\u{2C6B}', '\u{2C6D}', '\u{2C6E}', '\u{2C6F}', '\u{2C72}', '\u{2C75}', '\u{2C80}', '\u{2C82}', '\u{2C84}', '\u{2C86}', '\u{2C88}', '\u{2C8A}', '\u{2C8C}', '\u{2C8E}', '\u{2C90}', '\u{2C92}', '\u{2C94}', '\u{2C96}', '\u{2C98}', '\u{2C9A}', '\u{2C9C}', '\u{2C9E}', '\u{2CA0}', '\u{2CA2}', '\u{2CA4}', '\u{2CA6}', '\u{2CA8}', '\u{2CAA}', '\u{2CAC}', '\u{2CAE}', '\u{2CB0}', '\u{2CB2}', '\u{2CB4}', '\u{2CB6}', '\u{2CB8}', '\u{2CBA}', '\u{2CBC}', '\u{2CBE}', '\u{2CC0}', '\u{2CC2}', '\u{2CC4}', '\u{2CC6}', '\u{2CC8}', '\u{2CCA}', '\u{2CCC}', '\u{2CCE}', '\u{2CD0}', '\u{2CD2}', '\u{2CD4}', '\u{2CD6}', '\u{2CD8}', '\u{2CDA}', '\u{2CDC}', '\u{2CDE}', '\u{2CE0}', '\u{2CE2}', '\u{A640}', '\u{A642}', '\u{A644}', '\u{A646}', '\u{A648}', '\u{A64A}', '\u{A64C}', '\u{A64E}', '\u{A650}', '\u{A652}', '\u{A654}', '\u{A656}', '\u{A658}', '\u{A65A}', '\u{A65C}', '\u{A65E}', '\u{A662}', '\u{A664}', '\u{A666}', '\u{A668}', '\u{A66A}', '\u{A66C}', '\u{A680}', '\u{A682}', '\u{A684}', '\u{A686}', '\u{A688}', '\u{A68A}', '\u{A68C}', '\u{A68E}', '\u{A690}', '\u{A692}', '\u{A694}', '\u{A696}', '\u{A722}', '\u{A724}', '\u{A726}', '\u{A728}', '\u{A72A}', '\u{A72C}', '\u{A72E}', '\u{A732}', '\u{A734}', '\u{A736}', '\u{A738}', '\u{A73A}', '\u{A73C}', '\u{A73E}', '\u{A740}', '\u{A742}', '\u{A744}', '\u{A746}', '\u{A748}', '\u{A74A}', '\u{A74C}', '\u{A74E}', '\u{A750}', '\u{A752}', '\u{A754}', '\u{A756}', '\u{A758}', '\u{A75A}', '\u{A75C}', '\u{A75E}', '\u{A760}', '\u{A762}', '\u{A764}', '\u{A766}', '\u{A768}', '\u{A76A}', '\u{A76C}', '\u{A76E}', '\u{A779}', '\u{A77B}', '\u{A77D}', '\u{A77E}', '\u{A780}', '\u{A782}', '\u{A784}', '\u{A786}', '\u{A78B}', '\u{FF21}', '\u{FF22}', '\u{FF23}', '\u{FF24}', '\u{FF25}', '\u{FF26}', '\u{FF27}', '\u{FF28}', '\u{FF29}', '\u{FF2A}', '\u{FF2B}', '\u{FF2C}', '\u{FF2D}', '\u{FF2E}', '\u{FF2F}', '\u{FF30}', '\u{FF31}', '\u{FF32}', '\u{FF33}', '\u{FF34}', '\u{FF35}', '\u{FF36}', '\u{FF37}', '\u{FF38}', '\u{FF39}', '\u{FF3A}') + } + + fn is_unicode_lowercase_letter(self) -> bool { + match_char_class!(self, + '\u{0061}', '\u{0062}', '\u{0063}', '\u{0064}', '\u{0065}', '\u{0066}', '\u{0067}', '\u{0068}', '\u{0069}', '\u{006A}', '\u{006B}', '\u{006C}', '\u{006D}', '\u{006E}', '\u{006F}', '\u{0070}', '\u{0071}', '\u{0072}', '\u{0073}', '\u{0074}', '\u{0075}', '\u{0076}', '\u{0077}', '\u{0078}', '\u{0079}', '\u{007A}', '\u{00AA}', '\u{00B5}', '\u{00BA}', '\u{00DF}', '\u{00E0}', '\u{00E1}', '\u{00E2}', '\u{00E3}', '\u{00E4}', '\u{00E5}', '\u{00E6}', '\u{00E7}', '\u{00E8}', '\u{00E9}', '\u{00EA}', '\u{00EB}', '\u{00EC}', '\u{00ED}', '\u{00EE}', '\u{00EF}', '\u{00F0}', '\u{00F1}', '\u{00F2}', '\u{00F3}', '\u{00F4}', '\u{00F5}', '\u{00F6}', '\u{00F8}', '\u{00F9}', '\u{00FA}', '\u{00FB}', '\u{00FC}', '\u{00FD}', '\u{00FE}', '\u{00FF}', '\u{0101}', '\u{0103}', '\u{0105}', '\u{0107}', '\u{0109}', '\u{010B}', '\u{010D}', '\u{010F}', '\u{0111}', '\u{0113}', '\u{0115}', '\u{0117}', '\u{0119}', '\u{011B}', '\u{011D}', '\u{011F}', '\u{0121}', '\u{0123}', '\u{0125}', '\u{0127}', '\u{0129}', '\u{012B}', '\u{012D}', '\u{012F}', '\u{0131}', '\u{0133}', '\u{0135}', '\u{0137}', '\u{0138}', '\u{013A}', '\u{013C}', '\u{013E}', '\u{0140}', '\u{0142}', '\u{0144}', '\u{0146}', '\u{0148}', '\u{0149}', '\u{014B}', '\u{014D}', '\u{014F}', '\u{0151}', '\u{0153}', '\u{0155}', '\u{0157}', '\u{0159}', '\u{015B}', '\u{015D}', '\u{015F}', '\u{0161}', '\u{0163}', '\u{0165}', '\u{0167}', '\u{0169}', '\u{016B}', '\u{016D}', '\u{016F}', '\u{0171}', '\u{0173}', '\u{0175}', '\u{0177}', '\u{017A}', '\u{017C}', '\u{017E}', '\u{017F}', '\u{0180}', '\u{0183}', '\u{0185}', '\u{0188}', '\u{018C}', '\u{018D}', '\u{0192}', '\u{0195}', '\u{0199}', '\u{019A}', '\u{019B}', '\u{019E}', '\u{01A1}', '\u{01A3}', '\u{01A5}', '\u{01A8}', '\u{01AA}', '\u{01AB}', '\u{01AD}', '\u{01B0}', '\u{01B4}', '\u{01B6}', '\u{01B9}', '\u{01BA}', '\u{01BD}', '\u{01BE}', '\u{01BF}', '\u{01C6}', '\u{01C9}', '\u{01CC}', '\u{01CE}', '\u{01D0}', '\u{01D2}', '\u{01D4}', '\u{01D6}', '\u{01D8}', '\u{01DA}', '\u{01DC}', '\u{01DD}', '\u{01DF}', '\u{01E1}', '\u{01E3}', '\u{01E5}', '\u{01E7}', '\u{01E9}', '\u{01EB}', '\u{01ED}', '\u{01EF}', '\u{01F0}', '\u{01F3}', '\u{01F5}', '\u{01F9}', '\u{01FB}', '\u{01FD}', '\u{01FF}', '\u{0201}', '\u{0203}', '\u{0205}', '\u{0207}', '\u{0209}', '\u{020B}', '\u{020D}', '\u{020F}', '\u{0211}', '\u{0213}', '\u{0215}', '\u{0217}', '\u{0219}', '\u{021B}', '\u{021D}', '\u{021F}', '\u{0221}', '\u{0223}', '\u{0225}', '\u{0227}', '\u{0229}', '\u{022B}', '\u{022D}', '\u{022F}', '\u{0231}', '\u{0233}', '\u{0234}', '\u{0235}', '\u{0236}', '\u{0237}', '\u{0238}', '\u{0239}', '\u{023C}', '\u{023F}', '\u{0240}', '\u{0242}', '\u{0247}', '\u{0249}', '\u{024B}', '\u{024D}', '\u{024F}', '\u{0250}', '\u{0251}', '\u{0252}', '\u{0253}', '\u{0254}', '\u{0255}', '\u{0256}', '\u{0257}', '\u{0258}', '\u{0259}', '\u{025A}', '\u{025B}', '\u{025C}', '\u{025D}', '\u{025E}', '\u{025F}', '\u{0260}', '\u{0261}', '\u{0262}', '\u{0263}', '\u{0264}', '\u{0265}', '\u{0266}', '\u{0267}', '\u{0268}', '\u{0269}', '\u{026A}', '\u{026B}', '\u{026C}', '\u{026D}', '\u{026E}', '\u{026F}', '\u{0270}', '\u{0271}', '\u{0272}', '\u{0273}', '\u{0274}', '\u{0275}', '\u{0276}', '\u{0277}', '\u{0278}', '\u{0279}', '\u{027A}', '\u{027B}', '\u{027C}', '\u{027D}', '\u{027E}', '\u{027F}', '\u{0280}', '\u{0281}', '\u{0282}', '\u{0283}', '\u{0284}', '\u{0285}', '\u{0286}', '\u{0287}', '\u{0288}', '\u{0289}', '\u{028A}', '\u{028B}', '\u{028C}', '\u{028D}', '\u{028E}', '\u{028F}', '\u{0290}', '\u{0291}', '\u{0292}', '\u{0293}', '\u{0295}', '\u{0296}', '\u{0297}', '\u{0298}', '\u{0299}', '\u{029A}', '\u{029B}', '\u{029C}', '\u{029D}', '\u{029E}', '\u{029F}', '\u{02A0}', '\u{02A1}', '\u{02A2}', '\u{02A3}', '\u{02A4}', '\u{02A5}', '\u{02A6}', '\u{02A7}', '\u{02A8}', '\u{02A9}', '\u{02AA}', '\u{02AB}', '\u{02AC}', '\u{02AD}', '\u{02AE}', '\u{02AF}', '\u{0371}', '\u{0373}', '\u{0377}', '\u{037B}', '\u{037C}', '\u{037D}', '\u{0390}', '\u{03AC}', '\u{03AD}', '\u{03AE}', '\u{03AF}', '\u{03B0}', '\u{03B1}', '\u{03B2}', '\u{03B3}', '\u{03B4}', '\u{03B5}', '\u{03B6}', '\u{03B7}', '\u{03B8}', '\u{03B9}', '\u{03BA}', '\u{03BB}', '\u{03BC}', '\u{03BD}', '\u{03BE}', '\u{03BF}', '\u{03C0}', '\u{03C1}', '\u{03C2}', '\u{03C3}', '\u{03C4}', '\u{03C5}', '\u{03C6}', '\u{03C7}', '\u{03C8}', '\u{03C9}', '\u{03CA}', '\u{03CB}', '\u{03CC}', '\u{03CD}', '\u{03CE}', '\u{03D0}', '\u{03D1}', '\u{03D5}', '\u{03D6}', '\u{03D7}', '\u{03D9}', '\u{03DB}', '\u{03DD}', '\u{03DF}', '\u{03E1}', '\u{03E3}', '\u{03E5}', '\u{03E7}', '\u{03E9}', '\u{03EB}', '\u{03ED}', '\u{03EF}', '\u{03F0}', '\u{03F1}', '\u{03F2}', '\u{03F3}', '\u{03F5}', '\u{03F8}', '\u{03FB}', '\u{03FC}', '\u{0430}', '\u{0431}', '\u{0432}', '\u{0433}', '\u{0434}', '\u{0435}', '\u{0436}', '\u{0437}', '\u{0438}', '\u{0439}', '\u{043A}', '\u{043B}', '\u{043C}', '\u{043D}', '\u{043E}', '\u{043F}', '\u{0440}', '\u{0441}', '\u{0442}', '\u{0443}', '\u{0444}', '\u{0445}', '\u{0446}', '\u{0447}', '\u{0448}', '\u{0449}', '\u{044A}', '\u{044B}', '\u{044C}', '\u{044D}', '\u{044E}', '\u{044F}', '\u{0450}', '\u{0451}', '\u{0452}', '\u{0453}', '\u{0454}', '\u{0455}', '\u{0456}', '\u{0457}', '\u{0458}', '\u{0459}', '\u{045A}', '\u{045B}', '\u{045C}', '\u{045D}', '\u{045E}', '\u{045F}', '\u{0461}', '\u{0463}', '\u{0465}', '\u{0467}', '\u{0469}', '\u{046B}', '\u{046D}', '\u{046F}', '\u{0471}', '\u{0473}', '\u{0475}', '\u{0477}', '\u{0479}', '\u{047B}', '\u{047D}', '\u{047F}', '\u{0481}', '\u{048B}', '\u{048D}', '\u{048F}', '\u{0491}', '\u{0493}', '\u{0495}', '\u{0497}', '\u{0499}', '\u{049B}', '\u{049D}', '\u{049F}', '\u{04A1}', '\u{04A3}', '\u{04A5}', '\u{04A7}', '\u{04A9}', '\u{04AB}', '\u{04AD}', '\u{04AF}', '\u{04B1}', '\u{04B3}', '\u{04B5}', '\u{04B7}', '\u{04B9}', '\u{04BB}', '\u{04BD}', '\u{04BF}', '\u{04C2}', '\u{04C4}', '\u{04C6}', '\u{04C8}', '\u{04CA}', '\u{04CC}', '\u{04CE}', '\u{04CF}', '\u{04D1}', '\u{04D3}', '\u{04D5}', '\u{04D7}', '\u{04D9}', '\u{04DB}', '\u{04DD}', '\u{04DF}', '\u{04E1}', '\u{04E3}', '\u{04E5}', '\u{04E7}', '\u{04E9}', '\u{04EB}', '\u{04ED}', '\u{04EF}', '\u{04F1}', '\u{04F3}', '\u{04F5}', '\u{04F7}', '\u{04F9}', '\u{04FB}', '\u{04FD}', '\u{04FF}', '\u{0501}', '\u{0503}', '\u{0505}', '\u{0507}', '\u{0509}', '\u{050B}', '\u{050D}', '\u{050F}', '\u{0511}', '\u{0513}', '\u{0515}', '\u{0517}', '\u{0519}', '\u{051B}', '\u{051D}', '\u{051F}', '\u{0521}', '\u{0523}', '\u{0561}', '\u{0562}', '\u{0563}', '\u{0564}', '\u{0565}', '\u{0566}', '\u{0567}', '\u{0568}', '\u{0569}', '\u{056A}', '\u{056B}', '\u{056C}', '\u{056D}', '\u{056E}', '\u{056F}', '\u{0570}', '\u{0571}', '\u{0572}', '\u{0573}', '\u{0574}', '\u{0575}', '\u{0576}', '\u{0577}', '\u{0578}', '\u{0579}', '\u{057A}', '\u{057B}', '\u{057C}', '\u{057D}', '\u{057E}', '\u{057F}', '\u{0580}', '\u{0581}', '\u{0582}', '\u{0583}', '\u{0584}', '\u{0585}', '\u{0586}', '\u{0587}', '\u{1D00}', '\u{1D01}', '\u{1D02}', '\u{1D03}', '\u{1D04}', '\u{1D05}', '\u{1D06}', '\u{1D07}', '\u{1D08}', '\u{1D09}', '\u{1D0A}', '\u{1D0B}', '\u{1D0C}', '\u{1D0D}', '\u{1D0E}', '\u{1D0F}', '\u{1D10}', '\u{1D11}', '\u{1D12}', '\u{1D13}', '\u{1D14}', '\u{1D15}', '\u{1D16}', '\u{1D17}', '\u{1D18}', '\u{1D19}', '\u{1D1A}', '\u{1D1B}', '\u{1D1C}', '\u{1D1D}', '\u{1D1E}', '\u{1D1F}', '\u{1D20}', '\u{1D21}', '\u{1D22}', '\u{1D23}', '\u{1D24}', '\u{1D25}', '\u{1D26}', '\u{1D27}', '\u{1D28}', '\u{1D29}', '\u{1D2A}', '\u{1D2B}', '\u{1D62}', '\u{1D63}', '\u{1D64}', '\u{1D65}', '\u{1D66}', '\u{1D67}', '\u{1D68}', '\u{1D69}', '\u{1D6A}', '\u{1D6B}', '\u{1D6C}', '\u{1D6D}', '\u{1D6E}', '\u{1D6F}', '\u{1D70}', '\u{1D71}', '\u{1D72}', '\u{1D73}', '\u{1D74}', '\u{1D75}', '\u{1D76}', '\u{1D77}', '\u{1D79}', '\u{1D7A}', '\u{1D7B}', '\u{1D7C}', '\u{1D7D}', '\u{1D7E}', '\u{1D7F}', '\u{1D80}', '\u{1D81}', '\u{1D82}', '\u{1D83}', '\u{1D84}', '\u{1D85}', '\u{1D86}', '\u{1D87}', '\u{1D88}', '\u{1D89}', '\u{1D8A}', '\u{1D8B}', '\u{1D8C}', '\u{1D8D}', '\u{1D8E}', '\u{1D8F}', '\u{1D90}', '\u{1D91}', '\u{1D92}', '\u{1D93}', '\u{1D94}', '\u{1D95}', '\u{1D96}', '\u{1D97}', '\u{1D98}', '\u{1D99}', '\u{1D9A}', '\u{1E01}', '\u{1E03}', '\u{1E05}', '\u{1E07}', '\u{1E09}', '\u{1E0B}', '\u{1E0D}', '\u{1E0F}', '\u{1E11}', '\u{1E13}', '\u{1E15}', '\u{1E17}', '\u{1E19}', '\u{1E1B}', '\u{1E1D}', '\u{1E1F}', '\u{1E21}', '\u{1E23}', '\u{1E25}', '\u{1E27}', '\u{1E29}', '\u{1E2B}', '\u{1E2D}', '\u{1E2F}', '\u{1E31}', '\u{1E33}', '\u{1E35}', '\u{1E37}', '\u{1E39}', '\u{1E3B}', '\u{1E3D}', '\u{1E3F}', '\u{1E41}', '\u{1E43}', '\u{1E45}', '\u{1E47}', '\u{1E49}', '\u{1E4B}', '\u{1E4D}', '\u{1E4F}', '\u{1E51}', '\u{1E53}', '\u{1E55}', '\u{1E57}', '\u{1E59}', '\u{1E5B}', '\u{1E5D}', '\u{1E5F}', '\u{1E61}', '\u{1E63}', '\u{1E65}', '\u{1E67}', '\u{1E69}', '\u{1E6B}', '\u{1E6D}', '\u{1E6F}', '\u{1E71}', '\u{1E73}', '\u{1E75}', '\u{1E77}', '\u{1E79}', '\u{1E7B}', '\u{1E7D}', '\u{1E7F}', '\u{1E81}', '\u{1E83}', '\u{1E85}', '\u{1E87}', '\u{1E89}', '\u{1E8B}', '\u{1E8D}', '\u{1E8F}', '\u{1E91}', '\u{1E93}', '\u{1E95}', '\u{1E96}', '\u{1E97}', '\u{1E98}', '\u{1E99}', '\u{1E9A}', '\u{1E9B}', '\u{1E9C}', '\u{1E9D}', '\u{1E9F}', '\u{1EA1}', '\u{1EA3}', '\u{1EA5}', '\u{1EA7}', '\u{1EA9}', '\u{1EAB}', '\u{1EAD}', '\u{1EAF}', '\u{1EB1}', '\u{1EB3}', '\u{1EB5}', '\u{1EB7}', '\u{1EB9}', '\u{1EBB}', '\u{1EBD}', '\u{1EBF}', '\u{1EC1}', '\u{1EC3}', '\u{1EC5}', '\u{1EC7}', '\u{1EC9}', '\u{1ECB}', '\u{1ECD}', '\u{1ECF}', '\u{1ED1}', '\u{1ED3}', '\u{1ED5}', '\u{1ED7}', '\u{1ED9}', '\u{1EDB}', '\u{1EDD}', '\u{1EDF}', '\u{1EE1}', '\u{1EE3}', '\u{1EE5}', '\u{1EE7}', '\u{1EE9}', '\u{1EEB}', '\u{1EED}', '\u{1EEF}', '\u{1EF1}', '\u{1EF3}', '\u{1EF5}', '\u{1EF7}', '\u{1EF9}', '\u{1EFB}', '\u{1EFD}', '\u{1EFF}', '\u{1F00}', '\u{1F01}', '\u{1F02}', '\u{1F03}', '\u{1F04}', '\u{1F05}', '\u{1F06}', '\u{1F07}', '\u{1F10}', '\u{1F11}', '\u{1F12}', '\u{1F13}', '\u{1F14}', '\u{1F15}', '\u{1F20}', '\u{1F21}', '\u{1F22}', '\u{1F23}', '\u{1F24}', '\u{1F25}', '\u{1F26}', '\u{1F27}', '\u{1F30}', '\u{1F31}', '\u{1F32}', '\u{1F33}', '\u{1F34}', '\u{1F35}', '\u{1F36}', '\u{1F37}', '\u{1F40}', '\u{1F41}', '\u{1F42}', '\u{1F43}', '\u{1F44}', '\u{1F45}', '\u{1F50}', '\u{1F51}', '\u{1F52}', '\u{1F53}', '\u{1F54}', '\u{1F55}', '\u{1F56}', '\u{1F57}', '\u{1F60}', '\u{1F61}', '\u{1F62}', '\u{1F63}', '\u{1F64}', '\u{1F65}', '\u{1F66}', '\u{1F67}', '\u{1F70}', '\u{1F71}', '\u{1F72}', '\u{1F73}', '\u{1F74}', '\u{1F75}', '\u{1F76}', '\u{1F77}', '\u{1F78}', '\u{1F79}', '\u{1F7A}', '\u{1F7B}', '\u{1F7C}', '\u{1F7D}', '\u{1F80}', '\u{1F81}', '\u{1F82}', '\u{1F83}', '\u{1F84}', '\u{1F85}', '\u{1F86}', '\u{1F87}', '\u{1F90}', '\u{1F91}', '\u{1F92}', '\u{1F93}', '\u{1F94}', '\u{1F95}', '\u{1F96}', '\u{1F97}', '\u{1FA0}', '\u{1FA1}', '\u{1FA2}', '\u{1FA3}', '\u{1FA4}', '\u{1FA5}', '\u{1FA6}', '\u{1FA7}', '\u{1FB0}', '\u{1FB1}', '\u{1FB2}', '\u{1FB3}', '\u{1FB4}', '\u{1FB6}', '\u{1FB7}', '\u{1FBE}', '\u{1FC2}', '\u{1FC3}', '\u{1FC4}', '\u{1FC6}', '\u{1FC7}', '\u{1FD0}', '\u{1FD1}', '\u{1FD2}', '\u{1FD3}', '\u{1FD6}', '\u{1FD7}', '\u{1FE0}', '\u{1FE1}', '\u{1FE2}', '\u{1FE3}', '\u{1FE4}', '\u{1FE5}', '\u{1FE6}', '\u{1FE7}', '\u{1FF2}', '\u{1FF3}', '\u{1FF4}', '\u{1FF6}', '\u{1FF7}', '\u{2071}', '\u{207F}', '\u{210A}', '\u{210E}', '\u{210F}', '\u{2113}', '\u{212F}', '\u{2134}', '\u{2139}', '\u{213C}', '\u{213D}', '\u{2146}', '\u{2147}', '\u{2148}', '\u{2149}', '\u{214E}', '\u{2184}', '\u{2C30}', '\u{2C31}', '\u{2C32}', '\u{2C33}', '\u{2C34}', '\u{2C35}', '\u{2C36}', '\u{2C37}', '\u{2C38}', '\u{2C39}', '\u{2C3A}', '\u{2C3B}', '\u{2C3C}', '\u{2C3D}', '\u{2C3E}', '\u{2C3F}', '\u{2C40}', '\u{2C41}', '\u{2C42}', '\u{2C43}', '\u{2C44}', '\u{2C45}', '\u{2C46}', '\u{2C47}', '\u{2C48}', '\u{2C49}', '\u{2C4A}', '\u{2C4B}', '\u{2C4C}', '\u{2C4D}', '\u{2C4E}', '\u{2C4F}', '\u{2C50}', '\u{2C51}', '\u{2C52}', '\u{2C53}', '\u{2C54}', '\u{2C55}', '\u{2C56}', '\u{2C57}', '\u{2C58}', '\u{2C59}', '\u{2C5A}', '\u{2C5B}', '\u{2C5C}', '\u{2C5D}', '\u{2C5E}', '\u{2C61}', '\u{2C65}', '\u{2C66}', '\u{2C68}', '\u{2C6A}', '\u{2C6C}', '\u{2C71}', '\u{2C73}', '\u{2C74}', '\u{2C76}', '\u{2C77}', '\u{2C78}', '\u{2C79}', '\u{2C7A}', '\u{2C7B}', '\u{2C7C}', '\u{2C81}', '\u{2C83}', '\u{2C85}', '\u{2C87}', '\u{2C89}', '\u{2C8B}', '\u{2C8D}', '\u{2C8F}', '\u{2C91}', '\u{2C93}', '\u{2C95}', '\u{2C97}', '\u{2C99}', '\u{2C9B}', '\u{2C9D}', '\u{2C9F}', '\u{2CA1}', '\u{2CA3}', '\u{2CA5}', '\u{2CA7}', '\u{2CA9}', '\u{2CAB}', '\u{2CAD}', '\u{2CAF}', '\u{2CB1}', '\u{2CB3}', '\u{2CB5}', '\u{2CB7}', '\u{2CB9}', '\u{2CBB}', '\u{2CBD}', '\u{2CBF}', '\u{2CC1}', '\u{2CC3}', '\u{2CC5}', '\u{2CC7}', '\u{2CC9}', '\u{2CCB}', '\u{2CCD}', '\u{2CCF}', '\u{2CD1}', '\u{2CD3}', '\u{2CD5}', '\u{2CD7}', '\u{2CD9}', '\u{2CDB}', '\u{2CDD}', '\u{2CDF}', '\u{2CE1}', '\u{2CE3}', '\u{2CE4}', '\u{2D00}', '\u{2D01}', '\u{2D02}', '\u{2D03}', '\u{2D04}', '\u{2D05}', '\u{2D06}', '\u{2D07}', '\u{2D08}', '\u{2D09}', '\u{2D0A}', '\u{2D0B}', '\u{2D0C}', '\u{2D0D}', '\u{2D0E}', '\u{2D0F}', '\u{2D10}', '\u{2D11}', '\u{2D12}', '\u{2D13}', '\u{2D14}', '\u{2D15}', '\u{2D16}', '\u{2D17}', '\u{2D18}', '\u{2D19}', '\u{2D1A}', '\u{2D1B}', '\u{2D1C}', '\u{2D1D}', '\u{2D1E}', '\u{2D1F}', '\u{2D20}', '\u{2D21}', '\u{2D22}', '\u{2D23}', '\u{2D24}', '\u{2D25}', '\u{A641}', '\u{A643}', '\u{A645}', '\u{A647}', '\u{A649}', '\u{A64B}', '\u{A64D}', '\u{A64F}', '\u{A651}', '\u{A653}', '\u{A655}', '\u{A657}', '\u{A659}', '\u{A65B}', '\u{A65D}', '\u{A65F}', '\u{A663}', '\u{A665}', '\u{A667}', '\u{A669}', '\u{A66B}', '\u{A66D}', '\u{A681}', '\u{A683}', '\u{A685}', '\u{A687}', '\u{A689}', '\u{A68B}', '\u{A68D}', '\u{A68F}', '\u{A691}', '\u{A693}', '\u{A695}', '\u{A697}', '\u{A723}', '\u{A725}', '\u{A727}', '\u{A729}', '\u{A72B}', '\u{A72D}', '\u{A72F}', '\u{A730}', '\u{A731}', '\u{A733}', '\u{A735}', '\u{A737}', '\u{A739}', '\u{A73B}', '\u{A73D}', '\u{A73F}', '\u{A741}', '\u{A743}', '\u{A745}', '\u{A747}', '\u{A749}', '\u{A74B}', '\u{A74D}', '\u{A74F}', '\u{A751}', '\u{A753}', '\u{A755}', '\u{A757}', '\u{A759}', '\u{A75B}', '\u{A75D}', '\u{A75F}', '\u{A761}', '\u{A763}', '\u{A765}', '\u{A767}', '\u{A769}', '\u{A76B}', '\u{A76D}', '\u{A76F}', '\u{A771}', '\u{A772}', '\u{A773}', '\u{A774}', '\u{A775}', '\u{A776}', '\u{A777}', '\u{A778}', '\u{A77A}', '\u{A77C}', '\u{A77F}', '\u{A781}', '\u{A783}', '\u{A785}', '\u{A787}', '\u{A78C}', '\u{FB00}', '\u{FB01}', '\u{FB02}', '\u{FB03}', '\u{FB04}', '\u{FB05}', '\u{FB06}', '\u{FB13}', '\u{FB14}', '\u{FB15}', '\u{FB16}', '\u{FB17}', '\u{FF41}', '\u{FF42}', '\u{FF43}', '\u{FF44}', '\u{FF45}', '\u{FF46}', '\u{FF47}', '\u{FF48}', '\u{FF49}', '\u{FF4A}', '\u{FF4B}', '\u{FF4C}', '\u{FF4D}', '\u{FF4E}', '\u{FF4F}', '\u{FF50}', '\u{FF51}', '\u{FF52}', '\u{FF53}', '\u{FF54}', '\u{FF55}', '\u{FF56}', '\u{FF57}', '\u{FF58}', '\u{FF59}', '\u{FF5A}') + + } + + fn is_unicode_titlecase_letter(self) -> bool { + match_char_class!(self, + '\u{01C5}', '\u{01C8}', '\u{01CB}', '\u{01F2}', '\u{1F88}', '\u{1F89}', '\u{1F8A}', '\u{1F8B}', '\u{1F8C}', '\u{1F8D}', '\u{1F8E}', '\u{1F8F}', '\u{1F98}', '\u{1F99}', '\u{1F9A}', '\u{1F9B}', '\u{1F9C}', '\u{1F9D}', '\u{1F9E}', '\u{1F9F}', '\u{1FA8}', '\u{1FA9}', '\u{1FAA}', '\u{1FAB}', '\u{1FAC}', '\u{1FAD}', '\u{1FAE}', '\u{1FAF}', '\u{1FBC}', '\u{1FCC}') + } + + fn is_unicode_modifier_letter(self) -> bool { + match_char_class!(self, + '\u{02B0}', '\u{02B1}', '\u{02B2}', '\u{02B3}', '\u{02B4}', '\u{02B5}', '\u{02B6}', '\u{02B7}', '\u{02B8}', '\u{02B9}', '\u{02BA}', '\u{02BB}', '\u{02BC}', '\u{02BD}', '\u{02BE}', '\u{02BF}', '\u{02C0}', '\u{02C1}', '\u{02C6}', '\u{02C7}', '\u{02C8}', '\u{02C9}', '\u{02CA}', '\u{02CB}', '\u{02CC}', '\u{02CD}', '\u{02CE}', '\u{02CF}', '\u{02D0}', '\u{02D1}', '\u{02E0}', '\u{02E1}', '\u{02E2}', '\u{02E3}', '\u{02E4}', '\u{02EC}', '\u{02EE}', '\u{0374}', '\u{037A}', '\u{0559}', '\u{0640}', '\u{06E5}', '\u{06E6}', '\u{07F4}', '\u{07F5}', '\u{07FA}', '\u{0971}', '\u{0E46}', '\u{0EC6}', '\u{10FC}', '\u{17D7}', '\u{1843}', '\u{1C78}', '\u{1C79}', '\u{1C7A}', '\u{1C7B}', '\u{1C7C}', '\u{1C7D}', '\u{1D2C}', '\u{1D2D}', '\u{1D2E}', '\u{1D2F}', '\u{1D30}', '\u{1D31}', '\u{1D32}', '\u{1D33}', '\u{1D34}', '\u{1D35}', '\u{1D36}', '\u{1D37}', '\u{1D38}', '\u{1D39}', '\u{1D3A}', '\u{1D3B}', '\u{1D3C}', '\u{1D3D}', '\u{1D3E}', '\u{1D3F}', '\u{1D40}', '\u{1D41}', '\u{1D42}', '\u{1D43}', '\u{1D44}', '\u{1D45}', '\u{1D46}', '\u{1D47}', '\u{1D48}', '\u{1D49}', '\u{1D4A}', '\u{1D4B}', '\u{1D4C}', '\u{1D4D}', '\u{1D4E}', '\u{1D4F}', '\u{1D50}', '\u{1D51}', '\u{1D52}', '\u{1D53}', '\u{1D54}', '\u{1D55}', '\u{1D56}', '\u{1D57}', '\u{1D58}', '\u{1D59}', '\u{1D5A}', '\u{1D5B}', '\u{1D5C}', '\u{1D5D}', '\u{1D5E}', '\u{1D5F}', '\u{1D60}', '\u{1D61}', '\u{1D78}', '\u{1D9B}', '\u{1D9C}', '\u{1D9D}', '\u{1D9E}', '\u{1D9F}', '\u{1DA0}', '\u{1DA1}', '\u{1DA2}', '\u{1DA3}', '\u{1DA4}', '\u{1DA5}', '\u{1DA6}', '\u{1DA7}', '\u{1DA8}', '\u{1DA9}', '\u{1DAA}', '\u{1DAB}', '\u{1DAC}', '\u{1DAD}', '\u{1DAE}', '\u{1DAF}', '\u{1DB0}', '\u{1DB1}', '\u{1DB2}', '\u{1DB3}', '\u{1DB4}', '\u{1DB5}', '\u{1DB6}', '\u{1DB7}', '\u{1DB8}', '\u{1DB9}', '\u{1DBA}', '\u{1DBB}', '\u{1DBC}', '\u{1DBD}', '\u{1DBE}', '\u{1DBF}', '\u{2090}', '\u{2091}', '\u{2092}', '\u{2093}', '\u{2094}', '\u{2C7D}', '\u{2D6F}', '\u{2E2F}', '\u{3005}', '\u{3031}', '\u{3032}', '\u{3033}', '\u{3034}', '\u{3035}', '\u{303B}', '\u{309D}', '\u{309E}', '\u{30FC}', '\u{30FD}', '\u{30FE}', '\u{A015}', '\u{A60C}', '\u{A67F}', '\u{A717}', '\u{A718}', '\u{A719}', '\u{A71A}', '\u{A71B}', '\u{A71C}', '\u{A71D}', '\u{A71E}', '\u{A71F}', '\u{A770}', '\u{A788}', '\u{FF70}', '\u{FF9E}', '\u{FF9F}') + } + + fn is_unicode_other_letter(self) -> bool { + match_char_class!(self, + '\u{01BB}', '\u{01C0}', '\u{01C1}', '\u{01C2}', '\u{01C3}', '\u{0294}', '\u{05D0}', '\u{05D1}', '\u{05D2}', '\u{05D3}', '\u{05D4}', '\u{05D5}', '\u{05D6}', '\u{05D7}', '\u{05D8}', '\u{05D9}', '\u{05DA}', '\u{05DB}', '\u{05DC}', '\u{05DD}', '\u{05DE}', '\u{05DF}', '\u{05E0}', '\u{05E1}', '\u{05E2}', '\u{05E3}', '\u{05E4}', '\u{05E5}', '\u{05E6}', '\u{05E7}', '\u{05E8}', '\u{05E9}', '\u{05EA}', '\u{05F0}', '\u{05F1}', '\u{05F2}', '\u{0621}', '\u{0622}', '\u{0623}', '\u{0624}', '\u{0625}', '\u{0626}', '\u{0627}', '\u{0628}', '\u{0629}', '\u{062A}', '\u{062B}', '\u{062C}', '\u{062D}', '\u{062E}', '\u{062F}', '\u{0630}', '\u{0631}', '\u{0632}', '\u{0633}', '\u{0634}', '\u{0635}', '\u{0636}', '\u{0637}', '\u{0638}', '\u{0639}', '\u{063A}', '\u{063B}', '\u{063C}', '\u{063D}', '\u{063E}', '\u{063F}', '\u{0641}', '\u{0642}', '\u{0643}', '\u{0644}', '\u{0645}', '\u{0646}', '\u{0647}', '\u{0648}', '\u{0649}', '\u{064A}', '\u{066E}', '\u{066F}', '\u{0671}', '\u{0672}', '\u{0673}', '\u{0674}', '\u{0675}', '\u{0676}', '\u{0677}', '\u{0678}', '\u{0679}', '\u{067A}', '\u{067B}', '\u{067C}', '\u{067D}', '\u{067E}', '\u{067F}', '\u{0680}', '\u{0681}', '\u{0682}', '\u{0683}', '\u{0684}', '\u{0685}', '\u{0686}', '\u{0687}', '\u{0688}', '\u{0689}', '\u{068A}', '\u{068B}', '\u{068C}', '\u{068D}', '\u{068E}', '\u{068F}', '\u{0690}', '\u{0691}', '\u{0692}', '\u{0693}', '\u{0694}', '\u{0695}', '\u{0696}', '\u{0697}', '\u{0698}', '\u{0699}', '\u{069A}', '\u{069B}', '\u{069C}', '\u{069D}', '\u{069E}', '\u{069F}', '\u{06A0}', '\u{06A1}', '\u{06A2}', '\u{06A3}', '\u{06A4}', '\u{06A5}', '\u{06A6}', '\u{06A7}', '\u{06A8}', '\u{06A9}', '\u{06AA}', '\u{06AB}', '\u{06AC}', '\u{06AD}', '\u{06AE}', '\u{06AF}', '\u{06B0}', '\u{06B1}', '\u{06B2}', '\u{06B3}', '\u{06B4}', '\u{06B5}', '\u{06B6}', '\u{06B7}', '\u{06B8}', '\u{06B9}', '\u{06BA}', '\u{06BB}', '\u{06BC}', '\u{06BD}', '\u{06BE}', '\u{06BF}', '\u{06C0}', '\u{06C1}', '\u{06C2}', '\u{06C3}', '\u{06C4}', '\u{06C5}', '\u{06C6}', '\u{06C7}', '\u{06C8}', '\u{06C9}', '\u{06CA}', '\u{06CB}', '\u{06CC}', '\u{06CD}', '\u{06CE}', '\u{06CF}', '\u{06D0}', '\u{06D1}', '\u{06D2}', '\u{06D3}', '\u{06D5}', '\u{06EE}', '\u{06EF}', '\u{06FA}', '\u{06FB}', '\u{06FC}', '\u{06FF}', '\u{0710}', '\u{0712}', '\u{0713}', '\u{0714}', '\u{0715}', '\u{0716}', '\u{0717}', '\u{0718}', '\u{0719}', '\u{071A}', '\u{071B}', '\u{071C}', '\u{071D}', '\u{071E}', '\u{071F}', '\u{0720}', '\u{0721}', '\u{0722}', '\u{0723}', '\u{0724}', '\u{0725}', '\u{0726}', '\u{0727}', '\u{0728}', '\u{0729}', '\u{072A}', '\u{072B}', '\u{072C}', '\u{072D}', '\u{072E}', '\u{072F}', '\u{074D}', '\u{074E}', '\u{074F}', '\u{0750}', '\u{0751}', '\u{0752}', '\u{0753}', '\u{0754}', '\u{0755}', '\u{0756}', '\u{0757}', '\u{0758}', '\u{0759}', '\u{075A}', '\u{075B}', '\u{075C}', '\u{075D}', '\u{075E}', '\u{075F}', '\u{0760}', '\u{0761}', '\u{0762}', '\u{0763}', '\u{0764}', '\u{0765}', '\u{0766}', '\u{0767}', '\u{0768}', '\u{0769}', '\u{076A}', '\u{076B}', '\u{076C}', '\u{076D}', '\u{076E}', '\u{076F}', '\u{0770}', '\u{0771}', '\u{0772}', '\u{0773}', '\u{0774}', '\u{0775}', '\u{0776}', '\u{0777}', '\u{0778}', '\u{0779}', '\u{077A}', '\u{077B}', '\u{077C}', '\u{077D}', '\u{077E}', '\u{077F}', '\u{0780}', '\u{0781}', '\u{0782}', '\u{0783}', '\u{0784}', '\u{0785}', '\u{0786}', '\u{0787}', '\u{0788}', '\u{0789}', '\u{078A}', '\u{078B}', '\u{078C}', '\u{078D}', '\u{078E}', '\u{078F}', '\u{0790}', '\u{0791}', '\u{0792}', '\u{0793}', '\u{0794}', '\u{0795}', '\u{0796}', '\u{0797}', '\u{0798}', '\u{0799}', '\u{079A}', '\u{079B}', '\u{079C}', '\u{079D}', '\u{079E}', '\u{079F}', '\u{07A0}', '\u{07A1}', '\u{07A2}', '\u{07A3}', '\u{07A4}', '\u{07A5}', '\u{07B1}', '\u{07CA}', '\u{07CB}', '\u{07CC}', '\u{07CD}', '\u{07CE}', '\u{07CF}', '\u{07D0}', '\u{07D1}', '\u{07D2}', '\u{07D3}', '\u{07D4}', '\u{07D5}', '\u{07D6}', '\u{07D7}', '\u{07D8}', '\u{07D9}', '\u{07DA}', '\u{07DB}', '\u{07DC}', '\u{07DD}', '\u{07DE}', '\u{07DF}', '\u{07E0}', '\u{07E1}', '\u{07E2}', '\u{07E3}', '\u{07E4}', '\u{07E5}', '\u{07E6}', '\u{07E7}', '\u{07E8}', '\u{07E9}', '\u{07EA}', '\u{0904}', '\u{0905}', '\u{0906}', '\u{0907}', '\u{0908}', '\u{0909}', '\u{090A}', '\u{090B}', '\u{090C}', '\u{090D}', '\u{090E}', '\u{090F}', '\u{0910}', '\u{0911}', '\u{0912}', '\u{0913}', '\u{0914}', '\u{0915}', '\u{0916}', '\u{0917}', '\u{0918}', '\u{0919}', '\u{091A}', '\u{091B}', '\u{091C}', '\u{091D}', '\u{091E}', '\u{091F}', '\u{0920}', '\u{0921}', '\u{0922}', '\u{0923}', '\u{0924}', '\u{0925}', '\u{0926}', '\u{0927}', '\u{0928}', '\u{0929}', '\u{092A}', '\u{092B}', '\u{092C}', '\u{092D}', '\u{092E}', '\u{092F}', '\u{0930}', '\u{0931}', '\u{0932}', '\u{0933}', '\u{0934}', '\u{0935}', '\u{0936}', '\u{0937}', '\u{0938}', '\u{0939}', '\u{093D}', '\u{0950}', '\u{0958}', '\u{0959}', '\u{095A}', '\u{095B}', '\u{095C}', '\u{095D}', '\u{095E}', '\u{095F}', '\u{0960}', '\u{0961}', '\u{0972}', '\u{097B}', '\u{097C}', '\u{097D}', '\u{097E}', '\u{097F}', '\u{0985}', '\u{0986}', '\u{0987}', '\u{0988}', '\u{0989}', '\u{098A}', '\u{098B}', '\u{098C}', '\u{098F}', '\u{0990}', '\u{0993}', '\u{0994}', '\u{0995}', '\u{0996}', '\u{0997}', '\u{0998}', '\u{0999}', '\u{099A}', '\u{099B}', '\u{099C}', '\u{099D}', '\u{099E}', '\u{099F}', '\u{09A0}', '\u{09A1}', '\u{09A2}', '\u{09A3}', '\u{09A4}', '\u{09A5}', '\u{09A6}', '\u{09A7}', '\u{09A8}', '\u{09AA}', '\u{09AB}', '\u{09AC}', '\u{09AD}', '\u{09AE}', '\u{09AF}', '\u{09B0}', '\u{09B2}', '\u{09B6}', '\u{09B7}', '\u{09B8}', '\u{09B9}', '\u{09BD}', '\u{09CE}', '\u{09DC}', '\u{09DD}', '\u{09DF}', '\u{09E0}', '\u{09E1}', '\u{09F0}', '\u{09F1}', '\u{0A05}', '\u{0A06}', '\u{0A07}', '\u{0A08}', '\u{0A09}', '\u{0A0A}', '\u{0A0F}', '\u{0A10}', '\u{0A13}', '\u{0A14}', '\u{0A15}', '\u{0A16}', '\u{0A17}', '\u{0A18}', '\u{0A19}', '\u{0A1A}', '\u{0A1B}', '\u{0A1C}', '\u{0A1D}', '\u{0A1E}', '\u{0A1F}', '\u{0A20}', '\u{0A21}', '\u{0A22}', '\u{0A23}', '\u{0A24}', '\u{0A25}', '\u{0A26}', '\u{0A27}', '\u{0A28}', '\u{0A2A}', '\u{0A2B}', '\u{0A2C}', '\u{0A2D}', '\u{0A2E}', '\u{0A2F}', '\u{0A30}', '\u{0A32}', '\u{0A33}', '\u{0A35}', '\u{0A36}', '\u{0A38}', '\u{0A39}', '\u{0A59}', '\u{0A5A}', '\u{0A5B}', '\u{0A5C}', '\u{0A5E}', '\u{0A72}', '\u{0A73}', '\u{0A74}', '\u{0A85}', '\u{0A86}', '\u{0A87}', '\u{0A88}', '\u{0A89}', '\u{0A8A}', '\u{0A8B}', '\u{0A8C}', '\u{0A8D}', '\u{0A8F}', '\u{0A90}', '\u{0A91}', '\u{0A93}', '\u{0A94}', '\u{0A95}', '\u{0A96}', '\u{0A97}', '\u{0A98}', '\u{0A99}', '\u{0A9A}', '\u{0A9B}', '\u{0A9C}', '\u{0A9D}', '\u{0A9E}', '\u{0A9F}', '\u{0AA0}', '\u{0AA1}', '\u{0AA2}', '\u{0AA3}', '\u{0AA4}', '\u{0AA5}', '\u{0AA6}', '\u{0AA7}', '\u{0AA8}', '\u{0AAA}', '\u{0AAB}', '\u{0AAC}', '\u{0AAD}', '\u{0AAE}', '\u{0AAF}', '\u{0AB0}', '\u{0AB2}', '\u{0AB3}', '\u{0AB5}', '\u{0AB6}', '\u{0AB7}', '\u{0AB8}', '\u{0AB9}', '\u{0ABD}', '\u{0AD0}', '\u{0AE0}', '\u{0AE1}', '\u{0B05}', '\u{0B06}', '\u{0B07}', '\u{0B08}', '\u{0B09}', '\u{0B0A}', '\u{0B0B}', '\u{0B0C}', '\u{0B0F}', '\u{0B10}', '\u{0B13}', '\u{0B14}', '\u{0B15}', '\u{0B16}', '\u{0B17}', '\u{0B18}', '\u{0B19}', '\u{0B1A}', '\u{0B1B}', '\u{0B1C}', '\u{0B1D}', '\u{0B1E}', '\u{0B1F}', '\u{0B20}', '\u{0B21}', '\u{0B22}', '\u{0B23}', '\u{0B24}', '\u{0B25}', '\u{0B26}', '\u{0B27}', '\u{0B28}', '\u{0B2A}', '\u{0B2B}', '\u{0B2C}', '\u{0B2D}', '\u{0B2E}', '\u{0B2F}', '\u{0B30}', '\u{0B32}', '\u{0B33}', '\u{0B35}', '\u{0B36}', '\u{0B37}', '\u{0B38}', '\u{0B39}', '\u{0B3D}', '\u{0B5C}', '\u{0B5D}', '\u{0B5F}', '\u{0B60}', '\u{0B61}', '\u{0B71}', '\u{0B83}', '\u{0B85}', '\u{0B86}', '\u{0B87}', '\u{0B88}', '\u{0B89}', '\u{0B8A}', '\u{0B8E}', '\u{0B8F}', '\u{0B90}', '\u{0B92}', '\u{0B93}', '\u{0B94}', '\u{0B95}', '\u{0B99}', '\u{0B9A}', '\u{0B9C}', '\u{0B9E}', '\u{0B9F}', '\u{0BA3}', '\u{0BA4}', '\u{0BA8}', '\u{0BA9}', '\u{0BAA}', '\u{0BAE}', '\u{0BAF}', '\u{0BB0}', '\u{0BB1}', '\u{0BB2}', '\u{0BB3}', '\u{0BB4}', '\u{0BB5}', '\u{0BB6}', '\u{0BB7}', '\u{0BB8}', '\u{0BB9}', '\u{0BD0}', '\u{0C05}', '\u{0C06}', '\u{0C07}', '\u{0C08}', '\u{0C09}', '\u{0C0A}', '\u{0C0B}', '\u{0C0C}', '\u{0C0E}', '\u{0C0F}', '\u{0C10}', '\u{0C12}', '\u{0C13}', '\u{0C14}', '\u{0C15}', '\u{0C16}', '\u{0C17}', '\u{0C18}', '\u{0C19}', '\u{0C1A}', '\u{0C1B}', '\u{0C1C}', '\u{0C1D}', '\u{0C1E}', '\u{0C1F}', '\u{0C20}', '\u{0C21}', '\u{0C22}', '\u{0C23}', '\u{0C24}', '\u{0C25}', '\u{0C26}', '\u{0C27}', '\u{0C28}', '\u{0C2A}', '\u{0C2B}', '\u{0C2C}', '\u{0C2D}', '\u{0C2E}', '\u{0C2F}', '\u{0C30}', '\u{0C31}', '\u{0C32}', '\u{0C33}', '\u{0C35}', '\u{0C36}', '\u{0C37}', '\u{0C38}', '\u{0C39}', '\u{0C3D}', '\u{0C58}', '\u{0C59}', '\u{0C60}', '\u{0C61}', '\u{0C85}', '\u{0C86}', '\u{0C87}', '\u{0C88}', '\u{0C89}', '\u{0C8A}', '\u{0C8B}', '\u{0C8C}', '\u{0C8E}', '\u{0C8F}', '\u{0C90}', '\u{0C92}', '\u{0C93}', '\u{0C94}', '\u{0C95}', '\u{0C96}', '\u{0C97}', '\u{0C98}', '\u{0C99}', '\u{0C9A}', '\u{0C9B}', '\u{0C9C}', '\u{0C9D}', '\u{0C9E}', '\u{0C9F}', '\u{0CA0}', '\u{0CA1}', '\u{0CA2}', '\u{0CA3}', '\u{0CA4}', '\u{0CA5}', '\u{0CA6}', '\u{0CA7}', '\u{0CA8}', '\u{0CAA}', '\u{0CAB}', '\u{0CAC}', '\u{0CAD}', '\u{0CAE}', '\u{0CAF}', '\u{0CB0}', '\u{0CB1}', '\u{0CB2}', '\u{0CB3}', '\u{0CB5}', '\u{0CB6}', '\u{0CB7}', '\u{0CB8}', '\u{0CB9}', '\u{0CBD}', '\u{0CDE}', '\u{0CE0}', '\u{0CE1}', '\u{0D05}', '\u{0D06}', '\u{0D07}', '\u{0D08}', '\u{0D09}', '\u{0D0A}', '\u{0D0B}', '\u{0D0C}', '\u{0D0E}', '\u{0D0F}', '\u{0D10}', '\u{0D12}', '\u{0D13}', '\u{0D14}', '\u{0D15}', '\u{0D16}', '\u{0D17}', '\u{0D18}', '\u{0D19}', '\u{0D1A}', '\u{0D1B}', '\u{0D1C}', '\u{0D1D}', '\u{0D1E}', '\u{0D1F}', '\u{0D20}', '\u{0D21}', '\u{0D22}', '\u{0D23}', '\u{0D24}', '\u{0D25}', '\u{0D26}', '\u{0D27}', '\u{0D28}', '\u{0D2A}', '\u{0D2B}', '\u{0D2C}', '\u{0D2D}', '\u{0D2E}', '\u{0D2F}', '\u{0D30}', '\u{0D31}', '\u{0D32}', '\u{0D33}', '\u{0D34}', '\u{0D35}', '\u{0D36}', '\u{0D37}', '\u{0D38}', '\u{0D39}', '\u{0D3D}', '\u{0D60}', '\u{0D61}', '\u{0D7A}', '\u{0D7B}', '\u{0D7C}', '\u{0D7D}', '\u{0D7E}', '\u{0D7F}', '\u{0D85}', '\u{0D86}', '\u{0D87}', '\u{0D88}', '\u{0D89}', '\u{0D8A}', '\u{0D8B}', '\u{0D8C}', '\u{0D8D}', '\u{0D8E}', '\u{0D8F}', '\u{0D90}', '\u{0D91}', '\u{0D92}', '\u{0D93}', '\u{0D94}', '\u{0D95}', '\u{0D96}', '\u{0D9A}', '\u{0D9B}', '\u{0D9C}', '\u{0D9D}', '\u{0D9E}', '\u{0D9F}', '\u{0DA0}', '\u{0DA1}', '\u{0DA2}', '\u{0DA3}', '\u{0DA4}', '\u{0DA5}', '\u{0DA6}', '\u{0DA7}', '\u{0DA8}', '\u{0DA9}', '\u{0DAA}', '\u{0DAB}', '\u{0DAC}', '\u{0DAD}', '\u{0DAE}', '\u{0DAF}', '\u{0DB0}', '\u{0DB1}', '\u{0DB3}', '\u{0DB4}', '\u{0DB5}', '\u{0DB6}', '\u{0DB7}', '\u{0DB8}', '\u{0DB9}', '\u{0DBA}', '\u{0DBB}', '\u{0DBD}', '\u{0DC0}', '\u{0DC1}', '\u{0DC2}', '\u{0DC3}', '\u{0DC4}', '\u{0DC5}', '\u{0DC6}', '\u{0E01}', '\u{0E02}', '\u{0E03}', '\u{0E04}', '\u{0E05}', '\u{0E06}', '\u{0E07}', '\u{0E08}', '\u{0E09}', '\u{0E0A}', '\u{0E0B}', '\u{0E0C}', '\u{0E0D}', '\u{0E0E}', '\u{0E0F}', '\u{0E10}', '\u{0E11}', '\u{0E12}', '\u{0E13}', '\u{0E14}', '\u{0E15}', '\u{0E16}', '\u{0E17}', '\u{0E18}', '\u{0E19}', '\u{0E1A}', '\u{0E1B}', '\u{0E1C}', '\u{0E1D}', '\u{0E1E}', '\u{0E1F}', '\u{0E20}', '\u{0E21}', '\u{0E22}', '\u{0E23}', '\u{0E24}', '\u{0E25}', '\u{0E26}', '\u{0E27}', '\u{0E28}', '\u{0E29}', '\u{0E2A}', '\u{0E2B}', '\u{0E2C}', '\u{0E2D}', '\u{0E2E}', '\u{0E2F}', '\u{0E30}', '\u{0E32}', '\u{0E33}', '\u{0E40}', '\u{0E41}', '\u{0E42}', '\u{0E43}', '\u{0E44}', '\u{0E45}', '\u{0E81}', '\u{0E82}', '\u{0E84}', '\u{0E87}', '\u{0E88}', '\u{0E8A}', '\u{0E8D}', '\u{0E94}', '\u{0E95}', '\u{0E96}', '\u{0E97}', '\u{0E99}', '\u{0E9A}', '\u{0E9B}', '\u{0E9C}', '\u{0E9D}', '\u{0E9E}', '\u{0E9F}', '\u{0EA1}', '\u{0EA2}', '\u{0EA3}', '\u{0EA5}', '\u{0EA7}', '\u{0EAA}', '\u{0EAB}', '\u{0EAD}', '\u{0EAE}', '\u{0EAF}', '\u{0EB0}', '\u{0EB2}', '\u{0EB3}', '\u{0EBD}', '\u{0EC0}', '\u{0EC1}', '\u{0EC2}', '\u{0EC3}', '\u{0EC4}', '\u{0EDC}', '\u{0EDD}', '\u{0F00}', '\u{0F40}', '\u{0F41}', '\u{0F42}', '\u{0F43}', '\u{0F44}', '\u{0F45}', '\u{0F46}', '\u{0F47}', '\u{0F49}', '\u{0F4A}', '\u{0F4B}', '\u{0F4C}', '\u{0F4D}', '\u{0F4E}', '\u{0F4F}', '\u{0F50}', '\u{0F51}', '\u{0F52}', '\u{0F53}', '\u{0F54}', '\u{0F55}', '\u{0F56}', '\u{0F57}', '\u{0F58}', '\u{0F59}', '\u{0F5A}', '\u{0F5B}', '\u{0F5C}', '\u{0F5D}', '\u{0F5E}', '\u{0F5F}', '\u{0F60}', '\u{0F61}', '\u{0F62}', '\u{0F63}', '\u{0F64}', '\u{0F65}', '\u{0F66}', '\u{0F67}', '\u{0F68}', '\u{0F69}', '\u{0F6A}', '\u{0F6B}', '\u{0F6C}', '\u{0F88}', '\u{0F89}', '\u{0F8A}', '\u{0F8B}', '\u{1000}', '\u{1001}', '\u{1002}', '\u{1003}', '\u{1004}', '\u{1005}', '\u{1006}', '\u{1007}', '\u{1008}', '\u{1009}', '\u{100A}', '\u{100B}', '\u{100C}', '\u{100D}', '\u{100E}', '\u{100F}', '\u{1010}', '\u{1011}', '\u{1012}', '\u{1013}', '\u{1014}', '\u{1015}', '\u{1016}', '\u{1017}', '\u{1018}', '\u{1019}', '\u{101A}', '\u{101B}', '\u{101C}', '\u{101D}', '\u{101E}', '\u{101F}', '\u{1020}', '\u{1021}', '\u{1022}', '\u{1023}', '\u{1024}', '\u{1025}', '\u{1026}', '\u{1027}', '\u{1028}', '\u{1029}', '\u{102A}', '\u{103F}', '\u{1050}', '\u{1051}', '\u{1052}', '\u{1053}', '\u{1054}', '\u{1055}', '\u{105A}', '\u{105B}', '\u{105C}', '\u{105D}', '\u{1061}', '\u{1065}', '\u{1066}', '\u{106E}', '\u{106F}', '\u{1070}', '\u{1075}', '\u{1076}', '\u{1077}', '\u{1078}', '\u{1079}', '\u{107A}', '\u{107B}', '\u{107C}', '\u{107D}', '\u{107E}', '\u{107F}', '\u{1080}', '\u{1081}', '\u{108E}', '\u{10D0}', '\u{10D1}', '\u{10D2}', '\u{10D3}', '\u{10D4}', '\u{10D5}', '\u{10D6}', '\u{10D7}', '\u{10D8}', '\u{10D9}', '\u{10DA}', '\u{10DB}', '\u{10DC}', '\u{10DD}', '\u{10DE}', '\u{10DF}', '\u{10E0}', '\u{10E1}', '\u{10E2}', '\u{10E3}', '\u{10E4}', '\u{10E5}', '\u{10E6}', '\u{10E7}', '\u{10E8}', '\u{10E9}', '\u{10EA}', '\u{10EB}', '\u{10EC}', '\u{10ED}', '\u{10EE}', '\u{10EF}', '\u{10F0}', '\u{10F1}', '\u{10F2}', '\u{10F3}', '\u{10F4}', '\u{10F5}', '\u{10F6}', '\u{10F7}', '\u{10F8}', '\u{10F9}', '\u{10FA}', '\u{1100}', '\u{1101}', '\u{1102}', '\u{1103}', '\u{1104}', '\u{1105}', '\u{1106}', '\u{1107}', '\u{1108}', '\u{1109}', '\u{110A}', '\u{110B}', '\u{110C}', '\u{110D}', '\u{110E}', '\u{110F}', '\u{1110}', '\u{1111}', '\u{1112}', '\u{1113}', '\u{1114}', '\u{1115}', '\u{1116}', '\u{1117}', '\u{1118}', '\u{1119}', '\u{111A}', '\u{111B}', '\u{111C}', '\u{111D}', '\u{111E}', '\u{111F}', '\u{1120}', '\u{1121}', '\u{1122}', '\u{1123}', '\u{1124}', '\u{1125}', '\u{1126}', '\u{1127}', '\u{1128}', '\u{1129}', '\u{112A}', '\u{112B}', '\u{112C}', '\u{112D}', '\u{112E}', '\u{112F}', '\u{1130}', '\u{1131}', '\u{1132}', '\u{1133}', '\u{1134}', '\u{1135}', '\u{1136}', '\u{1137}', '\u{1138}', '\u{1139}', '\u{113A}', '\u{113B}', '\u{113C}', '\u{113D}', '\u{113E}', '\u{113F}', '\u{1140}', '\u{1141}', '\u{1142}', '\u{1143}', '\u{1144}', '\u{1145}', '\u{1146}', '\u{1147}', '\u{1148}', '\u{1149}', '\u{114A}', '\u{114B}', '\u{114C}', '\u{114D}', '\u{114E}', '\u{114F}', '\u{1150}', '\u{1151}', '\u{1152}', '\u{1153}', '\u{1154}', '\u{1155}', '\u{1156}', '\u{1157}', '\u{1158}', '\u{1159}', '\u{115F}', '\u{1160}', '\u{1161}', '\u{1162}', '\u{1163}', '\u{1164}', '\u{1165}', '\u{1166}', '\u{1167}', '\u{1168}', '\u{1169}', '\u{116A}', '\u{116B}', '\u{116C}', '\u{116D}', '\u{116E}', '\u{116F}', '\u{1170}', '\u{1171}', '\u{1172}', '\u{1173}', '\u{1174}', '\u{1175}', '\u{1176}', '\u{1177}', '\u{1178}', '\u{1179}', '\u{117A}', '\u{117B}', '\u{117C}', '\u{117D}', '\u{117E}', '\u{117F}', '\u{1180}', '\u{1181}', '\u{1182}', '\u{1183}', '\u{1184}', '\u{1185}', '\u{1186}', '\u{1187}', '\u{1188}', '\u{1189}', '\u{118A}', '\u{118B}', '\u{118C}', '\u{118D}', '\u{118E}', '\u{118F}', '\u{1190}', '\u{1191}', '\u{1192}', '\u{1193}', '\u{1194}', '\u{1195}', '\u{1196}', '\u{1197}', '\u{1198}', '\u{1199}', '\u{119A}', '\u{119B}', '\u{119C}', '\u{119D}', '\u{119E}', '\u{119F}', '\u{11A0}', '\u{11A1}', '\u{11A2}', '\u{11A8}', '\u{11A9}', '\u{11AA}', '\u{11AB}', '\u{11AC}', '\u{11AD}', '\u{11AE}', '\u{11AF}', '\u{11B0}', '\u{11B1}', '\u{11B2}', '\u{11B3}', '\u{11B4}', '\u{11B5}', '\u{11B6}', '\u{11B7}', '\u{11B8}', '\u{11B9}', '\u{11BA}', '\u{11BB}', '\u{11BC}', '\u{11BD}', '\u{11BE}', '\u{11BF}', '\u{11C0}', '\u{11C1}', '\u{11C2}', '\u{11C3}', '\u{11C4}', '\u{11C5}', '\u{11C6}', '\u{11C7}', '\u{11C8}', '\u{11C9}', '\u{11CA}', '\u{11CB}', '\u{11CC}', '\u{11CD}', '\u{11CE}', '\u{11CF}', '\u{11D0}', '\u{11D1}', '\u{11D2}', '\u{11D3}', '\u{11D4}', '\u{11D5}', '\u{11D6}', '\u{11D7}', '\u{11D8}', '\u{11D9}', '\u{11DA}', '\u{11DB}', '\u{11DC}', '\u{11DD}', '\u{11DE}', '\u{11DF}', '\u{11E0}', '\u{11E1}', '\u{11E2}', '\u{11E3}', '\u{11E4}', '\u{11E5}', '\u{11E6}', '\u{11E7}', '\u{11E8}', '\u{11E9}', '\u{11EA}', '\u{11EB}', '\u{11EC}', '\u{11ED}', '\u{11EE}', '\u{11EF}', '\u{11F0}', '\u{11F1}', '\u{11F2}', '\u{11F3}', '\u{11F4}', '\u{11F5}', '\u{11F6}', '\u{11F7}', '\u{11F8}', '\u{11F9}', '\u{1200}', '\u{1201}', '\u{1202}', '\u{1203}', '\u{1204}', '\u{1205}', '\u{1206}', '\u{1207}', '\u{1208}', '\u{1209}', '\u{120A}', '\u{120B}', '\u{120C}', '\u{120D}', '\u{120E}', '\u{120F}', '\u{1210}', '\u{1211}', '\u{1212}', '\u{1213}', '\u{1214}', '\u{1215}', '\u{1216}', '\u{1217}', '\u{1218}', '\u{1219}', '\u{121A}', '\u{121B}', '\u{121C}', '\u{121D}', '\u{121E}', '\u{121F}', '\u{1220}', '\u{1221}', '\u{1222}', '\u{1223}', '\u{1224}', '\u{1225}', '\u{1226}', '\u{1227}', '\u{1228}', '\u{1229}', '\u{122A}', '\u{122B}', '\u{122C}', '\u{122D}', '\u{122E}', '\u{122F}', '\u{1230}', '\u{1231}', '\u{1232}', '\u{1233}', '\u{1234}', '\u{1235}', '\u{1236}', '\u{1237}', '\u{1238}', '\u{1239}', '\u{123A}', '\u{123B}', '\u{123C}', '\u{123D}', '\u{123E}', '\u{123F}', '\u{1240}', '\u{1241}', '\u{1242}', '\u{1243}', '\u{1244}', '\u{1245}', '\u{1246}', '\u{1247}', '\u{1248}', '\u{124A}', '\u{124B}', '\u{124C}', '\u{124D}', '\u{1250}', '\u{1251}', '\u{1252}', '\u{1253}', '\u{1254}', '\u{1255}', '\u{1256}', '\u{1258}', '\u{125A}', '\u{125B}', '\u{125C}', '\u{125D}', '\u{1260}', '\u{1261}', '\u{1262}', '\u{1263}', '\u{1264}', '\u{1265}', '\u{1266}', '\u{1267}', '\u{1268}', '\u{1269}', '\u{126A}', '\u{126B}', '\u{126C}', '\u{126D}', '\u{126E}', '\u{126F}', '\u{1270}', '\u{1271}', '\u{1272}', '\u{1273}', '\u{1274}', '\u{1275}', '\u{1276}', '\u{1277}', '\u{1278}', '\u{1279}', '\u{127A}', '\u{127B}', '\u{127C}', '\u{127D}', '\u{127E}', '\u{127F}', '\u{1280}', '\u{1281}', '\u{1282}', '\u{1283}', '\u{1284}', '\u{1285}', '\u{1286}', '\u{1287}', '\u{1288}', '\u{128A}', '\u{128B}', '\u{128C}', '\u{128D}', '\u{1290}', '\u{1291}', '\u{1292}', '\u{1293}', '\u{1294}', '\u{1295}', '\u{1296}', '\u{1297}', '\u{1298}', '\u{1299}', '\u{129A}', '\u{129B}', '\u{129C}', '\u{129D}', '\u{129E}', '\u{129F}', '\u{12A0}', '\u{12A1}', '\u{12A2}', '\u{12A3}', '\u{12A4}', '\u{12A5}', '\u{12A6}', '\u{12A7}', '\u{12A8}', '\u{12A9}', '\u{12AA}', '\u{12AB}', '\u{12AC}', '\u{12AD}', '\u{12AE}', '\u{12AF}', '\u{12B0}', '\u{12B2}', '\u{12B3}', '\u{12B4}', '\u{12B5}', '\u{12B8}', '\u{12B9}', '\u{12BA}', '\u{12BB}', '\u{12BC}', '\u{12BD}', '\u{12BE}', '\u{12C0}', '\u{12C2}', '\u{12C3}', '\u{12C4}', '\u{12C5}', '\u{12C8}', '\u{12C9}', '\u{12CA}', '\u{12CB}', '\u{12CC}', '\u{12CD}', '\u{12CE}', '\u{12CF}', '\u{12D0}', '\u{12D1}', '\u{12D2}', '\u{12D3}', '\u{12D4}', '\u{12D5}', '\u{12D6}', '\u{12D8}', '\u{12D9}', '\u{12DA}', '\u{12DB}', '\u{12DC}', '\u{12DD}', '\u{12DE}', '\u{12DF}', '\u{12E0}', '\u{12E1}', '\u{12E2}', '\u{12E3}', '\u{12E4}', '\u{12E5}', '\u{12E6}', '\u{12E7}', '\u{12E8}', '\u{12E9}', '\u{12EA}', '\u{12EB}', '\u{12EC}', '\u{12ED}', '\u{12EE}', '\u{12EF}', '\u{12F0}', '\u{12F1}', '\u{12F2}', '\u{12F3}', '\u{12F4}', '\u{12F5}', '\u{12F6}', '\u{12F7}', '\u{12F8}', '\u{12F9}', '\u{12FA}', '\u{12FB}', '\u{12FC}', '\u{12FD}', '\u{12FE}', '\u{12FF}', '\u{1300}', '\u{1301}', '\u{1302}', '\u{1303}', '\u{1304}', '\u{1305}', '\u{1306}', '\u{1307}', '\u{1308}', '\u{1309}', '\u{130A}', '\u{130B}', '\u{130C}', '\u{130D}', '\u{130E}', '\u{130F}', '\u{1310}', '\u{1312}', '\u{1313}', '\u{1314}', '\u{1315}', '\u{1318}', '\u{1319}', '\u{131A}', '\u{131B}', '\u{131C}', '\u{131D}', '\u{131E}', '\u{131F}', '\u{1320}', '\u{1321}', '\u{1322}', '\u{1323}', '\u{1324}', '\u{1325}', '\u{1326}', '\u{1327}', '\u{1328}', '\u{1329}', '\u{132A}', '\u{132B}', '\u{132C}', '\u{132D}', '\u{132E}', '\u{132F}', '\u{1330}', '\u{1331}', '\u{1332}', '\u{1333}', '\u{1334}', '\u{1335}', '\u{1336}', '\u{1337}', '\u{1338}', '\u{1339}', '\u{133A}', '\u{133B}', '\u{133C}', '\u{133D}', '\u{133E}', '\u{133F}', '\u{1340}', '\u{1341}', '\u{1342}', '\u{1343}', '\u{1344}', '\u{1345}', '\u{1346}', '\u{1347}', '\u{1348}', '\u{1349}', '\u{134A}', '\u{134B}', '\u{134C}', '\u{134D}', '\u{134E}', '\u{134F}', '\u{1350}', '\u{1351}', '\u{1352}', '\u{1353}', '\u{1354}', '\u{1355}', '\u{1356}', '\u{1357}', '\u{1358}', '\u{1359}', '\u{135A}', '\u{1380}', '\u{1381}', '\u{1382}', '\u{1383}', '\u{1384}', '\u{1385}', '\u{1386}', '\u{1387}', '\u{1388}', '\u{1389}', '\u{138A}', '\u{138B}', '\u{138C}', '\u{138D}', '\u{138E}', '\u{138F}', '\u{13A0}', '\u{13A1}', '\u{13A2}', '\u{13A3}', '\u{13A4}', '\u{13A5}', '\u{13A6}', '\u{13A7}', '\u{13A8}', '\u{13A9}', '\u{13AA}', '\u{13AB}', '\u{13AC}', '\u{13AD}', '\u{13AE}', '\u{13AF}', '\u{13B0}', '\u{13B1}', '\u{13B2}', '\u{13B3}', '\u{13B4}', '\u{13B5}', '\u{13B6}', '\u{13B7}', '\u{13B8}', '\u{13B9}', '\u{13BA}', '\u{13BB}', '\u{13BC}', '\u{13BD}', '\u{13BE}', '\u{13BF}', '\u{13C0}', '\u{13C1}', '\u{13C2}', '\u{13C3}', '\u{13C4}', '\u{13C5}', '\u{13C6}', '\u{13C7}', '\u{13C8}', '\u{13C9}', '\u{13CA}', '\u{13CB}', '\u{13CC}', '\u{13CD}', '\u{13CE}', '\u{13CF}', '\u{13D0}', '\u{13D1}', '\u{13D2}', '\u{13D3}', '\u{13D4}', '\u{13D5}', '\u{13D6}', '\u{13D7}', '\u{13D8}', '\u{13D9}', '\u{13DA}', '\u{13DB}', '\u{13DC}', '\u{13DD}', '\u{13DE}', '\u{13DF}', '\u{13E0}', '\u{13E1}', '\u{13E2}', '\u{13E3}', '\u{13E4}', '\u{13E5}', '\u{13E6}', '\u{13E7}', '\u{13E8}', '\u{13E9}', '\u{13EA}', '\u{13EB}', '\u{13EC}', '\u{13ED}', '\u{13EE}', '\u{13EF}', '\u{13F0}', '\u{13F1}', '\u{13F2}', '\u{13F3}', '\u{13F4}', '\u{1401}', '\u{1402}', '\u{1403}', '\u{1404}', '\u{1405}', '\u{1406}', '\u{1407}', '\u{1408}', '\u{1409}', '\u{140A}', '\u{140B}', '\u{140C}', '\u{140D}', '\u{140E}', '\u{140F}', '\u{1410}', '\u{1411}', '\u{1412}', '\u{1413}', '\u{1414}', '\u{1415}', '\u{1416}', '\u{1417}', '\u{1418}', '\u{1419}', '\u{141A}', '\u{141B}', '\u{141C}', '\u{141D}', '\u{141E}', '\u{141F}', '\u{1420}', '\u{1421}', '\u{1422}', '\u{1423}', '\u{1424}', '\u{1425}', '\u{1426}', '\u{1427}', '\u{1428}', '\u{1429}', '\u{142A}', '\u{142B}', '\u{142C}', '\u{142D}', '\u{142E}', '\u{142F}', '\u{1430}', '\u{1431}', '\u{1432}', '\u{1433}', '\u{1434}', '\u{1435}', '\u{1436}', '\u{1437}', '\u{1438}', '\u{1439}', '\u{143A}', '\u{143B}', '\u{143C}', '\u{143D}', '\u{143E}', '\u{143F}', '\u{1440}', '\u{1441}', '\u{1442}', '\u{1443}', '\u{1444}', '\u{1445}', '\u{1446}', '\u{1447}', '\u{1448}', '\u{1449}', '\u{144A}', '\u{144B}', '\u{144C}', '\u{144D}', '\u{144E}', '\u{144F}', '\u{1450}', '\u{1451}', '\u{1452}', '\u{1453}', '\u{1454}', '\u{1455}', '\u{1456}', '\u{1457}', '\u{1458}', '\u{1459}', '\u{145A}', '\u{145B}', '\u{145C}', '\u{145D}', '\u{145E}', '\u{145F}', '\u{1460}', '\u{1461}', '\u{1462}', '\u{1463}', '\u{1464}', '\u{1465}', '\u{1466}', '\u{1467}', '\u{1468}', '\u{1469}', '\u{146A}', '\u{146B}', '\u{146C}', '\u{146D}', '\u{146E}', '\u{146F}', '\u{1470}', '\u{1471}', '\u{1472}', '\u{1473}', '\u{1474}', '\u{1475}', '\u{1476}', '\u{1477}', '\u{1478}', '\u{1479}', '\u{147A}', '\u{147B}', '\u{147C}', '\u{147D}', '\u{147E}', '\u{147F}', '\u{1480}', '\u{1481}', '\u{1482}', '\u{1483}', '\u{1484}', '\u{1485}', '\u{1486}', '\u{1487}', '\u{1488}', '\u{1489}', '\u{148A}', '\u{148B}', '\u{148C}', '\u{148D}', '\u{148E}', '\u{148F}', '\u{1490}', '\u{1491}', '\u{1492}', '\u{1493}', '\u{1494}', '\u{1495}', '\u{1496}', '\u{1497}', '\u{1498}', '\u{1499}', '\u{149A}', '\u{149B}', '\u{149C}', '\u{149D}', '\u{149E}', '\u{149F}', '\u{14A0}', '\u{14A1}', '\u{14A2}', '\u{14A3}', '\u{14A4}', '\u{14A5}', '\u{14A6}', '\u{14A7}', '\u{14A8}', '\u{14A9}', '\u{14AA}', '\u{14AB}', '\u{14AC}', '\u{14AD}', '\u{14AE}', '\u{14AF}', '\u{14B0}', '\u{14B1}', '\u{14B2}', '\u{14B3}', '\u{14B4}', '\u{14B5}', '\u{14B6}', '\u{14B7}', '\u{14B8}', '\u{14B9}', '\u{14BA}', '\u{14BB}', '\u{14BC}', '\u{14BD}', '\u{14BE}', '\u{14BF}', '\u{14C0}', '\u{14C1}', '\u{14C2}', '\u{14C3}', '\u{14C4}', '\u{14C5}', '\u{14C6}', '\u{14C7}', '\u{14C8}', '\u{14C9}', '\u{14CA}', '\u{14CB}', '\u{14CC}', '\u{14CD}', '\u{14CE}', '\u{14CF}', '\u{14D0}', '\u{14D1}', '\u{14D2}', '\u{14D3}', '\u{14D4}', '\u{14D5}', '\u{14D6}', '\u{14D7}', '\u{14D8}', '\u{14D9}', '\u{14DA}', '\u{14DB}', '\u{14DC}', '\u{14DD}', '\u{14DE}', '\u{14DF}', '\u{14E0}', '\u{14E1}', '\u{14E2}', '\u{14E3}', '\u{14E4}', '\u{14E5}', '\u{14E6}', '\u{14E7}', '\u{14E8}', '\u{14E9}', '\u{14EA}', '\u{14EB}', '\u{14EC}', '\u{14ED}', '\u{14EE}', '\u{14EF}', '\u{14F0}', '\u{14F1}', '\u{14F2}', '\u{14F3}', '\u{14F4}', '\u{14F5}', '\u{14F6}', '\u{14F7}', '\u{14F8}', '\u{14F9}', '\u{14FA}', '\u{14FB}', '\u{14FC}', '\u{14FD}', '\u{14FE}', '\u{14FF}', '\u{1500}', '\u{1501}', '\u{1502}', '\u{1503}', '\u{1504}', '\u{1505}', '\u{1506}', '\u{1507}', '\u{1508}', '\u{1509}', '\u{150A}', '\u{150B}', '\u{150C}', '\u{150D}', '\u{150E}', '\u{150F}', '\u{1510}', '\u{1511}', '\u{1512}', '\u{1513}', '\u{1514}', '\u{1515}', '\u{1516}', '\u{1517}', '\u{1518}', '\u{1519}', '\u{151A}', '\u{151B}', '\u{151C}', '\u{151D}', '\u{151E}', '\u{151F}', '\u{1520}', '\u{1521}', '\u{1522}', '\u{1523}', '\u{1524}', '\u{1525}', '\u{1526}', '\u{1527}', '\u{1528}', '\u{1529}', '\u{152A}', '\u{152B}', '\u{152C}', '\u{152D}', '\u{152E}', '\u{152F}', '\u{1530}', '\u{1531}', '\u{1532}', '\u{1533}', '\u{1534}', '\u{1535}', '\u{1536}', '\u{1537}', '\u{1538}', '\u{1539}', '\u{153A}', '\u{153B}', '\u{153C}', '\u{153D}', '\u{153E}', '\u{153F}', '\u{1540}', '\u{1541}', '\u{1542}', '\u{1543}', '\u{1544}', '\u{1545}', '\u{1546}', '\u{1547}', '\u{1548}', '\u{1549}', '\u{154A}', '\u{154B}', '\u{154C}', '\u{154D}', '\u{154E}', '\u{154F}', '\u{1550}', '\u{1551}', '\u{1552}', '\u{1553}', '\u{1554}', '\u{1555}', '\u{1556}', '\u{1557}', '\u{1558}', '\u{1559}', '\u{155A}', '\u{155B}', '\u{155C}', '\u{155D}', '\u{155E}', '\u{155F}', '\u{1560}', '\u{1561}', '\u{1562}', '\u{1563}', '\u{1564}', '\u{1565}', '\u{1566}', '\u{1567}', '\u{1568}', '\u{1569}', '\u{156A}', '\u{156B}', '\u{156C}', '\u{156D}', '\u{156E}', '\u{156F}', '\u{1570}', '\u{1571}', '\u{1572}', '\u{1573}', '\u{1574}', '\u{1575}', '\u{1576}', '\u{1577}', '\u{1578}', '\u{1579}', '\u{157A}', '\u{157B}', '\u{157C}', '\u{157D}', '\u{157E}', '\u{157F}', '\u{1580}', '\u{1581}', '\u{1582}', '\u{1583}', '\u{1584}', '\u{1585}', '\u{1586}', '\u{1587}', '\u{1588}', '\u{1589}', '\u{158A}', '\u{158B}', '\u{158C}', '\u{158D}', '\u{158E}', '\u{158F}', '\u{1590}', '\u{1591}', '\u{1592}', '\u{1593}', '\u{1594}', '\u{1595}', '\u{1596}', '\u{1597}', '\u{1598}', '\u{1599}', '\u{159A}', '\u{159B}', '\u{159C}', '\u{159D}', '\u{159E}', '\u{159F}', '\u{15A0}', '\u{15A1}', '\u{15A2}', '\u{15A3}', '\u{15A4}', '\u{15A5}', '\u{15A6}', '\u{15A7}', '\u{15A8}', '\u{15A9}', '\u{15AA}', '\u{15AB}', '\u{15AC}', '\u{15AD}', '\u{15AE}', '\u{15AF}', '\u{15B0}', '\u{15B1}', '\u{15B2}', '\u{15B3}', '\u{15B4}', '\u{15B5}', '\u{15B6}', '\u{15B7}', '\u{15B8}', '\u{15B9}', '\u{15BA}', '\u{15BB}', '\u{15BC}', '\u{15BD}', '\u{15BE}', '\u{15BF}', '\u{15C0}', '\u{15C1}', '\u{15C2}', '\u{15C3}', '\u{15C4}', '\u{15C5}', '\u{15C6}', '\u{15C7}', '\u{15C8}', '\u{15C9}', '\u{15CA}', '\u{15CB}', '\u{15CC}', '\u{15CD}', '\u{15CE}', '\u{15CF}', '\u{15D0}', '\u{15D1}', '\u{15D2}', '\u{15D3}', '\u{15D4}', '\u{15D5}', '\u{15D6}', '\u{15D7}', '\u{15D8}', '\u{15D9}', '\u{15DA}', '\u{15DB}', '\u{15DC}', '\u{15DD}', '\u{15DE}', '\u{15DF}', '\u{15E0}', '\u{15E1}', '\u{15E2}', '\u{15E3}', '\u{15E4}', '\u{15E5}', '\u{15E6}', '\u{15E7}', '\u{15E8}', '\u{15E9}', '\u{15EA}', '\u{15EB}', '\u{15EC}', '\u{15ED}', '\u{15EE}', '\u{15EF}', '\u{15F0}', '\u{15F1}', '\u{15F2}', '\u{15F3}', '\u{15F4}', '\u{15F5}', '\u{15F6}', '\u{15F7}', '\u{15F8}', '\u{15F9}', '\u{15FA}', '\u{15FB}', '\u{15FC}', '\u{15FD}', '\u{15FE}', '\u{15FF}', '\u{1600}', '\u{1601}', '\u{1602}', '\u{1603}', '\u{1604}', '\u{1605}', '\u{1606}', '\u{1607}', '\u{1608}', '\u{1609}', '\u{160A}', '\u{160B}', '\u{160C}', '\u{160D}', '\u{160E}', '\u{160F}', '\u{1610}', '\u{1611}', '\u{1612}', '\u{1613}', '\u{1614}', '\u{1615}', '\u{1616}', '\u{1617}', '\u{1618}', '\u{1619}', '\u{161A}', '\u{161B}', '\u{161C}', '\u{161D}', '\u{161E}', '\u{161F}', '\u{1620}', '\u{1621}', '\u{1622}', '\u{1623}', '\u{1624}', '\u{1625}', '\u{1626}', '\u{1627}', '\u{1628}', '\u{1629}', '\u{162A}', '\u{162B}', '\u{162C}', '\u{162D}', '\u{162E}', '\u{162F}', '\u{1630}', '\u{1631}', '\u{1632}', '\u{1633}', '\u{1634}', '\u{1635}', '\u{1636}', '\u{1637}', '\u{1638}', '\u{1639}', '\u{163A}', '\u{163B}', '\u{163C}', '\u{163D}', '\u{163E}', '\u{163F}', '\u{1640}', '\u{1641}', '\u{1642}', '\u{1643}', '\u{1644}', '\u{1645}', '\u{1646}', '\u{1647}', '\u{1648}', '\u{1649}', '\u{164A}', '\u{164B}', '\u{164C}', '\u{164D}', '\u{164E}', '\u{164F}', '\u{1650}', '\u{1651}', '\u{1652}', '\u{1653}', '\u{1654}', '\u{1655}', '\u{1656}', '\u{1657}', '\u{1658}', '\u{1659}', '\u{165A}', '\u{165B}', '\u{165C}', '\u{165D}', '\u{165E}', '\u{165F}', '\u{1660}', '\u{1661}', '\u{1662}', '\u{1663}', '\u{1664}', '\u{1665}', '\u{1666}', '\u{1667}', '\u{1668}', '\u{1669}', '\u{166A}', '\u{166B}', '\u{166C}', '\u{166F}', '\u{1670}', '\u{1671}', '\u{1672}', '\u{1673}', '\u{1674}', '\u{1675}', '\u{1676}', '\u{1681}', '\u{1682}', '\u{1683}', '\u{1684}', '\u{1685}', '\u{1686}', '\u{1687}', '\u{1688}', '\u{1689}', '\u{168A}', '\u{168B}', '\u{168C}', '\u{168D}', '\u{168E}', '\u{168F}', '\u{1690}', '\u{1691}', '\u{1692}', '\u{1693}', '\u{1694}', '\u{1695}', '\u{1696}', '\u{1697}', '\u{1698}', '\u{1699}', '\u{169A}', '\u{16A0}', '\u{16A1}', '\u{16A2}', '\u{16A3}', '\u{16A4}', '\u{16A5}', '\u{16A6}', '\u{16A7}', '\u{16A8}', '\u{16A9}', '\u{16AA}', '\u{16AB}', '\u{16AC}', '\u{16AD}', '\u{16AE}', '\u{16AF}', '\u{16B0}', '\u{16B1}', '\u{16B2}', '\u{16B3}', '\u{16B4}', '\u{16B5}', '\u{16B6}', '\u{16B7}', '\u{16B8}', '\u{16B9}', '\u{16BA}', '\u{16BB}', '\u{16BC}', '\u{16BD}', '\u{16BE}', '\u{16BF}', '\u{16C0}', '\u{16C1}', '\u{16C2}', '\u{16C3}', '\u{16C4}', '\u{16C5}', '\u{16C6}', '\u{16C7}', '\u{16C8}', '\u{16C9}', '\u{16CA}', '\u{16CB}', '\u{16CC}', '\u{16CD}', '\u{16CE}', '\u{16CF}', '\u{16D0}', '\u{16D1}', '\u{16D2}', '\u{16D3}', '\u{16D4}', '\u{16D5}', '\u{16D6}', '\u{16D7}', '\u{16D8}', '\u{16D9}', '\u{16DA}', '\u{16DB}', '\u{16DC}', '\u{16DD}', '\u{16DE}', '\u{16DF}', '\u{16E0}', '\u{16E1}', '\u{16E2}', '\u{16E3}', '\u{16E4}', '\u{16E5}', '\u{16E6}', '\u{16E7}', '\u{16E8}', '\u{16E9}', '\u{16EA}', '\u{1700}', '\u{1701}', '\u{1702}', '\u{1703}', '\u{1704}', '\u{1705}', '\u{1706}', '\u{1707}', '\u{1708}', '\u{1709}', '\u{170A}', '\u{170B}', '\u{170C}', '\u{170E}', '\u{170F}', '\u{1710}', '\u{1711}', '\u{1720}', '\u{1721}', '\u{1722}', '\u{1723}', '\u{1724}', '\u{1725}', '\u{1726}', '\u{1727}', '\u{1728}', '\u{1729}', '\u{172A}', '\u{172B}', '\u{172C}', '\u{172D}', '\u{172E}', '\u{172F}', '\u{1730}', '\u{1731}', '\u{1740}', '\u{1741}', '\u{1742}', '\u{1743}', '\u{1744}', '\u{1745}', '\u{1746}', '\u{1747}', '\u{1748}', '\u{1749}', '\u{174A}', '\u{174B}', '\u{174C}', '\u{174D}', '\u{174E}', '\u{174F}', '\u{1750}', '\u{1751}', '\u{1760}', '\u{1761}', '\u{1762}', '\u{1763}', '\u{1764}', '\u{1765}', '\u{1766}', '\u{1767}', '\u{1768}', '\u{1769}', '\u{176A}', '\u{176B}', '\u{176C}', '\u{176E}', '\u{176F}', '\u{1770}', '\u{1780}', '\u{1781}', '\u{1782}', '\u{1783}', '\u{1784}', '\u{1785}', '\u{1786}', '\u{1787}', '\u{1788}', '\u{1789}', '\u{178A}', '\u{178B}', '\u{178C}', '\u{178D}', '\u{178E}', '\u{178F}', '\u{1790}', '\u{1791}', '\u{1792}', '\u{1793}', '\u{1794}', '\u{1795}', '\u{1796}', '\u{1797}', '\u{1798}', '\u{1799}', '\u{179A}', '\u{179B}', '\u{179C}', '\u{179D}', '\u{179E}', '\u{179F}', '\u{17A0}', '\u{17A1}', '\u{17A2}', '\u{17A3}', '\u{17A4}', '\u{17A5}', '\u{17A6}', '\u{17A7}', '\u{17A8}', '\u{17A9}', '\u{17AA}', '\u{17AB}', '\u{17AC}', '\u{17AD}', '\u{17AE}', '\u{17AF}', '\u{17B0}', '\u{17B1}', '\u{17B2}', '\u{17B3}', '\u{17DC}', '\u{1820}', '\u{1821}', '\u{1822}', '\u{1823}', '\u{1824}', '\u{1825}', '\u{1826}', '\u{1827}', '\u{1828}', '\u{1829}', '\u{182A}', '\u{182B}', '\u{182C}', '\u{182D}', '\u{182E}', '\u{182F}', '\u{1830}', '\u{1831}', '\u{1832}', '\u{1833}', '\u{1834}', '\u{1835}', '\u{1836}', '\u{1837}', '\u{1838}', '\u{1839}', '\u{183A}', '\u{183B}', '\u{183C}', '\u{183D}', '\u{183E}', '\u{183F}', '\u{1840}', '\u{1841}', '\u{1842}', '\u{1844}', '\u{1845}', '\u{1846}', '\u{1847}', '\u{1848}', '\u{1849}', '\u{184A}', '\u{184B}', '\u{184C}', '\u{184D}', '\u{184E}', '\u{184F}', '\u{1850}', '\u{1851}', '\u{1852}', '\u{1853}', '\u{1854}', '\u{1855}', '\u{1856}', '\u{1857}', '\u{1858}', '\u{1859}', '\u{185A}', '\u{185B}', '\u{185C}', '\u{185D}', '\u{185E}', '\u{185F}', '\u{1860}', '\u{1861}', '\u{1862}', '\u{1863}', '\u{1864}', '\u{1865}', '\u{1866}', '\u{1867}', '\u{1868}', '\u{1869}', '\u{186A}', '\u{186B}', '\u{186C}', '\u{186D}', '\u{186E}', '\u{186F}', '\u{1870}', '\u{1871}', '\u{1872}', '\u{1873}', '\u{1874}', '\u{1875}', '\u{1876}', '\u{1877}', '\u{1880}', '\u{1881}', '\u{1882}', '\u{1883}', '\u{1884}', '\u{1885}', '\u{1886}', '\u{1887}', '\u{1888}', '\u{1889}', '\u{188A}', '\u{188B}', '\u{188C}', '\u{188D}', '\u{188E}', '\u{188F}', '\u{1890}', '\u{1891}', '\u{1892}', '\u{1893}', '\u{1894}', '\u{1895}', '\u{1896}', '\u{1897}', '\u{1898}', '\u{1899}', '\u{189A}', '\u{189B}', '\u{189C}', '\u{189D}', '\u{189E}', '\u{189F}', '\u{18A0}', '\u{18A1}', '\u{18A2}', '\u{18A3}', '\u{18A4}', '\u{18A5}', '\u{18A6}', '\u{18A7}', '\u{18A8}', '\u{18AA}', '\u{1900}', '\u{1901}', '\u{1902}', '\u{1903}', '\u{1904}', '\u{1905}', '\u{1906}', '\u{1907}', '\u{1908}', '\u{1909}', '\u{190A}', '\u{190B}', '\u{190C}', '\u{190D}', '\u{190E}', '\u{190F}', '\u{1910}', '\u{1911}', '\u{1912}', '\u{1913}', '\u{1914}', '\u{1915}', '\u{1916}', '\u{1917}', '\u{1918}', '\u{1919}', '\u{191A}', '\u{191B}', '\u{191C}', '\u{1950}', '\u{1951}', '\u{1952}', '\u{1953}', '\u{1954}', '\u{1955}', '\u{1956}', '\u{1957}', '\u{1958}', '\u{1959}', '\u{195A}', '\u{195B}', '\u{195C}', '\u{195D}', '\u{195E}', '\u{195F}', '\u{1960}', '\u{1961}', '\u{1962}', '\u{1963}', '\u{1964}', '\u{1965}', '\u{1966}', '\u{1967}', '\u{1968}', '\u{1969}', '\u{196A}', '\u{196B}', '\u{196C}', '\u{196D}', '\u{1970}', '\u{1971}', '\u{1972}', '\u{1973}', '\u{1974}', '\u{1980}', '\u{1981}', '\u{1982}', '\u{1983}', '\u{1984}', '\u{1985}', '\u{1986}', '\u{1987}', '\u{1988}', '\u{1989}', '\u{198A}', '\u{198B}', '\u{198C}', '\u{198D}', '\u{198E}', '\u{198F}', '\u{1990}', '\u{1991}', '\u{1992}', '\u{1993}', '\u{1994}', '\u{1995}', '\u{1996}', '\u{1997}', '\u{1998}', '\u{1999}', '\u{199A}', '\u{199B}', '\u{199C}', '\u{199D}', '\u{199E}', '\u{199F}', '\u{19A0}', '\u{19A1}', '\u{19A2}', '\u{19A3}', '\u{19A4}', '\u{19A5}', '\u{19A6}', '\u{19A7}', '\u{19A8}', '\u{19A9}', '\u{19C1}', '\u{19C2}', '\u{19C3}', '\u{19C4}', '\u{19C5}', '\u{19C6}', '\u{19C7}', '\u{1A00}', '\u{1A01}', '\u{1A02}', '\u{1A03}', '\u{1A04}', '\u{1A05}', '\u{1A06}', '\u{1A07}', '\u{1A08}', '\u{1A09}', '\u{1A0A}', '\u{1A0B}', '\u{1A0C}', '\u{1A0D}', '\u{1A0E}', '\u{1A0F}', '\u{1A10}', '\u{1A11}', '\u{1A12}', '\u{1A13}', '\u{1A14}', '\u{1A15}', '\u{1A16}', '\u{1B05}', '\u{1B06}', '\u{1B07}', '\u{1B08}', '\u{1B09}', '\u{1B0A}', '\u{1B0B}', '\u{1B0C}', '\u{1B0D}', '\u{1B0E}', '\u{1B0F}', '\u{1B10}', '\u{1B11}', '\u{1B12}', '\u{1B13}', '\u{1B14}', '\u{1B15}', '\u{1B16}', '\u{1B17}', '\u{1B18}', '\u{1B19}', '\u{1B1A}', '\u{1B1B}', '\u{1B1C}', '\u{1B1D}', '\u{1B1E}', '\u{1B1F}', '\u{1B20}', '\u{1B21}', '\u{1B22}', '\u{1B23}', '\u{1B24}', '\u{1B25}', '\u{1B26}', '\u{1B27}', '\u{1B28}', '\u{1B29}', '\u{1B2A}', '\u{1B2B}', '\u{1B2C}', '\u{1B2D}', '\u{1B2E}', '\u{1B2F}', '\u{1B30}', '\u{1B31}', '\u{1B32}', '\u{1B33}', '\u{1B45}', '\u{1B46}', '\u{1B47}', '\u{1B48}', '\u{1B49}', '\u{1B4A}', '\u{1B4B}', '\u{1B83}', '\u{1B84}', '\u{1B85}', '\u{1B86}', '\u{1B87}', '\u{1B88}', '\u{1B89}', '\u{1B8A}', '\u{1B8B}', '\u{1B8C}', '\u{1B8D}', '\u{1B8E}', '\u{1B8F}', '\u{1B90}', '\u{1B91}', '\u{1B92}', '\u{1B93}', '\u{1B94}', '\u{1B95}', '\u{1B96}', '\u{1B97}', '\u{1B98}', '\u{1B99}', '\u{1B9A}', '\u{1B9B}', '\u{1B9C}', '\u{1B9D}', '\u{1B9E}', '\u{1B9F}', '\u{1BA0}', '\u{1BAE}', '\u{1BAF}', '\u{1C00}', '\u{1C01}', '\u{1C02}', '\u{1C03}', '\u{1C04}', '\u{1C05}', '\u{1C06}', '\u{1C07}', '\u{1C08}', '\u{1C09}', '\u{1C0A}', '\u{1C0B}', '\u{1C0C}', '\u{1C0D}', '\u{1C0E}', '\u{1C0F}', '\u{1C10}', '\u{1C11}', '\u{1C12}', '\u{1C13}', '\u{1C14}', '\u{1C15}', '\u{1C16}', '\u{1C17}', '\u{1C18}', '\u{1C19}', '\u{1C1A}', '\u{1C1B}', '\u{1C1C}', '\u{1C1D}', '\u{1C1E}', '\u{1C1F}', '\u{1C20}', '\u{1C21}', '\u{1C22}', '\u{1C23}', '\u{1C4D}', '\u{1C4E}', '\u{1C4F}', '\u{1C5A}', '\u{1C5B}', '\u{1C5C}', '\u{1C5D}', '\u{1C5E}', '\u{1C5F}', '\u{1C60}', '\u{1C61}', '\u{1C62}', '\u{1C63}', '\u{1C64}', '\u{1C65}', '\u{1C66}', '\u{1C67}', '\u{1C68}', '\u{1C69}', '\u{1C6A}', '\u{1C6B}', '\u{1C6C}', '\u{1C6D}', '\u{1C6E}', '\u{1C6F}', '\u{1C70}', '\u{1C71}', '\u{1C72}', '\u{1C73}', '\u{1C74}', '\u{1C75}', '\u{1C76}', '\u{1C77}', '\u{2135}', '\u{2136}', '\u{2137}', '\u{2138}', '\u{2D30}', '\u{2D31}', '\u{2D32}', '\u{2D33}', '\u{2D34}', '\u{2D35}', '\u{2D36}', '\u{2D37}', '\u{2D38}', '\u{2D39}', '\u{2D3A}', '\u{2D3B}', '\u{2D3C}', '\u{2D3D}', '\u{2D3E}', '\u{2D3F}', '\u{2D40}', '\u{2D41}', '\u{2D42}', '\u{2D43}', '\u{2D44}', '\u{2D45}', '\u{2D46}', '\u{2D47}', '\u{2D48}', '\u{2D49}', '\u{2D4A}', '\u{2D4B}', '\u{2D4C}', '\u{2D4D}', '\u{2D4E}', '\u{2D4F}', '\u{2D50}', '\u{2D51}', '\u{2D52}', '\u{2D53}', '\u{2D54}', '\u{2D55}', '\u{2D56}', '\u{2D57}', '\u{2D58}', '\u{2D59}', '\u{2D5A}', '\u{2D5B}', '\u{2D5C}', '\u{2D5D}', '\u{2D5E}', '\u{2D5F}', '\u{2D60}', '\u{2D61}', '\u{2D62}', '\u{2D63}', '\u{2D64}', '\u{2D65}', '\u{2D80}', '\u{2D81}', '\u{2D82}', '\u{2D83}', '\u{2D84}', '\u{2D85}', '\u{2D86}', '\u{2D87}', '\u{2D88}', '\u{2D89}', '\u{2D8A}', '\u{2D8B}', '\u{2D8C}', '\u{2D8D}', '\u{2D8E}', '\u{2D8F}', '\u{2D90}', '\u{2D91}', '\u{2D92}', '\u{2D93}', '\u{2D94}', '\u{2D95}', '\u{2D96}', '\u{2DA0}', '\u{2DA1}', '\u{2DA2}', '\u{2DA3}', '\u{2DA4}', '\u{2DA5}', '\u{2DA6}', '\u{2DA8}', '\u{2DA9}', '\u{2DAA}', '\u{2DAB}', '\u{2DAC}', '\u{2DAD}', '\u{2DAE}', '\u{2DB0}', '\u{2DB1}', '\u{2DB2}', '\u{2DB3}', '\u{2DB4}', '\u{2DB5}', '\u{2DB6}', '\u{2DB8}', '\u{2DB9}', '\u{2DBA}', '\u{2DBB}', '\u{2DBC}', '\u{2DBD}', '\u{2DBE}', '\u{2DC0}', '\u{2DC1}', '\u{2DC2}', '\u{2DC3}', '\u{2DC4}', '\u{2DC5}', '\u{2DC6}', '\u{2DC8}', '\u{2DC9}', '\u{2DCA}', '\u{2DCB}', '\u{2DCC}', '\u{2DCD}', '\u{2DCE}', '\u{2DD0}', '\u{2DD1}', '\u{2DD2}', '\u{2DD3}', '\u{2DD4}', '\u{2DD5}', '\u{2DD6}', '\u{2DD8}', '\u{2DD9}', '\u{2DDA}', '\u{2DDB}', '\u{2DDC}', '\u{2DDD}', '\u{2DDE}', '\u{3006}', '\u{303C}', '\u{3041}', '\u{3042}', '\u{3043}', '\u{3044}', '\u{3045}', '\u{3046}', '\u{3047}', '\u{3048}', '\u{3049}', '\u{304A}', '\u{304B}', '\u{304C}', '\u{304D}', '\u{304E}', '\u{304F}', '\u{3050}', '\u{3051}', '\u{3052}', '\u{3053}', '\u{3054}', '\u{3055}', '\u{3056}', '\u{3057}', '\u{3058}', '\u{3059}', '\u{305A}', '\u{305B}', '\u{305C}', '\u{305D}', '\u{305E}', '\u{305F}', '\u{3060}', '\u{3061}', '\u{3062}', '\u{3063}', '\u{3064}', '\u{3065}', '\u{3066}', '\u{3067}', '\u{3068}', '\u{3069}', '\u{306A}', '\u{306B}', '\u{306C}', '\u{306D}', '\u{306E}', '\u{306F}', '\u{3070}', '\u{3071}', '\u{3072}', '\u{3073}', '\u{3074}', '\u{3075}', '\u{3076}', '\u{3077}', '\u{3078}', '\u{3079}', '\u{307A}', '\u{307B}', '\u{307C}', '\u{307D}', '\u{307E}', '\u{307F}', '\u{3080}', '\u{3081}', '\u{3082}', '\u{3083}', '\u{3084}', '\u{3085}', '\u{3086}', '\u{3087}', '\u{3088}', '\u{3089}', '\u{308A}', '\u{308B}', '\u{308C}', '\u{308D}', '\u{308E}', '\u{308F}', '\u{3090}', '\u{3091}', '\u{3092}', '\u{3093}', '\u{3094}', '\u{3095}', '\u{3096}', '\u{309F}', '\u{30A1}', '\u{30A2}', '\u{30A3}', '\u{30A4}', '\u{30A5}', '\u{30A6}', '\u{30A7}', '\u{30A8}', '\u{30A9}', '\u{30AA}', '\u{30AB}', '\u{30AC}', '\u{30AD}', '\u{30AE}', '\u{30AF}', '\u{30B0}', '\u{30B1}', '\u{30B2}', '\u{30B3}', '\u{30B4}', '\u{30B5}', '\u{30B6}', '\u{30B7}', '\u{30B8}', '\u{30B9}', '\u{30BA}', '\u{30BB}', '\u{30BC}', '\u{30BD}', '\u{30BE}', '\u{30BF}', '\u{30C0}', '\u{30C1}', '\u{30C2}', '\u{30C3}', '\u{30C4}', '\u{30C5}', '\u{30C6}', '\u{30C7}', '\u{30C8}', '\u{30C9}', '\u{30CA}', '\u{30CB}', '\u{30CC}', '\u{30CD}', '\u{30CE}', '\u{30CF}', '\u{30D0}', '\u{30D1}', '\u{30D2}', '\u{30D3}', '\u{30D4}', '\u{30D5}', '\u{30D6}', '\u{30D7}', '\u{30D8}', '\u{30D9}', '\u{30DA}', '\u{30DB}', '\u{30DC}', '\u{30DD}', '\u{30DE}', '\u{30DF}', '\u{30E0}', '\u{30E1}', '\u{30E2}', '\u{30E3}', '\u{30E4}', '\u{30E5}', '\u{30E6}', '\u{30E7}', '\u{30E8}', '\u{30E9}', '\u{30EA}', '\u{30EB}', '\u{30EC}', '\u{30ED}', '\u{30EE}', '\u{30EF}', '\u{30F0}', '\u{30F1}', '\u{30F2}', '\u{30F3}', '\u{30F4}', '\u{30F5}', '\u{30F6}', '\u{30F7}', '\u{30F8}', '\u{30F9}', '\u{30FA}', '\u{30FF}', '\u{3105}', '\u{3106}', '\u{3107}', '\u{3108}', '\u{3109}', '\u{310A}', '\u{310B}', '\u{310C}', '\u{310D}', '\u{310E}', '\u{310F}', '\u{3110}', '\u{3111}', '\u{3112}', '\u{3113}', '\u{3114}', '\u{3115}', '\u{3116}', '\u{3117}', '\u{3118}', '\u{3119}', '\u{311A}', '\u{311B}', '\u{311C}', '\u{311D}', '\u{311E}', '\u{311F}', '\u{3120}', '\u{3121}', '\u{3122}', '\u{3123}', '\u{3124}', '\u{3125}', '\u{3126}', '\u{3127}', '\u{3128}', '\u{3129}', '\u{312A}', '\u{312B}', '\u{312C}', '\u{312D}', '\u{3131}', '\u{3132}', '\u{3133}', '\u{3134}', '\u{3135}', '\u{3136}', '\u{3137}', '\u{3138}', '\u{3139}', '\u{313A}', '\u{313B}', '\u{313C}', '\u{313D}', '\u{313E}', '\u{313F}', '\u{3140}', '\u{3141}', '\u{3142}', '\u{3143}', '\u{3144}', '\u{3145}', '\u{3146}', '\u{3147}', '\u{3148}', '\u{3149}', '\u{314A}', '\u{314B}', '\u{314C}', '\u{314D}', '\u{314E}', '\u{314F}', '\u{3150}', '\u{3151}', '\u{3152}', '\u{3153}', '\u{3154}', '\u{3155}', '\u{3156}', '\u{3157}', '\u{3158}', '\u{3159}', '\u{315A}', '\u{315B}', '\u{315C}', '\u{315D}', '\u{315E}', '\u{315F}', '\u{3160}', '\u{3161}', '\u{3162}', '\u{3163}', '\u{3164}', '\u{3165}', '\u{3166}', '\u{3167}', '\u{3168}', '\u{3169}', '\u{316A}', '\u{316B}', '\u{316C}', '\u{316D}', '\u{316E}', '\u{316F}', '\u{3170}', '\u{3171}', '\u{3172}', '\u{3173}', '\u{3174}', '\u{3175}', '\u{3176}', '\u{3177}', '\u{3178}', '\u{3179}', '\u{317A}', '\u{317B}', '\u{317C}', '\u{317D}', '\u{317E}', '\u{317F}', '\u{3180}', '\u{3181}', '\u{3182}', '\u{3183}', '\u{3184}', '\u{3185}', '\u{3186}', '\u{3187}', '\u{3188}', '\u{3189}', '\u{318A}', '\u{318B}', '\u{318C}', '\u{318D}', '\u{318E}', '\u{31A0}', '\u{31A1}', '\u{31A2}', '\u{31A3}', '\u{31A4}', '\u{31A5}', '\u{31A6}', '\u{31A7}', '\u{31A8}', '\u{31A9}', '\u{31AA}', '\u{31AB}', '\u{31AC}', '\u{31AD}', '\u{31AE}', '\u{31AF}', '\u{31B0}', '\u{31B1}', '\u{31B2}', '\u{31B3}', '\u{31B4}', '\u{31B5}', '\u{31B6}', '\u{31B7}', '\u{31F0}', '\u{31F1}', '\u{31F2}', '\u{31F3}', '\u{31F4}', '\u{31F5}', '\u{31F6}', '\u{31F7}', '\u{31F8}', '\u{31F9}', '\u{31FA}', '\u{31FB}', '\u{31FC}', '\u{31FD}', '\u{31FE}', '\u{31FF}', '\u{3400}', '\u{4DB5}', '\u{4E00}', '\u{9FC3}', '\u{A000}', '\u{A001}', '\u{A002}', '\u{A003}', '\u{A004}', '\u{A005}', '\u{A006}', '\u{A007}', '\u{A008}', '\u{A009}', '\u{A00A}', '\u{A00B}', '\u{A00C}', '\u{A00D}', '\u{A00E}', '\u{A00F}', '\u{A010}', '\u{A011}', '\u{A012}', '\u{A013}', '\u{A014}', '\u{A016}', '\u{A017}', '\u{A018}', '\u{A019}', '\u{A01A}', '\u{A01B}', '\u{A01C}', '\u{A01D}', '\u{A01E}', '\u{A01F}', '\u{A020}', '\u{A021}', '\u{A022}', '\u{A023}', '\u{A024}', '\u{A025}', '\u{A026}', '\u{A027}', '\u{A028}', '\u{A029}', '\u{A02A}', '\u{A02B}', '\u{A02C}', '\u{A02D}', '\u{A02E}', '\u{A02F}', '\u{A030}', '\u{A031}', '\u{A032}', '\u{A033}', '\u{A034}', '\u{A035}', '\u{A036}', '\u{A037}', '\u{A038}', '\u{A039}', '\u{A03A}', '\u{A03B}', '\u{A03C}', '\u{A03D}', '\u{A03E}', '\u{A03F}', '\u{A040}', '\u{A041}', '\u{A042}', '\u{A043}', '\u{A044}', '\u{A045}', '\u{A046}', '\u{A047}', '\u{A048}', '\u{A049}', '\u{A04A}', '\u{A04B}', '\u{A04C}', '\u{A04D}', '\u{A04E}', '\u{A04F}', '\u{A050}', '\u{A051}', '\u{A052}', '\u{A053}', '\u{A054}', '\u{A055}', '\u{A056}', '\u{A057}', '\u{A058}', '\u{A059}', '\u{A05A}', '\u{A05B}', '\u{A05C}', '\u{A05D}', '\u{A05E}', '\u{A05F}', '\u{A060}', '\u{A061}', '\u{A062}', '\u{A063}', '\u{A064}', '\u{A065}', '\u{A066}', '\u{A067}', '\u{A068}', '\u{A069}', '\u{A06A}', '\u{A06B}', '\u{A06C}', '\u{A06D}', '\u{A06E}', '\u{A06F}', '\u{A070}', '\u{A071}', '\u{A072}', '\u{A073}', '\u{A074}', '\u{A075}', '\u{A076}', '\u{A077}', '\u{A078}', '\u{A079}', '\u{A07A}', '\u{A07B}', '\u{A07C}', '\u{A07D}', '\u{A07E}', '\u{A07F}', '\u{A080}', '\u{A081}', '\u{A082}', '\u{A083}', '\u{A084}', '\u{A085}', '\u{A086}', '\u{A087}', '\u{A088}', '\u{A089}', '\u{A08A}', '\u{A08B}', '\u{A08C}', '\u{A08D}', '\u{A08E}', '\u{A08F}', '\u{A090}', '\u{A091}', '\u{A092}', '\u{A093}', '\u{A094}', '\u{A095}', '\u{A096}', '\u{A097}', '\u{A098}', '\u{A099}', '\u{A09A}', '\u{A09B}', '\u{A09C}', '\u{A09D}', '\u{A09E}', '\u{A09F}', '\u{A0A0}', '\u{A0A1}', '\u{A0A2}', '\u{A0A3}', '\u{A0A4}', '\u{A0A5}', '\u{A0A6}', '\u{A0A7}', '\u{A0A8}', '\u{A0A9}', '\u{A0AA}', '\u{A0AB}', '\u{A0AC}', '\u{A0AD}', '\u{A0AE}', '\u{A0AF}', '\u{A0B0}', '\u{A0B1}', '\u{A0B2}', '\u{A0B3}', '\u{A0B4}', '\u{A0B5}', '\u{A0B6}', '\u{A0B7}', '\u{A0B8}', '\u{A0B9}', '\u{A0BA}', '\u{A0BB}', '\u{A0BC}', '\u{A0BD}', '\u{A0BE}', '\u{A0BF}', '\u{A0C0}', '\u{A0C1}', '\u{A0C2}', '\u{A0C3}', '\u{A0C4}', '\u{A0C5}', '\u{A0C6}', '\u{A0C7}', '\u{A0C8}', '\u{A0C9}', '\u{A0CA}', '\u{A0CB}', '\u{A0CC}', '\u{A0CD}', '\u{A0CE}', '\u{A0CF}', '\u{A0D0}', '\u{A0D1}', '\u{A0D2}', '\u{A0D3}', '\u{A0D4}', '\u{A0D5}', '\u{A0D6}', '\u{A0D7}', '\u{A0D8}', '\u{A0D9}', '\u{A0DA}', '\u{A0DB}', '\u{A0DC}', '\u{A0DD}', '\u{A0DE}', '\u{A0DF}', '\u{A0E0}', '\u{A0E1}', '\u{A0E2}', '\u{A0E3}', '\u{A0E4}', '\u{A0E5}', '\u{A0E6}', '\u{A0E7}', '\u{A0E8}', '\u{A0E9}', '\u{A0EA}', '\u{A0EB}', '\u{A0EC}', '\u{A0ED}', '\u{A0EE}', '\u{A0EF}', '\u{A0F0}', '\u{A0F1}', '\u{A0F2}', '\u{A0F3}', '\u{A0F4}', '\u{A0F5}', '\u{A0F6}', '\u{A0F7}', '\u{A0F8}', '\u{A0F9}', '\u{A0FA}', '\u{A0FB}', '\u{A0FC}', '\u{A0FD}', '\u{A0FE}', '\u{A0FF}', '\u{A100}', '\u{A101}', '\u{A102}', '\u{A103}', '\u{A104}', '\u{A105}', '\u{A106}', '\u{A107}', '\u{A108}', '\u{A109}', '\u{A10A}', '\u{A10B}', '\u{A10C}', '\u{A10D}', '\u{A10E}', '\u{A10F}', '\u{A110}', '\u{A111}', '\u{A112}', '\u{A113}', '\u{A114}', '\u{A115}', '\u{A116}', '\u{A117}', '\u{A118}', '\u{A119}', '\u{A11A}', '\u{A11B}', '\u{A11C}', '\u{A11D}', '\u{A11E}', '\u{A11F}', '\u{A120}', '\u{A121}', '\u{A122}', '\u{A123}', '\u{A124}', '\u{A125}', '\u{A126}', '\u{A127}', '\u{A128}', '\u{A129}', '\u{A12A}', '\u{A12B}', '\u{A12C}', '\u{A12D}', '\u{A12E}', '\u{A12F}', '\u{A130}', '\u{A131}', '\u{A132}', '\u{A133}', '\u{A134}', '\u{A135}', '\u{A136}', '\u{A137}', '\u{A138}', '\u{A139}', '\u{A13A}', '\u{A13B}', '\u{A13C}', '\u{A13D}', '\u{A13E}', '\u{A13F}', '\u{A140}', '\u{A141}', '\u{A142}', '\u{A143}', '\u{A144}', '\u{A145}', '\u{A146}', '\u{A147}', '\u{A148}', '\u{A149}', '\u{A14A}', '\u{A14B}', '\u{A14C}', '\u{A14D}', '\u{A14E}', '\u{A14F}', '\u{A150}', '\u{A151}', '\u{A152}', '\u{A153}', '\u{A154}', '\u{A155}', '\u{A156}', '\u{A157}', '\u{A158}', '\u{A159}', '\u{A15A}', '\u{A15B}', '\u{A15C}', '\u{A15D}', '\u{A15E}', '\u{A15F}', '\u{A160}', '\u{A161}', '\u{A162}', '\u{A163}', '\u{A164}', '\u{A165}', '\u{A166}', '\u{A167}', '\u{A168}', '\u{A169}', '\u{A16A}', '\u{A16B}', '\u{A16C}', '\u{A16D}', '\u{A16E}', '\u{A16F}', '\u{A170}', '\u{A171}', '\u{A172}', '\u{A173}', '\u{A174}', '\u{A175}', '\u{A176}', '\u{A177}', '\u{A178}', '\u{A179}', '\u{A17A}', '\u{A17B}', '\u{A17C}', '\u{A17D}', '\u{A17E}', '\u{A17F}', '\u{A180}', '\u{A181}', '\u{A182}', '\u{A183}', '\u{A184}', '\u{A185}', '\u{A186}', '\u{A187}', '\u{A188}', '\u{A189}', '\u{A18A}', '\u{A18B}', '\u{A18C}', '\u{A18D}', '\u{A18E}', '\u{A18F}', '\u{A190}', '\u{A191}', '\u{A192}', '\u{A193}', '\u{A194}', '\u{A195}', '\u{A196}', '\u{A197}', '\u{A198}', '\u{A199}', '\u{A19A}', '\u{A19B}', '\u{A19C}', '\u{A19D}', '\u{A19E}', '\u{A19F}', '\u{A1A0}', '\u{A1A1}', '\u{A1A2}', '\u{A1A3}', '\u{A1A4}', '\u{A1A5}', '\u{A1A6}', '\u{A1A7}', '\u{A1A8}', '\u{A1A9}', '\u{A1AA}', '\u{A1AB}', '\u{A1AC}', '\u{A1AD}', '\u{A1AE}', '\u{A1AF}') + } + + fn is_unicode_letter_number(self) -> bool { + match_char_class!(self, + '\u{16EE}', '\u{16EF}', '\u{16F0}', '\u{2160}', '\u{2161}', '\u{2162}', '\u{2163}', '\u{2164}', '\u{2165}', '\u{2166}', '\u{2167}', '\u{2168}', '\u{2169}', '\u{216A}', '\u{216B}', '\u{216C}', '\u{216D}', '\u{216E}', '\u{216F}', '\u{2170}', '\u{2171}', '\u{2172}', '\u{2173}', '\u{2174}', '\u{2175}', '\u{2176}', '\u{2177}', '\u{2178}', '\u{2179}', '\u{217A}', '\u{217B}', '\u{217C}', '\u{217D}', '\u{217E}', '\u{217F}', '\u{2180}', '\u{2181}', '\u{2182}', '\u{2185}', '\u{2186}', '\u{2187}', '\u{2188}', '\u{3007}', '\u{3021}', '\u{3022}', '\u{3023}', '\u{3024}', '\u{3025}', '\u{3026}', '\u{3027}', '\u{3028}', '\u{3029}', '\u{3038}', '\u{3039}', '\u{303A}') + } + + fn is_unicode_nonspacing_mark(self) -> bool { + match_char_class!(self, + '\u{0300}', '\u{0301}', '\u{0302}', '\u{0303}', '\u{0304}', '\u{0305}', '\u{0306}', '\u{0307}', '\u{0308}', '\u{0309}', '\u{030A}', '\u{030B}', '\u{030C}', '\u{030D}', '\u{030E}', '\u{030F}', '\u{0310}', '\u{0311}', '\u{0312}', '\u{0313}', '\u{0314}', '\u{0315}', '\u{0316}', '\u{0317}', '\u{0318}', '\u{0319}', '\u{031A}', '\u{031B}', '\u{031C}', '\u{031D}', '\u{031E}', '\u{031F}', '\u{0320}', '\u{0321}', '\u{0322}', '\u{0323}', '\u{0324}', '\u{0325}', '\u{0326}', '\u{0327}', '\u{0328}', '\u{0329}', '\u{032A}', '\u{032B}', '\u{032C}', '\u{032D}', '\u{032E}', '\u{032F}', '\u{0330}', '\u{0331}', '\u{0332}', '\u{0333}', '\u{0334}', '\u{0335}', '\u{0336}', '\u{0337}', '\u{0338}', '\u{0339}', '\u{033A}', '\u{033B}', '\u{033C}', '\u{033D}', '\u{033E}', '\u{033F}', '\u{0340}', '\u{0341}', '\u{0342}', '\u{0343}', '\u{0344}', '\u{0345}', '\u{0346}', '\u{0347}', '\u{0348}', '\u{0349}', '\u{034A}', '\u{034B}', '\u{034C}', '\u{034D}', '\u{034E}', '\u{034F}', '\u{0350}', '\u{0351}', '\u{0352}', '\u{0353}', '\u{0354}', '\u{0355}', '\u{0356}', '\u{0357}', '\u{0358}', '\u{0359}', '\u{035A}', '\u{035B}', '\u{035C}', '\u{035D}', '\u{035E}', '\u{035F}', '\u{0360}', '\u{0361}', '\u{0362}', '\u{0363}', '\u{0364}', '\u{0365}', '\u{0366}', '\u{0367}', '\u{0368}', '\u{0369}', '\u{036A}', '\u{036B}', '\u{036C}', '\u{036D}', '\u{036E}', '\u{036F}', '\u{0483}', '\u{0484}', '\u{0485}', '\u{0486}', '\u{0487}', '\u{0591}', '\u{0592}', '\u{0593}', '\u{0594}', '\u{0595}', '\u{0596}', '\u{0597}', '\u{0598}', '\u{0599}', '\u{059A}', '\u{059B}', '\u{059C}', '\u{059D}', '\u{059E}', '\u{059F}', '\u{05A0}', '\u{05A1}', '\u{05A2}', '\u{05A3}', '\u{05A4}', '\u{05A5}', '\u{05A6}', '\u{05A7}', '\u{05A8}', '\u{05A9}', '\u{05AA}', '\u{05AB}', '\u{05AC}', '\u{05AD}', '\u{05AE}', '\u{05AF}', '\u{05B0}', '\u{05B1}', '\u{05B2}', '\u{05B3}', '\u{05B4}', '\u{05B5}', '\u{05B6}', '\u{05B7}', '\u{05B8}', '\u{05B9}', '\u{05BA}', '\u{05BB}', '\u{05BC}', '\u{05BD}', '\u{05BF}', '\u{05C1}', '\u{05C2}', '\u{05C4}', '\u{05C5}', '\u{05C7}', '\u{0610}', '\u{0611}', '\u{0612}', '\u{0613}', '\u{0614}', '\u{0615}', '\u{0616}', '\u{0617}', '\u{0618}', '\u{0619}', '\u{061A}', '\u{064B}', '\u{064C}', '\u{064D}', '\u{064E}', '\u{064F}', '\u{0650}', '\u{0651}', '\u{0652}', '\u{0653}', '\u{0654}', '\u{0655}', '\u{0656}', '\u{0657}', '\u{0658}', '\u{0659}', '\u{065A}', '\u{065B}', '\u{065C}', '\u{065D}', '\u{065E}', '\u{0670}', '\u{06D6}', '\u{06D7}', '\u{06D8}', '\u{06D9}', '\u{06DA}', '\u{06DB}', '\u{06DC}', '\u{06DF}', '\u{06E0}', '\u{06E1}', '\u{06E2}', '\u{06E3}', '\u{06E4}', '\u{06E7}', '\u{06E8}', '\u{06EA}', '\u{06EB}', '\u{06EC}', '\u{06ED}', '\u{0711}', '\u{0730}', '\u{0731}', '\u{0732}', '\u{0733}', '\u{0734}', '\u{0735}', '\u{0736}', '\u{0737}', '\u{0738}', '\u{0739}', '\u{073A}', '\u{073B}', '\u{073C}', '\u{073D}', '\u{073E}', '\u{073F}', '\u{0740}', '\u{0741}', '\u{0742}', '\u{0743}', '\u{0744}', '\u{0745}', '\u{0746}', '\u{0747}', '\u{0748}', '\u{0749}', '\u{074A}', '\u{07A6}', '\u{07A7}', '\u{07A8}', '\u{07A9}', '\u{07AA}', '\u{07AB}', '\u{07AC}', '\u{07AD}', '\u{07AE}', '\u{07AF}', '\u{07B0}', '\u{07EB}', '\u{07EC}', '\u{07ED}', '\u{07EE}', '\u{07EF}', '\u{07F0}', '\u{07F1}', '\u{07F2}', '\u{07F3}', '\u{0901}', '\u{0902}', '\u{093C}', '\u{0941}', '\u{0942}', '\u{0943}', '\u{0944}', '\u{0945}', '\u{0946}', '\u{0947}', '\u{0948}', '\u{094D}', '\u{0951}', '\u{0952}', '\u{0953}', '\u{0954}', '\u{0962}', '\u{0963}', '\u{0981}', '\u{09BC}', '\u{09C1}', '\u{09C2}', '\u{09C3}', '\u{09C4}', '\u{09CD}', '\u{09E2}', '\u{09E3}', '\u{0A01}', '\u{0A02}', '\u{0A3C}', '\u{0A41}', '\u{0A42}', '\u{0A47}', '\u{0A48}', '\u{0A4B}', '\u{0A4C}', '\u{0A4D}', '\u{0A51}', '\u{0A70}', '\u{0A71}', '\u{0A75}', '\u{0A81}', '\u{0A82}', '\u{0ABC}', '\u{0AC1}', '\u{0AC2}', '\u{0AC3}', '\u{0AC4}', '\u{0AC5}', '\u{0AC7}', '\u{0AC8}', '\u{0ACD}', '\u{0AE2}', '\u{0AE3}', '\u{0B01}', '\u{0B3C}', '\u{0B3F}', '\u{0B41}', '\u{0B42}', '\u{0B43}', '\u{0B44}', '\u{0B4D}', '\u{0B56}', '\u{0B62}', '\u{0B63}', '\u{0B82}', '\u{0BC0}', '\u{0BCD}', '\u{0C3E}', '\u{0C3F}', '\u{0C40}', '\u{0C46}', '\u{0C47}', '\u{0C48}', '\u{0C4A}', '\u{0C4B}', '\u{0C4C}', '\u{0C4D}', '\u{0C55}', '\u{0C56}', '\u{0C62}', '\u{0C63}', '\u{0CBC}', '\u{0CBF}', '\u{0CC6}', '\u{0CCC}', '\u{0CCD}', '\u{0CE2}', '\u{0CE3}', '\u{0D41}', '\u{0D42}', '\u{0D43}', '\u{0D44}', '\u{0D4D}', '\u{0D62}', '\u{0D63}', '\u{0DCA}', '\u{0DD2}', '\u{0DD3}', '\u{0DD4}', '\u{0DD6}', '\u{0E31}', '\u{0E34}', '\u{0E35}', '\u{0E36}', '\u{0E37}', '\u{0E38}', '\u{0E39}', '\u{0E3A}', '\u{0E47}', '\u{0E48}', '\u{0E49}', '\u{0E4A}', '\u{0E4B}', '\u{0E4C}', '\u{0E4D}', '\u{0E4E}', '\u{0EB1}', '\u{0EB4}', '\u{0EB5}', '\u{0EB6}', '\u{0EB7}', '\u{0EB8}', '\u{0EB9}', '\u{0EBB}', '\u{0EBC}', '\u{0EC8}', '\u{0EC9}', '\u{0ECA}', '\u{0ECB}', '\u{0ECC}', '\u{0ECD}', '\u{0F18}', '\u{0F19}', '\u{0F35}', '\u{0F37}', '\u{0F39}', '\u{0F71}', '\u{0F72}', '\u{0F73}', '\u{0F74}', '\u{0F75}', '\u{0F76}', '\u{0F77}', '\u{0F78}', '\u{0F79}', '\u{0F7A}', '\u{0F7B}', '\u{0F7C}', '\u{0F7D}', '\u{0F7E}', '\u{0F80}', '\u{0F81}', '\u{0F82}', '\u{0F83}', '\u{0F84}', '\u{0F86}', '\u{0F87}', '\u{0F90}', '\u{0F91}', '\u{0F92}', '\u{0F93}', '\u{0F94}', '\u{0F95}', '\u{0F96}', '\u{0F97}', '\u{0F99}', '\u{0F9A}', '\u{0F9B}', '\u{0F9C}', '\u{0F9D}', '\u{0F9E}', '\u{0F9F}', '\u{0FA0}', '\u{0FA1}', '\u{0FA2}', '\u{0FA3}', '\u{0FA4}', '\u{0FA5}', '\u{0FA6}', '\u{0FA7}', '\u{0FA8}', '\u{0FA9}', '\u{0FAA}', '\u{0FAB}', '\u{0FAC}', '\u{0FAD}', '\u{0FAE}', '\u{0FAF}', '\u{0FB0}', '\u{0FB1}', '\u{0FB2}', '\u{0FB3}', '\u{0FB4}', '\u{0FB5}', '\u{0FB6}', '\u{0FB7}', '\u{0FB8}', '\u{0FB9}', '\u{0FBA}', '\u{0FBB}', '\u{0FBC}', '\u{0FC6}', '\u{102D}', '\u{102E}', '\u{102F}', '\u{1030}', '\u{1032}', '\u{1033}', '\u{1034}', '\u{1035}', '\u{1036}', '\u{1037}', '\u{1039}', '\u{103A}', '\u{103D}', '\u{103E}', '\u{1058}', '\u{1059}', '\u{105E}', '\u{105F}', '\u{1060}', '\u{1071}', '\u{1072}', '\u{1073}', '\u{1074}', '\u{1082}', '\u{1085}', '\u{1086}', '\u{108D}', '\u{135F}', '\u{1712}', '\u{1713}', '\u{1714}', '\u{1732}', '\u{1733}', '\u{1734}', '\u{1752}', '\u{1753}', '\u{1772}', '\u{1773}', '\u{17B7}', '\u{17B8}', '\u{17B9}', '\u{17BA}', '\u{17BB}', '\u{17BC}', '\u{17BD}', '\u{17C6}', '\u{17C9}', '\u{17CA}', '\u{17CB}', '\u{17CC}', '\u{17CD}', '\u{17CE}', '\u{17CF}', '\u{17D0}', '\u{17D1}', '\u{17D2}', '\u{17D3}', '\u{17DD}', '\u{180B}', '\u{180C}', '\u{180D}', '\u{18A9}', '\u{1920}', '\u{1921}', '\u{1922}', '\u{1927}', '\u{1928}', '\u{1932}', '\u{1939}', '\u{193A}', '\u{193B}', '\u{1A17}', '\u{1A18}', '\u{1B00}', '\u{1B01}', '\u{1B02}', '\u{1B03}', '\u{1B34}', '\u{1B36}', '\u{1B37}', '\u{1B38}', '\u{1B39}', '\u{1B3A}', '\u{1B3C}', '\u{1B42}', '\u{1B6B}', '\u{1B6C}', '\u{1B6D}', '\u{1B6E}', '\u{1B6F}', '\u{1B70}', '\u{1B71}', '\u{1B72}', '\u{1B73}', '\u{1B80}', '\u{1B81}', '\u{1BA2}', '\u{1BA3}', '\u{1BA4}', '\u{1BA5}', '\u{1BA8}', '\u{1BA9}', '\u{1C2C}', '\u{1C2D}', '\u{1C2E}', '\u{1C2F}', '\u{1C30}', '\u{1C31}', '\u{1C32}', '\u{1C33}', '\u{1C36}', '\u{1C37}', '\u{1DC0}', '\u{1DC1}', '\u{1DC2}', '\u{1DC3}', '\u{1DC4}', '\u{1DC5}', '\u{1DC6}', '\u{1DC7}', '\u{1DC8}', '\u{1DC9}', '\u{1DCA}', '\u{1DCB}', '\u{1DCC}', '\u{1DCD}', '\u{1DCE}', '\u{1DCF}', '\u{1DD0}', '\u{1DD1}', '\u{1DD2}', '\u{1DD3}', '\u{1DD4}', '\u{1DD5}', '\u{1DD6}', '\u{1DD7}', '\u{1DD8}', '\u{1DD9}', '\u{1DDA}', '\u{1DDB}', '\u{1DDC}', '\u{1DDD}', '\u{1DDE}', '\u{1DDF}', '\u{1DE0}', '\u{1DE1}', '\u{1DE2}', '\u{1DE3}', '\u{1DE4}', '\u{1DE5}', '\u{1DE6}', '\u{1DFE}', '\u{1DFF}', '\u{20D0}', '\u{20D1}', '\u{20D2}', '\u{20D3}', '\u{20D4}', '\u{20D5}', '\u{20D6}', '\u{20D7}', '\u{20D8}', '\u{20D9}', '\u{20DA}', '\u{20DB}', '\u{20DC}', '\u{20E1}', '\u{20E5}', '\u{20E6}', '\u{20E7}', '\u{20E8}', '\u{20E9}', '\u{20EA}', '\u{20EB}', '\u{20EC}', '\u{20ED}', '\u{20EE}', '\u{20EF}', '\u{20F0}', '\u{2DE0}', '\u{2DE1}', '\u{2DE2}', '\u{2DE3}', '\u{2DE4}', '\u{2DE5}', '\u{2DE6}', '\u{2DE7}', '\u{2DE8}', '\u{2DE9}', '\u{2DEA}', '\u{2DEB}', '\u{2DEC}', '\u{2DED}', '\u{2DEE}', '\u{2DEF}', '\u{2DF0}', '\u{2DF1}', '\u{2DF2}', '\u{2DF3}', '\u{2DF4}', '\u{2DF5}', '\u{2DF6}', '\u{2DF7}', '\u{2DF8}', '\u{2DF9}', '\u{2DFA}', '\u{2DFB}', '\u{2DFC}', '\u{2DFD}', '\u{2DFE}', '\u{2DFF}', '\u{302A}', '\u{302B}', '\u{302C}', '\u{302D}', '\u{302E}', '\u{302F}', '\u{3099}', '\u{309A}', '\u{A66F}', '\u{A67C}', '\u{A67D}', '\u{A802}', '\u{A806}', '\u{A80B}', '\u{A825}', '\u{A826}', '\u{A8C4}', '\u{A926}', '\u{A927}', '\u{A928}', '\u{A929}', '\u{A92A}', '\u{A92B}', '\u{A92C}', '\u{A92D}', '\u{A947}', '\u{A948}', '\u{A949}', '\u{A94A}', '\u{A94B}', '\u{A94C}', '\u{A94D}', '\u{A94E}', '\u{A94F}', '\u{A950}', '\u{A951}', '\u{AA29}', '\u{AA2A}', '\u{AA2B}', '\u{AA2C}', '\u{AA2D}', '\u{AA2E}', '\u{AA31}', '\u{AA32}', '\u{AA35}', '\u{AA36}', '\u{AA43}', '\u{AA4C}', '\u{FB1E}', '\u{FE00}', '\u{FE01}', '\u{FE02}', '\u{FE03}', '\u{FE04}', '\u{FE05}', '\u{FE06}', '\u{FE07}', '\u{FE08}', '\u{FE09}', '\u{FE0A}', '\u{FE0B}', '\u{FE0C}', '\u{FE0D}', '\u{FE0E}', '\u{FE0F}', '\u{FE20}', '\u{FE21}', '\u{FE22}', '\u{FE23}', '\u{FE24}', '\u{FE25}', '\u{FE26}', '\u{01BB}', '\u{01C0}', '\u{01C1}', '\u{01C2}', '\u{01C3}', '\u{0294}', '\u{05D0}', '\u{05D1}', '\u{05D2}', '\u{05D3}', '\u{05D4}', '\u{05D5}', '\u{05D6}', '\u{05D7}', '\u{05D8}', '\u{05D9}', '\u{05DA}', '\u{05DB}', '\u{05DC}', '\u{05DD}', '\u{05DE}', '\u{05DF}', '\u{05E0}', '\u{05E1}', '\u{05E2}', '\u{05E3}', '\u{05E4}', '\u{05E5}', '\u{05E6}', '\u{05E7}', '\u{05E8}', '\u{05E9}', '\u{05EA}', '\u{05F0}', '\u{05F1}', '\u{05F2}', '\u{0621}', '\u{0622}', '\u{0623}', '\u{0624}', '\u{0625}', '\u{0626}', '\u{0627}', '\u{0628}', '\u{0629}', '\u{062A}', '\u{062B}', '\u{062C}', '\u{062D}', '\u{062E}', '\u{062F}', '\u{0630}', '\u{0631}', '\u{0632}', '\u{0633}', '\u{0634}', '\u{0635}', '\u{0636}', '\u{0637}', '\u{0638}', '\u{0639}', '\u{063A}', '\u{063B}', '\u{063C}', '\u{063D}', '\u{063E}', '\u{063F}', '\u{0641}', '\u{0642}', '\u{0643}', '\u{0644}', '\u{0645}', '\u{0646}', '\u{0647}', '\u{0648}', '\u{0649}', '\u{064A}', '\u{066E}', '\u{066F}', '\u{0671}', '\u{0672}', '\u{0673}', '\u{0674}', '\u{0675}', '\u{0676}', '\u{0677}', '\u{0678}', '\u{0679}', '\u{067A}', '\u{067B}', '\u{067C}', '\u{067D}', '\u{067E}', '\u{067F}', '\u{0680}', '\u{0681}', '\u{0682}', '\u{0683}', '\u{0684}', '\u{0685}', '\u{0686}', '\u{0687}', '\u{0688}', '\u{0689}', '\u{068A}', '\u{068B}', '\u{068C}', '\u{068D}', '\u{068E}', '\u{068F}', '\u{0690}', '\u{0691}', '\u{0692}', '\u{0693}', '\u{0694}', '\u{0695}', '\u{0696}', '\u{0697}', '\u{0698}', '\u{0699}', '\u{069A}', '\u{069B}', '\u{069C}', '\u{069D}', '\u{069E}', '\u{069F}', '\u{06A0}', '\u{06A1}', '\u{06A2}', '\u{06A3}', '\u{06A4}', '\u{06A5}', '\u{06A6}', '\u{06A7}', '\u{06A8}', '\u{06A9}', '\u{06AA}', '\u{06AB}', '\u{06AC}', '\u{06AD}', '\u{06AE}', '\u{06AF}', '\u{06B0}', '\u{06B1}', '\u{06B2}', '\u{06B3}', '\u{06B4}', '\u{06B5}', '\u{06B6}', '\u{06B7}', '\u{06B8}', '\u{06B9}', '\u{06BA}', '\u{06BB}', '\u{06BC}', '\u{06BD}', '\u{06BE}', '\u{06BF}', '\u{06C0}', '\u{06C1}', '\u{06C2}', '\u{06C3}', '\u{06C4}', '\u{06C5}', '\u{06C6}', '\u{06C7}', '\u{06C8}', '\u{06C9}', '\u{06CA}', '\u{06CB}', '\u{06CC}', '\u{06CD}', '\u{06CE}', '\u{06CF}', '\u{06D0}', '\u{06D1}', '\u{06D2}', '\u{06D3}', '\u{06D5}', '\u{06EE}', '\u{06EF}', '\u{06FA}', '\u{06FB}', '\u{06FC}', '\u{06FF}', '\u{0710}', '\u{0712}', '\u{0713}', '\u{0714}', '\u{0715}', '\u{0716}', '\u{0717}', '\u{0718}', '\u{0719}', '\u{071A}', '\u{071B}', '\u{071C}', '\u{071D}', '\u{071E}', '\u{071F}', '\u{0720}', '\u{0721}', '\u{0722}', '\u{0723}', '\u{0724}', '\u{0725}', '\u{0726}', '\u{0727}', '\u{0728}', '\u{0729}', '\u{072A}', '\u{072B}', '\u{072C}', '\u{072D}', '\u{072E}', '\u{072F}', '\u{074D}', '\u{074E}', '\u{074F}', '\u{0750}', '\u{0751}', '\u{0752}', '\u{0753}', '\u{0754}', '\u{0755}', '\u{0756}', '\u{0757}', '\u{0758}', '\u{0759}', '\u{075A}', '\u{075B}', '\u{075C}', '\u{075D}', '\u{075E}', '\u{075F}', '\u{0760}', '\u{0761}', '\u{0762}', '\u{0763}', '\u{0764}', '\u{0765}', '\u{0766}', '\u{0767}', '\u{0768}', '\u{0769}', '\u{076A}', '\u{076B}', '\u{076C}', '\u{076D}', '\u{076E}', '\u{076F}', '\u{0770}', '\u{0771}', '\u{0772}', '\u{0773}', '\u{0774}', '\u{0775}', '\u{0776}', '\u{0777}', '\u{0778}', '\u{0779}', '\u{077A}', '\u{077B}', '\u{077C}', '\u{077D}', '\u{077E}', '\u{077F}', '\u{0780}', '\u{0781}', '\u{0782}', '\u{0783}', '\u{0784}', '\u{0785}', '\u{0786}', '\u{0787}', '\u{0788}', '\u{0789}', '\u{078A}', '\u{078B}', '\u{078C}', '\u{078D}', '\u{078E}', '\u{078F}', '\u{0790}', '\u{0791}', '\u{0792}', '\u{0793}', '\u{0794}', '\u{0795}', '\u{0796}', '\u{0797}', '\u{0798}', '\u{0799}', '\u{079A}', '\u{079B}', '\u{079C}', '\u{079D}', '\u{079E}', '\u{079F}', '\u{07A0}', '\u{07A1}', '\u{07A2}', '\u{07A3}', '\u{07A4}', '\u{07A5}', '\u{07B1}', '\u{07CA}', '\u{07CB}', '\u{07CC}', '\u{07CD}', '\u{07CE}', '\u{07CF}', '\u{07D0}', '\u{07D1}', '\u{07D2}', '\u{07D3}', '\u{07D4}', '\u{07D5}', '\u{07D6}', '\u{07D7}', '\u{07D8}', '\u{07D9}', '\u{07DA}', '\u{07DB}', '\u{07DC}', '\u{07DD}', '\u{07DE}', '\u{07DF}', '\u{07E0}', '\u{07E1}', '\u{07E2}', '\u{07E3}', '\u{07E4}', '\u{07E5}', '\u{07E6}', '\u{07E7}', '\u{07E8}', '\u{07E9}', '\u{07EA}', '\u{0904}', '\u{0905}', '\u{0906}', '\u{0907}', '\u{0908}', '\u{0909}', '\u{090A}', '\u{090B}', '\u{090C}', '\u{090D}', '\u{090E}', '\u{090F}', '\u{0910}', '\u{0911}', '\u{0912}', '\u{0913}', '\u{0914}', '\u{0915}', '\u{0916}', '\u{0917}', '\u{0918}', '\u{0919}', '\u{091A}', '\u{091B}', '\u{091C}', '\u{091D}', '\u{091E}', '\u{091F}', '\u{0920}', '\u{0921}', '\u{0922}', '\u{0923}', '\u{0924}', '\u{0925}', '\u{0926}', '\u{0927}', '\u{0928}', '\u{0929}', '\u{092A}', '\u{092B}', '\u{092C}', '\u{092D}', '\u{092E}', '\u{092F}', '\u{0930}', '\u{0931}', '\u{0932}', '\u{0933}', '\u{0934}', '\u{0935}', '\u{0936}', '\u{0937}', '\u{0938}', '\u{0939}', '\u{093D}', '\u{0950}', '\u{0958}', '\u{0959}', '\u{095A}', '\u{095B}', '\u{095C}', '\u{095D}', '\u{095E}', '\u{095F}', '\u{0960}', '\u{0961}', '\u{0972}', '\u{097B}', '\u{097C}', '\u{097D}', '\u{097E}', '\u{097F}', '\u{0985}', '\u{0986}', '\u{0987}', '\u{0988}', '\u{0989}', '\u{098A}', '\u{098B}', '\u{098C}', '\u{098F}', '\u{0990}', '\u{0993}', '\u{0994}', '\u{0995}', '\u{0996}', '\u{0997}', '\u{0998}', '\u{0999}', '\u{099A}', '\u{099B}', '\u{099C}', '\u{099D}', '\u{099E}', '\u{099F}', '\u{09A0}', '\u{09A1}', '\u{09A2}', '\u{09A3}', '\u{09A4}', '\u{09A5}', '\u{09A6}', '\u{09A7}', '\u{09A8}', '\u{09AA}', '\u{09AB}', '\u{09AC}', '\u{09AD}', '\u{09AE}', '\u{09AF}', '\u{09B0}', '\u{09B2}', '\u{09B6}', '\u{09B7}', '\u{09B8}', '\u{09B9}', '\u{09BD}', '\u{09CE}', '\u{09DC}', '\u{09DD}', '\u{09DF}', '\u{09E0}', '\u{09E1}', '\u{09F0}', '\u{09F1}', '\u{0A05}', '\u{0A06}', '\u{0A07}', '\u{0A08}', '\u{0A09}', '\u{0A0A}', '\u{0A0F}', '\u{0A10}', '\u{0A13}', '\u{0A14}', '\u{0A15}', '\u{0A16}', '\u{0A17}', '\u{0A18}', '\u{0A19}', '\u{0A1A}', '\u{0A1B}', '\u{0A1C}', '\u{0A1D}', '\u{0A1E}', '\u{0A1F}', '\u{0A20}', '\u{0A21}', '\u{0A22}', '\u{0A23}', '\u{0A24}', '\u{0A25}', '\u{0A26}', '\u{0A27}', '\u{0A28}', '\u{0A2A}', '\u{0A2B}', '\u{0A2C}', '\u{0A2D}', '\u{0A2E}', '\u{0A2F}', '\u{0A30}', '\u{0A32}', '\u{0A33}', '\u{0A35}', '\u{0A36}', '\u{0A38}', '\u{0A39}', '\u{0A59}', '\u{0A5A}', '\u{0A5B}', '\u{0A5C}', '\u{0A5E}', '\u{0A72}', '\u{0A73}', '\u{0A74}', '\u{0A85}', '\u{0A86}', '\u{0A87}', '\u{0A88}', '\u{0A89}', '\u{0A8A}', '\u{0A8B}', '\u{0A8C}', '\u{0A8D}', '\u{0A8F}', '\u{0A90}', '\u{0A91}', '\u{0A93}', '\u{0A94}', '\u{0A95}', '\u{0A96}', '\u{0A97}', '\u{0A98}', '\u{0A99}', '\u{0A9A}', '\u{0A9B}', '\u{0A9C}', '\u{0A9D}', '\u{0A9E}', '\u{0A9F}', '\u{0AA0}', '\u{0AA1}', '\u{0AA2}', '\u{0AA3}', '\u{0AA4}', '\u{0AA5}', '\u{0AA6}', '\u{0AA7}', '\u{0AA8}', '\u{0AAA}', '\u{0AAB}', '\u{0AAC}', '\u{0AAD}', '\u{0AAE}', '\u{0AAF}', '\u{0AB0}', '\u{0AB2}', '\u{0AB3}', '\u{0AB5}', '\u{0AB6}', '\u{0AB7}', '\u{0AB8}', '\u{0AB9}', '\u{0ABD}', '\u{0AD0}', '\u{0AE0}', '\u{0AE1}', '\u{0B05}', '\u{0B06}', '\u{0B07}', '\u{0B08}', '\u{0B09}', '\u{0B0A}', '\u{0B0B}', '\u{0B0C}', '\u{0B0F}', '\u{0B10}', '\u{0B13}', '\u{0B14}', '\u{0B15}', '\u{0B16}', '\u{0B17}', '\u{0B18}', '\u{0B19}', '\u{0B1A}', '\u{0B1B}', '\u{0B1C}', '\u{0B1D}', '\u{0B1E}', '\u{0B1F}', '\u{0B20}', '\u{0B21}', '\u{0B22}', '\u{0B23}', '\u{0B24}', '\u{0B25}', '\u{0B26}', '\u{0B27}', '\u{0B28}', '\u{0B2A}', '\u{0B2B}', '\u{0B2C}', '\u{0B2D}', '\u{0B2E}', '\u{0B2F}', '\u{0B30}', '\u{0B32}', '\u{0B33}', '\u{0B35}', '\u{0B36}', '\u{0B37}', '\u{0B38}', '\u{0B39}', '\u{0B3D}', '\u{0B5C}', '\u{0B5D}', '\u{0B5F}', '\u{0B60}', '\u{0B61}', '\u{0B71}', '\u{0B83}', '\u{0B85}', '\u{0B86}', '\u{0B87}', '\u{0B88}', '\u{0B89}', '\u{0B8A}', '\u{0B8E}', '\u{0B8F}', '\u{0B90}', '\u{0B92}', '\u{0B93}', '\u{0B94}', '\u{0B95}', '\u{0B99}', '\u{0B9A}', '\u{0B9C}', '\u{0B9E}', '\u{0B9F}', '\u{0BA3}', '\u{0BA4}', '\u{0BA8}', '\u{0BA9}', '\u{0BAA}', '\u{0BAE}', '\u{0BAF}', '\u{0BB0}', '\u{0BB1}', '\u{0BB2}', '\u{0BB3}', '\u{0BB4}', '\u{0BB5}', '\u{0BB6}', '\u{0BB7}', '\u{0BB8}', '\u{0BB9}', '\u{0BD0}', '\u{0C05}', '\u{0C06}', '\u{0C07}', '\u{0C08}', '\u{0C09}', '\u{0C0A}', '\u{0C0B}', '\u{0C0C}', '\u{0C0E}', '\u{0C0F}', '\u{0C10}', '\u{0C12}', '\u{0C13}', '\u{0C14}', '\u{0C15}', '\u{0C16}', '\u{0C17}', '\u{0C18}', '\u{0C19}', '\u{0C1A}', '\u{0C1B}', '\u{0C1C}', '\u{0C1D}', '\u{0C1E}', '\u{0C1F}', '\u{0C20}', '\u{0C21}', '\u{0C22}', '\u{0C23}', '\u{0C24}', '\u{0C25}', '\u{0C26}', '\u{0C27}', '\u{0C28}', '\u{0C2A}', '\u{0C2B}', '\u{0C2C}', '\u{0C2D}', '\u{0C2E}', '\u{0C2F}', '\u{0C30}', '\u{0C31}', '\u{0C32}', '\u{0C33}', '\u{0C35}', '\u{0C36}', '\u{0C37}', '\u{0C38}', '\u{0C39}', '\u{0C3D}', '\u{0C58}', '\u{0C59}', '\u{0C60}', '\u{0C61}', '\u{0C85}', '\u{0C86}', '\u{0C87}', '\u{0C88}', '\u{0C89}', '\u{0C8A}', '\u{0C8B}', '\u{0C8C}', '\u{0C8E}', '\u{0C8F}', '\u{0C90}', '\u{0C92}', '\u{0C93}', '\u{0C94}', '\u{0C95}', '\u{0C96}', '\u{0C97}', '\u{0C98}', '\u{0C99}', '\u{0C9A}', '\u{0C9B}', '\u{0C9C}', '\u{0C9D}', '\u{0C9E}', '\u{0C9F}', '\u{0CA0}', '\u{0CA1}', '\u{0CA2}', '\u{0CA3}', '\u{0CA4}', '\u{0CA5}', '\u{0CA6}', '\u{0CA7}', '\u{0CA8}', '\u{0CAA}', '\u{0CAB}', '\u{0CAC}', '\u{0CAD}', '\u{0CAE}', '\u{0CAF}', '\u{0CB0}', '\u{0CB1}', '\u{0CB2}', '\u{0CB3}', '\u{0CB5}', '\u{0CB6}', '\u{0CB7}', '\u{0CB8}', '\u{0CB9}', '\u{0CBD}', '\u{0CDE}', '\u{0CE0}', '\u{0CE1}', '\u{0D05}', '\u{0D06}', '\u{0D07}', '\u{0D08}', '\u{0D09}', '\u{0D0A}', '\u{0D0B}', '\u{0D0C}', '\u{0D0E}', '\u{0D0F}', '\u{0D10}', '\u{0D12}', '\u{0D13}', '\u{0D14}', '\u{0D15}', '\u{0D16}', '\u{0D17}', '\u{0D18}', '\u{0D19}', '\u{0D1A}', '\u{0D1B}', '\u{0D1C}', '\u{0D1D}', '\u{0D1E}', '\u{0D1F}', '\u{0D20}', '\u{0D21}', '\u{0D22}', '\u{0D23}', '\u{0D24}', '\u{0D25}', '\u{0D26}', '\u{0D27}', '\u{0D28}', '\u{0D2A}', '\u{0D2B}', '\u{0D2C}', '\u{0D2D}', '\u{0D2E}', '\u{0D2F}', '\u{0D30}', '\u{0D31}', '\u{0D32}', '\u{0D33}', '\u{0D34}', '\u{0D35}', '\u{0D36}', '\u{0D37}', '\u{0D38}', '\u{0D39}', '\u{0D3D}', '\u{0D60}', '\u{0D61}', '\u{0D7A}', '\u{0D7B}', '\u{0D7C}', '\u{0D7D}', '\u{0D7E}', '\u{0D7F}', '\u{0D85}', '\u{0D86}', '\u{0D87}', '\u{0D88}', '\u{0D89}', '\u{0D8A}', '\u{0D8B}', '\u{0D8C}', '\u{0D8D}', '\u{0D8E}', '\u{0D8F}', '\u{0D90}', '\u{0D91}', '\u{0D92}', '\u{0D93}', '\u{0D94}', '\u{0D95}', '\u{0D96}', '\u{0D9A}', '\u{0D9B}', '\u{0D9C}', '\u{0D9D}', '\u{0D9E}', '\u{0D9F}', '\u{0DA0}', '\u{0DA1}', '\u{0DA2}', '\u{0DA3}', '\u{0DA4}', '\u{0DA5}', '\u{0DA6}', '\u{0DA7}', '\u{0DA8}', '\u{0DA9}', '\u{0DAA}', '\u{0DAB}', '\u{0DAC}', '\u{0DAD}', '\u{0DAE}', '\u{0DAF}', '\u{0DB0}', '\u{0DB1}', '\u{0DB3}', '\u{0DB4}', '\u{0DB5}', '\u{0DB6}', '\u{0DB7}', '\u{0DB8}', '\u{0DB9}', '\u{0DBA}', '\u{0DBB}', '\u{0DBD}', '\u{0DC0}', '\u{0DC1}', '\u{0DC2}', '\u{0DC3}', '\u{0DC4}', '\u{0DC5}', '\u{0DC6}', '\u{0E01}', '\u{0E02}', '\u{0E03}', '\u{0E04}', '\u{0E05}', '\u{0E06}', '\u{0E07}', '\u{0E08}', '\u{0E09}', '\u{0E0A}', '\u{0E0B}', '\u{0E0C}', '\u{0E0D}', '\u{0E0E}', '\u{0E0F}', '\u{0E10}', '\u{0E11}', '\u{0E12}', '\u{0E13}', '\u{0E14}', '\u{0E15}', '\u{0E16}', '\u{0E17}', '\u{0E18}', '\u{0E19}', '\u{0E1A}', '\u{0E1B}', '\u{0E1C}', '\u{0E1D}', '\u{0E1E}', '\u{0E1F}', '\u{0E20}', '\u{0E21}', '\u{0E22}', '\u{0E23}', '\u{0E24}', '\u{0E25}', '\u{0E26}', '\u{0E27}', '\u{0E28}', '\u{0E29}', '\u{0E2A}', '\u{0E2B}', '\u{0E2C}', '\u{0E2D}', '\u{0E2E}', '\u{0E2F}', '\u{0E30}', '\u{0E32}', '\u{0E33}', '\u{0E40}', '\u{0E41}', '\u{0E42}', '\u{0E43}', '\u{0E44}', '\u{0E45}', '\u{0E81}', '\u{0E82}', '\u{0E84}', '\u{0E87}', '\u{0E88}', '\u{0E8A}', '\u{0E8D}', '\u{0E94}', '\u{0E95}', '\u{0E96}', '\u{0E97}', '\u{0E99}', '\u{0E9A}', '\u{0E9B}', '\u{0E9C}', '\u{0E9D}', '\u{0E9E}', '\u{0E9F}', '\u{0EA1}', '\u{0EA2}', '\u{0EA3}', '\u{0EA5}', '\u{0EA7}', '\u{0EAA}', '\u{0EAB}', '\u{0EAD}', '\u{0EAE}', '\u{0EAF}', '\u{0EB0}', '\u{0EB2}', '\u{0EB3}', '\u{0EBD}', '\u{0EC0}', '\u{0EC1}', '\u{0EC2}', '\u{0EC3}', '\u{0EC4}', '\u{0EDC}', '\u{0EDD}', '\u{0F00}', '\u{0F40}', '\u{0F41}', '\u{0F42}', '\u{0F43}', '\u{0F44}', '\u{0F45}', '\u{0F46}', '\u{0F47}', '\u{0F49}', '\u{0F4A}', '\u{0F4B}', '\u{0F4C}', '\u{0F4D}', '\u{0F4E}', '\u{0F4F}', '\u{0F50}', '\u{0F51}', '\u{0F52}', '\u{0F53}', '\u{0F54}', '\u{0F55}', '\u{0F56}', '\u{0F57}', '\u{0F58}', '\u{0F59}', '\u{0F5A}', '\u{0F5B}', '\u{0F5C}', '\u{0F5D}', '\u{0F5E}', '\u{0F5F}', '\u{0F60}', '\u{0F61}', '\u{0F62}', '\u{0F63}', '\u{0F64}', '\u{0F65}', '\u{0F66}', '\u{0F67}', '\u{0F68}', '\u{0F69}', '\u{0F6A}', '\u{0F6B}', '\u{0F6C}', '\u{0F88}', '\u{0F89}', '\u{0F8A}', '\u{0F8B}', '\u{1000}', '\u{1001}', '\u{1002}', '\u{1003}', '\u{1004}', '\u{1005}', '\u{1006}', '\u{1007}', '\u{1008}', '\u{1009}', '\u{100A}', '\u{100B}', '\u{100C}', '\u{100D}', '\u{100E}', '\u{100F}', '\u{1010}', '\u{1011}', '\u{1012}', '\u{1013}', '\u{1014}', '\u{1015}', '\u{1016}', '\u{1017}', '\u{1018}', '\u{1019}', '\u{101A}', '\u{101B}', '\u{101C}', '\u{101D}', '\u{101E}', '\u{101F}', '\u{1020}', '\u{1021}', '\u{1022}', '\u{1023}', '\u{1024}', '\u{1025}', '\u{1026}', '\u{1027}', '\u{1028}', '\u{1029}', '\u{102A}', '\u{103F}', '\u{1050}', '\u{1051}', '\u{1052}', '\u{1053}', '\u{1054}', '\u{1055}', '\u{105A}', '\u{105B}', '\u{105C}', '\u{105D}', '\u{1061}', '\u{1065}', '\u{1066}', '\u{106E}', '\u{106F}', '\u{1070}', '\u{1075}', '\u{1076}', '\u{1077}', '\u{1078}', '\u{1079}', '\u{107A}', '\u{107B}', '\u{107C}', '\u{107D}', '\u{107E}', '\u{107F}', '\u{1080}', '\u{1081}', '\u{108E}', '\u{10D0}', '\u{10D1}', '\u{10D2}', '\u{10D3}', '\u{10D4}', '\u{10D5}', '\u{10D6}', '\u{10D7}', '\u{10D8}', '\u{10D9}', '\u{10DA}', '\u{10DB}', '\u{10DC}', '\u{10DD}', '\u{10DE}', '\u{10DF}', '\u{10E0}', '\u{10E1}', '\u{10E2}', '\u{10E3}', '\u{10E4}', '\u{10E5}', '\u{10E6}', '\u{10E7}', '\u{10E8}', '\u{10E9}', '\u{10EA}', '\u{10EB}', '\u{10EC}', '\u{10ED}', '\u{10EE}', '\u{10EF}', '\u{10F0}', '\u{10F1}', '\u{10F2}', '\u{10F3}', '\u{10F4}', '\u{10F5}', '\u{10F6}', '\u{10F7}', '\u{10F8}', '\u{10F9}', '\u{10FA}', '\u{1100}', '\u{1101}', '\u{1102}', '\u{1103}', '\u{1104}', '\u{1105}', '\u{1106}', '\u{1107}', '\u{1108}', '\u{1109}', '\u{110A}', '\u{110B}', '\u{110C}', '\u{110D}', '\u{110E}', '\u{110F}', '\u{1110}', '\u{1111}', '\u{1112}', '\u{1113}', '\u{1114}', '\u{1115}', '\u{1116}', '\u{1117}', '\u{1118}', '\u{1119}', '\u{111A}', '\u{111B}', '\u{111C}', '\u{111D}', '\u{111E}', '\u{111F}', '\u{1120}', '\u{1121}', '\u{1122}', '\u{1123}', '\u{1124}', '\u{1125}', '\u{1126}', '\u{1127}', '\u{1128}', '\u{1129}', '\u{112A}', '\u{112B}', '\u{112C}', '\u{112D}', '\u{112E}', '\u{112F}', '\u{1130}', '\u{1131}', '\u{1132}', '\u{1133}', '\u{1134}', '\u{1135}', '\u{1136}', '\u{1137}', '\u{1138}', '\u{1139}', '\u{113A}', '\u{113B}', '\u{113C}', '\u{113D}', '\u{113E}', '\u{113F}', '\u{1140}', '\u{1141}', '\u{1142}', '\u{1143}', '\u{1144}', '\u{1145}', '\u{1146}', '\u{1147}', '\u{1148}', '\u{1149}', '\u{114A}', '\u{114B}', '\u{114C}', '\u{114D}', '\u{114E}', '\u{114F}', '\u{1150}', '\u{1151}', '\u{1152}', '\u{1153}', '\u{1154}', '\u{1155}', '\u{1156}', '\u{1157}', '\u{1158}', '\u{1159}', '\u{115F}', '\u{1160}', '\u{1161}', '\u{1162}', '\u{1163}', '\u{1164}', '\u{1165}', '\u{1166}', '\u{1167}', '\u{1168}', '\u{1169}', '\u{116A}', '\u{116B}', '\u{116C}', '\u{116D}', '\u{116E}', '\u{116F}', '\u{1170}', '\u{1171}', '\u{1172}', '\u{1173}', '\u{1174}', '\u{1175}', '\u{1176}', '\u{1177}', '\u{1178}', '\u{1179}', '\u{117A}', '\u{117B}', '\u{117C}', '\u{117D}', '\u{117E}', '\u{117F}', '\u{1180}', '\u{1181}', '\u{1182}', '\u{1183}', '\u{1184}', '\u{1185}', '\u{1186}', '\u{1187}', '\u{1188}', '\u{1189}', '\u{118A}', '\u{118B}', '\u{118C}', '\u{118D}', '\u{118E}', '\u{118F}', '\u{1190}', '\u{1191}', '\u{1192}', '\u{1193}', '\u{1194}', '\u{1195}', '\u{1196}', '\u{1197}', '\u{1198}', '\u{1199}', '\u{119A}', '\u{119B}', '\u{119C}', '\u{119D}', '\u{119E}', '\u{119F}', '\u{11A0}', '\u{11A1}', '\u{11A2}', '\u{11A8}', '\u{11A9}', '\u{11AA}', '\u{11AB}', '\u{11AC}', '\u{11AD}', '\u{11AE}', '\u{11AF}', '\u{11B0}', '\u{11B1}', '\u{11B2}', '\u{11B3}', '\u{11B4}', '\u{11B5}', '\u{11B6}', '\u{11B7}', '\u{11B8}', '\u{11B9}', '\u{11BA}', '\u{11BB}', '\u{11BC}', '\u{11BD}', '\u{11BE}', '\u{11BF}', '\u{11C0}', '\u{11C1}', '\u{11C2}', '\u{11C3}', '\u{11C4}', '\u{11C5}', '\u{11C6}', '\u{11C7}', '\u{11C8}', '\u{11C9}', '\u{11CA}', '\u{11CB}', '\u{11CC}', '\u{11CD}', '\u{11CE}', '\u{11CF}', '\u{11D0}', '\u{11D1}', '\u{11D2}', '\u{11D3}', '\u{11D4}', '\u{11D5}', '\u{11D6}', '\u{11D7}', '\u{11D8}', '\u{11D9}', '\u{11DA}', '\u{11DB}', '\u{11DC}', '\u{11DD}', '\u{11DE}', '\u{11DF}', '\u{11E0}', '\u{11E1}', '\u{11E2}', '\u{11E3}', '\u{11E4}', '\u{11E5}', '\u{11E6}', '\u{11E7}', '\u{11E8}', '\u{11E9}', '\u{11EA}', '\u{11EB}', '\u{11EC}', '\u{11ED}', '\u{11EE}', '\u{11EF}', '\u{11F0}', '\u{11F1}', '\u{11F2}', '\u{11F3}', '\u{11F4}', '\u{11F5}', '\u{11F6}', '\u{11F7}', '\u{11F8}', '\u{11F9}', '\u{1200}', '\u{1201}', '\u{1202}', '\u{1203}', '\u{1204}', '\u{1205}', '\u{1206}', '\u{1207}', '\u{1208}', '\u{1209}', '\u{120A}', '\u{120B}', '\u{120C}', '\u{120D}', '\u{120E}', '\u{120F}', '\u{1210}', '\u{1211}', '\u{1212}', '\u{1213}', '\u{1214}', '\u{1215}', '\u{1216}', '\u{1217}', '\u{1218}', '\u{1219}', '\u{121A}', '\u{121B}', '\u{121C}', '\u{121D}', '\u{121E}', '\u{121F}', '\u{1220}', '\u{1221}', '\u{1222}', '\u{1223}', '\u{1224}', '\u{1225}', '\u{1226}', '\u{1227}', '\u{1228}', '\u{1229}', '\u{122A}', '\u{122B}', '\u{122C}', '\u{122D}', '\u{122E}', '\u{122F}', '\u{1230}', '\u{1231}', '\u{1232}', '\u{1233}', '\u{1234}', '\u{1235}', '\u{1236}', '\u{1237}', '\u{1238}', '\u{1239}', '\u{123A}', '\u{123B}', '\u{123C}', '\u{123D}', '\u{123E}', '\u{123F}', '\u{1240}', '\u{1241}', '\u{1242}', '\u{1243}', '\u{1244}', '\u{1245}', '\u{1246}', '\u{1247}', '\u{1248}', '\u{124A}', '\u{124B}', '\u{124C}', '\u{124D}', '\u{1250}', '\u{1251}', '\u{1252}', '\u{1253}', '\u{1254}', '\u{1255}', '\u{1256}', '\u{1258}', '\u{125A}', '\u{125B}', '\u{125C}', '\u{125D}', '\u{1260}', '\u{1261}', '\u{1262}', '\u{1263}', '\u{1264}', '\u{1265}', '\u{1266}', '\u{1267}', '\u{1268}', '\u{1269}', '\u{126A}', '\u{126B}', '\u{126C}', '\u{126D}', '\u{126E}', '\u{126F}', '\u{1270}', '\u{1271}', '\u{1272}', '\u{1273}', '\u{1274}', '\u{1275}', '\u{1276}', '\u{1277}', '\u{1278}', '\u{1279}', '\u{127A}', '\u{127B}', '\u{127C}', '\u{127D}', '\u{127E}', '\u{127F}', '\u{1280}', '\u{1281}', '\u{1282}', '\u{1283}', '\u{1284}', '\u{1285}', '\u{1286}', '\u{1287}', '\u{1288}', '\u{128A}', '\u{128B}', '\u{128C}', '\u{128D}', '\u{1290}', '\u{1291}', '\u{1292}', '\u{1293}', '\u{1294}', '\u{1295}', '\u{1296}', '\u{1297}', '\u{1298}', '\u{1299}', '\u{129A}', '\u{129B}', '\u{129C}', '\u{129D}', '\u{129E}', '\u{129F}', '\u{12A0}', '\u{12A1}', '\u{12A2}', '\u{12A3}', '\u{12A4}', '\u{12A5}', '\u{12A6}', '\u{12A7}', '\u{12A8}', '\u{12A9}', '\u{12AA}', '\u{12AB}', '\u{12AC}', '\u{12AD}', '\u{12AE}', '\u{12AF}', '\u{12B0}', '\u{12B2}', '\u{12B3}', '\u{12B4}', '\u{12B5}', '\u{12B8}', '\u{12B9}', '\u{12BA}', '\u{12BB}', '\u{12BC}', '\u{12BD}', '\u{12BE}', '\u{12C0}', '\u{12C2}', '\u{12C3}', '\u{12C4}', '\u{12C5}', '\u{12C8}', '\u{12C9}', '\u{12CA}', '\u{12CB}', '\u{12CC}', '\u{12CD}', '\u{12CE}', '\u{12CF}', '\u{12D0}', '\u{12D1}', '\u{12D2}', '\u{12D3}', '\u{12D4}', '\u{12D5}', '\u{12D6}', '\u{12D8}', '\u{12D9}', '\u{12DA}', '\u{12DB}', '\u{12DC}', '\u{12DD}', '\u{12DE}', '\u{12DF}', '\u{12E0}', '\u{12E1}', '\u{12E2}', '\u{12E3}', '\u{12E4}', '\u{12E5}', '\u{12E6}', '\u{12E7}', '\u{12E8}', '\u{12E9}', '\u{12EA}', '\u{12EB}', '\u{12EC}', '\u{12ED}', '\u{12EE}', '\u{12EF}', '\u{12F0}', '\u{12F1}', '\u{12F2}', '\u{12F3}', '\u{12F4}', '\u{12F5}', '\u{12F6}', '\u{12F7}', '\u{12F8}', '\u{12F9}', '\u{12FA}', '\u{12FB}', '\u{12FC}', '\u{12FD}', '\u{12FE}', '\u{12FF}', '\u{1300}', '\u{1301}', '\u{1302}', '\u{1303}', '\u{1304}', '\u{1305}', '\u{1306}', '\u{1307}', '\u{1308}', '\u{1309}', '\u{130A}', '\u{130B}', '\u{130C}', '\u{130D}', '\u{130E}', '\u{130F}', '\u{1310}', '\u{1312}', '\u{1313}', '\u{1314}', '\u{1315}', '\u{1318}', '\u{1319}', '\u{131A}', '\u{131B}', '\u{131C}', '\u{131D}', '\u{131E}', '\u{131F}', '\u{1320}', '\u{1321}', '\u{1322}', '\u{1323}', '\u{1324}', '\u{1325}', '\u{1326}', '\u{1327}', '\u{1328}', '\u{1329}', '\u{132A}', '\u{132B}', '\u{132C}', '\u{132D}', '\u{132E}', '\u{132F}', '\u{1330}', '\u{1331}', '\u{1332}', '\u{1333}', '\u{1334}', '\u{1335}', '\u{1336}', '\u{1337}', '\u{1338}', '\u{1339}', '\u{133A}', '\u{133B}', '\u{133C}', '\u{133D}', '\u{133E}', '\u{133F}', '\u{1340}', '\u{1341}', '\u{1342}', '\u{1343}', '\u{1344}', '\u{1345}', '\u{1346}', '\u{1347}', '\u{1348}', '\u{1349}', '\u{134A}', '\u{134B}', '\u{134C}', '\u{134D}', '\u{134E}', '\u{134F}', '\u{1350}', '\u{1351}', '\u{1352}', '\u{1353}', '\u{1354}', '\u{1355}', '\u{1356}', '\u{1357}', '\u{1358}', '\u{1359}', '\u{135A}', '\u{1380}', '\u{1381}', '\u{1382}', '\u{1383}', '\u{1384}', '\u{1385}', '\u{1386}', '\u{1387}', '\u{1388}', '\u{1389}', '\u{138A}', '\u{138B}', '\u{138C}', '\u{138D}', '\u{138E}', '\u{138F}', '\u{13A0}', '\u{13A1}', '\u{13A2}', '\u{13A3}', '\u{13A4}', '\u{13A5}', '\u{13A6}', '\u{13A7}', '\u{13A8}', '\u{13A9}', '\u{13AA}', '\u{13AB}', '\u{13AC}', '\u{13AD}', '\u{13AE}', '\u{13AF}', '\u{13B0}', '\u{13B1}', '\u{13B2}', '\u{13B3}', '\u{13B4}', '\u{13B5}', '\u{13B6}', '\u{13B7}', '\u{13B8}', '\u{13B9}', '\u{13BA}', '\u{13BB}', '\u{13BC}', '\u{13BD}', '\u{13BE}', '\u{13BF}', '\u{13C0}', '\u{13C1}', '\u{13C2}', '\u{13C3}', '\u{13C4}', '\u{13C5}', '\u{13C6}', '\u{13C7}', '\u{13C8}', '\u{13C9}', '\u{13CA}', '\u{13CB}', '\u{13CC}', '\u{13CD}', '\u{13CE}', '\u{13CF}', '\u{13D0}', '\u{13D1}', '\u{13D2}', '\u{13D3}', '\u{13D4}', '\u{13D5}', '\u{13D6}', '\u{13D7}', '\u{13D8}', '\u{13D9}', '\u{13DA}', '\u{13DB}', '\u{13DC}', '\u{13DD}', '\u{13DE}', '\u{13DF}', '\u{13E0}', '\u{13E1}', '\u{13E2}', '\u{13E3}', '\u{13E4}', '\u{13E5}', '\u{13E6}', '\u{13E7}', '\u{13E8}', '\u{13E9}', '\u{13EA}', '\u{13EB}', '\u{13EC}', '\u{13ED}', '\u{13EE}', '\u{13EF}', '\u{13F0}', '\u{13F1}', '\u{13F2}', '\u{13F3}', '\u{13F4}', '\u{1401}', '\u{1402}', '\u{1403}', '\u{1404}', '\u{1405}', '\u{1406}', '\u{1407}', '\u{1408}', '\u{1409}', '\u{140A}', '\u{140B}', '\u{140C}', '\u{140D}', '\u{140E}', '\u{140F}', '\u{1410}', '\u{1411}', '\u{1412}', '\u{1413}', '\u{1414}', '\u{1415}', '\u{1416}', '\u{1417}', '\u{1418}', '\u{1419}', '\u{141A}', '\u{141B}', '\u{141C}', '\u{141D}', '\u{141E}', '\u{141F}', '\u{1420}', '\u{1421}', '\u{1422}', '\u{1423}', '\u{1424}', '\u{1425}', '\u{1426}', '\u{1427}', '\u{1428}', '\u{1429}', '\u{142A}', '\u{142B}', '\u{142C}', '\u{142D}', '\u{142E}', '\u{142F}', '\u{1430}', '\u{1431}', '\u{1432}', '\u{1433}', '\u{1434}', '\u{1435}', '\u{1436}', '\u{1437}', '\u{1438}', '\u{1439}', '\u{143A}', '\u{143B}', '\u{143C}', '\u{143D}', '\u{143E}', '\u{143F}', '\u{1440}', '\u{1441}', '\u{1442}', '\u{1443}', '\u{1444}', '\u{1445}', '\u{1446}', '\u{1447}', '\u{1448}', '\u{1449}', '\u{144A}', '\u{144B}', '\u{144C}', '\u{144D}', '\u{144E}', '\u{144F}', '\u{1450}', '\u{1451}', '\u{1452}', '\u{1453}', '\u{1454}', '\u{1455}', '\u{1456}', '\u{1457}', '\u{1458}', '\u{1459}', '\u{145A}', '\u{145B}', '\u{145C}', '\u{145D}', '\u{145E}', '\u{145F}', '\u{1460}', '\u{1461}', '\u{1462}', '\u{1463}', '\u{1464}', '\u{1465}', '\u{1466}', '\u{1467}', '\u{1468}', '\u{1469}', '\u{146A}', '\u{146B}', '\u{146C}', '\u{146D}', '\u{146E}', '\u{146F}', '\u{1470}', '\u{1471}', '\u{1472}', '\u{1473}', '\u{1474}', '\u{1475}', '\u{1476}', '\u{1477}', '\u{1478}', '\u{1479}', '\u{147A}', '\u{147B}', '\u{147C}', '\u{147D}', '\u{147E}', '\u{147F}', '\u{1480}', '\u{1481}', '\u{1482}', '\u{1483}', '\u{1484}', '\u{1485}', '\u{1486}', '\u{1487}', '\u{1488}', '\u{1489}', '\u{148A}', '\u{148B}', '\u{148C}', '\u{148D}', '\u{148E}', '\u{148F}', '\u{1490}', '\u{1491}', '\u{1492}', '\u{1493}', '\u{1494}', '\u{1495}', '\u{1496}', '\u{1497}', '\u{1498}', '\u{1499}', '\u{149A}', '\u{149B}', '\u{149C}', '\u{149D}', '\u{149E}', '\u{149F}', '\u{14A0}', '\u{14A1}', '\u{14A2}', '\u{14A3}', '\u{14A4}', '\u{14A5}', '\u{14A6}', '\u{14A7}', '\u{14A8}', '\u{14A9}', '\u{14AA}', '\u{14AB}', '\u{14AC}', '\u{14AD}', '\u{14AE}', '\u{14AF}', '\u{14B0}', '\u{14B1}', '\u{14B2}', '\u{14B3}', '\u{14B4}', '\u{14B5}', '\u{14B6}', '\u{14B7}', '\u{14B8}', '\u{14B9}', '\u{14BA}', '\u{14BB}', '\u{14BC}', '\u{14BD}', '\u{14BE}', '\u{14BF}', '\u{14C0}', '\u{14C1}', '\u{14C2}', '\u{14C3}', '\u{14C4}', '\u{14C5}', '\u{14C6}', '\u{14C7}', '\u{14C8}', '\u{14C9}', '\u{14CA}', '\u{14CB}', '\u{14CC}', '\u{14CD}', '\u{14CE}', '\u{14CF}', '\u{14D0}', '\u{14D1}', '\u{14D2}', '\u{14D3}', '\u{14D4}', '\u{14D5}', '\u{14D6}', '\u{14D7}', '\u{14D8}', '\u{14D9}', '\u{14DA}', '\u{14DB}', '\u{14DC}', '\u{14DD}', '\u{14DE}', '\u{14DF}', '\u{14E0}', '\u{14E1}', '\u{14E2}', '\u{14E3}', '\u{14E4}', '\u{14E5}', '\u{14E6}', '\u{14E7}', '\u{14E8}', '\u{14E9}', '\u{14EA}', '\u{14EB}', '\u{14EC}', '\u{14ED}', '\u{14EE}', '\u{14EF}', '\u{14F0}', '\u{14F1}', '\u{14F2}', '\u{14F3}', '\u{14F4}', '\u{14F5}', '\u{14F6}', '\u{14F7}', '\u{14F8}', '\u{14F9}', '\u{14FA}', '\u{14FB}', '\u{14FC}', '\u{14FD}', '\u{14FE}', '\u{14FF}', '\u{1500}', '\u{1501}', '\u{1502}', '\u{1503}', '\u{1504}', '\u{1505}', '\u{1506}', '\u{1507}', '\u{1508}', '\u{1509}', '\u{150A}', '\u{150B}', '\u{150C}', '\u{150D}', '\u{150E}', '\u{150F}', '\u{1510}', '\u{1511}', '\u{1512}', '\u{1513}', '\u{1514}', '\u{1515}', '\u{1516}', '\u{1517}', '\u{1518}', '\u{1519}', '\u{151A}', '\u{151B}', '\u{151C}', '\u{151D}', '\u{151E}', '\u{151F}', '\u{1520}', '\u{1521}', '\u{1522}', '\u{1523}', '\u{1524}', '\u{1525}', '\u{1526}', '\u{1527}', '\u{1528}', '\u{1529}', '\u{152A}', '\u{152B}', '\u{152C}', '\u{152D}', '\u{152E}', '\u{152F}', '\u{1530}', '\u{1531}', '\u{1532}', '\u{1533}', '\u{1534}', '\u{1535}', '\u{1536}', '\u{1537}', '\u{1538}', '\u{1539}', '\u{153A}', '\u{153B}', '\u{153C}', '\u{153D}', '\u{153E}', '\u{153F}', '\u{1540}', '\u{1541}', '\u{1542}', '\u{1543}', '\u{1544}', '\u{1545}', '\u{1546}', '\u{1547}', '\u{1548}', '\u{1549}', '\u{154A}', '\u{154B}', '\u{154C}', '\u{154D}', '\u{154E}', '\u{154F}', '\u{1550}', '\u{1551}', '\u{1552}', '\u{1553}', '\u{1554}', '\u{1555}', '\u{1556}', '\u{1557}', '\u{1558}', '\u{1559}', '\u{155A}', '\u{155B}', '\u{155C}', '\u{155D}', '\u{155E}', '\u{155F}', '\u{1560}', '\u{1561}', '\u{1562}', '\u{1563}', '\u{1564}', '\u{1565}', '\u{1566}', '\u{1567}', '\u{1568}', '\u{1569}', '\u{156A}', '\u{156B}', '\u{156C}', '\u{156D}', '\u{156E}', '\u{156F}', '\u{1570}', '\u{1571}', '\u{1572}', '\u{1573}', '\u{1574}', '\u{1575}', '\u{1576}', '\u{1577}', '\u{1578}', '\u{1579}', '\u{157A}', '\u{157B}', '\u{157C}', '\u{157D}', '\u{157E}', '\u{157F}', '\u{1580}', '\u{1581}', '\u{1582}', '\u{1583}', '\u{1584}', '\u{1585}', '\u{1586}', '\u{1587}', '\u{1588}', '\u{1589}', '\u{158A}', '\u{158B}', '\u{158C}', '\u{158D}', '\u{158E}', '\u{158F}', '\u{1590}', '\u{1591}', '\u{1592}', '\u{1593}', '\u{1594}', '\u{1595}', '\u{1596}', '\u{1597}', '\u{1598}', '\u{1599}', '\u{159A}', '\u{159B}', '\u{159C}', '\u{159D}', '\u{159E}', '\u{159F}', '\u{15A0}', '\u{15A1}', '\u{15A2}', '\u{15A3}', '\u{15A4}', '\u{15A5}', '\u{15A6}', '\u{15A7}', '\u{15A8}', '\u{15A9}', '\u{15AA}', '\u{15AB}', '\u{15AC}', '\u{15AD}', '\u{15AE}', '\u{15AF}', '\u{15B0}', '\u{15B1}', '\u{15B2}', '\u{15B3}', '\u{15B4}', '\u{15B5}', '\u{15B6}', '\u{15B7}', '\u{15B8}', '\u{15B9}', '\u{15BA}', '\u{15BB}', '\u{15BC}', '\u{15BD}', '\u{15BE}', '\u{15BF}', '\u{15C0}', '\u{15C1}', '\u{15C2}', '\u{15C3}', '\u{15C4}', '\u{15C5}', '\u{15C6}', '\u{15C7}', '\u{15C8}', '\u{15C9}', '\u{15CA}', '\u{15CB}', '\u{15CC}', '\u{15CD}', '\u{15CE}', '\u{15CF}', '\u{15D0}', '\u{15D1}', '\u{15D2}', '\u{15D3}', '\u{15D4}', '\u{15D5}', '\u{15D6}', '\u{15D7}', '\u{15D8}', '\u{15D9}', '\u{15DA}', '\u{15DB}', '\u{15DC}', '\u{15DD}', '\u{15DE}', '\u{15DF}', '\u{15E0}', '\u{15E1}', '\u{15E2}', '\u{15E3}', '\u{15E4}', '\u{15E5}', '\u{15E6}', '\u{15E7}', '\u{15E8}', '\u{15E9}', '\u{15EA}', '\u{15EB}', '\u{15EC}', '\u{15ED}', '\u{15EE}', '\u{15EF}', '\u{15F0}', '\u{15F1}', '\u{15F2}', '\u{15F3}', '\u{15F4}', '\u{15F5}', '\u{15F6}', '\u{15F7}', '\u{15F8}', '\u{15F9}', '\u{15FA}', '\u{15FB}', '\u{15FC}', '\u{15FD}', '\u{15FE}', '\u{15FF}', '\u{1600}', '\u{1601}', '\u{1602}', '\u{1603}', '\u{1604}', '\u{1605}', '\u{1606}', '\u{1607}', '\u{1608}', '\u{1609}', '\u{160A}', '\u{160B}', '\u{160C}', '\u{160D}', '\u{160E}', '\u{160F}', '\u{1610}', '\u{1611}', '\u{1612}', '\u{1613}', '\u{1614}', '\u{1615}', '\u{1616}', '\u{1617}', '\u{1618}', '\u{1619}', '\u{161A}', '\u{161B}', '\u{161C}', '\u{161D}', '\u{161E}', '\u{161F}', '\u{1620}', '\u{1621}', '\u{1622}', '\u{1623}', '\u{1624}', '\u{1625}', '\u{1626}', '\u{1627}', '\u{1628}', '\u{1629}', '\u{162A}', '\u{162B}', '\u{162C}', '\u{162D}', '\u{162E}', '\u{162F}', '\u{1630}', '\u{1631}', '\u{1632}', '\u{1633}', '\u{1634}', '\u{1635}', '\u{1636}', '\u{1637}', '\u{1638}', '\u{1639}', '\u{163A}', '\u{163B}', '\u{163C}', '\u{163D}', '\u{163E}', '\u{163F}', '\u{1640}', '\u{1641}', '\u{1642}', '\u{1643}', '\u{1644}', '\u{1645}', '\u{1646}', '\u{1647}', '\u{1648}', '\u{1649}', '\u{164A}', '\u{164B}', '\u{164C}', '\u{164D}', '\u{164E}', '\u{164F}', '\u{1650}', '\u{1651}', '\u{1652}', '\u{1653}', '\u{1654}', '\u{1655}', '\u{1656}', '\u{1657}', '\u{1658}', '\u{1659}', '\u{165A}', '\u{165B}', '\u{165C}', '\u{165D}', '\u{165E}', '\u{165F}', '\u{1660}', '\u{1661}', '\u{1662}', '\u{1663}', '\u{1664}', '\u{1665}', '\u{1666}', '\u{1667}', '\u{1668}', '\u{1669}', '\u{166A}', '\u{166B}', '\u{166C}', '\u{166F}', '\u{1670}', '\u{1671}', '\u{1672}', '\u{1673}', '\u{1674}', '\u{1675}', '\u{1676}', '\u{1681}', '\u{1682}', '\u{1683}', '\u{1684}', '\u{1685}', '\u{1686}', '\u{1687}', '\u{1688}', '\u{1689}', '\u{168A}', '\u{168B}', '\u{168C}', '\u{168D}', '\u{168E}', '\u{168F}', '\u{1690}', '\u{1691}', '\u{1692}', '\u{1693}', '\u{1694}', '\u{1695}', '\u{1696}', '\u{1697}', '\u{1698}', '\u{1699}', '\u{169A}', '\u{16A0}', '\u{16A1}', '\u{16A2}', '\u{16A3}', '\u{16A4}', '\u{16A5}', '\u{16A6}', '\u{16A7}', '\u{16A8}', '\u{16A9}', '\u{16AA}', '\u{16AB}', '\u{16AC}', '\u{16AD}', '\u{16AE}', '\u{16AF}', '\u{16B0}', '\u{16B1}', '\u{16B2}', '\u{16B3}', '\u{16B4}', '\u{16B5}', '\u{16B6}', '\u{16B7}', '\u{16B8}', '\u{16B9}', '\u{16BA}', '\u{16BB}', '\u{16BC}', '\u{16BD}', '\u{16BE}', '\u{16BF}', '\u{16C0}', '\u{16C1}', '\u{16C2}', '\u{16C3}', '\u{16C4}', '\u{16C5}', '\u{16C6}', '\u{16C7}', '\u{16C8}', '\u{16C9}', '\u{16CA}', '\u{16CB}', '\u{16CC}', '\u{16CD}', '\u{16CE}', '\u{16CF}', '\u{16D0}', '\u{16D1}', '\u{16D2}', '\u{16D3}', '\u{16D4}', '\u{16D5}', '\u{16D6}', '\u{16D7}', '\u{16D8}', '\u{16D9}', '\u{16DA}', '\u{16DB}', '\u{16DC}', '\u{16DD}', '\u{16DE}', '\u{16DF}', '\u{16E0}', '\u{16E1}', '\u{16E2}', '\u{16E3}', '\u{16E4}', '\u{16E5}', '\u{16E6}', '\u{16E7}', '\u{16E8}', '\u{16E9}', '\u{16EA}', '\u{1700}', '\u{1701}', '\u{1702}', '\u{1703}', '\u{1704}', '\u{1705}', '\u{1706}', '\u{1707}', '\u{1708}', '\u{1709}', '\u{170A}', '\u{170B}', '\u{170C}', '\u{170E}', '\u{170F}', '\u{1710}', '\u{1711}', '\u{1720}', '\u{1721}', '\u{1722}', '\u{1723}', '\u{1724}', '\u{1725}', '\u{1726}', '\u{1727}', '\u{1728}', '\u{1729}', '\u{172A}', '\u{172B}', '\u{172C}', '\u{172D}', '\u{172E}', '\u{172F}', '\u{1730}', '\u{1731}', '\u{1740}', '\u{1741}', '\u{1742}', '\u{1743}', '\u{1744}', '\u{1745}', '\u{1746}', '\u{1747}', '\u{1748}', '\u{1749}', '\u{174A}', '\u{174B}', '\u{174C}', '\u{174D}', '\u{174E}', '\u{174F}', '\u{1750}', '\u{1751}', '\u{1760}', '\u{1761}', '\u{1762}', '\u{1763}', '\u{1764}', '\u{1765}', '\u{1766}', '\u{1767}', '\u{1768}', '\u{1769}', '\u{176A}', '\u{176B}', '\u{176C}', '\u{176E}', '\u{176F}', '\u{1770}', '\u{1780}', '\u{1781}', '\u{1782}', '\u{1783}', '\u{1784}', '\u{1785}', '\u{1786}', '\u{1787}', '\u{1788}', '\u{1789}', '\u{178A}', '\u{178B}', '\u{178C}', '\u{178D}', '\u{178E}', '\u{178F}', '\u{1790}', '\u{1791}', '\u{1792}', '\u{1793}', '\u{1794}', '\u{1795}', '\u{1796}', '\u{1797}', '\u{1798}', '\u{1799}', '\u{179A}', '\u{179B}', '\u{179C}', '\u{179D}', '\u{179E}', '\u{179F}', '\u{17A0}', '\u{17A1}', '\u{17A2}', '\u{17A3}', '\u{17A4}', '\u{17A5}', '\u{17A6}', '\u{17A7}', '\u{17A8}', '\u{17A9}', '\u{17AA}', '\u{17AB}', '\u{17AC}', '\u{17AD}', '\u{17AE}', '\u{17AF}', '\u{17B0}', '\u{17B1}', '\u{17B2}', '\u{17B3}', '\u{17DC}', '\u{1820}', '\u{1821}', '\u{1822}', '\u{1823}', '\u{1824}', '\u{1825}', '\u{1826}', '\u{1827}', '\u{1828}', '\u{1829}', '\u{182A}', '\u{182B}', '\u{182C}', '\u{182D}', '\u{182E}', '\u{182F}', '\u{1830}', '\u{1831}', '\u{1832}', '\u{1833}', '\u{1834}', '\u{1835}', '\u{1836}', '\u{1837}', '\u{1838}', '\u{1839}', '\u{183A}', '\u{183B}', '\u{183C}', '\u{183D}', '\u{183E}', '\u{183F}', '\u{1840}', '\u{1841}', '\u{1842}', '\u{1844}', '\u{1845}', '\u{1846}', '\u{1847}', '\u{1848}', '\u{1849}', '\u{184A}', '\u{184B}', '\u{184C}', '\u{184D}', '\u{184E}', '\u{184F}', '\u{1850}', '\u{1851}', '\u{1852}', '\u{1853}', '\u{1854}', '\u{1855}', '\u{1856}', '\u{1857}', '\u{1858}', '\u{1859}', '\u{185A}', '\u{185B}', '\u{185C}', '\u{185D}', '\u{185E}', '\u{185F}', '\u{1860}', '\u{1861}', '\u{1862}', '\u{1863}', '\u{1864}', '\u{1865}', '\u{1866}', '\u{1867}', '\u{1868}', '\u{1869}', '\u{186A}', '\u{186B}', '\u{186C}', '\u{186D}', '\u{186E}', '\u{186F}', '\u{1870}', '\u{1871}', '\u{1872}', '\u{1873}', '\u{1874}', '\u{1875}', '\u{1876}', '\u{1877}', '\u{1880}', '\u{1881}', '\u{1882}', '\u{1883}', '\u{1884}', '\u{1885}', '\u{1886}', '\u{1887}', '\u{1888}', '\u{1889}', '\u{188A}', '\u{188B}', '\u{188C}', '\u{188D}', '\u{188E}', '\u{188F}', '\u{1890}', '\u{1891}', '\u{1892}', '\u{1893}', '\u{1894}', '\u{1895}', '\u{1896}', '\u{1897}', '\u{1898}', '\u{1899}', '\u{189A}', '\u{189B}', '\u{189C}', '\u{189D}', '\u{189E}', '\u{189F}', '\u{18A0}', '\u{18A1}', '\u{18A2}', '\u{18A3}', '\u{18A4}', '\u{18A5}', '\u{18A6}', '\u{18A7}', '\u{18A8}', '\u{18AA}', '\u{1900}', '\u{1901}', '\u{1902}', '\u{1903}', '\u{1904}', '\u{1905}', '\u{1906}', '\u{1907}', '\u{1908}', '\u{1909}', '\u{190A}', '\u{190B}', '\u{190C}', '\u{190D}', '\u{190E}', '\u{190F}', '\u{1910}', '\u{1911}', '\u{1912}', '\u{1913}', '\u{1914}', '\u{1915}', '\u{1916}', '\u{1917}', '\u{1918}', '\u{1919}', '\u{191A}', '\u{191B}', '\u{191C}', '\u{1950}', '\u{1951}', '\u{1952}', '\u{1953}', '\u{1954}', '\u{1955}', '\u{1956}', '\u{1957}', '\u{1958}', '\u{1959}', '\u{195A}', '\u{195B}', '\u{195C}', '\u{195D}', '\u{195E}', '\u{195F}', '\u{1960}', '\u{1961}', '\u{1962}', '\u{1963}', '\u{1964}', '\u{1965}', '\u{1966}', '\u{1967}', '\u{1968}', '\u{1969}', '\u{196A}', '\u{196B}', '\u{196C}', '\u{196D}', '\u{1970}', '\u{1971}', '\u{1972}', '\u{1973}', '\u{1974}', '\u{1980}', '\u{1981}', '\u{1982}', '\u{1983}', '\u{1984}', '\u{1985}', '\u{1986}', '\u{1987}', '\u{1988}', '\u{1989}', '\u{198A}', '\u{198B}', '\u{198C}', '\u{198D}', '\u{198E}', '\u{198F}', '\u{1990}', '\u{1991}', '\u{1992}', '\u{1993}', '\u{1994}', '\u{1995}', '\u{1996}', '\u{1997}', '\u{1998}', '\u{1999}', '\u{199A}', '\u{199B}', '\u{199C}', '\u{199D}', '\u{199E}', '\u{199F}', '\u{19A0}', '\u{19A1}', '\u{19A2}', '\u{19A3}', '\u{19A4}', '\u{19A5}', '\u{19A6}', '\u{19A7}', '\u{19A8}', '\u{19A9}', '\u{19C1}', '\u{19C2}', '\u{19C3}', '\u{19C4}', '\u{19C5}', '\u{19C6}', '\u{19C7}', '\u{1A00}', '\u{1A01}', '\u{1A02}', '\u{1A03}', '\u{1A04}', '\u{1A05}', '\u{1A06}', '\u{1A07}', '\u{1A08}', '\u{1A09}', '\u{1A0A}', '\u{1A0B}', '\u{1A0C}', '\u{1A0D}', '\u{1A0E}', '\u{1A0F}', '\u{1A10}', '\u{1A11}', '\u{1A12}', '\u{1A13}', '\u{1A14}', '\u{1A15}', '\u{1A16}', '\u{1B05}', '\u{1B06}', '\u{1B07}', '\u{1B08}', '\u{1B09}', '\u{1B0A}', '\u{1B0B}', '\u{1B0C}', '\u{1B0D}', '\u{1B0E}', '\u{1B0F}', '\u{1B10}', '\u{1B11}', '\u{1B12}', '\u{1B13}', '\u{1B14}', '\u{1B15}', '\u{1B16}', '\u{1B17}', '\u{1B18}', '\u{1B19}', '\u{1B1A}', '\u{1B1B}', '\u{1B1C}', '\u{1B1D}', '\u{1B1E}', '\u{1B1F}', '\u{1B20}', '\u{1B21}', '\u{1B22}', '\u{1B23}', '\u{1B24}', '\u{1B25}', '\u{1B26}', '\u{1B27}', '\u{1B28}', '\u{1B29}', '\u{1B2A}', '\u{1B2B}', '\u{1B2C}', '\u{1B2D}', '\u{1B2E}', '\u{1B2F}', '\u{1B30}', '\u{1B31}', '\u{1B32}', '\u{1B33}', '\u{1B45}', '\u{1B46}', '\u{1B47}', '\u{1B48}', '\u{1B49}', '\u{1B4A}', '\u{1B4B}', '\u{1B83}', '\u{1B84}', '\u{1B85}', '\u{1B86}', '\u{1B87}', '\u{1B88}', '\u{1B89}', '\u{1B8A}', '\u{1B8B}', '\u{1B8C}', '\u{1B8D}', '\u{1B8E}', '\u{1B8F}', '\u{1B90}', '\u{1B91}', '\u{1B92}', '\u{1B93}', '\u{1B94}', '\u{1B95}', '\u{1B96}', '\u{1B97}', '\u{1B98}', '\u{1B99}', '\u{1B9A}', '\u{1B9B}', '\u{1B9C}', '\u{1B9D}', '\u{1B9E}', '\u{1B9F}', '\u{1BA0}', '\u{1BAE}', '\u{1BAF}', '\u{1C00}', '\u{1C01}', '\u{1C02}', '\u{1C03}', '\u{1C04}', '\u{1C05}', '\u{1C06}', '\u{1C07}', '\u{1C08}', '\u{1C09}', '\u{1C0A}', '\u{1C0B}', '\u{1C0C}', '\u{1C0D}', '\u{1C0E}', '\u{1C0F}', '\u{1C10}', '\u{1C11}', '\u{1C12}', '\u{1C13}', '\u{1C14}', '\u{1C15}', '\u{1C16}', '\u{1C17}', '\u{1C18}', '\u{1C19}', '\u{1C1A}', '\u{1C1B}', '\u{1C1C}', '\u{1C1D}', '\u{1C1E}', '\u{1C1F}', '\u{1C20}', '\u{1C21}', '\u{1C22}', '\u{1C23}', '\u{1C4D}', '\u{1C4E}', '\u{1C4F}', '\u{1C5A}', '\u{1C5B}', '\u{1C5C}', '\u{1C5D}', '\u{1C5E}', '\u{1C5F}', '\u{1C60}', '\u{1C61}', '\u{1C62}', '\u{1C63}', '\u{1C64}', '\u{1C65}', '\u{1C66}', '\u{1C67}', '\u{1C68}', '\u{1C69}', '\u{1C6A}', '\u{1C6B}', '\u{1C6C}', '\u{1C6D}', '\u{1C6E}', '\u{1C6F}', '\u{1C70}', '\u{1C71}', '\u{1C72}', '\u{1C73}', '\u{1C74}', '\u{1C75}', '\u{1C76}', '\u{1C77}', '\u{2135}', '\u{2136}', '\u{2137}', '\u{2138}', '\u{2D30}', '\u{2D31}', '\u{2D32}', '\u{2D33}', '\u{2D34}', '\u{2D35}', '\u{2D36}', '\u{2D37}', '\u{2D38}', '\u{2D39}', '\u{2D3A}', '\u{2D3B}', '\u{2D3C}', '\u{2D3D}', '\u{2D3E}', '\u{2D3F}', '\u{2D40}', '\u{2D41}', '\u{2D42}', '\u{2D43}', '\u{2D44}', '\u{2D45}', '\u{2D46}', '\u{2D47}', '\u{2D48}', '\u{2D49}', '\u{2D4A}', '\u{2D4B}', '\u{2D4C}', '\u{2D4D}', '\u{2D4E}', '\u{2D4F}', '\u{2D50}', '\u{2D51}', '\u{2D52}', '\u{2D53}', '\u{2D54}', '\u{2D55}', '\u{2D56}', '\u{2D57}', '\u{2D58}', '\u{2D59}', '\u{2D5A}', '\u{2D5B}', '\u{2D5C}', '\u{2D5D}', '\u{2D5E}', '\u{2D5F}', '\u{2D60}', '\u{2D61}', '\u{2D62}', '\u{2D63}', '\u{2D64}', '\u{2D65}', '\u{2D80}', '\u{2D81}', '\u{2D82}', '\u{2D83}', '\u{2D84}', '\u{2D85}', '\u{2D86}', '\u{2D87}', '\u{2D88}', '\u{2D89}', '\u{2D8A}', '\u{2D8B}', '\u{2D8C}', '\u{2D8D}', '\u{2D8E}', '\u{2D8F}', '\u{2D90}', '\u{2D91}', '\u{2D92}', '\u{2D93}', '\u{2D94}', '\u{2D95}', '\u{2D96}', '\u{2DA0}', '\u{2DA1}', '\u{2DA2}', '\u{2DA3}', '\u{2DA4}', '\u{2DA5}', '\u{2DA6}', '\u{2DA8}', '\u{2DA9}', '\u{2DAA}', '\u{2DAB}', '\u{2DAC}', '\u{2DAD}', '\u{2DAE}', '\u{2DB0}', '\u{2DB1}', '\u{2DB2}', '\u{2DB3}', '\u{2DB4}', '\u{2DB5}', '\u{2DB6}', '\u{2DB8}', '\u{2DB9}', '\u{2DBA}', '\u{2DBB}', '\u{2DBC}', '\u{2DBD}', '\u{2DBE}', '\u{2DC0}', '\u{2DC1}', '\u{2DC2}', '\u{2DC3}', '\u{2DC4}', '\u{2DC5}', '\u{2DC6}', '\u{2DC8}', '\u{2DC9}', '\u{2DCA}', '\u{2DCB}', '\u{2DCC}', '\u{2DCD}', '\u{2DCE}', '\u{2DD0}', '\u{2DD1}', '\u{2DD2}', '\u{2DD3}', '\u{2DD4}', '\u{2DD5}', '\u{2DD6}', '\u{2DD8}', '\u{2DD9}', '\u{2DDA}', '\u{2DDB}', '\u{2DDC}', '\u{2DDD}', '\u{2DDE}', '\u{3006}', '\u{303C}', '\u{3041}', '\u{3042}', '\u{3043}', '\u{3044}', '\u{3045}', '\u{3046}', '\u{3047}', '\u{3048}', '\u{3049}', '\u{304A}', '\u{304B}', '\u{304C}', '\u{304D}', '\u{304E}', '\u{304F}', '\u{3050}', '\u{3051}', '\u{3052}', '\u{3053}', '\u{3054}', '\u{3055}', '\u{3056}', '\u{3057}', '\u{3058}', '\u{3059}', '\u{305A}', '\u{305B}', '\u{305C}', '\u{305D}', '\u{305E}', '\u{305F}', '\u{3060}', '\u{3061}', '\u{3062}', '\u{3063}', '\u{3064}', '\u{3065}', '\u{3066}', '\u{3067}', '\u{3068}', '\u{3069}', '\u{306A}', '\u{306B}', '\u{306C}', '\u{306D}', '\u{306E}', '\u{306F}', '\u{3070}', '\u{3071}', '\u{3072}', '\u{3073}', '\u{3074}', '\u{3075}', '\u{3076}', '\u{3077}', '\u{3078}', '\u{3079}', '\u{307A}', '\u{307B}', '\u{307C}', '\u{307D}', '\u{307E}', '\u{307F}', '\u{3080}', '\u{3081}', '\u{3082}', '\u{3083}', '\u{3084}', '\u{3085}', '\u{3086}', '\u{3087}', '\u{3088}', '\u{3089}', '\u{308A}', '\u{308B}', '\u{308C}', '\u{308D}', '\u{308E}', '\u{308F}', '\u{3090}', '\u{3091}', '\u{3092}', '\u{3093}', '\u{3094}', '\u{3095}', '\u{3096}', '\u{309F}', '\u{30A1}', '\u{30A2}', '\u{30A3}', '\u{30A4}', '\u{30A5}', '\u{30A6}', '\u{30A7}', '\u{30A8}', '\u{30A9}', '\u{30AA}', '\u{30AB}', '\u{30AC}', '\u{30AD}', '\u{30AE}', '\u{30AF}', '\u{30B0}', '\u{30B1}', '\u{30B2}', '\u{30B3}', '\u{30B4}', '\u{30B5}', '\u{30B6}', '\u{30B7}', '\u{30B8}', '\u{30B9}', '\u{30BA}', '\u{30BB}', '\u{30BC}', '\u{30BD}', '\u{30BE}', '\u{30BF}', '\u{30C0}', '\u{30C1}', '\u{30C2}', '\u{30C3}', '\u{30C4}', '\u{30C5}', '\u{30C6}', '\u{30C7}', '\u{30C8}', '\u{30C9}', '\u{30CA}', '\u{30CB}', '\u{30CC}', '\u{30CD}', '\u{30CE}', '\u{30CF}', '\u{30D0}', '\u{30D1}', '\u{30D2}', '\u{30D3}', '\u{30D4}', '\u{30D5}', '\u{30D6}', '\u{30D7}', '\u{30D8}', '\u{30D9}', '\u{30DA}', '\u{30DB}', '\u{30DC}', '\u{30DD}', '\u{30DE}', '\u{30DF}', '\u{30E0}', '\u{30E1}', '\u{30E2}', '\u{30E3}', '\u{30E4}', '\u{30E5}', '\u{30E6}', '\u{30E7}', '\u{30E8}', '\u{30E9}', '\u{30EA}', '\u{30EB}', '\u{30EC}', '\u{30ED}', '\u{30EE}', '\u{30EF}', '\u{30F0}', '\u{30F1}', '\u{30F2}', '\u{30F3}', '\u{30F4}', '\u{30F5}', '\u{30F6}', '\u{30F7}', '\u{30F8}', '\u{30F9}', '\u{30FA}', '\u{30FF}', '\u{3105}', '\u{3106}', '\u{3107}', '\u{3108}', '\u{3109}', '\u{310A}', '\u{310B}', '\u{310C}', '\u{310D}', '\u{310E}', '\u{310F}', '\u{3110}', '\u{3111}', '\u{3112}', '\u{3113}', '\u{3114}', '\u{3115}', '\u{3116}', '\u{3117}', '\u{3118}', '\u{3119}', '\u{311A}', '\u{311B}', '\u{311C}', '\u{311D}', '\u{311E}', '\u{311F}', '\u{3120}', '\u{3121}', '\u{3122}', '\u{3123}', '\u{3124}', '\u{3125}', '\u{3126}', '\u{3127}', '\u{3128}', '\u{3129}', '\u{312A}', '\u{312B}', '\u{312C}', '\u{312D}', '\u{3131}', '\u{3132}', '\u{3133}', '\u{3134}', '\u{3135}', '\u{3136}', '\u{3137}', '\u{3138}', '\u{3139}', '\u{313A}', '\u{313B}', '\u{313C}', '\u{313D}', '\u{313E}', '\u{313F}', '\u{3140}', '\u{3141}', '\u{3142}', '\u{3143}', '\u{3144}', '\u{3145}', '\u{3146}', '\u{3147}', '\u{3148}', '\u{3149}', '\u{314A}', '\u{314B}', '\u{314C}', '\u{314D}', '\u{314E}', '\u{314F}', '\u{3150}', '\u{3151}', '\u{3152}', '\u{3153}', '\u{3154}', '\u{3155}', '\u{3156}', '\u{3157}', '\u{3158}', '\u{3159}', '\u{315A}', '\u{315B}', '\u{315C}', '\u{315D}', '\u{315E}', '\u{315F}', '\u{3160}', '\u{3161}', '\u{3162}', '\u{3163}', '\u{3164}', '\u{3165}', '\u{3166}', '\u{3167}', '\u{3168}', '\u{3169}', '\u{316A}', '\u{316B}', '\u{316C}', '\u{316D}', '\u{316E}', '\u{316F}', '\u{3170}', '\u{3171}', '\u{3172}', '\u{3173}', '\u{3174}', '\u{3175}', '\u{3176}', '\u{3177}', '\u{3178}', '\u{3179}', '\u{317A}', '\u{317B}', '\u{317C}', '\u{317D}', '\u{317E}', '\u{317F}', '\u{3180}', '\u{3181}', '\u{3182}', '\u{3183}', '\u{3184}', '\u{3185}', '\u{3186}', '\u{3187}', '\u{3188}', '\u{3189}', '\u{318A}', '\u{318B}', '\u{318C}', '\u{318D}', '\u{318E}', '\u{31A0}', '\u{31A1}', '\u{31A2}', '\u{31A3}', '\u{31A4}', '\u{31A5}', '\u{31A6}', '\u{31A7}', '\u{31A8}', '\u{31A9}', '\u{31AA}', '\u{31AB}', '\u{31AC}', '\u{31AD}', '\u{31AE}', '\u{31AF}', '\u{31B0}', '\u{31B1}', '\u{31B2}', '\u{31B3}', '\u{31B4}', '\u{31B5}', '\u{31B6}', '\u{31B7}', '\u{31F0}', '\u{31F1}', '\u{31F2}', '\u{31F3}', '\u{31F4}', '\u{31F5}', '\u{31F6}', '\u{31F7}', '\u{31F8}', '\u{31F9}', '\u{31FA}', '\u{31FB}', '\u{31FC}', '\u{31FD}', '\u{31FE}', '\u{31FF}', '\u{3400}', '\u{4DB5}', '\u{4E00}', '\u{9FC3}', '\u{A000}', '\u{A001}', '\u{A002}', '\u{A003}', '\u{A004}', '\u{A005}', '\u{A006}', '\u{A007}', '\u{A008}', '\u{A009}', '\u{A00A}', '\u{A00B}', '\u{A00C}', '\u{A00D}', '\u{A00E}', '\u{A00F}', '\u{A010}', '\u{A011}', '\u{A012}', '\u{A013}', '\u{A014}', '\u{A016}', '\u{A017}', '\u{A018}', '\u{A019}', '\u{A01A}', '\u{A01B}', '\u{A01C}', '\u{A01D}', '\u{A01E}', '\u{A01F}', '\u{A020}', '\u{A021}', '\u{A022}', '\u{A023}', '\u{A024}', '\u{A025}', '\u{A026}', '\u{A027}', '\u{A028}', '\u{A029}', '\u{A02A}', '\u{A02B}', '\u{A02C}', '\u{A02D}', '\u{A02E}', '\u{A02F}', '\u{A030}', '\u{A031}', '\u{A032}', '\u{A033}', '\u{A034}', '\u{A035}', '\u{A036}', '\u{A037}', '\u{A038}', '\u{A039}', '\u{A03A}', '\u{A03B}', '\u{A03C}', '\u{A03D}', '\u{A03E}', '\u{A03F}', '\u{A040}', '\u{A041}', '\u{A042}', '\u{A043}', '\u{A044}', '\u{A045}', '\u{A046}', '\u{A047}', '\u{A048}', '\u{A049}', '\u{A04A}', '\u{A04B}', '\u{A04C}', '\u{A04D}', '\u{A04E}', '\u{A04F}', '\u{A050}', '\u{A051}', '\u{A052}', '\u{A053}', '\u{A054}', '\u{A055}', '\u{A056}', '\u{A057}', '\u{A058}', '\u{A059}', '\u{A05A}', '\u{A05B}', '\u{A05C}', '\u{A05D}', '\u{A05E}', '\u{A05F}', '\u{A060}', '\u{A061}', '\u{A062}', '\u{A063}', '\u{A064}', '\u{A065}', '\u{A066}', '\u{A067}', '\u{A068}', '\u{A069}', '\u{A06A}', '\u{A06B}', '\u{A06C}', '\u{A06D}', '\u{A06E}', '\u{A06F}', '\u{A070}', '\u{A071}', '\u{A072}', '\u{A073}', '\u{A074}', '\u{A075}', '\u{A076}', '\u{A077}', '\u{A078}', '\u{A079}', '\u{A07A}', '\u{A07B}', '\u{A07C}', '\u{A07D}', '\u{A07E}', '\u{A07F}', '\u{A080}', '\u{A081}', '\u{A082}', '\u{A083}', '\u{A084}', '\u{A085}', '\u{A086}', '\u{A087}', '\u{A088}', '\u{A089}', '\u{A08A}', '\u{A08B}', '\u{A08C}', '\u{A08D}', '\u{A08E}', '\u{A08F}', '\u{A090}', '\u{A091}', '\u{A092}', '\u{A093}', '\u{A094}', '\u{A095}', '\u{A096}', '\u{A097}', '\u{A098}', '\u{A099}', '\u{A09A}', '\u{A09B}', '\u{A09C}', '\u{A09D}', '\u{A09E}', '\u{A09F}', '\u{A0A0}', '\u{A0A1}', '\u{A0A2}', '\u{A0A3}', '\u{A0A4}', '\u{A0A5}', '\u{A0A6}', '\u{A0A7}', '\u{A0A8}', '\u{A0A9}', '\u{A0AA}', '\u{A0AB}', '\u{A0AC}', '\u{A0AD}', '\u{A0AE}', '\u{A0AF}', '\u{A0B0}', '\u{A0B1}', '\u{A0B2}', '\u{A0B3}', '\u{A0B4}', '\u{A0B5}', '\u{A0B6}', '\u{A0B7}', '\u{A0B8}', '\u{A0B9}', '\u{A0BA}', '\u{A0BB}', '\u{A0BC}', '\u{A0BD}', '\u{A0BE}', '\u{A0BF}', '\u{A0C0}', '\u{A0C1}', '\u{A0C2}', '\u{A0C3}', '\u{A0C4}', '\u{A0C5}', '\u{A0C6}', '\u{A0C7}', '\u{A0C8}', '\u{A0C9}', '\u{A0CA}', '\u{A0CB}', '\u{A0CC}', '\u{A0CD}', '\u{A0CE}', '\u{A0CF}', '\u{A0D0}', '\u{A0D1}', '\u{A0D2}', '\u{A0D3}', '\u{A0D4}', '\u{A0D5}', '\u{A0D6}', '\u{A0D7}', '\u{A0D8}', '\u{A0D9}', '\u{A0DA}', '\u{A0DB}', '\u{A0DC}', '\u{A0DD}', '\u{A0DE}', '\u{A0DF}', '\u{A0E0}', '\u{A0E1}', '\u{A0E2}', '\u{A0E3}', '\u{A0E4}', '\u{A0E5}', '\u{A0E6}', '\u{A0E7}', '\u{A0E8}', '\u{A0E9}', '\u{A0EA}', '\u{A0EB}', '\u{A0EC}', '\u{A0ED}', '\u{A0EE}', '\u{A0EF}', '\u{A0F0}', '\u{A0F1}', '\u{A0F2}', '\u{A0F3}', '\u{A0F4}', '\u{A0F5}', '\u{A0F6}', '\u{A0F7}', '\u{A0F8}', '\u{A0F9}', '\u{A0FA}', '\u{A0FB}', '\u{A0FC}', '\u{A0FD}', '\u{A0FE}', '\u{A0FF}', '\u{A100}', '\u{A101}', '\u{A102}', '\u{A103}', '\u{A104}', '\u{A105}', '\u{A106}', '\u{A107}', '\u{A108}', '\u{A109}', '\u{A10A}', '\u{A10B}', '\u{A10C}', '\u{A10D}', '\u{A10E}', '\u{A10F}', '\u{A110}', '\u{A111}', '\u{A112}', '\u{A113}', '\u{A114}', '\u{A115}', '\u{A116}', '\u{A117}', '\u{A118}', '\u{A119}', '\u{A11A}', '\u{A11B}', '\u{A11C}', '\u{A11D}', '\u{A11E}', '\u{A11F}', '\u{A120}', '\u{A121}', '\u{A122}', '\u{A123}', '\u{A124}', '\u{A125}', '\u{A126}', '\u{A127}', '\u{A128}', '\u{A129}', '\u{A12A}', '\u{A12B}', '\u{A12C}', '\u{A12D}', '\u{A12E}', '\u{A12F}', '\u{A130}', '\u{A131}', '\u{A132}', '\u{A133}', '\u{A134}', '\u{A135}', '\u{A136}', '\u{A137}', '\u{A138}', '\u{A139}', '\u{A13A}', '\u{A13B}', '\u{A13C}', '\u{A13D}', '\u{A13E}', '\u{A13F}', '\u{A140}', '\u{A141}', '\u{A142}', '\u{A143}', '\u{A144}', '\u{A145}', '\u{A146}', '\u{A147}', '\u{A148}', '\u{A149}', '\u{A14A}', '\u{A14B}', '\u{A14C}', '\u{A14D}', '\u{A14E}', '\u{A14F}', '\u{A150}', '\u{A151}', '\u{A152}', '\u{A153}', '\u{A154}', '\u{A155}', '\u{A156}', '\u{A157}', '\u{A158}', '\u{A159}', '\u{A15A}', '\u{A15B}', '\u{A15C}', '\u{A15D}', '\u{A15E}', '\u{A15F}', '\u{A160}', '\u{A161}', '\u{A162}', '\u{A163}', '\u{A164}', '\u{A165}', '\u{A166}', '\u{A167}', '\u{A168}', '\u{A169}', '\u{A16A}', '\u{A16B}', '\u{A16C}', '\u{A16D}', '\u{A16E}', '\u{A16F}', '\u{A170}', '\u{A171}', '\u{A172}', '\u{A173}', '\u{A174}', '\u{A175}', '\u{A176}', '\u{A177}', '\u{A178}', '\u{A179}', '\u{A17A}', '\u{A17B}', '\u{A17C}', '\u{A17D}', '\u{A17E}', '\u{A17F}', '\u{A180}', '\u{A181}', '\u{A182}', '\u{A183}', '\u{A184}', '\u{A185}', '\u{A186}', '\u{A187}', '\u{A188}', '\u{A189}', '\u{A18A}', '\u{A18B}', '\u{A18C}', '\u{A18D}', '\u{A18E}', '\u{A18F}', '\u{A190}', '\u{A191}', '\u{A192}', '\u{A193}', '\u{A194}', '\u{A195}', '\u{A196}', '\u{A197}', '\u{A198}', '\u{A199}', '\u{A19A}', '\u{A19B}', '\u{A19C}', '\u{A19D}', '\u{A19E}', '\u{A19F}', '\u{A1A0}', '\u{A1A1}', '\u{A1A2}', '\u{A1A3}', '\u{A1A4}', '\u{A1A5}', '\u{A1A6}', '\u{A1A7}', '\u{A1A8}', '\u{A1A9}', '\u{A1AA}', '\u{A1AB}', '\u{A1AC}', '\u{A1AD}', '\u{A1AE}', '\u{A1AF}') + } + + fn is_unicode_combining_spacing_mark(self) -> bool { + match_char_class!(self, + '\u{0903}', '\u{093E}', '\u{093F}', '\u{0940}', '\u{0949}', '\u{094A}', '\u{094B}', '\u{094C}', '\u{0982}', '\u{0983}', '\u{09BE}', '\u{09BF}', '\u{09C0}', '\u{09C7}', '\u{09C8}', '\u{09CB}', '\u{09CC}', '\u{09D7}', '\u{0A03}', '\u{0A3E}', '\u{0A3F}', '\u{0A40}', '\u{0A83}', '\u{0ABE}', '\u{0ABF}', '\u{0AC0}', '\u{0AC9}', '\u{0ACB}', '\u{0ACC}', '\u{0B02}', '\u{0B03}', '\u{0B3E}', '\u{0B40}', '\u{0B47}', '\u{0B48}', '\u{0B4B}', '\u{0B4C}', '\u{0B57}', '\u{0BBE}', '\u{0BBF}', '\u{0BC1}', '\u{0BC2}', '\u{0BC6}', '\u{0BC7}', '\u{0BC8}', '\u{0BCA}', '\u{0BCB}', '\u{0BCC}', '\u{0BD7}', '\u{0C01}', '\u{0C02}', '\u{0C03}', '\u{0C41}', '\u{0C42}', '\u{0C43}', '\u{0C44}', '\u{0C82}', '\u{0C83}', '\u{0CBE}', '\u{0CC0}', '\u{0CC1}', '\u{0CC2}', '\u{0CC3}', '\u{0CC4}', '\u{0CC7}', '\u{0CC8}', '\u{0CCA}', '\u{0CCB}', '\u{0CD5}', '\u{0CD6}', '\u{0D02}', '\u{0D03}', '\u{0D3E}', '\u{0D3F}', '\u{0D40}', '\u{0D46}', '\u{0D47}', '\u{0D48}', '\u{0D4A}', '\u{0D4B}', '\u{0D4C}', '\u{0D57}', '\u{0D82}', '\u{0D83}', '\u{0DCF}', '\u{0DD0}', '\u{0DD1}', '\u{0DD8}', '\u{0DD9}', '\u{0DDA}', '\u{0DDB}', '\u{0DDC}', '\u{0DDD}', '\u{0DDE}', '\u{0DDF}', '\u{0DF2}', '\u{0DF3}', '\u{0F3E}', '\u{0F3F}', '\u{0F7F}', '\u{102B}', '\u{102C}', '\u{1031}', '\u{1038}', '\u{103B}', '\u{103C}', '\u{1056}', '\u{1057}', '\u{1062}', '\u{1063}', '\u{1064}', '\u{1067}', '\u{1068}', '\u{1069}', '\u{106A}', '\u{106B}', '\u{106C}', '\u{106D}', '\u{1083}', '\u{1084}', '\u{1087}', '\u{1088}', '\u{1089}', '\u{108A}', '\u{108B}', '\u{108C}', '\u{108F}', '\u{17B6}', '\u{17BE}', '\u{17BF}', '\u{17C0}', '\u{17C1}', '\u{17C2}', '\u{17C3}', '\u{17C4}', '\u{17C5}', '\u{17C7}', '\u{17C8}', '\u{1923}', '\u{1924}', '\u{1925}', '\u{1926}', '\u{1929}', '\u{192A}', '\u{192B}', '\u{1930}', '\u{1931}', '\u{1933}', '\u{1934}', '\u{1935}', '\u{1936}', '\u{1937}', '\u{1938}', '\u{19B0}', '\u{19B1}', '\u{19B2}', '\u{19B3}', '\u{19B4}', '\u{19B5}', '\u{19B6}', '\u{19B7}', '\u{19B8}', '\u{19B9}', '\u{19BA}', '\u{19BB}', '\u{19BC}', '\u{19BD}', '\u{19BE}', '\u{19BF}', '\u{19C0}', '\u{19C8}', '\u{19C9}', '\u{1A19}', '\u{1A1A}', '\u{1A1B}', '\u{1B04}', '\u{1B35}', '\u{1B3B}', '\u{1B3D}', '\u{1B3E}', '\u{1B3F}', '\u{1B40}', '\u{1B41}', '\u{1B43}', '\u{1B44}', '\u{1B82}', '\u{1BA1}', '\u{1BA6}', '\u{1BA7}', '\u{1BAA}', '\u{1C24}', '\u{1C25}', '\u{1C26}', '\u{1C27}', '\u{1C28}', '\u{1C29}', '\u{1C2A}', '\u{1C2B}', '\u{1C34}', '\u{1C35}', '\u{A823}', '\u{A824}', '\u{A827}', '\u{A880}', '\u{A881}', '\u{A8B4}', '\u{A8B5}', '\u{A8B6}', '\u{A8B7}', '\u{A8B8}', '\u{A8B9}', '\u{A8BA}', '\u{A8BB}', '\u{A8BC}', '\u{A8BD}', '\u{A8BE}', '\u{A8BF}', '\u{A8C0}', '\u{A8C1}', '\u{A8C2}', '\u{A8C3}', '\u{A952}', '\u{A953}', '\u{AA2F}', '\u{AA30}', '\u{AA33}', '\u{AA34}', '\u{AA4D}') + } + + fn is_unicode_decimal_number(self) -> bool { + match_char_class!(self, + '\u{0030}', '\u{0031}', '\u{0032}', '\u{0033}', '\u{0034}', '\u{0035}', '\u{0036}', '\u{0037}', '\u{0038}', '\u{0039}', '\u{0660}', '\u{0661}', '\u{0662}', '\u{0663}', '\u{0664}', '\u{0665}', '\u{0666}', '\u{0667}', '\u{0668}', '\u{0669}', '\u{06F0}', '\u{06F1}', '\u{06F2}', '\u{06F3}', '\u{06F4}', '\u{06F5}', '\u{06F6}', '\u{06F7}', '\u{06F8}', '\u{06F9}', '\u{07C0}', '\u{07C1}', '\u{07C2}', '\u{07C3}', '\u{07C4}', '\u{07C5}', '\u{07C6}', '\u{07C7}', '\u{07C8}', '\u{07C9}', '\u{0966}', '\u{0967}', '\u{0968}', '\u{0969}', '\u{096A}', '\u{096B}', '\u{096C}', '\u{096D}', '\u{096E}', '\u{096F}', '\u{09E6}', '\u{09E7}', '\u{09E8}', '\u{09E9}', '\u{09EA}', '\u{09EB}', '\u{09EC}', '\u{09ED}', '\u{09EE}', '\u{09EF}', '\u{0A66}', '\u{0A67}', '\u{0A68}', '\u{0A69}', '\u{0A6A}', '\u{0A6B}', '\u{0A6C}', '\u{0A6D}', '\u{0A6E}', '\u{0A6F}', '\u{0AE6}', '\u{0AE7}', '\u{0AE8}', '\u{0AE9}', '\u{0AEA}', '\u{0AEB}', '\u{0AEC}', '\u{0AED}', '\u{0AEE}', '\u{0AEF}', '\u{0B66}', '\u{0B67}', '\u{0B68}', '\u{0B69}', '\u{0B6A}', '\u{0B6B}', '\u{0B6C}', '\u{0B6D}', '\u{0B6E}', '\u{0B6F}', '\u{0BE6}', '\u{0BE7}', '\u{0BE8}', '\u{0BE9}', '\u{0BEA}', '\u{0BEB}', '\u{0BEC}', '\u{0BED}', '\u{0BEE}', '\u{0BEF}', '\u{0C66}', '\u{0C67}', '\u{0C68}', '\u{0C69}', '\u{0C6A}', '\u{0C6B}', '\u{0C6C}', '\u{0C6D}', '\u{0C6E}', '\u{0C6F}', '\u{0CE6}', '\u{0CE7}', '\u{0CE8}', '\u{0CE9}', '\u{0CEA}', '\u{0CEB}', '\u{0CEC}', '\u{0CED}', '\u{0CEE}', '\u{0CEF}', '\u{0D66}', '\u{0D67}', '\u{0D68}', '\u{0D69}', '\u{0D6A}', '\u{0D6B}', '\u{0D6C}', '\u{0D6D}', '\u{0D6E}', '\u{0D6F}', '\u{0E50}', '\u{0E51}', '\u{0E52}', '\u{0E53}', '\u{0E54}', '\u{0E55}', '\u{0E56}', '\u{0E57}', '\u{0E58}', '\u{0E59}', '\u{0ED0}', '\u{0ED1}', '\u{0ED2}', '\u{0ED3}', '\u{0ED4}', '\u{0ED5}', '\u{0ED6}', '\u{0ED7}', '\u{0ED8}', '\u{0ED9}', '\u{0F20}', '\u{0F21}', '\u{0F22}', '\u{0F23}', '\u{0F24}', '\u{0F25}', '\u{0F26}', '\u{0F27}', '\u{0F28}', '\u{0F29}', '\u{1040}', '\u{1041}', '\u{1042}', '\u{1043}', '\u{1044}', '\u{1045}', '\u{1046}', '\u{1047}', '\u{1048}', '\u{1049}', '\u{1090}', '\u{1091}', '\u{1092}', '\u{1093}', '\u{1094}', '\u{1095}', '\u{1096}', '\u{1097}', '\u{1098}', '\u{1099}', '\u{17E0}', '\u{17E1}', '\u{17E2}', '\u{17E3}', '\u{17E4}', '\u{17E5}', '\u{17E6}', '\u{17E7}', '\u{17E8}', '\u{17E9}', '\u{1810}', '\u{1811}', '\u{1812}', '\u{1813}', '\u{1814}', '\u{1815}', '\u{1816}', '\u{1817}', '\u{1818}', '\u{1819}', '\u{1946}', '\u{1947}', '\u{1948}', '\u{1949}', '\u{194A}', '\u{194B}', '\u{194C}', '\u{194D}', '\u{194E}', '\u{194F}', '\u{19D0}', '\u{19D1}', '\u{19D2}', '\u{19D3}', '\u{19D4}', '\u{19D5}', '\u{19D6}', '\u{19D7}', '\u{19D8}', '\u{19D9}', '\u{1B50}', '\u{1B51}', '\u{1B52}', '\u{1B53}', '\u{1B54}', '\u{1B55}', '\u{1B56}', '\u{1B57}', '\u{1B58}', '\u{1B59}', '\u{1BB0}', '\u{1BB1}', '\u{1BB2}', '\u{1BB3}', '\u{1BB4}', '\u{1BB5}', '\u{1BB6}', '\u{1BB7}', '\u{1BB8}', '\u{1BB9}', '\u{1C40}', '\u{1C41}', '\u{1C42}', '\u{1C43}', '\u{1C44}', '\u{1C45}', '\u{1C46}', '\u{1C47}', '\u{1C48}', '\u{1C49}', '\u{1C50}', '\u{1C51}', '\u{1C52}', '\u{1C53}', '\u{1C54}', '\u{1C55}', '\u{1C56}', '\u{1C57}', '\u{1C58}', '\u{1C59}', '\u{A620}', '\u{A621}', '\u{A622}', '\u{A623}', '\u{A624}', '\u{A625}', '\u{A626}', '\u{A627}', '\u{A628}', '\u{A629}', '\u{A8D0}', '\u{A8D1}', '\u{A8D2}', '\u{A8D3}', '\u{A8D4}', '\u{A8D5}', '\u{A8D6}', '\u{A8D7}', '\u{A8D8}', '\u{A8D9}', '\u{A900}', '\u{A901}', '\u{A902}', '\u{A903}', '\u{A904}', '\u{A905}', '\u{A906}', '\u{A907}', '\u{A908}', '\u{A909}', '\u{AA50}', '\u{AA51}', '\u{AA52}', '\u{AA53}', '\u{AA54}', '\u{AA55}', '\u{AA56}', '\u{AA57}', '\u{AA58}', '\u{AA59}', '\u{FF10}', '\u{FF11}', '\u{FF12}', '\u{FF13}', '\u{FF14}', '\u{FF15}', '\u{FF16}', '\u{FF17}', '\u{FF18}', '\u{FF19}') + } + + fn is_unicode_connector_punctiation(self) -> bool { + match_char_class!(self, + '\u{005F}', '\u{203F}', '\u{2040}', '\u{2054}', '\u{FE33}', '\u{FE34}', '\u{FE4D}', '\u{FE4E}', '\u{FE4F}', '\u{FF3F}') + } + + fn is_unicode_space_separator(self) -> bool { + match_char_class!(self, + '\u{0020}', '\u{00A0}', '\u{1680}', '\u{2000}', '\u{2001}', '\u{2002}', '\u{2003}', '\u{2004}', '\u{2005}', '\u{2006}', '\u{2007}', '\u{2008}', '\u{2009}', '\u{200A}', '\u{202F}', '\u{205F}', '\u{3000}') + } + + fn is_es_identifier_start(self) -> bool { + match self { + '$' | '_' | '\\' => true, + c if c.is_unicode_letter() => true, + _ => false + } + } + + // see section 7.6 + fn is_es_identifier_part(self) -> bool { + match self { + '\u{200C}' | '\u{200D}' => true, + c if c.is_es_identifier_start() => true, + c if c.is_unicode_combining_spacing_mark() => true, + c if c.is_unicode_nonspacing_mark() => true, + c if c.is_unicode_decimal_number() => true, + c if c.is_unicode_connector_punctiation() => true, + _ => false + } + } + + fn is_es_whitespace(self) -> bool { + match self { + '\t' | '\u{000B}' | '\u{000C}' | '\u{0020}' | '\u{00A0}' | '\u{FEFF}' => true, + c => c.is_unicode_space_separator() + } + } + + fn is_es_line_terminator(self) -> bool { + match self { + '\n' | '\r' | '\u{2028}' | '\u{2029}' => true, + _ => false + } + } +} + +fn main() { + +} diff --git a/src/test/run-pass/issue-29488.rs b/src/test/run-pass/issue-29488.rs new file mode 100644 index 0000000000000..eee0f663df24c --- /dev/null +++ b/src/test/run-pass/issue-29488.rs @@ -0,0 +1,30 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::thread; + +struct Foo; + +impl Drop for Foo { + fn drop(&mut self) { + println!("test2"); + } +} + +thread_local!(static FOO: Foo = Foo); + +fn main() { + // Off the main thread due to #28129, be sure to initialize FOO first before + // calling `println!` + thread::spawn(|| { + FOO.with(|_| {}); + println!("test1"); + }).join().unwrap(); +} diff --git a/src/test/run-pass/issue-29522.rs b/src/test/run-pass/issue-29522.rs new file mode 100644 index 0000000000000..de7c7aee05530 --- /dev/null +++ b/src/test/run-pass/issue-29522.rs @@ -0,0 +1,25 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// check that we don't accidentally capture upvars just because their name +// occurs in a path + +fn assert_static(_t: T) {} + +mod foo { + pub fn scope() {} +} + +fn main() { + let scope = &mut 0; + assert_static(|| { + foo::scope(); + }); +} diff --git a/src/test/run-pass/issue-29540.rs b/src/test/run-pass/issue-29540.rs new file mode 100644 index 0000000000000..285cf5763cc3a --- /dev/null +++ b/src/test/run-pass/issue-29540.rs @@ -0,0 +1,501 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[derive(Debug)] +pub struct Config { + pub name: String, + pub cluster: String, + pub debug_none: String, + pub debug_lockdep: String, + pub debug_context: String, + pub debug_crush: String, + pub debug_mds: String, + pub debug_mds_balancer: String, + pub debug_mds_locker: String, + pub debug_mds_log: String, + pub debug_mds_log_expire: String, + pub debug_mds_migrator: String, + pub debug_buffer: String, + pub debug_timer: String, + pub debug_filer: String, + pub debug_striper: String, + pub debug_objecter: String, + pub debug_rados: String, + pub debug_rbd: String, + pub debug_journaler: String, + pub debug_objectcacher: String, + pub debug_client: String, + pub debug_osd: String, + pub debug_optracker: String, + pub debug_objclass: String, + pub debug_filestore: String, + pub debug_keyvaluestore: String, + pub debug_journal: String, + pub debug_ms: String, + pub debug_mon: String, + pub debug_monc: String, + pub debug_paxos: String, + pub debug_tp: String, + pub debug_auth: String, + pub debug_crypto: String, + pub debug_finisher: String, + pub debug_heartbeatmap: String, + pub debug_perfcounter: String, + pub debug_rgw: String, + pub debug_civetweb: String, + pub debug_javaclient: String, + pub debug_asok: String, + pub debug_throttle: String, + pub host: String, + pub fsid: String, + pub public_addr: String, + pub cluster_addr: String, + pub public_network: String, + pub cluster_network: String, + pub num_client: String, + pub monmap: String, + pub mon_host: String, + pub lockdep: String, + pub run_dir: String, + pub admin_socket: String, + pub daemonize: String, + pub pid_file: String, + pub chdir: String, + pub max_open_files: String, + pub restapi_log_level: String, + pub restapi_base_url: String, + pub fatal_signal_handlers: String, + pub log_file: String, + pub log_max_new: String, + pub log_max_recent: String, + pub log_to_stderr: String, + pub err_to_stderr: String, + pub log_to_syslog: String, + pub err_to_syslog: String, + pub log_flush_on_exit: String, + pub log_stop_at_utilization: String, + pub clog_to_monitors: String, + pub clog_to_syslog: String, + pub clog_to_syslog_level: String, + pub clog_to_syslog_facility: String, + pub mon_cluster_log_to_syslog: String, + pub mon_cluster_log_to_syslog_level: String, + pub mon_cluster_log_to_syslog_facility: String, + pub mon_cluster_log_file: String, + pub mon_cluster_log_file_level: String, + pub key: String, + pub keyfile: String, + pub keyring: String, + pub heartbeat_interval: String, + pub heartbeat_file: String, + pub heartbeat_inject_failure: String, + pub perf: String, + pub ms_tcp_nodelay: String, + pub ms_tcp_rcvbuf: String, + pub ms_initial_backoff: String, + pub ms_max_backoff: String, + pub ms_nocrc: String, + pub ms_die_on_bad_msg: String, + pub ms_die_on_unhandled_msg: String, + pub ms_die_on_old_message: String, + pub ms_dispatch_throttle_bytes: String, + pub ms_bind_ipv6: String, + pub ms_bind_port_min: String, + pub ms_bind_port_max: String, + pub ms_rwthread_stack_bytes: String, + pub ms_tcp_read_timeout: String, + pub ms_pq_max_tokens_per_priority: String, + pub ms_pq_min_cost: String, + pub ms_inject_socket_failures: String, + pub ms_inject_delay_type: String, + pub ms_inject_delay_msg_type: String, + pub ms_inject_delay_max: String, + pub ms_inject_delay_probability: String, + pub ms_inject_internal_delays: String, + pub ms_dump_on_send: String, + pub inject_early_sigterm: String, + pub mon_data: String, + pub mon_initial_members: String, + pub mon_sync_fs_threshold: String, + pub mon_compact_on_start: String, + pub mon_compact_on_bootstrap: String, + pub mon_compact_on_trim: String, + pub mon_tick_interval: String, + pub mon_subscribe_interval: String, + pub mon_delta_reset_interval: String, + pub mon_osd_laggy_halflife: String, + pub mon_osd_laggy_weight: String, + pub mon_osd_adjust_heartbeat_grace: String, + pub mon_osd_adjust_down_out_interval: String, + pub mon_osd_auto_mark_in: String, + pub mon_osd_auto_mark_auto_out_in: String, + pub mon_osd_auto_mark_new_in: String, + pub mon_osd_down_out_interval: String, + pub mon_osd_down_out_subtree_limit: String, + pub mon_osd_min_up_ratio: String, + pub mon_osd_min_in_ratio: String, + pub mon_osd_max_op_age: String, + pub mon_osd_max_split_count: String, + pub mon_osd_allow_primary_temp: String, + pub mon_osd_allow_primary_affinity: String, + pub mon_stat_smooth_intervals: String, + pub mon_lease: String, + pub mon_lease_renew_interval: String, + pub mon_lease_ack_timeout: String, + pub mon_clock_drift_allowed: String, + pub mon_clock_drift_warn_backoff: String, + pub mon_timecheck_interval: String, + pub mon_accept_timeout: String, + pub mon_pg_create_interval: String, + pub mon_pg_stuck_threshold: String, + pub mon_pg_warn_min_per_osd: String, + pub mon_pg_warn_max_object_skew: String, + pub mon_pg_warn_min_objects: String, + pub mon_pg_warn_min_pool_objects: String, + pub mon_cache_target_full_warn_ratio: String, + pub mon_osd_full_ratio: String, + pub mon_osd_nearfull_ratio: String, + pub mon_globalid_prealloc: String, + pub mon_osd_report_timeout: String, + pub mon_force_standby_active: String, + pub mon_warn_on_old_mons: String, + pub mon_warn_on_legacy_crush_tunables: String, + pub mon_warn_on_osd_down_out_interval_zero: String, + pub mon_warn_on_cache_pools_without_hit_sets: String, + pub mon_min_osdmap_epochs: String, + pub mon_max_pgmap_epochs: String, + pub mon_max_log_epochs: String, + pub mon_max_mdsmap_epochs: String, + pub mon_max_osd: String, + pub mon_probe_timeout: String, + pub mon_slurp_timeout: String, + pub mon_slurp_bytes: String, + pub mon_client_bytes: String, + pub mon_daemon_bytes: String, + pub mon_max_log_entries_per_event: String, + pub mon_health_data_update_interval: String, + pub mon_data_avail_crit: String, + pub mon_data_avail_warn: String, + pub mon_config_key_max_entry_size: String, + pub mon_sync_timeout: String, + pub mon_sync_max_payload_size: String, + pub mon_sync_debug: String, + pub mon_sync_debug_leader: String, + pub mon_sync_debug_provider: String, + pub mon_sync_debug_provider_fallback: String, + pub mon_inject_sync_get_chunk_delay: String, + pub mon_osd_min_down_reporters: String, + pub mon_osd_min_down_reports: String, + pub mon_osd_force_trim_to: String, + pub mon_mds_force_trim_to: String, + pub mon_advanced_debug_mode: String, + pub mon_debug_dump_transactions: String, + pub mon_debug_dump_location: String, + pub mon_sync_provider_kill_at: String, + pub mon_sync_requester_kill_at: String, + pub mon_leveldb_write_buffer_size: String, + pub mon_leveldb_cache_size: String, + pub mon_leveldb_block_size: String, + pub mon_leveldb_bloom_size: String, + pub mon_leveldb_max_open_files: String, + pub mon_leveldb_compression: String, + pub mon_leveldb_paranoid: String, + pub mon_leveldb_log: String, + pub mon_leveldb_size_warn: String, + pub mon_force_quorum_join: String, + pub paxos_stash_full_interval: String, + pub paxos_max_join_drift: String, + pub paxos_propose_interval: String, + pub paxos_min_wait: String, + pub paxos_min: String, + pub paxos_trim_min: String, + pub paxos_trim_max: String, + pub paxos_service_trim_min: String, + pub paxos_service_trim_max: String, + pub paxos_kill_at: String, + pub clock_offset: String, + pub auth_cluster_required: String, + pub auth_service_required: String, + pub auth_client_required: String, + pub auth_supported: String, + pub cephx_require_signatures: String, + pub cephx_cluster_require_signatures: String, + pub cephx_service_require_signatures: String, + pub cephx_sign_messages: String, + pub auth_mon_ticket_ttl: String, + pub auth_service_ticket_ttl: String, + pub auth_debug: String, + pub mon_client_hunt_interval: String, + pub mon_client_ping_interval: String, + pub mon_client_ping_timeout: String, + pub mon_client_hunt_interval_backoff: String, + pub mon_client_hunt_interval_max_multiple: String, + pub mon_client_max_log_entries_per_message: String, + pub mon_max_pool_pg_num: String, + pub mon_pool_quota_warn_threshold: String, + pub mon_pool_quota_crit_threshold: String, + pub client_cache_size: String, + pub client_cache_mid: String, + pub client_use_random_mds: String, + pub client_mount_timeout: String, + pub client_tick_interval: String, + pub client_trace: String, + pub client_readahead_min: String, + pub client_readahead_max_bytes: String, + pub client_readahead_max_periods: String, + pub client_snapdir: String, + pub client_mountpoint: String, + pub client_notify_timeout: String, + pub osd_client_watch_timeout: String, + pub client_caps_release_delay: String, + pub client_oc: String, + pub client_oc_size: String, + pub client_oc_max_dirty: String, + pub client_oc_target_dirty: String, + pub client_oc_max_dirty_age: String, + pub client_oc_max_objects: String, + pub client_debug_force_sync_read: String, + pub client_debug_inject_tick_delay: String, + pub client_max_inline_size: String, + pub fuse_use_invalidate_cb: String, + pub fuse_allow_other: String, + pub fuse_default_permissions: String, + pub fuse_big_writes: String, + pub fuse_atomic_o_trunc: String, + pub fuse_debug: String, + pub fuse_multithreaded: String, + pub crush_location: String, + pub objecter_tick_interval: String, + pub objecter_timeout: String, + pub objecter_inflight_op_bytes: String, + pub objecter_inflight_ops: String, + pub journaler_allow_split_entries: String, + pub journaler_write_head_interval: String, + pub journaler_prefetch_periods: String, + pub journaler_prezero_periods: String, + pub journaler_batch_interval: String, + pub journaler_batch_max: String, + pub mds_data: String, + pub mds_max_file_size: String, + pub mds_cache_size: String, + pub mds_cache_mid: String, + pub mds_mem_max: String, + pub mds_dir_max_commit_size: String, + pub mds_decay_halflife: String, + pub mds_beacon_interval: String, + pub mds_beacon_grace: String, + pub mds_enforce_unique_name: String, + pub mds_blacklist_interval: String, + pub mds_session_timeout: String, + pub mds_freeze_tree_timeout: String, + pub mds_session_autoclose: String, + pub mds_reconnect_timeout: String, + pub mds_tick_interval: String, + pub mds_dirstat_min_interval: String, + pub mds_scatter_nudge_interval: String, + pub mds_client_prealloc_inos: String, + pub mds_early_reply: String, + pub mds_default_dir_hash: String, + pub mds_log: String, + pub mds_log_skip_corrupt_events: String, + pub mds_log_max_events: String, + pub mds_log_segment_size: String, + pub mds_log_max_segments: String, + pub mds_log_max_expiring: String, + pub mds_bal_sample_interval: String, + pub mds_bal_replicate_threshold: String, + pub mds_bal_unreplicate_threshold: String, + pub mds_bal_frag: String, + pub mds_bal_split_size: String, + pub mds_bal_split_rd: String, + pub mds_bal_split_wr: String, + pub mds_bal_split_bits: String, + pub mds_bal_merge_size: String, + pub mds_bal_merge_rd: String, + pub mds_bal_merge_wr: String, + pub mds_bal_interval: String, + pub mds_bal_fragment_interval: String, + pub mds_bal_idle_threshold: String, + pub mds_bal_max: String, + pub mds_bal_max_until: String, + pub mds_bal_mode: String, + pub mds_bal_min_rebalance: String, + pub mds_bal_min_start: String, + pub mds_bal_need_min: String, + pub mds_bal_need_max: String, + pub mds_bal_midchunk: String, + pub mds_bal_minchunk: String, + pub mds_bal_target_removal_min: String, + pub mds_bal_target_removal_max: String, + pub mds_replay_interval: String, + pub mds_shutdown_check: String, + pub mds_thrash_exports: String, + pub mds_thrash_fragments: String, + pub mds_dump_cache_on_map: String, + pub mds_dump_cache_after_rejoin: String, + pub mds_verify_scatter: String, + pub mds_debug_scatterstat: String, + pub mds_debug_frag: String, + pub mds_debug_auth_pins: String, + pub mds_debug_subtrees: String, + pub mds_kill_mdstable_at: String, + pub mds_kill_export_at: String, + pub mds_kill_import_at: String, + pub mds_kill_link_at: String, + pub mds_kill_rename_at: String, + pub mds_kill_openc_at: String, + pub mds_kill_journal_at: String, + pub mds_kill_journal_expire_at: String, + pub mds_kill_journal_replay_at: String, + pub mds_kill_create_at: String, + pub mds_open_remote_link_mode: String, + pub mds_inject_traceless_reply_probability: String, + pub mds_wipe_sessions: String, + pub mds_wipe_ino_prealloc: String, + pub mds_skip_ino: String, + pub max_mds: String, + pub mds_standby_for_name: String, + pub mds_standby_for_rank: String, + pub mds_standby_replay: String, + pub osd_compact_leveldb_on_mount: String, + pub osd_max_backfills: String, + pub osd_backfill_full_ratio: String, + pub osd_backfill_retry_interval: String, + pub osd_agent_max_ops: String, + pub osd_agent_min_evict_effort: String, + pub osd_agent_quantize_effort: String, + pub osd_agent_delay_time: String, + pub osd_agent_hist_halflife: String, + pub osd_agent_slop: String, + pub osd_uuid: String, + pub osd_data: String, + pub osd_journal: String, + pub osd_journal_size: String, + pub osd_max_write_size: String, + pub osd_max_pgls: String, + pub osd_client_message_size_cap: String, + pub osd_client_message_cap: String, + pub osd_pg_bits: String, + pub osd_pgp_bits: String, + pub osd_crush_chooseleaf_type: String, + pub osd_pool_default_crush_rule: String, + pub osd_pool_default_crush_replicated_ruleset: String, + pub osd_pool_erasure_code_stripe_width: String, + pub osd_pool_default_size: String, + pub osd_pool_default_min_size: String, + pub osd_pool_default_pg_num: String, + pub osd_pool_default_pgp_num: String, + pub osd_pool_default_erasure_code_directory: String, + pub osd_pool_default_erasure_code_profile: String, + pub osd_erasure_code_plugins: String, + pub osd_pool_default_flags: String, + pub osd_pool_default_flag_hashpspool: String, + pub osd_pool_default_hit_set_bloom_fpp: String, + pub osd_pool_default_cache_target_dirty_ratio: String, + pub osd_pool_default_cache_target_full_ratio: String, + pub osd_pool_default_cache_min_flush_age: String, + pub osd_pool_default_cache_min_evict_age: String, + pub osd_hit_set_min_size: String, + pub osd_hit_set_max_size: String, + pub osd_hit_set_namespace: String, + pub osd_tier_default_cache_mode: String, + pub osd_tier_default_cache_hit_set_count: String, + pub osd_tier_default_cache_hit_set_period: String, + pub osd_tier_default_cache_hit_set_type: String, + pub osd_map_dedup: String, + pub osd_map_max_advance: String, + pub osd_map_cache_size: String, + pub osd_map_message_max: String, + pub osd_map_share_max_epochs: String, + pub osd_op_threads: String, + pub osd_peering_wq_batch_size: String, + pub osd_op_pq_max_tokens_per_priority: String, + pub osd_op_pq_min_cost: String, + pub osd_disk_threads: String, + pub osd_disk_thread_ioprio_class: String, + pub osd_disk_thread_ioprio_priority: String, + pub osd_recovery_threads: String, + pub osd_recover_clone_overlap: String, + pub osd_recover_clone_overlap_limit: String, + pub osd_backfill_scan_min: String, + pub osd_backfill_scan_max: String, + pub osd_op_thread_timeout: String, + pub osd_recovery_thread_timeout: String, + pub osd_snap_trim_thread_timeout: String, + pub osd_snap_trim_sleep: String, + pub osd_scrub_thread_timeout: String, + pub osd_scrub_finalize_thread_timeout: String, + pub osd_scrub_invalid_stats: String, + pub osd_remove_thread_timeout: String, + pub osd_command_thread_timeout: String, + pub osd_age: String, + pub osd_age_time: String, + pub osd_heartbeat_addr: String, + pub osd_heartbeat_interval: String, + pub osd_heartbeat_grace: String, + pub osd_heartbeat_min_peers: String, + pub osd_pg_max_concurrent_snap_trims: String, + pub osd_heartbeat_min_healthy_ratio: String, + pub osd_mon_heartbeat_interval: String, + pub osd_mon_report_interval_max: String, + pub osd_mon_report_interval_min: String, + pub osd_pg_stat_report_interval_max: String, + pub osd_mon_ack_timeout: String, + pub osd_default_data_pool_replay_window: String, + pub osd_preserve_trimmed_log: String, + pub osd_auto_mark_unfound_lost: String, + pub osd_recovery_delay_start: String, + pub osd_recovery_max_active: String, + pub osd_recovery_max_single_start: String, + pub osd_recovery_max_chunk: String, + pub osd_copyfrom_max_chunk: String, + pub osd_push_per_object_cost: String, + pub osd_max_push_cost: String, + pub osd_max_push_objects: String, + pub osd_recovery_forget_lost_objects: String, + pub osd_max_scrubs: String, + pub osd_scrub_load_threshold: String, + pub osd_scrub_min_interval: String, + pub osd_scrub_max_interval: String, + pub osd_scrub_chunk_min: String, + pub osd_scrub_chunk_max: String, + pub osd_scrub_sleep: String, + pub osd_deep_scrub_interval: String, + pub osd_deep_scrub_stride: String, + pub osd_scan_list_ping_tp_interval: String, + pub osd_auto_weight: String, + pub osd_class_dir: String, + pub osd_open_classes_on_start: String, + pub osd_check_for_log_corruption: String, + pub osd_use_stale_snap: String, + pub osd_rollback_to_cluster_snap: String, + pub osd_default_notify_timeout: String, + pub osd_kill_backfill_at: String, + pub osd_pg_epoch_persisted_max_stale: String, + pub osd_min_pg_log_entries: String, + pub osd_max_pg_log_entries: String, + pub osd_op_complaint_time: String, + pub osd_command_max_records: String, + pub osd_op_log_threshold: String, + pub osd_verify_sparse_read_holes: String, + pub osd_debug_drop_ping_probability: String, + pub osd_debug_drop_ping_duration: String, + pub osd_debug_drop_pg_create_probability: String, + pub osd_debug_drop_pg_create_duration: String, + pub osd_debug_drop_op_probability: String, + pub osd_debug_op_order: String, + pub osd_debug_verify_snaps_on_info: String, + pub osd_debug_verify_stray_on_activate: String, + pub osd_debug_skip_full_check_in_backfill_reservation: String, + pub osd_debug_reject_backfill_probability: String, + pub osd_enable_op_tracker: String, +} + +fn main() {} diff --git a/src/test/run-pass/issue-29710.rs b/src/test/run-pass/issue-29710.rs new file mode 100644 index 0000000000000..f4cfb7e3af884 --- /dev/null +++ b/src/test/run-pass/issue-29710.rs @@ -0,0 +1,20 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![deny(unused_results)] +#![allow(dead_code)] + +#[derive(Debug)] +struct A(usize); + +#[derive(Debug)] +struct B { a: usize } + +fn main() {} diff --git a/src/test/run-pass/issue-29740.rs b/src/test/run-pass/issue-29740.rs new file mode 100644 index 0000000000000..75bcd431ec8e1 --- /dev/null +++ b/src/test/run-pass/issue-29740.rs @@ -0,0 +1,326 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Regression test for #29740. Inefficient MIR matching algorithms +// generated way too much code for this sort of case, leading to OOM. + +// ignore-pretty + +pub mod KeyboardEventConstants { + pub const DOM_KEY_LOCATION_STANDARD: u32 = 0; + pub const DOM_KEY_LOCATION_LEFT: u32 = 1; + pub const DOM_KEY_LOCATION_RIGHT: u32 = 2; + pub const DOM_KEY_LOCATION_NUMPAD: u32 = 3; +} // mod KeyboardEventConstants + +pub enum Key { + Space, + Apostrophe, + Comma, + Minus, + Period, + Slash, + Num0, + Num1, + Num2, + Num3, + Num4, + Num5, + Num6, + Num7, + Num8, + Num9, + Semicolon, + Equal, + A, + B, + C, + D, + E, + F, + G, + H, + I, + J, + K, + L, + M, + N, + O, + P, + Q, + R, + S, + T, + U, + V, + W, + X, + Y, + Z, + LeftBracket, + Backslash, + RightBracket, + GraveAccent, + World1, + World2, + + Escape, + Enter, + Tab, + Backspace, + Insert, + Delete, + Right, + Left, + Down, + Up, + PageUp, + PageDown, + Home, + End, + CapsLock, + ScrollLock, + NumLock, + PrintScreen, + Pause, + F1, + F2, + F3, + F4, + F5, + F6, + F7, + F8, + F9, + F10, + F11, + F12, + F13, + F14, + F15, + F16, + F17, + F18, + F19, + F20, + F21, + F22, + F23, + F24, + F25, + Kp0, + Kp1, + Kp2, + Kp3, + Kp4, + Kp5, + Kp6, + Kp7, + Kp8, + Kp9, + KpDecimal, + KpDivide, + KpMultiply, + KpSubtract, + KpAdd, + KpEnter, + KpEqual, + LeftShift, + LeftControl, + LeftAlt, + LeftSuper, + RightShift, + RightControl, + RightAlt, + RightSuper, + Menu, +} + +fn key_from_string(key_string: &str, location: u32) -> Option { + match key_string { + " " => Some(Key::Space), + "\"" => Some(Key::Apostrophe), + "'" => Some(Key::Apostrophe), + "<" => Some(Key::Comma), + "," => Some(Key::Comma), + "_" => Some(Key::Minus), + "-" if location == KeyboardEventConstants::DOM_KEY_LOCATION_STANDARD => Some(Key::Minus), + ">" => Some(Key::Period), + "." if location == KeyboardEventConstants::DOM_KEY_LOCATION_STANDARD => Some(Key::Period), + "?" => Some(Key::Slash), + "/" if location == KeyboardEventConstants::DOM_KEY_LOCATION_STANDARD => Some(Key::Slash), + "~" => Some(Key::GraveAccent), + "`" => Some(Key::GraveAccent), + ")" => Some(Key::Num0), + "0" if location == KeyboardEventConstants::DOM_KEY_LOCATION_STANDARD => Some(Key::Num0), + "!" => Some(Key::Num1), + "1" if location == KeyboardEventConstants::DOM_KEY_LOCATION_STANDARD => Some(Key::Num1), + "@" => Some(Key::Num2), + "2" if location == KeyboardEventConstants::DOM_KEY_LOCATION_STANDARD => Some(Key::Num2), + "#" => Some(Key::Num3), + "3" if location == KeyboardEventConstants::DOM_KEY_LOCATION_STANDARD => Some(Key::Num3), + "$" => Some(Key::Num4), + "4" if location == KeyboardEventConstants::DOM_KEY_LOCATION_STANDARD => Some(Key::Num4), + "%" => Some(Key::Num5), + "5" if location == KeyboardEventConstants::DOM_KEY_LOCATION_STANDARD => Some(Key::Num5), + "^" => Some(Key::Num6), + "6" if location == KeyboardEventConstants::DOM_KEY_LOCATION_STANDARD => Some(Key::Num6), + "&" => Some(Key::Num7), + "7" if location == KeyboardEventConstants::DOM_KEY_LOCATION_STANDARD => Some(Key::Num7), + "*" if location == KeyboardEventConstants::DOM_KEY_LOCATION_STANDARD => Some(Key::Num8), + "8" if location == KeyboardEventConstants::DOM_KEY_LOCATION_STANDARD => Some(Key::Num8), + "(" => Some(Key::Num9), + "9" if location == KeyboardEventConstants::DOM_KEY_LOCATION_STANDARD => Some(Key::Num9), + ":" => Some(Key::Semicolon), + ";" => Some(Key::Semicolon), + "+" if location == KeyboardEventConstants::DOM_KEY_LOCATION_STANDARD => Some(Key::Equal), + "=" if location == KeyboardEventConstants::DOM_KEY_LOCATION_STANDARD => Some(Key::Equal), + "A" => Some(Key::A), + "a" => Some(Key::A), + "B" => Some(Key::B), + "b" => Some(Key::B), + "C" => Some(Key::C), + "c" => Some(Key::C), + "D" => Some(Key::D), + "d" => Some(Key::D), + "E" => Some(Key::E), + "e" => Some(Key::E), + "F" => Some(Key::F), + "f" => Some(Key::F), + "G" => Some(Key::G), + "g" => Some(Key::G), + "H" => Some(Key::H), + "h" => Some(Key::H), + "I" => Some(Key::I), + "i" => Some(Key::I), + "J" => Some(Key::J), + "j" => Some(Key::J), + "K" => Some(Key::K), + "k" => Some(Key::K), + "L" => Some(Key::L), + "l" => Some(Key::L), + "M" => Some(Key::M), + "m" => Some(Key::M), + "N" => Some(Key::N), + "n" => Some(Key::N), + "O" => Some(Key::O), + "o" => Some(Key::O), + "P" => Some(Key::P), + "p" => Some(Key::P), + "Q" => Some(Key::Q), + "q" => Some(Key::Q), + "R" => Some(Key::R), + "r" => Some(Key::R), + "S" => Some(Key::S), + "s" => Some(Key::S), + "T" => Some(Key::T), + "t" => Some(Key::T), + "U" => Some(Key::U), + "u" => Some(Key::U), + "V" => Some(Key::V), + "v" => Some(Key::V), + "W" => Some(Key::W), + "w" => Some(Key::W), + "X" => Some(Key::X), + "x" => Some(Key::X), + "Y" => Some(Key::Y), + "y" => Some(Key::Y), + "Z" => Some(Key::Z), + "z" => Some(Key::Z), + "{" => Some(Key::LeftBracket), + "[" => Some(Key::LeftBracket), + "|" => Some(Key::Backslash), + "\\" => Some(Key::Backslash), + "}" => Some(Key::RightBracket), + "]" => Some(Key::RightBracket), + "Escape" => Some(Key::Escape), + "Enter" if location == KeyboardEventConstants::DOM_KEY_LOCATION_STANDARD + => Some(Key::Enter), + "Tab" => Some(Key::Tab), + "Backspace" => Some(Key::Backspace), + "Insert" => Some(Key::Insert), + "Delete" => Some(Key::Delete), + "ArrowRight" => Some(Key::Right), + "ArrowLeft" => Some(Key::Left), + "ArrowDown" => Some(Key::Down), + "ArrowUp" => Some(Key::Up), + "PageUp" => Some(Key::PageUp), + "PageDown" => Some(Key::PageDown), + "Home" => Some(Key::Home), + "End" => Some(Key::End), + "CapsLock" => Some(Key::CapsLock), + "ScrollLock" => Some(Key::ScrollLock), + "NumLock" => Some(Key::NumLock), + "PrintScreen" => Some(Key::PrintScreen), + "Pause" => Some(Key::Pause), + "F1" => Some(Key::F1), + "F2" => Some(Key::F2), + "F3" => Some(Key::F3), + "F4" => Some(Key::F4), + "F5" => Some(Key::F5), + "F6" => Some(Key::F6), + "F7" => Some(Key::F7), + "F8" => Some(Key::F8), + "F9" => Some(Key::F9), + "F10" => Some(Key::F10), + "F11" => Some(Key::F11), + "F12" => Some(Key::F12), + "F13" => Some(Key::F13), + "F14" => Some(Key::F14), + "F15" => Some(Key::F15), + "F16" => Some(Key::F16), + "F17" => Some(Key::F17), + "F18" => Some(Key::F18), + "F19" => Some(Key::F19), + "F20" => Some(Key::F20), + "F21" => Some(Key::F21), + "F22" => Some(Key::F22), + "F23" => Some(Key::F23), + "F24" => Some(Key::F24), + "F25" => Some(Key::F25), + "0" if location == KeyboardEventConstants::DOM_KEY_LOCATION_NUMPAD => Some(Key::Kp0), + "1" if location == KeyboardEventConstants::DOM_KEY_LOCATION_NUMPAD => Some(Key::Kp1), + "2" if location == KeyboardEventConstants::DOM_KEY_LOCATION_NUMPAD => Some(Key::Kp2), + "3" if location == KeyboardEventConstants::DOM_KEY_LOCATION_NUMPAD => Some(Key::Kp3), + "4" if location == KeyboardEventConstants::DOM_KEY_LOCATION_NUMPAD => Some(Key::Kp4), + "5" if location == KeyboardEventConstants::DOM_KEY_LOCATION_NUMPAD => Some(Key::Kp5), + "6" if location == KeyboardEventConstants::DOM_KEY_LOCATION_NUMPAD => Some(Key::Kp6), + "7" if location == KeyboardEventConstants::DOM_KEY_LOCATION_NUMPAD => Some(Key::Kp7), + "8" if location == KeyboardEventConstants::DOM_KEY_LOCATION_NUMPAD => Some(Key::Kp8), + "9" if location == KeyboardEventConstants::DOM_KEY_LOCATION_NUMPAD => Some(Key::Kp9), + "." if location == KeyboardEventConstants::DOM_KEY_LOCATION_NUMPAD => Some(Key::KpDecimal), + "/" if location == KeyboardEventConstants::DOM_KEY_LOCATION_NUMPAD => Some(Key::KpDivide), + "*" if location == KeyboardEventConstants::DOM_KEY_LOCATION_NUMPAD => Some(Key::KpMultiply), + "-" if location == KeyboardEventConstants::DOM_KEY_LOCATION_NUMPAD => Some(Key::KpSubtract), + "+" if location == KeyboardEventConstants::DOM_KEY_LOCATION_NUMPAD => Some(Key::KpAdd), + "Enter" if location == KeyboardEventConstants::DOM_KEY_LOCATION_NUMPAD + => Some(Key::KpEnter), + "=" if location == KeyboardEventConstants::DOM_KEY_LOCATION_NUMPAD => Some(Key::KpEqual), + "Shift" if location == KeyboardEventConstants::DOM_KEY_LOCATION_LEFT + => Some(Key::LeftShift), + "Control" if location == KeyboardEventConstants::DOM_KEY_LOCATION_LEFT + => Some(Key::LeftControl), + "Alt" if location == KeyboardEventConstants::DOM_KEY_LOCATION_LEFT => Some(Key::LeftAlt), + "Super" if location == KeyboardEventConstants::DOM_KEY_LOCATION_LEFT + => Some(Key::LeftSuper), + "Shift" if location == KeyboardEventConstants::DOM_KEY_LOCATION_RIGHT + => Some(Key::RightShift), + "Control" if location == KeyboardEventConstants::DOM_KEY_LOCATION_RIGHT + => Some(Key::RightControl), + "Alt" if location == KeyboardEventConstants::DOM_KEY_LOCATION_RIGHT => Some(Key::RightAlt), + "Super" if location == KeyboardEventConstants::DOM_KEY_LOCATION_RIGHT + => Some(Key::RightSuper), + "ContextMenu" => Some(Key::Menu), + _ => None + } +} + +fn main() { } diff --git a/src/test/run-pass/issue-29746.rs b/src/test/run-pass/issue-29746.rs new file mode 100644 index 0000000000000..61c601ac6a903 --- /dev/null +++ b/src/test/run-pass/issue-29746.rs @@ -0,0 +1,45 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// zip!(a1,a2,a3,a4) is equivalent to: +// a1.zip(a2).zip(a3).zip(a4).map(|(((x1,x2),x3),x4)| (x1,x2,x3,x4)) +macro_rules! zip { + // Entry point + ([$a:expr, $b:expr, $($rest:expr),*]) => { + zip!([$($rest),*], $a.zip($b), (x,y), [x,y]) + }; + + // Intermediate steps to build the zipped expression, the match pattern, and + // and the output tuple of the closure, using macro hygene to repeatedly + // introduce new variables named 'x'. + ([$a:expr, $($rest:expr),*], $zip:expr, $pat:pat, [$($flat:expr),*]) => { + zip!([$($rest),*], $zip.zip($a), ($pat,x), [$($flat),*, x]) + }; + + // Final step + ([], $zip:expr, $pat:pat, [$($flat:expr),+]) => { + $zip.map(|$pat| ($($flat),+)) + }; + + // Comma + ([$a:expr], $zip:expr, $pat:pat, [$($flat:expr),*]) => { + zip!([$a,], $zip, $pat, [$($flat),*]) + }; +} + +fn main() { + let p1 = vec![1i32, 2].into_iter(); + let p2 = vec!["10", "20"].into_iter(); + let p3 = vec![100u16, 200].into_iter(); + let p4 = vec![1000i64, 2000].into_iter(); + + let e = zip!([p1,p2,p3,p4]).collect::>(); + assert_eq!(e[0], (1i32,"10",100u16,1000i64)); +} diff --git a/src/test/run-pass/mir_coercions.rs b/src/test/run-pass/mir_coercions.rs new file mode 100644 index 0000000000000..c1897f79f22c6 --- /dev/null +++ b/src/test/run-pass/mir_coercions.rs @@ -0,0 +1,76 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(rustc_attrs, coerce_unsized, unsize)] + +use std::ops::CoerceUnsized; +use std::marker::Unsize; + +#[rustc_mir] +fn identity_coercion(x: &(Fn(u32)->u32 + Send)) -> &Fn(u32)->u32 { + x +} +#[rustc_mir] +fn fn_coercions(f: &fn(u32) -> u32) -> + (unsafe fn(u32) -> u32, + &(Fn(u32) -> u32+Send)) +{ + (*f, f) +} + +#[rustc_mir] +fn simple_array_coercion(x: &[u8; 3]) -> &[u8] { x } + +fn square(a: u32) -> u32 { a * a } + +#[derive(PartialEq,Eq)] +struct PtrWrapper<'a, T: 'a+?Sized>(u32, u32, (), &'a T); +impl<'a, T: ?Sized+Unsize, U: ?Sized> + CoerceUnsized> for PtrWrapper<'a, T> {} + +struct TrivPtrWrapper<'a, T: 'a+?Sized>(&'a T); +impl<'a, T: ?Sized+Unsize, U: ?Sized> + CoerceUnsized> for TrivPtrWrapper<'a, T> {} + +#[rustc_mir] +fn coerce_ptr_wrapper(p: PtrWrapper<[u8; 3]>) -> PtrWrapper<[u8]> { + p +} + +#[rustc_mir] +fn coerce_triv_ptr_wrapper(p: TrivPtrWrapper<[u8; 3]>) -> TrivPtrWrapper<[u8]> { + p +} + +#[rustc_mir] +fn coerce_fat_ptr_wrapper(p: PtrWrapper u32+Send>) + -> PtrWrapper u32> { + p +} + + +fn main() { + let a = [0,1,2]; + let square_local : fn(u32) -> u32 = square; + let (f,g) = fn_coercions(&square_local); + assert_eq!(f as usize, square as usize); + assert_eq!(g(4), 16); + assert_eq!(identity_coercion(g)(5), 25); + + assert_eq!(simple_array_coercion(&a), &a); + let w = coerce_ptr_wrapper(PtrWrapper(2,3,(),&a)); + assert!(w == PtrWrapper(2,3,(),&a) as PtrWrapper<[u8]>); + + let w = coerce_triv_ptr_wrapper(TrivPtrWrapper(&a)); + assert_eq!(&w.0, &a); + + let z = coerce_fat_ptr_wrapper(PtrWrapper(2,3,(),&square_local)); + assert_eq!((z.3)(6), 36); +} diff --git a/src/test/run-pass/mir_fat_ptr.rs b/src/test/run-pass/mir_fat_ptr.rs new file mode 100644 index 0000000000000..1916e608a8c79 --- /dev/null +++ b/src/test/run-pass/mir_fat_ptr.rs @@ -0,0 +1,63 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// test that ordinary fat pointer operations work. + +#![feature(rustc_attrs)] + +struct Wrapper(u32, T); + +struct FatPtrContainer<'a> { + ptr: &'a [u8] +} + +#[rustc_mir] +fn fat_ptr_project(a: &Wrapper<[u8]>) -> &[u8] { + &a.1 +} + +#[rustc_mir] +fn fat_ptr_simple(a: &[u8]) -> &[u8] { + a +} + +#[rustc_mir] +fn fat_ptr_via_local(a: &[u8]) -> &[u8] { + let x = a; + x +} + +#[rustc_mir] +fn fat_ptr_from_struct(s: FatPtrContainer) -> &[u8] { + s.ptr +} + +#[rustc_mir] +fn fat_ptr_to_struct(a: &[u8]) -> FatPtrContainer { + FatPtrContainer { ptr: a } +} + +#[rustc_mir] +fn fat_ptr_store_to<'a>(a: &'a [u8], b: &mut &'a [u8]) { + *b = a; +} + +fn main() { + let a = Wrapper(4, [7,6,5]); + + let p = fat_ptr_project(&a); + let p = fat_ptr_simple(p); + let p = fat_ptr_via_local(p); + let p = fat_ptr_from_struct(fat_ptr_to_struct(p)); + + let mut target : &[u8] = &[42]; + fat_ptr_store_to(p, &mut target); + assert_eq!(target, &a.1); +} diff --git a/src/test/run-pass/mir_raw_fat_ptr.rs b/src/test/run-pass/mir_raw_fat_ptr.rs new file mode 100644 index 0000000000000..20c3357d7d232 --- /dev/null +++ b/src/test/run-pass/mir_raw_fat_ptr.rs @@ -0,0 +1,173 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(rustc_attrs)] + +// check raw fat pointer ops in mir +// FIXME: please improve this when we get monomorphization support + +use std::mem; + +#[derive(Debug, PartialEq, Eq)] +struct ComparisonResults { + lt: bool, + le: bool, + gt: bool, + ge: bool, + eq: bool, + ne: bool +} + +const LT: ComparisonResults = ComparisonResults { + lt: true, + le: true, + gt: false, + ge: false, + eq: false, + ne: true +}; + +const EQ: ComparisonResults = ComparisonResults { + lt: false, + le: true, + gt: false, + ge: true, + eq: true, + ne: false +}; + +const GT: ComparisonResults = ComparisonResults { + lt: false, + le: false, + gt: true, + ge: true, + eq: false, + ne: true +}; + +#[rustc_mir] +fn compare_su8(a: *const S<[u8]>, b: *const S<[u8]>) -> ComparisonResults { + ComparisonResults { + lt: a < b, + le: a <= b, + gt: a > b, + ge: a >= b, + eq: a == b, + ne: a != b + } +} + +#[rustc_mir] +fn compare_au8(a: *const [u8], b: *const [u8]) -> ComparisonResults { + ComparisonResults { + lt: a < b, + le: a <= b, + gt: a > b, + ge: a >= b, + eq: a == b, + ne: a != b + } +} + +#[rustc_mir(graphviz="comparefoo.gv")] +fn compare_foo<'a>(a: *const (Foo+'a), b: *const (Foo+'a)) -> ComparisonResults { + ComparisonResults { + lt: a < b, + le: a <= b, + gt: a > b, + ge: a >= b, + eq: a == b, + ne: a != b + } +} + +#[rustc_mir(graphviz="simpleeq.gv")] +fn simple_eq<'a>(a: *const (Foo+'a), b: *const (Foo+'a)) -> bool { + let result = a == b; + result +} + +fn assert_inorder(a: &[T], + compare: fn(T, T) -> ComparisonResults) { + for i in 0..a.len() { + for j in 0..a.len() { + let cres = compare(a[i], a[j]); + if i < j { + assert_eq!(cres, LT); + } else if i == j { + assert_eq!(cres, EQ); + } else { + assert_eq!(cres, GT); + } + } + } +} + +trait Foo { fn foo(&self) -> usize; } +impl Foo for T { + fn foo(&self) -> usize { + mem::size_of::() + } +} + +struct S(u32, T); + +fn main() { + let array = [0,1,2,3,4]; + let array2 = [5,6,7,8,9]; + + // fat ptr comparison: addr then extra + + // check ordering for arrays + let mut ptrs: Vec<*const [u8]> = vec![ + &array[0..0], &array[0..1], &array, &array[1..] + ]; + + let array_addr = &array as *const [u8] as *const u8 as usize; + let array2_addr = &array2 as *const [u8] as *const u8 as usize; + if array2_addr < array_addr { + ptrs.insert(0, &array2); + } else { + ptrs.push(&array2); + } + assert_inorder(&ptrs, compare_au8); + + let u8_ = (0u8, 1u8); + let u32_ = (4u32, 5u32); + + // check ordering for ptrs + let buf: &mut [*const Foo] = &mut [ + &u8_, &u8_.0, + &u32_, &u32_.0, + ]; + buf.sort_by(|u,v| { + let u : [*const (); 2] = unsafe { mem::transmute(*u) }; + let v : [*const (); 2] = unsafe { mem::transmute(*v) }; + u.cmp(&v) + }); + assert_inorder(buf, compare_foo); + + // check ordering for structs containing arrays + let ss: (S<[u8; 2]>, + S<[u8; 3]>, + S<[u8; 2]>) = ( + S(7, [8, 9]), + S(10, [11, 12, 13]), + S(4, [5, 6]) + ); + assert_inorder(&[ + &ss.0 as *const S<[u8]>, + &ss.1 as *const S<[u8]>, + &ss.2 as *const S<[u8]> + ], compare_su8); + + assert!(simple_eq(&0u8 as *const _, &0u8 as *const _)); + assert!(!simple_eq(&0u8 as *const _, &1u8 as *const _)); +} diff --git a/src/test/run-pass/mir_small_agg_arg.rs b/src/test/run-pass/mir_small_agg_arg.rs new file mode 100644 index 0000000000000..8a0cb046b7a7d --- /dev/null +++ b/src/test/run-pass/mir_small_agg_arg.rs @@ -0,0 +1,19 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(rustc_attrs)] + +#[rustc_mir] +fn foo((x, y): (i8, i8)) { +} + +fn main() { + foo((0, 1)); +} diff --git a/src/test/run-pass/mir_trans_array.rs b/src/test/run-pass/mir_trans_array.rs new file mode 100644 index 0000000000000..e6ffb89582512 --- /dev/null +++ b/src/test/run-pass/mir_trans_array.rs @@ -0,0 +1,21 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. +#![feature(rustc_attrs)] + +#[rustc_mir] +fn into_inner() -> [u64; 1024] { + let mut x = 10 + 20; + [x; 1024] +} + +fn main(){ + let x: &[u64] = &[30; 1024]; + assert_eq!(&into_inner()[..], x); +} diff --git a/src/test/run-pass/mir_trans_array_2.rs b/src/test/run-pass/mir_trans_array_2.rs new file mode 100644 index 0000000000000..4aa686298e9ee --- /dev/null +++ b/src/test/run-pass/mir_trans_array_2.rs @@ -0,0 +1,20 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. +#![feature(rustc_attrs)] + +#[rustc_mir] +fn into_inner(x: u64) -> [u64; 1024] { + [x; 2*4*8*16] +} + +fn main(){ + let x: &[u64] = &[42; 1024]; + assert_eq!(&into_inner(42)[..], x); +} diff --git a/src/test/run-pass/mir_trans_spike1.rs b/src/test/run-pass/mir_trans_spike1.rs new file mode 100644 index 0000000000000..9a06ab78e73b4 --- /dev/null +++ b/src/test/run-pass/mir_trans_spike1.rs @@ -0,0 +1,24 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// A simple spike test for MIR version of trans. + +#![feature(rustc_attrs)] + +#[rustc_mir] +fn sum(x: i32, y: i32) -> i32 { + x + y +} + +fn main() { + let x = sum(22, 44); + assert_eq!(x, 66); + println!("sum()={:?}", x); +} diff --git a/src/test/run-pass/mir_trans_switchint.rs b/src/test/run-pass/mir_trans_switchint.rs new file mode 100644 index 0000000000000..edde5f3c89587 --- /dev/null +++ b/src/test/run-pass/mir_trans_switchint.rs @@ -0,0 +1,24 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(rustc_attrs)] + +#[rustc_mir] +pub fn foo(x: i8) -> i32 { + match x { + 1 => 0, + _ => 1, + } +} + +fn main() { + assert_eq!(foo(0), 1); + assert_eq!(foo(1), 0); +} diff --git a/src/test/run-pass/resolve-pseudo-shadowing.rs b/src/test/run-pass/resolve-pseudo-shadowing.rs new file mode 100644 index 0000000000000..071279ae7d818 --- /dev/null +++ b/src/test/run-pass/resolve-pseudo-shadowing.rs @@ -0,0 +1,20 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// check that type parameters can't "shadow" qualified paths. + +fn check(_c: Clone) { + fn check2() { + <() as std::clone::Clone>::clone(&()); + } + check2(); +} + +fn main() { check(()); } diff --git a/src/test/run-pass/rfc-1014-2.rs b/src/test/run-pass/rfc-1014-2.rs index ad76daaace49b..7cdaf278a08f5 100644 --- a/src/test/run-pass/rfc-1014-2.rs +++ b/src/test/run-pass/rfc-1014-2.rs @@ -11,15 +11,19 @@ extern crate libc; +type DWORD = u32; +type HANDLE = *mut u8; +type BOOL = i32; + #[cfg(windows)] extern "system" { - fn SetStdHandle(nStdHandle: libc::DWORD, nHandle: libc::HANDLE) -> libc::BOOL; + fn SetStdHandle(nStdHandle: DWORD, nHandle: HANDLE) -> BOOL; } #[cfg(windows)] fn close_stdout() { - const STD_OUTPUT_HANDLE: libc::DWORD = -11i32 as libc::DWORD; - unsafe { SetStdHandle(STD_OUTPUT_HANDLE, 0 as libc::HANDLE); } + const STD_OUTPUT_HANDLE: DWORD = -11i32 as DWORD; + unsafe { SetStdHandle(STD_OUTPUT_HANDLE, 0 as HANDLE); } } #[cfg(windows)] diff --git a/src/test/run-pass/rfc-1014.rs b/src/test/run-pass/rfc-1014.rs index 98cad4efab71a..df969070a2ad4 100644 --- a/src/test/run-pass/rfc-1014.rs +++ b/src/test/run-pass/rfc-1014.rs @@ -11,20 +11,24 @@ extern crate libc; +type DWORD = u32; +type HANDLE = *mut u8; + #[cfg(windows)] extern "system" { - pub fn GetStdHandle(which: libc::DWORD) -> libc::HANDLE; + fn GetStdHandle(which: DWORD) -> HANDLE; + fn CloseHandle(handle: HANDLE) -> i32; } #[cfg(windows)] fn close_stdout() { - const STD_OUTPUT_HANDLE: libc::DWORD = -11i32 as libc::DWORD; - unsafe { libc::CloseHandle(GetStdHandle(STD_OUTPUT_HANDLE)); } + const STD_OUTPUT_HANDLE: DWORD = -11i32 as DWORD; + unsafe { CloseHandle(GetStdHandle(STD_OUTPUT_HANDLE)); } } #[cfg(not(windows))] fn close_stdout() { - unsafe { libc::close(libc::STDOUT_FILENO); } + unsafe { libc::close(1); } } fn main() { diff --git a/src/test/run-pass/simd-intrinsic-generic-cast.rs b/src/test/run-pass/simd-intrinsic-generic-cast.rs old mode 100755 new mode 100644 diff --git a/src/test/run-pass/trait-copy-guessing.rs b/src/test/run-pass/trait-copy-guessing.rs new file mode 100644 index 0000000000000..71cd3c9441e10 --- /dev/null +++ b/src/test/run-pass/trait-copy-guessing.rs @@ -0,0 +1,46 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// "guessing" in trait selection can affect `copy_or_move`. Check that this +// is correctly handled. I am not sure what is the "correct" behaviour, +// but we should at least not ICE. + +use std::mem; + +struct U([u8; 1337]); + +struct S<'a,T:'a>(&'a T); +impl<'a, T> Clone for S<'a, T> { fn clone(&self) -> Self { S(self.0) } } +/// This impl triggers inference "guessing" - S<_>: Copy => _ = U +impl<'a> Copy for S<'a, Option> {} + +fn assert_impls_fnR>(_: &T){} + +fn main() { + let n = None; + let e = S(&n); + let f = || { + // S being copy is critical for this to work + drop(e); + mem::size_of_val(e.0) + }; + assert_impls_fn(&f); + assert_eq!(f(), 1337+1); + + assert_eq!((|| { + // S being Copy is not critical here, but + // we check it anyway. + let n = None; + let e = S(&n); + let ret = mem::size_of_val(e.0); + drop(e); + ret + })(), 1337+1); +} diff --git a/src/test/run-pass/wait-forked-but-failed-child.rs b/src/test/run-pass/wait-forked-but-failed-child.rs index 1d0004bafa356..795c3f46f7579 100644 --- a/src/test/run-pass/wait-forked-but-failed-child.rs +++ b/src/test/run-pass/wait-forked-but-failed-child.rs @@ -15,8 +15,6 @@ extern crate libc; use std::process::Command; -use libc::funcs::posix88::unistd; - // The output from "ps -A -o pid,ppid,args" should look like this: // PID PPID COMMAND // 1 0 /sbin/init @@ -34,7 +32,7 @@ use libc::funcs::posix88::unistd; #[cfg(unix)] fn find_zombies() { - let my_pid = unsafe { unistd::getpid() }; + let my_pid = unsafe { libc::getpid() }; // http://pubs.opengroup.org/onlinepubs/9699919799/utilities/ps.html let ps_cmd_output = Command::new("ps").args(&["-A", "-o", "pid,ppid,args"]).output().unwrap(); diff --git a/src/test/run-pass/weird-exit-code.rs b/src/test/run-pass/weird-exit-code.rs new file mode 100644 index 0000000000000..27c7f9bef15cc --- /dev/null +++ b/src/test/run-pass/weird-exit-code.rs @@ -0,0 +1,37 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// On Windows the GetExitCodeProcess API is used to get the exit code of a +// process, but it's easy to mistake a process exiting with the code 259 as +// "still running" because this is the value of the STILL_ACTIVE constant. Make +// sure we handle this case in the standard library and correctly report the +// status. +// +// Note that this is disabled on unix as processes exiting with 259 will have +// their exit status truncated to 3 (only the lower 8 bits are used). + +use std::process::{self, Command}; +use std::env; + +fn main() { + if !cfg!(windows) { + return + } + + if env::args().len() == 1 { + let status = Command::new(env::current_exe().unwrap()) + .arg("foo") + .status() + .unwrap(); + assert_eq!(status.code(), Some(259)); + } else { + process::exit(259); + } +} diff --git a/src/test/rustdoc/issue-28927.rs b/src/test/rustdoc/issue-28927.rs new file mode 100644 index 0000000000000..b3096a949625f --- /dev/null +++ b/src/test/rustdoc/issue-28927.rs @@ -0,0 +1,16 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// aux-build:issue-28927-2.rs +// aux-build:issue-28927-1.rs +// ignore-cross-compile + +extern crate issue_28927_1 as inner1; +pub use inner1 as foo;