diff --git a/.mailmap b/.mailmap index ee5b6f257b555..40e9c003313ce 100644 --- a/.mailmap +++ b/.mailmap @@ -6,6 +6,7 @@ # Aaron Todd +Aaron Power Abhishek Chanda Abhishek Chanda Adolfo Ochagavía Adrien Tétar @@ -56,6 +57,7 @@ Corey Richardson Elaine "See More" Nemo Cyryl Płotnicki Damien Schoof Daniel Ramos +Daniel J Rollins David Klein David Manescu David Ross @@ -63,11 +65,12 @@ Derek Chiang Derek Chiang (Enchi Jiang) Diggory Hardy Dylan Braithwaite Dzmitry Malyshau +E. Dunham edunham Eduardo Bautista <=> Eduardo Bautista +Eduard-Mihai Burtescu Elliott Slaughter Elly Fong-Jones -Emily Dunham edunham Eric Holk Eric Holk Eric Holmes @@ -83,6 +86,8 @@ Gareth Daniel Smith Gareth Smith Graham Fawcett Graham Fawcett Graydon Hoare Graydon Hoare +Guillaume Gomez +Guillaume Gomez ggomez Guillaume Gomez Guillaume Gomez Heather Heather @@ -114,6 +119,7 @@ John Kåre Alsaker John Talling Jonathan Bailey Jonathan S Jonathan S +Jonathan Turner Jorge Aparicio Joseph Martin João Oliveira joaoxsouls @@ -136,6 +142,7 @@ NAKASHIMA, Makoto NAKASHIMA, Makoto Marcell Pardavi Margaret Meyerhofer +Mark Simulacrum Mark Sinclair Mark Sinclair =Mark Sinclair <=125axel125@gmail.com> Markus Westerlind Markus @@ -171,6 +178,7 @@ Peter Zotov Phil Dawes Phil Dawes Philipp Brüschweiler Philipp Brüschweiler +Philipp Matthias Schäfer Przemysław Wesołek Przemek Wesołek Rafael Ávila de Espíndola Rafael Avila de Espindola Ralph Giles Ralph Giles @@ -189,11 +197,13 @@ S Pradeep Kumar Scott Olson Scott Olson Sean Gillespie swgillespie Seonghyun Kim +Shyam Sundar B Simon Barber-Dueck Simon BD Simon Sapin Simonas Kazlauskas Simonas Kazlauskas startling Stepan Koltsov Stepan Koltsov +Steve Klabnik Steven Fackler Steven Stewart-Gallus Stuart Pernsteiner Stuart Pernsteiner diff --git a/.travis.yml b/.travis.yml index 21877ecb43e10..eb8db13c0bb7f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,4 @@ -language: generic +language: shell sudo: required dist: trusty services: @@ -64,9 +64,9 @@ matrix: os: osx osx_image: xcode8.2 install: &osx_install_sccache > - travis_retry curl -o /usr/local/bin/sccache https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-apple-darwin && + travis_retry curl -fo /usr/local/bin/sccache https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-apple-darwin && chmod +x /usr/local/bin/sccache && - travis_retry curl -o /usr/local/bin/stamp https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-17-stamp-x86_64-apple-darwin && + travis_retry curl -fo /usr/local/bin/stamp https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-17-stamp-x86_64-apple-darwin && chmod +x /usr/local/bin/stamp - env: > RUST_CHECK_TARGET=check @@ -122,7 +122,7 @@ matrix: - env: IMAGE=dist-x86_64-linux DEPLOY_ALT=1 - env: > RUST_CHECK_TARGET=dist - RUST_CONFIGURE_ARGS="--enable-extended" + RUST_CONFIGURE_ARGS="--enable-extended --enable-profiler" SRC=. DEPLOY_ALT=1 RUSTC_RETRY_LINKER_ON_SEGFAULT=1 @@ -144,7 +144,7 @@ env: # Note that this is overridden on OSX builders install: > - travis_retry curl -o $HOME/stamp https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-17-stamp-x86_64-unknown-linux-musl && + travis_retry curl -fo $HOME/stamp https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-17-stamp-x86_64-unknown-linux-musl && chmod +x $HOME/stamp && export PATH=$PATH:$HOME @@ -183,10 +183,10 @@ before_script: # clock drift. Timezones don't matter since relative deltas give all the necessary info. script: - > - date && curl -s --head https://google.com | grep ^Date: | sed 's/Date: //g' + date && (curl -fs --head https://google.com | grep ^Date: | sed 's/Date: //g' || true) - stamp sh -x -c "$RUN_SCRIPT" - > - date && curl -s --head https://google.com | grep ^Date: | sed 's/Date: //g' + date && (curl -fs --head https://google.com | grep ^Date: | sed 's/Date: //g' || true) after_success: - > diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000000000..6bec933018686 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,38 @@ +# The Rust Code of Conduct + +A version of this document [can be found online](https://www.rust-lang.org/conduct.html). + +## Conduct + +**Contact**: [rust-mods@rust-lang.org](mailto:rust-mods@rust-lang.org) + +* We are committed to providing a friendly, safe and welcoming environment for all, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, religion, nationality, or other similar characteristic. +* On IRC, please avoid using overtly sexual nicknames or other nicknames that might detract from a friendly, safe and welcoming environment for all. +* Please be kind and courteous. There's no need to be mean or rude. +* Respect that people have differences of opinion and that every design or implementation choice carries a trade-off and numerous costs. There is seldom a right answer. +* Please keep unstructured critique to a minimum. If you have solid ideas you want to experiment with, make a fork and see how it works. +* We will exclude you from interaction if you insult, demean or harass anyone. That is not welcome behaviour. We interpret the term "harassment" as including the definition in the Citizen Code of Conduct; if you have any lack of clarity about what might be included in that concept, please read their definition. In particular, we don't tolerate behavior that excludes people in socially marginalized groups. +* Private harassment is also unacceptable. No matter who you are, if you feel you have been or are being harassed or made uncomfortable by a community member, please contact one of the channel ops or any of the [Rust moderation team](/team.html#Moderation) immediately. Whether you're a regular contributor or a newcomer, we care about making this community a safe place for you and we've got your back. +* Likewise any spamming, trolling, flaming, baiting or other attention-stealing behaviour is not welcome. + +## Moderation + + +These are the policies for upholding our community's standards of conduct. If you feel that a thread needs moderation, please contact the [Rust moderation team](/team.html#Moderation). + +1. Remarks that violate the Rust standards of conduct, including hateful, hurtful, oppressive, or exclusionary remarks, are not allowed. (Cursing is allowed, but never targeting another user, and never in a hateful manner.) +2. Remarks that moderators find inappropriate, whether listed in the code of conduct or not, are also not allowed. +3. Moderators will first respond to such remarks with a warning. +4. If the warning is unheeded, the user will be "kicked," i.e., kicked out of the communication channel to cool off. +5. If the user comes back and continues to make trouble, they will be banned, i.e., indefinitely excluded. +6. Moderators may choose at their discretion to un-ban the user if it was a first offense and they offer the offended party a genuine apology. +7. If a moderator bans someone and you think it was unjustified, please take it up with that moderator, or with a different moderator, **in private**. Complaints about bans in-channel are not allowed. +8. Moderators are held to a higher standard than other community members. If a moderator creates an inappropriate situation, they should expect less leeway than others. + +In the Rust community we strive to go the extra step to look out for each other. Don't just aim to be technically unimpeachable, try to be your best self. In particular, avoid flirting with offensive or sensitive issues, particularly if they're off-topic; this all too often leads to unnecessary fights, hurt feelings, and damaged trust; worse, it can drive people away from the community entirely. + +And if someone takes issue with something you said or did, resist the urge to be defensive. Just stop doing what it was they complained about and apologize. Even if you feel you were misinterpreted or unfairly accused, chances are good there was something you could've communicated better — remember that it's your responsibility to make your fellow Rustaceans comfortable. Everyone wants to get along and we are all here first and foremost because we want to talk about cool technology. You will find that people will be eager to assume good intent and forgive as long as you earn their trust. + +The enforcement policies listed above apply to all official Rust venues; including official IRC channels (#rust, #rust-internals, #rust-tools, #rust-libs, #rustc, #rust-beginners, #rust-docs, #rust-community, #rust-lang, and #cargo); GitHub repositories under rust-lang, rust-lang-nursery, and rust-lang-deprecated; and all forums under rust-lang.org (users.rust-lang.org, internals.rust-lang.org). For other projects adopting the Rust Code of Conduct, please contact the maintainers of those projects for enforcement. If you wish to use this code of conduct for your own project, consider explicitly mentioning your moderation policy or making a copy with your own moderation policy so as to avoid confusion. + +*Adapted from the [Node.js Policy on Trolling](http://blog.izs.me/post/30036893703/policy-on-trolling) as well as the [Contributor Covenant v1.3.0](http://contributor-covenant.org/version/1/3/0/).* diff --git a/appveyor.yml b/appveyor.yml index 4711f34f830e6..582ca5d0f9de3 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -75,7 +75,7 @@ environment: # "alternate" deployment, see .travis.yml for more info - MSYS_BITS: 64 - RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-extended + RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-extended --enable-profiler SCRIPT: python x.py dist DEPLOY_ALT: 1 diff --git a/src/Cargo.lock b/src/Cargo.lock index 1b21ffdfe70f4..3c8d1164863de 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -75,7 +75,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -85,10 +85,10 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "backtrace-sys 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-demangle 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -99,13 +99,16 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "bitflags" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" +name = "bin_lib" +version = "0.1.0" + +[[package]] +name = "bin_lib_no_cfg_test" +version = "0.1.0" [[package]] name = "bitflags" @@ -131,12 +134,16 @@ dependencies = [ "filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)", "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "borrow_error" +version = "0.1.0" + [[package]] name = "bufstream" version = "0.1.3" @@ -160,7 +167,7 @@ dependencies = [ [[package]] name = "cargo" version = "0.21.0" -source = "git+https://github.com/rust-lang/cargo#eb6cf012a6cc23c9c89c4009564de9fccc38b9cb" +source = "git+https://github.com/rust-lang/cargo#5982cf904be1d72f575dcbd1e750c07bf730b966" replace = "cargo 0.21.0" [[package]] @@ -185,9 +192,9 @@ dependencies = [ "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "hamcrest 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "hex 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "jobserver 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "jobserver 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)", "libgit2-sys 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -196,8 +203,8 @@ dependencies = [ "psapi-sys 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", "serde_ignored 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "shell-escape 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -221,9 +228,9 @@ dependencies = [ "hamcrest 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "hex 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "tar 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -237,20 +244,21 @@ version = "0.1.0" [[package]] name = "cfg-if" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "clap" -version = "2.24.2" +version = "2.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "atty 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "bitflags 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", "strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "term_size 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "textwrap 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-segmentation 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "yaml-rust 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -288,10 +296,15 @@ dependencies = [ "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "completion" +version = "0.1.0" + [[package]] name = "core" version = "0.0.0" @@ -305,8 +318,8 @@ version = "0.10.0" dependencies = [ "curl 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -322,7 +335,7 @@ version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "curl-sys 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-probe 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-sys 0.9.14 (registry+https://github.com/rust-lang/crates.io-index)", "socket2 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -335,7 +348,7 @@ version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)", "libz-sys 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-sys 0.9.14 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", @@ -373,8 +386,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", "strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -426,15 +439,23 @@ name = "filetime" version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "find_all_refs" +version = "0.1.0" + +[[package]] +name = "find_all_refs_no_cfg_test" +version = "0.1.0" + [[package]] name = "flate2" version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)", "miniz-sys 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -453,7 +474,7 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -473,7 +494,7 @@ version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)", "libgit2-sys 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-probe 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-sys 0.9.14 (registry+https://github.com/rust-lang/crates.io-index)", @@ -496,6 +517,10 @@ name = "glob" version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "goto_def" +version = "0.1.0" + [[package]] name = "graphviz" version = "0.0.0" @@ -511,7 +536,7 @@ dependencies = [ [[package]] name = "handlebars" -version = "0.25.3" +version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -519,8 +544,8 @@ dependencies = [ "pest 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "quick-error 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 0.9.10 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -528,13 +553,21 @@ name = "hex" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "highlight" +version = "0.1.0" + +[[package]] +name = "hover" +version = "0.1.0" + [[package]] name = "idna" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-bidi 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-normalization 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -542,7 +575,7 @@ dependencies = [ name = "installer" version = "0.0.0" dependencies = [ - "clap 2.24.2 (registry+https://github.com/rust-lang/crates.io-index)", + "clap 2.25.0 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "flate2 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -560,10 +593,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "jobserver" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -582,8 +615,8 @@ version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "enum_primitive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "url_serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -603,7 +636,7 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.24" +version = "0.2.26" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -614,7 +647,7 @@ dependencies = [ "cmake 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)", "curl-sys 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)", "libssh2-sys 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", "libz-sys 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-sys 0.9.14 (registry+https://github.com/rust-lang/crates.io-index)", @@ -627,7 +660,7 @@ version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cmake 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)", "libz-sys 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-sys 0.9.14 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", @@ -639,7 +672,7 @@ version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "vcpkg 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -660,7 +693,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -670,19 +703,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "mdbook" -version = "0.0.21" +version = "0.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "clap 2.24.2 (registry+https://github.com/rust-lang/crates.io-index)", + "clap 2.25.0 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "handlebars 0.25.3 (registry+https://github.com/rust-lang/crates.io-index)", + "handlebars 0.26.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "open 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "pulldown-cmark 0.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "pulldown-cmark 0.0.14 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 0.9.10 (registry+https://github.com/rust-lang/crates.io-index)", - "toml 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -690,7 +723,7 @@ name = "memchr" version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -698,7 +731,7 @@ name = "memchr" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -707,7 +740,7 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -721,14 +754,18 @@ dependencies = [ "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "multiple_bins" +version = "0.1.0" + [[package]] name = "net2" version = "0.2.29" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -804,7 +841,7 @@ name = "num_cpus" version = "1.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -820,7 +857,7 @@ dependencies = [ "bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", "foreign-types 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-sys 0.9.14 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -835,7 +872,7 @@ version = "0.9.14" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -905,21 +942,13 @@ dependencies = [ "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "pulldown-cmark" -version = "0.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bitflags 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "pulldown-cmark" version = "0.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", + "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -942,7 +971,7 @@ name = "racer" version = "2.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "clap 2.24.2 (registry+https://github.com/rust-lang/crates.io-index)", + "clap 2.25.0 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -965,9 +994,17 @@ name = "rand" version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "reformat" +version = "0.1.0" + +[[package]] +name = "reformat_with_range" +version = "0.1.0" + [[package]] name = "regex" version = "0.1.80" @@ -1010,6 +1047,10 @@ version = "0.1.0" name = "remote-test-server" version = "0.1.0" +[[package]] +name = "rename" +version = "0.1.0" + [[package]] name = "rls" version = "0.1.0" @@ -1020,13 +1061,13 @@ dependencies = [ "languageserver-types 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "racer 2.0.9 (registry+https://github.com/rust-lang/crates.io-index)", - "rls-analysis 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rls-analysis 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "rls-data 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rls-vfs 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "rustfmt-nightly 0.1.8 (git+https://github.com/rust-lang-nursery/rustfmt?branch=rustfmt-42492)", - "serde 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "rls-vfs 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "rustfmt-nightly 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1035,7 +1076,7 @@ dependencies = [ [[package]] name = "rls-analysis" -version = "0.4.1" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "derive-new 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1060,13 +1101,13 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rls-vfs" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "racer 2.0.9 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1077,8 +1118,8 @@ dependencies = [ name = "rustbook" version = "0.1.0" dependencies = [ - "clap 2.24.2 (registry+https://github.com/rust-lang/crates.io-index)", - "mdbook 0.0.21 (registry+https://github.com/rust-lang/crates.io-index)", + "clap 2.25.0 (registry+https://github.com/rust-lang/crates.io-index)", + "mdbook 0.0.22 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1089,7 +1130,7 @@ dependencies = [ "flate2 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", "fmt_macros 0.0.0", "graphviz 0.0.0", - "jobserver 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "jobserver 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_back 0.0.0", @@ -1401,7 +1442,7 @@ dependencies = [ "crossbeam 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", "flate2 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)", - "jobserver 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "jobserver 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", @@ -1474,23 +1515,23 @@ dependencies = [ [[package]] name = "rustfmt-nightly" -version = "0.1.8" -source = "git+https://github.com/rust-lang-nursery/rustfmt?branch=rustfmt-42492#7333dfc95b4af5c7283ba03f33c50f108d2be3f5" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "diff 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "strings 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-segmentation 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1514,7 +1555,7 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1524,17 +1565,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde" -version = "0.9.15" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "serde" -version = "1.0.8" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde_derive" -version = "1.0.8" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1556,18 +1592,7 @@ name = "serde_ignored" version = "0.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "serde_json" -version = "0.9.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "dtoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1578,7 +1603,7 @@ dependencies = [ "dtoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1595,9 +1620,9 @@ name = "socket2" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1716,7 +1741,7 @@ name = "syntex_errors" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", "syntex_pos 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1738,7 +1763,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", "syntex_errors 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1753,7 +1778,7 @@ version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)", "xattr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1784,7 +1809,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1804,13 +1829,22 @@ dependencies = [ "term 0.0.0", ] +[[package]] +name = "textwrap" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "term_size 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "thread-id" version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1850,20 +1884,12 @@ dependencies = [ "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "toml" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "serde 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "toml" version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1873,7 +1899,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "unicode-bidi" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1886,7 +1912,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "unicode-segmentation" -version = "1.2.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1934,7 +1960,7 @@ name = "url_serde" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2006,7 +2032,7 @@ name = "xattr" version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2030,14 +2056,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum atty 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d912da0db7fa85514874458ca3651fe2cddace8d0b0505571dbdcd41ab490159" "checksum backtrace 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "72f9b4182546f4b04ebc4ab7f84948953a118bd6021a1b6a6c909e3e94f6be76" "checksum backtrace-sys 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "3a0d842ea781ce92be2bf78a9b38883948542749640b8378b3b2f03d1fd9f1ff" -"checksum bitflags 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4f67931368edf3a9a51d29886d245f1c3db2f1ef0dcc9e35ff70341b78c10d23" "checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d" "checksum bitflags 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1370e9fc2a6ae53aea8b7a5110edbd08836ed87c88736dfabccade1c2b44bff4" "checksum bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5" "checksum bufstream 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f2f382711e76b9de6c744cc00d0497baba02fb00a787f088c879f01d09468e32" "checksum cargo 0.21.0 (git+https://github.com/rust-lang/cargo)" = "" -"checksum cfg-if 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d0c47d456a36ebf0536a6705c83c1cbbcb9255fbc1d905a6ded104f479268a29" -"checksum clap 2.24.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6b8f69e518f967224e628896b54e41ff6acfb4dcfefc5076325c36525dac900f" +"checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de" +"checksum clap 2.25.0 (registry+https://github.com/rust-lang/crates.io-index)" = "867a885995b4184be051b70a592d4d70e32d7a188db6e8dff626af286a962771" "checksum cmake 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)" = "b8ebbb35d3dc9cd09497168f33de1acb79b265d350ab0ac34133b98f8509af1f" "checksum crossbeam 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "0c5ea215664ca264da8a9d9c3be80d2eaf30923c259d03e870388eb927508f97" "checksum curl 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "6689276ab61f97c660669a5ecc117c36875dfc1ba301c986b16c653415bdf9d7" @@ -2061,22 +2086,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum git2-curl 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "68676bc784bf0bef83278898929bf64a251e87c0340723d0b93fa096c9c5bf8e" "checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" "checksum hamcrest 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bf088f042a467089e9baa4972f57f9247e42a0cc549ba264c7a04fbb8ecb89d4" -"checksum handlebars 0.25.3 (registry+https://github.com/rust-lang/crates.io-index)" = "15bdf598fc3c2de40c6b340213028301c0d225eea55a2294e6cc148074e557a1" +"checksum handlebars 0.26.2 (registry+https://github.com/rust-lang/crates.io-index)" = "fbba80e74e9591a5f6a4ffff6b7f9d645759a896e431cfbdc853e9184370294a" "checksum hex 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d6a22814455d41612f41161581c2883c0c6a1c41852729b17d5ed88f01e153aa" "checksum idna 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2233d4940b1f19f0418c158509cd7396b8d70a5db5705ce410914dc8fa603b37" "checksum itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eb2f404fbc66fd9aac13e998248505e7ecb2ad8e44ab6388684c5fb11c6c251c" -"checksum jobserver 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "4e28adc987f6d0521ef66ad60b055968107b164b3bb3cf3dc8474e0a380474a6" +"checksum jobserver 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "443ae8bc0af6c106e6e8b77e04684faecc1a5ce94e058f4c2b0a037b0ea1b133" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum languageserver-types 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)" = "680aee78c75504fdcb172635a7b7da0dccaafa4c42d935e19576c14b27942362" "checksum lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3b37545ab726dd833ec6420aaba8231c5b320814b9029ad585555d2a03e94fbf" -"checksum libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)" = "38f5c2b18a287cf78b4097db62e20f43cace381dc76ae5c0a3073067f78b7ddc" +"checksum libc 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)" = "30885bcb161cf67054244d10d4a7f4835ffd58773bc72e07d35fecf472295503" "checksum libgit2-sys 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "df18a822100352d9863b302faf6f8f25c0e77f0e60feb40e5dbe1238b7f13b1d" "checksum libssh2-sys 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0db4ec23611747ef772db1c4d650f8bd762f07b461727ec998f953c614024b75" "checksum libz-sys 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)" = "3fdd64ef8ee652185674455c1d450b83cbc8ad895625d543b5324d923f82e4d8" "checksum log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "880f77541efa6e5cc74e76910c9884d9859683118839d6a1dc3b11e63512565b" "checksum lzma-sys 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "013fa6506eb7d26040c46dab9ecb7ccb4e2896b5bf24a9d65932501ea9f67af8" "checksum matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "100aabe6b8ff4e4a7e32c1c13523379802df0772b82466207ac25b013f193376" -"checksum mdbook 0.0.21 (registry+https://github.com/rust-lang/crates.io-index)" = "f1e2e9d848514dcfad4195788d0d42ae5153a477c191d75d5b84fab10f222fbd" +"checksum mdbook 0.0.22 (registry+https://github.com/rust-lang/crates.io-index)" = "22911d86cde6f80fa9f0fb2a68bbbde85d97af4fe0ce267141c83a4187d28700" "checksum memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d8b629fb514376c675b98c1421e80b151d3817ac42d7c667717d282761418d20" "checksum memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1dbccc0e46f1ea47b9f17e6d67c5a96bd27030519c519c9c91327e31275a47b4" "checksum miniz-sys 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "28eaee17666671fa872e567547e8428e83308ebe5808cdf6a0e28397dbe2c726" @@ -2100,7 +2125,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3a8b4c6b8165cd1a1cd4b9b120978131389f64bdaf456435caa41e630edba903" "checksum psapi-sys 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "abcd5d1a07d360e29727f757a9decb3ce8bc6e0efa8969cfaad669a8317a2478" "checksum pulldown-cmark 0.0.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9ab1e588ef8efd702c7ed9d2bd774db5e6f4d878bb5a1a9f371828fbdff6973" -"checksum pulldown-cmark 0.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "1058d7bb927ca067656537eec4e02c2b4b70eaaa129664c5b90c111e20326f41" "checksum quick-error 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c36987d4978eb1be2e422b1e0423a557923a5c3e7e6f31d5699e9aafaefa469" "checksum quote 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4c5cf478fe1006dbcc72567121d23dbdae5f1632386068c5c86ff4f645628504" "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" @@ -2110,23 +2134,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1731164734096285ec2a5ec7fea5248ae2f5485b3feeb0115af4fda2183b2d1b" "checksum regex-syntax 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "f9ec002c35e86791825ed294b50008eea9ddfc8def4420124fbc6b08db834957" "checksum regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad890a5eef7953f55427c50575c680c42841653abd2b028b68cd223d157f62db" -"checksum rls-analysis 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "78a05b130793ebc781c2d933299d7214a10d014fdebe5184eb652c81ba8d3184" +"checksum rls-analysis 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ea940411ed2ad6d1e705fc2a0b146a0a3f30f8098ba4e61b45b4e5f2bfa7ed63" "checksum rls-data 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e502ac679bc35e023e982506c32d0278ef89e29af1e4ad21cb70c44b525b87a9" "checksum rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d7c7046dc6a92f2ae02ed302746db4382e75131b9ce20ce967259f6b5867a6a" -"checksum rls-vfs 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1f19246a0fda45f2fb6eb34addef2a692c044cbf1c90ec7695583450fb5f23e7" +"checksum rls-vfs 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ffd34691a510938bb67fe0444fb363103c73ffb31c121d1e16bc92d8945ea8ff" "checksum rustc-demangle 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3058a43ada2c2d0b92b3ae38007a2d0fa5e9db971be260e0171408a4ff471c95" "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" -"checksum rustfmt-nightly 0.1.8 (git+https://github.com/rust-lang-nursery/rustfmt?branch=rustfmt-42492)" = "" +"checksum rustfmt-nightly 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "6693f90ac7d0a2291aa309f5214f5f3ac1bd79961c11116fcf6d5545749bf2e7" "checksum same-file 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d931a44fdaa43b8637009e7632a02adc4f2b2e0733c08caa4cf00e8da4a117a7" "checksum scoped-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f417c22df063e9450888a7561788e9bd46d3bb3c1466435b4eccb903807f147d" "checksum semver 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3fdd61b85a0fa777f7fb7c454b9189b2941b110d1385ce84d7f76efdf1606a85" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum serde 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)" = "34b623917345a631dc9608d5194cc206b3fe6c3554cd1c75b937e55e285254af" -"checksum serde 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "c2f530d36fb84ec48fb7146936881f026cdbf4892028835fd9398475f82c1bb4" -"checksum serde_derive 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "10552fad5500771f3902d0c5ba187c5881942b811b7ba0d8fbbfbf84d80806d3" +"checksum serde 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)" = "433d7d9f8530d5a939ad5e0e72a6243d2e42a24804f70bf592c679363dcacb2f" +"checksum serde_derive 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)" = "7b707cf0d4cab852084f573058def08879bb467fda89d99052485e7d00edd624" "checksum serde_derive_internals 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)" = "37aee4e0da52d801acfbc0cc219eb1eda7142112339726e427926a6f6ee65d3a" "checksum serde_ignored 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c10e798e4405d7dcec3658989e35ee6706f730a9ed7c1184d5ebd84317e82f46" -"checksum serde_json 0.9.10 (registry+https://github.com/rust-lang/crates.io-index)" = "ad8bcf487be7d2e15d3d543f04312de991d631cfe1b43ea0ade69e6a8a5b16a1" "checksum serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "48b04779552e92037212c3615370f6bd57a40ebba7f20e554ff9f55e41a69a7b" "checksum shell-escape 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "dd5cc96481d54583947bfe88bf30c23d53f883c6cd0145368b69989d97b84ef8" "checksum socket2 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "12cdbddbaa27bf94cc194b8e37f5811db6fe83cea96cf99cf1f8e92b65a41371" @@ -2144,17 +2166,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "fa63644f74ce96fbeb9b794f66aff2a52d601cbd5e80f4b97123e3899f4570f1" "checksum term_size 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2b6b55df3198cc93372e85dd2ed817f0e38ce8cc0f22eb32391bfad9c4bf209" "checksum termcolor 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9a5193a56b8d82014662c4b933dea6bec851daf018a2b01722e007daaf5f9dca" +"checksum textwrap 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f86300c3e7416ee233abd7cda890c492007a3980f941f79185c753a701257167" "checksum thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9539db560102d1cef46b8b78ce737ff0bb64e7e18d35b2a5688f7d097d0ff03" "checksum thread_local 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "8576dbbfcaef9641452d5cf0df9b0e7eeab7694956dd33bb61515fb8f18cfdd5" "checksum thread_local 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1697c4b57aeeb7a536b647165a2825faddffb1d3bad386d507709bd51a90bb14" "checksum toml 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)" = "0590d72182e50e879c4da3b11c6488dae18fccb1ae0c7a3eda18e16795844796" "checksum toml 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "736b60249cb25337bc196faa43ee12c705e426f3d55c214d73a4e7be06f92cb4" -"checksum toml 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bd86ad9ebee246fdedd610e0f6d0587b754a3d81438db930a244d0480ed7878f" "checksum toml 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b0601da6c97135c8d330c7a13a013ca6cd4143221b01de2f8d4edc50a9e551c7" "checksum typed-arena 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5934776c3ac1bea4a9d56620d6bf2d483b20d394e49581db40f187e1118ff667" -"checksum unicode-bidi 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a6a2c4e3710edd365cd7e78383153ed739fa31af19f9172f72d3575060f5a43a" +"checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" "checksum unicode-normalization 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "51ccda9ef9efa3f7ef5d91e8f9b83bbe6955f9bf86aec89d5cce2c874625920f" -"checksum unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a8083c594e02b8ae1654ae26f0ade5158b119bd88ad0e8227a5d8fcd72407946" +"checksum unicode-segmentation 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "18127285758f0e2c6cf325bb3f3d138a12fee27de4f23e146cd6a179f26c2cf3" "checksum unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bf3a113775714a22dcb774d8ea3655c53a32debae63a063acc00a91cc586245f" "checksum unicode-xid 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "36dff09cafb4ec7c8cf0023eb0b686cb6ce65499116a12201c9e11840ca01beb" "checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" diff --git a/src/Cargo.toml b/src/Cargo.toml index 9cf6297d463be..f027965e791be 100644 --- a/src/Cargo.toml +++ b/src/Cargo.toml @@ -17,6 +17,20 @@ members = [ "tools/rust-installer", "tools/cargo", "tools/rls", + # FIXME(https://github.com/rust-lang/cargo/issues/4089): move these to exclude + "tools/rls/test_data/borrow_error", + "tools/rls/test_data/completion", + "tools/rls/test_data/find_all_refs", + "tools/rls/test_data/find_all_refs_no_cfg_test", + "tools/rls/test_data/goto_def", + "tools/rls/test_data/highlight", + "tools/rls/test_data/hover", + "tools/rls/test_data/rename", + "tools/rls/test_data/reformat", + "tools/rls/test_data/bin_lib_no_cfg_test", + "tools/rls/test_data/multiple_bins", + "tools/rls/test_data/bin_lib", + "tools/rls/test_data/reformat_with_range", ] # Curiously, compiletest will segfault if compiled with opt-level=3 on 64-bit diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs index 497a5ab6c536c..134406b1acdb3 100644 --- a/src/bootstrap/bin/rustc.rs +++ b/src/bootstrap/bin/rustc.rs @@ -150,7 +150,12 @@ fn main() { // This... is a bit of a hack how we detect this. Ideally this // information should be encoded in the crate I guess? Would likely // require an RFC amendment to RFC 1513, however. - if crate_name == "panic_abort" { + // + // `compiler_builtins` are unconditionally compiled with panic=abort to + // workaround undefined references to `rust_eh_unwind_resume` generated + // otherwise, see issue https://github.com/rust-lang/rust/issues/43095. + if crate_name == "panic_abort" || + crate_name == "compiler_builtins" && stage != "0" { cmd.arg("-C").arg("panic=abort"); } diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index 371512908a031..e4b0e2fb9ca0c 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -15,6 +15,7 @@ use std::collections::HashSet; use std::env; +use std::ffi::OsString; use std::iter; use std::fmt; use std::fs::{self, File}; @@ -117,14 +118,7 @@ pub fn cargotest(build: &Build, stage: u32, host: &str) { /// Runs `cargo test` for `cargo` packaged with Rust. pub fn cargo(build: &Build, stage: u32, host: &str) { - let ref compiler = Compiler::new(stage, host); - - // Configure PATH to find the right rustc. NB. we have to use PATH - // and not RUSTC because the Cargo test suite has tests that will - // fail if rustc is not spelled `rustc`. - let path = build.sysroot(compiler).join("bin"); - let old_path = env::var_os("PATH").unwrap_or_default(); - let newpath = env::join_paths(iter::once(path).chain(env::split_paths(&old_path))).expect(""); + let compiler = &Compiler::new(stage, host); let mut cargo = build.cargo(compiler, Mode::Tool, host, "test"); cargo.arg("--manifest-path").arg(build.src.join("src/tools/cargo/Cargo.toml")); @@ -139,7 +133,31 @@ pub fn cargo(build: &Build, stage: u32, host: &str) { // available. cargo.env("CFG_DISABLE_CROSS_TESTS", "1"); - try_run(build, cargo.env("PATH", newpath)); + try_run(build, cargo.env("PATH", &path_for_cargo(build, compiler))); +} + +/// Runs `cargo test` for the rls. +pub fn rls(build: &Build, stage: u32, host: &str) { + let compiler = &Compiler::new(stage, host); + + let mut cargo = build.cargo(compiler, Mode::Tool, host, "test"); + cargo.arg("--manifest-path").arg(build.src.join("src/tools/rls/Cargo.toml")); + + // Don't build tests dynamically, just a pain to work with + cargo.env("RUSTC_NO_PREFER_DYNAMIC", "1"); + + build.add_rustc_lib_path(compiler, &mut cargo); + + try_run(build, &mut cargo); +} + +fn path_for_cargo(build: &Build, compiler: &Compiler) -> OsString { + // Configure PATH to find the right rustc. NB. we have to use PATH + // and not RUSTC because the Cargo test suite has tests that will + // fail if rustc is not spelled `rustc`. + let path = build.sysroot(compiler).join("bin"); + let old_path = env::var_os("PATH").unwrap_or_default(); + env::join_paths(iter::once(path).chain(env::split_paths(&old_path))).expect("") } /// Runs the `tidy` tool as compiled in `stage` by the `host` compiler. diff --git a/src/bootstrap/mk/Makefile.in b/src/bootstrap/mk/Makefile.in index 47c792a510b1b..ad0ee8d47d643 100644 --- a/src/bootstrap/mk/Makefile.in +++ b/src/bootstrap/mk/Makefile.in @@ -55,7 +55,8 @@ check: check-aux: $(Q)$(BOOTSTRAP) test \ src/tools/cargotest \ - cargo \ + src/tools/cargo \ + src/tools/rls \ src/test/pretty \ src/test/run-pass/pretty \ src/test/run-fail/pretty \ diff --git a/src/bootstrap/step.rs b/src/bootstrap/step.rs index c221d7076832f..a1b26f44b7de1 100644 --- a/src/bootstrap/step.rs +++ b/src/bootstrap/step.rs @@ -28,6 +28,7 @@ use std::collections::{BTreeMap, HashSet, HashMap}; use std::mem; +use std::path::PathBuf; use std::process; use check::{self, TestKind}; @@ -471,10 +472,14 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules { .dep(|s| s.name("librustc")) .host(true) .run(move |s| check::cargotest(build, s.stage, s.target)); - rules.test("check-cargo", "cargo") + rules.test("check-cargo", "src/tools/cargo") .dep(|s| s.name("tool-cargo")) .host(true) .run(move |s| check::cargo(build, s.stage, s.target)); + rules.test("check-rls", "src/tools/rls") + .dep(|s| s.name("tool-rls")) + .host(true) + .run(move |s| check::rls(build, s.stage, s.target)); rules.test("check-tidy", "src/tools/tidy") .dep(|s| s.name("tool-tidy").stage(0)) .default(true) @@ -1209,11 +1214,19 @@ invalid rule dependency graph detected, was a rule added and maybe typo'd? if paths.len() == 0 && rule.default { Some((rule, 0)) } else { - paths.iter().position(|path| path.ends_with(rule.path)) + paths.iter() + .position(|path| path.ends_with(rule.path)) .map(|priority| (rule, priority)) } }).collect(); + if rules.is_empty() && + !paths.get(0).unwrap_or(&PathBuf::new()) + .ends_with("nonexistent/path/to/trigger/cargo/metadata") { + println!("\nNothing to run...\n"); + process::exit(1); + } + rules.sort_by_key(|&(_, priority)| priority); rules.into_iter().flat_map(|(rule, _)| { diff --git a/src/ci/docker/arm-android/Dockerfile b/src/ci/docker/arm-android/Dockerfile index 2a928c5ec7e89..6cdaf6acfef64 100644 --- a/src/ci/docker/arm-android/Dockerfile +++ b/src/ci/docker/arm-android/Dockerfile @@ -1,31 +1,15 @@ FROM ubuntu:16.04 -RUN apt-get update && \ - apt-get install -y --no-install-recommends \ - ca-certificates \ - cmake \ - curl \ - file \ - g++ \ - git \ - libssl-dev \ - make \ - pkg-config \ - python2.7 \ - sudo \ - unzip \ - xz-utils - -# dumb-init +COPY scripts/android-base-apt-get.sh /scripts/ +RUN sh /scripts/android-base-apt-get.sh + COPY scripts/dumb-init.sh /scripts/ RUN sh /scripts/dumb-init.sh -# ndk COPY scripts/android-ndk.sh /scripts/ RUN . /scripts/android-ndk.sh && \ download_and_make_toolchain android-ndk-r13b-linux-x86_64.zip arm 9 -# sdk RUN dpkg --add-architecture i386 && \ apt-get update && \ apt-get install -y --no-install-recommends \ @@ -39,7 +23,6 @@ COPY scripts/android-sdk.sh /scripts/ RUN . /scripts/android-sdk.sh && \ download_and_create_avd tools_r25.2.5-linux.zip armeabi-v7a 18 -# env ENV PATH=$PATH:/android/sdk/tools ENV PATH=$PATH:/android/sdk/platform-tools @@ -51,10 +34,8 @@ ENV RUST_CONFIGURE_ARGS \ ENV SCRIPT python2.7 ../x.py test --target $TARGETS -# sccache COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh -# init COPY scripts/android-start-emulator.sh /scripts/ ENTRYPOINT ["/usr/bin/dumb-init", "--", "/scripts/android-start-emulator.sh"] diff --git a/src/ci/docker/armhf-gnu/Dockerfile b/src/ci/docker/armhf-gnu/Dockerfile index 03e0b78ba89b3..d289a93c35295 100644 --- a/src/ci/docker/armhf-gnu/Dockerfile +++ b/src/ci/docker/armhf-gnu/Dockerfile @@ -73,13 +73,12 @@ RUN arm-linux-gnueabihf-gcc addentropy.c -o rootfs/addentropy -static # TODO: What is this?! RUN curl -O http://ftp.nl.debian.org/debian/dists/jessie/main/installer-armhf/current/images/device-tree/vexpress-v2p-ca15-tc1.dtb -RUN curl -o /usr/local/bin/sccache \ - https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \ - chmod +x /usr/local/bin/sccache +COPY scripts/dumb-init.sh /scripts/ +RUN sh /scripts/dumb-init.sh + +COPY scripts/sccache.sh /scripts/ +RUN sh /scripts/sccache.sh -RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \ - dpkg -i dumb-init_*.deb && \ - rm dumb-init_*.deb ENTRYPOINT ["/usr/bin/dumb-init", "--"] ENV RUST_CONFIGURE_ARGS \ diff --git a/src/ci/docker/asmjs/Dockerfile b/src/ci/docker/asmjs/Dockerfile index 899ce1e4569df..1c39e8523daaa 100644 --- a/src/ci/docker/asmjs/Dockerfile +++ b/src/ci/docker/asmjs/Dockerfile @@ -13,15 +13,12 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ gdb \ xz-utils -# dumb-init COPY scripts/dumb-init.sh /scripts/ RUN sh /scripts/dumb-init.sh -# emscripten COPY scripts/emscripten.sh /scripts/ RUN bash /scripts/emscripten.sh -# env ENV PATH=$PATH:/emsdk-portable ENV PATH=$PATH:/emsdk-portable/clang/e1.37.13_64bit/ ENV PATH=$PATH:/emsdk-portable/emscripten/1.37.13/ @@ -36,9 +33,7 @@ ENV RUST_CONFIGURE_ARGS --target=$TARGETS ENV SCRIPT python2.7 ../x.py test --target $TARGETS -# cache COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh -# init ENTRYPOINT ["/usr/bin/dumb-init", "--"] diff --git a/src/ci/docker/cross/Dockerfile b/src/ci/docker/cross/Dockerfile index b4399a8d53ff0..70dfbb53da24e 100644 --- a/src/ci/docker/cross/Dockerfile +++ b/src/ci/docker/cross/Dockerfile @@ -21,7 +21,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ libssl-dev \ pkg-config -# dumb-init COPY scripts/dumb-init.sh /scripts/ RUN sh /scripts/dumb-init.sh @@ -68,5 +67,4 @@ ENV SCRIPT python2.7 ../x.py dist --target $TARGETS COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh -# init ENTRYPOINT ["/usr/bin/dumb-init", "--"] diff --git a/src/ci/docker/disabled/dist-aarch64-android/Dockerfile b/src/ci/docker/disabled/dist-aarch64-android/Dockerfile index 918d2911ae28f..1c9e036f093da 100644 --- a/src/ci/docker/disabled/dist-aarch64-android/Dockerfile +++ b/src/ci/docker/disabled/dist-aarch64-android/Dockerfile @@ -1,31 +1,15 @@ FROM ubuntu:16.04 -RUN apt-get update && \ - apt-get install -y --no-install-recommends \ - ca-certificates \ - cmake \ - curl \ - file \ - g++ \ - git \ - libssl-dev \ - make \ - pkg-config \ - python2.7 \ - sudo \ - unzip \ - xz-utils - -# dumb-init +COPY scripts/android-base-apt-get.sh /scripts/ +RUN sh /scripts/android-base-apt-get.sh + COPY scripts/dumb-init.sh /scripts/ RUN sh /scripts/dumb-init.sh -# ndk COPY scripts/android-ndk.sh /scripts/ RUN . /scripts/android-ndk.sh && \ download_and_make_toolchain android-ndk-r13b-linux-x86_64.zip arm64 21 -# env ENV PATH=$PATH:/android/ndk/arm64-21/bin ENV DEP_Z_ROOT=/android/ndk/arm64-21/sysroot/usr/ @@ -42,9 +26,7 @@ ENV RUST_CONFIGURE_ARGS \ ENV SCRIPT python2.7 ../x.py dist --target $HOSTS --host $HOSTS -# sccache COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh -# init ENTRYPOINT ["/usr/bin/dumb-init", "--"] diff --git a/src/ci/docker/disabled/dist-armv7-android/Dockerfile b/src/ci/docker/disabled/dist-armv7-android/Dockerfile index aed82e6c13872..326e00548b1ce 100644 --- a/src/ci/docker/disabled/dist-armv7-android/Dockerfile +++ b/src/ci/docker/disabled/dist-armv7-android/Dockerfile @@ -1,26 +1,11 @@ FROM ubuntu:16.04 -RUN apt-get update && \ - apt-get install -y --no-install-recommends \ - ca-certificates \ - cmake \ - curl \ - file \ - g++ \ - git \ - libssl-dev \ - make \ - pkg-config \ - python2.7 \ - sudo \ - unzip \ - xz-utils +COPY scripts/android-base-apt-get.sh /scripts/ +RUN sh /scripts/android-base-apt-get.sh -# dumb-init COPY scripts/dumb-init.sh /scripts/ RUN sh /scripts/dumb-init.sh -# ndk COPY scripts/android-ndk.sh /scripts/ RUN . /scripts/android-ndk.sh && \ download_ndk android-ndk-r13b-linux-x86_64.zip && \ @@ -31,7 +16,6 @@ RUN . /scripts/android-ndk.sh && \ RUN chmod 777 /android/ndk && \ ln -s /android/ndk/arm-21 /android/ndk/arm -# env ENV PATH=$PATH:/android/ndk/arm-9/bin ENV DEP_Z_ROOT=/android/ndk/arm-9/sysroot/usr/ @@ -60,9 +44,7 @@ ENV SCRIPT \ ln -s /android/ndk/arm-9 /android/ndk/arm && \ python2.7 ../x.py dist --host $HOSTS --target $HOSTS) -# sccache COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh -# init ENTRYPOINT ["/usr/bin/dumb-init", "--"] diff --git a/src/ci/docker/disabled/dist-i686-android/Dockerfile b/src/ci/docker/disabled/dist-i686-android/Dockerfile index f012e869e7885..d01648e2b9d7f 100644 --- a/src/ci/docker/disabled/dist-i686-android/Dockerfile +++ b/src/ci/docker/disabled/dist-i686-android/Dockerfile @@ -1,26 +1,11 @@ FROM ubuntu:16.04 -RUN apt-get update && \ - apt-get install -y --no-install-recommends \ - ca-certificates \ - cmake \ - curl \ - file \ - g++ \ - git \ - libssl-dev \ - make \ - pkg-config \ - python2.7 \ - sudo \ - unzip \ - xz-utils +COPY scripts/android-base-apt-get.sh /scripts/ +RUN sh /scripts/android-base-apt-get.sh -# dumb-init COPY scripts/dumb-init.sh /scripts/ RUN sh /scripts/dumb-init.sh -# ndk COPY scripts/android-ndk.sh /scripts/ RUN . /scripts/android-ndk.sh && \ download_ndk android-ndk-r13b-linux-x86_64.zip && \ @@ -31,7 +16,6 @@ RUN . /scripts/android-ndk.sh && \ RUN chmod 777 /android/ndk && \ ln -s /android/ndk/x86-21 /android/ndk/x86 -# env ENV PATH=$PATH:/android/ndk/x86-9/bin ENV DEP_Z_ROOT=/android/ndk/x86-9/sysroot/usr/ @@ -60,9 +44,7 @@ ENV SCRIPT \ ln -s /android/ndk/x86-9 /android/ndk/x86 && \ python2.7 ../x.py dist --host $HOSTS --target $HOSTS) -# sccache COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh -# init ENTRYPOINT ["/usr/bin/dumb-init", "--"] diff --git a/src/ci/docker/disabled/dist-x86_64-android/Dockerfile b/src/ci/docker/disabled/dist-x86_64-android/Dockerfile index 0c586452840f9..2622b4b3fac3b 100644 --- a/src/ci/docker/disabled/dist-x86_64-android/Dockerfile +++ b/src/ci/docker/disabled/dist-x86_64-android/Dockerfile @@ -1,31 +1,15 @@ FROM ubuntu:16.04 -RUN apt-get update && \ - apt-get install -y --no-install-recommends \ - ca-certificates \ - cmake \ - curl \ - file \ - g++ \ - git \ - libssl-dev \ - make \ - pkg-config \ - python2.7 \ - sudo \ - unzip \ - xz-utils - -# dumb-init +COPY scripts/android-base-apt-get.sh /scripts/ +RUN sh /scripts/android-base-apt-get.sh + COPY scripts/dumb-init.sh /scripts/ RUN sh /scripts/dumb-init.sh -# ndk COPY scripts/android-ndk.sh /scripts/ RUN . /scripts/android-ndk.sh && \ download_and_make_toolchain android-ndk-r13b-linux-x86_64.zip x86_64 21 -# env ENV PATH=$PATH:/android/ndk/x86_64-21/bin ENV DEP_Z_ROOT=/android/ndk/x86_64-21/sysroot/usr/ @@ -42,9 +26,7 @@ ENV RUST_CONFIGURE_ARGS \ ENV SCRIPT python2.7 ../x.py dist --target $HOSTS --host $HOSTS -# sccache COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh -# init ENTRYPOINT ["/usr/bin/dumb-init", "--"] diff --git a/src/ci/docker/disabled/wasm32-exp/Dockerfile b/src/ci/docker/disabled/wasm32-exp/Dockerfile new file mode 100644 index 0000000000000..4e337883165bd --- /dev/null +++ b/src/ci/docker/disabled/wasm32-exp/Dockerfile @@ -0,0 +1,42 @@ +FROM ubuntu:16.04 + +RUN apt-get update && apt-get install -y --no-install-recommends \ + g++ \ + make \ + file \ + curl \ + ca-certificates \ + python \ + git \ + cmake \ + sudo \ + gdb \ + xz-utils \ + jq \ + bzip2 + +# dumb-init +COPY scripts/dumb-init.sh /scripts/ +RUN sh /scripts/dumb-init.sh + +# emscripten +COPY scripts/emscripten-wasm.sh /scripts/ +COPY disabled/wasm32-exp/node.sh /usr/local/bin/node +RUN bash /scripts/emscripten-wasm.sh + +# cache +COPY scripts/sccache.sh /scripts/ +RUN sh /scripts/sccache.sh + +# env +ENV PATH=/wasm-install/emscripten:/wasm-install/bin:$PATH +ENV EM_CONFIG=/root/.emscripten + +ENV TARGETS=wasm32-experimental-emscripten + +ENV RUST_CONFIGURE_ARGS --target=$TARGETS --experimental-targets=WebAssembly + +ENV SCRIPT python2.7 ../x.py test --target $TARGETS + +# init +ENTRYPOINT ["/usr/bin/dumb-init", "--"] diff --git a/src/ci/docker/disabled/wasm32-exp/node.sh b/src/ci/docker/disabled/wasm32-exp/node.sh new file mode 100755 index 0000000000000..dfa7f221ffa20 --- /dev/null +++ b/src/ci/docker/disabled/wasm32-exp/node.sh @@ -0,0 +1,18 @@ +#!/bin/bash +# Copyright 2017 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. + +path="$(dirname $1)" +file="$(basename $1)" + +shift + +cd "$path" +exec /node-v8.0.0-linux-x64/bin/node "$file" "$@" diff --git a/src/ci/docker/disabled/wasm32/Dockerfile b/src/ci/docker/disabled/wasm32/Dockerfile index c75b5d455c522..60b15d7afb47d 100644 --- a/src/ci/docker/disabled/wasm32/Dockerfile +++ b/src/ci/docker/disabled/wasm32/Dockerfile @@ -11,24 +11,19 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ cmake \ sudo \ gdb \ - xz-utils \ - jq \ - bzip2 + xz-utils -# dumb-init COPY scripts/dumb-init.sh /scripts/ RUN sh /scripts/dumb-init.sh # emscripten -COPY scripts/emscripten-wasm.sh /scripts/ -RUN bash /scripts/emscripten-wasm.sh +COPY scripts/emscripten.sh /scripts/ +RUN bash /scripts/emscripten.sh COPY disabled/wasm32/node.sh /usr/local/bin/node -# cache COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh -# env ENV PATH=$PATH:/emsdk-portable ENV PATH=$PATH:/emsdk-portable/clang/e1.37.13_64bit/ ENV PATH=$PATH:/emsdk-portable/emscripten/1.37.13/ @@ -36,11 +31,10 @@ ENV EMSCRIPTEN=/emsdk-portable/emscripten/1.37.13/ ENV BINARYEN_ROOT=/emsdk-portable/clang/e1.37.13_64bit/binaryen/ ENV EM_CONFIG=/emsdk-portable/.emscripten -ENV TARGETS=wasm32-unknown-emscripten,wasm32-experimental-emscripten +ENV TARGETS=wasm32-unknown-emscripten -ENV RUST_CONFIGURE_ARGS --target=$TARGETS --experimental-targets=WebAssembly +ENV RUST_CONFIGURE_ARGS --target=$TARGETS ENV SCRIPT python2.7 ../x.py test --target $TARGETS -# init ENTRYPOINT ["/usr/bin/dumb-init", "--"] diff --git a/src/ci/docker/dist-aarch64-linux/Dockerfile b/src/ci/docker/dist-aarch64-linux/Dockerfile index 0134a5407932a..cc3b6b8c692a6 100644 --- a/src/ci/docker/dist-aarch64-linux/Dockerfile +++ b/src/ci/docker/dist-aarch64-linux/Dockerfile @@ -1,58 +1,23 @@ FROM ubuntu:16.04 -RUN apt-get update && apt-get install -y --no-install-recommends \ - automake \ - bison \ - bzip2 \ - ca-certificates \ - cmake \ - curl \ - file \ - flex \ - g++ \ - gawk \ - gdb \ - git \ - gperf \ - help2man \ - libncurses-dev \ - libtool-bin \ - make \ - patch \ - python2.7 \ - sudo \ - texinfo \ - wget \ - xz-utils \ - libssl-dev \ - pkg-config +COPY scripts/cross-apt-packages.sh /scripts/ +RUN sh /scripts/cross-apt-packages.sh + +COPY scripts/dumb-init.sh /scripts/ +RUN sh /scripts/dumb-init.sh -RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \ - dpkg -i dumb-init_*.deb && \ - rm dumb-init_*.deb ENTRYPOINT ["/usr/bin/dumb-init", "--"] -# Ubuntu 16.04 (this contianer) ships with make 4, but something in the +# Ubuntu 16.04 (this container) ships with make 4, but something in the # toolchains we build below chokes on that, so go back to make 3 -RUN curl https://ftp.gnu.org/gnu/make/make-3.81.tar.gz | tar xzf - && \ - cd make-3.81 && \ - ./configure --prefix=/usr && \ - make && \ - make install && \ - cd .. && \ - rm -rf make-3.81 +COPY scripts/make3.sh /scripts/ +RUN sh /scripts/make3.sh -RUN curl http://crosstool-ng.org/download/crosstool-ng/crosstool-ng-1.22.0.tar.bz2 | \ - tar xjf - && \ - cd crosstool-ng && \ - ./configure --prefix=/usr/local && \ - make -j$(nproc) && \ - make install && \ - cd .. && \ - rm -rf crosstool-ng +COPY scripts/crosstool-ng.sh /scripts/ +RUN sh /scripts/crosstool-ng.sh -RUN groupadd -r rustbuild && useradd -m -r -g rustbuild rustbuild -RUN mkdir /x-tools && chown rustbuild:rustbuild /x-tools +COPY scripts/rustbuild-setup.sh /scripts/ +RUN sh /scripts/rustbuild-setup.sh USER rustbuild WORKDIR /tmp @@ -61,9 +26,8 @@ RUN ./build-toolchains.sh USER root -RUN curl -o /usr/local/bin/sccache \ - https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \ - chmod +x /usr/local/bin/sccache +COPY scripts/sccache.sh /scripts/ +RUN sh /scripts/sccache.sh ENV PATH=$PATH:/x-tools/aarch64-unknown-linux-gnueabi/bin diff --git a/src/ci/docker/dist-android/Dockerfile b/src/ci/docker/dist-android/Dockerfile index 31389dd148a8a..f3beddfae0a16 100644 --- a/src/ci/docker/dist-android/Dockerfile +++ b/src/ci/docker/dist-android/Dockerfile @@ -1,22 +1,8 @@ FROM ubuntu:16.04 -RUN apt-get update && \ - apt-get install -y --no-install-recommends \ - ca-certificates \ - cmake \ - curl \ - file \ - g++ \ - git \ - libssl-dev \ - make \ - pkg-config \ - python2.7 \ - sudo \ - unzip \ - xz-utils - -# dumb-init +COPY scripts/android-base-apt-get.sh /scripts/ +RUN sh /scripts/android-base-apt-get.sh + COPY scripts/dumb-init.sh /scripts/ RUN sh /scripts/dumb-init.sh @@ -48,9 +34,7 @@ ENV RUST_CONFIGURE_ARGS \ ENV SCRIPT python2.7 ../x.py dist --target $TARGETS -# cache COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh -# init ENTRYPOINT ["/usr/bin/dumb-init", "--"] diff --git a/src/ci/docker/dist-arm-linux/Dockerfile b/src/ci/docker/dist-arm-linux/Dockerfile index 862818a7c9182..590d6eb98b382 100644 --- a/src/ci/docker/dist-arm-linux/Dockerfile +++ b/src/ci/docker/dist-arm-linux/Dockerfile @@ -1,58 +1,23 @@ FROM ubuntu:16.04 -RUN apt-get update && apt-get install -y --no-install-recommends \ - automake \ - bison \ - bzip2 \ - ca-certificates \ - cmake \ - curl \ - file \ - flex \ - g++ \ - gawk \ - gdb \ - git \ - gperf \ - help2man \ - libncurses-dev \ - libtool-bin \ - make \ - patch \ - python2.7 \ - sudo \ - texinfo \ - wget \ - xz-utils \ - libssl-dev \ - pkg-config +COPY scripts/cross-apt-packages.sh /scripts/ +RUN sh /scripts/cross-apt-packages.sh + +COPY scripts/dumb-init.sh /scripts/ +RUN sh /scripts/dumb-init.sh -RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \ - dpkg -i dumb-init_*.deb && \ - rm dumb-init_*.deb ENTRYPOINT ["/usr/bin/dumb-init", "--"] -# Ubuntu 16.04 (this contianer) ships with make 4, but something in the +# Ubuntu 16.04 (this container) ships with make 4, but something in the # toolchains we build below chokes on that, so go back to make 3 -RUN curl https://ftp.gnu.org/gnu/make/make-3.81.tar.gz | tar xzf - && \ - cd make-3.81 && \ - ./configure --prefix=/usr && \ - make && \ - make install && \ - cd .. && \ - rm -rf make-3.81 +COPY scripts/make3.sh /scripts/ +RUN sh /scripts/make3.sh -RUN curl http://crosstool-ng.org/download/crosstool-ng/crosstool-ng-1.22.0.tar.bz2 | \ - tar xjf - && \ - cd crosstool-ng && \ - ./configure --prefix=/usr/local && \ - make -j$(nproc) && \ - make install && \ - cd .. && \ - rm -rf crosstool-ng +COPY scripts/crosstool-ng.sh /scripts/ +RUN sh /scripts/crosstool-ng.sh -RUN groupadd -r rustbuild && useradd -m -r -g rustbuild rustbuild -RUN mkdir /x-tools && chown rustbuild:rustbuild /x-tools +COPY scripts/rustbuild-setup.sh /scripts/ +RUN sh /scripts/rustbuild-setup.sh USER rustbuild WORKDIR /tmp @@ -61,9 +26,8 @@ RUN ./build-toolchains.sh USER root -RUN curl -o /usr/local/bin/sccache \ - https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \ - chmod +x /usr/local/bin/sccache +COPY scripts/sccache.sh /scripts/ +RUN sh /scripts/sccache.sh ENV PATH=$PATH:/x-tools/arm-unknown-linux-gnueabi/bin diff --git a/src/ci/docker/dist-armhf-linux/Dockerfile b/src/ci/docker/dist-armhf-linux/Dockerfile index 7f1f91f844c77..b3dedc4b7f0fe 100644 --- a/src/ci/docker/dist-armhf-linux/Dockerfile +++ b/src/ci/docker/dist-armhf-linux/Dockerfile @@ -1,58 +1,23 @@ FROM ubuntu:16.04 -RUN apt-get update && apt-get install -y --no-install-recommends \ - automake \ - bison \ - bzip2 \ - ca-certificates \ - cmake \ - curl \ - file \ - flex \ - g++ \ - gawk \ - gdb \ - git \ - gperf \ - help2man \ - libncurses-dev \ - libtool-bin \ - make \ - patch \ - python2.7 \ - sudo \ - texinfo \ - wget \ - xz-utils \ - libssl-dev \ - pkg-config +COPY scripts/cross-apt-packages.sh /scripts/ +RUN sh /scripts/cross-apt-packages.sh + +COPY scripts/dumb-init.sh /scripts/ +RUN sh /scripts/dumb-init.sh -RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \ - dpkg -i dumb-init_*.deb && \ - rm dumb-init_*.deb ENTRYPOINT ["/usr/bin/dumb-init", "--"] -# Ubuntu 16.04 (this contianer) ships with make 4, but something in the +# Ubuntu 16.04 (this container) ships with make 4, but something in the # toolchains we build below chokes on that, so go back to make 3 -RUN curl https://ftp.gnu.org/gnu/make/make-3.81.tar.gz | tar xzf - && \ - cd make-3.81 && \ - ./configure --prefix=/usr && \ - make && \ - make install && \ - cd .. && \ - rm -rf make-3.81 +COPY scripts/make3.sh /scripts/ +RUN sh /scripts/make3.sh -RUN curl http://crosstool-ng.org/download/crosstool-ng/crosstool-ng-1.22.0.tar.bz2 | \ - tar xjf - && \ - cd crosstool-ng && \ - ./configure --prefix=/usr/local && \ - make -j$(nproc) && \ - make install && \ - cd .. && \ - rm -rf crosstool-ng +COPY scripts/crosstool-ng.sh /scripts/ +RUN sh /scripts/crosstool-ng.sh -RUN groupadd -r rustbuild && useradd -m -r -g rustbuild rustbuild -RUN mkdir /x-tools && chown rustbuild:rustbuild /x-tools +COPY scripts/rustbuild-setup.sh /scripts/ +RUN sh /scripts/rustbuild-setup.sh USER rustbuild WORKDIR /tmp @@ -61,9 +26,8 @@ RUN ./build-toolchains.sh USER root -RUN curl -o /usr/local/bin/sccache \ - https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \ - chmod +x /usr/local/bin/sccache +COPY scripts/sccache.sh /scripts/ +RUN sh /scripts/sccache.sh ENV PATH=$PATH:/x-tools/arm-unknown-linux-gnueabihf/bin diff --git a/src/ci/docker/dist-armv7-linux/Dockerfile b/src/ci/docker/dist-armv7-linux/Dockerfile index 030fd24ebcdd0..82536b68bbe06 100644 --- a/src/ci/docker/dist-armv7-linux/Dockerfile +++ b/src/ci/docker/dist-armv7-linux/Dockerfile @@ -1,58 +1,23 @@ FROM ubuntu:16.04 -RUN apt-get update && apt-get install -y --no-install-recommends \ - automake \ - bison \ - bzip2 \ - ca-certificates \ - cmake \ - curl \ - file \ - flex \ - g++ \ - gawk \ - gdb \ - git \ - gperf \ - help2man \ - libncurses-dev \ - libtool-bin \ - make \ - patch \ - python2.7 \ - sudo \ - texinfo \ - wget \ - xz-utils \ - libssl-dev \ - pkg-config +COPY scripts/cross-apt-packages.sh /scripts/ +RUN sh /scripts/cross-apt-packages.sh + +COPY scripts/dumb-init.sh /scripts/ +RUN sh /scripts/dumb-init.sh -RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \ - dpkg -i dumb-init_*.deb && \ - rm dumb-init_*.deb ENTRYPOINT ["/usr/bin/dumb-init", "--"] -# Ubuntu 16.04 (this contianer) ships with make 4, but something in the +# Ubuntu 16.04 (this container) ships with make 4, but something in the # toolchains we build below chokes on that, so go back to make 3 -RUN curl https://ftp.gnu.org/gnu/make/make-3.81.tar.gz | tar xzf - && \ - cd make-3.81 && \ - ./configure --prefix=/usr && \ - make && \ - make install && \ - cd .. && \ - rm -rf make-3.81 +COPY scripts/make3.sh /scripts/ +RUN sh /scripts/make3.sh -RUN curl http://crosstool-ng.org/download/crosstool-ng/crosstool-ng-1.22.0.tar.bz2 | \ - tar xjf - && \ - cd crosstool-ng && \ - ./configure --prefix=/usr/local && \ - make -j$(nproc) && \ - make install && \ - cd .. && \ - rm -rf crosstool-ng +COPY scripts/crosstool-ng.sh /scripts/ +RUN sh /scripts/crosstool-ng.sh -RUN groupadd -r rustbuild && useradd -m -r -g rustbuild rustbuild -RUN mkdir /x-tools && chown rustbuild:rustbuild /x-tools +COPY scripts/rustbuild-setup.sh /scripts/ +RUN sh /scripts/rustbuild-setup.sh USER rustbuild WORKDIR /tmp @@ -61,9 +26,8 @@ RUN ./build-toolchains.sh USER root -RUN curl -o /usr/local/bin/sccache \ - https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \ - chmod +x /usr/local/bin/sccache +COPY scripts/sccache.sh /scripts/ +RUN sh /scripts/sccache.sh ENV PATH=$PATH:/x-tools/armv7-unknown-linux-gnueabihf/bin diff --git a/src/ci/docker/dist-fuchsia/Dockerfile b/src/ci/docker/dist-fuchsia/Dockerfile index d1d9767d35e63..24ad12a49007c 100644 --- a/src/ci/docker/dist-fuchsia/Dockerfile +++ b/src/ci/docker/dist-fuchsia/Dockerfile @@ -24,14 +24,13 @@ WORKDIR /tmp COPY dist-fuchsia/shared.sh dist-fuchsia/build-toolchain.sh dist-fuchsia/compiler-rt-dso-handle.patch /tmp/ RUN /tmp/build-toolchain.sh -RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \ - dpkg -i dumb-init_*.deb && \ - rm dumb-init_*.deb +COPY scripts/dumb-init.sh /scripts/ +RUN sh /scripts/dumb-init.sh + ENTRYPOINT ["/usr/bin/dumb-init", "--"] -RUN curl -o /usr/local/bin/sccache \ - https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \ - chmod +x /usr/local/bin/sccache +COPY scripts/sccache.sh /scripts/ +RUN sh /scripts/sccache.sh ENV \ AR_x86_64_unknown_fuchsia=x86_64-unknown-fuchsia-ar \ diff --git a/src/ci/docker/dist-i586-gnu-i686-musl/Dockerfile b/src/ci/docker/dist-i586-gnu-i686-musl/Dockerfile index 805d238de1f9b..036dce2a73526 100644 --- a/src/ci/docker/dist-i586-gnu-i686-musl/Dockerfile +++ b/src/ci/docker/dist-i586-gnu-i686-musl/Dockerfile @@ -20,14 +20,13 @@ WORKDIR /build/ COPY dist-i586-gnu-i686-musl/musl-libunwind-patch.patch dist-i586-gnu-i686-musl/build-musl.sh /build/ RUN sh /build/build-musl.sh && rm -rf /build -RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \ - dpkg -i dumb-init_*.deb && \ - rm dumb-init_*.deb +COPY scripts/dumb-init.sh /scripts/ +RUN sh /scripts/dumb-init.sh + ENTRYPOINT ["/usr/bin/dumb-init", "--"] -RUN curl -o /usr/local/bin/sccache \ - https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \ - chmod +x /usr/local/bin/sccache +COPY scripts/sccache.sh /scripts/ +RUN sh /scripts/sccache.sh ENV RUST_CONFIGURE_ARGS \ --target=i686-unknown-linux-musl,i586-unknown-linux-gnu \ diff --git a/src/ci/docker/dist-i686-freebsd/Dockerfile b/src/ci/docker/dist-i686-freebsd/Dockerfile index 9c4d43bfa92bc..c40881332a108 100644 --- a/src/ci/docker/dist-i686-freebsd/Dockerfile +++ b/src/ci/docker/dist-i686-freebsd/Dockerfile @@ -19,14 +19,13 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ COPY dist-i686-freebsd/build-toolchain.sh /tmp/ RUN /tmp/build-toolchain.sh i686 -RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \ - dpkg -i dumb-init_*.deb && \ - rm dumb-init_*.deb +COPY scripts/dumb-init.sh /scripts/ +RUN sh /scripts/dumb-init.sh + ENTRYPOINT ["/usr/bin/dumb-init", "--"] -RUN curl -o /usr/local/bin/sccache \ - https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \ - chmod +x /usr/local/bin/sccache +COPY scripts/sccache.sh /scripts/ +RUN sh /scripts/sccache.sh ENV \ AR_i686_unknown_freebsd=i686-unknown-freebsd10-ar \ diff --git a/src/ci/docker/dist-i686-linux/Dockerfile b/src/ci/docker/dist-i686-linux/Dockerfile index 9145e9dfc8d1a..beb53783bac40 100644 --- a/src/ci/docker/dist-i686-linux/Dockerfile +++ b/src/ci/docker/dist-i686-linux/Dockerfile @@ -81,9 +81,8 @@ RUN curl -Lo /rustroot/dumb-init \ chmod +x /rustroot/dumb-init ENTRYPOINT ["/rustroot/dumb-init", "--"] -RUN curl -o /usr/local/bin/sccache \ - https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \ - chmod +x /usr/local/bin/sccache +COPY scripts/sccache.sh /scripts/ +RUN sh /scripts/sccache.sh ENV HOSTS=i686-unknown-linux-gnu diff --git a/src/ci/docker/dist-mips-linux/Dockerfile b/src/ci/docker/dist-mips-linux/Dockerfile index c23240f0c70f9..81997e0508ac5 100644 --- a/src/ci/docker/dist-mips-linux/Dockerfile +++ b/src/ci/docker/dist-mips-linux/Dockerfile @@ -16,13 +16,13 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ libssl-dev \ pkg-config -RUN curl -o /usr/local/bin/sccache \ - https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \ - chmod +x /usr/local/bin/sccache -RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \ - dpkg -i dumb-init_*.deb && \ - rm dumb-init_*.deb +COPY scripts/dumb-init.sh /scripts/ +RUN sh /scripts/dumb-init.sh + +COPY scripts/sccache.sh /scripts/ +RUN sh /scripts/sccache.sh + ENTRYPOINT ["/usr/bin/dumb-init", "--"] ENV HOSTS=mips-unknown-linux-gnu diff --git a/src/ci/docker/dist-mips64-linux/Dockerfile b/src/ci/docker/dist-mips64-linux/Dockerfile index 415dca99d95ee..646cb4d256ac0 100644 --- a/src/ci/docker/dist-mips64-linux/Dockerfile +++ b/src/ci/docker/dist-mips64-linux/Dockerfile @@ -16,13 +16,12 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ libssl-dev \ pkg-config -RUN curl -o /usr/local/bin/sccache \ - https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \ - chmod +x /usr/local/bin/sccache +COPY scripts/dumb-init.sh /scripts/ +RUN sh /scripts/dumb-init.sh + +COPY scripts/sccache.sh /scripts/ +RUN sh /scripts/sccache.sh -RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \ - dpkg -i dumb-init_*.deb && \ - rm dumb-init_*.deb ENTRYPOINT ["/usr/bin/dumb-init", "--"] ENV HOSTS=mips64-unknown-linux-gnuabi64 diff --git a/src/ci/docker/dist-mips64el-linux/Dockerfile b/src/ci/docker/dist-mips64el-linux/Dockerfile index 2aba5f615baba..1abb04fd8b286 100644 --- a/src/ci/docker/dist-mips64el-linux/Dockerfile +++ b/src/ci/docker/dist-mips64el-linux/Dockerfile @@ -16,13 +16,13 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ libssl-dev \ pkg-config -RUN curl -o /usr/local/bin/sccache \ - https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \ - chmod +x /usr/local/bin/sccache -RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \ - dpkg -i dumb-init_*.deb && \ - rm dumb-init_*.deb +COPY scripts/dumb-init.sh /scripts/ +RUN sh /scripts/dumb-init.sh + +COPY scripts/sccache.sh /scripts/ +RUN sh /scripts/sccache.sh + ENTRYPOINT ["/usr/bin/dumb-init", "--"] ENV HOSTS=mips64el-unknown-linux-gnuabi64 diff --git a/src/ci/docker/dist-mipsel-linux/Dockerfile b/src/ci/docker/dist-mipsel-linux/Dockerfile index d15e3010863c4..a78e39e7d7129 100644 --- a/src/ci/docker/dist-mipsel-linux/Dockerfile +++ b/src/ci/docker/dist-mipsel-linux/Dockerfile @@ -16,13 +16,12 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ libssl-dev \ pkg-config -RUN curl -o /usr/local/bin/sccache \ - https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \ - chmod +x /usr/local/bin/sccache +COPY scripts/dumb-init.sh /scripts/ +RUN sh /scripts/dumb-init.sh + +COPY scripts/sccache.sh /scripts/ +RUN sh /scripts/sccache.sh -RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \ - dpkg -i dumb-init_*.deb && \ - rm dumb-init_*.deb ENTRYPOINT ["/usr/bin/dumb-init", "--"] ENV HOSTS=mipsel-unknown-linux-gnu diff --git a/src/ci/docker/dist-powerpc-linux/Dockerfile b/src/ci/docker/dist-powerpc-linux/Dockerfile index 0074665f34f7e..ed9f883cc83f7 100644 --- a/src/ci/docker/dist-powerpc-linux/Dockerfile +++ b/src/ci/docker/dist-powerpc-linux/Dockerfile @@ -1,58 +1,23 @@ FROM ubuntu:16.04 -RUN apt-get update && apt-get install -y --no-install-recommends \ - automake \ - bison \ - bzip2 \ - ca-certificates \ - cmake \ - curl \ - file \ - flex \ - g++ \ - gawk \ - gdb \ - git \ - gperf \ - help2man \ - libncurses-dev \ - libtool-bin \ - make \ - patch \ - python2.7 \ - sudo \ - texinfo \ - wget \ - xz-utils \ - libssl-dev \ - pkg-config +COPY scripts/cross-apt-packages.sh /scripts/ +RUN sh /scripts/cross-apt-packages.sh + +COPY scripts/dumb-init.sh /scripts/ +RUN sh /scripts/dumb-init.sh -RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \ - dpkg -i dumb-init_*.deb && \ - rm dumb-init_*.deb ENTRYPOINT ["/usr/bin/dumb-init", "--"] -# Ubuntu 16.04 (this contianer) ships with make 4, but something in the +# Ubuntu 16.04 (this container) ships with make 4, but something in the # toolchains we build below chokes on that, so go back to make 3 -RUN curl https://ftp.gnu.org/gnu/make/make-3.81.tar.gz | tar xzf - && \ - cd make-3.81 && \ - ./configure --prefix=/usr && \ - make && \ - make install && \ - cd .. && \ - rm -rf make-3.81 +COPY scripts/make3.sh /scripts/ +RUN sh /scripts/make3.sh -RUN curl http://crosstool-ng.org/download/crosstool-ng/crosstool-ng-1.22.0.tar.bz2 | \ - tar xjf - && \ - cd crosstool-ng && \ - ./configure --prefix=/usr/local && \ - make -j$(nproc) && \ - make install && \ - cd .. && \ - rm -rf crosstool-ng +COPY scripts/crosstool-ng.sh /scripts/ +RUN sh /scripts/crosstool-ng.sh -RUN groupadd -r rustbuild && useradd -m -r -g rustbuild rustbuild -RUN mkdir /x-tools && chown rustbuild:rustbuild /x-tools +COPY scripts/rustbuild-setup.sh /scripts/ +RUN sh /scripts/rustbuild-setup.sh USER rustbuild WORKDIR /tmp @@ -62,9 +27,8 @@ RUN ./build-powerpc-toolchain.sh USER root -RUN curl -o /usr/local/bin/sccache \ - https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \ - chmod +x /usr/local/bin/sccache +COPY scripts/sccache.sh /scripts/ +RUN sh /scripts/sccache.sh ENV PATH=$PATH:/x-tools/powerpc-unknown-linux-gnu/bin diff --git a/src/ci/docker/dist-powerpc64-linux/Dockerfile b/src/ci/docker/dist-powerpc64-linux/Dockerfile index bd38ee0c11158..523211498fb43 100644 --- a/src/ci/docker/dist-powerpc64-linux/Dockerfile +++ b/src/ci/docker/dist-powerpc64-linux/Dockerfile @@ -1,58 +1,23 @@ FROM ubuntu:16.04 -RUN apt-get update && apt-get install -y --no-install-recommends \ - automake \ - bison \ - bzip2 \ - ca-certificates \ - cmake \ - curl \ - file \ - flex \ - g++ \ - gawk \ - gdb \ - git \ - gperf \ - help2man \ - libncurses-dev \ - libtool-bin \ - make \ - patch \ - python2.7 \ - sudo \ - texinfo \ - wget \ - xz-utils \ - libssl-dev \ - pkg-config +COPY scripts/cross-apt-packages.sh /scripts/ +RUN sh /scripts/cross-apt-packages.sh + +COPY scripts/dumb-init.sh /scripts/ +RUN sh /scripts/dumb-init.sh -RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \ - dpkg -i dumb-init_*.deb && \ - rm dumb-init_*.deb ENTRYPOINT ["/usr/bin/dumb-init", "--"] -# Ubuntu 16.04 (this contianer) ships with make 4, but something in the +# Ubuntu 16.04 (this container) ships with make 4, but something in the # toolchains we build below chokes on that, so go back to make 3 -RUN curl https://ftp.gnu.org/gnu/make/make-3.81.tar.gz | tar xzf - && \ - cd make-3.81 && \ - ./configure --prefix=/usr && \ - make && \ - make install && \ - cd .. && \ - rm -rf make-3.81 +COPY scripts/make3.sh /scripts/ +RUN sh /scripts/make3.sh -RUN curl http://crosstool-ng.org/download/crosstool-ng/crosstool-ng-1.22.0.tar.bz2 | \ - tar xjf - && \ - cd crosstool-ng && \ - ./configure --prefix=/usr/local && \ - make -j$(nproc) && \ - make install && \ - cd .. && \ - rm -rf crosstool-ng +COPY scripts/crosstool-ng.sh /scripts/ +RUN sh /scripts/crosstool-ng.sh -RUN groupadd -r rustbuild && useradd -m -r -g rustbuild rustbuild -RUN mkdir /x-tools && chown rustbuild:rustbuild /x-tools +COPY scripts/rustbuild-setup.sh /scripts/ +RUN sh /scripts/rustbuild-setup.sh USER rustbuild WORKDIR /tmp @@ -62,9 +27,8 @@ RUN ./build-powerpc64-toolchain.sh USER root -RUN curl -o /usr/local/bin/sccache \ - https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \ - chmod +x /usr/local/bin/sccache +COPY scripts/sccache.sh /scripts/ +RUN sh /scripts/sccache.sh ENV PATH=$PATH:/x-tools/powerpc64-unknown-linux-gnu/bin diff --git a/src/ci/docker/dist-powerpc64le-linux/Dockerfile b/src/ci/docker/dist-powerpc64le-linux/Dockerfile index cbded156b4cbd..06b262c515a24 100644 --- a/src/ci/docker/dist-powerpc64le-linux/Dockerfile +++ b/src/ci/docker/dist-powerpc64le-linux/Dockerfile @@ -1,58 +1,23 @@ FROM ubuntu:16.04 -RUN apt-get update && apt-get install -y --no-install-recommends \ - automake \ - bison \ - bzip2 \ - ca-certificates \ - cmake \ - curl \ - file \ - flex \ - g++ \ - gawk \ - gdb \ - git \ - gperf \ - help2man \ - libncurses-dev \ - libtool-bin \ - make \ - patch \ - python2.7 \ - sudo \ - texinfo \ - wget \ - xz-utils \ - libssl-dev \ - pkg-config +COPY scripts/cross-apt-packages.sh /scripts/ +RUN sh /scripts/cross-apt-packages.sh + +COPY scripts/dumb-init.sh /scripts/ +RUN sh /scripts/dumb-init.sh -RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \ - dpkg -i dumb-init_*.deb && \ - rm dumb-init_*.deb ENTRYPOINT ["/usr/bin/dumb-init", "--"] -# Ubuntu 16.04 (this contianer) ships with make 4, but something in the +# Ubuntu 16.04 (this container) ships with make 4, but something in the # toolchains we build below chokes on that, so go back to make 3 -RUN curl https://ftp.gnu.org/gnu/make/make-3.81.tar.gz | tar xzf - && \ - cd make-3.81 && \ - ./configure --prefix=/usr && \ - make && \ - make install && \ - cd .. && \ - rm -rf make-3.81 +COPY scripts/make3.sh /scripts/ +RUN sh /scripts/make3.sh -RUN curl http://crosstool-ng.org/download/crosstool-ng/crosstool-ng-1.22.0.tar.bz2 | \ - tar xjf - && \ - cd crosstool-ng && \ - ./configure --prefix=/usr/local && \ - make -j$(nproc) && \ - make install && \ - cd .. && \ - rm -rf crosstool-ng +COPY scripts/crosstool-ng.sh /scripts/ +RUN sh /scripts/crosstool-ng.sh -RUN groupadd -r rustbuild && useradd -m -r -g rustbuild rustbuild -RUN mkdir /x-tools && chown rustbuild:rustbuild /x-tools +COPY scripts/rustbuild-setup.sh /scripts/ +RUN sh /scripts/rustbuild-setup.sh USER rustbuild WORKDIR /tmp @@ -62,9 +27,8 @@ RUN apt-get install -y --no-install-recommends rpm2cpio cpio COPY dist-powerpc64le-linux/shared.sh dist-powerpc64le-linux/build-powerpc64le-toolchain.sh /tmp/ RUN ./build-powerpc64le-toolchain.sh -RUN curl -o /usr/local/bin/sccache \ - https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \ - chmod +x /usr/local/bin/sccache +COPY scripts/sccache.sh /scripts/ +RUN sh /scripts/sccache.sh ENV \ AR_powerpc64le_unknown_linux_gnu=powerpc64le-linux-gnu-ar \ diff --git a/src/ci/docker/dist-s390x-linux/Dockerfile b/src/ci/docker/dist-s390x-linux/Dockerfile index 5c00287107aa3..84769af12b5a6 100644 --- a/src/ci/docker/dist-s390x-linux/Dockerfile +++ b/src/ci/docker/dist-s390x-linux/Dockerfile @@ -1,58 +1,23 @@ FROM ubuntu:16.04 -RUN apt-get update && apt-get install -y --no-install-recommends \ - automake \ - bison \ - bzip2 \ - ca-certificates \ - cmake \ - curl \ - file \ - flex \ - g++ \ - gawk \ - gdb \ - git \ - gperf \ - help2man \ - libncurses-dev \ - libtool-bin \ - make \ - patch \ - python2.7 \ - sudo \ - texinfo \ - wget \ - xz-utils \ - libssl-dev \ - pkg-config +COPY scripts/cross-apt-packages.sh /scripts/ +RUN sh /scripts/cross-apt-packages.sh + +COPY scripts/dumb-init.sh /scripts/ +RUN sh /scripts/dumb-init.sh -RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \ - dpkg -i dumb-init_*.deb && \ - rm dumb-init_*.deb ENTRYPOINT ["/usr/bin/dumb-init", "--"] -# Ubuntu 16.04 (this contianer) ships with make 4, but something in the +# Ubuntu 16.04 (this container) ships with make 4, but something in the # toolchains we build below chokes on that, so go back to make 3 -RUN curl https://ftp.gnu.org/gnu/make/make-3.81.tar.gz | tar xzf - && \ - cd make-3.81 && \ - ./configure --prefix=/usr && \ - make && \ - make install && \ - cd .. && \ - rm -rf make-3.81 +COPY scripts/make3.sh /scripts/ +RUN sh /scripts/make3.sh -RUN curl http://crosstool-ng.org/download/crosstool-ng/crosstool-ng-1.22.0.tar.bz2 | \ - tar xjf - && \ - cd crosstool-ng && \ - ./configure --prefix=/usr/local && \ - make -j$(nproc) && \ - make install && \ - cd .. && \ - rm -rf crosstool-ng +COPY scripts/crosstool-ng.sh /scripts/ +RUN sh /scripts/crosstool-ng.sh -RUN groupadd -r rustbuild && useradd -m -r -g rustbuild rustbuild -RUN mkdir /x-tools && chown rustbuild:rustbuild /x-tools +COPY scripts/rustbuild-setup.sh /scripts/ +RUN sh /scripts/rustbuild-setup.sh USER rustbuild WORKDIR /tmp @@ -62,9 +27,8 @@ RUN ./build-s390x-toolchain.sh USER root -RUN curl -o /usr/local/bin/sccache \ - https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \ - chmod +x /usr/local/bin/sccache +COPY scripts/sccache.sh /scripts/ +RUN sh /scripts/sccache.sh ENV PATH=$PATH:/x-tools/s390x-ibm-linux-gnu/bin diff --git a/src/ci/docker/dist-x86_64-freebsd/Dockerfile b/src/ci/docker/dist-x86_64-freebsd/Dockerfile index a6c4eee5e812c..b62b46701a764 100644 --- a/src/ci/docker/dist-x86_64-freebsd/Dockerfile +++ b/src/ci/docker/dist-x86_64-freebsd/Dockerfile @@ -19,14 +19,13 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ COPY dist-x86_64-freebsd/build-toolchain.sh /tmp/ RUN /tmp/build-toolchain.sh x86_64 -RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \ - dpkg -i dumb-init_*.deb && \ - rm dumb-init_*.deb +COPY scripts/dumb-init.sh /scripts/ +RUN sh /scripts/dumb-init.sh + ENTRYPOINT ["/usr/bin/dumb-init", "--"] -RUN curl -o /usr/local/bin/sccache \ - https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \ - chmod +x /usr/local/bin/sccache +COPY scripts/sccache.sh /scripts/ +RUN sh /scripts/sccache.sh ENV \ AR_x86_64_unknown_freebsd=x86_64-unknown-freebsd10-ar \ diff --git a/src/ci/docker/dist-x86_64-linux/Dockerfile b/src/ci/docker/dist-x86_64-linux/Dockerfile index 78b62839a35d5..d0ab47ad3dcd8 100644 --- a/src/ci/docker/dist-x86_64-linux/Dockerfile +++ b/src/ci/docker/dist-x86_64-linux/Dockerfile @@ -81,9 +81,8 @@ RUN curl -Lo /rustroot/dumb-init \ chmod +x /rustroot/dumb-init ENTRYPOINT ["/rustroot/dumb-init", "--"] -RUN curl -o /usr/local/bin/sccache \ - https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \ - chmod +x /usr/local/bin/sccache +COPY scripts/sccache.sh /scripts/ +RUN sh /scripts/sccache.sh ENV HOSTS=x86_64-unknown-linux-gnu diff --git a/src/ci/docker/dist-x86_64-musl/Dockerfile b/src/ci/docker/dist-x86_64-musl/Dockerfile index 2eea5ab146972..eebc283e96642 100644 --- a/src/ci/docker/dist-x86_64-musl/Dockerfile +++ b/src/ci/docker/dist-x86_64-musl/Dockerfile @@ -20,14 +20,13 @@ WORKDIR /build/ COPY dist-x86_64-musl/build-musl.sh /build/ RUN sh /build/build-musl.sh && rm -rf /build -RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \ - dpkg -i dumb-init_*.deb && \ - rm dumb-init_*.deb +COPY scripts/dumb-init.sh /scripts/ +RUN sh /scripts/dumb-init.sh + ENTRYPOINT ["/usr/bin/dumb-init", "--"] -RUN curl -o /usr/local/bin/sccache \ - https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \ - chmod +x /usr/local/bin/sccache +COPY scripts/sccache.sh /scripts/ +RUN sh /scripts/sccache.sh ENV RUST_CONFIGURE_ARGS \ --target=x86_64-unknown-linux-musl \ diff --git a/src/ci/docker/dist-x86_64-netbsd/Dockerfile b/src/ci/docker/dist-x86_64-netbsd/Dockerfile index f76e6271f4c8c..0c1405002666b 100644 --- a/src/ci/docker/dist-x86_64-netbsd/Dockerfile +++ b/src/ci/docker/dist-x86_64-netbsd/Dockerfile @@ -1,58 +1,23 @@ FROM ubuntu:16.04 -RUN apt-get update && apt-get install -y --no-install-recommends \ - automake \ - bison \ - bzip2 \ - ca-certificates \ - cmake \ - curl \ - file \ - flex \ - g++ \ - gawk \ - gdb \ - git \ - gperf \ - help2man \ - libncurses-dev \ - libtool-bin \ - make \ - patch \ - python2.7 \ - sudo \ - texinfo \ - wget \ - xz-utils \ - libssl-dev \ - pkg-config +COPY scripts/cross-apt-packages.sh /scripts/ +RUN sh /scripts/cross-apt-packages.sh + +COPY scripts/dumb-init.sh /scripts/ +RUN sh /scripts/dumb-init.sh -RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \ - dpkg -i dumb-init_*.deb && \ - rm dumb-init_*.deb ENTRYPOINT ["/usr/bin/dumb-init", "--"] -# Ubuntu 16.04 (this contianer) ships with make 4, but something in the +# Ubuntu 16.04 (this container) ships with make 4, but something in the # toolchains we build below chokes on that, so go back to make 3 -RUN curl https://ftp.gnu.org/gnu/make/make-3.81.tar.gz | tar xzf - && \ - cd make-3.81 && \ - ./configure --prefix=/usr && \ - make && \ - make install && \ - cd .. && \ - rm -rf make-3.81 +COPY scripts/make3.sh /scripts/ +RUN sh /scripts/make3.sh -RUN curl http://crosstool-ng.org/download/crosstool-ng/crosstool-ng-1.22.0.tar.bz2 | \ - tar xjf - && \ - cd crosstool-ng && \ - ./configure --prefix=/usr/local && \ - make -j$(nproc) && \ - make install && \ - cd .. && \ - rm -rf crosstool-ng +COPY scripts/crosstool-ng.sh /scripts/ +RUN sh /scripts/crosstool-ng.sh -RUN groupadd -r rustbuild && useradd -m -r -g rustbuild rustbuild -RUN mkdir /x-tools && chown rustbuild:rustbuild /x-tools +COPY scripts/rustbuild-setup.sh /scripts/ +RUN sh /scripts/rustbuild-setup.sh USER rustbuild WORKDIR /tmp @@ -61,9 +26,8 @@ RUN ./build-netbsd-toolchain.sh USER root -RUN curl -o /usr/local/bin/sccache \ - https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \ - chmod +x /usr/local/bin/sccache +COPY scripts/sccache.sh /scripts/ +RUN sh /scripts/sccache.sh ENV PATH=$PATH:/x-tools/x86_64-unknown-netbsd/bin diff --git a/src/ci/docker/i686-gnu-nopt/Dockerfile b/src/ci/docker/i686-gnu-nopt/Dockerfile index 076be8f429116..56ff9922ae347 100644 --- a/src/ci/docker/i686-gnu-nopt/Dockerfile +++ b/src/ci/docker/i686-gnu-nopt/Dockerfile @@ -13,13 +13,13 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ gdb \ xz-utils -RUN curl -o /usr/local/bin/sccache \ - https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \ - chmod +x /usr/local/bin/sccache -RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \ - dpkg -i dumb-init_*.deb && \ - rm dumb-init_*.deb +COPY scripts/dumb-init.sh /scripts/ +RUN sh /scripts/dumb-init.sh + +COPY scripts/sccache.sh /scripts/ +RUN sh /scripts/sccache.sh + ENTRYPOINT ["/usr/bin/dumb-init", "--"] ENV RUST_CONFIGURE_ARGS --build=i686-unknown-linux-gnu --disable-optimize-tests diff --git a/src/ci/docker/i686-gnu/Dockerfile b/src/ci/docker/i686-gnu/Dockerfile index 5fac057357467..1c1333cd7c84f 100644 --- a/src/ci/docker/i686-gnu/Dockerfile +++ b/src/ci/docker/i686-gnu/Dockerfile @@ -13,13 +13,13 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ gdb \ xz-utils -RUN curl -o /usr/local/bin/sccache \ - https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \ - chmod +x /usr/local/bin/sccache -RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \ - dpkg -i dumb-init_*.deb && \ - rm dumb-init_*.deb +COPY scripts/dumb-init.sh /scripts/ +RUN sh /scripts/dumb-init.sh + +COPY scripts/sccache.sh /scripts/ +RUN sh /scripts/sccache.sh + ENTRYPOINT ["/usr/bin/dumb-init", "--"] ENV RUST_CONFIGURE_ARGS --build=i686-unknown-linux-gnu diff --git a/src/ci/docker/scripts/android-base-apt-get.sh b/src/ci/docker/scripts/android-base-apt-get.sh new file mode 100644 index 0000000000000..7ae3bf39a3832 --- /dev/null +++ b/src/ci/docker/scripts/android-base-apt-get.sh @@ -0,0 +1,27 @@ +# Copyright 2017 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. + +set -ex + +apt-get update +apt-get install -y --no-install-recommends \ + ca-certificates \ + cmake \ + curl \ + file \ + g++ \ + git \ + libssl-dev \ + make \ + pkg-config \ + python2.7 \ + sudo \ + unzip \ + xz-utils diff --git a/src/ci/docker/scripts/android-ndk.sh b/src/ci/docker/scripts/android-ndk.sh index c3d83c087e52f..7fc2ebafea8c2 100644 --- a/src/ci/docker/scripts/android-ndk.sh +++ b/src/ci/docker/scripts/android-ndk.sh @@ -15,7 +15,7 @@ URL=https://dl.google.com/android/repository download_ndk() { mkdir -p /android/ndk cd /android/ndk - curl -O $URL/$1 + curl -sO $URL/$1 unzip -q $1 rm $1 mv android-ndk-* ndk diff --git a/src/ci/docker/scripts/android-sdk.sh b/src/ci/docker/scripts/android-sdk.sh index 7d8110efedec9..90257dc411ea8 100644 --- a/src/ci/docker/scripts/android-sdk.sh +++ b/src/ci/docker/scripts/android-sdk.sh @@ -15,7 +15,7 @@ URL=https://dl.google.com/android/repository download_sdk() { mkdir -p /android/sdk cd /android/sdk - curl -O $URL/$1 + curl -sO $URL/$1 unzip -q $1 rm -rf $1 } diff --git a/src/ci/docker/scripts/cross-apt-packages.sh b/src/ci/docker/scripts/cross-apt-packages.sh new file mode 100644 index 0000000000000..f6c9cc960c56d --- /dev/null +++ b/src/ci/docker/scripts/cross-apt-packages.sh @@ -0,0 +1,36 @@ +# Copyright 2017 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. + +apt-get update && apt-get install -y --no-install-recommends \ + automake \ + bison \ + bzip2 \ + ca-certificates \ + cmake \ + curl \ + file \ + flex \ + g++ \ + gawk \ + gdb \ + git \ + gperf \ + help2man \ + libncurses-dev \ + libssl-dev \ + libtool-bin \ + make \ + patch \ + pkg-config \ + python2.7 \ + sudo \ + texinfo \ + wget \ + xz-utils diff --git a/src/ci/docker/scripts/crosstool-ng.sh b/src/ci/docker/scripts/crosstool-ng.sh new file mode 100644 index 0000000000000..53ad0f8a2ebc5 --- /dev/null +++ b/src/ci/docker/scripts/crosstool-ng.sh @@ -0,0 +1,20 @@ +# Copyright 2017 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. + +set -ex + +url="http://crosstool-ng.org/download/crosstool-ng/crosstool-ng-1.22.0.tar.bz2" +curl -s $url | tar xjf - +cd crosstool-ng +./configure --prefix=/usr/local +make -j$(nproc) +make install +cd .. +rm -rf crosstool-ng diff --git a/src/ci/docker/scripts/dumb-init.sh b/src/ci/docker/scripts/dumb-init.sh index 839c390799278..616288f572b11 100644 --- a/src/ci/docker/scripts/dumb-init.sh +++ b/src/ci/docker/scripts/dumb-init.sh @@ -10,6 +10,6 @@ set -ex -curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb +curl -sOL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb dpkg -i dumb-init_*.deb rm dumb-init_*.deb diff --git a/src/ci/docker/scripts/emscripten-wasm.sh b/src/ci/docker/scripts/emscripten-wasm.sh index e693f975f69bc..18792c139ba76 100644 --- a/src/ci/docker/scripts/emscripten-wasm.sh +++ b/src/ci/docker/scripts/emscripten-wasm.sh @@ -27,38 +27,21 @@ exit 1 set -x } -# Download emsdk -cd / -curl -L https://s3.amazonaws.com/mozilla-games/emscripten/releases/emsdk-portable.tar.gz | \ - tar -xz - # Download last known good emscripten from WebAssembly waterfall -BUILD=$(curl -L https://storage.googleapis.com/wasm-llvm/builds/linux/lkgr.json | \ +BUILD=$(curl -sL https://storage.googleapis.com/wasm-llvm/builds/linux/lkgr.json | \ jq '.build | tonumber') -curl -L https://storage.googleapis.com/wasm-llvm/builds/linux/$BUILD/wasm-binaries.tbz2 | \ +curl -sL https://storage.googleapis.com/wasm-llvm/builds/linux/$BUILD/wasm-binaries.tbz2 | \ hide_output tar xvkj # node 8 is required to run wasm cd / -curl -L https://nodejs.org/dist/v8.0.0/node-v8.0.0-linux-x64.tar.xz | \ +curl -sL https://nodejs.org/dist/v8.0.0/node-v8.0.0-linux-x64.tar.xz | \ tar -xJ -cd /emsdk-portable -./emsdk update -hide_output ./emsdk install sdk-1.37.13-64bit -./emsdk activate sdk-1.37.13-64bit - # Make emscripten use wasm-ready node and LLVM tools -echo "NODE_JS='/node-v8.0.0-linux-x64/bin/node'" >> /root/.emscripten +echo "EMSCRIPTEN_ROOT = '/wasm-install/emscripten'" >> /root/.emscripten +echo "NODE_JS='/usr/local/bin/node'" >> /root/.emscripten echo "LLVM_ROOT='/wasm-install/bin'" >> /root/.emscripten - -# Make emsdk usable by any user -cp /root/.emscripten /emsdk-portable -chmod a+rxw -R /emsdk-portable - -# Compile and cache libc -source ./emsdk_env.sh -echo "main(){}" > a.c -HOME=/emsdk-portable/ emcc a.c -HOME=/emsdk-portable/ emcc -s WASM=1 a.c -rm -f a.* +echo "BINARYEN_ROOT = '/wasm-install'" >> /root/.emscripten +echo "COMPILER_ENGINE = NODE_JS" >> /root/.emscripten +echo "JS_ENGINES = [NODE_JS]" >> /root/.emscripten diff --git a/src/ci/docker/scripts/emscripten.sh b/src/ci/docker/scripts/emscripten.sh index cf5eecbdb6c8c..0a570f18bfe75 100644 --- a/src/ci/docker/scripts/emscripten.sh +++ b/src/ci/docker/scripts/emscripten.sh @@ -28,7 +28,7 @@ exit 1 } cd / -curl -L https://s3.amazonaws.com/mozilla-games/emscripten/releases/emsdk-portable.tar.gz | \ +curl -sL https://s3.amazonaws.com/mozilla-games/emscripten/releases/emsdk-portable.tar.gz | \ tar -xz cd /emsdk-portable @@ -49,5 +49,5 @@ chmod a+rxw -R /emsdk-portable # node 8 is required to run wasm cd / -curl -L https://nodejs.org/dist/v8.0.0/node-v8.0.0-linux-x64.tar.xz | \ +curl -sL https://nodejs.org/dist/v8.0.0/node-v8.0.0-linux-x64.tar.xz | \ tar -xJ diff --git a/src/ci/docker/scripts/make3.sh b/src/ci/docker/scripts/make3.sh new file mode 100644 index 0000000000000..a0b15cca1f146 --- /dev/null +++ b/src/ci/docker/scripts/make3.sh @@ -0,0 +1,19 @@ +# Copyright 2017 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. + +set -ex + +curl -s https://ftp.gnu.org/gnu/make/make-3.81.tar.gz | tar xzf - +cd make-3.81 +./configure --prefix=/usr +make +make install +cd .. +rm -rf make-3.81 diff --git a/src/ci/docker/scripts/rustbuild-setup.sh b/src/ci/docker/scripts/rustbuild-setup.sh new file mode 100644 index 0000000000000..96efccfdff386 --- /dev/null +++ b/src/ci/docker/scripts/rustbuild-setup.sh @@ -0,0 +1,14 @@ +# Copyright 2017 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. + +set -ex + +groupadd -r rustbuild && useradd -m -r -g rustbuild rustbuild +mkdir /x-tools && chown rustbuild:rustbuild /x-tools diff --git a/src/ci/docker/scripts/sccache.sh b/src/ci/docker/scripts/sccache.sh index 7a2befaf6715f..4e497a6c9ce94 100644 --- a/src/ci/docker/scripts/sccache.sh +++ b/src/ci/docker/scripts/sccache.sh @@ -10,7 +10,7 @@ set -ex -curl -o /usr/local/bin/sccache \ +curl -so /usr/local/bin/sccache \ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl chmod +x /usr/local/bin/sccache diff --git a/src/ci/docker/x86_64-gnu-aux/Dockerfile b/src/ci/docker/x86_64-gnu-aux/Dockerfile index 06c7c2824fd9d..a449526efcce2 100644 --- a/src/ci/docker/x86_64-gnu-aux/Dockerfile +++ b/src/ci/docker/x86_64-gnu-aux/Dockerfile @@ -14,13 +14,12 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ xz-utils \ pkg-config -RUN curl -o /usr/local/bin/sccache \ - https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \ - chmod +x /usr/local/bin/sccache +COPY scripts/dumb-init.sh /scripts/ +RUN sh /scripts/dumb-init.sh + +COPY scripts/sccache.sh /scripts/ +RUN sh /scripts/sccache.sh -RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \ - dpkg -i dumb-init_*.deb && \ - rm dumb-init_*.deb ENTRYPOINT ["/usr/bin/dumb-init", "--"] ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu diff --git a/src/ci/docker/x86_64-gnu-debug/Dockerfile b/src/ci/docker/x86_64-gnu-debug/Dockerfile index 6ea54ac4db3e7..8111118ad3d91 100644 --- a/src/ci/docker/x86_64-gnu-debug/Dockerfile +++ b/src/ci/docker/x86_64-gnu-debug/Dockerfile @@ -13,13 +13,12 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ gdb \ xz-utils -RUN curl -o /usr/local/bin/sccache \ - https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \ - chmod +x /usr/local/bin/sccache +COPY scripts/dumb-init.sh /scripts/ +RUN sh /scripts/dumb-init.sh + +COPY scripts/sccache.sh /scripts/ +RUN sh /scripts/sccache.sh -RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \ - dpkg -i dumb-init_*.deb && \ - rm dumb-init_*.deb ENTRYPOINT ["/usr/bin/dumb-init", "--"] ENV RUST_CONFIGURE_ARGS \ diff --git a/src/ci/docker/x86_64-gnu-distcheck/Dockerfile b/src/ci/docker/x86_64-gnu-distcheck/Dockerfile index e24c660a8c36d..c3fe8ea51cb3f 100644 --- a/src/ci/docker/x86_64-gnu-distcheck/Dockerfile +++ b/src/ci/docker/x86_64-gnu-distcheck/Dockerfile @@ -15,13 +15,12 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ libssl-dev \ pkg-config -RUN curl -o /usr/local/bin/sccache \ - https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \ - chmod +x /usr/local/bin/sccache +COPY scripts/dumb-init.sh /scripts/ +RUN sh /scripts/dumb-init.sh + +COPY scripts/sccache.sh /scripts/ +RUN sh /scripts/sccache.sh -RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \ - dpkg -i dumb-init_*.deb && \ - rm dumb-init_*.deb ENTRYPOINT ["/usr/bin/dumb-init", "--"] ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu diff --git a/src/ci/docker/x86_64-gnu-full-bootstrap/Dockerfile b/src/ci/docker/x86_64-gnu-full-bootstrap/Dockerfile index 78035c7fe3d7f..377e086955779 100644 --- a/src/ci/docker/x86_64-gnu-full-bootstrap/Dockerfile +++ b/src/ci/docker/x86_64-gnu-full-bootstrap/Dockerfile @@ -13,13 +13,12 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ gdb \ xz-utils -RUN curl -o /usr/local/bin/sccache \ - https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \ - chmod +x /usr/local/bin/sccache +COPY scripts/dumb-init.sh /scripts/ +RUN sh /scripts/dumb-init.sh + +COPY scripts/sccache.sh /scripts/ +RUN sh /scripts/sccache.sh -RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \ - dpkg -i dumb-init_*.deb && \ - rm dumb-init_*.deb ENTRYPOINT ["/usr/bin/dumb-init", "--"] ENV RUST_CONFIGURE_ARGS \ diff --git a/src/ci/docker/x86_64-gnu-incremental/Dockerfile b/src/ci/docker/x86_64-gnu-incremental/Dockerfile index 0aaed64e384ed..a21a99e965e83 100644 --- a/src/ci/docker/x86_64-gnu-incremental/Dockerfile +++ b/src/ci/docker/x86_64-gnu-incremental/Dockerfile @@ -13,13 +13,12 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ gdb \ xz-utils -RUN curl -o /usr/local/bin/sccache \ - https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \ - chmod +x /usr/local/bin/sccache +COPY scripts/dumb-init.sh /scripts/ +RUN sh /scripts/dumb-init.sh + +COPY scripts/sccache.sh /scripts/ +RUN sh /scripts/sccache.sh -RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \ - dpkg -i dumb-init_*.deb && \ - rm dumb-init_*.deb ENTRYPOINT ["/usr/bin/dumb-init", "--"] ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu diff --git a/src/ci/docker/x86_64-gnu-llvm-3.7/Dockerfile b/src/ci/docker/x86_64-gnu-llvm-3.7/Dockerfile index 7c136fa39bc8b..1a9f1d2d737b8 100644 --- a/src/ci/docker/x86_64-gnu-llvm-3.7/Dockerfile +++ b/src/ci/docker/x86_64-gnu-llvm-3.7/Dockerfile @@ -16,13 +16,12 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ zlib1g-dev \ xz-utils -RUN curl -o /usr/local/bin/sccache \ - https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \ - chmod +x /usr/local/bin/sccache +COPY scripts/dumb-init.sh /scripts/ +RUN sh /scripts/dumb-init.sh + +COPY scripts/sccache.sh /scripts/ +RUN sh /scripts/sccache.sh -RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \ - dpkg -i dumb-init_*.deb && \ - rm dumb-init_*.deb ENTRYPOINT ["/usr/bin/dumb-init", "--"] ENV RUST_CONFIGURE_ARGS \ diff --git a/src/ci/docker/x86_64-gnu-nopt/Dockerfile b/src/ci/docker/x86_64-gnu-nopt/Dockerfile index 4499736967cf4..e008b21f66fe2 100644 --- a/src/ci/docker/x86_64-gnu-nopt/Dockerfile +++ b/src/ci/docker/x86_64-gnu-nopt/Dockerfile @@ -13,13 +13,12 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ gdb \ xz-utils -RUN curl -o /usr/local/bin/sccache \ - https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \ - chmod +x /usr/local/bin/sccache +COPY scripts/dumb-init.sh /scripts/ +RUN sh /scripts/dumb-init.sh + +COPY scripts/sccache.sh /scripts/ +RUN sh /scripts/sccache.sh -RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \ - dpkg -i dumb-init_*.deb && \ - rm dumb-init_*.deb ENTRYPOINT ["/usr/bin/dumb-init", "--"] ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu --disable-optimize-tests diff --git a/src/ci/docker/x86_64-gnu/Dockerfile b/src/ci/docker/x86_64-gnu/Dockerfile index 0bbbded57f27d..3a6760b476225 100644 --- a/src/ci/docker/x86_64-gnu/Dockerfile +++ b/src/ci/docker/x86_64-gnu/Dockerfile @@ -13,13 +13,12 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ gdb \ xz-utils -RUN curl -o /usr/local/bin/sccache \ - https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \ - chmod +x /usr/local/bin/sccache +COPY scripts/dumb-init.sh /scripts/ +RUN sh /scripts/dumb-init.sh + +COPY scripts/sccache.sh /scripts/ +RUN sh /scripts/sccache.sh -RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \ - dpkg -i dumb-init_*.deb && \ - rm dumb-init_*.deb ENTRYPOINT ["/usr/bin/dumb-init", "--"] ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu --enable-sanitizers --enable-profiler diff --git a/src/doc/book b/src/doc/book index 325c3da0814f4..4ee596df22f8e 160000 --- a/src/doc/book +++ b/src/doc/book @@ -1 +1 @@ -Subproject commit 325c3da0814f44916bef00ff225f934f2d613203 +Subproject commit 4ee596df22f8ecaa9a0b2ddc0624b0104540dbf7 diff --git a/src/doc/nomicon b/src/doc/nomicon index eee5ffb127734..81134a4dff811 160000 --- a/src/doc/nomicon +++ b/src/doc/nomicon @@ -1 +1 @@ -Subproject commit eee5ffb12773469bc02895d6b5e7e663b3a572a2 +Subproject commit 81134a4dff811403b3b2f349b0c59a819f0fe0c1 diff --git a/src/doc/reference b/src/doc/reference index 876582e9d0fbd..1abfbaa70313f 160000 --- a/src/doc/reference +++ b/src/doc/reference @@ -1 +1 @@ -Subproject commit 876582e9d0fbdc9cecb03133c28db96e9ff8c844 +Subproject commit 1abfbaa70313fdf527cf799ffd9b9a096a62105c diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 76cf10f0d55ea..94f5f4042e134 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -726,14 +726,14 @@ impl Clone for Box<[T]> { } } -#[stable(feature = "rust1", since = "1.0.0")] +#[stable(feature = "box_borrow", since = "1.1.0")] impl borrow::Borrow for Box { fn borrow(&self) -> &T { &**self } } -#[stable(feature = "rust1", since = "1.0.0")] +#[stable(feature = "box_borrow", since = "1.1.0")] impl borrow::BorrowMut for Box { fn borrow_mut(&mut self) -> &mut T { &mut **self diff --git a/src/libcompiler_builtins b/src/libcompiler_builtins index e9b258bc0cde0..5e49856003f33 160000 --- a/src/libcompiler_builtins +++ b/src/libcompiler_builtins @@ -1 +1 @@ -Subproject commit e9b258bc0cde0f7ed4e36ca96a25d7575e1e58b0 +Subproject commit 5e49856003f33aa5781a0edca148be21025e18e7 diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs index 1eebf67ad04cb..35744f3f16b39 100644 --- a/src/libcore/cell.rs +++ b/src/libcore/cell.rs @@ -942,7 +942,7 @@ impl<'b, T: ?Sized> Ref<'b, T> { #[unstable(feature = "coerce_unsized", issue = "27732")] impl<'b, T: ?Sized + Unsize, U: ?Sized> CoerceUnsized> for Ref<'b, T> {} -#[stable(feature = "std_guard_impls", since = "1.20")] +#[stable(feature = "std_guard_impls", since = "1.20.0")] impl<'a, T: ?Sized + fmt::Display> fmt::Display for Ref<'a, T> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.value.fmt(f) @@ -1041,7 +1041,7 @@ impl<'b, T: ?Sized> DerefMut for RefMut<'b, T> { #[unstable(feature = "coerce_unsized", issue = "27732")] impl<'b, T: ?Sized + Unsize, U: ?Sized> CoerceUnsized> for RefMut<'b, T> {} -#[stable(feature = "std_guard_impls", since = "1.20")] +#[stable(feature = "std_guard_impls", since = "1.20.0")] impl<'a, T: ?Sized + fmt::Display> fmt::Display for RefMut<'a, T> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.value.fmt(f) diff --git a/src/libcore/char.rs b/src/libcore/char.rs index 44f5fdbf4312b..bb4cb0ac3b215 100644 --- a/src/libcore/char.rs +++ b/src/libcore/char.rs @@ -210,7 +210,7 @@ impl From for char { /// An error which can be returned when parsing a char. -#[stable(feature = "char_from_str", since = "1.19.0")] +#[stable(feature = "char_from_str", since = "1.20.0")] #[derive(Clone, Debug)] pub struct ParseCharError { kind: CharErrorKind, @@ -237,7 +237,7 @@ enum CharErrorKind { TooManyChars, } -#[stable(feature = "char_from_str", since = "1.19.0")] +#[stable(feature = "char_from_str", since = "1.20.0")] impl fmt::Display for ParseCharError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.__description().fmt(f) @@ -245,7 +245,7 @@ impl fmt::Display for ParseCharError { } -#[stable(feature = "char_from_str", since = "1.19.0")] +#[stable(feature = "char_from_str", since = "1.20.0")] impl FromStr for char { type Err = ParseCharError; diff --git a/src/libcore/default.rs b/src/libcore/default.rs index 0d7c1672fbcd2..244df1a9966d4 100644 --- a/src/libcore/default.rs +++ b/src/libcore/default.rs @@ -126,32 +126,33 @@ pub trait Default: Sized { } macro_rules! default_impl { - ($t:ty, $v:expr) => { + ($t:ty, $v:expr, $doc:expr) => { #[stable(feature = "rust1", since = "1.0.0")] impl Default for $t { #[inline] + #[doc = $doc] fn default() -> $t { $v } } } } -default_impl! { (), () } -default_impl! { bool, false } -default_impl! { char, '\x00' } +default_impl! { (), (), "Returns the default value of `()`" } +default_impl! { bool, false, "Returns the default value of `false`" } +default_impl! { char, '\x00', "Returns the default value of `\\x00`" } -default_impl! { usize, 0 } -default_impl! { u8, 0 } -default_impl! { u16, 0 } -default_impl! { u32, 0 } -default_impl! { u64, 0 } -default_impl! { u128, 0 } +default_impl! { usize, 0, "Returns the default value of `0`" } +default_impl! { u8, 0, "Returns the default value of `0`" } +default_impl! { u16, 0, "Returns the default value of `0`" } +default_impl! { u32, 0, "Returns the default value of `0`" } +default_impl! { u64, 0, "Returns the default value of `0`" } +default_impl! { u128, 0, "Returns the default value of `0`" } -default_impl! { isize, 0 } -default_impl! { i8, 0 } -default_impl! { i16, 0 } -default_impl! { i32, 0 } -default_impl! { i64, 0 } -default_impl! { i128, 0 } +default_impl! { isize, 0, "Returns the default value of `0`" } +default_impl! { i8, 0, "Returns the default value of `0`" } +default_impl! { i16, 0, "Returns the default value of `0`" } +default_impl! { i32, 0, "Returns the default value of `0`" } +default_impl! { i64, 0, "Returns the default value of `0`" } +default_impl! { i128, 0, "Returns the default value of `0`" } -default_impl! { f32, 0.0f32 } -default_impl! { f64, 0.0f64 } +default_impl! { f32, 0.0f32, "Returns the default value of `0.0`" } +default_impl! { f64, 0.0f64, "Returns the default value of `0.0`" } diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index bcc6d53c81d3b..750e86114c4bb 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -1627,13 +1627,13 @@ macro_rules! tuple { () => (); ( $($name:ident,)+ ) => ( #[stable(feature = "rust1", since = "1.0.0")] - impl<$($name:Debug),*> Debug for ($($name,)*) { + impl<$($name:Debug),*> Debug for ($($name,)*) where last_type!($($name,)+): ?Sized { #[allow(non_snake_case, unused_assignments, deprecated)] fn fmt(&self, f: &mut Formatter) -> Result { let mut builder = f.debug_tuple(""); let ($(ref $name,)*) = *self; $( - builder.field($name); + builder.field(&$name); )* builder.finish() @@ -1643,6 +1643,11 @@ macro_rules! tuple { ) } +macro_rules! last_type { + ($a:ident,) => { $a }; + ($a:ident, $($rest_a:ident,)+) => { last_type!($($rest_a,)+) }; +} + tuple! { T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, } #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libcore/hash/mod.rs b/src/libcore/hash/mod.rs index 3b304f4c479a0..2000ba9146029 100644 --- a/src/libcore/hash/mod.rs +++ b/src/libcore/hash/mod.rs @@ -559,7 +559,7 @@ mod impls { ( $($name:ident)+) => ( #[stable(feature = "rust1", since = "1.0.0")] - impl<$($name: Hash),*> Hash for ($($name,)*) { + impl<$($name: Hash),*> Hash for ($($name,)*) where last_type!($($name,)+): ?Sized { #[allow(non_snake_case)] fn hash(&self, state: &mut S) { let ($(ref $name,)*) = *self; @@ -569,6 +569,11 @@ mod impls { ); } + macro_rules! last_type { + ($a:ident,) => { $a }; + ($a:ident, $($rest_a:ident,)+) => { last_type!($($rest_a,)+) }; + } + impl_hash_tuple! {} impl_hash_tuple! { A } impl_hash_tuple! { A B } diff --git a/src/libcore/iter/mod.rs b/src/libcore/iter/mod.rs index decd718d65e15..79e6b11beaca6 100644 --- a/src/libcore/iter/mod.rs +++ b/src/libcore/iter/mod.rs @@ -359,11 +359,19 @@ impl Iterator for Rev where I: DoubleEndedIterator { #[inline] fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() } + #[inline] fn find

(&mut self, predicate: P) -> Option where P: FnMut(&Self::Item) -> bool { self.iter.rfind(predicate) } + + #[inline] + fn rposition

(&mut self, predicate: P) -> Option where + P: FnMut(Self::Item) -> bool + { + self.iter.position(predicate) + } } #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libcore/iter/traits.rs b/src/libcore/iter/traits.rs index 679cf3a9b23ee..d35aa026685dd 100644 --- a/src/libcore/iter/traits.rs +++ b/src/libcore/iter/traits.rs @@ -732,7 +732,7 @@ macro_rules! float_sum_product { )*) } -integer_sum_product! { i8 i16 i32 i64 isize u8 u16 u32 u64 usize } +integer_sum_product! { i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize } float_sum_product! { f32 f64 } /// An iterator adapter that produces output as long as the underlying diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs index 70820dce5f940..ae74016ad7449 100644 --- a/src/libcore/macros.rs +++ b/src/libcore/macros.rs @@ -462,7 +462,7 @@ macro_rules! writeln { /// /// # Panics /// -/// This will always panic. +/// This will always [panic!](macro.panic.html) /// /// # Examples /// diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index 92470299366ce..4f118f58441c4 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -160,7 +160,10 @@ unsafe fn swap_nonoverlapping_bytes(x: *mut u8, y: *mut u8, len: usize) { // #[repr(simd)], even if we don't actually use this struct directly. // // FIXME repr(simd) broken on emscripten and redox - #[cfg_attr(not(any(target_os = "emscripten", target_os = "redox")), repr(simd))] + // It's also broken on big-endian powerpc64 and s390x. #42778 + #[cfg_attr(not(any(target_os = "emscripten", target_os = "redox", + target_endian = "big")), + repr(simd))] struct Block(u64, u64, u64, u64); struct UnalignedBlock(u64, u64, u64, u64); diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index 624c3638df5cc..3862b4a2eb046 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -710,6 +710,37 @@ impl<'a> Iterator for Bytes<'a> { fn nth(&mut self, n: usize) -> Option { self.0.nth(n) } + + #[inline] + fn all(&mut self, f: F) -> bool where F: FnMut(Self::Item) -> bool { + self.0.all(f) + } + + #[inline] + fn any(&mut self, f: F) -> bool where F: FnMut(Self::Item) -> bool { + self.0.any(f) + } + + #[inline] + fn find

(&mut self, predicate: P) -> Option where + P: FnMut(&Self::Item) -> bool + { + self.0.find(predicate) + } + + #[inline] + fn position

(&mut self, predicate: P) -> Option where + P: FnMut(Self::Item) -> bool + { + self.0.position(predicate) + } + + #[inline] + fn rposition

(&mut self, predicate: P) -> Option where + P: FnMut(Self::Item) -> bool + { + self.0.rposition(predicate) + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -718,6 +749,13 @@ impl<'a> DoubleEndedIterator for Bytes<'a> { fn next_back(&mut self) -> Option { self.0.next_back() } + + #[inline] + fn rfind

(&mut self, predicate: P) -> Option where + P: FnMut(&Self::Item) -> bool + { + self.0.rfind(predicate) + } } #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libcore/tuple.rs b/src/libcore/tuple.rs index 55d55079ddc1b..47e9c7c903880 100644 --- a/src/libcore/tuple.rs +++ b/src/libcore/tuple.rs @@ -29,7 +29,7 @@ macro_rules! tuple_impls { } #[stable(feature = "rust1", since = "1.0.0")] - impl<$($T:PartialEq),+> PartialEq for ($($T,)+) { + impl<$($T:PartialEq),+> PartialEq for ($($T,)+) where last_type!($($T,)+): ?Sized { #[inline] fn eq(&self, other: &($($T,)+)) -> bool { $(self.$idx == other.$idx)&&+ @@ -41,10 +41,11 @@ macro_rules! tuple_impls { } #[stable(feature = "rust1", since = "1.0.0")] - impl<$($T:Eq),+> Eq for ($($T,)+) {} + impl<$($T:Eq),+> Eq for ($($T,)+) where last_type!($($T,)+): ?Sized {} #[stable(feature = "rust1", since = "1.0.0")] - impl<$($T:PartialOrd + PartialEq),+> PartialOrd for ($($T,)+) { + impl<$($T:PartialOrd + PartialEq),+> PartialOrd for ($($T,)+) + where last_type!($($T,)+): ?Sized { #[inline] fn partial_cmp(&self, other: &($($T,)+)) -> Option { lexical_partial_cmp!($(self.$idx, other.$idx),+) @@ -68,7 +69,7 @@ macro_rules! tuple_impls { } #[stable(feature = "rust1", since = "1.0.0")] - impl<$($T:Ord),+> Ord for ($($T,)+) { + impl<$($T:Ord),+> Ord for ($($T,)+) where last_type!($($T,)+): ?Sized { #[inline] fn cmp(&self, other: &($($T,)+)) -> Ordering { lexical_cmp!($(self.$idx, other.$idx),+) @@ -118,6 +119,11 @@ macro_rules! lexical_cmp { ($a:expr, $b:expr) => { ($a).cmp(&$b) }; } +macro_rules! last_type { + ($a:ident,) => { $a }; + ($a:ident, $($rest_a:ident,)+) => { last_type!($($rest_a,)+) }; +} + tuple_impls! { Tuple1 { (0) -> A diff --git a/src/libproc_macro/lib.rs b/src/libproc_macro/lib.rs index 06f9634d70613..3c5d6aceca919 100644 --- a/src/libproc_macro/lib.rs +++ b/src/libproc_macro/lib.rs @@ -57,6 +57,7 @@ use syntax::symbol::Symbol; use syntax::tokenstream; use syntax_pos::DUMMY_SP; use syntax_pos::SyntaxContext; +use syntax_pos::hygiene::Mark; /// The main type provided by this crate, representing an abstract stream of /// tokens. @@ -86,8 +87,16 @@ impl FromStr for TokenStream { __internal::with_sess(|(sess, mark)| { let src = src.to_string(); let name = "".to_string(); - let call_site = mark.expn_info().unwrap().call_site; - let stream = parse::parse_stream_from_source_str(name, src, sess, Some(call_site)); + let expn_info = mark.expn_info().unwrap(); + let call_site = expn_info.call_site; + // notify the expansion info that it is unhygienic + let mark = Mark::fresh(mark); + mark.set_expn_info(expn_info); + let span = syntax_pos::Span { + ctxt: SyntaxContext::empty().apply_mark(mark), + ..call_site + }; + let stream = parse::parse_stream_from_source_str(name, src, sess, Some(span)); Ok(__internal::token_stream_wrap(stream)) }) } @@ -303,7 +312,7 @@ impl Literal { Literal(token::Literal(token::Lit::Integer(Symbol::intern(&n.to_string())), None)) } - int_literals!(u8, i8, u16, i16, u32, i32, u64, i64); + int_literals!(u8, i8, u16, i16, u32, i32, u64, i64, usize, isize); fn typed_integer(n: i128, kind: &'static str) -> Literal { Literal(token::Literal(token::Lit::Integer(Symbol::intern(&n.to_string())), Some(Symbol::intern(kind)))) diff --git a/src/librustc/dep_graph/README.md b/src/librustc/dep_graph/README.md index c747c443b3a4a..c8d0362f17c8e 100644 --- a/src/librustc/dep_graph/README.md +++ b/src/librustc/dep_graph/README.md @@ -16,7 +16,7 @@ The nodes of the graph are defined by the enum `DepNode`. They represent one of three things: 1. HIR nodes (like `Hir(DefId)`) represent the HIR input itself. -2. Data nodes (like `ItemSignature(DefId)`) represent some computed +2. Data nodes (like `TypeOfItem(DefId)`) represent some computed information about a particular item. 3. Procedure nodes (like `CoherenceCheckTrait(DefId)`) represent some procedure that is executing. Usually this procedure is @@ -289,7 +289,7 @@ to see something like: Hir(foo) -> Collect(bar) Collect(bar) -> TypeckTables(bar) - + That first edge looks suspicious to you. So you set `RUST_FORBID_DEP_GRAPH_EDGE` to `Hir&foo -> Collect&bar`, re-run, and then observe the backtrace. Voila, bug fixed! diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index 92efeb7fd8629..8e2c44a427b70 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -64,7 +64,9 @@ use hir::def_id::{CrateNum, DefId}; use hir::map::DefPathHash; use ich::Fingerprint; -use ty::TyCtxt; +use ty::{TyCtxt, Instance, InstanceDef}; +use ty::fast_reject::SimplifiedType; +use ty::subst::Substs; use rustc_data_structures::stable_hasher::{StableHasher, HashStable}; use ich::StableHashingContext; use std::fmt; @@ -77,8 +79,14 @@ macro_rules! erase { ($x:tt) => ({}) } +macro_rules! anon_attr_to_bool { + (anon) => (true) +} + macro_rules! define_dep_nodes { - ($( + (<$tcx:tt> + $( + [$($anon:ident)*] $variant:ident $(( $($tuple_arg:tt),* ))* $({ $($struct_arg_name:ident : $struct_arg_ty:ty),* })* ,)* @@ -92,7 +100,7 @@ macro_rules! define_dep_nodes { impl DepKind { #[allow(unreachable_code)] #[inline] - pub fn can_reconstruct_query_key(&self) -> bool { + pub fn can_reconstruct_query_key<$tcx>(&self) -> bool { match *self { $( DepKind :: $variant => { @@ -114,6 +122,19 @@ macro_rules! define_dep_nodes { } } + #[allow(unreachable_code)] + #[inline] + pub fn is_anon<$tcx>(&self) -> bool { + match *self { + $( + DepKind :: $variant => { + $(return anon_attr_to_bool!($anon);)* + false + } + )* + } + } + #[allow(unreachable_code)] #[inline] pub fn has_params(&self) -> bool { @@ -139,7 +160,7 @@ macro_rules! define_dep_nodes { } } - pub enum DepConstructor { + pub enum DepConstructor<$tcx> { $( $variant $(( $($tuple_arg),* ))* $({ $($struct_arg_name : $struct_arg_ty),* })* @@ -155,7 +176,12 @@ macro_rules! define_dep_nodes { impl DepNode { #[allow(unreachable_code, non_snake_case)] - pub fn new(tcx: TyCtxt, dep: DepConstructor) -> DepNode { + pub fn new<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, + dep: DepConstructor<'gcx>) + -> DepNode + where 'gcx: 'a + 'tcx, + 'tcx: 'a + { match dep { $( DepConstructor :: $variant $(( $($tuple_arg),* ))* @@ -336,7 +362,7 @@ impl DefId { } } -define_dep_nodes!( +define_dep_nodes!( <'tcx> // Represents the `Krate` as a whole (the `hir::Krate` value) (as // distinct from the krate module). This is basically a hash of // the entire krate, so if you read from `Krate` (e.g., by calling @@ -348,90 +374,101 @@ define_dep_nodes!( // suitable wrapper, you can use `tcx.dep_graph.ignore()` to gain // access to the krate, but you must remember to add suitable // edges yourself for the individual items that you read. - Krate, + [] Krate, // Represents the HIR node with the given node-id - Hir(DefId), + [] Hir(DefId), // Represents the body of a function or method. The def-id is that of the // function/method. - HirBody(DefId), + [] HirBody(DefId), // Represents the metadata for a given HIR node, typically found // in an extern crate. - MetaData(DefId), + [] MetaData(DefId), // Represents some artifact that we save to disk. Note that these // do not have a def-id as part of their identifier. - WorkProduct(WorkProductId), + [] WorkProduct(WorkProductId), // Represents different phases in the compiler. - RegionMaps(DefId), - Coherence, - Resolve, - CoherenceCheckTrait(DefId), - PrivacyAccessLevels(CrateNum), + [] RegionMaps(DefId), + [] Coherence, + [] Resolve, + [] CoherenceCheckTrait(DefId), + [] PrivacyAccessLevels(CrateNum), // Represents the MIR for a fn; also used as the task node for // things read/modify that MIR. - Mir(DefId), - MirShim(DefIdList), - - BorrowCheckKrate, - BorrowCheck(DefId), - RvalueCheck(DefId), - Reachability, - MirKeys, - TransWriteMetadata, - CrateVariances, + [] MirConstQualif(DefId), + [] MirConst(DefId), + [] MirValidated(DefId), + [] MirOptimized(DefId), + [] MirShim { instance_def: InstanceDef<'tcx> }, + + [] BorrowCheckKrate, + [] BorrowCheck(DefId), + [] RvalueCheck(DefId), + [] Reachability, + [] MirKeys, + [] TransWriteMetadata, + [] CrateVariances, // Nodes representing bits of computed IR in the tcx. Each shared // table in the tcx (or elsewhere) maps to one of these - // nodes. Often we map multiple tables to the same node if there - // is no point in distinguishing them (e.g., both the type and - // predicates for an item wind up in `ItemSignature`). - AssociatedItems(DefId), - ItemSignature(DefId), - ItemVarianceConstraints(DefId), - ItemVariances(DefId), - IsConstFn(DefId), - IsForeignItem(DefId), - TypeParamPredicates { item_id: DefId, param_id: DefId }, - SizedConstraint(DefId), - DtorckConstraint(DefId), - AdtDestructor(DefId), - AssociatedItemDefIds(DefId), - InherentImpls(DefId), - TypeckBodiesKrate, - TypeckTables(DefId), - ConstEval(DefId), - SymbolName(DefId), - SpecializationGraph(DefId), - ObjectSafety(DefId), - IsCopy(DefId), - IsSized(DefId), - IsFreeze(DefId), - NeedsDrop(DefId), - Layout(DefId), - - // The set of impls for a given trait. Ultimately, it would be - // nice to get more fine-grained here (e.g., to include a - // simplified type), but we can't do that until we restructure the - // HIR to distinguish the *header* of an impl from its body. This - // is because changes to the header may change the self-type of - // the impl and hence would require us to be more conservative - // than changes in the impl body. - TraitImpls(DefId), - - AllLocalTraitImpls, + // nodes. + [] AssociatedItems(DefId), + [] TypeOfItem(DefId), + [] GenericsOfItem(DefId), + [] PredicatesOfItem(DefId), + [] SuperPredicatesOfItem(DefId), + [] TraitDefOfItem(DefId), + [] AdtDefOfItem(DefId), + [] IsDefaultImpl(DefId), + [] ImplTraitRef(DefId), + [] ImplPolarity(DefId), + [] ClosureKind(DefId), + [] FnSignature(DefId), + [] CoerceUnsizedInfo(DefId), + + [] ItemVarianceConstraints(DefId), + [] ItemVariances(DefId), + [] IsConstFn(DefId), + [] IsForeignItem(DefId), + [] TypeParamPredicates { item_id: DefId, param_id: DefId }, + [] SizedConstraint(DefId), + [] DtorckConstraint(DefId), + [] AdtDestructor(DefId), + [] AssociatedItemDefIds(DefId), + [] InherentImpls(DefId), + [] TypeckBodiesKrate, + [] TypeckTables(DefId), + [] HasTypeckTables(DefId), + [] ConstEval { def_id: DefId, substs: &'tcx Substs<'tcx> }, + [] SymbolName(DefId), + [] InstanceSymbolName { instance: Instance<'tcx> }, + [] SpecializationGraph(DefId), + [] ObjectSafety(DefId), + + [anon] IsCopy(DefId), + [anon] IsSized(DefId), + [anon] IsFreeze(DefId), + [anon] NeedsDrop(DefId), + [anon] Layout(DefId), + + // The set of impls for a given trait. + [] TraitImpls(DefId), + [] RelevantTraitImpls(DefId, SimplifiedType), + + [] AllLocalTraitImpls, // Nodes representing caches. To properly handle a true cache, we // don't use a DepTrackingMap, but rather we push a task node. // Otherwise the write into the map would be incorrectly // attributed to the first task that happened to fill the cache, // which would yield an overly conservative dep-graph. - TraitItems(DefId), - ReprHints(DefId), + [] TraitItems(DefId), + [] ReprHints(DefId), // Trait selection cache is a little funny. Given a trait // reference like `Foo: SomeTrait`, there could be @@ -458,35 +495,45 @@ define_dep_nodes!( // imprecision in our dep-graph tracking. The important thing is // that for any given trait-ref, we always map to the **same** // trait-select node. - TraitSelect { trait_def_id: DefId, input_def_id: DefId }, + [anon] TraitSelect, // For proj. cache, we just keep a list of all def-ids, since it is // not a hotspot. - ProjectionCache { def_ids: DefIdList }, - - ParamEnv(DefId), - DescribeDef(DefId), - DefSpan(DefId), - Stability(DefId), - Deprecation(DefId), - ItemBodyNestedBodies(DefId), - ConstIsRvaluePromotableToStatic(DefId), - ImplParent(DefId), - TraitOfItem(DefId), - IsExportedSymbol(DefId), - IsMirAvailable(DefId), - ItemAttrs(DefId), - FnArgNames(DefId), - DylibDepFormats(DefId), - IsAllocator(DefId), - IsPanicRuntime(DefId), - ExternCrate(DefId), + [] ProjectionCache { def_ids: DefIdList }, + + [] ParamEnv(DefId), + [] DescribeDef(DefId), + [] DefSpan(DefId), + [] Stability(DefId), + [] Deprecation(DefId), + [] ItemBodyNestedBodies(DefId), + [] ConstIsRvaluePromotableToStatic(DefId), + [] ImplParent(DefId), + [] TraitOfItem(DefId), + [] IsExportedSymbol(DefId), + [] IsMirAvailable(DefId), + [] ItemAttrs(DefId), + [] FnArgNames(DefId), + [] DylibDepFormats(DefId), + [] IsAllocator(DefId), + [] IsPanicRuntime(DefId), + [] ExternCrate(DefId), ); -trait DepNodeParams<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> { +trait DepNodeParams<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> : fmt::Debug { const CAN_RECONSTRUCT_QUERY_KEY: bool; - fn to_fingerprint(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Fingerprint; - fn to_debug_str(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> String; + + /// This method turns the parameters of a DepNodeConstructor into an opaque + /// Fingerprint to be used in DepNode. + /// Not all DepNodeParams support being turned into a Fingerprint (they + /// don't need to if the corresponding DepNode is anonymous). + fn to_fingerprint(&self, _: TyCtxt<'a, 'gcx, 'tcx>) -> Fingerprint { + panic!("Not implemented. Accidentally called on anonymous node?") + } + + fn to_debug_str(&self, _: TyCtxt<'a, 'gcx, 'tcx>) -> String { + format!("{:?}", self) + } } impl<'a, 'gcx: 'tcx + 'a, 'tcx: 'a, T> DepNodeParams<'a, 'gcx, 'tcx> for T diff --git a/src/librustc/dep_graph/dep_tracking_map.rs b/src/librustc/dep_graph/dep_tracking_map.rs index ca53fd7a43311..2d19b34c5040e 100644 --- a/src/librustc/dep_graph/dep_tracking_map.rs +++ b/src/librustc/dep_graph/dep_tracking_map.rs @@ -12,10 +12,9 @@ use rustc_data_structures::fx::FxHashMap; use std::cell::RefCell; use std::hash::Hash; use std::marker::PhantomData; -use ty::TyCtxt; use util::common::MemoizationMap; -use super::{DepNode, DepGraph}; +use super::{DepKind, DepNodeIndex, DepGraph}; /// A DepTrackingMap offers a subset of the `Map` API and ensures that /// we make calls to `read` and `write` as appropriate. We key the @@ -23,13 +22,13 @@ use super::{DepNode, DepGraph}; pub struct DepTrackingMap { phantom: PhantomData, graph: DepGraph, - map: FxHashMap, + map: FxHashMap, } pub trait DepTrackingMapConfig { type Key: Eq + Hash + Clone; type Value: Clone; - fn to_dep_node(tcx: TyCtxt, key: &Self::Key) -> DepNode; + fn to_dep_kind() -> DepKind; } impl DepTrackingMap { @@ -40,27 +39,6 @@ impl DepTrackingMap { map: FxHashMap(), } } - - /// Registers a (synthetic) read from the key `k`. Usually this - /// is invoked automatically by `get`. - fn read(&self, tcx: TyCtxt, k: &M::Key) { - let dep_node = M::to_dep_node(tcx, k); - self.graph.read(dep_node); - } - - pub fn get(&self, tcx: TyCtxt, k: &M::Key) -> Option<&M::Value> { - self.read(tcx, k); - self.map.get(k) - } - - pub fn contains_key(&self, tcx: TyCtxt, k: &M::Key) -> bool { - self.read(tcx, k); - self.map.contains_key(k) - } - - pub fn keys(&self) -> Vec { - self.map.keys().cloned().collect() - } } impl MemoizationMap for RefCell> { @@ -98,22 +76,22 @@ impl MemoizationMap for RefCell> { /// The key is the line marked `(*)`: the closure implicitly /// accesses the body of the item `item`, so we register a read /// from `Hir(item_def_id)`. - fn memoize(&self, tcx: TyCtxt, key: M::Key, op: OP) -> M::Value + fn memoize(&self, key: M::Key, op: OP) -> M::Value where OP: FnOnce() -> M::Value { let graph; { let this = self.borrow(); - if let Some(result) = this.map.get(&key) { - this.read(tcx, &key); + if let Some(&(ref result, dep_node)) = this.map.get(&key) { + this.graph.read_index(dep_node); return result.clone(); } graph = this.graph.clone(); } - let _task = graph.in_task(M::to_dep_node(tcx, &key)); - let result = op(); - self.borrow_mut().map.insert(key, result.clone()); + let (result, dep_node) = graph.with_anon_task(M::to_dep_kind(), op); + self.borrow_mut().map.insert(key, (result.clone(), dep_node)); + graph.read_index(dep_node); result } } diff --git a/src/librustc/dep_graph/edges.rs b/src/librustc/dep_graph/edges.rs index a323e44d0d427..277b69262c92d 100644 --- a/src/librustc/dep_graph/edges.rs +++ b/src/librustc/dep_graph/edges.rs @@ -8,25 +8,35 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use ich::Fingerprint; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; -use super::{DepGraphQuery, DepNode}; +use rustc_data_structures::stable_hasher::StableHasher; +use std::env; +use std::hash::Hash; +use std::mem; +use super::{DepGraphQuery, DepKind, DepNode}; +use super::debug::EdgeFilter; pub struct DepGraphEdges { nodes: Vec, - indices: FxHashMap, - edges: FxHashSet<(IdIndex, IdIndex)>, - open_nodes: Vec, + indices: FxHashMap, + edges: FxHashSet<(DepNodeIndex, DepNodeIndex)>, + task_stack: Vec, + forbidden_edge: Option, } #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] -struct IdIndex { +pub struct DepNodeIndex { index: u32 } -impl IdIndex { - fn new(v: usize) -> IdIndex { +impl DepNodeIndex { + + pub const INVALID: DepNodeIndex = DepNodeIndex { index: ::std::u32::MAX }; + + fn new(v: usize) -> DepNodeIndex { assert!((v & 0xFFFF_FFFF) == v); - IdIndex { index: v as u32 } + DepNodeIndex { index: v as u32 } } fn index(self) -> usize { @@ -35,67 +45,136 @@ impl IdIndex { } #[derive(Clone, Debug, PartialEq)] -enum OpenNode { - Node(IdIndex), +enum OpenTask { + Regular { + node: DepNode, + reads: Vec, + read_set: FxHashSet, + }, + Anon { + reads: Vec, + read_set: FxHashSet, + }, Ignore, } impl DepGraphEdges { pub fn new() -> DepGraphEdges { + let forbidden_edge = if cfg!(debug_assertions) { + match env::var("RUST_FORBID_DEP_GRAPH_EDGE") { + Ok(s) => { + match EdgeFilter::new(&s) { + Ok(f) => Some(f), + Err(err) => bug!("RUST_FORBID_DEP_GRAPH_EDGE invalid: {}", err), + } + } + Err(_) => None, + } + } else { + None + }; + DepGraphEdges { nodes: vec![], indices: FxHashMap(), edges: FxHashSet(), - open_nodes: Vec::new() + task_stack: Vec::new(), + forbidden_edge, } } - fn id(&self, index: IdIndex) -> DepNode { - self.nodes[index.index()].clone() - } - - /// Creates a node for `id` in the graph. - fn make_node(&mut self, id: DepNode) -> IdIndex { - if let Some(&i) = self.indices.get(&id) { - return i; - } - - let index = IdIndex::new(self.nodes.len()); - self.nodes.push(id.clone()); - self.indices.insert(id, index); - index - } - - /// Top of the stack of open nodes. - fn current_node(&self) -> Option { - self.open_nodes.last().cloned() + fn id(&self, index: DepNodeIndex) -> DepNode { + self.nodes[index.index()] } pub fn push_ignore(&mut self) { - self.open_nodes.push(OpenNode::Ignore); + self.task_stack.push(OpenTask::Ignore); } pub fn pop_ignore(&mut self) { - let popped_node = self.open_nodes.pop().unwrap(); - assert_eq!(popped_node, OpenNode::Ignore); + let popped_node = self.task_stack.pop().unwrap(); + debug_assert_eq!(popped_node, OpenTask::Ignore); } pub fn push_task(&mut self, key: DepNode) { - let top_node = self.current_node(); + self.task_stack.push(OpenTask::Regular { + node: key, + reads: Vec::new(), + read_set: FxHashSet(), + }); + } - let new_node = self.make_node(key); - self.open_nodes.push(OpenNode::Node(new_node)); + pub fn pop_task(&mut self, key: DepNode) -> DepNodeIndex { + let popped_node = self.task_stack.pop().unwrap(); - // if we are in the midst of doing task T, then this new task - // N is a subtask of T, so add an edge N -> T. - if let Some(top_node) = top_node { - self.add_edge_from_open_node(top_node, |t| (new_node, t)); + if let OpenTask::Regular { + node, + read_set: _, + reads + } = popped_node { + debug_assert_eq!(node, key); + + let target_id = self.get_or_create_node(node); + + for read in reads.into_iter() { + let source_id = self.get_or_create_node(read); + self.edges.insert((source_id, target_id)); + } + + target_id + } else { + bug!("pop_task() - Expected regular task to be popped") } } - pub fn pop_task(&mut self, key: DepNode) { - let popped_node = self.open_nodes.pop().unwrap(); - assert_eq!(OpenNode::Node(self.indices[&key]), popped_node); + pub fn push_anon_task(&mut self) { + self.task_stack.push(OpenTask::Anon { + reads: Vec::new(), + read_set: FxHashSet(), + }); + } + + pub fn pop_anon_task(&mut self, kind: DepKind) -> DepNodeIndex { + let popped_node = self.task_stack.pop().unwrap(); + + if let OpenTask::Anon { + read_set: _, + reads + } = popped_node { + let mut fingerprint = Fingerprint::zero(); + let mut hasher = StableHasher::new(); + + for read in reads.iter() { + mem::discriminant(&read.kind).hash(&mut hasher); + + // Fingerprint::combine() is faster than sending Fingerprint + // through the StableHasher (at least as long as StableHasher + // is so slow). + fingerprint = fingerprint.combine(read.hash); + } + + fingerprint = fingerprint.combine(hasher.finish()); + + let target_dep_node = DepNode { + kind, + hash: fingerprint, + }; + + if let Some(&index) = self.indices.get(&target_dep_node) { + return index; + } + + let target_id = self.get_or_create_node(target_dep_node); + + for read in reads.into_iter() { + let source_id = self.get_or_create_node(read); + self.edges.insert((source_id, target_id)); + } + + target_id + } else { + bug!("pop_anon_task() - Expected anonymous task to be popped") + } } /// Indicates that the current task `C` reads `v` by adding an @@ -103,58 +182,42 @@ impl DepGraphEdges { /// effect. Note that *reading* from tracked state is harmless if /// you are not in a task; what is bad is *writing* to tracked /// state (and leaking data that you read into a tracked task). - pub fn read(&mut self, v: DepNode) { - if self.current_node().is_some() { - let source = self.make_node(v); - self.add_edge_from_current_node(|current| (source, current)) - } - } - - /// Indicates that the current task `C` writes `v` by adding an - /// edge from `C` to `v`. If there is no current task, panics. If - /// you want to suppress this edge, use `ignore`. - pub fn write(&mut self, v: DepNode) { - let target = self.make_node(v); - self.add_edge_from_current_node(|current| (current, target)) - } - - /// Invoke `add_edge_from_open_node` with the top of the stack, or - /// panic if stack is empty. - fn add_edge_from_current_node(&mut self, - op: OP) - where OP: FnOnce(IdIndex) -> (IdIndex, IdIndex) - { - match self.current_node() { - Some(open_node) => self.add_edge_from_open_node(open_node, op), - None => bug!("no current node, cannot add edge into dependency graph") + pub fn read(&mut self, source: DepNode) { + match self.task_stack.last_mut() { + Some(&mut OpenTask::Regular { + node: target, + ref mut reads, + ref mut read_set, + }) => { + if read_set.insert(source) { + reads.push(source); + + if cfg!(debug_assertions) { + if let Some(ref forbidden_edge) = self.forbidden_edge { + if forbidden_edge.test(&source, &target) { + bug!("forbidden edge {:?} -> {:?} created", source, target) + } + } + } + } + } + Some(&mut OpenTask::Anon { + ref mut reads, + ref mut read_set, + }) => { + if read_set.insert(source) { + reads.push(source); + } + } + Some(&mut OpenTask::Ignore) | None => { + // ignore + } } } - /// Adds an edge to or from the `open_node`, assuming `open_node` - /// is not `Ignore`. The direction of the edge is determined by - /// the closure `op` --- we pass as argument the open node `n`, - /// and the closure returns a (source, target) tuple, which should - /// include `n` in one spot or another. - fn add_edge_from_open_node(&mut self, - open_node: OpenNode, - op: OP) - where OP: FnOnce(IdIndex) -> (IdIndex, IdIndex) - { - let (source, target) = match open_node { - OpenNode::Node(n) => op(n), - OpenNode::Ignore => { return; } - }; - - // ignore trivial self edges, which are not very interesting - if source == target { - return; - } - - if self.edges.insert((source, target)) { - debug!("adding edge from {:?} to {:?}", - self.id(source), - self.id(target)); - } + pub fn read_index(&mut self, source: DepNodeIndex) { + let dep_node = self.nodes[source.index()]; + self.read(dep_node); } pub fn query(&self) -> DepGraphQuery { @@ -163,4 +226,30 @@ impl DepGraphEdges { .collect(); DepGraphQuery::new(&self.nodes, &edges) } + + #[inline] + pub fn add_edge(&mut self, source: DepNode, target: DepNode) { + let source = self.get_or_create_node(source); + let target = self.get_or_create_node(target); + self.edges.insert((source, target)); + } + + pub fn add_node(&mut self, node: DepNode) { + self.get_or_create_node(node); + } + + #[inline] + fn get_or_create_node(&mut self, dep_node: DepNode) -> DepNodeIndex { + let DepGraphEdges { + ref mut indices, + ref mut nodes, + .. + } = *self; + + *indices.entry(dep_node).or_insert_with(|| { + let next_id = nodes.len(); + nodes.push(dep_node); + DepNodeIndex::new(next_id) + }) + } } diff --git a/src/librustc/dep_graph/graph.rs b/src/librustc/dep_graph/graph.rs index e48e61d803510..4ca59132e0ad9 100644 --- a/src/librustc/dep_graph/graph.rs +++ b/src/librustc/dep_graph/graph.rs @@ -13,21 +13,20 @@ use session::config::OutputType; use std::cell::{Ref, RefCell}; use std::rc::Rc; -use super::dep_node::{DepNode, WorkProductId}; +use super::dep_node::{DepNode, DepKind, WorkProductId}; use super::query::DepGraphQuery; use super::raii; use super::safe::DepGraphSafe; -use super::thread::{DepGraphThreadData, DepMessage}; +use super::edges::{DepGraphEdges, DepNodeIndex}; #[derive(Clone)] pub struct DepGraph { - data: Rc + data: Option> } struct DepGraphData { - /// We send messages to the thread to let it build up the dep-graph - /// from the current run. - thread: DepGraphThreadData, + /// The actual graph data. + edges: RefCell, /// When we load, there may be `.o` files, cached mir, or other such /// things available to us. If we find that they are not dirty, we @@ -44,31 +43,35 @@ struct DepGraphData { impl DepGraph { pub fn new(enabled: bool) -> DepGraph { DepGraph { - data: Rc::new(DepGraphData { - thread: DepGraphThreadData::new(enabled), - previous_work_products: RefCell::new(FxHashMap()), - work_products: RefCell::new(FxHashMap()), - dep_node_debug: RefCell::new(FxHashMap()), - }) + data: if enabled { + Some(Rc::new(DepGraphData { + previous_work_products: RefCell::new(FxHashMap()), + work_products: RefCell::new(FxHashMap()), + edges: RefCell::new(DepGraphEdges::new()), + dep_node_debug: RefCell::new(FxHashMap()), + })) + } else { + None + } } } /// True if we are actually building the full dep-graph. #[inline] pub fn is_fully_enabled(&self) -> bool { - self.data.thread.is_fully_enabled() + self.data.is_some() } pub fn query(&self) -> DepGraphQuery { - self.data.thread.query() + self.data.as_ref().unwrap().edges.borrow().query() } pub fn in_ignore<'graph>(&'graph self) -> Option> { - raii::IgnoreTask::new(&self.data.thread) + self.data.as_ref().map(|data| raii::IgnoreTask::new(&data.edges)) } pub fn in_task<'graph>(&'graph self, key: DepNode) -> Option> { - raii::DepTask::new(&self.data.thread, key) + self.data.as_ref().map(|data| raii::DepTask::new(&data.edges, key)) } pub fn with_ignore(&self, op: OP) -> R @@ -105,26 +108,75 @@ impl DepGraph { /// `arg` parameter. /// /// [README]: README.md - pub fn with_task(&self, key: DepNode, cx: C, arg: A, task: fn(C, A) -> R) -> R - where C: DepGraphSafe, A: DepGraphSafe + pub fn with_task(&self, + key: DepNode, + cx: C, + arg: A, + task: fn(C, A) -> R) + -> (R, DepNodeIndex) + where C: DepGraphSafe { - let _task = self.in_task(key); - task(cx, arg) + if let Some(ref data) = self.data { + data.edges.borrow_mut().push_task(key); + let result = task(cx, arg); + let dep_node_index = data.edges.borrow_mut().pop_task(key); + (result, dep_node_index) + } else { + (task(cx, arg), DepNodeIndex::INVALID) + } } + /// Execute something within an "anonymous" task, that is, a task the + /// DepNode of which is determined by the list of inputs it read from. + pub fn with_anon_task(&self, dep_kind: DepKind, op: OP) -> (R, DepNodeIndex) + where OP: FnOnce() -> R + { + if let Some(ref data) = self.data { + data.edges.borrow_mut().push_anon_task(); + let result = op(); + let dep_node = data.edges.borrow_mut().pop_anon_task(dep_kind); + (result, dep_node) + } else { + (op(), DepNodeIndex::INVALID) + } + } + + #[inline] pub fn read(&self, v: DepNode) { - if self.data.thread.is_enqueue_enabled() { - self.data.thread.enqueue(DepMessage::Read(v)); + if let Some(ref data) = self.data { + data.edges.borrow_mut().read(v); + } + } + + #[inline] + pub fn read_index(&self, v: DepNodeIndex) { + if let Some(ref data) = self.data { + data.edges.borrow_mut().read_index(v); } } + /// Only to be used during graph loading + #[inline] + pub fn add_edge_directly(&self, source: DepNode, target: DepNode) { + self.data.as_ref().unwrap().edges.borrow_mut().add_edge(source, target); + } + + /// Only to be used during graph loading + pub fn add_node_directly(&self, node: DepNode) { + self.data.as_ref().unwrap().edges.borrow_mut().add_node(node); + } + /// Indicates that a previous work product exists for `v`. This is /// invoked during initial start-up based on what nodes are clean /// (and what files exist in the incr. directory). pub fn insert_previous_work_product(&self, v: &WorkProductId, data: WorkProduct) { debug!("insert_previous_work_product({:?}, {:?})", v, data); - self.data.previous_work_products.borrow_mut() - .insert(v.clone(), data); + self.data + .as_ref() + .unwrap() + .previous_work_products + .borrow_mut() + .insert(v.clone(), data); } /// Indicates that we created the given work-product in this run @@ -132,44 +184,50 @@ impl DepGraph { /// run. pub fn insert_work_product(&self, v: &WorkProductId, data: WorkProduct) { debug!("insert_work_product({:?}, {:?})", v, data); - self.data.work_products.borrow_mut() - .insert(v.clone(), data); + self.data + .as_ref() + .unwrap() + .work_products + .borrow_mut() + .insert(v.clone(), data); } /// Check whether a previous work product exists for `v` and, if /// so, return the path that leads to it. Used to skip doing work. pub fn previous_work_product(&self, v: &WorkProductId) -> Option { - self.data.previous_work_products.borrow() - .get(v) - .cloned() + self.data + .as_ref() + .and_then(|data| { + data.previous_work_products.borrow().get(v).cloned() + }) } /// Access the map of work-products created during this run. Only /// used during saving of the dep-graph. pub fn work_products(&self) -> Ref> { - self.data.work_products.borrow() + self.data.as_ref().unwrap().work_products.borrow() } /// Access the map of work-products created during the cached run. Only /// used during saving of the dep-graph. pub fn previous_work_products(&self) -> Ref> { - self.data.previous_work_products.borrow() + self.data.as_ref().unwrap().previous_work_products.borrow() } #[inline(always)] - pub(super) fn register_dep_node_debug_str(&self, - dep_node: DepNode, - debug_str_gen: F) + pub fn register_dep_node_debug_str(&self, + dep_node: DepNode, + debug_str_gen: F) where F: FnOnce() -> String { - let mut dep_node_debug = self.data.dep_node_debug.borrow_mut(); + let mut dep_node_debug = self.data.as_ref().unwrap().dep_node_debug.borrow_mut(); dep_node_debug.entry(dep_node) .or_insert_with(debug_str_gen); } pub(super) fn dep_node_debug_str(&self, dep_node: DepNode) -> Option { - self.data.dep_node_debug.borrow().get(&dep_node).cloned() + self.data.as_ref().and_then(|t| t.dep_node_debug.borrow().get(&dep_node).cloned()) } } @@ -206,6 +264,7 @@ impl DepGraph { /// previous hash. If it matches up, we can reuse the object file. #[derive(Clone, Debug, RustcEncodable, RustcDecodable)] pub struct WorkProduct { + pub cgu_name: String, /// Extra hash used to decide if work-product is still suitable; /// note that this is *not* a hash of the work-product itself. /// See documentation on `WorkProduct` type for an example. diff --git a/src/librustc/dep_graph/mod.rs b/src/librustc/dep_graph/mod.rs index 92b05f6a6558e..ac0c88ced93c8 100644 --- a/src/librustc/dep_graph/mod.rs +++ b/src/librustc/dep_graph/mod.rs @@ -16,14 +16,13 @@ mod graph; mod query; mod raii; mod safe; -mod shadow; -mod thread; pub use self::dep_tracking_map::{DepTrackingMap, DepTrackingMapConfig}; pub use self::dep_node::DepNode; pub use self::dep_node::WorkProductId; pub use self::graph::DepGraph; pub use self::graph::WorkProduct; +pub use self::edges::DepNodeIndex; pub use self::query::DepGraphQuery; pub use self::safe::AssertDepGraphSafe; pub use self::safe::DepGraphSafe; diff --git a/src/librustc/dep_graph/raii.rs b/src/librustc/dep_graph/raii.rs index b45f5de802714..ce261ca68e8a3 100644 --- a/src/librustc/dep_graph/raii.rs +++ b/src/librustc/dep_graph/raii.rs @@ -9,53 +9,49 @@ // except according to those terms. use super::DepNode; -use super::thread::{DepGraphThreadData, DepMessage}; +use super::edges::DepGraphEdges; + +use std::cell::RefCell; pub struct DepTask<'graph> { - data: &'graph DepGraphThreadData, - key: Option, + graph: &'graph RefCell, + key: DepNode, } impl<'graph> DepTask<'graph> { - pub fn new(data: &'graph DepGraphThreadData, key: DepNode) - -> Option> { - if data.is_enqueue_enabled() { - data.enqueue(DepMessage::PushTask(key.clone())); - Some(DepTask { data: data, key: Some(key) }) - } else { - None + pub fn new(graph: &'graph RefCell, + key: DepNode) + -> DepTask<'graph> { + graph.borrow_mut().push_task(key); + DepTask { + graph, + key, } } } impl<'graph> Drop for DepTask<'graph> { fn drop(&mut self) { - if self.data.is_enqueue_enabled() { - self.data.enqueue(DepMessage::PopTask(self.key.take().unwrap())); - } + self.graph.borrow_mut().pop_task(self.key); } } pub struct IgnoreTask<'graph> { - data: &'graph DepGraphThreadData + graph: &'graph RefCell, } impl<'graph> IgnoreTask<'graph> { - pub fn new(data: &'graph DepGraphThreadData) -> Option> { - if data.is_enqueue_enabled() { - data.enqueue(DepMessage::PushIgnore); - Some(IgnoreTask { data: data }) - } else { - None + pub fn new(graph: &'graph RefCell) -> IgnoreTask<'graph> { + graph.borrow_mut().push_ignore(); + IgnoreTask { + graph } } } impl<'graph> Drop for IgnoreTask<'graph> { fn drop(&mut self) { - if self.data.is_enqueue_enabled() { - self.data.enqueue(DepMessage::PopIgnore); - } + self.graph.borrow_mut().pop_ignore(); } } diff --git a/src/librustc/dep_graph/shadow.rs b/src/librustc/dep_graph/shadow.rs deleted file mode 100644 index e32acbf4756ca..0000000000000 --- a/src/librustc/dep_graph/shadow.rs +++ /dev/null @@ -1,151 +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. - -//! The "Shadow Graph" is maintained on the main thread and which -//! tracks each message relating to the dep-graph and applies some -//! sanity checks as they go by. If an error results, it means you get -//! a nice stack-trace telling you precisely what caused the error. -//! -//! NOTE: This is a debugging facility which can potentially have non-trivial -//! runtime impact. Therefore, it is largely compiled out if -//! debug-assertions are not enabled. -//! -//! The basic sanity check, enabled if you have debug assertions -//! enabled, is that there is always a task (or ignore) on the stack -//! when you do read/write, and that the tasks are pushed/popped -//! according to a proper stack discipline. -//! -//! Optionally, if you specify RUST_FORBID_DEP_GRAPH_EDGE, you can -//! specify an edge filter to be applied to each edge as it is -//! created. See `./README.md` for details. - -use std::cell::RefCell; -use std::env; - -use super::DepNode; -use super::thread::DepMessage; -use super::debug::EdgeFilter; - -pub struct ShadowGraph { - // if you push None onto the stack, that corresponds to an Ignore - stack: RefCell>>, - forbidden_edge: Option, -} - -const ENABLED: bool = cfg!(debug_assertions); - -impl ShadowGraph { - pub fn new() -> Self { - let forbidden_edge = if !ENABLED { - None - } else { - match env::var("RUST_FORBID_DEP_GRAPH_EDGE") { - Ok(s) => { - match EdgeFilter::new(&s) { - Ok(f) => Some(f), - Err(err) => bug!("RUST_FORBID_DEP_GRAPH_EDGE invalid: {}", err), - } - } - Err(_) => None, - } - }; - - ShadowGraph { - stack: RefCell::new(vec![]), - forbidden_edge, - } - } - - #[inline] - pub fn enabled(&self) -> bool { - ENABLED - } - - pub fn enqueue(&self, message: &DepMessage) { - if ENABLED { - if self.stack.try_borrow().is_err() { - // When we apply edge filters, that invokes the Debug trait on - // DefIds, which in turn reads from various bits of state and - // creates reads! Ignore those recursive reads. - return; - } - - let mut stack = self.stack.borrow_mut(); - match *message { - // It is ok to READ shared state outside of a - // task. That can't do any harm (at least, the only - // way it can do harm is by leaking that data into a - // query or task, which would be a problem - // anyway). What would be bad is WRITING to that - // state. - DepMessage::Read(_) => { } - DepMessage::Write(ref n) => self.check_edge(top(&stack), Some(Some(n))), - DepMessage::PushTask(ref n) => stack.push(Some(n.clone())), - DepMessage::PushIgnore => stack.push(None), - DepMessage::PopTask(ref n) => { - match stack.pop() { - Some(Some(m)) => { - if *n != m { - bug!("stack mismatch: found {:?} expected {:?}", m, n) - } - } - Some(None) => bug!("stack mismatch: found Ignore expected {:?}", n), - None => bug!("stack mismatch: found empty stack, expected {:?}", n), - } - } - DepMessage::PopIgnore => { - match stack.pop() { - Some(Some(m)) => bug!("stack mismatch: found {:?} expected ignore", m), - Some(None) => (), - None => bug!("stack mismatch: found empty stack, expected ignore"), - } - } - DepMessage::Query => (), - } - } - } - - fn check_edge(&self, - source: Option>, - target: Option>) { - assert!(ENABLED); - match (source, target) { - // cannot happen, one side is always Some(Some(_)) - (None, None) => unreachable!(), - - // nothing on top of the stack - (None, Some(n)) | (Some(n), None) => bug!("write of {:?} but no current task", n), - - // this corresponds to an Ignore being top of the stack - (Some(None), _) | (_, Some(None)) => (), - - // a task is on top of the stack - (Some(Some(source)), Some(Some(target))) => { - if let Some(ref forbidden_edge) = self.forbidden_edge { - if forbidden_edge.test(source, target) { - bug!("forbidden edge {:?} -> {:?} created", source, target) - } - } - } - } - } -} - -// Do a little juggling: we get back a reference to an option at the -// top of the stack, convert it to an optional reference. -fn top<'s>(stack: &'s Vec>) -> Option> { - stack.last() - .map(|n: &'s Option| -> Option<&'s DepNode> { - // (*) - // (*) type annotation just there to clarify what would - // otherwise be some *really* obscure code - n.as_ref() - }) -} diff --git a/src/librustc/dep_graph/thread.rs b/src/librustc/dep_graph/thread.rs deleted file mode 100644 index f6635fe16f77d..0000000000000 --- a/src/librustc/dep_graph/thread.rs +++ /dev/null @@ -1,178 +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. - -//! Manages the communication between the compiler's main thread and -//! the thread that constructs the dependency graph. The basic idea is -//! to use double buffering to lower the cost of producing a message. -//! In the compiler thread, we accumulate messages in a vector until -//! the vector is full, or until we want to query the graph, and then -//! we send that vector over to the depgraph thread. At the same time, -//! we receive an empty vector from the depgraph thread that we can use -//! to accumulate more messages. This way we only ever have two vectors -//! allocated (and both have a fairly large capacity). - -use rustc_data_structures::veccell::VecCell; -use std::sync::mpsc::{self, Sender, Receiver}; -use std::thread; - -use super::DepGraphQuery; -use super::DepNode; -use super::edges::DepGraphEdges; -use super::shadow::ShadowGraph; - -#[derive(Debug)] -pub enum DepMessage { - Read(DepNode), - Write(DepNode), - PushTask(DepNode), - PopTask(DepNode), - PushIgnore, - PopIgnore, - Query, -} - -pub struct DepGraphThreadData { - enabled: bool, - - // The "shadow graph" is a debugging aid. We give it each message - // in real time as it arrives and it checks for various errors - // (for example, a read/write when there is no current task; it - // can also apply user-defined filters; see `shadow` module for - // details). This only occurs if debug-assertions are enabled. - // - // Note that in some cases the same errors will occur when the - // data is processed off the main thread, but that's annoying - // because it lacks precision about the source of the error. - shadow_graph: ShadowGraph, - - // current buffer, where we accumulate messages - messages: VecCell, - - // where to receive new buffer when full - swap_in: Receiver>, - - // where to send buffer when full - swap_out: Sender>, - - // where to receive query results - query_in: Receiver, -} - -const INITIAL_CAPACITY: usize = 2048; - -impl DepGraphThreadData { - pub fn new(enabled: bool) -> DepGraphThreadData { - let (tx1, rx1) = mpsc::channel(); - let (tx2, rx2) = mpsc::channel(); - let (txq, rxq) = mpsc::channel(); - - if enabled { - thread::spawn(move || main(rx1, tx2, txq)); - } - - DepGraphThreadData { - enabled, - shadow_graph: ShadowGraph::new(), - messages: VecCell::with_capacity(INITIAL_CAPACITY), - swap_in: rx2, - swap_out: tx1, - query_in: rxq, - } - } - - /// True if we are actually building the full dep-graph. - #[inline] - pub fn is_fully_enabled(&self) -> bool { - self.enabled - } - - /// True if (a) we are actually building the full dep-graph, or (b) we are - /// only enqueuing messages in order to sanity-check them (which happens - /// when debug assertions are enabled). - #[inline] - pub fn is_enqueue_enabled(&self) -> bool { - self.is_fully_enabled() || self.shadow_graph.enabled() - } - - /// Sends the current batch of messages to the thread. Installs a - /// new vector of messages. - fn swap(&self) { - assert!(self.is_fully_enabled(), "should never swap if not fully enabled"); - - // should be a buffer waiting for us (though of course we may - // have to wait for depgraph thread to finish processing the - // old messages) - let new_messages = self.swap_in.recv().unwrap(); - assert!(new_messages.is_empty()); - - // swap in the empty buffer and extract the full one - let old_messages = self.messages.swap(new_messages); - - // send full buffer to depgraph thread to be processed - self.swap_out.send(old_messages).unwrap(); - } - - pub fn query(&self) -> DepGraphQuery { - assert!(self.is_fully_enabled(), "should never query if not fully enabled"); - self.enqueue(DepMessage::Query); - self.swap(); - self.query_in.recv().unwrap() - } - - /// Enqueue a message to be sent when things are next swapped. (If - /// the buffer is full, this may swap.) - #[inline] - pub fn enqueue(&self, message: DepMessage) { - assert!(self.is_enqueue_enabled(), "should never enqueue if not enqueue-enabled"); - self.shadow_graph.enqueue(&message); - if self.is_fully_enabled() { - self.enqueue_enabled(message); - } - } - - // Outline this fn since I expect it may want to be inlined - // separately. - fn enqueue_enabled(&self, message: DepMessage) { - let len = self.messages.push(message); - if len == INITIAL_CAPACITY { - self.swap(); - } - } -} - -/// Definition of the depgraph thread. -pub fn main(swap_in: Receiver>, - swap_out: Sender>, - query_out: Sender) { - let mut edges = DepGraphEdges::new(); - - // the compiler thread always expects a fresh buffer to be - // waiting, so queue one up - swap_out.send(Vec::with_capacity(INITIAL_CAPACITY)).unwrap(); - - // process the buffers from compiler thread as we receive them - for mut messages in swap_in { - for msg in messages.drain(..) { - match msg { - DepMessage::Read(node) => edges.read(node), - DepMessage::Write(node) => edges.write(node), - DepMessage::PushTask(node) => edges.push_task(node), - DepMessage::PopTask(node) => edges.pop_task(node), - DepMessage::PushIgnore => edges.push_ignore(), - DepMessage::PopIgnore => edges.pop_ignore(), - DepMessage::Query => query_out.send(edges.query()).unwrap(), - } - } - if let Err(_) = swap_out.send(messages) { - // the receiver must have been dropped already - break; - } - } -} diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs index 08184d62679ea..cef1be5cee232 100644 --- a/src/librustc/diagnostics.rs +++ b/src/librustc/diagnostics.rs @@ -1947,27 +1947,25 @@ Either way, try to update/remove it in order to fix the error. "##, E0621: r##" -This error code indicates a mismatch between the function signature (i.e., -the parameter types and the return type) and the function body. Most of -the time, this indicates that the function signature needs to be changed to -match the body, but it may be that the body needs to be changed to match -the signature. +This error code indicates a mismatch between the lifetimes appearing in the +function signature (i.e., the parameter types and the return type) and the +data-flow found in the function body. -Specifically, one or more of the parameters contain borrowed data that -needs to have a named lifetime in order for the body to type-check. Most of -the time, this is because the borrowed data is being returned from the -function, as in this example: +Erroneous code example: ```compile_fail,E0621 -fn foo<'a>(x: &'a i32, y: &i32) -> &'a i32 { // explicit lifetime required - // in the type of `y` +fn foo<'a>(x: &'a i32, y: &i32) -> &'a i32 { // error: explicit lifetime + // required in the type of + // `y` if x > y { x } else { y } } ``` -Here, the function is returning data borrowed from either x or y, but the -'a annotation indicates that it is returning data only from x. We can make -the signature match the body by changing the type of y to &'a i32, like so: +In the code above, the function is returning data borrowed from either `x` or +`y`, but the `'a` annotation indicates that it is returning data only from `x`. +To fix the error, the signature and the body must be made to match. Typically, +this is done by updating the function signature. So, in this case, we change +the type of `y` to `&'a i32`, like so: ``` fn foo<'a>(x: &'a i32, y: &'a i32) -> &'a i32 { @@ -1975,7 +1973,8 @@ fn foo<'a>(x: &'a i32, y: &'a i32) -> &'a i32 { } ``` -Alternatively, you could change the body not to return data from y: +Now the signature indicates that the function data borrowed from either `x` or +`y`. Alternatively, you could change the body to not return data from `y`: ``` fn foo<'a>(x: &'a i32, y: &i32) -> &'a i32 { diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs index 1f7b73d134596..beaf65b77d81f 100644 --- a/src/librustc/hir/print.rs +++ b/src/librustc/hir/print.rs @@ -15,10 +15,9 @@ use syntax::ast; use syntax::codemap::{CodeMap, Spanned}; use syntax::parse::ParseSess; use syntax::parse::lexer::comments; -use syntax::print::pp::{self, break_offset, word, space, hardbreak}; -use syntax::print::pp::{Breaks, eof}; +use syntax::print::pp::{self, Breaks}; use syntax::print::pp::Breaks::{Consistent, Inconsistent}; -use syntax::print::pprust::{self as ast_pp, PrintState}; +use syntax::print::pprust::PrintState; use syntax::ptr::P; use syntax::symbol::keywords; use syntax_pos::{self, BytePos}; @@ -28,6 +27,8 @@ use hir::{PatKind, RegionTyParamBound, TraitTyParamBound, TraitBoundModifier, Ra use std::cell::Cell; use std::io::{self, Write, Read}; +use std::iter::Peekable; +use std::vec; pub enum AnnNode<'a> { NodeName(&'a ast::Name), @@ -78,8 +79,8 @@ pub struct State<'a> { pub s: pp::Printer<'a>, cm: Option<&'a CodeMap>, comments: Option>, - literals: Option>, - cur_cmnt_and_lit: ast_pp::CurrentCommentAndLiteral, + literals: Peekable>, + cur_cmnt: usize, boxes: Vec, ann: &'a (PpAnn + 'a), } @@ -97,12 +98,16 @@ impl<'a> PrintState<'a> for State<'a> { &mut self.comments } - fn cur_cmnt_and_lit(&mut self) -> &mut ast_pp::CurrentCommentAndLiteral { - &mut self.cur_cmnt_and_lit + fn cur_cmnt(&mut self) -> &mut usize { + &mut self.cur_cmnt } - fn literals(&self) -> &Option> { - &self.literals + fn cur_lit(&mut self) -> Option<&comments::Literal> { + self.literals.peek() + } + + fn bump_lit(&mut self) -> Option { + self.literals.next() } } @@ -132,7 +137,7 @@ pub fn print_crate<'a>(cm: &'a CodeMap, s.print_mod(&krate.module, &krate.attrs)?; s.print_remaining_comments()?; - eof(&mut s.s) + s.s.eof() } impl<'a> State<'a> { @@ -170,11 +175,8 @@ impl<'a> State<'a> { s: pp::mk_printer(out, default_columns), cm: Some(cm), comments: comments.clone(), - literals: literals.clone(), - cur_cmnt_and_lit: ast_pp::CurrentCommentAndLiteral { - cur_cmnt: 0, - cur_lit: 0, - }, + literals: literals.unwrap_or_default().into_iter().peekable(), + cur_cmnt: 0, boxes: Vec::new(), ann, } @@ -190,16 +192,13 @@ pub fn to_string(ann: &PpAnn, f: F) -> String s: pp::mk_printer(Box::new(&mut wr), default_columns), cm: None, comments: None, - literals: None, - cur_cmnt_and_lit: ast_pp::CurrentCommentAndLiteral { - cur_cmnt: 0, - cur_lit: 0, - }, + literals: vec![].into_iter().peekable(), + cur_cmnt: 0, boxes: Vec::new(), ann, }; f(&mut printer).unwrap(); - eof(&mut printer.s).unwrap(); + printer.s.eof().unwrap(); } String::from_utf8(wr).unwrap() } @@ -207,7 +206,7 @@ pub fn to_string(ann: &PpAnn, f: F) -> String pub fn visibility_qualified(vis: &hir::Visibility, w: &str) -> String { to_string(NO_ANN, |s| { s.print_visibility(vis)?; - word(&mut s.s, w) + s.s.word(w) }) } @@ -226,15 +225,15 @@ fn needs_parentheses(expr: &hir::Expr) -> bool { impl<'a> State<'a> { pub fn cbox(&mut self, u: usize) -> io::Result<()> { self.boxes.push(pp::Breaks::Consistent); - pp::cbox(&mut self.s, u) + self.s.cbox(u) } pub fn nbsp(&mut self) -> io::Result<()> { - word(&mut self.s, " ") + self.s.word(" ") } pub fn word_nbsp(&mut self, w: &str) -> io::Result<()> { - word(&mut self.s, w)?; + self.s.word(w)?; self.nbsp() } @@ -251,7 +250,7 @@ impl<'a> State<'a> { } pub fn bopen(&mut self) -> io::Result<()> { - word(&mut self.s, "{")?; + self.s.word("{")?; self.end() // close the head-box } @@ -265,7 +264,7 @@ impl<'a> State<'a> { -> io::Result<()> { self.maybe_print_comment(span.hi)?; self.break_offset_if_not_bol(1, -(indented as isize))?; - word(&mut self.s, "}")?; + self.s.word("}")?; if close_box { self.end()?; // close the outer-box } @@ -283,19 +282,19 @@ impl<'a> State<'a> { } pub fn space_if_not_bol(&mut self) -> io::Result<()> { if !self.is_bol() { - space(&mut self.s)?; + self.s.space()?; } Ok(()) } pub fn break_offset_if_not_bol(&mut self, n: usize, off: isize) -> io::Result<()> { if !self.is_bol() { - break_offset(&mut self.s, n, off) + self.s.break_offset(n, off) } else { if off != 0 && self.s.last_token().is_hardbreak_tok() { // We do something pretty sketchy here: tuck the nonzero // offset-adjustment we were going to deposit along with the // break into the previous hardbreak. - self.s.replace_last_token(pp::hardbreak_tok_offset(off)); + self.s.replace_last_token(pp::Printer::hardbreak_tok_offset(off)); } Ok(()) } @@ -304,11 +303,11 @@ impl<'a> State<'a> { // Synthesizes a comment that was not textually present in the original source // file. pub fn synth_comment(&mut self, text: String) -> io::Result<()> { - word(&mut self.s, "/*")?; - space(&mut self.s)?; - word(&mut self.s, &text[..])?; - space(&mut self.s)?; - word(&mut self.s, "*/") + self.s.word("/*")?; + self.s.space()?; + self.s.word(&text[..])?; + self.s.space()?; + self.s.word("*/") } @@ -329,7 +328,7 @@ impl<'a> State<'a> { op(self, elt)?; i += 1; if i < len { - word(&mut self.s, ",")?; + self.s.word(",")?; self.maybe_print_trailing_comment(get_span(elt), Some(get_span(&elts[i]).hi))?; self.space_if_not_bol()?; } @@ -373,12 +372,12 @@ impl<'a> State<'a> { self.ibox(0)?; match ty.node { hir::TySlice(ref ty) => { - word(&mut self.s, "[")?; + self.s.word("[")?; self.print_type(&ty)?; - word(&mut self.s, "]")?; + self.s.word("]")?; } hir::TyPtr(ref mt) => { - word(&mut self.s, "*")?; + self.s.word("*")?; match mt.mutbl { hir::MutMutable => self.word_nbsp("mut")?, hir::MutImmutable => self.word_nbsp("const")?, @@ -386,18 +385,18 @@ impl<'a> State<'a> { self.print_type(&mt.ty)?; } hir::TyRptr(ref lifetime, ref mt) => { - word(&mut self.s, "&")?; + self.s.word("&")?; self.print_opt_lifetime(lifetime)?; self.print_mt(mt)?; } hir::TyNever => { - word(&mut self.s, "!")?; + self.s.word("!")?; }, hir::TyTup(ref elts) => { self.popen()?; self.commasep(Inconsistent, &elts[..], |s, ty| s.print_type(&ty))?; if elts.len() == 1 { - word(&mut self.s, ",")?; + self.s.word(",")?; } self.pclose()?; } @@ -436,22 +435,22 @@ impl<'a> State<'a> { self.print_bounds("impl ", &bounds[..])?; } hir::TyArray(ref ty, v) => { - word(&mut self.s, "[")?; + self.s.word("[")?; self.print_type(&ty)?; - word(&mut self.s, "; ")?; + self.s.word("; ")?; self.ann.nested(self, Nested::Body(v))?; - word(&mut self.s, "]")?; + self.s.word("]")?; } hir::TyTypeof(e) => { - word(&mut self.s, "typeof(")?; + self.s.word("typeof(")?; self.ann.nested(self, Nested::Body(e))?; - word(&mut self.s, ")")?; + self.s.word(")")?; } hir::TyInfer => { - word(&mut self.s, "_")?; + self.s.word("_")?; } hir::TyErr => { - word(&mut self.s, "?")?; + self.s.word("?")?; } } self.end() @@ -474,7 +473,7 @@ impl<'a> State<'a> { arg_names, None)?; self.end()?; // end head-ibox - word(&mut self.s, ";")?; + self.s.word(";")?; self.end() // end the outer fn box } hir::ForeignItemStatic(ref t, m) => { @@ -485,7 +484,7 @@ impl<'a> State<'a> { self.print_name(item.name)?; self.word_space(":")?; self.print_type(&t)?; - word(&mut self.s, ";")?; + self.s.word(";")?; self.end()?; // end the head-ibox self.end() // end the outer cbox } @@ -498,17 +497,17 @@ impl<'a> State<'a> { default: Option, vis: &hir::Visibility) -> io::Result<()> { - word(&mut self.s, &visibility_qualified(vis, ""))?; + self.s.word(&visibility_qualified(vis, ""))?; self.word_space("const")?; self.print_name(name)?; self.word_space(":")?; self.print_type(ty)?; if let Some(expr) = default { - space(&mut self.s)?; + self.s.space()?; self.word_space("=")?; self.ann.nested(self, Nested::Body(expr))?; } - word(&mut self.s, ";") + self.s.word(";") } fn print_associated_type(&mut self, @@ -522,11 +521,11 @@ impl<'a> State<'a> { self.print_bounds(":", bounds)?; } if let Some(ty) = ty { - space(&mut self.s)?; + self.s.space()?; self.word_space("=")?; self.print_type(ty)?; } - word(&mut self.s, ";") + self.s.word(";") } /// Pretty-print an item @@ -545,12 +544,12 @@ impl<'a> State<'a> { } else { self.print_name(p)?; } - space(&mut self.s)?; - word(&mut self.s, "as")?; - space(&mut self.s)?; + self.s.space()?; + self.s.word("as")?; + self.s.space()?; } self.print_name(item.name)?; - word(&mut self.s, ";")?; + self.s.word(";")?; self.end()?; // end inner head-block self.end()?; // end outer head-block } @@ -561,14 +560,14 @@ impl<'a> State<'a> { match kind { hir::UseKind::Single => { if path.segments.last().unwrap().name != item.name { - space(&mut self.s)?; + self.s.space()?; self.word_space("as")?; self.print_name(item.name)?; } - word(&mut self.s, ";")?; + self.s.word(";")?; } - hir::UseKind::Glob => word(&mut self.s, "::*;")?, - hir::UseKind::ListStem => word(&mut self.s, "::{};")? + hir::UseKind::Glob => self.s.word("::*;")?, + hir::UseKind::ListStem => self.s.word("::{};")? } self.end()?; // end inner head-block self.end()?; // end outer head-block @@ -581,12 +580,12 @@ impl<'a> State<'a> { self.print_name(item.name)?; self.word_space(":")?; self.print_type(&ty)?; - space(&mut self.s)?; + self.s.space()?; self.end()?; // end the head-ibox self.word_space("=")?; self.ann.nested(self, Nested::Body(expr))?; - word(&mut self.s, ";")?; + self.s.word(";")?; self.end()?; // end the outer cbox } hir::ItemConst(ref ty, expr) => { @@ -594,12 +593,12 @@ impl<'a> State<'a> { self.print_name(item.name)?; self.word_space(":")?; self.print_type(&ty)?; - space(&mut self.s)?; + self.s.space()?; self.end()?; // end the head-ibox self.word_space("=")?; self.ann.nested(self, Nested::Body(expr))?; - word(&mut self.s, ";")?; + self.s.word(";")?; self.end()?; // end the outer cbox } hir::ItemFn(ref decl, unsafety, constness, abi, ref typarams, body) => { @@ -613,7 +612,7 @@ impl<'a> State<'a> { &item.vis, &[], Some(body))?; - word(&mut self.s, " ")?; + self.s.word(" ")?; self.end()?; // need to close a box self.end()?; // need to close a box self.ann.nested(self, Nested::Body(body))?; @@ -635,7 +634,7 @@ impl<'a> State<'a> { } hir::ItemGlobalAsm(ref ga) => { self.head(&visibility_qualified(&item.vis, "global asm"))?; - word(&mut self.s, &ga.asm.as_str())?; + self.s.word(&ga.asm.as_str())?; self.end()? } hir::ItemTy(ref ty, ref params) => { @@ -647,10 +646,10 @@ impl<'a> State<'a> { self.end()?; // end the inner ibox self.print_where_clause(¶ms.where_clause)?; - space(&mut self.s)?; + self.s.space()?; self.word_space("=")?; self.print_type(&ty)?; - word(&mut self.s, ";")?; + self.s.word(";")?; self.end()?; // end the outer ibox } hir::ItemEnum(ref enum_definition, ref params) => { @@ -670,7 +669,7 @@ impl<'a> State<'a> { self.print_unsafety(unsafety)?; self.word_nbsp("impl")?; self.print_trait_ref(trait_ref)?; - space(&mut self.s)?; + self.s.space()?; self.word_space("for")?; self.word_space("..")?; self.bopen()?; @@ -691,12 +690,12 @@ impl<'a> State<'a> { if generics.is_parameterized() { self.print_generics(generics)?; - space(&mut self.s)?; + self.s.space()?; } match polarity { hir::ImplPolarity::Negative => { - word(&mut self.s, "!")?; + self.s.word("!")?; } _ => {} } @@ -704,7 +703,7 @@ impl<'a> State<'a> { match opt_trait { &Some(ref t) => { self.print_trait_ref(t)?; - space(&mut self.s)?; + self.s.space()?; self.word_space("for")?; } &None => {} @@ -713,7 +712,7 @@ impl<'a> State<'a> { self.print_type(&ty)?; self.print_where_clause(&generics.where_clause)?; - space(&mut self.s)?; + self.s.space()?; self.bopen()?; self.print_inner_attributes(&item.attrs)?; for impl_item in impl_items { @@ -731,7 +730,7 @@ impl<'a> State<'a> { let mut real_bounds = Vec::with_capacity(bounds.len()); for b in bounds.iter() { if let TraitTyParamBound(ref ptr, hir::TraitBoundModifier::Maybe) = *b { - space(&mut self.s)?; + self.s.space()?; self.word_space("for ?")?; self.print_trait_ref(&ptr.trait_ref)?; } else { @@ -740,7 +739,7 @@ impl<'a> State<'a> { } self.print_bounds(":", &real_bounds[..])?; self.print_where_clause(&generics.where_clause)?; - word(&mut self.s, " ")?; + self.s.word(" ")?; self.bopen()?; for trait_item in trait_items { self.ann.nested(self, Nested::TraitItem(trait_item.id))?; @@ -757,7 +756,7 @@ impl<'a> State<'a> { fn print_formal_lifetime_list(&mut self, lifetimes: &[hir::LifetimeDef]) -> io::Result<()> { if !lifetimes.is_empty() { - word(&mut self.s, "for<")?; + self.s.word("for<")?; let mut comma = false; for lifetime_def in lifetimes { if comma { @@ -766,7 +765,7 @@ impl<'a> State<'a> { self.print_lifetime_def(lifetime_def)?; comma = true; } - word(&mut self.s, ">")?; + self.s.word(">")?; } Ok(()) } @@ -787,7 +786,7 @@ impl<'a> State<'a> { self.print_name(name)?; self.print_generics(generics)?; self.print_where_clause(&generics.where_clause)?; - space(&mut self.s)?; + self.s.space()?; self.print_variants(&enum_definition.variants, span) } @@ -802,7 +801,7 @@ impl<'a> State<'a> { self.print_outer_attributes(&v.node.attrs)?; self.ibox(indent_unit)?; self.print_variant(v)?; - word(&mut self.s, ",")?; + self.s.word(",")?; self.end()?; self.maybe_print_trailing_comment(v.span, None)?; } @@ -814,7 +813,7 @@ impl<'a> State<'a> { hir::Public => self.word_nbsp("pub"), hir::Visibility::Crate => self.word_nbsp("pub(crate)"), hir::Visibility::Restricted { ref path, .. } => { - word(&mut self.s, "pub(")?; + self.s.word("pub(")?; self.print_path(path, false)?; self.word_nbsp(")") } @@ -852,7 +851,7 @@ impl<'a> State<'a> { } self.print_where_clause(&generics.where_clause)?; if print_finalizer { - word(&mut self.s, ";")?; + self.s.word(";")?; } self.end()?; self.end() // close the outer-box @@ -870,7 +869,7 @@ impl<'a> State<'a> { self.print_name(field.name)?; self.word_nbsp(":")?; self.print_type(&field.ty)?; - word(&mut self.s, ",")?; + self.s.word(",")?; } self.bclose(span) @@ -882,7 +881,7 @@ impl<'a> State<'a> { let generics = hir::Generics::empty(); self.print_struct(&v.node.data, &generics, v.node.name, v.span, false)?; if let Some(d) = v.node.disr_expr { - space(&mut self.s)?; + self.s.space()?; self.word_space("=")?; self.ann.nested(self, Nested::Body(d))?; } @@ -917,7 +916,7 @@ impl<'a> State<'a> { } hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Required(ref arg_names)) => { self.print_method_sig(ti.name, sig, &hir::Inherited, arg_names, None)?; - word(&mut self.s, ";")?; + self.s.word(";")?; } hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Provided(body)) => { self.head("")?; @@ -975,11 +974,11 @@ impl<'a> State<'a> { hir::StmtSemi(ref expr, _) => { self.space_if_not_bol()?; self.print_expr(&expr)?; - word(&mut self.s, ";")?; + self.s.word(";")?; } } if stmt_ends_with_semi(&st.node) { - word(&mut self.s, ";")?; + self.s.word(";")?; } self.maybe_print_trailing_comment(st.span, None) } @@ -1047,9 +1046,9 @@ impl<'a> State<'a> { hir::ExprIf(ref i, ref then, ref e) => { self.cbox(indent_unit - 1)?; self.ibox(0)?; - word(&mut self.s, " else if ")?; + self.s.word(" else if ")?; self.print_expr(&i)?; - space(&mut self.s)?; + self.s.space()?; self.print_expr(&then)?; self.print_else(e.as_ref().map(|e| &**e)) } @@ -1057,7 +1056,7 @@ impl<'a> State<'a> { hir::ExprBlock(ref b) => { self.cbox(indent_unit - 1)?; self.ibox(0)?; - word(&mut self.s, " else ")?; + self.s.word(" else ")?; self.print_block(&b) } // BLEAH, constraints would be great here @@ -1077,7 +1076,7 @@ impl<'a> State<'a> { -> io::Result<()> { self.head("if")?; self.print_expr(test)?; - space(&mut self.s)?; + self.s.space()?; self.print_expr(blk)?; self.print_else(elseopt) } @@ -1090,10 +1089,10 @@ impl<'a> State<'a> { -> io::Result<()> { self.head("if let")?; self.print_pat(pat)?; - space(&mut self.s)?; + self.s.space()?; self.word_space("=")?; self.print_expr(expr)?; - space(&mut self.s)?; + self.s.space()?; self.print_block(blk)?; self.print_else(elseopt) } @@ -1119,19 +1118,19 @@ impl<'a> State<'a> { fn print_expr_vec(&mut self, exprs: &[hir::Expr]) -> io::Result<()> { self.ibox(indent_unit)?; - word(&mut self.s, "[")?; + self.s.word("[")?; self.commasep_exprs(Inconsistent, exprs)?; - word(&mut self.s, "]")?; + self.s.word("]")?; self.end() } fn print_expr_repeat(&mut self, element: &hir::Expr, count: hir::BodyId) -> io::Result<()> { self.ibox(indent_unit)?; - word(&mut self.s, "[")?; + self.s.word("[")?; self.print_expr(element)?; self.word_space(";")?; self.ann.nested(self, Nested::Body(count))?; - word(&mut self.s, "]")?; + self.s.word("]")?; self.end() } @@ -1141,7 +1140,7 @@ impl<'a> State<'a> { wth: &Option>) -> io::Result<()> { self.print_qpath(qpath, true)?; - word(&mut self.s, "{")?; + self.s.word("{")?; self.commasep_cmnt(Consistent, &fields[..], |s, field| { @@ -1158,18 +1157,18 @@ impl<'a> State<'a> { Some(ref expr) => { self.ibox(indent_unit)?; if !fields.is_empty() { - word(&mut self.s, ",")?; - space(&mut self.s)?; + self.s.word(",")?; + self.s.space()?; } - word(&mut self.s, "..")?; + self.s.word("..")?; self.print_expr(&expr)?; self.end()?; } _ => if !fields.is_empty() { - word(&mut self.s, ",")? + self.s.word(",")? }, } - word(&mut self.s, "}")?; + self.s.word("}")?; Ok(()) } @@ -1177,7 +1176,7 @@ impl<'a> State<'a> { self.popen()?; self.commasep_exprs(Inconsistent, exprs)?; if exprs.len() == 1 { - word(&mut self.s, ",")?; + self.s.word(",")?; } self.pclose() } @@ -1193,7 +1192,7 @@ impl<'a> State<'a> { -> io::Result<()> { let base_args = &args[1..]; self.print_expr(&args[0])?; - word(&mut self.s, ".")?; + self.s.word(".")?; self.print_name(segment.name)?; if !segment.parameters.lifetimes().is_empty() || !segment.parameters.types().is_empty() || @@ -1209,13 +1208,13 @@ impl<'a> State<'a> { rhs: &hir::Expr) -> io::Result<()> { self.print_expr(lhs)?; - space(&mut self.s)?; + self.s.space()?; self.word_space(op.node.as_str())?; self.print_expr(rhs) } fn print_expr_unary(&mut self, op: hir::UnOp, expr: &hir::Expr) -> io::Result<()> { - word(&mut self.s, op.as_str())?; + self.s.word(op.as_str())?; self.print_expr_maybe_paren(expr) } @@ -1223,7 +1222,7 @@ impl<'a> State<'a> { mutability: hir::Mutability, expr: &hir::Expr) -> io::Result<()> { - word(&mut self.s, "&")?; + self.s.word("&")?; self.print_mutability(mutability)?; self.print_expr_maybe_paren(expr) } @@ -1270,7 +1269,7 @@ impl<'a> State<'a> { } hir::ExprCast(ref expr, ref ty) => { self.print_expr(&expr)?; - space(&mut self.s)?; + self.s.space()?; self.word_space("as")?; self.print_type(&ty)?; } @@ -1289,7 +1288,7 @@ impl<'a> State<'a> { } self.head("while")?; self.print_expr(&test)?; - space(&mut self.s)?; + self.s.space()?; self.print_block(&blk)?; } hir::ExprLoop(ref blk, opt_sp_name, _) => { @@ -1298,7 +1297,7 @@ impl<'a> State<'a> { self.word_space(":")?; } self.head("loop")?; - space(&mut self.s)?; + self.s.space()?; self.print_block(&blk)?; } hir::ExprMatch(ref expr, ref arms, _) => { @@ -1306,7 +1305,7 @@ impl<'a> State<'a> { self.ibox(4)?; self.word_nbsp("match")?; self.print_expr(&expr)?; - space(&mut self.s)?; + self.s.space()?; self.bopen()?; for arm in arms { self.print_arm(arm)?; @@ -1317,7 +1316,7 @@ impl<'a> State<'a> { self.print_capture_clause(capture_clause)?; self.print_closure_args(&decl, body)?; - space(&mut self.s)?; + self.s.space()?; // this is a bare expression self.ann.nested(self, Nested::Body(body))?; @@ -1337,68 +1336,68 @@ impl<'a> State<'a> { } hir::ExprAssign(ref lhs, ref rhs) => { self.print_expr(&lhs)?; - space(&mut self.s)?; + self.s.space()?; self.word_space("=")?; self.print_expr(&rhs)?; } hir::ExprAssignOp(op, ref lhs, ref rhs) => { self.print_expr(&lhs)?; - space(&mut self.s)?; - word(&mut self.s, op.node.as_str())?; + self.s.space()?; + self.s.word(op.node.as_str())?; self.word_space("=")?; self.print_expr(&rhs)?; } hir::ExprField(ref expr, name) => { self.print_expr(&expr)?; - word(&mut self.s, ".")?; + self.s.word(".")?; self.print_name(name.node)?; } hir::ExprTupField(ref expr, id) => { self.print_expr(&expr)?; - word(&mut self.s, ".")?; + self.s.word(".")?; self.print_usize(id.node)?; } hir::ExprIndex(ref expr, ref index) => { self.print_expr(&expr)?; - word(&mut self.s, "[")?; + self.s.word("[")?; self.print_expr(&index)?; - word(&mut self.s, "]")?; + self.s.word("]")?; } hir::ExprPath(ref qpath) => { self.print_qpath(qpath, true)? } hir::ExprBreak(label, ref opt_expr) => { - word(&mut self.s, "break")?; - space(&mut self.s)?; + self.s.word("break")?; + self.s.space()?; if let Some(label_ident) = label.ident { self.print_name(label_ident.node.name)?; - space(&mut self.s)?; + self.s.space()?; } if let Some(ref expr) = *opt_expr { self.print_expr(expr)?; - space(&mut self.s)?; + self.s.space()?; } } hir::ExprAgain(label) => { - word(&mut self.s, "continue")?; - space(&mut self.s)?; + self.s.word("continue")?; + self.s.space()?; if let Some(label_ident) = label.ident { self.print_name(label_ident.node.name)?; - space(&mut self.s)? + self.s.space()? } } hir::ExprRet(ref result) => { - word(&mut self.s, "return")?; + self.s.word("return")?; match *result { Some(ref expr) => { - word(&mut self.s, " ")?; + self.s.word(" ")?; self.print_expr(&expr)?; } _ => (), } } hir::ExprInlineAsm(ref a, ref outputs, ref inputs) => { - word(&mut self.s, "asm!")?; + self.s.word("asm!")?; self.popen()?; self.print_string(&a.asm.as_str(), a.asm_str_style)?; self.word_space(":")?; @@ -1420,7 +1419,7 @@ impl<'a> State<'a> { out_idx += 1; Ok(()) })?; - space(&mut self.s)?; + self.s.space()?; self.word_space(":")?; let mut in_idx = 0; @@ -1432,7 +1431,7 @@ impl<'a> State<'a> { in_idx += 1; Ok(()) })?; - space(&mut self.s)?; + self.s.space()?; self.word_space(":")?; self.commasep(Inconsistent, &a.clobbers, |s, co| { @@ -1452,7 +1451,7 @@ impl<'a> State<'a> { } if !options.is_empty() { - space(&mut self.s)?; + self.s.space()?; self.word_space(":")?; self.commasep(Inconsistent, &options, |s, &co| { s.print_string(co, ast::StrStyle::Cooked)?; @@ -1501,17 +1500,17 @@ impl<'a> State<'a> { } pub fn print_usize(&mut self, i: usize) -> io::Result<()> { - word(&mut self.s, &i.to_string()) + self.s.word(&i.to_string()) } pub fn print_name(&mut self, name: ast::Name) -> io::Result<()> { - word(&mut self.s, &name.as_str())?; + self.s.word(&name.as_str())?; self.ann.post(self, NodeName(&name)) } pub fn print_for_decl(&mut self, loc: &hir::Local, coll: &hir::Expr) -> io::Result<()> { self.print_local_decl(loc)?; - space(&mut self.s)?; + self.s.space()?; self.word_space("in")?; self.print_expr(coll) } @@ -1524,7 +1523,7 @@ impl<'a> State<'a> { for (i, segment) in path.segments.iter().enumerate() { if i > 0 { - word(&mut self.s, "::")? + self.s.word("::")? } if segment.name != keywords::CrateRoot.name() && segment.name != keywords::DollarCrate.name() { @@ -1545,14 +1544,14 @@ impl<'a> State<'a> { self.print_path(path, colons_before_params) } hir::QPath::Resolved(Some(ref qself), ref path) => { - word(&mut self.s, "<")?; + self.s.word("<")?; self.print_type(qself)?; - space(&mut self.s)?; + self.s.space()?; self.word_space("as")?; for (i, segment) in path.segments[..path.segments.len() - 1].iter().enumerate() { if i > 0 { - word(&mut self.s, "::")? + self.s.word("::")? } if segment.name != keywords::CrateRoot.name() && segment.name != keywords::DollarCrate.name() { @@ -1561,17 +1560,17 @@ impl<'a> State<'a> { } } - word(&mut self.s, ">")?; - word(&mut self.s, "::")?; + self.s.word(">")?; + self.s.word("::")?; let item_segment = path.segments.last().unwrap(); self.print_name(item_segment.name)?; self.print_path_parameters(&item_segment.parameters, colons_before_params) } hir::QPath::TypeRelative(ref qself, ref item_segment) => { - word(&mut self.s, "<")?; + self.s.word("<")?; self.print_type(qself)?; - word(&mut self.s, ">")?; - word(&mut self.s, "::")?; + self.s.word(">")?; + self.s.word("::")?; self.print_name(item_segment.name)?; self.print_path_parameters(&item_segment.parameters, colons_before_params) } @@ -1589,7 +1588,7 @@ impl<'a> State<'a> { let start_or_comma = |this: &mut Self| { if empty.get() { empty.set(false); - word(&mut this.s, start) + this.s.word(start) } else { this.word_space(",") } @@ -1611,26 +1610,26 @@ impl<'a> State<'a> { // "non-exhaustive patterns: `Some::<..>(_)` not covered". if data.infer_types && false { start_or_comma(self)?; - word(&mut self.s, "..")?; + self.s.word("..")?; } for binding in data.bindings.iter() { start_or_comma(self)?; self.print_name(binding.name)?; - space(&mut self.s)?; + self.s.space()?; self.word_space("=")?; self.print_type(&binding.ty)?; } if !empty.get() { - word(&mut self.s, ">")? + self.s.word(">")? } } hir::ParenthesizedParameters(ref data) => { - word(&mut self.s, "(")?; + self.s.word("(")?; self.commasep(Inconsistent, &data.inputs, |s, ty| s.print_type(&ty))?; - word(&mut self.s, ")")?; + self.s.word(")")?; if let Some(ref ty) = data.output { self.space_if_not_bol()?; @@ -1649,7 +1648,7 @@ impl<'a> State<'a> { // Pat isn't normalized, but the beauty of it // is that it doesn't matter match pat.node { - PatKind::Wild => word(&mut self.s, "_")?, + PatKind::Wild => self.s.word("_")?, PatKind::Binding(binding_mode, _, ref path1, ref sub) => { match binding_mode { hir::BindByRef(mutbl) => { @@ -1663,7 +1662,7 @@ impl<'a> State<'a> { } self.print_name(path1.node)?; if let Some(ref p) = *sub { - word(&mut self.s, "@")?; + self.s.word("@")?; self.print_pat(&p)?; } } @@ -1675,9 +1674,9 @@ impl<'a> State<'a> { if ddpos != 0 { self.word_space(",")?; } - word(&mut self.s, "..")?; + self.s.word("..")?; if ddpos != elts.len() { - word(&mut self.s, ",")?; + self.s.word(",")?; self.commasep(Inconsistent, &elts[ddpos..], |s, p| s.print_pat(&p))?; } } else { @@ -1708,10 +1707,10 @@ impl<'a> State<'a> { if !fields.is_empty() { self.word_space(",")?; } - word(&mut self.s, "..")?; + self.s.word("..")?; } - space(&mut self.s)?; - word(&mut self.s, "}")?; + self.s.space()?; + self.s.word("}")?; } PatKind::Tuple(ref elts, ddpos) => { self.popen()?; @@ -1720,42 +1719,42 @@ impl<'a> State<'a> { if ddpos != 0 { self.word_space(",")?; } - word(&mut self.s, "..")?; + self.s.word("..")?; if ddpos != elts.len() { - word(&mut self.s, ",")?; + self.s.word(",")?; self.commasep(Inconsistent, &elts[ddpos..], |s, p| s.print_pat(&p))?; } } else { self.commasep(Inconsistent, &elts[..], |s, p| s.print_pat(&p))?; if elts.len() == 1 { - word(&mut self.s, ",")?; + self.s.word(",")?; } } self.pclose()?; } PatKind::Box(ref inner) => { - word(&mut self.s, "box ")?; + self.s.word("box ")?; self.print_pat(&inner)?; } PatKind::Ref(ref inner, mutbl) => { - word(&mut self.s, "&")?; + self.s.word("&")?; if mutbl == hir::MutMutable { - word(&mut self.s, "mut ")?; + self.s.word("mut ")?; } self.print_pat(&inner)?; } PatKind::Lit(ref e) => self.print_expr(&e)?, PatKind::Range(ref begin, ref end, ref end_kind) => { self.print_expr(&begin)?; - space(&mut self.s)?; + self.s.space()?; match *end_kind { - RangeEnd::Included => word(&mut self.s, "...")?, - RangeEnd::Excluded => word(&mut self.s, "..")?, + RangeEnd::Included => self.s.word("...")?, + RangeEnd::Excluded => self.s.word("..")?, } self.print_expr(&end)?; } PatKind::Slice(ref before, ref slice, ref after) => { - word(&mut self.s, "[")?; + self.s.word("[")?; self.commasep(Inconsistent, &before[..], |s, p| s.print_pat(&p))?; if let Some(ref p) = *slice { if !before.is_empty() { @@ -1764,13 +1763,13 @@ impl<'a> State<'a> { if p.node != PatKind::Wild { self.print_pat(&p)?; } - word(&mut self.s, "..")?; + self.s.word("..")?; if !after.is_empty() { self.word_space(",")?; } } self.commasep(Inconsistent, &after[..], |s, p| s.print_pat(&p))?; - word(&mut self.s, "]")?; + self.s.word("]")?; } } self.ann.post(self, NodePat(pat)) @@ -1780,7 +1779,7 @@ impl<'a> State<'a> { // I have no idea why this check is necessary, but here it // is :( if arm.attrs.is_empty() { - space(&mut self.s)?; + self.s.space()?; } self.cbox(indent_unit)?; self.ibox(0)?; @@ -1790,16 +1789,16 @@ impl<'a> State<'a> { if first { first = false; } else { - space(&mut self.s)?; + self.s.space()?; self.word_space("|")?; } self.print_pat(&p)?; } - space(&mut self.s)?; + self.s.space()?; if let Some(ref e) = arm.guard { self.word_space("if")?; self.print_expr(&e)?; - space(&mut self.s)?; + self.s.space()?; } self.word_space("=>")?; @@ -1810,13 +1809,13 @@ impl<'a> State<'a> { // If it is a user-provided unsafe block, print a comma after it if let hir::UnsafeBlock(hir::UserProvided) = blk.rules { - word(&mut self.s, ",")?; + self.s.word(",")?; } } _ => { self.end()?; // close the ibox for the pattern self.print_expr(&arm.body)?; - word(&mut self.s, ",")?; + self.s.word(",")?; } } self.end() // close enclosing cbox @@ -1848,20 +1847,20 @@ impl<'a> State<'a> { self.commasep(Inconsistent, &decl.inputs, |s, ty| { s.ibox(indent_unit)?; if let Some(name) = arg_names.get(i) { - word(&mut s.s, &name.node.as_str())?; - word(&mut s.s, ":")?; - space(&mut s.s)?; + s.s.word(&name.node.as_str())?; + s.s.word(":")?; + s.s.space()?; } else if let Some(body_id) = body_id { s.ann.nested(s, Nested::BodyArgPat(body_id, i))?; - word(&mut s.s, ":")?; - space(&mut s.s)?; + s.s.word(":")?; + s.s.space()?; } i += 1; s.print_type(ty)?; s.end() })?; if decl.variadic { - word(&mut self.s, ", ...")?; + self.s.word(", ...")?; } self.pclose()?; @@ -1870,7 +1869,7 @@ impl<'a> State<'a> { } fn print_closure_args(&mut self, decl: &hir::FnDecl, body_id: hir::BodyId) -> io::Result<()> { - word(&mut self.s, "|")?; + self.s.word("|")?; let mut i = 0; self.commasep(Inconsistent, &decl.inputs, |s, ty| { s.ibox(indent_unit)?; @@ -1879,13 +1878,13 @@ impl<'a> State<'a> { i += 1; if ty.node != hir::TyInfer { - word(&mut s.s, ":")?; - space(&mut s.s)?; + s.s.word(":")?; + s.s.space()?; s.print_type(ty)?; } s.end() })?; - word(&mut self.s, "|")?; + self.s.word("|")?; if let hir::DefaultReturn(..) = decl.output { return Ok(()); @@ -1911,7 +1910,7 @@ impl<'a> State<'a> { pub fn print_bounds(&mut self, prefix: &str, bounds: &[hir::TyParamBound]) -> io::Result<()> { if !bounds.is_empty() { - word(&mut self.s, prefix)?; + self.s.word(prefix)?; let mut first = true; for bound in bounds { self.nbsp()?; @@ -1926,7 +1925,7 @@ impl<'a> State<'a> { self.print_poly_trait_ref(tref) } TraitTyParamBound(ref tref, TraitBoundModifier::Maybe) => { - word(&mut self.s, "?")?; + self.s.word("?")?; self.print_poly_trait_ref(tref) } RegionTyParamBound(ref lt) => { @@ -1948,7 +1947,7 @@ impl<'a> State<'a> { self.print_lifetime(&lifetime.lifetime)?; let mut sep = ":"; for v in &lifetime.bounds { - word(&mut self.s, sep)?; + self.s.word(sep)?; self.print_lifetime(v)?; sep = "+"; } @@ -1961,7 +1960,7 @@ impl<'a> State<'a> { return Ok(()); } - word(&mut self.s, "<")?; + self.s.word("<")?; let mut ints = Vec::new(); for i in 0..total { @@ -1979,7 +1978,7 @@ impl<'a> State<'a> { } })?; - word(&mut self.s, ">")?; + self.s.word(">")?; Ok(()) } @@ -1988,7 +1987,7 @@ impl<'a> State<'a> { self.print_bounds(":", ¶m.bounds)?; match param.default { Some(ref default) => { - space(&mut self.s)?; + self.s.space()?; self.word_space("=")?; self.print_type(&default) } @@ -2001,7 +2000,7 @@ impl<'a> State<'a> { return Ok(()); } - space(&mut self.s)?; + self.s.space()?; self.word_space("where")?; for (i, predicate) in where_clause.predicates.iter().enumerate() { @@ -2022,13 +2021,13 @@ impl<'a> State<'a> { ref bounds, ..}) => { self.print_lifetime(lifetime)?; - word(&mut self.s, ":")?; + self.s.word(":")?; for (i, bound) in bounds.iter().enumerate() { self.print_lifetime(bound)?; if i != 0 { - word(&mut self.s, ":")?; + self.s.word(":")?; } } } @@ -2036,7 +2035,7 @@ impl<'a> State<'a> { ref rhs_ty, ..}) => { self.print_type(lhs_ty)?; - space(&mut self.s)?; + self.s.space()?; self.word_space("=")?; self.print_type(rhs_ty)?; } @@ -2087,7 +2086,7 @@ impl<'a> State<'a> { -> io::Result<()> { self.ibox(indent_unit)?; if !generics.lifetimes.is_empty() || !generics.ty_params.is_empty() { - word(&mut self.s, "for")?; + self.s.word("for")?; self.print_generics(generics)?; } let generics = hir::Generics { @@ -2132,7 +2131,6 @@ impl<'a> State<'a> { if span.hi < (*cmnt).pos && (*cmnt).pos < next && span_line.line == comment_line.line { self.print_comment(cmnt)?; - self.cur_cmnt_and_lit.cur_cmnt += 1; } } Ok(()) @@ -2142,13 +2140,12 @@ impl<'a> State<'a> { // If there aren't any remaining comments, then we need to manually // make sure there is a line break at the end. if self.next_comment().is_none() { - hardbreak(&mut self.s)?; + self.s.hardbreak()?; } loop { match self.next_comment() { Some(ref cmnt) => { self.print_comment(cmnt)?; - self.cur_cmnt_and_lit.cur_cmnt += 1; } _ => break, } @@ -2185,7 +2182,7 @@ impl<'a> State<'a> { abi: Abi, vis: &hir::Visibility) -> io::Result<()> { - word(&mut self.s, &visibility_qualified(vis, ""))?; + self.s.word(&visibility_qualified(vis, ""))?; self.print_unsafety(unsafety)?; match constness { @@ -2198,7 +2195,7 @@ impl<'a> State<'a> { self.word_nbsp(&abi.to_string())?; } - word(&mut self.s, "fn") + self.s.word("fn") } pub fn print_unsafety(&mut self, s: hir::Unsafety) -> io::Result<()> { diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs index c82fea197fb75..7805029a67ff7 100644 --- a/src/librustc/ich/impls_hir.rs +++ b/src/librustc/ich/impls_hir.rs @@ -895,25 +895,28 @@ impl<'a, 'gcx, 'tcx> HashStable> for hir::I fn hash_stable(&self, hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { - let node_id_hashing_mode = match self.node { - hir::ItemExternCrate(..) | + let (node_id_hashing_mode, hash_spans) = match self.node { hir::ItemStatic(..) | hir::ItemConst(..) | - hir::ItemFn(..) | - hir::ItemMod(..) | + hir::ItemFn(..) => { + (NodeIdHashingMode::Ignore, hcx.hash_spans()) + } + hir::ItemUse(..) => { + (NodeIdHashingMode::HashTraitsInScope, false) + } + + hir::ItemExternCrate(..) | hir::ItemForeignMod(..) | hir::ItemGlobalAsm(..) | + hir::ItemMod(..) | + hir::ItemDefaultImpl(..) | + hir::ItemTrait(..) | + hir::ItemImpl(..) | hir::ItemTy(..) | hir::ItemEnum(..) | hir::ItemStruct(..) | - hir::ItemUnion(..) | - hir::ItemTrait(..) | - hir::ItemDefaultImpl(..) | - hir::ItemImpl(..) => { - NodeIdHashingMode::Ignore - } - hir::ItemUse(..) => { - NodeIdHashingMode::HashTraitsInScope + hir::ItemUnion(..) => { + (NodeIdHashingMode::Ignore, false) } }; @@ -927,14 +930,16 @@ impl<'a, 'gcx, 'tcx> HashStable> for hir::I } = *self; hcx.hash_hir_item_like(attrs, |hcx| { - hcx.with_node_id_hashing_mode(node_id_hashing_mode, |hcx| { - id.hash_stable(hcx, hasher); + hcx.while_hashing_spans(hash_spans, |hcx| { + hcx.with_node_id_hashing_mode(node_id_hashing_mode, |hcx| { + id.hash_stable(hcx, hasher); + }); + name.hash_stable(hcx, hasher); + attrs.hash_stable(hcx, hasher); + node.hash_stable(hcx, hasher); + vis.hash_stable(hcx, hasher); + span.hash_stable(hcx, hasher); }); - name.hash_stable(hcx, hasher); - attrs.hash_stable(hcx, hasher); - node.hash_stable(hcx, hasher); - vis.hash_stable(hcx, hasher); - span.hash_stable(hcx, hasher); }); } } diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs index 4f365a97f4ceb..3e227872848ef 100644 --- a/src/librustc/ich/impls_ty.rs +++ b/src/librustc/ich/impls_ty.rs @@ -187,7 +187,7 @@ for ty::OutlivesPredicate } impl_stable_hash_for!(struct ty::ProjectionPredicate<'tcx> { projection_ty, ty }); -impl_stable_hash_for!(struct ty::ProjectionTy<'tcx> { trait_ref, item_def_id }); +impl_stable_hash_for!(struct ty::ProjectionTy<'tcx> { substs, item_def_id }); impl<'a, 'gcx, 'tcx> HashStable> for ty::Predicate<'tcx> { @@ -346,6 +346,7 @@ impl<'a, 'gcx, 'tcx> HashStable> for ty::Ge // `def_id.index` (`def_id.krate` is the same as the item's). type_param_to_index: _, // Don't hash this has_self, + has_late_bound_regions, } = *self; parent.hash_stable(hcx, hasher); @@ -354,6 +355,7 @@ impl<'a, 'gcx, 'tcx> HashStable> for ty::Ge regions.hash_stable(hcx, hasher); types.hash_stable(hcx, hasher); has_self.hash_stable(hcx, hasher); + has_late_bound_regions.hash_stable(hcx, hasher); } } @@ -599,8 +601,8 @@ impl_stable_hash_for!(struct ty::ExistentialTraitRef<'tcx> { }); impl_stable_hash_for!(struct ty::ExistentialProjection<'tcx> { - trait_ref, - item_name, + item_def_id, + substs, ty }); @@ -661,3 +663,60 @@ for ty::TypeckTables<'tcx> { }) } } + +impl_stable_hash_for!(enum ty::fast_reject::SimplifiedType { + BoolSimplifiedType, + CharSimplifiedType, + IntSimplifiedType(int_ty), + UintSimplifiedType(int_ty), + FloatSimplifiedType(float_ty), + AdtSimplifiedType(def_id), + StrSimplifiedType, + ArraySimplifiedType, + PtrSimplifiedType, + NeverSimplifiedType, + TupleSimplifiedType(size), + TraitSimplifiedType(def_id), + ClosureSimplifiedType(def_id), + AnonSimplifiedType(def_id), + FunctionSimplifiedType(params), + ParameterSimplifiedType +}); + +impl_stable_hash_for!(struct ty::Instance<'tcx> { + def, + substs +}); + +impl<'a, 'gcx, 'tcx> HashStable> for ty::InstanceDef<'tcx> { + fn hash_stable(&self, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, + hasher: &mut StableHasher) { + mem::discriminant(self).hash_stable(hcx, hasher); + + match *self { + ty::InstanceDef::Item(def_id) => { + def_id.hash_stable(hcx, hasher); + } + ty::InstanceDef::Intrinsic(def_id) => { + def_id.hash_stable(hcx, hasher); + } + ty::InstanceDef::FnPtrShim(def_id, ty) => { + def_id.hash_stable(hcx, hasher); + ty.hash_stable(hcx, hasher); + } + ty::InstanceDef::Virtual(def_id, n) => { + def_id.hash_stable(hcx, hasher); + n.hash_stable(hcx, hasher); + } + ty::InstanceDef::ClosureOnceShim { call_once } => { + call_once.hash_stable(hcx, hasher); + } + ty::InstanceDef::DropGlue(def_id, t) => { + def_id.hash_stable(hcx, hasher); + t.hash_stable(hcx, hasher); + } + } + } +} + diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index 82bbb4a1bf515..95722a93beda1 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -72,12 +72,12 @@ use ty::error::TypeError; use syntax::ast::DUMMY_NODE_ID; use syntax_pos::{Pos, Span}; use errors::{DiagnosticBuilder, DiagnosticStyledString}; + mod note; mod need_type_info; mod named_anon_conflict; - impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { pub fn note_and_explain_region(self, err: &mut DiagnosticBuilder, @@ -265,40 +265,34 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // together into a `ProcessedErrors` group: let errors = self.process_errors(errors); - debug!("report_region_errors: {} errors after preprocessing", - errors.len()); + debug!("report_region_errors: {} errors after preprocessing", errors.len()); for error in errors { - debug!("report_region_errors: error = {:?}", error); - if !self.try_report_named_anon_conflict(&error){ - - match error.clone() { - // These errors could indicate all manner of different - // problems with many different solutions. Rather - // than generate a "one size fits all" error, what we - // attempt to do is go through a number of specific - // scenarios and try to find the best way to present - // the error. If all of these fails, we fall back to a rather - // general bit of code that displays the error information - ConcreteFailure(origin, sub, sup) => { - - self.report_concrete_failure(origin, sub, sup).emit(); - } - - GenericBoundFailure(kind, param_ty, sub) => { - self.report_generic_bound_failure(kind, param_ty, sub); - } - - SubSupConflict(var_origin, - sub_origin, sub_r, - sup_origin, sup_r) => { - self.report_sub_sup_conflict(var_origin, - sub_origin, sub_r, - sup_origin, sup_r); - } - } + if !self.try_report_named_anon_conflict(&error) { + match error.clone() { + // These errors could indicate all manner of different + // problems with many different solutions. Rather + // than generate a "one size fits all" error, what we + // attempt to do is go through a number of specific + // scenarios and try to find the best way to present + // the error. If all of these fails, we fall back to a rather + // general bit of code that displays the error information + ConcreteFailure(origin, sub, sup) => { + self.report_concrete_failure(origin, sub, sup).emit(); + } + GenericBoundFailure(kind, param_ty, sub) => { + self.report_generic_bound_failure(kind, param_ty, sub); + } + SubSupConflict(var_origin, + sub_origin, sub_r, + sup_origin, sup_r) => { + self.report_sub_sup_conflict(var_origin, + sub_origin, sub_r, + sup_origin, sup_r); + } + } } } } @@ -353,9 +347,12 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { if !(did1.is_local() || did2.is_local()) && did1.krate != did2.krate { let exp_path = self.tcx.item_path_str(did1); let found_path = self.tcx.item_path_str(did2); + let exp_abs_path = self.tcx.absolute_item_path_str(did1); + let found_abs_path = self.tcx.absolute_item_path_str(did2); // We compare strings because DefPath can be different // for imported and non-imported crates - if exp_path == found_path { + if exp_path == found_path + || exp_abs_path == found_abs_path { let crate_name = self.tcx.sess.cstore.crate_name(did1.krate); err.span_note(sp, &format!("Perhaps two different versions \ of crate `{}` are being used?", diff --git a/src/librustc/infer/error_reporting/named_anon_conflict.rs b/src/librustc/infer/error_reporting/named_anon_conflict.rs index ccbc5cdb862f9..48f39ac5b3e56 100644 --- a/src/librustc/infer/error_reporting/named_anon_conflict.rs +++ b/src/librustc/infer/error_reporting/named_anon_conflict.rs @@ -37,7 +37,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { match *anon_region { ty::ReFree(ref free_region) => { - let id = free_region.scope; let node_id = self.tcx.hir.as_local_node_id(id).unwrap(); let body_id = self.tcx.hir.maybe_body_owned_by(node_id).unwrap(); @@ -69,7 +68,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } } _ => None, - } } @@ -77,7 +75,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // the function arguments consist of a named region and an anonymous // region and corresponds to `ConcreteFailure(..)` pub fn try_report_named_anon_conflict(&self, error: &RegionResolutionError<'tcx>) -> bool { - let (span, sub, sup) = match *error { ConcreteFailure(ref origin, sub, sup) => (origin.span(), sub, sup), _ => return false, // inapplicable @@ -113,7 +110,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { .collect_referenced_late_bound_regions(&sig.output()); if late_bound_regions.iter().any(|r| *r == br) { return false; - } else { } } _ => {} @@ -134,10 +130,9 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { let (error_var, span_label_var) = if let Some(simple_name) = arg.pat.simple_name() { (format!("the type of `{}`", simple_name), format!("the type of `{}`", simple_name)) } else { - (format!("parameter type"), format!("type")) + ("parameter type".to_owned(), "type".to_owned()) }; - struct_span_err!(self.tcx.sess, span, E0621, @@ -149,13 +144,11 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { .emit(); return true; - } // This method returns whether the given Region is Anonymous // and returns the DefId corresponding to the region. pub fn is_suitable_anonymous_region(&self, region: Region<'tcx>) -> Option { - match *region { ty::ReFree(ref free_region) => { match free_region.bound_region { diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index a70a4248cb75b..7154ce9e38f5e 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -38,6 +38,7 @@ use errors::DiagnosticBuilder; use syntax_pos::{self, Span, DUMMY_SP}; use util::nodemap::FxHashMap; use arena::DroplessArena; + use self::combine::CombineFields; use self::higher_ranked::HrMatchResult; use self::region_inference::{RegionVarBindings, RegionSnapshot}; @@ -273,7 +274,7 @@ pub enum LateBoundRegionConversionTime { HigherRankedType, /// when projecting an associated type - AssocTypeProjection(ast::Name), + AssocTypeProjection(ast::Name), // FIXME(tschottdorf): should contain DefId, not Name } /// Reasons to create a region inference variable @@ -1276,14 +1277,13 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { match_b: ty::TraitRef<'tcx>) -> InferResult<'tcx, HrMatchResult>> { + let match_pair = match_a.map_bound(|p| (p.projection_ty.trait_ref(self.tcx), p.ty)); let span = cause.span; - let match_trait_ref = match_a.skip_binder().projection_ty.trait_ref; let trace = TypeTrace { cause, - values: TraitRefs(ExpectedFound::new(true, match_trait_ref, match_b)) + values: TraitRefs(ExpectedFound::new(true, match_pair.skip_binder().0, match_b)) }; - let match_pair = match_a.map_bound(|p| (p.projection_ty.trait_ref, p.ty)); let mut combine = self.combine_fields(trace, param_env); let result = combine.higher_ranked_match(span, &match_pair, &match_b, true)?; Ok(InferOk { value: result, obligations: combine.obligations }) diff --git a/src/librustc/infer/region_inference/mod.rs b/src/librustc/infer/region_inference/mod.rs index 4f8168982496e..57f2f748b246e 100644 --- a/src/librustc/infer/region_inference/mod.rs +++ b/src/librustc/infer/region_inference/mod.rs @@ -1550,8 +1550,7 @@ impl<'a, 'gcx, 'tcx> GenericKind<'tcx> { pub fn to_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx> { match *self { GenericKind::Param(ref p) => p.to_ty(tcx), - GenericKind::Projection(ref p) => tcx.mk_projection( - p.trait_ref.clone(), p.item_name(tcx)), + GenericKind::Projection(ref p) => tcx.mk_projection(p.item_def_id, p.substs), } } } diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index 2d088c4f6d172..cbe642a9a76a6 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -204,6 +204,12 @@ declare_lint! { "detects parenthesized generic parameters in type and module names" } +declare_lint! { + pub LATE_BOUND_LIFETIME_ARGUMENTS, + Warn, + "detects generic lifetime arguments in path segments with late bound lifetime parameters" +} + declare_lint! { pub DEPRECATED, Warn, @@ -249,6 +255,7 @@ impl LintPass for HardwiredLints { LEGACY_CONSTRUCTOR_VISIBILITY, MISSING_FRAGMENT_SPECIFIER, PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES, + LATE_BOUND_LIFETIME_ARGUMENTS, DEPRECATED ) } diff --git a/src/librustc/middle/dataflow.rs b/src/librustc/middle/dataflow.rs index 42f4c5c59d994..f6be709009177 100644 --- a/src/librustc/middle/dataflow.rs +++ b/src/librustc/middle/dataflow.rs @@ -21,7 +21,6 @@ use std::io; use std::mem; use std::usize; use syntax::ast; -use syntax::print::pp; use syntax::print::pprust::PrintState; use util::nodemap::NodeMap; use hir; @@ -157,7 +156,7 @@ impl<'a, 'tcx, O:DataFlowOperator> pprust::PpAnn for DataFlowContext<'a, 'tcx, O ps.synth_comment( format!("id {}: {}{}{}{}", id, entry_str, gens_str, action_kills_str, scope_kills_str))?; - pp::space(&mut ps.s)?; + ps.s.space()?; } Ok(()) } diff --git a/src/librustc/middle/dependency_format.rs b/src/librustc/middle/dependency_format.rs index 9af93d0d49424..837ab4fd4a3cc 100644 --- a/src/librustc/middle/dependency_format.rs +++ b/src/librustc/middle/dependency_format.rs @@ -396,7 +396,8 @@ fn verify_ok<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, list: &[Linkage]) { } let cnum = CrateNum::new(i + 1); let found_strategy = sess.cstore.panic_strategy(cnum); - if desired_strategy == found_strategy { + let is_compiler_builtins = sess.cstore.is_compiler_builtins(cnum); + if is_compiler_builtins || desired_strategy == found_strategy { continue } diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 96ccc3ba50078..d176ae761e181 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -66,6 +66,25 @@ macro_rules! newtype_index { ) } +/// Types for locals +type LocalDecls<'tcx> = IndexVec>; + +pub trait HasLocalDecls<'tcx> { + fn local_decls(&self) -> &LocalDecls<'tcx>; +} + +impl<'tcx> HasLocalDecls<'tcx> for LocalDecls<'tcx> { + fn local_decls(&self) -> &LocalDecls<'tcx> { + self + } +} + +impl<'tcx> HasLocalDecls<'tcx> for Mir<'tcx> { + fn local_decls(&self) -> &LocalDecls<'tcx> { + &self.local_decls + } +} + /// Lowered representation of a single function. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct Mir<'tcx> { @@ -90,7 +109,7 @@ pub struct Mir<'tcx> { /// The first local is the return value pointer, followed by `arg_count` /// locals for the function arguments, followed by any user-declared /// variables and temporaries. - pub local_decls: IndexVec>, + pub local_decls: LocalDecls<'tcx>, /// Number of arguments this function takes. /// diff --git a/src/librustc/mir/tcx.rs b/src/librustc/mir/tcx.rs index 71acb36ecf75d..1af80771fb952 100644 --- a/src/librustc/mir/tcx.rs +++ b/src/librustc/mir/tcx.rs @@ -121,31 +121,34 @@ impl<'tcx> TypeFoldable<'tcx> for LvalueTy<'tcx> { } impl<'tcx> Lvalue<'tcx> { - pub fn ty<'a, 'gcx>(&self, mir: &Mir<'tcx>, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> LvalueTy<'tcx> { + pub fn ty<'a, 'gcx, D>(&self, local_decls: &D, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> LvalueTy<'tcx> + where D: HasLocalDecls<'tcx> + { match *self { Lvalue::Local(index) => - LvalueTy::Ty { ty: mir.local_decls[index].ty }, + LvalueTy::Ty { ty: local_decls.local_decls()[index].ty }, Lvalue::Static(ref data) => LvalueTy::Ty { ty: data.ty }, Lvalue::Projection(ref proj) => - proj.base.ty(mir, tcx).projection_ty(tcx, &proj.elem), + proj.base.ty(local_decls, tcx).projection_ty(tcx, &proj.elem), } } } impl<'tcx> Rvalue<'tcx> { - pub fn ty<'a, 'gcx>(&self, mir: &Mir<'tcx>, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx> + pub fn ty<'a, 'gcx, D>(&self, local_decls: &D, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx> + where D: HasLocalDecls<'tcx> { match *self { - Rvalue::Use(ref operand) => operand.ty(mir, tcx), + Rvalue::Use(ref operand) => operand.ty(local_decls, tcx), Rvalue::Repeat(ref operand, ref count) => { - let op_ty = operand.ty(mir, tcx); + let op_ty = operand.ty(local_decls, tcx); let count = count.as_u64(tcx.sess.target.uint_type); assert_eq!(count as usize as u64, count); tcx.mk_array(op_ty, count as usize) } Rvalue::Ref(reg, bk, ref lv) => { - let lv_ty = lv.ty(mir, tcx).to_ty(tcx); + let lv_ty = lv.ty(local_decls, tcx).to_ty(tcx); tcx.mk_ref(reg, ty::TypeAndMut { ty: lv_ty, @@ -156,22 +159,22 @@ impl<'tcx> Rvalue<'tcx> { Rvalue::Len(..) => tcx.types.usize, Rvalue::Cast(.., ty) => ty, Rvalue::BinaryOp(op, ref lhs, ref rhs) => { - let lhs_ty = lhs.ty(mir, tcx); - let rhs_ty = rhs.ty(mir, tcx); + let lhs_ty = lhs.ty(local_decls, tcx); + let rhs_ty = rhs.ty(local_decls, tcx); op.ty(tcx, lhs_ty, rhs_ty) } Rvalue::CheckedBinaryOp(op, ref lhs, ref rhs) => { - let lhs_ty = lhs.ty(mir, tcx); - let rhs_ty = rhs.ty(mir, tcx); + let lhs_ty = lhs.ty(local_decls, tcx); + let rhs_ty = rhs.ty(local_decls, tcx); let ty = op.ty(tcx, lhs_ty, rhs_ty); tcx.intern_tup(&[ty, tcx.types.bool], false) } Rvalue::UnaryOp(UnOp::Not, ref operand) | Rvalue::UnaryOp(UnOp::Neg, ref operand) => { - operand.ty(mir, tcx) + operand.ty(local_decls, tcx) } Rvalue::Discriminant(ref lval) => { - let ty = lval.ty(mir, tcx).to_ty(tcx); + let ty = lval.ty(local_decls, tcx).to_ty(tcx); if let ty::TyAdt(adt_def, _) = ty.sty { adt_def.repr.discr_type().to_ty(tcx) } else { @@ -189,7 +192,7 @@ impl<'tcx> Rvalue<'tcx> { } AggregateKind::Tuple => { tcx.mk_tup( - ops.iter().map(|op| op.ty(mir, tcx)), + ops.iter().map(|op| op.ty(local_decls, tcx)), false ) } @@ -206,9 +209,11 @@ impl<'tcx> Rvalue<'tcx> { } impl<'tcx> Operand<'tcx> { - pub fn ty<'a, 'gcx>(&self, mir: &Mir<'tcx>, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx> { + pub fn ty<'a, 'gcx, D>(&self, local_decls: &D, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx> + where D: HasLocalDecls<'tcx> + { match self { - &Operand::Consume(ref l) => l.ty(mir, tcx).to_ty(tcx), + &Operand::Consume(ref l) => l.ty(local_decls, tcx).to_ty(tcx), &Operand::Constant(ref c) => c.ty, } } diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 240f000a424c0..167249f29ba85 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -489,6 +489,12 @@ impl Options { self.debugging_opts.query_dep_graph } + #[inline(always)] + pub fn enable_dep_node_debug_strs(&self) -> bool { + cfg!(debug_assertions) && + (self.debugging_opts.query_dep_graph || self.debugging_opts.incremental_info) + } + pub fn single_codegen_unit(&self) -> bool { self.incremental.is_none() || self.cg.codegen_units == 1 @@ -975,6 +981,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, "dump the dependency graph to $RUST_DEP_GRAPH (default: /tmp/dep_graph.gv)"), query_dep_graph: bool = (false, parse_bool, [UNTRACKED], "enable queries of the dependency graph for regression testing"), + profile_queries: bool = (false, parse_bool, [UNTRACKED], + "trace and profile the queries of the incremental compilation framework"), no_analysis: bool = (false, parse_bool, [UNTRACKED], "parse and expand the source, but run no analysis"), extra_plugins: Vec = (Vec::new(), parse_list, [TRACKED], @@ -2515,6 +2523,8 @@ mod tests { assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); opts.debugging_opts.query_dep_graph = true; assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); + opts.debugging_opts.profile_queries = true; + assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); opts.debugging_opts.no_analysis = true; assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); opts.debugging_opts.unstable_options = true; diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index fe6b24f3e1f2a..4b41edd483a22 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -396,6 +396,7 @@ impl Session { } pub fn verbose(&self) -> bool { self.opts.debugging_opts.verbose } pub fn time_passes(&self) -> bool { self.opts.debugging_opts.time_passes } + pub fn profile_queries(&self) -> bool { self.opts.debugging_opts.profile_queries } pub fn count_llvm_insns(&self) -> bool { self.opts.debugging_opts.count_llvm_insns } diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 0bf0e21baaf93..c02d1394f6bb5 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -330,6 +330,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { .filter(|a| a.check_name("rustc_on_unimplemented")) .next() { + let name = self.tcx.item_name(def_id).as_str(); let err_sp = item.span.substitute_dummy(span); let trait_str = self.tcx.item_path_str(trait_ref.def_id); if let Some(istring) = item.value_str() { @@ -347,6 +348,9 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { Piece::NextArgument(a) => match a.position { Position::ArgumentNamed(s) => match generic_map.get(s) { Some(val) => Some(val), + None if s == name => { + Some(&trait_str) + } None => { span_err!(self.tcx.sess, err_sp, E0272, "the #[rustc_on_unimplemented] attribute on trait \ diff --git a/src/librustc/traits/fulfill.rs b/src/librustc/traits/fulfill.rs index 826d4a2815838..4f1eb6169209b 100644 --- a/src/librustc/traits/fulfill.rs +++ b/src/librustc/traits/fulfill.rs @@ -470,8 +470,9 @@ fn process_predicate<'a, 'gcx, 'tcx>( let project_obligation = obligation.with(data.clone()); match project::poly_project_and_unify_type(selcx, &project_obligation) { Ok(None) => { + let tcx = selcx.tcx(); pending_obligation.stalled_on = - trait_ref_type_vars(selcx, data.to_poly_trait_ref()); + trait_ref_type_vars(selcx, data.to_poly_trait_ref(tcx)); Ok(None) } Ok(v) => Ok(v), diff --git a/src/librustc/traits/object_safety.rs b/src/librustc/traits/object_safety.rs index c6c052fa4b1bc..9c04c013c4b1a 100644 --- a/src/librustc/traits/object_safety.rs +++ b/src/librustc/traits/object_safety.rs @@ -354,7 +354,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // direct equality here because all of these types // are part of the formal parameter listing, and // hence there should be no inference variables. - let projection_trait_ref = ty::Binder(data.trait_ref.clone()); + let projection_trait_ref = ty::Binder(data.trait_ref(self)); let is_supertrait_of_current_trait = supertraits.as_ref().unwrap().contains(&projection_trait_ref); diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs index 14b6d4605e89f..b5284852747f9 100644 --- a/src/librustc/traits/project.rs +++ b/src/librustc/traits/project.rs @@ -365,9 +365,7 @@ pub fn normalize_projection_type<'a, 'b, 'gcx, 'tcx>( // information is available. let tcx = selcx.infcx().tcx; - let def_id = tcx.associated_items(projection_ty.trait_ref.def_id).find(|i| - i.name == projection_ty.item_name(tcx) && i.kind == ty::AssociatedKind::Type - ).map(|i| i.def_id).unwrap(); + let def_id = projection_ty.item_def_id; let ty_var = selcx.infcx().next_ty_var( TypeVariableOrigin::NormalizeProjectionType(tcx.def_span(def_id))); let projection = ty::Binder(ty::ProjectionPredicate { @@ -447,8 +445,8 @@ fn opt_normalize_projection_type<'a, 'b, 'gcx, 'tcx>( // normalization. In that case, I think we will want this code: // // ``` - // let ty = selcx.tcx().mk_projection(projection_ty.trait_ref, - // projection_ty.item_name(tcx); + // let ty = selcx.tcx().mk_projection(projection_ty.item_def_id, + // projection_ty.substs; // return Some(NormalizedTy { value: v, obligations: vec![] }); // ``` @@ -585,15 +583,13 @@ fn normalize_to_error<'a, 'gcx, 'tcx>(selcx: &mut SelectionContext<'a, 'gcx, 'tc depth: usize) -> NormalizedTy<'tcx> { - let trait_ref = projection_ty.trait_ref.to_poly_trait_ref(); + let trait_ref = projection_ty.trait_ref(selcx.tcx()).to_poly_trait_ref(); let trait_obligation = Obligation { cause, recursion_depth: depth, param_env, predicate: trait_ref.to_predicate() }; let tcx = selcx.infcx().tcx; - let def_id = tcx.associated_items(projection_ty.trait_ref.def_id).find(|i| - i.name == projection_ty.item_name(tcx) && i.kind == ty::AssociatedKind::Type - ).map(|i| i.def_id).unwrap(); + let def_id = projection_ty.item_def_id; let new_value = selcx.infcx().next_ty_var( TypeVariableOrigin::NormalizeProjectionType(tcx.def_span(def_id))); Normalized { @@ -654,7 +650,7 @@ fn project_type<'cx, 'gcx, 'tcx>( selcx.infcx().report_overflow_error(&obligation, true); } - let obligation_trait_ref = &obligation.predicate.trait_ref; + let obligation_trait_ref = &obligation.predicate.trait_ref(selcx.tcx()); debug!("project: obligation_trait_ref={:?}", obligation_trait_ref); @@ -743,12 +739,10 @@ fn project_type<'cx, 'gcx, 'tcx>( &obligation_trait_ref, candidate))) } - None => { - Ok(ProjectedTy::NoProgress( - selcx.tcx().mk_projection( - obligation.predicate.trait_ref.clone(), - obligation.predicate.item_name(selcx.tcx())))) - } + None => Ok(ProjectedTy::NoProgress( + selcx.tcx().mk_projection( + obligation.predicate.item_def_id, + obligation.predicate.substs))) } } @@ -788,10 +782,11 @@ fn assemble_candidates_from_trait_def<'cx, 'gcx, 'tcx>( { debug!("assemble_candidates_from_trait_def(..)"); + let tcx = selcx.tcx(); // Check whether the self-type is itself a projection. let (def_id, substs) = match obligation_trait_ref.self_ty().sty { ty::TyProjection(ref data) => { - (data.trait_ref.def_id, data.trait_ref.substs) + (data.trait_ref(tcx).def_id, data.substs) } ty::TyAnon(def_id, substs) => (def_id, substs), ty::TyInfer(ty::TyVar(_)) => { @@ -804,9 +799,9 @@ fn assemble_candidates_from_trait_def<'cx, 'gcx, 'tcx>( }; // If so, extract what we know from the trait and try to come up with a good answer. - let trait_predicates = selcx.tcx().predicates_of(def_id); - let bounds = trait_predicates.instantiate(selcx.tcx(), substs); - let bounds = elaborate_predicates(selcx.tcx(), bounds.predicates); + let trait_predicates = tcx.predicates_of(def_id); + let bounds = trait_predicates.instantiate(tcx, substs); + let bounds = elaborate_predicates(tcx, bounds.predicates); assemble_candidates_from_predicates(selcx, obligation, obligation_trait_ref, @@ -832,12 +827,12 @@ fn assemble_candidates_from_predicates<'cx, 'gcx, 'tcx, I>( predicate); match predicate { ty::Predicate::Projection(ref data) => { - let tcx = selcx.tcx(); - let same_name = data.item_name(tcx) == obligation.predicate.item_name(tcx); + let same_def_id = + data.0.projection_ty.item_def_id == obligation.predicate.item_def_id; - let is_match = same_name && infcx.probe(|_| { + let is_match = same_def_id && infcx.probe(|_| { let data_poly_trait_ref = - data.to_poly_trait_ref(); + data.to_poly_trait_ref(infcx.tcx); let obligation_poly_trait_ref = obligation_trait_ref.to_poly_trait_ref(); infcx.at(&obligation.cause, obligation.param_env) @@ -850,8 +845,8 @@ fn assemble_candidates_from_predicates<'cx, 'gcx, 'tcx, I>( }); debug!("assemble_candidates_from_predicates: candidate={:?} \ - is_match={} same_name={}", - data, is_match, same_name); + is_match={} same_def_id={}", + data, is_match, same_def_id); if is_match { candidate_set.vec.push(ctor(data.clone())); @@ -916,9 +911,10 @@ fn assemble_candidates_from_impls<'cx, 'gcx, 'tcx>( // In either case, we handle this by not adding a // candidate for an impl if it contains a `default` // type. + let item_name = selcx.tcx().associated_item(obligation.predicate.item_def_id).name; let node_item = assoc_ty_def(selcx, impl_data.impl_def_id, - obligation.predicate.item_name(selcx.tcx())); + item_name); let is_default = if node_item.node.is_from_trait() { // If true, the impl inherited a `type Foo = Bar` @@ -1091,10 +1087,9 @@ fn confirm_object_candidate<'cx, 'gcx, 'tcx>( // select only those projections that are actually projecting an // item with the correct name - let tcx = selcx.tcx(); let env_predicates = env_predicates.filter_map(|p| match p { ty::Predicate::Projection(data) => - if data.item_name(tcx) == obligation.predicate.item_name(tcx) { + if data.0.projection_ty.item_def_id == obligation.predicate.item_def_id { Some(data) } else { None @@ -1104,7 +1099,7 @@ fn confirm_object_candidate<'cx, 'gcx, 'tcx>( // select those with a relevant trait-ref let mut env_predicates = env_predicates.filter(|data| { - let data_poly_trait_ref = data.to_poly_trait_ref(); + let data_poly_trait_ref = data.to_poly_trait_ref(selcx.tcx()); let obligation_poly_trait_ref = obligation_trait_ref.to_poly_trait_ref(); selcx.infcx().probe(|_| { selcx.infcx().at(&obligation.cause, obligation.param_env) @@ -1202,7 +1197,7 @@ fn confirm_callable_candidate<'cx, 'gcx, 'tcx>( // Note: we unwrap the binder here but re-create it below (1) let ty::Binder((trait_ref, ret_type)) = tcx.closure_trait_ref_and_return_type(fn_once_def_id, - obligation.predicate.trait_ref.self_ty(), + obligation.predicate.self_ty(), fn_sig, flag); @@ -1227,7 +1222,7 @@ fn confirm_param_env_candidate<'cx, 'gcx, 'tcx>( let infcx = selcx.infcx(); let cause = obligation.cause.clone(); let param_env = obligation.param_env; - let trait_ref = obligation.predicate.trait_ref; + let trait_ref = obligation.predicate.trait_ref(infcx.tcx); match infcx.match_poly_projection_predicate(cause, param_env, poly_projection, trait_ref) { Ok(InferOk { value: ty_match, obligations }) => { Progress { @@ -1258,7 +1253,8 @@ fn confirm_impl_candidate<'cx, 'gcx, 'tcx>( let tcx = selcx.tcx(); let param_env = obligation.param_env; - let assoc_ty = assoc_ty_def(selcx, impl_def_id, obligation.predicate.item_name(tcx)); + let assoc_ty = assoc_ty_def(selcx, impl_def_id, + tcx.associated_item(obligation.predicate.item_def_id).name); let ty = if !assoc_ty.item.defaultness.has_value() { // This means that the impl is missing a definition for the @@ -1267,7 +1263,7 @@ fn confirm_impl_candidate<'cx, 'gcx, 'tcx>( // just return TyError. debug!("confirm_impl_candidate: no associated type {:?} for {:?}", assoc_ty.item.name, - obligation.predicate.trait_ref); + obligation.predicate); tcx.types.err } else { tcx.type_of(assoc_ty.item.def_id) diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 452ad43cd699f..c690bebed8c00 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -30,6 +30,7 @@ use super::{VtableImplData, VtableObjectData, VtableBuiltinData, VtableClosureData, VtableDefaultImplData, VtableFnPointerData}; use super::util; +use dep_graph::{DepNodeIndex, DepKind}; use hir::def_id::DefId; use infer; use infer::{InferCtxt, InferOk, TypeFreshener}; @@ -105,7 +106,7 @@ struct TraitObligationStack<'prev, 'tcx: 'prev> { #[derive(Clone)] pub struct SelectionCache<'tcx> { hashmap: RefCell, - SelectionResult<'tcx, SelectionCandidate<'tcx>>>>, + WithDepNode>>>>, } /// The selection process begins by considering all impls, where @@ -369,7 +370,7 @@ impl EvaluationResult { #[derive(Clone)] pub struct EvaluationCache<'tcx> { - hashmap: RefCell, EvaluationResult>> + hashmap: RefCell, WithDepNode>> } impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { @@ -466,8 +467,6 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { assert!(!obligation.predicate.has_escaping_regions()); let tcx = self.tcx(); - let dep_node = obligation.predicate.dep_node(tcx); - let _task = tcx.dep_graph.in_task(dep_node); let stack = self.push_stack(TraitObligationStackList::empty(), obligation); let ret = match self.candidate_from_obligation(&stack)? { @@ -710,12 +709,12 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { return result; } - let result = self.evaluate_stack(&stack); + let (result, dep_node) = self.in_task(|this| this.evaluate_stack(&stack)); debug!("CACHE MISS: EVAL({:?})={:?}", fresh_trait_ref, result); - self.insert_evaluation_cache(obligation.param_env, fresh_trait_ref, result); + self.insert_evaluation_cache(obligation.param_env, fresh_trait_ref, dep_node, result); result } @@ -870,22 +869,23 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { trait_ref: ty::PolyTraitRef<'tcx>) -> Option { + let tcx = self.tcx(); if self.can_use_global_caches(param_env) { - let cache = self.tcx().evaluation_cache.hashmap.borrow(); + let cache = tcx.evaluation_cache.hashmap.borrow(); if let Some(cached) = cache.get(&trait_ref) { - let dep_node = trait_ref - .to_poly_trait_predicate() - .dep_node(self.tcx()); - self.tcx().hir.dep_graph.read(dep_node); - return Some(cached.clone()); + return Some(cached.get(tcx)); } } - self.infcx.evaluation_cache.hashmap.borrow().get(&trait_ref).cloned() + self.infcx.evaluation_cache.hashmap + .borrow() + .get(&trait_ref) + .map(|v| v.get(tcx)) } fn insert_evaluation_cache(&mut self, param_env: ty::ParamEnv<'tcx>, trait_ref: ty::PolyTraitRef<'tcx>, + dep_node: DepNodeIndex, result: EvaluationResult) { // Avoid caching results that depend on more than just the trait-ref: @@ -902,12 +902,14 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { if self.can_use_global_caches(param_env) { let mut cache = self.tcx().evaluation_cache.hashmap.borrow_mut(); if let Some(trait_ref) = self.tcx().lift_to_global(&trait_ref) { - cache.insert(trait_ref, result); + cache.insert(trait_ref, WithDepNode::new(dep_node, result)); return; } } - self.infcx.evaluation_cache.hashmap.borrow_mut().insert(trait_ref, result); + self.infcx.evaluation_cache.hashmap + .borrow_mut() + .insert(trait_ref, WithDepNode::new(dep_node, result)); } /////////////////////////////////////////////////////////////////////////// @@ -949,19 +951,32 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { } // If no match, compute result and insert into cache. - let candidate = self.candidate_from_obligation_no_cache(stack); + let (candidate, dep_node) = self.in_task(|this| { + this.candidate_from_obligation_no_cache(stack) + }); if self.should_update_candidate_cache(&cache_fresh_trait_pred, &candidate) { debug!("CACHE MISS: SELECT({:?})={:?}", cache_fresh_trait_pred, candidate); self.insert_candidate_cache(stack.obligation.param_env, cache_fresh_trait_pred, + dep_node, candidate.clone()); } candidate } + fn in_task(&mut self, op: OP) -> (R, DepNodeIndex) + where OP: FnOnce(&mut Self) -> R + { + let (result, dep_node) = self.tcx().dep_graph.with_anon_task(DepKind::TraitSelect, || { + op(self) + }); + self.tcx().dep_graph.read_index(dep_node); + (result, dep_node) + } + // Treat negative impls as unimplemented fn filter_negative_impls(&self, candidate: SelectionCandidate<'tcx>) -> SelectionResult<'tcx, SelectionCandidate<'tcx>> { @@ -1151,33 +1166,41 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { cache_fresh_trait_pred: &ty::PolyTraitPredicate<'tcx>) -> Option>> { + let tcx = self.tcx(); let trait_ref = &cache_fresh_trait_pred.0.trait_ref; if self.can_use_global_caches(param_env) { - let cache = self.tcx().selection_cache.hashmap.borrow(); + let cache = tcx.selection_cache.hashmap.borrow(); if let Some(cached) = cache.get(&trait_ref) { - return Some(cached.clone()); + return Some(cached.get(tcx)); } } - self.infcx.selection_cache.hashmap.borrow().get(trait_ref).cloned() + self.infcx.selection_cache.hashmap + .borrow() + .get(trait_ref) + .map(|v| v.get(tcx)) } fn insert_candidate_cache(&mut self, param_env: ty::ParamEnv<'tcx>, cache_fresh_trait_pred: ty::PolyTraitPredicate<'tcx>, + dep_node: DepNodeIndex, candidate: SelectionResult<'tcx, SelectionCandidate<'tcx>>) { + let tcx = self.tcx(); let trait_ref = cache_fresh_trait_pred.0.trait_ref; if self.can_use_global_caches(param_env) { - let mut cache = self.tcx().selection_cache.hashmap.borrow_mut(); - if let Some(trait_ref) = self.tcx().lift_to_global(&trait_ref) { - if let Some(candidate) = self.tcx().lift_to_global(&candidate) { - cache.insert(trait_ref, candidate); + let mut cache = tcx.selection_cache.hashmap.borrow_mut(); + if let Some(trait_ref) = tcx.lift_to_global(&trait_ref) { + if let Some(candidate) = tcx.lift_to_global(&candidate) { + cache.insert(trait_ref, WithDepNode::new(dep_node, candidate)); return; } } } - self.infcx.selection_cache.hashmap.borrow_mut().insert(trait_ref, candidate); + self.infcx.selection_cache.hashmap + .borrow_mut() + .insert(trait_ref, WithDepNode::new(dep_node, candidate)); } fn should_update_candidate_cache(&mut self, @@ -1335,7 +1358,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { skol_map); let (def_id, substs) = match skol_trait_predicate.trait_ref.self_ty().sty { - ty::TyProjection(ref data) => (data.trait_ref.def_id, data.trait_ref.substs), + ty::TyProjection(ref data) => + (data.trait_ref(self.tcx()).def_id, data.substs), ty::TyAnon(def_id, substs) => (def_id, substs), _ => { span_bug!( @@ -3137,3 +3161,20 @@ impl<'o,'tcx> fmt::Debug for TraitObligationStack<'o,'tcx> { write!(f, "TraitObligationStack({:?})", self.obligation) } } + +#[derive(Clone)] +pub struct WithDepNode { + dep_node: DepNodeIndex, + cached_value: T +} + +impl WithDepNode { + pub fn new(dep_node: DepNodeIndex, cached_value: T) -> Self { + WithDepNode { dep_node, cached_value } + } + + pub fn get(&self, tcx: TyCtxt) -> T { + tcx.dep_graph.read_index(self.dep_node); + self.cached_value.clone() + } +} diff --git a/src/librustc/traits/trans/mod.rs b/src/librustc/traits/trans/mod.rs index 40bd88d731d3d..827a5092c0042 100644 --- a/src/librustc/traits/trans/mod.rs +++ b/src/librustc/traits/trans/mod.rs @@ -13,9 +13,7 @@ // seems likely that they should eventually be merged into more // general routines. -use dep_graph::{DepGraph, DepNode, DepTrackingMap, DepTrackingMapConfig, - DepConstructor}; -use hir::def_id::DefId; +use dep_graph::{DepGraph, DepKind, DepTrackingMap, DepTrackingMapConfig}; use infer::TransNormalize; use std::cell::RefCell; use std::marker::PhantomData; @@ -41,7 +39,7 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> { // Remove any references to regions; this helps improve caching. let trait_ref = self.erase_regions(&trait_ref); - self.trans_trait_caches.trait_cache.memoize(self, trait_ref, || { + self.trans_trait_caches.trait_cache.memoize(trait_ref, || { debug!("trans::fulfill_obligation(trait_ref={:?}, def_id={:?})", trait_ref, trait_ref.def_id()); @@ -139,7 +137,7 @@ impl<'a, 'gcx> TypeFolder<'gcx, 'gcx> for AssociatedTypeNormalizer<'a, 'gcx> { if !ty.has_projection_types() { ty } else { - self.tcx.trans_trait_caches.project_cache.memoize(self.tcx, ty, || { + self.tcx.trans_trait_caches.project_cache.memoize(ty, || { debug!("AssociatedTypeNormalizer: ty={:?}", ty); self.tcx.normalize_associated_type(&ty) }) @@ -171,8 +169,8 @@ pub struct TraitSelectionCache<'tcx> { impl<'tcx> DepTrackingMapConfig for TraitSelectionCache<'tcx> { type Key = ty::PolyTraitRef<'tcx>; type Value = Vtable<'tcx, ()>; - fn to_dep_node(tcx: TyCtxt, key: &ty::PolyTraitRef<'tcx>) -> DepNode { - key.to_poly_trait_predicate().dep_node(tcx) + fn to_dep_kind() -> DepKind { + DepKind::TraitSelect } } @@ -185,31 +183,8 @@ pub struct ProjectionCache<'gcx> { impl<'gcx> DepTrackingMapConfig for ProjectionCache<'gcx> { type Key = Ty<'gcx>; type Value = Ty<'gcx>; - fn to_dep_node(tcx: TyCtxt, key: &Self::Key) -> DepNode { - // Ideally, we'd just put `key` into the dep-node, but we - // can't put full types in there. So just collect up all the - // def-ids of structs/enums as well as any traits that we - // project out of. It doesn't matter so much what we do here, - // except that if we are too coarse, we'll create overly - // coarse edges between impls and the trans. For example, if - // we just used the def-id of things we are projecting out of, - // then the key for `::T` and `::T` would both share a dep-node - // (`TraitSelect(SomeTrait)`), and hence the impls for both - // `Foo` and `Bar` would be considered inputs. So a change to - // `Bar` would affect things that just normalized `Foo`. - // Anyway, this heuristic is not ideal, but better than - // nothing. - let def_ids: Vec = - key.walk() - .filter_map(|t| match t.sty { - ty::TyAdt(adt_def, _) => Some(adt_def.did), - ty::TyProjection(ref proj) => Some(proj.trait_ref.def_id), - _ => None, - }) - .collect(); - - DepNode::new(tcx, DepConstructor::ProjectionCache { def_ids: def_ids }) + fn to_dep_kind() -> DepKind { + DepKind::TraitSelect } } diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 1f20993f96cfd..0058704236b2d 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -28,7 +28,7 @@ use mir::transform::Passes; use ty::subst::{Kind, Substs}; use ty::ReprOptions; use traits; -use ty::{self, TraitRef, Ty, TypeAndMut}; +use ty::{self, Ty, TypeAndMut}; use ty::{TyS, TypeVariants, Slice}; use ty::{AdtKind, AdtDef, ClosureSubsts, Region}; use hir::FreevarMap; @@ -41,6 +41,7 @@ use ty::inhabitedness::DefIdForest; use ty::maps; use ty::steal::Steal; use util::nodemap::{NodeMap, NodeSet, DefIdSet}; + use util::nodemap::{FxHashMap, FxHashSet}; use rustc_data_structures::accumulate_vec::AccumulateVec; @@ -54,6 +55,7 @@ use std::mem; use std::ops::Deref; use std::iter; use std::rc::Rc; + use syntax::abi; use syntax::ast::{self, Name, NodeId}; use syntax::attr; @@ -1387,12 +1389,13 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } pub fn mk_projection(self, - trait_ref: TraitRef<'tcx>, - item_name: Name) + item_def_id: DefId, + substs: &'tcx Substs<'tcx>) -> Ty<'tcx> { - // take a copy of substs so that we own the vectors inside - let inner = ProjectionTy::from_ref_and_name(self, trait_ref, item_name); - self.mk_ty(TyProjection(inner)) + self.mk_ty(TyProjection(ProjectionTy { + item_def_id: item_def_id, + substs: substs, + })) } pub fn mk_closure(self, diff --git a/src/librustc/ty/error.rs b/src/librustc/ty/error.rs index d6804976e84c5..3442cf0ef698a 100644 --- a/src/librustc/ty/error.rs +++ b/src/librustc/ty/error.rs @@ -14,7 +14,7 @@ use ty::{self, BoundRegion, DefIdTree, Region, Ty, TyCtxt}; use std::fmt; use syntax::abi; -use syntax::ast::{self, Name}; +use syntax::ast; use errors::DiagnosticBuilder; use syntax_pos::Span; @@ -47,7 +47,7 @@ pub enum TypeError<'tcx> { Traits(ExpectedFound), VariadicMismatch(ExpectedFound), CyclicTy, - ProjectionNameMismatched(ExpectedFound), + ProjectionMismatched(ExpectedFound), ProjectionBoundsLength(ExpectedFound), TyParamDefaultMismatch(ExpectedFound>), ExistentialMismatch(ExpectedFound<&'tcx ty::Slice>>), @@ -154,11 +154,11 @@ impl<'tcx> fmt::Display for TypeError<'tcx> { if values.expected { "variadic" } else { "non-variadic" }, if values.found { "variadic" } else { "non-variadic" }) } - ProjectionNameMismatched(ref values) => { + ProjectionMismatched(ref values) => ty::tls::with(|tcx| { write!(f, "expected {}, found {}", - values.expected, - values.found) - } + tcx.item_path_str(values.expected), + tcx.item_path_str(values.found)) + }), ProjectionBoundsLength(ref values) => { write!(f, "expected {} associated type bindings, found {}", values.expected, diff --git a/src/librustc/ty/flags.rs b/src/librustc/ty/flags.rs index d5aa9f55ff0c4..ce2bb23660ce0 100644 --- a/src/librustc/ty/flags.rs +++ b/src/librustc/ty/flags.rs @@ -193,12 +193,12 @@ impl FlagComputation { } fn add_existential_projection(&mut self, projection: &ty::ExistentialProjection) { - self.add_substs(projection.trait_ref.substs); + self.add_substs(projection.substs); self.add_ty(projection.ty); } fn add_projection_ty(&mut self, projection_ty: &ty::ProjectionTy) { - self.add_substs(projection_ty.trait_ref.substs); + self.add_substs(projection_ty.substs); } fn add_substs(&mut self, substs: &Substs) { diff --git a/src/librustc/ty/fold.rs b/src/librustc/ty/fold.rs index 66868040925e1..a1cd92c760915 100644 --- a/src/librustc/ty/fold.rs +++ b/src/librustc/ty/fold.rs @@ -150,10 +150,6 @@ pub trait TypeVisitor<'tcx> : Sized { t.super_visit_with(self) } - fn visit_trait_ref(&mut self, trait_ref: ty::TraitRef<'tcx>) -> bool { - trait_ref.super_visit_with(self) - } - fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool { r.super_visit_with(self) } diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs index 76103148ec3e8..32063a2dda603 100644 --- a/src/librustc/ty/instance.rs +++ b/src/librustc/ty/instance.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use dep_graph::DepConstructor; use hir::def_id::DefId; use ty::{self, Ty, TypeFoldable, Substs}; use util::ppaux; @@ -59,27 +58,6 @@ impl<'tcx> InstanceDef<'tcx> { pub fn attrs<'a>(&self, tcx: ty::TyCtxt<'a, 'tcx, 'tcx>) -> ty::Attributes<'tcx> { tcx.get_attrs(self.def_id()) } - - pub //(crate) - fn dep_node(&self) -> DepConstructor { - // HACK: def-id binning, project-style; someone replace this with - // real on-demand. - let ty = match self { - &InstanceDef::FnPtrShim(_, ty) => Some(ty), - &InstanceDef::DropGlue(_, ty) => ty, - _ => None - }.into_iter(); - - DepConstructor::MirShim( - Some(self.def_id()).into_iter().chain( - ty.flat_map(|t| t.walk()).flat_map(|t| match t.sty { - ty::TyAdt(adt_def, _) => Some(adt_def.did), - ty::TyProjection(ref proj) => Some(proj.trait_ref.def_id), - _ => None, - }) - ).collect() - ) - } } impl<'tcx> fmt::Display for Instance<'tcx> { diff --git a/src/librustc/ty/maps.rs b/src/librustc/ty/maps.rs index f4e333228c94d..845cd978b4475 100644 --- a/src/librustc/ty/maps.rs +++ b/src/librustc/ty/maps.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use dep_graph::{DepConstructor, DepNode, DepTrackingMapConfig}; +use dep_graph::{DepConstructor, DepNode, DepNodeIndex}; use hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId, LOCAL_CRATE}; use hir::def::Def; use hir; @@ -26,6 +26,8 @@ use ty::item_path; use ty::steal::Steal; use ty::subst::Substs; use ty::fast_reject::SimplifiedType; + +use util::common::{profq_msg, ProfileQueriesMsg}; use util::nodemap::{DefIdSet, NodeSet}; use rustc_data_structures::indexed_vec::IndexVec; @@ -186,7 +188,7 @@ impl<'tcx> Value<'tcx> for ty::SymbolName { struct QueryMap { phantom: PhantomData, - map: FxHashMap, + map: FxHashMap, } impl QueryMap { @@ -261,11 +263,16 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } } -trait QueryDescription: DepTrackingMapConfig { +pub trait QueryConfig { + type Key: Eq + Hash + Clone; + type Value; +} + +trait QueryDescription: QueryConfig { fn describe(tcx: TyCtxt, key: Self::Key) -> String; } -impl> QueryDescription for M { +impl> QueryDescription for M { default fn describe(tcx: TyCtxt, def_id: DefId) -> String { format!("processing `{}`", tcx.item_path_str(def_id)) } @@ -507,6 +514,15 @@ impl<'tcx> QueryDescription for queries::extern_crate<'tcx> { } } +// If enabled, send a message to the profile-queries thread +macro_rules! profq_msg { + ($tcx:expr, $msg:expr) => { + if $tcx.sess.opts.debugging_opts.profile_queries { + profq_msg($msg) + } + } +} + macro_rules! define_maps { (<$tcx:tt> $($(#[$attr:meta])* @@ -533,6 +549,12 @@ macro_rules! define_maps { $($(#[$attr])* $name($K)),* } + #[allow(bad_style)] + #[derive(Clone, Debug, PartialEq, Eq)] + pub enum QueryMsg { + $($name(String)),* + } + impl<$tcx> Query<$tcx> { pub fn describe(&self, tcx: TyCtxt) -> String { match *self { @@ -550,18 +572,19 @@ macro_rules! define_maps { })* } - $(impl<$tcx> DepTrackingMapConfig for queries::$name<$tcx> { + $(impl<$tcx> QueryConfig for queries::$name<$tcx> { type Key = $K; type Value = $V; + } + impl<'a, $tcx, 'lcx> queries::$name<$tcx> { #[allow(unused)] - fn to_dep_node(tcx: TyCtxt, key: &$K) -> DepNode { + fn to_dep_node(tcx: TyCtxt<'a, $tcx, 'lcx>, key: &$K) -> DepNode { use dep_graph::DepConstructor::*; DepNode::new(tcx, $node(*key)) } - } - impl<'a, $tcx, 'lcx> queries::$name<$tcx> { + fn try_get_with(tcx: TyCtxt<'a, $tcx, 'lcx>, mut span: Span, key: $K, @@ -574,9 +597,17 @@ macro_rules! define_maps { key, span); - if let Some(result) = tcx.maps.$name.borrow().map.get(&key) { + profq_msg!(tcx, + ProfileQueriesMsg::QueryBegin(span.clone(), + QueryMsg::$name(format!("{:?}", key)))); + + if let Some(&(ref result, dep_node_index)) = tcx.maps.$name.borrow().map.get(&key) { + tcx.dep_graph.read_index(dep_node_index); + profq_msg!(tcx, ProfileQueriesMsg::CacheHit); return Ok(f(result)); } + // else, we are going to run the provider: + profq_msg!(tcx, ProfileQueriesMsg::ProviderBegin); // FIXME(eddyb) Get more valid Span's on queries. // def_span guard is necesary to prevent a recursive loop, @@ -585,26 +616,47 @@ macro_rules! define_maps { span = key.default_span(tcx) } - let _task = tcx.dep_graph.in_task(Self::to_dep_node(tcx, &key)); - - let result = tcx.cycle_check(span, Query::$name(key), || { - let provider = tcx.maps.providers[key.map_crate()].$name; - provider(tcx.global_tcx(), key) + let (result, dep_node_index) = tcx.cycle_check(span, Query::$name(key), || { + let dep_node = Self::to_dep_node(tcx, &key); + + if dep_node.kind.is_anon() { + tcx.dep_graph.with_anon_task(dep_node.kind, || { + let provider = tcx.maps.providers[key.map_crate()].$name; + provider(tcx.global_tcx(), key) + }) + } else { + fn run_provider<'a, 'tcx, 'lcx>(tcx: TyCtxt<'a, 'tcx, 'lcx>, + key: $K) + -> $V { + let provider = tcx.maps.providers[key.map_crate()].$name; + provider(tcx.global_tcx(), key) + } + + tcx.dep_graph.with_task(dep_node, tcx, key, run_provider) + } })?; + profq_msg!(tcx, ProfileQueriesMsg::ProviderEnd); + + tcx.dep_graph.read_index(dep_node_index); - Ok(f(tcx.maps.$name.borrow_mut().map.entry(key).or_insert(result))) + Ok(f(&tcx.maps + .$name + .borrow_mut() + .map + .entry(key) + .or_insert((result, dep_node_index)) + .0)) } pub fn try_get(tcx: TyCtxt<'a, $tcx, 'lcx>, span: Span, key: $K) -> Result<$V, CycleError<'a, $tcx>> { - // We register the `read` here, but not in `force`, since - // `force` does not give access to the value produced (and thus - // we actually don't read it). - tcx.dep_graph.read(Self::to_dep_node(tcx, &key)); Self::try_get_with(tcx, span, key, Clone::clone) } pub fn force(tcx: TyCtxt<'a, $tcx, 'lcx>, span: Span, key: $K) { + // Ignore dependencies, since we not reading the computed value + let _task = tcx.dep_graph.in_ignore(); + match Self::try_get_with(tcx, span, key, |_| ()) { Ok(()) => {} Err(e) => tcx.report_cycle(e) @@ -796,12 +848,12 @@ macro_rules! define_provider_struct { // the driver creates (using several `rustc_*` crates). define_maps! { <'tcx> /// Records the type of every item. - [] type_of: ItemSignature(DefId) -> Ty<'tcx>, + [] type_of: TypeOfItem(DefId) -> Ty<'tcx>, /// Maps from the def-id of an item (trait/struct/enum/fn) to its /// associated generics and predicates. - [] generics_of: ItemSignature(DefId) -> &'tcx ty::Generics, - [] predicates_of: ItemSignature(DefId) -> ty::GenericPredicates<'tcx>, + [] generics_of: GenericsOfItem(DefId) -> &'tcx ty::Generics, + [] predicates_of: PredicatesOfItem(DefId) -> ty::GenericPredicates<'tcx>, /// Maps from the def-id of a trait to the list of /// super-predicates. This is a subset of the full list of @@ -809,15 +861,15 @@ define_maps! { <'tcx> /// evaluate them even during type conversion, often before the /// full predicates are available (note that supertraits have /// additional acyclicity requirements). - [] super_predicates_of: ItemSignature(DefId) -> ty::GenericPredicates<'tcx>, + [] super_predicates_of: SuperPredicatesOfItem(DefId) -> ty::GenericPredicates<'tcx>, /// To avoid cycles within the predicates of a single item we compute /// per-type-parameter predicates for resolving `T::AssocTy`. [] type_param_predicates: type_param_predicates((DefId, DefId)) -> ty::GenericPredicates<'tcx>, - [] trait_def: ItemSignature(DefId) -> &'tcx ty::TraitDef, - [] adt_def: ItemSignature(DefId) -> &'tcx ty::AdtDef, + [] trait_def: TraitDefOfItem(DefId) -> &'tcx ty::TraitDef, + [] adt_def: AdtDefOfItem(DefId) -> &'tcx ty::AdtDef, [] adt_destructor: AdtDestructor(DefId) -> Option, [] adt_sized_constraint: SizedConstraint(DefId) -> &'tcx [Ty<'tcx>], [] adt_dtorck_constraint: DtorckConstraint(DefId) -> ty::DtorckConstraint<'tcx>, @@ -829,7 +881,7 @@ define_maps! { <'tcx> [] is_foreign_item: IsForeignItem(DefId) -> bool, /// True if this is a default impl (aka impl Foo for ..) - [] is_default_impl: ItemSignature(DefId) -> bool, + [] is_default_impl: IsDefaultImpl(DefId) -> bool, /// Get a map with the variance of every item; use `item_variance` /// instead. @@ -845,8 +897,8 @@ define_maps! { <'tcx> /// Maps from a trait item to the trait item "descriptor" [] associated_item: AssociatedItems(DefId) -> ty::AssociatedItem, - [] impl_trait_ref: ItemSignature(DefId) -> Option>, - [] impl_polarity: ItemSignature(DefId) -> hir::ImplPolarity, + [] impl_trait_ref: ImplTraitRef(DefId) -> Option>, + [] impl_polarity: ImplPolarity(DefId) -> hir::ImplPolarity, /// Maps a DefId of a type to a list of its inherent impls. /// Contains implementations of methods that are inherent to a type. @@ -861,36 +913,36 @@ define_maps! { <'tcx> /// Maps DefId's that have an associated Mir to the result /// of the MIR qualify_consts pass. The actual meaning of /// the value isn't known except to the pass itself. - [] mir_const_qualif: Mir(DefId) -> u8, + [] mir_const_qualif: MirConstQualif(DefId) -> u8, /// Fetch the MIR for a given def-id up till the point where it is /// ready for const evaluation. /// /// See the README for the `mir` module for details. - [] mir_const: Mir(DefId) -> &'tcx Steal>, + [] mir_const: MirConst(DefId) -> &'tcx Steal>, - [] mir_validated: Mir(DefId) -> &'tcx Steal>, + [] mir_validated: MirValidated(DefId) -> &'tcx Steal>, /// MIR after our optimization passes have run. This is MIR that is ready /// for trans. This is also the only query that can fetch non-local MIR, at present. - [] optimized_mir: Mir(DefId) -> &'tcx mir::Mir<'tcx>, + [] optimized_mir: MirOptimized(DefId) -> &'tcx mir::Mir<'tcx>, /// Type of each closure. The def ID is the ID of the /// expression defining the closure. - [] closure_kind: ItemSignature(DefId) -> ty::ClosureKind, + [] closure_kind: ClosureKind(DefId) -> ty::ClosureKind, /// The signature of functions and closures. - [] fn_sig: ItemSignature(DefId) -> ty::PolyFnSig<'tcx>, + [] fn_sig: FnSignature(DefId) -> ty::PolyFnSig<'tcx>, /// Caches CoerceUnsized kinds for impls on custom types. - [] coerce_unsized_info: ItemSignature(DefId) + [] coerce_unsized_info: CoerceUnsizedInfo(DefId) -> ty::adjustment::CoerceUnsizedInfo, [] typeck_item_bodies: typeck_item_bodies_dep_node(CrateNum) -> CompileResult, [] typeck_tables_of: TypeckTables(DefId) -> &'tcx ty::TypeckTables<'tcx>, - [] has_typeck_tables: TypeckTables(DefId) -> bool, + [] has_typeck_tables: HasTypeckTables(DefId) -> bool, [] coherent_trait: coherent_trait_dep_node((CrateNum, DefId)) -> (), @@ -972,80 +1024,81 @@ define_maps! { <'tcx> [] extern_crate: ExternCrate(DefId) -> Rc>, } -fn type_param_predicates((item_id, param_id): (DefId, DefId)) -> DepConstructor { +fn type_param_predicates<'tcx>((item_id, param_id): (DefId, DefId)) -> DepConstructor<'tcx> { DepConstructor::TypeParamPredicates { item_id, param_id } } -fn coherent_trait_dep_node((_, def_id): (CrateNum, DefId)) -> DepConstructor { +fn coherent_trait_dep_node<'tcx>((_, def_id): (CrateNum, DefId)) -> DepConstructor<'tcx> { DepConstructor::CoherenceCheckTrait(def_id) } -fn crate_inherent_impls_dep_node(_: CrateNum) -> DepConstructor { +fn crate_inherent_impls_dep_node<'tcx>(_: CrateNum) -> DepConstructor<'tcx> { DepConstructor::Coherence } -fn reachability_dep_node(_: CrateNum) -> DepConstructor { +fn reachability_dep_node<'tcx>(_: CrateNum) -> DepConstructor<'tcx> { DepConstructor::Reachability } -fn mir_shim_dep_node(instance: ty::InstanceDef) -> DepConstructor { - instance.dep_node() +fn mir_shim_dep_node<'tcx>(instance_def: ty::InstanceDef<'tcx>) -> DepConstructor<'tcx> { + DepConstructor::MirShim { + instance_def + } } -fn symbol_name_dep_node(instance: ty::Instance) -> DepConstructor { - // symbol_name uses the substs only to traverse them to find the - // hash, and that does not create any new dep-nodes. - DepConstructor::SymbolName(instance.def.def_id()) +fn symbol_name_dep_node<'tcx>(instance: ty::Instance<'tcx>) -> DepConstructor<'tcx> { + DepConstructor::InstanceSymbolName { instance } } -fn typeck_item_bodies_dep_node(_: CrateNum) -> DepConstructor { +fn typeck_item_bodies_dep_node<'tcx>(_: CrateNum) -> DepConstructor<'tcx> { DepConstructor::TypeckBodiesKrate } -fn const_eval_dep_node((def_id, _): (DefId, &Substs)) -> DepConstructor { - DepConstructor::ConstEval(def_id) +fn const_eval_dep_node<'tcx>((def_id, substs): (DefId, &'tcx Substs<'tcx>)) + -> DepConstructor<'tcx> { + DepConstructor::ConstEval { def_id, substs } } -fn mir_keys(_: CrateNum) -> DepConstructor { +fn mir_keys<'tcx>(_: CrateNum) -> DepConstructor<'tcx> { DepConstructor::MirKeys } -fn crate_variances(_: CrateNum) -> DepConstructor { +fn crate_variances<'tcx>(_: CrateNum) -> DepConstructor<'tcx> { DepConstructor::CrateVariances } -fn relevant_trait_impls_for((def_id, _): (DefId, SimplifiedType)) -> DepConstructor { - DepConstructor::TraitImpls(def_id) +fn relevant_trait_impls_for<'tcx>((def_id, t): (DefId, SimplifiedType)) -> DepConstructor<'tcx> { + DepConstructor::RelevantTraitImpls(def_id, t) } -fn is_copy_dep_node<'tcx>(key: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> DepConstructor { +fn is_copy_dep_node<'tcx>(key: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> DepConstructor<'tcx> { let def_id = ty::item_path::characteristic_def_id_of_type(key.value) .unwrap_or(DefId::local(CRATE_DEF_INDEX)); DepConstructor::IsCopy(def_id) } -fn is_sized_dep_node<'tcx>(key: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> DepConstructor { +fn is_sized_dep_node<'tcx>(key: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> DepConstructor<'tcx> { let def_id = ty::item_path::characteristic_def_id_of_type(key.value) .unwrap_or(DefId::local(CRATE_DEF_INDEX)); DepConstructor::IsSized(def_id) } -fn is_freeze_dep_node<'tcx>(key: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> DepConstructor { +fn is_freeze_dep_node<'tcx>(key: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> DepConstructor<'tcx> { let def_id = ty::item_path::characteristic_def_id_of_type(key.value) .unwrap_or(DefId::local(CRATE_DEF_INDEX)); DepConstructor::IsFreeze(def_id) } -fn needs_drop_dep_node<'tcx>(key: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> DepConstructor { +fn needs_drop_dep_node<'tcx>(key: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> DepConstructor<'tcx> { let def_id = ty::item_path::characteristic_def_id_of_type(key.value) .unwrap_or(DefId::local(CRATE_DEF_INDEX)); DepConstructor::NeedsDrop(def_id) } -fn layout_dep_node<'tcx>(key: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> DepConstructor { +fn layout_dep_node<'tcx>(key: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> DepConstructor<'tcx> { let def_id = ty::item_path::characteristic_def_id_of_type(key.value) .unwrap_or(DefId::local(CRATE_DEF_INDEX)); DepConstructor::Layout(def_id) diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 0ce91b33c510d..1fee0dd98634a 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -15,7 +15,6 @@ pub use self::IntVarValue::*; pub use self::LvaluePreference::*; pub use self::fold::TypeFoldable; -use dep_graph::{DepNode, DepConstructor}; use hir::{map as hir_map, FreevarMap, TraitMap}; use hir::def::{Def, CtorKind, ExportMap}; use hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE}; @@ -720,6 +719,7 @@ pub struct Generics { pub type_param_to_index: BTreeMap, pub has_self: bool, + pub has_late_bound_regions: bool, } impl Generics { @@ -947,28 +947,6 @@ impl<'tcx> TraitPredicate<'tcx> { self.trait_ref.def_id } - /// Creates the dep-node for selecting/evaluating this trait reference. - fn dep_node(&self, tcx: TyCtxt) -> DepNode { - // Extact the trait-def and first def-id from inputs. See the - // docs for `DepNode::TraitSelect` for more information. - let trait_def_id = self.def_id(); - let input_def_id = - self.input_types() - .flat_map(|t| t.walk()) - .filter_map(|t| match t.sty { - ty::TyAdt(adt_def, ..) => Some(adt_def.did), - ty::TyClosure(def_id, ..) => Some(def_id), - ty::TyFnDef(def_id, ..) => Some(def_id), - _ => None - }) - .next() - .unwrap_or(trait_def_id); - DepNode::new(tcx, DepConstructor::TraitSelect { - trait_def_id, - input_def_id, - }) - } - pub fn input_types<'a>(&'a self) -> impl DoubleEndedIterator> + 'a { self.trait_ref.input_types() } @@ -983,11 +961,6 @@ impl<'tcx> PolyTraitPredicate<'tcx> { // ok to skip binder since trait def-id does not care about regions self.0.def_id() } - - pub fn dep_node(&self, tcx: TyCtxt) -> DepNode { - // ok to skip binder since depnode does not care about regions - self.0.dep_node(tcx) - } } #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)] @@ -1030,8 +1003,13 @@ pub struct ProjectionPredicate<'tcx> { pub type PolyProjectionPredicate<'tcx> = Binder>; impl<'tcx> PolyProjectionPredicate<'tcx> { - pub fn item_name(&self, tcx: TyCtxt) -> Name { - self.0.projection_ty.item_name(tcx) // safe to skip the binder to access a name + pub fn to_poly_trait_ref(&self, tcx: TyCtxt) -> PolyTraitRef<'tcx> { + // Note: unlike with TraitRef::to_poly_trait_ref(), + // self.0.trait_ref is permitted to have escaping regions. + // This is because here `self` has a `Binder` and so does our + // return value, so we are preserving the number of binding + // levels. + ty::Binder(self.0.projection_ty.trait_ref(tcx)) } } @@ -1052,17 +1030,6 @@ impl<'tcx> ToPolyTraitRef<'tcx> for PolyTraitPredicate<'tcx> { } } -impl<'tcx> ToPolyTraitRef<'tcx> for PolyProjectionPredicate<'tcx> { - fn to_poly_trait_ref(&self) -> PolyTraitRef<'tcx> { - // Note: unlike with TraitRef::to_poly_trait_ref(), - // self.0.trait_ref is permitted to have escaping regions. - // This is because here `self` has a `Binder` and so does our - // return value, so we are preserving the number of binding - // levels. - ty::Binder(self.0.projection_ty.trait_ref) - } -} - pub trait ToPredicate<'tcx> { fn to_predicate(&self) -> Predicate<'tcx>; } @@ -1132,8 +1099,7 @@ impl<'tcx> Predicate<'tcx> { vec![] } ty::Predicate::Projection(ref data) => { - let trait_inputs = data.0.projection_ty.trait_ref.input_types(); - trait_inputs.chain(Some(data.0.ty)).collect() + data.0.projection_ty.substs.types().chain(Some(data.0.ty)).collect() } ty::Predicate::WellFormed(data) => { vec![data] diff --git a/src/librustc/ty/relate.rs b/src/librustc/ty/relate.rs index 7710cc965c8f0..0d9ef8196c794 100644 --- a/src/librustc/ty/relate.rs +++ b/src/librustc/ty/relate.rs @@ -225,13 +225,15 @@ impl<'tcx> Relate<'tcx> for ty::ProjectionTy<'tcx> { -> RelateResult<'tcx, ty::ProjectionTy<'tcx>> where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a { - let tcx = relation.tcx(); - if a.item_name(tcx) != b.item_name(tcx) { - Err(TypeError::ProjectionNameMismatched( - expected_found(relation, &a.item_name(tcx), &b.item_name(tcx)))) + if a.item_def_id != b.item_def_id { + Err(TypeError::ProjectionMismatched( + expected_found(relation, &a.item_def_id, &b.item_def_id))) } else { - let trait_ref = relation.relate(&a.trait_ref, &b.trait_ref)?; - Ok(ty::ProjectionTy::from_ref_and_name(tcx, trait_ref, a.item_name(tcx))) + let substs = relation.relate(&a.substs, &b.substs)?; + Ok(ty::ProjectionTy { + item_def_id: a.item_def_id, + substs: &substs, + }) } } } @@ -243,15 +245,15 @@ impl<'tcx> Relate<'tcx> for ty::ExistentialProjection<'tcx> { -> RelateResult<'tcx, ty::ExistentialProjection<'tcx>> where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a { - if a.item_name != b.item_name { - Err(TypeError::ProjectionNameMismatched( - expected_found(relation, &a.item_name, &b.item_name))) + if a.item_def_id != b.item_def_id { + Err(TypeError::ProjectionMismatched( + expected_found(relation, &a.item_def_id, &b.item_def_id))) } else { - let trait_ref = relation.relate(&a.trait_ref, &b.trait_ref)?; let ty = relation.relate(&a.ty, &b.ty)?; + let substs = relation.relate(&a.substs, &b.substs)?; Ok(ty::ExistentialProjection { - trait_ref, - item_name: a.item_name, + item_def_id: a.item_def_id, + substs: substs, ty, }) } @@ -456,7 +458,7 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R, (&ty::TyProjection(ref a_data), &ty::TyProjection(ref b_data)) => { let projection_ty = relation.relate(a_data, b_data)?; - Ok(tcx.mk_projection(projection_ty.trait_ref, projection_ty.item_name(tcx))) + Ok(tcx.mk_projection(projection_ty.item_def_id, projection_ty.substs)) } (&ty::TyAnon(a_def_id, a_substs), &ty::TyAnon(b_def_id, b_substs)) diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index c9b3d038c0774..b81bd595e25b0 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -134,8 +134,11 @@ impl<'a, 'tcx> Lift<'tcx> for ty::ProjectionTy<'a> { type Lifted = ty::ProjectionTy<'tcx>; fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option> { - tcx.lift(&self.trait_ref).map(|trait_ref| { - ty::ProjectionTy::from_ref_and_name(tcx, trait_ref, self.item_name(tcx)) + tcx.lift(&self.substs).map(|substs| { + ty::ProjectionTy { + item_def_id: self.item_def_id, + substs: substs, + } }) } } @@ -156,11 +159,11 @@ impl<'a, 'tcx> Lift<'tcx> for ty::ProjectionPredicate<'a> { impl<'a, 'tcx> Lift<'tcx> for ty::ExistentialProjection<'a> { type Lifted = ty::ExistentialProjection<'tcx>; fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option { - tcx.lift(&(self.trait_ref, self.ty)).map(|(trait_ref, ty)| { + tcx.lift(&self.substs).map(|substs| { ty::ExistentialProjection { - trait_ref, - item_name: self.item_name, - ty, + substs, + ty: tcx.lift(&self.ty).expect("type must lift when substs do"), + item_def_id: self.item_def_id, } }) } @@ -356,7 +359,7 @@ impl<'a, 'tcx> Lift<'tcx> for ty::error::TypeError<'a> { Traits(x) => Traits(x), VariadicMismatch(x) => VariadicMismatch(x), CyclicTy => CyclicTy, - ProjectionNameMismatched(x) => ProjectionNameMismatched(x), + ProjectionMismatched(x) => ProjectionMismatched(x), ProjectionBoundsLength(x) => ProjectionBoundsLength(x), Sorts(ref x) => return tcx.lift(x).map(Sorts), @@ -621,10 +624,6 @@ impl<'tcx> TypeFoldable<'tcx> for ty::TraitRef<'tcx> { fn super_visit_with>(&self, visitor: &mut V) -> bool { self.substs.visit_with(visitor) } - - fn visit_with>(&self, visitor: &mut V) -> bool { - visitor.visit_trait_ref(*self) - } } impl<'tcx> TypeFoldable<'tcx> for ty::ExistentialTraitRef<'tcx> { @@ -847,27 +846,27 @@ impl<'tcx> TypeFoldable<'tcx> for ty::ProjectionPredicate<'tcx> { impl<'tcx> TypeFoldable<'tcx> for ty::ExistentialProjection<'tcx> { fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { ty::ExistentialProjection { - trait_ref: self.trait_ref.fold_with(folder), - item_name: self.item_name, ty: self.ty.fold_with(folder), + substs: self.substs.fold_with(folder), + item_def_id: self.item_def_id, } } fn super_visit_with>(&self, visitor: &mut V) -> bool { - self.trait_ref.visit_with(visitor) || self.ty.visit_with(visitor) + self.substs.visit_with(visitor) || self.ty.visit_with(visitor) } } impl<'tcx> TypeFoldable<'tcx> for ty::ProjectionTy<'tcx> { fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { ty::ProjectionTy { - trait_ref: self.trait_ref.fold_with(folder), + substs: self.substs.fold_with(folder), item_def_id: self.item_def_id, } } fn super_visit_with>(&self, visitor: &mut V) -> bool { - self.trait_ref.visit_with(visitor) + self.substs.visit_with(visitor) } } @@ -1018,7 +1017,7 @@ impl<'tcx> TypeFoldable<'tcx> for ty::error::TypeError<'tcx> { Traits(x) => Traits(x), VariadicMismatch(x) => VariadicMismatch(x), CyclicTy => CyclicTy, - ProjectionNameMismatched(x) => ProjectionNameMismatched(x), + ProjectionMismatched(x) => ProjectionMismatched(x), ProjectionBoundsLength(x) => ProjectionBoundsLength(x), Sorts(x) => Sorts(x.fold_with(folder)), TyParamDefaultMismatch(ref x) => TyParamDefaultMismatch(x.fold_with(folder)), @@ -1054,7 +1053,7 @@ impl<'tcx> TypeFoldable<'tcx> for ty::error::TypeError<'tcx> { Traits(_) | VariadicMismatch(_) | CyclicTy | - ProjectionNameMismatched(_) | + ProjectionMismatched(_) | ProjectionBoundsLength(_) => false, } } diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 737e69b658348..5f89714b33fda 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -11,7 +11,6 @@ //! This module contains TypeVariants and its major components use hir::def_id::DefId; -use hir::map::DefPathHash; use middle::region; use ty::subst::{Substs, Subst}; @@ -24,7 +23,7 @@ use std::iter; use std::cmp::Ordering; use syntax::abi; use syntax::ast::{self, Name}; -use syntax::symbol::{keywords, InternedString}; +use syntax::symbol::keywords; use util::nodemap::FxHashMap; use serialize; @@ -291,7 +290,8 @@ impl<'a, 'gcx, 'tcx> ExistentialPredicate<'tcx> { use self::ExistentialPredicate::*; match (*self, *other) { (Trait(_), Trait(_)) => Ordering::Equal, - (Projection(ref a), Projection(ref b)) => a.sort_key(tcx).cmp(&b.sort_key(tcx)), + (Projection(ref a), Projection(ref b)) => + tcx.def_path_hash(a.item_def_id).cmp(&tcx.def_path_hash(b.item_def_id)), (AutoTrait(ref a), AutoTrait(ref b)) => tcx.trait_def(*a).def_path_hash.cmp(&tcx.trait_def(*b).def_path_hash), (Trait(_), _) => Ordering::Less, @@ -551,8 +551,8 @@ impl fmt::Debug for TypeFlags { /// form this would be written `>::N`. #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)] pub struct ProjectionTy<'tcx> { - /// The trait reference `T as Trait<..>`. - pub trait_ref: ty::TraitRef<'tcx>, + /// The parameters of the associated item. + pub substs: &'tcx Substs<'tcx>, /// The DefId of the TraitItem for the associated type N. /// @@ -568,16 +568,28 @@ impl<'a, 'tcx> ProjectionTy<'tcx> { tcx: TyCtxt, trait_ref: ty::TraitRef<'tcx>, item_name: Name ) -> ProjectionTy<'tcx> { let item_def_id = tcx.associated_items(trait_ref.def_id).find( - |item| item.name == item_name).unwrap().def_id; + |item| item.name == item_name && item.kind == ty::AssociatedKind::Type + ).unwrap().def_id; ProjectionTy { - trait_ref, + substs: trait_ref.substs, item_def_id, } } - pub fn item_name(self, tcx: TyCtxt) -> Name { - tcx.associated_item(self.item_def_id).name + /// Extracts the underlying trait reference from this projection. + /// For example, if this is a projection of `::Item`, + /// then this function would return a `T: Iterator` trait reference. + pub fn trait_ref(&self, tcx: TyCtxt) -> ty::TraitRef<'tcx> { + let def_id = tcx.associated_item(self.item_def_id).container.id(); + ty::TraitRef { + def_id: def_id, + substs: self.substs, + } + } + + pub fn self_ty(&self) -> Ty<'tcx> { + self.substs.type_at(0) } } @@ -861,29 +873,24 @@ pub enum InferTy { /// A `ProjectionPredicate` for an `ExistentialTraitRef`. #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)] pub struct ExistentialProjection<'tcx> { - pub trait_ref: ExistentialTraitRef<'tcx>, - pub item_name: Name, + pub item_def_id: DefId, + pub substs: &'tcx Substs<'tcx>, pub ty: Ty<'tcx>, } pub type PolyExistentialProjection<'tcx> = Binder>; impl<'a, 'tcx, 'gcx> ExistentialProjection<'tcx> { - pub fn item_name(&self) -> Name { - self.item_name // safe to skip the binder to access a name - } - - pub fn sort_key(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> (DefPathHash, InternedString) { - // We want something here that is stable across crate boundaries. - // The DefId isn't but the `deterministic_hash` of the corresponding - // DefPath is. - let trait_def = tcx.trait_def(self.trait_ref.def_id); - let def_path_hash = trait_def.def_path_hash; - - // An `ast::Name` is also not stable (it's just an index into an - // interning table), so map to the corresponding `InternedString`. - let item_name = self.item_name.as_str(); - (def_path_hash, item_name) + /// Extracts the underlying existential trait reference from this projection. + /// For example, if this is a projection of `exists T. ::Item == X`, + /// then this function would return a `exists T. T: Iterator` existential trait + /// reference. + pub fn trait_ref(&self, tcx: TyCtxt) -> ty::ExistentialTraitRef<'tcx> { + let def_id = tcx.associated_item(self.item_def_id).container.id(); + ty::ExistentialTraitRef{ + def_id: def_id, + substs: self.substs, + } } pub fn with_self_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, @@ -894,24 +901,17 @@ impl<'a, 'tcx, 'gcx> ExistentialProjection<'tcx> { assert!(!self_ty.has_escaping_regions()); ty::ProjectionPredicate { - projection_ty: ty::ProjectionTy::from_ref_and_name( - tcx, - self.trait_ref.with_self_ty(tcx, self_ty), - self.item_name), + projection_ty: ty::ProjectionTy { + item_def_id: self.item_def_id, + substs: tcx.mk_substs( + iter::once(Kind::from(self_ty)).chain(self.substs.iter().cloned())), + }, ty: self.ty, } } } impl<'a, 'tcx, 'gcx> PolyExistentialProjection<'tcx> { - pub fn item_name(&self) -> Name { - self.skip_binder().item_name() - } - - pub fn sort_key(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> (DefPathHash, InternedString) { - self.skip_binder().sort_key(tcx) - } - pub fn with_self_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, self_ty: Ty<'tcx>) -> ty::PolyProjectionPredicate<'tcx> { self.map_bound(|p| p.with_self_ty(tcx, self_ty)) @@ -993,7 +993,6 @@ impl RegionKind { // This method returns whether the given Region is Named pub fn is_named_region(&self) -> bool { - match *self { ty::ReFree(ref free_region) => { match free_region.bound_region { @@ -1398,7 +1397,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { substs.substs.regions().collect() } TyProjection(ref data) => { - data.trait_ref.substs.regions().collect() + data.substs.regions().collect() } TyFnDef(..) | TyFnPtr(_) | diff --git a/src/librustc/ty/walk.rs b/src/librustc/ty/walk.rs index 71844abfe534c..a7f0bafe9b67d 100644 --- a/src/librustc/ty/walk.rs +++ b/src/librustc/ty/walk.rs @@ -90,14 +90,14 @@ fn push_subtypes<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent_ty: Ty<'tcx>) { stack.push(mt.ty); } ty::TyProjection(ref data) => { - stack.extend(data.trait_ref.substs.types().rev()); + stack.extend(data.substs.types().rev()); } ty::TyDynamic(ref obj, ..) => { stack.extend(obj.iter().rev().flat_map(|predicate| { let (substs, opt_ty) = match *predicate.skip_binder() { ty::ExistentialPredicate::Trait(tr) => (tr.substs, None), ty::ExistentialPredicate::Projection(p) => - (p.trait_ref.substs, Some(p.ty)), + (p.substs, Some(p.ty)), ty::ExistentialPredicate::AutoTrait(_) => // Empty iterator (ty::Substs::empty(), None), diff --git a/src/librustc/ty/wf.rs b/src/librustc/ty/wf.rs index 91bc56155969a..c24c583ad1e19 100644 --- a/src/librustc/ty/wf.rs +++ b/src/librustc/ty/wf.rs @@ -155,11 +155,11 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> { // A projection is well-formed if (a) the trait ref itself is // WF and (b) the trait-ref holds. (It may also be // normalizable and be WF that way.) - - self.compute_trait_ref(&data.trait_ref); + let trait_ref = data.trait_ref(self.infcx.tcx); + self.compute_trait_ref(&trait_ref); if !data.has_escaping_regions() { - let predicate = data.trait_ref.to_predicate(); + let predicate = trait_ref.to_predicate(); let cause = self.cause(traits::ProjectionWf(data)); self.out.push(traits::Obligation::new(cause, self.param_env, predicate)); } diff --git a/src/librustc/util/common.rs b/src/librustc/util/common.rs index 40ee3cd28f562..17e448f787e50 100644 --- a/src/librustc/util/common.rs +++ b/src/librustc/util/common.rs @@ -19,7 +19,9 @@ use std::iter::repeat; use std::path::Path; use std::time::{Duration, Instant}; -use ty::TyCtxt; +use std::sync::mpsc::{Sender}; +use syntax_pos::{Span}; +use ty::maps::{QueryMsg}; // The name of the associated type for `Fn` return types pub const FN_OUTPUT_NAME: &'static str = "Output"; @@ -31,6 +33,52 @@ pub struct ErrorReported; thread_local!(static TIME_DEPTH: Cell = Cell::new(0)); +/// Initialized for -Z profile-queries +thread_local!(static PROFQ_CHAN: RefCell>> = RefCell::new(None)); + +/// A sequence of these messages induce a trace of query-based incremental compilation. +/// FIXME(matthewhammer): Determine whether we should include cycle detection here or not. +#[derive(Clone,Debug)] +pub enum ProfileQueriesMsg { + /// begin a new query + QueryBegin(Span,QueryMsg), + /// query is satisfied by using an already-known value for the given key + CacheHit, + /// query requires running a provider; providers may nest, permitting queries to nest. + ProviderBegin, + /// query is satisfied by a provider terminating with a value + ProviderEnd, + /// dump a record of the queries to the given path + Dump(String, Sender<()>), + /// stop the profilequeriesmsg service + Halt +} + +// If enabled, send a message to the profile-queries thread +pub fn profq_msg(msg: ProfileQueriesMsg) { + PROFQ_CHAN.with(|sender|{ + if let Some(s) = sender.borrow().as_ref() { + s.send(msg).unwrap() + } else { + panic!("no channel on which to send profq_msg: {:?}", msg) + } + }) +} + +pub fn profq_set_chan(s: Sender) -> bool { + PROFQ_CHAN.with(|chan|{ + let is_none = + if let None = chan.borrow().as_ref() { + true + } else { false } + ; + if is_none { + *chan.borrow_mut() = Some(s); + true + } else { false } + }) +} + /// Read the current depth of `time()` calls. This is used to /// encourage indentation across threads. pub fn time_depth() -> usize { @@ -211,7 +259,7 @@ pub trait MemoizationMap { /// needed in the `op` to ensure that the correct edges are /// added into the dep graph. See the `DepTrackingMap` impl for /// more details! - fn memoize(&self, tcx: TyCtxt, key: Self::Key, op: OP) -> Self::Value + fn memoize(&self, key: Self::Key, op: OP) -> Self::Value where OP: FnOnce() -> Self::Value; } @@ -221,7 +269,7 @@ impl MemoizationMap for RefCell> type Key = K; type Value = V; - fn memoize(&self, _tcx: TyCtxt, key: K, op: OP) -> V + fn memoize(&self, key: K, op: OP) -> V where OP: FnOnce() -> V { let result = self.borrow().get(&key).cloned(); diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index eb6bffc29c561..d9c99ccd50843 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -224,7 +224,7 @@ pub fn parameterized(f: &mut fmt::Formatter, start_or_continue(f, "<", ", ")?; ty::tls::with(|tcx| write!(f, "{}={}", - projection.projection_ty.item_name(tcx), + tcx.associated_item(projection.projection_ty.item_def_id).name, projection.ty) )?; } @@ -958,9 +958,14 @@ impl<'tcx> fmt::Display for ty::ProjectionPredicate<'tcx> { impl<'tcx> fmt::Display for ty::ProjectionTy<'tcx> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let item_name = ty::tls::with(|tcx| self.item_name(tcx)); + // FIXME(tschottdorf): use something like + // parameterized(f, self.substs, self.item_def_id, &[]) + // (which currently ICEs). + let (trait_ref, item_name) = ty::tls::with(|tcx| + (self.trait_ref(tcx), tcx.associated_item(self.item_def_id).name) + ); write!(f, "{:?}::{}", - self.trait_ref, + trait_ref, item_name) } } diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs index 3be7c43cab938..1bfc5805bc8fd 100644 --- a/src/librustc_borrowck/borrowck/mod.rs +++ b/src/librustc_borrowck/borrowck/mod.rs @@ -991,7 +991,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { .span_suggestion(err.span, &format!("to force the closure to take ownership of {} \ (and any other referenced variables), \ - use the `move` keyword, as shown:", + use the `move` keyword", cmt_path_or_string), suggestion) .emit(); diff --git a/src/librustc_const_eval/_match.rs b/src/librustc_const_eval/_match.rs index 98d90188312df..bae44c0047e2e 100644 --- a/src/librustc_const_eval/_match.rs +++ b/src/librustc_const_eval/_match.rs @@ -835,7 +835,7 @@ fn slice_pat_covered_by_constructor(_tcx: TyCtxt, _span: Span, Ok(true) } -fn range_covered_by_constructor(tcx: TyCtxt, span: Span, +fn constructor_covered_by_range(tcx: TyCtxt, span: Span, ctor: &Constructor, from: &ConstVal, to: &ConstVal, end: RangeEnd) @@ -845,14 +845,14 @@ fn range_covered_by_constructor(tcx: TyCtxt, span: Span, match *ctor { ConstantValue(ref value) => { let to = cmp_to(value)?; - let end = (to != Ordering::Greater) || - (end == RangeEnd::Excluded && to == Ordering::Equal); + let end = (to == Ordering::Less) || + (end == RangeEnd::Included && to == Ordering::Equal); Ok(cmp_from(value)? && end) }, ConstantRange(ref from, ref to, RangeEnd::Included) => { let to = cmp_to(to)?; - let end = (to != Ordering::Greater) || - (end == RangeEnd::Excluded && to == Ordering::Equal); + let end = (to == Ordering::Less) || + (end == RangeEnd::Included && to == Ordering::Equal); Ok(cmp_from(from)? && end) }, ConstantRange(ref from, ref to, RangeEnd::Excluded) => { @@ -933,7 +933,7 @@ fn specialize<'p, 'a: 'p, 'tcx: 'a>( "unexpected const-val {:?} with ctor {:?}", value, constructor) }, _ => { - match range_covered_by_constructor( + match constructor_covered_by_range( cx.tcx, pat.span, constructor, value, value, RangeEnd::Included ) { Ok(true) => Some(vec![]), @@ -945,7 +945,7 @@ fn specialize<'p, 'a: 'p, 'tcx: 'a>( } PatternKind::Range { ref lo, ref hi, ref end } => { - match range_covered_by_constructor( + match constructor_covered_by_range( cx.tcx, pat.span, constructor, lo, hi, end.clone() ) { Ok(true) => Some(vec![]), diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index daa5917cf324d..6b76beb76cb51 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -24,7 +24,7 @@ use rustc::middle::privacy::AccessLevels; use rustc::mir::transform::{MIR_CONST, MIR_VALIDATED, MIR_OPTIMIZED, Passes}; use rustc::ty::{self, TyCtxt, Resolutions, GlobalArenas}; use rustc::traits; -use rustc::util::common::{ErrorReported, time}; +use rustc::util::common::{ErrorReported, time, ProfileQueriesMsg, profq_msg}; use rustc::util::nodemap::NodeSet; use rustc::util::fs::rename_or_copy_remove; use rustc_allocator as allocator; @@ -52,6 +52,7 @@ use std::io::{self, Write}; use std::iter; use std::path::{Path, PathBuf}; use std::rc::Rc; + use syntax::{ast, diagnostics, visit}; use syntax::attr; use syntax::ext::base::ExtCtxt; @@ -64,6 +65,8 @@ use arena::DroplessArena; use derive_registrar; +use profile; + pub fn compile_input(sess: &Session, cstore: &CStore, input: &Input, @@ -87,6 +90,10 @@ pub fn compile_input(sess: &Session, }} } + if sess.opts.debugging_opts.profile_queries { + profile::begin(); + } + // We need nested scopes here, because the intermediate results can keep // large chunks of memory alive and we want to free them as soon as // possible to keep the peak memory usage low @@ -503,6 +510,10 @@ pub fn phase_1_parse_input<'a>(sess: &'a Session, input: &Input) -> PResult<'a, let continue_after_error = sess.opts.debugging_opts.continue_parse_after_error; sess.diagnostic().set_continue_after_error(continue_after_error); + if sess.opts.debugging_opts.profile_queries { + profile::begin(); + } + let krate = time(sess.time_passes(), "parsing", || { match *input { Input::File(ref file) => { @@ -972,6 +983,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session, index, name, |tcx| { + let incremental_hashes_map = time(time_passes, "compute_incremental_hashes_map", @@ -1078,6 +1090,14 @@ pub fn phase_4_translate_to_llvm<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, &incremental_hashes_map, &translation.metadata.hashes, translation.link.crate_hash)); + + if tcx.sess.opts.debugging_opts.profile_queries { + use std::sync::mpsc::{channel}; + let (tx, rx) = channel(); + profq_msg(ProfileQueriesMsg::Dump("profile_queries".to_string(), tx)); + let _ = rx.recv().unwrap(); + } + translation } diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 1f9f6aad90536..4b63b37f6c75f 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -105,6 +105,7 @@ use syntax_pos::{DUMMY_SP, MultiSpan}; pub mod test; pub mod driver; +pub mod profile; pub mod pretty; pub mod target_features; mod derive_registrar; diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs index d40a2ab0b5309..269363fdd2f98 100644 --- a/src/librustc_driver/pretty.rs +++ b/src/librustc_driver/pretty.rs @@ -30,7 +30,7 @@ use rustc_mir::util::{write_mir_pretty, write_mir_graphviz}; use syntax::ast::{self, BlockCheckMode}; use syntax::fold::{self, Folder}; -use syntax::print::{pp, pprust}; +use syntax::print::{pprust}; use syntax::print::pprust::PrintState; use syntax::ptr::P; use syntax::util::small_vector::SmallVector; @@ -163,13 +163,12 @@ pub fn parse_pretty(sess: &Session, impl PpSourceMode { /// Constructs a `PrinterSupport` object and passes it to `f`. - fn call_with_pp_support<'tcx, A, B, F>(&self, + fn call_with_pp_support<'tcx, A, F>(&self, sess: &'tcx Session, hir_map: Option<&hir_map::Map<'tcx>>, - payload: B, f: F) -> A - where F: FnOnce(&PrinterSupport, B) -> A + where F: FnOnce(&PrinterSupport) -> A { match *self { PpmNormal | PpmEveryBodyLoops | PpmExpanded => { @@ -177,7 +176,7 @@ impl PpSourceMode { sess: sess, hir_map: hir_map.map(|m| m.clone()), }; - f(&annotation, payload) + f(&annotation) } PpmIdentified | PpmExpandedIdentified => { @@ -185,18 +184,18 @@ impl PpSourceMode { sess: sess, hir_map: hir_map.map(|m| m.clone()), }; - f(&annotation, payload) + f(&annotation) } PpmExpandedHygiene => { let annotation = HygieneAnnotation { sess: sess, }; - f(&annotation, payload) + f(&annotation) } _ => panic!("Should use call_with_pp_support_hir"), } } - fn call_with_pp_support_hir<'tcx, A, B, F>(&self, + fn call_with_pp_support_hir<'tcx, A, F>(&self, sess: &'tcx Session, hir_map: &hir_map::Map<'tcx>, analysis: &ty::CrateAnalysis, @@ -204,10 +203,9 @@ impl PpSourceMode { arena: &'tcx DroplessArena, arenas: &'tcx GlobalArenas<'tcx>, id: &str, - payload: B, f: F) -> A - where F: FnOnce(&HirPrinterSupport, B, &hir::Crate) -> A + where F: FnOnce(&HirPrinterSupport, &hir::Crate) -> A { match *self { PpmNormal => { @@ -215,7 +213,7 @@ impl PpSourceMode { sess: sess, hir_map: Some(hir_map.clone()), }; - f(&annotation, payload, hir_map.forest.krate()) + f(&annotation, hir_map.forest.krate()) } PpmIdentified => { @@ -223,7 +221,7 @@ impl PpSourceMode { sess: sess, hir_map: Some(hir_map.clone()), }; - f(&annotation, payload, hir_map.forest.krate()) + f(&annotation, hir_map.forest.krate()) } PpmTyped => { abort_on_err(driver::phase_3_run_analysis_passes(sess, @@ -240,7 +238,7 @@ impl PpSourceMode { tables: Cell::new(&empty_tables) }; let _ignore = tcx.dep_graph.in_ignore(); - f(&annotation, payload, hir_map.forest.krate()) + f(&annotation, hir_map.forest.krate()) }), sess) } @@ -357,24 +355,24 @@ impl<'hir> pprust::PpAnn for IdentifiedAnnotation<'hir> { pprust::NodeName(_) => Ok(()), pprust::NodeItem(item) => { - pp::space(&mut s.s)?; + s.s.space()?; s.synth_comment(item.id.to_string()) } pprust::NodeSubItem(id) => { - pp::space(&mut s.s)?; + s.s.space()?; s.synth_comment(id.to_string()) } pprust::NodeBlock(blk) => { - pp::space(&mut s.s)?; + s.s.space()?; s.synth_comment(format!("block {}", blk.id)) } pprust::NodeExpr(expr) => { - pp::space(&mut s.s)?; + s.s.space()?; s.synth_comment(expr.id.to_string())?; s.pclose() } pprust::NodePat(pat) => { - pp::space(&mut s.s)?; + s.s.space()?; s.synth_comment(format!("pat {}", pat.id)) } } @@ -414,24 +412,24 @@ impl<'hir> pprust_hir::PpAnn for IdentifiedAnnotation<'hir> { match node { pprust_hir::NodeName(_) => Ok(()), pprust_hir::NodeItem(item) => { - pp::space(&mut s.s)?; + s.s.space()?; s.synth_comment(item.id.to_string()) } pprust_hir::NodeSubItem(id) => { - pp::space(&mut s.s)?; + s.s.space()?; s.synth_comment(id.to_string()) } pprust_hir::NodeBlock(blk) => { - pp::space(&mut s.s)?; + s.s.space()?; s.synth_comment(format!("block {}", blk.id)) } pprust_hir::NodeExpr(expr) => { - pp::space(&mut s.s)?; + s.s.space()?; s.synth_comment(expr.id.to_string())?; s.pclose() } pprust_hir::NodePat(pat) => { - pp::space(&mut s.s)?; + s.s.space()?; s.synth_comment(format!("pat {}", pat.id)) } } @@ -456,13 +454,13 @@ impl<'a> pprust::PpAnn for HygieneAnnotation<'a> { fn post(&self, s: &mut pprust::State, node: pprust::AnnNode) -> io::Result<()> { match node { pprust::NodeIdent(&ast::Ident { name, ctxt }) => { - pp::space(&mut s.s)?; + s.s.space()?; // FIXME #16420: this doesn't display the connections // between syntax contexts s.synth_comment(format!("{}{:?}", name.as_u32(), ctxt)) } pprust::NodeName(&name) => { - pp::space(&mut s.s)?; + s.s.space()?; s.synth_comment(name.as_u32().to_string()) } _ => Ok(()), @@ -514,10 +512,10 @@ impl<'a, 'tcx> pprust_hir::PpAnn for TypedAnnotation<'a, 'tcx> { fn post(&self, s: &mut pprust_hir::State, node: pprust_hir::AnnNode) -> io::Result<()> { match node { pprust_hir::NodeExpr(expr) => { - pp::space(&mut s.s)?; - pp::word(&mut s.s, "as")?; - pp::space(&mut s.s)?; - pp::word(&mut s.s, &self.tables.get().expr_ty(expr).to_string())?; + s.s.space()?; + s.s.word("as")?; + s.s.space()?; + s.s.word(&self.tables.get().expr_ty(expr).to_string())?; s.pclose() } _ => Ok(()), @@ -825,7 +823,7 @@ pub fn print_after_parsing(sess: &Session, if let PpmSource(s) = ppm { // Silently ignores an identified node. let out: &mut Write = &mut out; - s.call_with_pp_support(sess, None, box out, |annotation, out| { + s.call_with_pp_support(sess, None, move |annotation| { debug!("pretty printing source code {:?}", s); let sess = annotation.sess(); pprust::print_crate(sess.codemap(), @@ -833,7 +831,7 @@ pub fn print_after_parsing(sess: &Session, krate, src_name.to_string(), &mut rdr, - out, + box out, annotation.pp_ann(), false) }) @@ -883,7 +881,7 @@ pub fn print_after_hir_lowering<'tcx, 'a: 'tcx>(sess: &'a Session, (PpmSource(s), _) => { // Silently ignores an identified node. let out: &mut Write = &mut out; - s.call_with_pp_support(sess, Some(hir_map), box out, |annotation, out| { + s.call_with_pp_support(sess, Some(hir_map), move |annotation| { debug!("pretty printing source code {:?}", s); let sess = annotation.sess(); pprust::print_crate(sess.codemap(), @@ -891,7 +889,7 @@ pub fn print_after_hir_lowering<'tcx, 'a: 'tcx>(sess: &'a Session, krate, src_name.to_string(), &mut rdr, - out, + box out, annotation.pp_ann(), true) }) @@ -906,8 +904,7 @@ pub fn print_after_hir_lowering<'tcx, 'a: 'tcx>(sess: &'a Session, arena, arenas, crate_name, - box out, - |annotation, out, krate| { + move |annotation, krate| { debug!("pretty printing source code {:?}", s); let sess = annotation.sess(); pprust_hir::print_crate(sess.codemap(), @@ -915,7 +912,7 @@ pub fn print_after_hir_lowering<'tcx, 'a: 'tcx>(sess: &'a Session, krate, src_name.to_string(), &mut rdr, - out, + box out, annotation.pp_ann(), true) }) @@ -930,8 +927,7 @@ pub fn print_after_hir_lowering<'tcx, 'a: 'tcx>(sess: &'a Session, arena, arenas, crate_name, - (out, uii), - |annotation, (out, uii), _| { + move |annotation, _| { debug!("pretty printing source code {:?}", s); let sess = annotation.sess(); let hir_map = annotation.hir_map().expect("--unpretty missing HIR map"); @@ -945,13 +941,13 @@ pub fn print_after_hir_lowering<'tcx, 'a: 'tcx>(sess: &'a Session, for node_id in uii.all_matching_node_ids(hir_map) { let node = hir_map.get(node_id); pp_state.print_node(node)?; - pp::space(&mut pp_state.s)?; + pp_state.s.space()?; let path = annotation.node_path(node_id) .expect("--unpretty missing node paths"); pp_state.synth_comment(path)?; - pp::hardbreak(&mut pp_state.s)?; + pp_state.s.hardbreak()?; } - pp::eof(&mut pp_state.s) + pp_state.s.eof() }) } _ => unreachable!(), diff --git a/src/librustc_driver/profile/mod.rs b/src/librustc_driver/profile/mod.rs new file mode 100644 index 0000000000000..fce279e5182a8 --- /dev/null +++ b/src/librustc_driver/profile/mod.rs @@ -0,0 +1,167 @@ +// 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. + +use rustc::util::common::{ProfileQueriesMsg,profq_set_chan}; +use std::sync::mpsc::{Receiver}; +use std::io::{Write}; + +pub mod trace; + +// begin a thread, if not already running +pub fn begin() { + use std::thread; + use std::sync::mpsc::{channel}; + let (tx, rx) = channel(); + if profq_set_chan(tx) { + thread::spawn(move||profile_queries_thread(rx)); + } +} + +// profiling thread; retains state (in local variables) and dump traces, upon request. +fn profile_queries_thread(r:Receiver) { + use self::trace::*; + use std::fs::File; + use std::time::{Instant}; + + let mut queries : Vec = vec![]; + let mut frame : StackFrame = StackFrame{ parse_st:ParseState::NoQuery, traces:vec![] }; + let mut stack : Vec = vec![]; + loop { + let msg = r.recv(); + if let Err(_recv_err) = msg { + // FIXME: Perhaps do something smarter than simply quitting? + break + }; + let msg = msg.unwrap(); + debug!("profile_queries_thread: {:?}", msg); + + // Meta-level versus _actual_ queries messages + match msg { + ProfileQueriesMsg::Halt => return, + ProfileQueriesMsg::Dump(path, ack) => { + assert!(stack.len() == 0); + assert!(frame.parse_st == trace::ParseState::NoQuery); + { + // write log + if false { + let mut queries_file = File::create(format!("{}.log.txt", path)).unwrap(); + for q in queries.iter() { + writeln!(&mut queries_file, "{:?}", q).unwrap() + }; + } + + // write HTML file, and counts file + let html_path = format!("{}.html", path); + let mut html_file = File::create(&html_path).unwrap(); + + let counts_path = format!("{}.counts.txt", path); + let mut counts_file = File::create(&counts_path).unwrap(); + + write!(html_file, "\n").unwrap(); + write!(html_file, + "\n\n", + "profile_queries.css").unwrap(); + write!(html_file, "\n").unwrap(); + write!(html_file, "\n").unwrap(); + write!(html_file, "\n").unwrap(); + trace::write_traces(&mut html_file, &mut counts_file, &frame.traces); + write!(html_file, "\n\n").unwrap(); + + ack.send(()).unwrap(); + } + continue + } + // Actual query message: + msg => { + queries.push(msg.clone()); + match (frame.parse_st.clone(), msg) { + (_,ProfileQueriesMsg::Halt) => unreachable!(), + (_,ProfileQueriesMsg::Dump(_,_)) => unreachable!(), + + // Parse State: NoQuery + (ParseState::NoQuery, + ProfileQueriesMsg::QueryBegin(span,querymsg)) => { + let start = Instant::now(); + frame.parse_st = ParseState::HaveQuery + (Query{span:span, msg:querymsg}, start) + }, + (ParseState::NoQuery, + ProfileQueriesMsg::CacheHit) => { + panic!("parse error: unexpected CacheHit; expected QueryBegin") + }, + (ParseState::NoQuery, + ProfileQueriesMsg::ProviderBegin) => { + panic!("parse error: expected QueryBegin before beginning a provider") + }, + (ParseState::NoQuery, + ProfileQueriesMsg::ProviderEnd) => { + let provider_extent = frame.traces; + match stack.pop() { + None => + panic!("parse error: expected a stack frame; found an empty stack"), + Some(old_frame) => { + match old_frame.parse_st { + ParseState::NoQuery => + panic!("parse error: expected a stack frame for a query"), + ParseState::HaveQuery(q,start) => { + let duration = start.elapsed(); + frame = StackFrame{ + parse_st:ParseState::NoQuery, + traces:old_frame.traces + }; + let trace = Rec { + effect: Effect::QueryBegin(q, CacheCase::Miss), + extent: Box::new(provider_extent), + start: start, + duration: duration, + }; + frame.traces.push( trace ); + } + } + } + } + } + + // Parse State: HaveQuery + (ParseState::HaveQuery(q,start), + ProfileQueriesMsg::CacheHit) => { + let duration = start.elapsed(); + let trace : Rec = Rec{ + effect: Effect::QueryBegin(q, CacheCase::Hit), + extent: Box::new(vec![]), + start: start, + duration: duration, + }; + frame.traces.push( trace ); + frame.parse_st = ParseState::NoQuery; + }, + (ParseState::HaveQuery(_,_), + ProfileQueriesMsg::ProviderBegin) => { + stack.push(frame); + frame = StackFrame{parse_st:ParseState::NoQuery, traces:vec![]}; + }, + (ParseState::HaveQuery(q,_), + ProfileQueriesMsg::ProviderEnd) => { + panic!("parse error: unexpected ProviderEnd; +expected something else to follow BeginQuery for {:?}", q) + }, + (ParseState::HaveQuery(q1,_), + ProfileQueriesMsg::QueryBegin(span2,querymsg2)) => { + panic!("parse error: unexpected QueryBegin; +earlier query is unfinished: {:?} and now {:?}", + q1, Query{span:span2, msg:querymsg2}) + }, + } + } + } + } +} diff --git a/src/librustc_driver/profile/trace.rs b/src/librustc_driver/profile/trace.rs new file mode 100644 index 0000000000000..9d5dde3188f37 --- /dev/null +++ b/src/librustc_driver/profile/trace.rs @@ -0,0 +1,246 @@ +// 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. + +use super::*; +use syntax_pos::Span; +use rustc::ty::maps::QueryMsg; +use std::fs::File; +use std::time::{Duration, Instant}; +use std::collections::hash_map::HashMap; + +#[derive(Debug, Clone, Eq, PartialEq)] +pub struct Query { + pub span: Span, + pub msg: QueryMsg, +} +pub enum Effect { + QueryBegin(Query, CacheCase), +} +pub enum CacheCase { + Hit, Miss +} +/// Recursive trace structure +pub struct Rec { + pub effect: Effect, + pub start: Instant, + pub duration: Duration, + pub extent: Box>, +} +/// State for parsing recursive trace structure +#[derive(Clone, Eq, PartialEq)] +pub enum ParseState { + NoQuery, + HaveQuery(Query, Instant), +} +pub struct StackFrame { + pub parse_st: ParseState, + pub traces: Vec, +} +pub struct QueryMetric { + pub count: usize, + pub duration: Duration, +} + +pub fn cons_of_query_msg(q: &trace::Query) -> String { + let s = format!("{:?}", q.msg); + let cons: Vec<&str> = s.split(|d| d == '(' || d == '{').collect(); + assert!(cons.len() > 0 && cons[0] != ""); + cons[0].to_string() +} + +// First return value is text; second return value is a CSS class +pub fn html_of_effect(eff: &Effect) -> (String, String) { + match *eff { + Effect::QueryBegin(ref qmsg, ref cc) => { + let cons = cons_of_query_msg(qmsg); + (cons.clone(), + format!("{} {}", + cons, + match *cc { + CacheCase::Hit => "hit", + CacheCase::Miss => "miss", + })) + } + } +} + +// First return value is text; second return value is a CSS class +fn html_of_duration(_start: &Instant, dur: &Duration) -> (String, String) { + use rustc::util::common::duration_to_secs_str; + (duration_to_secs_str(dur.clone()), + "".to_string() + ) +} + +fn html_of_fraction(frac: f64) -> (String, String) { + let css = { + if frac > 0.50 { format!("frac-50") } + else if frac > 0.40 { format!("frac-40") } + else if frac > 0.30 { format!("frac-30") } + else if frac > 0.20 { format!("frac-20") } + else if frac > 0.10 { format!("frac-10") } + else if frac > 0.05 { format!("frac-05") } + else if frac > 0.02 { format!("frac-02") } + else if frac > 0.01 { format!("frac-01") } + else if frac > 0.001 { format!("frac-001") } + else { format!("frac-0") } + }; + let percent = frac * 100 as f64; + if percent > 0.1 as f64 { (format!("{:.1}%", percent), css) } + else { (format!("< 0.1%", ), css) } +} + +fn total_duration(traces: &Vec) -> Duration { + let mut sum : Duration = Duration::new(0,0); + for t in traces.iter() { + sum += t.duration; + } + return sum +} + +fn duration_div(nom: Duration, den: Duration) -> f64 { + let nom_sec = nom.as_secs(); + let den_sec = den.as_secs(); + let nom_nanos = nom.subsec_nanos(); + let den_nanos = den.subsec_nanos(); + if nom_sec == den_sec { + if nom_sec == 0 { + nom_nanos as f64 / den_nanos as f64 + } else { + panic!("FIXME(matthewhammer)") + } + } else { + panic!("FIXME(matthewhammer)") + } +} + +fn write_traces_rec(file: &mut File, traces: &Vec, total: Duration, depth: usize) { + for t in traces { + let (eff_text, eff_css_classes) = html_of_effect(&t.effect); + let (dur_text, dur_css_classes) = html_of_duration(&t.start, &t.duration); + let fraction = duration_div(t.duration, total); + let percent = fraction * 100 as f64; + let (frc_text, frc_css_classes) = html_of_fraction(fraction); + write!(file, "

\n", + depth, + t.extent.len(), + /* Heuristic for 'important' CSS class: */ + if t.extent.len() > 5 || percent >= 1.0 as f64 { + " important" } + else { "" }, + eff_css_classes, + dur_css_classes, + frc_css_classes, + ).unwrap(); + write!(file, "
{}
\n", eff_text).unwrap(); + write!(file, "
{}
\n", dur_text).unwrap(); + write!(file, "
{}
\n", frc_text).unwrap(); + write_traces_rec(file, &t.extent, total, depth + 1); + write!(file, "
\n").unwrap(); + } +} + +fn compute_counts_rec(counts: &mut HashMap, traces: &Vec) { + for t in traces.iter() { + match t.effect { + Effect::QueryBegin(ref qmsg, ref _cc) => { + let qcons = cons_of_query_msg(qmsg); + let qm = match counts.get(&qcons) { + Some(qm) => + QueryMetric{ + count: qm.count + 1, + duration: qm.duration + t.duration + }, + None => QueryMetric{ + count: 1, + duration: t.duration + } + }; + counts.insert(qcons, qm); + } + } + compute_counts_rec(counts, &t.extent) + } +} + +pub fn write_counts(count_file: &mut File, counts: &mut HashMap) { + use rustc::util::common::duration_to_secs_str; + use std::cmp::Ordering; + + let mut data = vec![]; + for (ref cons, ref qm) in counts.iter() { + data.push((cons.clone(), qm.count.clone(), qm.duration.clone())); + }; + data.sort_by(|&(_,_,d1),&(_,_,d2)| + if d1 > d2 { Ordering::Less } else { Ordering::Greater } ); + for (cons, count, duration) in data { + write!(count_file, "{},{},{}\n", + cons, count, duration_to_secs_str(duration) + ).unwrap(); + } +} + +pub fn write_traces(html_file: &mut File, counts_file: &mut File, traces: &Vec) { + let mut counts : HashMap = HashMap::new(); + compute_counts_rec(&mut counts, traces); + write_counts(counts_file, &mut counts); + + let total : Duration = total_duration(traces); + write_traces_rec(html_file, traces, total, 0) +} + +pub fn write_style(html_file: &mut File) { + write!(html_file,"{}", " +body { + font-family: sans-serif; + background: black; +} +.trace { + color: black; + display: inline-block; + border-style: solid; + border-color: red; + border-width: 1px; + border-radius: 5px; + padding: 0px; + margin: 1px; + font-size: 0px; +} +.miss { + border-color: red; + border-width: 1px; +} +.extent-0 { + padding: 2px; +} +.important { + border-width: 3px; + font-size: 12px; + color: white; + border-color: #f77; +} +.hit { + padding: 0px; + border-color: blue; + border-width: 3px; +} +.eff { + color: #fff; + display: inline-block; +} +.frc { + color: #7f7; + display: inline-block; +} +.dur { + display: none +} +").unwrap(); +} diff --git a/src/librustc_errors/diagnostic.rs b/src/librustc_errors/diagnostic.rs index d7c21127474a4..ee07b6e909f7d 100644 --- a/src/librustc_errors/diagnostic.rs +++ b/src/librustc_errors/diagnostic.rs @@ -211,6 +211,18 @@ impl Diagnostic { /// Prints out a message with a suggested edit of the code. /// + /// In case of short messages and a simple suggestion, + /// rustc displays it as a label like + /// + /// "try adding parentheses: `(tup.0).1`" + /// + /// The message + /// * should not end in any punctuation (a `:` is added automatically) + /// * should not be a question + /// * should not contain any parts like "the following", "as shown" + /// * may look like "to do xyz, use" or "to do xyz, use abc" + /// * may contain a name of a function, variable or type, but not whole expressions + /// /// See `diagnostic::CodeSuggestion` for more information. pub fn span_suggestion(&mut self, sp: Span, msg: &str, suggestion: String) -> &mut Self { self.suggestions.push(CodeSuggestion { diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs index 2aea6d125f201..3e8bd093f4f93 100644 --- a/src/librustc_errors/emitter.rs +++ b/src/librustc_errors/emitter.rs @@ -51,7 +51,7 @@ impl Emitter for EmitterWriter { // This substitution is only removal, don't show it format!("help: {}", sugg.msg) } else { - format!("help: {} `{}`", sugg.msg, substitution) + format!("help: {}: `{}`", sugg.msg, substitution) }; primary_span.push_span_label(sugg.substitution_spans().next().unwrap(), msg); } else { diff --git a/src/librustc_incremental/persist/load.rs b/src/librustc_incremental/persist/load.rs index 586bb79e596e1..2c43896ec73d2 100644 --- a/src/librustc_incremental/persist/load.rs +++ b/src/librustc_incremental/persist/load.rs @@ -189,7 +189,8 @@ pub fn decode_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, &serialized_dep_graph.nodes, &dirty_raw_nodes, &mut clean_work_products, - &mut dirty_work_products); + &mut dirty_work_products, + &work_products); } } @@ -201,11 +202,7 @@ pub fn decode_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, clean_work_products.insert(wp_id); } - tcx.dep_graph.with_task(*bootstrap_output, (), (), create_node); - - fn create_node((): (), (): ()) { - // just create the node with no inputs - } + tcx.dep_graph.add_node_directly(*bootstrap_output); } // Add in work-products that are still clean, and delete those that are @@ -394,7 +391,8 @@ fn process_edge<'a, 'tcx, 'edges>( nodes: &IndexVec, dirty_raw_nodes: &DirtyNodes, clean_work_products: &mut FxHashSet, - dirty_work_products: &mut FxHashSet) + dirty_work_products: &mut FxHashSet, + work_products: &[SerializedWorkProduct]) { // If the target is dirty, skip the edge. If this is an edge // that targets a work-product, we can print the blame @@ -418,9 +416,11 @@ fn process_edge<'a, 'tcx, 'edges>( format!("{:?}", blame) }; - eprintln!("incremental: module {:?} is dirty because {:?} \ - changed or was removed", - wp_id, + let wp = work_products.iter().find(|swp| swp.id == wp_id).unwrap(); + + eprintln!("incremental: module {:?} is dirty because \ + {:?} changed or was removed", + wp.work_product.cgu_name, blame_str); } } @@ -449,8 +449,7 @@ fn process_edge<'a, 'tcx, 'edges>( if !dirty_raw_nodes.contains_key(&target) { let target = nodes[target]; let source = nodes[source]; - let _task = tcx.dep_graph.in_task(target); - tcx.dep_graph.read(source); + tcx.dep_graph.add_edge_directly(source, target); if let DepKind::WorkProduct = target.kind { let wp_id = WorkProductId::from_fingerprint(target.hash); @@ -458,4 +457,3 @@ fn process_edge<'a, 'tcx, 'edges>( } } } - diff --git a/src/librustc_incremental/persist/work_product.rs b/src/librustc_incremental/persist/work_product.rs index 16ab10ab4bbbd..8f99ce91a67a9 100644 --- a/src/librustc_incremental/persist/work_product.rs +++ b/src/librustc_incremental/persist/work_product.rs @@ -55,6 +55,7 @@ pub fn save_trans_partition(sess: &Session, }; let work_product = WorkProduct { + cgu_name: cgu_name.to_string(), input_hash: partition_hash, saved_files: saved_files, }; diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs index a03f12c3dfbca..21dca7f6c61c4 100644 --- a/src/librustc_lint/lib.rs +++ b/src/librustc_lint/lib.rs @@ -235,7 +235,11 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) { FutureIncompatibleInfo { id: LintId::of(PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES), reference: "issue #42238 ", - } + }, + FutureIncompatibleInfo { + id: LintId::of(LATE_BOUND_LIFETIME_ARGUMENTS), + reference: "issue #42868 ", + }, ]); // Register renamed and removed lints diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index ac39da48ac1fc..d15843b4f318b 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -856,21 +856,48 @@ impl<'a> CrateLoader<'a> { return } - if !self.sess.crate_types.borrow().iter().all(|ct| { - match *ct { - // Link the runtime - config::CrateTypeExecutable => true, - // This crate will be compiled with the required - // instrumentation pass - config::CrateTypeRlib => false, - _ => { - self.sess.err(&format!("Only executables and rlibs can be \ - compiled with `-Z sanitizer`")); - false + // firstyear 2017 - during testing I was unable to access an OSX machine + // to make this work on different crate types. As a result, today I have + // only been able to test and support linux as a target. + if self.sess.target.target.llvm_target == "x86_64-unknown-linux-gnu" { + if !self.sess.crate_types.borrow().iter().all(|ct| { + match *ct { + // Link the runtime + config::CrateTypeStaticlib | + config::CrateTypeExecutable => true, + // This crate will be compiled with the required + // instrumentation pass + config::CrateTypeRlib | + config::CrateTypeDylib | + config::CrateTypeCdylib => + false, + _ => { + self.sess.err(&format!("Only executables, staticlibs, \ + cdylibs, dylibs and rlibs can be compiled with \ + `-Z sanitizer`")); + false + } } + }) { + return + } + } else { + if !self.sess.crate_types.borrow().iter().all(|ct| { + match *ct { + // Link the runtime + config::CrateTypeExecutable => true, + // This crate will be compiled with the required + // instrumentation pass + config::CrateTypeRlib => false, + _ => { + self.sess.err(&format!("Only executables and rlibs can be \ + compiled with `-Z sanitizer`")); + false + } + } + }) { + return } - }) { - return } let mut uses_std = false; @@ -890,7 +917,7 @@ impl<'a> CrateLoader<'a> { info!("loading sanitizer: {}", name); let symbol = Symbol::intern(name); - let dep_kind = DepKind::Implicit; + let dep_kind = DepKind::Explicit; let (_, data) = self.resolve_crate(&None, symbol, symbol, None, DUMMY_SP, PathKind::Crate, dep_kind); @@ -900,6 +927,8 @@ impl<'a> CrateLoader<'a> { self.sess.err(&format!("the crate `{}` is not a sanitizer runtime", name)); } + } else { + self.sess.err(&format!("Must link std to be compiled with `-Z sanitizer`")); } } } diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index 86db6fa1f90ce..4bdfdd51f659a 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -12,7 +12,7 @@ use cstore; use encoder; use schema; -use rustc::dep_graph::DepTrackingMapConfig; +use rustc::ty::maps::QueryConfig; use rustc::middle::cstore::{CrateStore, CrateSource, LibSource, DepKind, NativeLibrary, MetadataLoader, LinkMeta, LinkagePreference, LoadedMacro, EncodedMetadata}; @@ -45,7 +45,7 @@ macro_rules! provide { pub fn provide<$lt>(providers: &mut Providers<$lt>) { $(fn $name<'a, $lt:$lt>($tcx: TyCtxt<'a, $lt, $lt>, $def_id: DefId) -> as - DepTrackingMapConfig>::Value { + QueryConfig>::Value { assert!(!$def_id.is_local()); let def_path_hash = $tcx.def_path_hash($def_id); diff --git a/src/librustc_metadata/locator.rs b/src/librustc_metadata/locator.rs index ff74698deab3f..9bcf590eb8bb3 100644 --- a/src/librustc_metadata/locator.rs +++ b/src/librustc_metadata/locator.rs @@ -242,7 +242,7 @@ use std::io::{self, Read}; use std::path::{Path, PathBuf}; use std::time::Instant; -use flate2::read::ZlibDecoder; +use flate2::read::DeflateDecoder; use owning_ref::{ErasedBoxRef, OwningRef}; pub struct CrateMismatch { @@ -862,7 +862,7 @@ fn get_metadata_section_imp(target: &Target, let compressed_bytes = &buf[header_len..]; debug!("inflating {} bytes of compressed metadata", compressed_bytes.len()); let mut inflated = Vec::new(); - match ZlibDecoder::new(compressed_bytes).read_to_end(&mut inflated) { + match DeflateDecoder::new(compressed_bytes).read_to_end(&mut inflated) { Ok(_) => { let buf = unsafe { OwningRef::new_assert_stable_address(inflated) }; buf.map_owner_box().erase_owner() diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs index 5f80c7bee1478..d3fee8045e6e3 100644 --- a/src/librustc_mir/transform/inline.rs +++ b/src/librustc_mir/transform/inline.rs @@ -250,7 +250,7 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> { work_list.push(target); // If the location doesn't actually need dropping, treat it like // a regular goto. - let ty = location.ty(&callee_mir, tcx).subst(tcx, callsite.substs); + let ty = location.ty(callee_mir, tcx).subst(tcx, callsite.substs); let ty = ty.to_ty(tcx); if ty.needs_drop(tcx, param_env) { cost += CALL_PENALTY; diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index 72c7b92fe6e30..99a49dbd7d732 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_passes/ast_validation.rs @@ -127,18 +127,9 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } ExprKind::MethodCall(ref segment, ..) => { if let Some(ref params) = segment.parameters { - match **params { - PathParameters::AngleBracketed(ref param_data) => { - if !param_data.bindings.is_empty() { - let binding_span = param_data.bindings[0].span; - self.err_handler().span_err(binding_span, - "type bindings cannot be used in method calls"); - } - } - PathParameters::Parenthesized(..) => { - self.err_handler().span_err(expr.span, - "parenthesized parameters cannot be used on method calls"); - } + if let PathParameters::Parenthesized(..) = **params { + self.err_handler().span_err(expr.span, + "parenthesized parameters cannot be used on method calls"); } } } diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 4a74a9e524d0c..64af24d92eecb 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -89,7 +89,7 @@ impl<'a, 'tcx> EmbargoVisitor<'a, 'tcx> { ty::TyAdt(adt, _) => adt.did, ty::TyDynamic(ref obj, ..) if obj.principal().is_some() => obj.principal().unwrap().def_id(), - ty::TyProjection(ref proj) => proj.trait_ref.def_id, + ty::TyProjection(ref proj) => proj.trait_ref(self.tcx).def_id, _ => return Some(AccessLevel::Public) }; if let Some(node_id) = self.tcx.hir.as_local_node_id(ty_def_id) { @@ -395,7 +395,22 @@ impl<'b, 'a, 'tcx> ReachEverythingInTheInterfaceVisitor<'b, 'a, 'tcx> { } fn predicates(&mut self) -> &mut Self { - self.ev.tcx.predicates_of(self.item_def_id).visit_with(self); + let predicates = self.ev.tcx.predicates_of(self.item_def_id); + for predicate in &predicates.predicates { + predicate.visit_with(self); + match predicate { + &ty::Predicate::Trait(poly_predicate) => { + self.check_trait_ref(poly_predicate.skip_binder().trait_ref); + }, + &ty::Predicate::Projection(poly_predicate) => { + let tcx = self.ev.tcx; + self.check_trait_ref( + poly_predicate.skip_binder().projection_ty.trait_ref(tcx) + ); + }, + _ => (), + }; + } self } @@ -411,9 +426,19 @@ impl<'b, 'a, 'tcx> ReachEverythingInTheInterfaceVisitor<'b, 'a, 'tcx> { } fn impl_trait_ref(&mut self) -> &mut Self { - self.ev.tcx.impl_trait_ref(self.item_def_id).visit_with(self); + if let Some(impl_trait_ref) = self.ev.tcx.impl_trait_ref(self.item_def_id) { + self.check_trait_ref(impl_trait_ref); + impl_trait_ref.super_visit_with(self); + } self } + + fn check_trait_ref(&mut self, trait_ref: ty::TraitRef<'tcx>) { + if let Some(node_id) = self.ev.tcx.hir.as_local_node_id(trait_ref.def_id) { + let item = self.ev.tcx.hir.expect_item(node_id); + self.ev.update(item.id, Some(AccessLevel::Reachable)); + } + } } impl<'b, 'a, 'tcx> TypeVisitor<'tcx> for ReachEverythingInTheInterfaceVisitor<'b, 'a, 'tcx> { @@ -421,7 +446,7 @@ impl<'b, 'a, 'tcx> TypeVisitor<'tcx> for ReachEverythingInTheInterfaceVisitor<'b let ty_def_id = match ty.sty { ty::TyAdt(adt, _) => Some(adt.did), ty::TyDynamic(ref obj, ..) => obj.principal().map(|p| p.def_id()), - ty::TyProjection(ref proj) => Some(proj.trait_ref.def_id), + ty::TyProjection(ref proj) => Some(proj.item_def_id), ty::TyFnDef(def_id, ..) | ty::TyAnon(def_id, _) => Some(def_id), _ => None @@ -435,15 +460,6 @@ impl<'b, 'a, 'tcx> TypeVisitor<'tcx> for ReachEverythingInTheInterfaceVisitor<'b ty.super_visit_with(self) } - - fn visit_trait_ref(&mut self, trait_ref: ty::TraitRef<'tcx>) -> bool { - if let Some(node_id) = self.ev.tcx.hir.as_local_node_id(trait_ref.def_id) { - let item = self.ev.tcx.hir.expect_item(node_id); - self.ev.update(item.id, Some(AccessLevel::Reachable)); - } - - trait_ref.super_visit_with(self) - } } ////////////////////////////////////////////////////////////////////////////////////// @@ -633,14 +649,42 @@ impl<'a, 'tcx> TypePrivacyVisitor<'a, 'tcx> { } fn predicates(&mut self) -> &mut Self { - self.tcx.predicates_of(self.current_item).visit_with(self); + let predicates = self.tcx.predicates_of(self.current_item); + for predicate in &predicates.predicates { + predicate.visit_with(self); + match predicate { + &ty::Predicate::Trait(poly_predicate) => { + self.check_trait_ref(poly_predicate.skip_binder().trait_ref); + }, + &ty::Predicate::Projection(poly_predicate) => { + let tcx = self.tcx; + self.check_trait_ref( + poly_predicate.skip_binder().projection_ty.trait_ref(tcx) + ); + }, + _ => (), + }; + } self } fn impl_trait_ref(&mut self) -> &mut Self { - self.tcx.impl_trait_ref(self.current_item).visit_with(self); + if let Some(impl_trait_ref) = self.tcx.impl_trait_ref(self.current_item) { + self.check_trait_ref(impl_trait_ref); + } + self.tcx.predicates_of(self.current_item).visit_with(self); self } + + fn check_trait_ref(&mut self, trait_ref: ty::TraitRef<'tcx>) -> bool { + if !self.item_is_accessible(trait_ref.def_id) { + let msg = format!("trait `{}` is private", trait_ref); + self.tcx.sess.span_err(self.span, &msg); + return true; + } + + trait_ref.super_visit_with(self) + } } impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> { @@ -817,7 +861,8 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> { let is_private = predicates.skip_binder().iter().any(|predicate| { let def_id = match *predicate { ty::ExistentialPredicate::Trait(trait_ref) => trait_ref.def_id, - ty::ExistentialPredicate::Projection(proj) => proj.trait_ref.def_id, + ty::ExistentialPredicate::Projection(proj) => + proj.trait_ref(self.tcx).def_id, ty::ExistentialPredicate::AutoTrait(def_id) => def_id, }; !self.item_is_accessible(def_id) @@ -828,6 +873,12 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> { return true; } } + ty::TyProjection(ref proj) => { + let tcx = self.tcx; + if self.check_trait_ref(proj.trait_ref(tcx)) { + return true; + } + } ty::TyAnon(def_id, ..) => { for predicate in &self.tcx.predicates_of(def_id).predicates { let trait_ref = match *predicate { @@ -838,7 +889,8 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> { if poly_projection_predicate.skip_binder().ty.visit_with(self) { return true; } - Some(poly_projection_predicate.skip_binder().projection_ty.trait_ref) + Some(poly_projection_predicate.skip_binder() + .projection_ty.trait_ref(self.tcx)) } ty::Predicate::TypeOutlives(..) => None, _ => bug!("unexpected predicate: {:?}", predicate), @@ -863,16 +915,6 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> { ty.super_visit_with(self) } - - fn visit_trait_ref(&mut self, trait_ref: ty::TraitRef<'tcx>) -> bool { - if !self.item_is_accessible(trait_ref.def_id) { - let msg = format!("trait `{}` is private", trait_ref); - self.tcx.sess.span_err(self.span, &msg); - return true; - } - - trait_ref.super_visit_with(self) - } } /////////////////////////////////////////////////////////////////////////////// @@ -1249,7 +1291,22 @@ impl<'a, 'tcx: 'a> SearchInterfaceForPrivateItemsVisitor<'a, 'tcx> { } fn predicates(&mut self) -> &mut Self { - self.tcx.predicates_of(self.item_def_id).visit_with(self); + let predicates = self.tcx.predicates_of(self.item_def_id); + for predicate in &predicates.predicates { + predicate.visit_with(self); + match predicate { + &ty::Predicate::Trait(poly_predicate) => { + self.check_trait_ref(poly_predicate.skip_binder().trait_ref); + }, + &ty::Predicate::Projection(poly_predicate) => { + let tcx = self.tcx; + self.check_trait_ref( + poly_predicate.skip_binder().projection_ty.trait_ref(tcx) + ); + }, + _ => (), + }; + } self } @@ -1265,9 +1322,38 @@ impl<'a, 'tcx: 'a> SearchInterfaceForPrivateItemsVisitor<'a, 'tcx> { } fn impl_trait_ref(&mut self) -> &mut Self { - self.tcx.impl_trait_ref(self.item_def_id).visit_with(self); + if let Some(impl_trait_ref) = self.tcx.impl_trait_ref(self.item_def_id) { + self.check_trait_ref(impl_trait_ref); + impl_trait_ref.super_visit_with(self); + } self } + + fn check_trait_ref(&mut self, trait_ref: ty::TraitRef<'tcx>) { + // Non-local means public (private items can't leave their crate, modulo bugs) + if let Some(node_id) = self.tcx.hir.as_local_node_id(trait_ref.def_id) { + let item = self.tcx.hir.expect_item(node_id); + let vis = ty::Visibility::from_hir(&item.vis, node_id, self.tcx); + if !vis.is_at_least(self.min_visibility, self.tcx) { + self.min_visibility = vis; + } + if !vis.is_at_least(self.required_visibility, self.tcx) { + if self.has_pub_restricted || self.has_old_errors { + struct_span_err!(self.tcx.sess, self.span, E0445, + "private trait `{}` in public interface", trait_ref) + .span_label(self.span, format!( + "private trait can't be public")) + .emit(); + } else { + self.tcx.sess.add_lint(lint::builtin::PRIVATE_IN_PUBLIC, + node_id, + self.span, + format!("private trait `{}` in public \ + interface (error E0445)", trait_ref)); + } + } + } + } } impl<'a, 'tcx: 'a> TypeVisitor<'tcx> for SearchInterfaceForPrivateItemsVisitor<'a, 'tcx> { @@ -1285,8 +1371,8 @@ impl<'a, 'tcx: 'a> TypeVisitor<'tcx> for SearchInterfaceForPrivateItemsVisitor<' // free type aliases, but this isn't done yet. return false; } - - Some(proj.trait_ref.def_id) + let trait_ref = proj.trait_ref(self.tcx); + Some(trait_ref.def_id) } _ => None }; @@ -1317,42 +1403,7 @@ impl<'a, 'tcx: 'a> TypeVisitor<'tcx> for SearchInterfaceForPrivateItemsVisitor<' } } - if let ty::TyProjection(ref proj) = ty.sty { - // Avoid calling `visit_trait_ref` below on the trait, - // as we have already checked the trait itself above. - proj.trait_ref.super_visit_with(self) - } else { - ty.super_visit_with(self) - } - } - - fn visit_trait_ref(&mut self, trait_ref: ty::TraitRef<'tcx>) -> bool { - // Non-local means public (private items can't leave their crate, modulo bugs) - if let Some(node_id) = self.tcx.hir.as_local_node_id(trait_ref.def_id) { - let item = self.tcx.hir.expect_item(node_id); - let vis = ty::Visibility::from_hir(&item.vis, node_id, self.tcx); - - if !vis.is_at_least(self.min_visibility, self.tcx) { - self.min_visibility = vis; - } - if !vis.is_at_least(self.required_visibility, self.tcx) { - if self.has_pub_restricted || self.has_old_errors { - struct_span_err!(self.tcx.sess, self.span, E0445, - "private trait `{}` in public interface", trait_ref) - .span_label(self.span, format!( - "private trait can't be public")) - .emit(); - } else { - self.tcx.sess.add_lint(lint::builtin::PRIVATE_IN_PUBLIC, - node_id, - self.span, - format!("private trait `{}` in public \ - interface (error E0445)", trait_ref)); - } - } - } - - trait_ref.super_visit_with(self) + ty.super_visit_with(self) } } diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 7754cd7366ecf..49e6929aeef1d 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -2409,13 +2409,15 @@ impl<'a> Resolver<'a> { .map(|suggestion| import_candidate_to_paths(&suggestion)).collect::>(); enum_candidates.sort(); for (sp, variant_path, enum_path) in enum_candidates { - let msg = format!("there is an enum variant `{}`, did you mean to use `{}`?", - variant_path, - enum_path); if sp == DUMMY_SP { + let msg = format!("there is an enum variant `{}`, \ + try using `{}`?", + variant_path, + enum_path); err.help(&msg); } else { - err.span_help(sp, &msg); + err.span_suggestion(span, "you can try using the variant's enum", + enum_path); } } } @@ -2424,18 +2426,20 @@ impl<'a> Resolver<'a> { let self_is_available = this.self_value_is_available(path[0].ctxt, span); match candidate { AssocSuggestion::Field => { - err.span_label(span, format!("did you mean `self.{}`?", path_str)); + err.span_suggestion(span, "try", + format!("self.{}", path_str)); if !self_is_available { err.span_label(span, format!("`self` value is only available in \ methods with `self` parameter")); } } AssocSuggestion::MethodWithSelf if self_is_available => { - err.span_label(span, format!("did you mean `self.{}(...)`?", - path_str)); + err.span_suggestion(span, "try", + format!("self.{}", path_str)); } AssocSuggestion::MethodWithSelf | AssocSuggestion::AssocItem => { - err.span_label(span, format!("did you mean `Self::{}`?", path_str)); + err.span_suggestion(span, "try", + format!("Self::{}", path_str)); } } return err; diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 0fbc596f2e1c2..a993aca92dd12 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -658,9 +658,10 @@ impl<'a> Resolver<'a> { if let Some(suggestion) = suggestion { if suggestion != name { if let MacroKind::Bang = kind { - err.help(&format!("did you mean `{}!`?", suggestion)); + err.span_suggestion(span, "you could try the macro", + format!("{}!", suggestion)); } else { - err.help(&format!("did you mean `{}`?", suggestion)); + err.span_suggestion(span, "try", suggestion.to_string()); } } else { err.help("have you added the `#[macro_use]` on the module/import?"); diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index f54973e08975c..ac2baa9e8b1d2 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -608,13 +608,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { hir::QPath::TypeRelative(..) => { let ty = hir_ty_to_ty(self.tcx, ty); if let ty::TyProjection(proj) = ty.sty { - for item in self.tcx.associated_items(proj.trait_ref.def_id) { - if item.kind == ty::AssociatedKind::Type { - if item.name == proj.item_name(self.tcx) { - return HirDef::AssociatedTy(item.def_id); - } - } - } + return HirDef::AssociatedTy(proj.item_def_id); } HirDef::Err } diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs index a4bbdef82f094..6cbdae7627714 100644 --- a/src/librustc_trans/back/link.rs +++ b/src/librustc_trans/back/link.rs @@ -43,7 +43,7 @@ use std::path::{Path, PathBuf}; use std::process::Command; use std::str; use flate2::Compression; -use flate2::write::ZlibEncoder; +use flate2::write::DeflateEncoder; use syntax::ast; use syntax::attr; use syntax_pos::Span; @@ -622,7 +622,7 @@ fn link_rlib<'a>(sess: &'a Session, } let mut bc_data_deflated = Vec::new(); - ZlibEncoder::new(&mut bc_data_deflated, Compression::Default) + DeflateEncoder::new(&mut bc_data_deflated, Compression::Fast) .write_all(&bc_data).unwrap(); let mut bc_file_deflated = match fs::File::create(&bc_deflated_filename) { diff --git a/src/librustc_trans/back/lto.rs b/src/librustc_trans/back/lto.rs index 906815583bf09..c402bdea2b23f 100644 --- a/src/librustc_trans/back/lto.rs +++ b/src/librustc_trans/back/lto.rs @@ -22,7 +22,7 @@ use rustc::hir::def_id::LOCAL_CRATE; use back::write::{ModuleConfig, with_llvm_pmb, CodegenContext}; use libc; -use flate2::read::ZlibDecoder; +use flate2::read::DeflateDecoder; use std::io::Read; use std::ffi::CString; @@ -111,7 +111,7 @@ pub fn run(cgcx: &CodegenContext, (link::RLIB_BYTECODE_OBJECT_V1_DATA_OFFSET + data_size as usize)]; let mut inflated = Vec::new(); - let res = ZlibDecoder::new(compressed_data) + let res = DeflateDecoder::new(compressed_data) .read_to_end(&mut inflated); if res.is_err() { let msg = format!("failed to decompress bc of `{}`", @@ -131,7 +131,7 @@ pub fn run(cgcx: &CodegenContext, // simply inflate everything and let LLVM decide if it can // make sense of it let mut inflated = Vec::new(); - let res = ZlibDecoder::new(bc_encoded) + let res = DeflateDecoder::new(bc_encoded) .read_to_end(&mut inflated); if res.is_err() { let msg = format!("failed to decompress bc of `{}`", diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index 8298324e99680..ccb4742e4504a 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -730,7 +730,7 @@ fn write_metadata<'a, 'gcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>, -> (ContextRef, ModuleRef, EncodedMetadata) { use std::io::Write; use flate2::Compression; - use flate2::write::ZlibEncoder; + use flate2::write::DeflateEncoder; let (metadata_llcx, metadata_llmod) = unsafe { context::create_context_and_module(tcx.sess, "metadata") @@ -770,7 +770,7 @@ fn write_metadata<'a, 'gcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>, assert!(kind == MetadataKind::Compressed); let mut compressed = cstore.metadata_encoding_version().to_vec(); - ZlibEncoder::new(&mut compressed, Compression::Default) + DeflateEncoder::new(&mut compressed, Compression::Fast) .write_all(&metadata.raw_data).unwrap(); let llmeta = C_bytes_in_context(metadata_llcx, &compressed); @@ -1120,7 +1120,7 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, .into_iter() .map(|cgu| { let dep_node = cgu.work_product_dep_node(); - let (stats, module) = + let ((stats, module), _) = tcx.dep_graph.with_task(dep_node, AssertDepGraphSafe(&shared_ccx), AssertDepGraphSafe(cgu), diff --git a/src/librustc_trans/debuginfo/metadata.rs b/src/librustc_trans/debuginfo/metadata.rs index 0cc1993601119..61204b88e130e 100644 --- a/src/librustc_trans/debuginfo/metadata.rs +++ b/src/librustc_trans/debuginfo/metadata.rs @@ -14,7 +14,7 @@ use self::MemberDescriptionFactory::*; use self::EnumDiscriminantInfo::*; use super::utils::{debug_context, DIB, span_start, bytes_to_bits, size_and_align_of, - get_namespace_and_span_for_item, create_DIArray, is_node_local_to_unit}; + get_namespace_for_item, create_DIArray, is_node_local_to_unit}; use super::namespace::mangled_name_of_item; use super::type_names::compute_debuginfo_type_name; use super::{CrateDebugContext}; @@ -421,7 +421,7 @@ fn trait_pointer_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, let containing_scope = match trait_type.sty { ty::TyDynamic(ref data, ..) => if let Some(principal) = data.principal() { let def_id = principal.def_id(); - get_namespace_and_span_for_item(cx, def_id).0 + get_namespace_for_item(cx, def_id) } else { NO_SCOPE_METADATA }, @@ -971,7 +971,7 @@ fn prepare_struct_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, _ => bug!("prepare_struct_metadata on a non-ADT") }; - let (containing_scope, _) = get_namespace_and_span_for_item(cx, struct_def_id); + let containing_scope = get_namespace_for_item(cx, struct_def_id); let struct_metadata_stub = create_struct_stub(cx, struct_llvm_type, @@ -1096,7 +1096,7 @@ fn prepare_union_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, _ => bug!("prepare_union_metadata on a non-ADT") }; - let (containing_scope, _) = get_namespace_and_span_for_item(cx, union_def_id); + let containing_scope = get_namespace_for_item(cx, union_def_id); let union_metadata_stub = create_union_stub(cx, union_llvm_type, @@ -1483,7 +1483,7 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, -> RecursiveTypeDescription<'tcx> { let enum_name = compute_debuginfo_type_name(cx, enum_type, false); - let (containing_scope, _) = get_namespace_and_span_for_item(cx, enum_def_id); + let containing_scope = get_namespace_for_item(cx, enum_def_id); // FIXME: This should emit actual file metadata for the enum, but we // currently can't get the necessary information when it comes to types // imported from other crates. Formerly we violated the ODR when performing @@ -1781,7 +1781,8 @@ pub fn create_global_var_metadata(cx: &CrateContext, let tcx = cx.tcx(); let node_def_id = tcx.hir.local_def_id(node_id); - let (var_scope, span) = get_namespace_and_span_for_item(cx, node_def_id); + let var_scope = get_namespace_for_item(cx, node_def_id); + let span = cx.tcx().def_span(node_def_id); let (file_metadata, line_number) = if span != syntax_pos::DUMMY_SP { let loc = span_start(cx, span); diff --git a/src/librustc_trans/debuginfo/namespace.rs b/src/librustc_trans/debuginfo/namespace.rs index 54a129536d03d..d4dd112f3027f 100644 --- a/src/librustc_trans/debuginfo/namespace.rs +++ b/src/librustc_trans/debuginfo/namespace.rs @@ -10,8 +10,8 @@ // Namespace Handling. -use super::metadata::{file_metadata, unknown_file_metadata, UNKNOWN_LINE_NUMBER}; -use super::utils::{DIB, debug_context, span_start}; +use super::metadata::{unknown_file_metadata, UNKNOWN_LINE_NUMBER}; +use super::utils::{DIB, debug_context}; use llvm; use llvm::debuginfo::DIScope; @@ -19,10 +19,8 @@ use rustc::hir::def_id::DefId; use rustc::hir::map::DefPathData; use common::CrateContext; -use libc::c_uint; use std::ffi::CString; use std::ptr; -use syntax_pos::DUMMY_SP; pub fn mangled_name_of_item(ccx: &CrateContext, def_id: DefId, extra: &str) -> String { fn fill_nested(ccx: &CrateContext, def_id: DefId, extra: &str, output: &mut String) { @@ -69,21 +67,14 @@ pub fn item_namespace(ccx: &CrateContext, def_id: DefId) -> DIScope { }; let namespace_name = CString::new(namespace_name.as_bytes()).unwrap(); - let span = ccx.tcx().def_span(def_id); - let (file, line) = if span != DUMMY_SP { - let loc = span_start(ccx, span); - (file_metadata(ccx, &loc.file.name, def_id.krate), loc.line as c_uint) - } else { - (unknown_file_metadata(ccx), UNKNOWN_LINE_NUMBER) - }; let scope = unsafe { llvm::LLVMRustDIBuilderCreateNameSpace( DIB(ccx), parent_scope, namespace_name.as_ptr(), - file, - line as c_uint) + unknown_file_metadata(ccx), + UNKNOWN_LINE_NUMBER) }; debug_context(ccx).namespace_map.borrow_mut().insert(def_id, scope); diff --git a/src/librustc_trans/debuginfo/utils.rs b/src/librustc_trans/debuginfo/utils.rs index 0a873767d9359..0555714d623e6 100644 --- a/src/librustc_trans/debuginfo/utils.rs +++ b/src/librustc_trans/debuginfo/utils.rs @@ -73,13 +73,7 @@ pub fn DIB(cx: &CrateContext) -> DIBuilderRef { cx.dbg_cx().as_ref().unwrap().builder } -pub fn get_namespace_and_span_for_item(cx: &CrateContext, def_id: DefId) - -> (DIScope, Span) { - let containing_scope = item_namespace(cx, cx.tcx().parent(def_id) - .expect("get_namespace_and_span_for_item: missing parent?")); - - // Try to get some span information, if we have an inlined item. - let definition_span = cx.tcx().def_span(def_id); - - (containing_scope, definition_span) +pub fn get_namespace_for_item(cx: &CrateContext, def_id: DefId) -> DIScope { + item_namespace(cx, cx.tcx().parent(def_id) + .expect("get_namespace_for_item: missing parent?")) } diff --git a/src/librustc_trans/mir/block.rs b/src/librustc_trans/mir/block.rs index 48b166c61deb1..9bb29c340d983 100644 --- a/src/librustc_trans/mir/block.rs +++ b/src/librustc_trans/mir/block.rs @@ -263,7 +263,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> { } mir::TerminatorKind::Drop { ref location, target, unwind } => { - let ty = location.ty(&self.mir, bcx.tcx()).to_ty(bcx.tcx()); + let ty = location.ty(self.mir, bcx.tcx()).to_ty(bcx.tcx()); let ty = self.monomorphize(&ty); let drop_fn = monomorphize::resolve_drop_in_place(bcx.ccx.shared(), ty); @@ -438,7 +438,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> { let extra_args = &args[sig.inputs().len()..]; let extra_args = extra_args.iter().map(|op_arg| { - let op_ty = op_arg.ty(&self.mir, bcx.tcx()); + let op_ty = op_arg.ty(self.mir, bcx.tcx()); self.monomorphize(&op_ty) }).collect::>(); diff --git a/src/librustc_trans/mir/lvalue.rs b/src/librustc_trans/mir/lvalue.rs index 88e46b5c99a44..af8976967a1e7 100644 --- a/src/librustc_trans/mir/lvalue.rs +++ b/src/librustc_trans/mir/lvalue.rs @@ -408,7 +408,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> { pub fn monomorphized_lvalue_ty(&self, lvalue: &mir::Lvalue<'tcx>) -> Ty<'tcx> { let tcx = self.ccx.tcx(); - let lvalue_ty = lvalue.ty(&self.mir, tcx); + let lvalue_ty = lvalue.ty(self.mir, tcx); self.monomorphize(&lvalue_ty.to_ty(tcx)) } } diff --git a/src/librustc_trans/partitioning.rs b/src/librustc_trans/partitioning.rs index ead442d338820..68b72087b2e65 100644 --- a/src/librustc_trans/partitioning.rs +++ b/src/librustc_trans/partitioning.rs @@ -270,6 +270,14 @@ pub fn partition<'a, 'tcx, I>(scx: &SharedCrateContext<'a, 'tcx>, (&cgu1.name[..]).cmp(&cgu2.name[..]) }); + if scx.sess().opts.enable_dep_node_debug_strs() { + for cgu in &result { + let dep_node = cgu.work_product_dep_node(); + scx.tcx().dep_graph.register_dep_node_debug_str(dep_node, + || cgu.name().to_string()); + } + } + result } diff --git a/src/librustc_trans/trans_item.rs b/src/librustc_trans/trans_item.rs index 200f6dee334ad..8a77b26580999 100644 --- a/src/librustc_trans/trans_item.rs +++ b/src/librustc_trans/trans_item.rs @@ -558,7 +558,7 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> { for projection in projections { let projection = projection.skip_binder(); - let name = &projection.item_name.as_str(); + let name = &self.tcx.associated_item(projection.item_def_id).name.as_str(); output.push_str(name); output.push_str("="); self.push_type_name(projection.ty, output); diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 212461a6d70e2..bb6e478738aa2 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -66,8 +66,8 @@ pub trait AstConv<'gcx, 'tcx> { /// late-bound regions. fn projected_ty_from_poly_trait_ref(&self, span: Span, - poly_trait_ref: ty::PolyTraitRef<'tcx>, - item_name: ast::Name) + item_def_id: DefId, + poly_trait_ref: ty::PolyTraitRef<'tcx>) -> Ty<'tcx>; /// Normalize an associated type coming from the user. @@ -651,11 +651,11 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { }); let existential_projections = projection_bounds.iter().map(|bound| { bound.map_bound(|b| { - let p = b.projection_ty; + let trait_ref = self.trait_ref_to_existential(b.projection_ty.trait_ref(tcx)); ty::ExistentialProjection { - trait_ref: self.trait_ref_to_existential(p.trait_ref), - item_name: p.item_name(tcx), - ty: b.ty + ty: b.ty, + item_def_id: b.projection_ty.item_def_id, + substs: trait_ref.substs, } }) }); @@ -676,22 +676,22 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { for tr in traits::supertraits(tcx, principal) { associated_types.extend(tcx.associated_items(tr.def_id()) .filter(|item| item.kind == ty::AssociatedKind::Type) - .map(|item| (tr.def_id(), item.name))); + .map(|item| item.def_id)); } for projection_bound in &projection_bounds { - let pair = (projection_bound.0.projection_ty.trait_ref.def_id, - projection_bound.0.projection_ty.item_name(tcx)); - associated_types.remove(&pair); + associated_types.remove(&projection_bound.0.projection_ty.item_def_id); } - for (trait_def_id, name) in associated_types { + for item_def_id in associated_types { + let assoc_item = tcx.associated_item(item_def_id); + let trait_def_id = assoc_item.container.id(); struct_span_err!(tcx.sess, span, E0191, "the value of the associated type `{}` (from the trait `{}`) must be specified", - name, + assoc_item.name, tcx.item_path_str(trait_def_id)) .span_label(span, format!( - "missing associated type `{}` value", name)) + "missing associated type `{}` value", assoc_item.name)) .emit(); } @@ -896,11 +896,12 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { }; let trait_did = bound.0.def_id; - let ty = self.projected_ty_from_poly_trait_ref(span, bound, assoc_name); - let ty = self.normalize_ty(span, ty); - let item = tcx.associated_items(trait_did).find(|i| i.name == assoc_name) .expect("missing associated type"); + + let ty = self.projected_ty_from_poly_trait_ref(span, item.def_id, bound); + let ty = self.normalize_ty(span, ty); + let def = Def::AssociatedTy(item.def_id); let def_scope = tcx.adjust(assoc_name, item.container.id(), ref_id).1; if !item.vis.is_accessible_from(def_scope, tcx) { @@ -915,12 +916,13 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { fn qpath_to_ty(&self, span: Span, opt_self_ty: Option>, - trait_def_id: DefId, + item_def_id: DefId, trait_segment: &hir::PathSegment, item_segment: &hir::PathSegment) -> Ty<'tcx> { let tcx = self.tcx(); + let trait_def_id = tcx.parent_def_id(item_def_id).unwrap(); self.prohibit_type_params(slice::ref_slice(item_segment)); @@ -944,7 +946,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { debug!("qpath_to_ty: trait_ref={:?}", trait_ref); - self.normalize_ty(span, tcx.mk_projection(trait_ref, item_segment.name)) + self.normalize_ty(span, tcx.mk_projection(item_def_id, trait_ref.substs)) } pub fn prohibit_type_params(&self, segments: &[hir::PathSegment]) { @@ -1050,10 +1052,9 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { } Def::AssociatedTy(def_id) => { self.prohibit_type_params(&path.segments[..path.segments.len()-2]); - let trait_did = tcx.parent_def_id(def_id).unwrap(); self.qpath_to_ty(span, opt_self_ty, - trait_did, + def_id, &path.segments[path.segments.len()-2], path.segments.last().unwrap()) } diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs index 7bd24c939caf0..b3f62de5b570b 100644 --- a/src/librustc_typeck/check/cast.rs +++ b/src/librustc_typeck/check/cast.rs @@ -253,7 +253,7 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> { match fcx.tcx.sess.codemap().span_to_snippet(self.cast_span) { Ok(s) => { err.span_suggestion(self.cast_span, - "try casting to a reference instead:", + "try casting to a reference instead", format!("&{}{}", mtstr, s)); } Err(_) => { @@ -272,7 +272,7 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> { match fcx.tcx.sess.codemap().span_to_snippet(self.cast_span) { Ok(s) => { err.span_suggestion(self.cast_span, - "try casting to a `Box` instead:", + "try casting to a `Box` instead", format!("Box<{}>", s)); } Err(_) => span_help!(err, self.cast_span, "did you mean `Box<{}>`?", tstr), diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index f041db43e16d7..802eee91efcf3 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -156,7 +156,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // Given a Projection predicate, we can potentially infer // the complete signature. ty::Predicate::Projection(ref proj_predicate) => { - let trait_ref = proj_predicate.to_poly_trait_ref(); + let trait_ref = proj_predicate.to_poly_trait_ref(self.tcx); self.self_type_matches_expected_vid(trait_ref, expected_vid) .and_then(|_| self.deduce_sig_from_projection(proj_predicate)) } @@ -174,7 +174,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { .map(|obligation| &obligation.obligation) .filter_map(|obligation| { let opt_trait_ref = match obligation.predicate { - ty::Predicate::Projection(ref data) => Some(data.to_poly_trait_ref()), + ty::Predicate::Projection(ref data) => Some(data.to_poly_trait_ref(self.tcx)), ty::Predicate::Trait(ref data) => Some(data.to_poly_trait_ref()), ty::Predicate::Equate(..) => None, ty::Predicate::Subtype(..) => None, @@ -211,7 +211,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { debug!("deduce_sig_from_projection({:?})", projection); - let trait_ref = projection.to_poly_trait_ref(); + let trait_ref = projection.to_poly_trait_ref(tcx); if tcx.lang_items.fn_trait_kind(trait_ref.def_id()).is_none() { return None; diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index 0829951e12deb..ad4ee5a9d6dcf 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -10,6 +10,7 @@ use super::{probe, MethodCallee}; +use astconv::AstConv; use check::{FnCtxt, LvalueOp, callee}; use hir::def_id::DefId; use rustc::ty::subst::Substs; @@ -280,62 +281,38 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { fn instantiate_method_substs(&mut self, pick: &probe::Pick<'tcx>, segment: &hir::PathSegment, - substs: &Substs<'tcx>) + parent_substs: &Substs<'tcx>) -> &'tcx Substs<'tcx> { - let supplied_method_types = match segment.parameters { - hir::AngleBracketedParameters(ref data) => &data.types, - _ => bug!("unexpected generic arguments: {:?}", segment.parameters), - }; - // Determine the values for the generic parameters of the method. // If they were not explicitly supplied, just construct fresh // variables. - let num_supplied_types = supplied_method_types.len(); let method_generics = self.tcx.generics_of(pick.item.def_id); - let num_method_types = method_generics.types.len(); - - if num_supplied_types > 0 && num_supplied_types != num_method_types { - if num_method_types == 0 { - struct_span_err!(self.tcx.sess, - self.span, - E0035, - "does not take type parameters") - .span_label(self.span, "called with unneeded type parameters") - .emit(); - } else { - struct_span_err!(self.tcx.sess, - self.span, - E0036, - "incorrect number of type parameters given for this method: \ - expected {}, found {}", - num_method_types, - num_supplied_types) - .span_label(self.span, - format!("Passed {} type argument{}, expected {}", - num_supplied_types, - if num_supplied_types != 1 { "s" } else { "" }, - num_method_types)) - .emit(); - } - } + let mut fn_segment = Some((segment, method_generics)); + self.fcx.check_path_parameter_count(self.span, &mut fn_segment, true); // Create subst for early-bound lifetime parameters, combining // parameters from the type and those from the method. - // - // FIXME -- permit users to manually specify lifetimes - let supplied_start = substs.len() + method_generics.regions.len(); + let (supplied_types, supplied_lifetimes) = match segment.parameters { + hir::AngleBracketedParameters(ref data) => (&data.types, &data.lifetimes), + _ => bug!("unexpected generic arguments: {:?}", segment.parameters), + }; + assert_eq!(method_generics.parent_count(), parent_substs.len()); Substs::for_item(self.tcx, pick.item.def_id, |def, _| { let i = def.index as usize; - if i < substs.len() { - substs.region_at(i) + if i < parent_substs.len() { + parent_substs.region_at(i) + } else if let Some(lifetime) = + supplied_lifetimes.get(i - parent_substs.len()) { + AstConv::ast_region_to_region(self.fcx, lifetime, Some(def)) } else { self.region_var_for_def(self.span, def) } }, |def, cur_substs| { let i = def.index as usize; - if i < substs.len() { - substs.type_at(i) - } else if let Some(ast_ty) = supplied_method_types.get(i - supplied_start) { + if i < parent_substs.len() { + parent_substs.type_at(i) + } else if let Some(ast_ty) = + supplied_types.get(i - parent_substs.len() - method_generics.regions.len()) { self.to_ty(ast_ty) } else { self.type_var_for_def(self.span, def, cur_substs) diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index ee9a347ae9511..dfc5cd00b6eab 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -861,7 +861,10 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { debug!("assemble_projection_candidates: step={:?}", step); let (def_id, substs) = match step.self_ty.sty { - ty::TyProjection(ref data) => (data.trait_ref.def_id, data.trait_ref.substs), + ty::TyProjection(ref data) => { + let trait_ref = data.trait_ref(self.tcx); + (trait_ref.def_id, trait_ref.substs) + }, ty::TyAnon(def_id, substs) => (def_id, substs), _ => continue, }; diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 2634e8fcc006d..af11cacb247b6 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1167,6 +1167,7 @@ fn check_on_unimplemented<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, }) { if let Some(istring) = attr.value_str() { let istring = istring.as_str(); + let name = tcx.item_name(def_id).as_str(); let parser = Parser::new(&istring); let types = &generics.types; for token in parser { @@ -1175,13 +1176,14 @@ fn check_on_unimplemented<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, Piece::NextArgument(a) => match a.position { // `{Self}` is allowed Position::ArgumentNamed(s) if s == "Self" => (), + // `{ThisTraitsName}` is allowed + Position::ArgumentNamed(s) if s == name => (), // So is `{A}` if A is a type parameter Position::ArgumentNamed(s) => match types.iter().find(|t| { t.name == s }) { Some(_) => (), None => { - let name = tcx.item_name(def_id); span_err!(tcx.sess, attr.span, E0230, "there is no type parameter \ {} on trait {}", @@ -1620,17 +1622,18 @@ impl<'a, 'gcx, 'tcx> AstConv<'gcx, 'tcx> for FnCtxt<'a, 'gcx, 'tcx> { fn projected_ty_from_poly_trait_ref(&self, span: Span, - poly_trait_ref: ty::PolyTraitRef<'tcx>, - item_name: ast::Name) + item_def_id: DefId, + poly_trait_ref: ty::PolyTraitRef<'tcx>) -> Ty<'tcx> { + let item = self.tcx().associated_item(item_def_id); let (trait_ref, _) = self.replace_late_bound_regions_with_fresh_var( span, - infer::LateBoundRegionConversionTime::AssocTypeProjection(item_name), + infer::LateBoundRegionConversionTime::AssocTypeProjection(item.name), &poly_trait_ref); - self.tcx().mk_projection(trait_ref, item_name) + self.tcx().mk_projection(item_def_id, trait_ref.substs) } fn normalize_ty(&self, span: Span, ty: Ty<'tcx>) -> Ty<'tcx> { @@ -4488,8 +4491,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // variables. If the user provided some types, we may still need // to add defaults. If the user provided *too many* types, that's // a problem. - self.check_path_parameter_count(span, &mut type_segment); - self.check_path_parameter_count(span, &mut fn_segment); + self.check_path_parameter_count(span, &mut type_segment, false); + self.check_path_parameter_count(span, &mut fn_segment, false); let (fn_start, has_self) = match (type_segment, fn_segment) { (_, Some((_, generics))) => { @@ -4615,7 +4618,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { /// Report errors if the provided parameters are too few or too many. fn check_path_parameter_count(&self, span: Span, - segment: &mut Option<(&hir::PathSegment, &ty::Generics)>) { + segment: &mut Option<(&hir::PathSegment, &ty::Generics)>, + is_method_call: bool) { let (lifetimes, types, infer_types, bindings) = { match segment.map(|(s, _)| &s.parameters) { Some(&hir::AngleBracketedParameters(ref data)) => { @@ -4629,6 +4633,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { None => (&[][..], &[][..], true, &[][..]) } }; + let infer_lifetimes = lifetimes.len() == 0; let count_lifetime_params = |n| { format!("{} lifetime parameter{}", n, if n == 1 { "" } else { "s" }) @@ -4637,32 +4642,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { format!("{} type parameter{}", n, if n == 1 { "" } else { "s" }) }; - // Check provided lifetime parameters. - let lifetime_defs = segment.map_or(&[][..], |(_, generics)| &generics.regions); - if lifetimes.len() > lifetime_defs.len() { - let expected_text = count_lifetime_params(lifetime_defs.len()); - let actual_text = count_lifetime_params(lifetimes.len()); - struct_span_err!(self.tcx.sess, span, E0088, - "too many lifetime parameters provided: \ - expected at most {}, found {}", - expected_text, actual_text) - .span_label(span, format!("expected {}", expected_text)) - .emit(); - } else if lifetimes.len() > 0 && lifetimes.len() < lifetime_defs.len() { - let expected_text = count_lifetime_params(lifetime_defs.len()); - let actual_text = count_lifetime_params(lifetimes.len()); - struct_span_err!(self.tcx.sess, span, E0090, - "too few lifetime parameters provided: \ - expected {}, found {}", - expected_text, actual_text) - .span_label(span, format!("expected {}", expected_text)) - .emit(); - } - - // The case where there is not enough lifetime parameters is not checked, - // because this is not possible - a function never takes lifetime parameters. - // See discussion for Pull Request 36208. - // Check provided type parameters. let type_defs = segment.map_or(&[][..], |(_, generics)| { if generics.parent.is_none() { @@ -4687,7 +4666,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // type parameters, we force instantiate_value_path to // use inference variables instead of the provided types. *segment = None; - } else if !infer_types && types.len() < required_len { + } else if types.len() < required_len && !infer_types { let expected_text = count_type_params(required_len); let actual_text = count_type_params(types.len()); struct_span_err!(self.tcx.sess, span, E0089, @@ -4703,6 +4682,51 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { "unexpected binding of associated item in expression path \ (only allowed in type paths)"); } + + // Check provided lifetime parameters. + let lifetime_defs = segment.map_or(&[][..], |(_, generics)| &generics.regions); + let required_len = lifetime_defs.len(); + + // Prohibit explicit lifetime arguments if late bound lifetime parameters are present. + let has_late_bound_lifetime_defs = + segment.map_or(false, |(_, generics)| generics.has_late_bound_regions); + if has_late_bound_lifetime_defs && !lifetimes.is_empty() { + // Report this as a lint only if no error was reported previously. + if !is_method_call && (lifetimes.len() > lifetime_defs.len() || + lifetimes.len() < required_len && !infer_lifetimes) { + self.tcx.sess.span_err(lifetimes[0].span, + "cannot specify lifetime arguments explicitly \ + if late bound lifetime parameters are present"); + *segment = None; + } else { + self.tcx.sess.add_lint(lint::builtin::LATE_BOUND_LIFETIME_ARGUMENTS, + lifetimes[0].id, lifetimes[0].span, + format!("cannot specify lifetime arguments explicitly \ + if late bound lifetime parameters are present")); + } + return; + } + + if lifetimes.len() > lifetime_defs.len() { + let span = lifetimes[lifetime_defs.len()].span; + let expected_text = count_lifetime_params(lifetime_defs.len()); + let actual_text = count_lifetime_params(lifetimes.len()); + struct_span_err!(self.tcx.sess, span, E0088, + "too many lifetime parameters provided: \ + expected at most {}, found {}", + expected_text, actual_text) + .span_label(span, format!("expected {}", expected_text)) + .emit(); + } else if lifetimes.len() < required_len && !infer_lifetimes { + let expected_text = count_lifetime_params(lifetime_defs.len()); + let actual_text = count_lifetime_params(lifetimes.len()); + struct_span_err!(self.tcx.sess, span, E0090, + "too few lifetime parameters provided: \ + expected {}, found {}", + expected_text, actual_text) + .span_label(span, format!("expected {}", expected_text)) + .emit(); + } } fn structurally_resolve_type_or_else(&self, sp: Span, ty: Ty<'tcx>, f: F) diff --git a/src/librustc_typeck/check/op.rs b/src/librustc_typeck/check/op.rs index 4d69b37b113cf..032e37a34a887 100644 --- a/src/librustc_typeck/check/op.rs +++ b/src/librustc_typeck/check/op.rs @@ -320,7 +320,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { from a string reference. String concatenation \ appends the string on the right to the string \ on the left and may require reallocation. This \ - requires ownership of the string on the left."), suggestion); + requires ownership of the string on the left"), suggestion); is_string_addition = true; } diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index 5e79237da69d4..82207428efc4f 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -1595,15 +1595,15 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { // the problem is to add `T: 'r`, which isn't true. So, if there are no // inference variables, we use a verify constraint instead of adding // edges, which winds up enforcing the same condition. - let needs_infer = projection_ty.trait_ref.needs_infer(); + let needs_infer = projection_ty.needs_infer(); if env_bounds.is_empty() && needs_infer { debug!("projection_must_outlive: no declared bounds"); - for component_ty in projection_ty.trait_ref.substs.types() { + for component_ty in projection_ty.substs.types() { self.type_must_outlive(origin.clone(), component_ty, region); } - for r in projection_ty.trait_ref.substs.regions() { + for r in projection_ty.substs.regions() { self.sub_regions(origin.clone(), region, r); } @@ -1621,7 +1621,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { if !env_bounds.is_empty() && env_bounds[1..].iter().all(|b| *b == env_bounds[0]) { let unique_bound = env_bounds[0]; debug!("projection_must_outlive: unique declared bound = {:?}", unique_bound); - if projection_ty.trait_ref.substs.regions().any(|r| env_bounds.contains(&r)) { + if projection_ty.substs.regions().any(|r| env_bounds.contains(&r)) { debug!("projection_must_outlive: unique declared bound appears in trait ref"); self.sub_regions(origin.clone(), region, unique_bound); return; @@ -1691,8 +1691,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { declared_bounds, projection_ty); // see the extensive comment in projection_must_outlive - let item_name = projection_ty.item_name(self.tcx); - let ty = self.tcx.mk_projection(projection_ty.trait_ref, item_name); + let ty = self.tcx.mk_projection(projection_ty.item_def_id, projection_ty.substs); let recursive_bound = self.recursive_type_bound(span, ty); VerifyBound::AnyRegion(declared_bounds).or(recursive_bound) @@ -1758,9 +1757,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { { debug!("projection_bounds(projection_ty={:?})", projection_ty); - let item_name = projection_ty.item_name(self.tcx); - let ty = self.tcx.mk_projection(projection_ty.trait_ref.clone(), - item_name); + let ty = self.tcx.mk_projection(projection_ty.item_def_id, projection_ty.substs); // Say we have a projection `>::SomeType`. We are interested // in looking for a trait definition like: @@ -1772,7 +1769,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { // ``` // // we can thus deduce that `>::SomeType : 'a`. - let trait_predicates = self.tcx.predicates_of(projection_ty.trait_ref.def_id); + let trait_predicates = self.tcx.predicates_of(projection_ty.trait_ref(self.tcx).def_id); assert_eq!(trait_predicates.parent, None); let predicates = trait_predicates.predicates.as_slice().to_vec(); traits::elaborate_predicates(self.tcx, predicates) @@ -1788,7 +1785,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { // apply the substitutions (and normalize any projected types) let outlives = self.instantiate_type_scheme(span, - projection_ty.trait_ref.substs, + projection_ty.substs, &outlives); debug!("projection_bounds: outlives={:?} (2)", @@ -1798,7 +1795,8 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { let (outlives, _) = self.replace_late_bound_regions_with_fresh_var( span, - infer::AssocTypeProjection(projection_ty.item_name(self.tcx)), + infer::AssocTypeProjection( + self.tcx.associated_item(projection_ty.item_def_id).name), &outlives); debug!("projection_bounds: outlives={:?} (3)", diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index cbda1227742ca..69cd141462875 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -508,7 +508,8 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> { .map(|(index, _)| Parameter(index as u32)) .collect(); - identify_constrained_type_params(ty_predicates.predicates.as_slice(), + identify_constrained_type_params(self.tcx, + ty_predicates.predicates.as_slice(), None, &mut constrained_parameters); diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index fd6dda5ccf4a7..72bd084330dd3 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -225,12 +225,12 @@ impl<'a, 'tcx> AstConv<'tcx, 'tcx> for ItemCtxt<'a, 'tcx> { fn projected_ty_from_poly_trait_ref(&self, span: Span, - poly_trait_ref: ty::PolyTraitRef<'tcx>, - item_name: ast::Name) + item_def_id: DefId, + poly_trait_ref: ty::PolyTraitRef<'tcx>) -> Ty<'tcx> { if let Some(trait_ref) = self.tcx().no_late_bound_regions(&poly_trait_ref) { - self.tcx().mk_projection(trait_ref, item_name) + self.tcx().mk_projection(item_def_id, trait_ref.substs) } else { // no late-bound regions, we can just ignore the binder span_err!(self.tcx().sess, span, E0212, @@ -772,6 +772,95 @@ fn trait_def<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, tcx.alloc_trait_def(def) } +fn has_late_bound_regions<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + node: hir_map::Node<'tcx>) + -> bool { + struct LateBoundRegionsDetector<'a, 'tcx: 'a> { + tcx: TyCtxt<'a, 'tcx, 'tcx>, + binder_depth: u32, + has_late_bound_regions: bool, + } + + impl<'a, 'tcx> Visitor<'tcx> for LateBoundRegionsDetector<'a, 'tcx> { + fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { + NestedVisitorMap::None + } + + fn visit_ty(&mut self, ty: &'tcx hir::Ty) { + if self.has_late_bound_regions { return } + match ty.node { + hir::TyBareFn(..) => { + self.binder_depth += 1; + intravisit::walk_ty(self, ty); + self.binder_depth -= 1; + } + _ => intravisit::walk_ty(self, ty) + } + } + + fn visit_poly_trait_ref(&mut self, + tr: &'tcx hir::PolyTraitRef, + m: hir::TraitBoundModifier) { + if self.has_late_bound_regions { return } + self.binder_depth += 1; + intravisit::walk_poly_trait_ref(self, tr, m); + self.binder_depth -= 1; + } + + fn visit_lifetime(&mut self, lt: &'tcx hir::Lifetime) { + if self.has_late_bound_regions { return } + + match self.tcx.named_region_map.defs.get(<.id).cloned() { + Some(rl::Region::Static) | Some(rl::Region::EarlyBound(..)) => {} + Some(rl::Region::LateBound(debruijn, _)) | + Some(rl::Region::LateBoundAnon(debruijn, _)) + if debruijn.depth < self.binder_depth => {} + _ => self.has_late_bound_regions = true, + } + } + } + + fn has_late_bound_regions<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + generics: &'tcx hir::Generics, + decl: &'tcx hir::FnDecl) + -> bool { + let mut visitor = LateBoundRegionsDetector { + tcx, binder_depth: 1, has_late_bound_regions: false + }; + for lifetime in &generics.lifetimes { + if tcx.named_region_map.late_bound.contains(&lifetime.lifetime.id) { + return true; + } + } + visitor.visit_fn_decl(decl); + visitor.has_late_bound_regions + } + + match node { + hir_map::NodeTraitItem(item) => match item.node { + hir::TraitItemKind::Method(ref sig, _) => + has_late_bound_regions(tcx, &sig.generics, &sig.decl), + _ => false, + }, + hir_map::NodeImplItem(item) => match item.node { + hir::ImplItemKind::Method(ref sig, _) => + has_late_bound_regions(tcx, &sig.generics, &sig.decl), + _ => false, + }, + hir_map::NodeForeignItem(item) => match item.node { + hir::ForeignItemFn(ref fn_decl, _, ref generics) => + has_late_bound_regions(tcx, generics, fn_decl), + _ => false, + }, + hir_map::NodeItem(item) => match item.node { + hir::ItemFn(ref fn_decl, .., ref generics, _) => + has_late_bound_regions(tcx, generics, fn_decl), + _ => false, + }, + _ => false + } +} + fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx ty::Generics { @@ -959,7 +1048,8 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, regions: regions, types: types, type_param_to_index: type_param_to_index, - has_self: has_self || parent_has_self + has_self: has_self || parent_has_self, + has_late_bound_regions: has_late_bound_regions(tcx, node), }) } @@ -1438,7 +1528,10 @@ fn predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } }; - let assoc_ty = tcx.mk_projection(self_trait_ref, trait_item.name); + let assoc_ty = tcx.mk_projection( + tcx.hir.local_def_id(trait_item.id), + self_trait_ref.substs, + ); let bounds = compute_bounds(&ItemCtxt::new(tcx, def_id), assoc_ty, @@ -1458,7 +1551,8 @@ fn predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, if let NodeItem(&Item { node: ItemImpl(..), .. }) = node { let self_ty = tcx.type_of(def_id); let trait_ref = tcx.impl_trait_ref(def_id); - ctp::setup_constraining_predicates(&mut predicates, + ctp::setup_constraining_predicates(tcx, + &mut predicates, trait_ref, &mut ctp::parameters_for_impl(self_ty, trait_ref)); } diff --git a/src/librustc_typeck/constrained_type_params.rs b/src/librustc_typeck/constrained_type_params.rs index ee11b774cf261..7742194dfe6e0 100644 --- a/src/librustc_typeck/constrained_type_params.rs +++ b/src/librustc_typeck/constrained_type_params.rs @@ -86,12 +86,13 @@ impl<'tcx> TypeVisitor<'tcx> for ParameterCollector { } } -pub fn identify_constrained_type_params<'tcx>(predicates: &[ty::Predicate<'tcx>], +pub fn identify_constrained_type_params<'tcx>(tcx: ty::TyCtxt, + predicates: &[ty::Predicate<'tcx>], impl_trait_ref: Option>, input_parameters: &mut FxHashSet) { let mut predicates = predicates.to_owned(); - setup_constraining_predicates(&mut predicates, impl_trait_ref, input_parameters); + setup_constraining_predicates(tcx, &mut predicates, impl_trait_ref, input_parameters); } @@ -135,7 +136,8 @@ pub fn identify_constrained_type_params<'tcx>(predicates: &[ty::Predicate<'tcx>] /// which is determined by 1, which requires `U`, that is determined /// by 0. I should probably pick a less tangled example, but I can't /// think of any. -pub fn setup_constraining_predicates<'tcx>(predicates: &mut [ty::Predicate<'tcx>], +pub fn setup_constraining_predicates<'tcx>(tcx: ty::TyCtxt, + predicates: &mut [ty::Predicate<'tcx>], impl_trait_ref: Option>, input_parameters: &mut FxHashSet) { @@ -175,7 +177,7 @@ pub fn setup_constraining_predicates<'tcx>(predicates: &mut [ty::Predicate<'tcx> // 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; + let unbound_trait_ref = projection.projection_ty.trait_ref(tcx); if Some(unbound_trait_ref.clone()) == impl_trait_ref { continue; } @@ -185,8 +187,7 @@ pub fn setup_constraining_predicates<'tcx>(predicates: &mut [ty::Predicate<'tcx> // `<::Baz as Iterator>::Output = ::Output` // Then the projection only applies if `T` is known, but it still // does not determine `U`. - - let inputs = parameters_for(&projection.projection_ty.trait_ref, true); + let inputs = parameters_for(&projection.projection_ty.trait_ref(tcx), true); let relies_only_on_inputs = inputs.iter().all(|p| input_parameters.contains(&p)); if !relies_only_on_inputs { continue; diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index 87e59683fd2a8..1e26a734e7640 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -332,92 +332,6 @@ fn main() { ``` "##, -E0035: r##" -You tried to give a type parameter where it wasn't needed. Erroneous code -example: - -```compile_fail,E0035 -struct Test; - -impl Test { - fn method(&self) {} -} - -fn main() { - let x = Test; - - x.method::(); // Error: Test::method doesn't need type parameter! -} -``` - -To fix this error, just remove the type parameter: - -``` -struct Test; - -impl Test { - fn method(&self) {} -} - -fn main() { - let x = Test; - - x.method(); // OK, we're good! -} -``` -"##, - -E0036: r##" -This error occurrs when you pass too many or not enough type parameters to -a method. Erroneous code example: - -```compile_fail,E0036 -struct Test; - -impl Test { - fn method(&self, v: &[T]) -> usize { - v.len() - } -} - -fn main() { - let x = Test; - let v = &[0]; - - x.method::(v); // error: only one type parameter is expected! -} -``` - -To fix it, just specify a correct number of type parameters: - -``` -struct Test; - -impl Test { - fn method(&self, v: &[T]) -> usize { - v.len() - } -} - -fn main() { - let x = Test; - let v = &[0]; - - x.method::(v); // OK, we're good! -} -``` - -Please note on the last example that we could have called `method` like this: - -``` -# struct Test; -# impl Test { fn method(&self, v: &[T]) -> usize { v.len() } } -# let x = Test; -# let v = &[0]; -x.method(v); -``` -"##, - E0040: r##" It is not allowed to manually call destructors in Rust. It is also not necessary to do this since `drop` is called automatically whenever a value goes @@ -4681,6 +4595,8 @@ error, just declare a function. } register_diagnostics! { +// E0035, merged into E0087/E0089 +// E0036, merged into E0087/E0089 // E0068, // E0085, // E0086, diff --git a/src/librustc_typeck/impl_wf_check.rs b/src/librustc_typeck/impl_wf_check.rs index 6b4f08d3d4c8d..14e48b9302964 100644 --- a/src/librustc_typeck/impl_wf_check.rs +++ b/src/librustc_typeck/impl_wf_check.rs @@ -102,7 +102,7 @@ fn enforce_impl_params_are_constrained<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let mut input_parameters = ctp::parameters_for_impl(impl_self_ty, impl_trait_ref); ctp::identify_constrained_type_params( - &impl_predicates.predicates.as_slice(), impl_trait_ref, &mut input_parameters); + tcx, &impl_predicates.predicates.as_slice(), impl_trait_ref, &mut input_parameters); // Disallow ANY unconstrained type parameters. for (ty_param, param) in impl_generics.types.iter().zip(&impl_hir_generics.ty_params) { diff --git a/src/librustc_typeck/variance/constraints.rs b/src/librustc_typeck/variance/constraints.rs index f4963619370e4..284c9c5cfc398 100644 --- a/src/librustc_typeck/variance/constraints.rs +++ b/src/librustc_typeck/variance/constraints.rs @@ -324,7 +324,8 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { } ty::TyProjection(ref data) => { - self.add_constraints_from_trait_ref(current, data.trait_ref, variance); + let tcx = self.tcx(); + self.add_constraints_from_trait_ref(current, data.trait_ref(tcx), variance); } ty::TyAnon(_, substs) => { diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 478e2fc5085d1..9d0b5b41a913f 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -952,15 +952,15 @@ impl<'tcx> Clean for ty::ProjectionPredicate<'tcx> { impl<'tcx> Clean for ty::ProjectionTy<'tcx> { fn clean(&self, cx: &DocContext) -> Type { - let trait_ = match self.trait_ref.clean(cx) { + let trait_ = match self.trait_ref(cx.tcx).clean(cx) { TyParamBound::TraitBound(t, _) => t.trait_, TyParamBound::RegionBound(_) => { panic!("cleaning a trait got a region") } }; Type::QPath { - name: self.item_name(cx.tcx).clean(cx), - self_type: box self.trait_ref.self_ty().clean(cx), + name: cx.tcx.associated_item(self.item_def_id).name.clean(cx), + self_type: box self.self_ty().clean(cx), trait_: box trait_ } } @@ -1784,7 +1784,7 @@ impl Clean for hir::Ty { let mut def = Def::Err; let ty = hir_ty_to_ty(cx.tcx, self); if let ty::TyProjection(proj) = ty.sty { - def = Def::Trait(proj.trait_ref.def_id); + def = Def::Trait(proj.trait_ref(cx.tcx).def_id); } let trait_path = hir::Path { span: self.span, @@ -1901,7 +1901,7 @@ impl<'tcx> Clean for ty::Ty<'tcx> { let mut bindings = vec![]; for ty::Binder(ref pb) in obj.projection_bounds() { bindings.push(TypeBinding { - name: pb.item_name.clean(cx), + name: cx.tcx.associated_item(pb.item_def_id).name.clean(cx), ty: pb.ty.clean(cx) }); } diff --git a/src/libstd/error.rs b/src/libstd/error.rs index d77f817659c56..d1c2bfb96b336 100644 --- a/src/libstd/error.rs +++ b/src/libstd/error.rs @@ -340,7 +340,7 @@ impl Error for char::CharTryFromError { } } -#[stable(feature = "char_from_str", since = "1.19.0")] +#[stable(feature = "char_from_str", since = "1.20.0")] impl Error for char::ParseCharError { fn description(&self) -> &str { self.__description() diff --git a/src/libstd/f32.rs b/src/libstd/f32.rs index a6eb17c8fa41b..9bacfee055385 100644 --- a/src/libstd/f32.rs +++ b/src/libstd/f32.rs @@ -1090,12 +1090,11 @@ impl f32 { /// # Examples /// /// ``` - /// #![feature(float_bits_conv)] /// assert_ne!((1f32).to_bits(), 1f32 as u32); // to_bits() is not casting! /// assert_eq!((12.5f32).to_bits(), 0x41480000); /// /// ``` - #[unstable(feature = "float_bits_conv", reason = "recently added", issue = "40470")] + #[stable(feature = "float_bits_conv", since = "1.21.0")] #[inline] pub fn to_bits(self) -> u32 { unsafe { ::mem::transmute(self) } @@ -1118,7 +1117,6 @@ impl f32 { /// # Examples /// /// ``` - /// #![feature(float_bits_conv)] /// use std::f32; /// let v = f32::from_bits(0x41480000); /// let difference = (v - 12.5).abs(); @@ -1127,7 +1125,7 @@ impl f32 { /// let snan = 0x7F800001; /// assert_ne!(f32::from_bits(snan).to_bits(), snan); /// ``` - #[unstable(feature = "float_bits_conv", reason = "recently added", issue = "40470")] + #[stable(feature = "float_bits_conv", since = "1.21.0")] #[inline] pub fn from_bits(mut v: u32) -> Self { const EXP_MASK: u32 = 0x7F800000; diff --git a/src/libstd/f64.rs b/src/libstd/f64.rs index 4d8d8b4ebe6aa..5236048ade43f 100644 --- a/src/libstd/f64.rs +++ b/src/libstd/f64.rs @@ -1005,12 +1005,11 @@ impl f64 { /// # Examples /// /// ``` - /// #![feature(float_bits_conv)] /// assert!((1f64).to_bits() != 1f64 as u64); // to_bits() is not casting! /// assert_eq!((12.5f64).to_bits(), 0x4029000000000000); /// /// ``` - #[unstable(feature = "float_bits_conv", reason = "recently added", issue = "40470")] + #[stable(feature = "float_bits_conv", since = "1.21.0")] #[inline] pub fn to_bits(self) -> u64 { unsafe { ::mem::transmute(self) } @@ -1033,7 +1032,6 @@ impl f64 { /// # Examples /// /// ``` - /// #![feature(float_bits_conv)] /// use std::f64; /// let v = f64::from_bits(0x4029000000000000); /// let difference = (v - 12.5).abs(); @@ -1042,7 +1040,7 @@ impl f64 { /// let snan = 0x7FF0000000000001; /// assert_ne!(f64::from_bits(snan).to_bits(), snan); /// ``` - #[unstable(feature = "float_bits_conv", reason = "recently added", issue = "40470")] + #[stable(feature = "float_bits_conv", since = "1.21.0")] #[inline] pub fn from_bits(mut v: u64) -> Self { const EXP_MASK: u64 = 0x7FF0000000000000; diff --git a/src/libstd/io/buffered.rs b/src/libstd/io/buffered.rs index 296ee78aadb22..1b832453523fb 100644 --- a/src/libstd/io/buffered.rs +++ b/src/libstd/io/buffered.rs @@ -276,7 +276,10 @@ impl Seek for BufReader { /// `BufWriter` keeps an in-memory buffer of data and writes it to an underlying /// writer in large, infrequent batches. /// -/// The buffer will be written out when the writer is dropped. +/// When the `BufWriter` is dropped, the contents of its buffer will be written +/// out. However, any errors that happen in the process of flushing the buffer +/// when the writer is dropped will be ignored. Code that wishes to handle such +/// errors must manually call [`flush`] before the writer is dropped. /// /// # Examples /// @@ -316,6 +319,7 @@ impl Seek for BufReader { /// [`Write`]: ../../std/io/trait.Write.html /// [`Tcpstream::write`]: ../../std/net/struct.TcpStream.html#method.write /// [`TcpStream`]: ../../std/net/struct.TcpStream.html +/// [`flush`]: #method.flush #[stable(feature = "rust1", since = "1.0.0")] pub struct BufWriter { inner: Option, diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index 71c76008244e6..9a3036f753ed3 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -1755,6 +1755,35 @@ impl Take { #[stable(feature = "rust1", since = "1.0.0")] pub fn limit(&self) -> u64 { self.limit } + /// Sets the number of bytes that can be read before this instance will + /// return EOF. This is the same as constructing a new `Take` instance, so + /// the amount of bytes read and the previous limit value don't matter when + /// calling this method. + /// + /// # Examples + /// + /// ``` + /// #![feature(take_set_limit)] + /// use std::io; + /// use std::io::prelude::*; + /// use std::fs::File; + /// + /// # fn foo() -> io::Result<()> { + /// let f = File::open("foo.txt")?; + /// + /// // read at most five bytes + /// let mut handle = f.take(5); + /// handle.set_limit(10); + /// + /// assert_eq!(handle.limit(), 10); + /// # Ok(()) + /// # } + /// ``` + #[unstable(feature = "take_set_limit", issue = "42781")] + pub fn set_limit(&mut self, limit: u64) { + self.limit = limit; + } + /// Consumes the `Take`, returning the wrapped reader. /// /// # Examples diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 2fc107c663bb4..a012f2f42c19c 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -277,6 +277,7 @@ #![feature(link_args)] #![feature(linkage)] #![feature(macro_reexport)] +#![feature(macro_vis_matcher)] #![feature(needs_panic_runtime)] #![feature(needs_drop)] #![feature(never_type)] @@ -316,7 +317,6 @@ #![feature(unwind_attributes)] #![feature(vec_push_all)] #![cfg_attr(test, feature(update_panic_count))] -#![cfg_attr(test, feature(float_bits_conv))] #![cfg_attr(not(stage0), default_lib_allocator)] #![cfg_attr(stage0, feature(associated_consts))] diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs index 6eb9faacf7fbe..6ad22820a7d90 100644 --- a/src/libstd/macros.rs +++ b/src/libstd/macros.rs @@ -24,6 +24,11 @@ /// The multi-argument form of this macro panics with a string and has the /// `format!` syntax for building a string. /// +/// # Current implementation +/// +/// If the main thread panics it will terminate all your threads and end your +/// program with code `101`. +/// /// # Examples /// /// ```should_panic diff --git a/src/libstd/path.rs b/src/libstd/path.rs index e7c7be981d25f..432605cf3b25b 100644 --- a/src/libstd/path.rs +++ b/src/libstd/path.rs @@ -135,12 +135,12 @@ use sys::path::{is_sep_byte, is_verbatim_sep, MAIN_SEP_STR, parse_prefix}; /// get_path_prefix(r"\\?\pictures\kittens")); /// assert_eq!(VerbatimUNC(OsStr::new("server"), OsStr::new("share")), /// get_path_prefix(r"\\?\UNC\server\share")); -/// assert_eq!(VerbatimDisk('C' as u8), get_path_prefix(r"\\?\c:\")); +/// assert_eq!(VerbatimDisk(b'C'), get_path_prefix(r"\\?\c:\")); /// assert_eq!(DeviceNS(OsStr::new("BrainInterface")), /// get_path_prefix(r"\\.\BrainInterface")); /// assert_eq!(UNC(OsStr::new("server"), OsStr::new("share")), /// get_path_prefix(r"\\server\share")); -/// assert_eq!(Disk('C' as u8), get_path_prefix(r"C:\Users\Rust\Pictures\Ferris")); +/// assert_eq!(Disk(b'C'), get_path_prefix(r"C:\Users\Rust\Pictures\Ferris")); /// # } /// ``` #[derive(Copy, Clone, Debug, Hash, PartialOrd, Ord, PartialEq, Eq)] @@ -235,10 +235,10 @@ impl<'a> Prefix<'a> { /// /// assert!(Verbatim(OsStr::new("pictures")).is_verbatim()); /// assert!(VerbatimUNC(OsStr::new("server"), OsStr::new("share")).is_verbatim()); - /// assert!(VerbatimDisk('C' as u8).is_verbatim()); + /// assert!(VerbatimDisk(b'C').is_verbatim()); /// assert!(!DeviceNS(OsStr::new("BrainInterface")).is_verbatim()); /// assert!(!UNC(OsStr::new("server"), OsStr::new("share")).is_verbatim()); - /// assert!(!Disk('C' as u8).is_verbatim()); + /// assert!(!Disk(b'C').is_verbatim()); /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] @@ -401,7 +401,7 @@ enum State { /// let path = Path::new(r"c:\you\later\"); /// match path.components().next().unwrap() { /// Component::Prefix(prefix_component) => { -/// assert_eq!(Prefix::Disk('C' as u8), prefix_component.kind()); +/// assert_eq!(Prefix::Disk(b'C'), prefix_component.kind()); /// assert_eq!(OsStr::new("c:"), prefix_component.as_os_str()); /// } /// _ => unreachable!(), @@ -1040,7 +1040,7 @@ impl<'a> cmp::Ord for Components<'a> { /// [`Deref`]: ../ops/trait.Deref.html /// /// More details about the overall approach can be found in -/// the module documentation. +/// the [module documentation](index.html). /// /// # Examples /// @@ -1186,7 +1186,7 @@ impl PathBuf { self.inner.push(path); } - /// Truncate `self` to [`self.parent`]. + /// Truncates `self` to [`self.parent`]. /// /// Returns `false` and does nothing if [`self.file_name`] is [`None`]. /// Otherwise, returns `true`. @@ -1512,7 +1512,7 @@ impl AsRef for PathBuf { /// [`PathBuf`]: struct.PathBuf.html /// /// More details about the overall approach can be found in -/// the module documentation. +/// the [module documentation](index.html). /// /// # Examples /// @@ -1689,7 +1689,7 @@ impl Path { self.has_root() && (cfg!(unix) || cfg!(target_os = "redox") || self.prefix().is_some()) } - /// Return `false` if the `Path` is relative, i.e. not absolute. + /// Returns `true` if the `Path` is relative, i.e. not absolute. /// /// See [`is_absolute`]'s documentation for more details. /// @@ -2019,7 +2019,7 @@ impl Path { /// * Repeated separators are ignored, so `a/b` and `a//b` both have /// `a` and `b` as components. /// - /// * Occurentces of `.` are normalized away, exept if they are at the + /// * Occurences of `.` are normalized away, except if they are at the /// beginning of the path. For example, `a/./b`, `a/b/`, `a/b/.` and /// `a/b` all have `a` and `b` as components, but `./a/b` starts with /// an additional [`CurDir`] component. @@ -2216,12 +2216,22 @@ impl Path { /// This function will traverse symbolic links to query information about the /// destination file. In case of broken symbolic links this will return `false`. /// + /// If you cannot access the directory containing the file, e.g. because of a + /// permission error, this will return `false`. + /// /// # Examples /// /// ```no_run /// use std::path::Path; /// assert_eq!(Path::new("does_not_exist.txt").exists(), false); /// ``` + /// + /// # See Also + /// + /// This is a convenience function that coerces errors to false. If you want to + /// check errors, call [fs::metadata]. + /// + /// [fs::metadata]: ../../std/fs/fn.metadata.html #[stable(feature = "path_ext", since = "1.5.0")] pub fn exists(&self) -> bool { fs::metadata(self).is_ok() @@ -2232,6 +2242,9 @@ impl Path { /// This function will traverse symbolic links to query information about the /// destination file. In case of broken symbolic links this will return `false`. /// + /// If you cannot access the directory containing the file, e.g. because of a + /// permission error, this will return `false`. + /// /// # Examples /// /// ```no_run @@ -2239,6 +2252,15 @@ impl Path { /// assert_eq!(Path::new("./is_a_directory/").is_file(), false); /// assert_eq!(Path::new("a_file.txt").is_file(), true); /// ``` + /// + /// # See Also + /// + /// This is a convenience function that coerces errors to false. If you want to + /// check errors, call [fs::metadata] and handle its Result. Then call + /// [fs::Metadata::is_file] if it was Ok. + /// + /// [fs::metadata]: ../../std/fs/fn.metadata.html + /// [fs::Metadata::is_file]: ../../std/fs/struct.Metadata.html#method.is_file #[stable(feature = "path_ext", since = "1.5.0")] pub fn is_file(&self) -> bool { fs::metadata(self).map(|m| m.is_file()).unwrap_or(false) @@ -2249,6 +2271,9 @@ impl Path { /// This function will traverse symbolic links to query information about the /// destination file. In case of broken symbolic links this will return `false`. /// + /// If you cannot access the directory containing the file, e.g. because of a + /// permission error, this will return `false`. + /// /// # Examples /// /// ```no_run @@ -2256,6 +2281,15 @@ impl Path { /// assert_eq!(Path::new("./is_a_directory/").is_dir(), true); /// assert_eq!(Path::new("a_file.txt").is_dir(), false); /// ``` + /// + /// # See Also + /// + /// This is a convenience function that coerces errors to false. If you want to + /// check errors, call [fs::metadata] and handle its Result. Then call + /// [fs::Metadata::is_dir] if it was Ok. + /// + /// [fs::metadata]: ../../std/fs/fn.metadata.html + /// [fs::Metadata::is_dir]: ../../std/fs/struct.Metadata.html#method.is_dir #[stable(feature = "path_ext", since = "1.5.0")] pub fn is_dir(&self) -> bool { fs::metadata(self).map(|m| m.is_dir()).unwrap_or(false) diff --git a/src/libstd/sync/mutex.rs b/src/libstd/sync/mutex.rs index fc6c7de9ef083..62d8de18f4b45 100644 --- a/src/libstd/sync/mutex.rs +++ b/src/libstd/sync/mutex.rs @@ -440,7 +440,7 @@ impl<'a, T: ?Sized + fmt::Debug> fmt::Debug for MutexGuard<'a, T> { } } -#[stable(feature = "std_guard_impls", since = "1.20")] +#[stable(feature = "std_guard_impls", since = "1.20.0")] impl<'a, T: ?Sized + fmt::Display> fmt::Display for MutexGuard<'a, T> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { (**self).fmt(f) diff --git a/src/libstd/sync/rwlock.rs b/src/libstd/sync/rwlock.rs index 944801e8a3bf0..5c5231f4e84a3 100644 --- a/src/libstd/sync/rwlock.rs +++ b/src/libstd/sync/rwlock.rs @@ -370,7 +370,7 @@ impl<'a, T: fmt::Debug> fmt::Debug for RwLockReadGuard<'a, T> { } } -#[stable(feature = "std_guard_impls", since = "1.20")] +#[stable(feature = "std_guard_impls", since = "1.20.0")] impl<'a, T: ?Sized + fmt::Display> fmt::Display for RwLockReadGuard<'a, T> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { (**self).fmt(f) @@ -386,7 +386,7 @@ impl<'a, T: fmt::Debug> fmt::Debug for RwLockWriteGuard<'a, T> { } } -#[stable(feature = "std_guard_impls", since = "1.20")] +#[stable(feature = "std_guard_impls", since = "1.20.0")] impl<'a, T: ?Sized + fmt::Display> fmt::Display for RwLockWriteGuard<'a, T> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { (**self).fmt(f) diff --git a/src/libstd/sys/redox/backtrace.rs b/src/libstd/sys/redox/backtrace.rs index 961148fb6b4a8..6cafe3e69bac1 100644 --- a/src/libstd/sys/redox/backtrace.rs +++ b/src/libstd/sys/redox/backtrace.rs @@ -8,16 +8,25 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use libc; use io; use sys_common::backtrace::Frame; -pub use sys_common::gnu::libbacktrace::*; +pub use sys_common::gnu::libbacktrace::{foreach_symbol_fileline, resolve_symname}; pub struct BacktraceContext; #[inline(never)] -pub fn unwind_backtrace(frames: &mut [Frame]) +pub fn unwind_backtrace(_frames: &mut [Frame]) -> io::Result<(usize, BacktraceContext)> { Ok((0, BacktraceContext)) } + +pub mod gnu { + use io; + use fs; + use libc::c_char; + + pub fn get_executable_filename() -> io::Result<(Vec, fs::File)> { + Err(io::Error::new(io::ErrorKind::Other, "Not implemented")) + } +} diff --git a/src/libstd/sys/redox/ext/fs.rs b/src/libstd/sys/redox/ext/fs.rs index 4437cf43920c5..9a0d1e06da327 100644 --- a/src/libstd/sys/redox/ext/fs.rs +++ b/src/libstd/sys/redox/ext/fs.rs @@ -177,6 +177,8 @@ pub trait MetadataExt { #[stable(feature = "metadata_ext", since = "1.1.0")] fn mode(&self) -> u32; #[stable(feature = "metadata_ext", since = "1.1.0")] + fn nlink(&self) -> u64; + #[stable(feature = "metadata_ext", since = "1.1.0")] fn uid(&self) -> u32; #[stable(feature = "metadata_ext", since = "1.1.0")] fn gid(&self) -> u32; @@ -194,6 +196,10 @@ pub trait MetadataExt { fn ctime(&self) -> i64; #[stable(feature = "metadata_ext", since = "1.1.0")] fn ctime_nsec(&self) -> i64; + #[stable(feature = "metadata_ext", since = "1.1.0")] + fn blksize(&self) -> u64; + #[stable(feature = "metadata_ext", since = "1.1.0")] + fn blocks(&self) -> u64; } #[stable(feature = "metadata_ext", since = "1.1.0")] @@ -207,6 +213,9 @@ impl MetadataExt for fs::Metadata { fn mode(&self) -> u32 { self.as_inner().as_inner().st_mode as u32 } + fn nlink(&self) -> u64 { + self.as_inner().as_inner().st_nlink as u64 + } fn uid(&self) -> u32 { self.as_inner().as_inner().st_uid as u32 } @@ -234,6 +243,12 @@ impl MetadataExt for fs::Metadata { fn ctime_nsec(&self) -> i64 { self.as_inner().as_inner().st_ctime_nsec as i64 } + fn blksize(&self) -> u64 { + self.as_inner().as_inner().st_blksize as u64 + } + fn blocks(&self) -> u64 { + self.as_inner().as_inner().st_blocks as u64 + } } /// Add special Redox types (block/char device, fifo and socket) diff --git a/src/libstd/sys/redox/fs.rs b/src/libstd/sys/redox/fs.rs index c5a19e8debe93..918893097f841 100644 --- a/src/libstd/sys/redox/fs.rs +++ b/src/libstd/sys/redox/fs.rs @@ -119,10 +119,10 @@ impl FilePermissions { impl FileType { pub fn is_dir(&self) -> bool { self.is(syscall::MODE_DIR) } pub fn is_file(&self) -> bool { self.is(syscall::MODE_FILE) } - pub fn is_symlink(&self) -> bool { false /*FIXME: Implement symlink mode*/ } + pub fn is_symlink(&self) -> bool { self.is(syscall::MODE_SYMLINK) } pub fn is(&self, mode: u16) -> bool { - self.mode & (syscall::MODE_DIR | syscall::MODE_FILE) == mode + self.mode & syscall::MODE_TYPE == mode } } @@ -383,9 +383,10 @@ pub fn unlink(p: &Path) -> io::Result<()> { Ok(()) } -pub fn rename(_old: &Path, _new: &Path) -> io::Result<()> { - ::sys_common::util::dumb_print(format_args!("Rename\n")); - unimplemented!(); +pub fn rename(old: &Path, new: &Path) -> io::Result<()> { + copy(old, new)?; + unlink(old)?; + Ok(()) } pub fn set_perm(p: &Path, perm: FilePermissions) -> io::Result<()> { @@ -447,7 +448,10 @@ pub fn stat(p: &Path) -> io::Result { } pub fn lstat(p: &Path) -> io::Result { - stat(p) + let fd = cvt(syscall::open(p.to_str().unwrap(), + syscall::O_CLOEXEC | syscall::O_STAT | syscall::O_NOFOLLOW))?; + let file = File(FileDesc::new(fd)); + file.file_attr() } pub fn canonicalize(p: &Path) -> io::Result { diff --git a/src/libstd/sys/redox/mod.rs b/src/libstd/sys/redox/mod.rs index 31c40ea58b1de..7c728ebb1af2e 100644 --- a/src/libstd/sys/redox/mod.rs +++ b/src/libstd/sys/redox/mod.rs @@ -39,25 +39,7 @@ pub mod thread_local; pub mod time; #[cfg(not(test))] -pub fn init() { - use alloc::oom; - - oom::set_oom_handler(oom_handler); - - // A nicer handler for out-of-memory situations than the default one. This - // one prints a message to stderr before aborting. It is critical that this - // code does not allocate any memory since we are in an OOM situation. Any - // errors are ignored while printing since there's nothing we can do about - // them and we are about to exit anyways. - fn oom_handler() -> ! { - use intrinsics; - let msg = "fatal runtime error: out of memory\n"; - unsafe { - let _ = syscall::write(2, msg.as_bytes()); - intrinsics::abort(); - } - } -} +pub fn init() {} pub fn decode_error_kind(errno: i32) -> ErrorKind { match errno { diff --git a/src/libstd/sys/redox/net/tcp.rs b/src/libstd/sys/redox/net/tcp.rs index 5d1067e4039ba..98ec3aa3e2959 100644 --- a/src/libstd/sys/redox/net/tcp.rs +++ b/src/libstd/sys/redox/net/tcp.rs @@ -32,7 +32,7 @@ impl TcpStream { Ok(TcpStream(File::open(&Path::new(path.as_str()), &options)?)) } - pub fn connect_timeout(_addr: &SocketAddr, _timeout: Duration) -> Result<()> { + pub fn connect_timeout(_addr: &SocketAddr, _timeout: Duration) -> Result { Err(Error::new(ErrorKind::Other, "TcpStream::connect_timeout not implemented")) } diff --git a/src/libstd/sys/redox/syscall/flag.rs b/src/libstd/sys/redox/syscall/flag.rs index bd603cfe6ef9d..65ad9842d699a 100644 --- a/src/libstd/sys/redox/syscall/flag.rs +++ b/src/libstd/sys/redox/syscall/flag.rs @@ -55,6 +55,7 @@ pub const O_EXCL: usize = 0x0800_0000; pub const O_DIRECTORY: usize = 0x1000_0000; pub const O_STAT: usize = 0x2000_0000; pub const O_SYMLINK: usize = 0x4000_0000; +pub const O_NOFOLLOW: usize = 0x8000_0000; pub const O_ACCMODE: usize = O_RDONLY | O_WRONLY | O_RDWR; pub const SEEK_SET: usize = 0; diff --git a/src/libstd/sys/windows/ext/fs.rs b/src/libstd/sys/windows/ext/fs.rs index 67348a0049417..a1c63e3358840 100644 --- a/src/libstd/sys/windows/ext/fs.rs +++ b/src/libstd/sys/windows/ext/fs.rs @@ -477,7 +477,7 @@ pub fn symlink_file, Q: AsRef>(src: P, dst: Q) /// use std::os::windows::fs; /// /// # fn foo() -> std::io::Result<()> { -/// fs::symlink_file("a", "b")?; +/// fs::symlink_dir("a", "b")?; /// # Ok(()) /// # } /// ``` diff --git a/src/libstd/sys_common/mod.rs b/src/libstd/sys_common/mod.rs index d4d3365dc0198..ccd4b91a7b733 100644 --- a/src/libstd/sys_common/mod.rs +++ b/src/libstd/sys_common/mod.rs @@ -52,7 +52,8 @@ pub mod net; #[cfg(feature = "backtrace")] #[cfg(any(all(unix, not(any(target_os = "macos", target_os = "ios", target_os = "emscripten"))), - all(windows, target_env = "gnu")))] + all(windows, target_env = "gnu"), + target_os = "redox"))] pub mod gnu; // common error constructors diff --git a/src/libstd/sys_common/thread_info.rs b/src/libstd/sys_common/thread_info.rs index 5ed48ee455871..2abb8afa82848 100644 --- a/src/libstd/sys_common/thread_info.rs +++ b/src/libstd/sys_common/thread_info.rs @@ -12,7 +12,6 @@ use cell::RefCell; use thread::Thread; -use thread::LocalKeyState; struct ThreadInfo { stack_guard: Option, @@ -23,19 +22,15 @@ thread_local! { static THREAD_INFO: RefCell> = RefCell::new(N impl ThreadInfo { fn with(f: F) -> Option where F: FnOnce(&mut ThreadInfo) -> R { - if THREAD_INFO.state() == LocalKeyState::Destroyed { - return None - } - - THREAD_INFO.with(move |c| { + THREAD_INFO.try_with(move |c| { if c.borrow().is_none() { *c.borrow_mut() = Some(ThreadInfo { stack_guard: None, thread: Thread::new(None), }) } - Some(f(c.borrow_mut().as_mut().unwrap())) - }) + f(c.borrow_mut().as_mut().unwrap()) + }).ok() } } diff --git a/src/libstd/thread/local.rs b/src/libstd/thread/local.rs index dad21473eae1e..be433e2b81e6b 100644 --- a/src/libstd/thread/local.rs +++ b/src/libstd/thread/local.rs @@ -110,12 +110,13 @@ impl fmt::Debug for LocalKey { } } +#[cfg(not(stage0))] /// Declare a new thread local storage key of type [`std::thread::LocalKey`]. /// /// # Syntax /// /// The macro wraps any number of static declarations and makes them thread local. -/// Each static may be public or private, and attributes are allowed. Example: +/// Publicity and attributes for each static are allowed. Example: /// /// ``` /// use std::cell::RefCell; @@ -135,6 +136,60 @@ impl fmt::Debug for LocalKey { #[macro_export] #[stable(feature = "rust1", since = "1.0.0")] #[allow_internal_unstable] +macro_rules! thread_local { + // empty (base case for the recursion) + () => {}; + + // process multiple declarations + ($(#[$attr:meta])* $vis:vis static $name:ident: $t:ty = $init:expr; $($rest:tt)*) => ( + __thread_local_inner!($(#[$attr])* $vis $name, $t, $init); + thread_local!($($rest)*); + ); + + // handle a single declaration + ($(#[$attr:meta])* $vis:vis static $name:ident: $t:ty = $init:expr) => ( + __thread_local_inner!($(#[$attr])* $vis $name, $t, $init); + ); +} + +#[cfg(not(stage0))] +#[doc(hidden)] +#[unstable(feature = "thread_local_internals", + reason = "should not be necessary", + issue = "0")] +#[macro_export] +#[allow_internal_unstable] +macro_rules! __thread_local_inner { + ($(#[$attr:meta])* $vis:vis $name:ident, $t:ty, $init:expr) => { + $(#[$attr])* $vis static $name: $crate::thread::LocalKey<$t> = { + fn __init() -> $t { $init } + + fn __getit() -> $crate::option::Option< + &'static $crate::cell::UnsafeCell< + $crate::option::Option<$t>>> + { + #[thread_local] + #[cfg(target_thread_local)] + static __KEY: $crate::thread::__FastLocalKeyInner<$t> = + $crate::thread::__FastLocalKeyInner::new(); + + #[cfg(not(target_thread_local))] + static __KEY: $crate::thread::__OsLocalKeyInner<$t> = + $crate::thread::__OsLocalKeyInner::new(); + + __KEY.get() + } + + $crate::thread::LocalKey::new(__getit, __init) + }; + } +} + +#[cfg(stage0)] +/// Declare a new thread local storage key of type `std::thread::LocalKey`. +#[macro_export] +#[stable(feature = "rust1", since = "1.0.0")] +#[allow_internal_unstable] macro_rules! thread_local { // rule 0: empty (base case for the recursion) () => {}; @@ -164,6 +219,7 @@ macro_rules! thread_local { ); } +#[cfg(stage0)] #[doc(hidden)] #[unstable(feature = "thread_local_internals", reason = "should not be necessary", @@ -232,6 +288,32 @@ pub enum LocalKeyState { Destroyed, } +/// An error returned by [`LocalKey::try_with`](struct.LocalKey.html#method.try_with). +#[unstable(feature = "thread_local_state", + reason = "state querying was recently added", + issue = "27716")] +pub struct AccessError { + _private: (), +} + +#[unstable(feature = "thread_local_state", + reason = "state querying was recently added", + issue = "27716")] +impl fmt::Debug for AccessError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("AccessError").finish() + } +} + +#[unstable(feature = "thread_local_state", + reason = "state querying was recently added", + issue = "27716")] +impl fmt::Display for AccessError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Display::fmt("already destroyed", f) + } +} + impl LocalKey { #[doc(hidden)] #[unstable(feature = "thread_local_internals", @@ -258,15 +340,8 @@ impl LocalKey { #[stable(feature = "rust1", since = "1.0.0")] pub fn with(&'static self, f: F) -> R where F: FnOnce(&T) -> R { - unsafe { - let slot = (self.inner)(); - let slot = slot.expect("cannot access a TLS value during or \ - after it is destroyed"); - f(match *slot.get() { - Some(ref inner) => inner, - None => self.init(slot), - }) - } + self.try_with(f).expect("cannot access a TLS value during or \ + after it is destroyed") } unsafe fn init(&self, slot: &UnsafeCell>) -> &T { @@ -331,6 +406,32 @@ impl LocalKey { } } } + + /// Acquires a reference to the value in this TLS key. + /// + /// This will lazily initialize the value if this thread has not referenced + /// this key yet. If the key has been destroyed (which may happen if this is called + /// in a destructor), this function will return a ThreadLocalError. + /// + /// # Panics + /// + /// This function will still `panic!()` if the key is uninitialized and the + /// key's initializer panics. + #[unstable(feature = "thread_local_state", + reason = "state querying was recently added", + issue = "27716")] + pub fn try_with(&'static self, f: F) -> Result + where F: FnOnce(&T) -> R { + unsafe { + let slot = (self.inner)().ok_or(AccessError { + _private: (), + })?; + Ok(f(match *slot.get() { + Some(ref inner) => inner, + None => self.init(slot), + })) + } + } } #[doc(hidden)] diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs index f4fe52ca3b36c..07a3a01ce8666 100644 --- a/src/libstd/thread/mod.rs +++ b/src/libstd/thread/mod.rs @@ -159,7 +159,7 @@ use time::Duration; #[macro_use] mod local; #[stable(feature = "rust1", since = "1.0.0")] -pub use self::local::{LocalKey, LocalKeyState}; +pub use self::local::{LocalKey, LocalKeyState, AccessError}; // The types used by the thread_local! macro to access TLS keys. Note that there // are two types, the "OS" type and the "fast" type. The OS thread local key diff --git a/src/libstd_unicode/char.rs b/src/libstd_unicode/char.rs index d4d8993efb316..d6836418b4b5c 100644 --- a/src/libstd_unicode/char.rs +++ b/src/libstd_unicode/char.rs @@ -38,7 +38,7 @@ use tables::{conversions, derived_property, general_category, property}; pub use core::char::{MAX, from_digit, from_u32, from_u32_unchecked}; #[stable(feature = "rust1", since = "1.0.0")] pub use core::char::{EscapeDebug, EscapeDefault, EscapeUnicode}; -#[stable(feature = "char_from_str", since = "1.19.0")] +#[stable(feature = "char_from_str", since = "1.20.0")] pub use core::char::ParseCharError; // unstable reexports diff --git a/src/libsyntax/ext/tt/macro_parser.rs b/src/libsyntax/ext/tt/macro_parser.rs index e877f1fedd409..d18961b75c84a 100644 --- a/src/libsyntax/ext/tt/macro_parser.rs +++ b/src/libsyntax/ext/tt/macro_parser.rs @@ -386,12 +386,11 @@ fn inner_parse_loop(sess: &ParseSess, return Error(span, "missing fragment specifier".to_string()); } } - TokenTree::MetaVarDecl(..) => { + TokenTree::MetaVarDecl(_, _, id) => { // Built-in nonterminals never start with these tokens, // so we can eliminate them from consideration. - match *token { - token::CloseDelim(_) => {}, - _ => bb_eis.push(ei), + if may_begin_with(&*id.name.as_str(), token) { + bb_eis.push(ei); } } seq @ TokenTree::Delimited(..) | seq @ TokenTree::Token(_, DocComment(..)) => { @@ -493,6 +492,73 @@ pub fn parse(sess: &ParseSess, } } +/// Checks whether a non-terminal may begin with a particular token. +/// +/// Returning `false` is a *stability guarantee* that such a matcher will *never* begin with that +/// token. Be conservative (return true) if not sure. +fn may_begin_with(name: &str, token: &Token) -> bool { + /// Checks whether the non-terminal may contain a single (non-keyword) identifier. + fn may_be_ident(nt: &token::Nonterminal) -> bool { + match *nt { + token::NtItem(_) | token::NtBlock(_) | token::NtVis(_) => false, + _ => true, + } + } + + match name { + "expr" => token.can_begin_expr(), + "ty" => token.can_begin_type(), + "ident" => token.is_ident(), + "vis" => match *token { // The follow-set of :vis + "priv" keyword + interpolated + Token::Comma | Token::Ident(_) | Token::Interpolated(_) => true, + _ => token.can_begin_type(), + }, + "block" => match *token { + Token::OpenDelim(token::Brace) => true, + Token::Interpolated(ref nt) => match nt.0 { + token::NtItem(_) | + token::NtPat(_) | + token::NtTy(_) | + token::NtIdent(_) | + token::NtMeta(_) | + token::NtPath(_) | + token::NtVis(_) => false, // none of these may start with '{'. + _ => true, + }, + _ => false, + }, + "path" | "meta" => match *token { + Token::ModSep | Token::Ident(_) => true, + Token::Interpolated(ref nt) => match nt.0 { + token::NtPath(_) | token::NtMeta(_) => true, + _ => may_be_ident(&nt.0), + }, + _ => false, + }, + "pat" => match *token { + Token::Ident(_) | // box, ref, mut, and other identifiers (can stricten) + Token::OpenDelim(token::Paren) | // tuple pattern + Token::OpenDelim(token::Bracket) | // slice pattern + Token::BinOp(token::And) | // reference + Token::BinOp(token::Minus) | // negative literal + Token::AndAnd | // double reference + Token::Literal(..) | // literal + Token::DotDot | // range pattern (future compat) + Token::DotDotDot | // range pattern (future compat) + Token::ModSep | // path + Token::Lt | // path (UFCS constant) + Token::BinOp(token::Shl) | // path (double UFCS) + Token::Underscore => true, // placeholder + Token::Interpolated(ref nt) => may_be_ident(&nt.0), + _ => false, + }, + _ => match *token { + token::CloseDelim(_) => false, + _ => true, + }, + } +} + fn parse_nt<'a>(p: &mut Parser<'a>, sp: Span, name: &str) -> Nonterminal { if name == "tt" { return token::NtTT(p.parse_token_tree()); diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index a98a9dd204046..f786b1abb8a1b 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -222,7 +222,7 @@ pub fn compile(sess: &ParseSess, features: &RefCell, def: &ast::Item) if let MatchedNonterminal(ref nt) = *m { if let NtTT(ref tt) = **nt { let tt = quoted::parse(tt.clone().into(), true, sess).pop().unwrap(); - valid &= check_lhs_nt_follows(sess, features, &tt); + valid &= check_lhs_nt_follows(sess, features, &def.attrs, &tt); return tt; } } @@ -272,11 +272,12 @@ pub fn compile(sess: &ParseSess, features: &RefCell, def: &ast::Item) fn check_lhs_nt_follows(sess: &ParseSess, features: &RefCell, + attrs: &[ast::Attribute], lhs: "ed::TokenTree) -> bool { // 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. if let quoted::TokenTree::Delimited(_, ref tts) = *lhs { - check_matcher(sess, features, &tts.tts) + check_matcher(sess, features, attrs, &tts.tts) } else { let msg = "invalid macro matcher; matchers must be contained in balanced delimiters"; sess.span_diagnostic.span_err(lhs.span(), msg); @@ -328,11 +329,12 @@ fn check_rhs(sess: &ParseSess, rhs: "ed::TokenTree) -> bool { fn check_matcher(sess: &ParseSess, features: &RefCell, + attrs: &[ast::Attribute], matcher: &[quoted::TokenTree]) -> bool { let first_sets = FirstSets::new(matcher); let empty_suffix = TokenSet::empty(); let err = sess.span_diagnostic.err_count(); - check_matcher_core(sess, features, &first_sets, matcher, &empty_suffix); + check_matcher_core(sess, features, attrs, &first_sets, matcher, &empty_suffix); err == sess.span_diagnostic.err_count() } @@ -575,6 +577,7 @@ impl TokenSet { // see `FirstSets::new`. fn check_matcher_core(sess: &ParseSess, features: &RefCell, + attrs: &[ast::Attribute], first_sets: &FirstSets, matcher: &[quoted::TokenTree], follow: &TokenSet) -> TokenSet { @@ -605,7 +608,7 @@ fn check_matcher_core(sess: &ParseSess, match *token { TokenTree::Token(..) | TokenTree::MetaVar(..) | TokenTree::MetaVarDecl(..) => { let can_be_followed_by_any; - if let Err(bad_frag) = has_legal_fragment_specifier(sess, features, token) { + if let Err(bad_frag) = has_legal_fragment_specifier(sess, features, attrs, token) { let msg = format!("invalid fragment specifier `{}`", bad_frag); sess.span_diagnostic.struct_span_err(token.span(), &msg) .help("valid fragment specifiers are `ident`, `block`, `stmt`, `expr`, \ @@ -631,7 +634,7 @@ fn check_matcher_core(sess: &ParseSess, } TokenTree::Delimited(span, ref d) => { let my_suffix = TokenSet::singleton(d.close_tt(span)); - check_matcher_core(sess, features, first_sets, &d.tts, &my_suffix); + check_matcher_core(sess, features, attrs, first_sets, &d.tts, &my_suffix); // don't track non NT tokens last.replace_with_irrelevant(); @@ -663,7 +666,12 @@ fn check_matcher_core(sess: &ParseSess, // At this point, `suffix_first` is built, and // `my_suffix` is some TokenSet that we can use // for checking the interior of `seq_rep`. - let next = check_matcher_core(sess, features, first_sets, &seq_rep.tts, my_suffix); + let next = check_matcher_core(sess, + features, + attrs, + first_sets, + &seq_rep.tts, + my_suffix); if next.maybe_empty { last.add_all(&next); } else { @@ -836,12 +844,13 @@ fn is_in_follow(tok: "ed::TokenTree, frag: &str) -> Result, + attrs: &[ast::Attribute], tok: "ed::TokenTree) -> Result<(), String> { debug!("has_legal_fragment_specifier({:?})", tok); if let quoted::TokenTree::MetaVarDecl(_, _, ref frag_spec) = *tok { let frag_name = frag_spec.name.as_str(); let frag_span = tok.span(); - if !is_legal_fragment_specifier(sess, features, &frag_name, frag_span) { + if !is_legal_fragment_specifier(sess, features, attrs, &frag_name, frag_span) { return Err(frag_name.to_string()); } } @@ -850,13 +859,15 @@ fn has_legal_fragment_specifier(sess: &ParseSess, fn is_legal_fragment_specifier(sess: &ParseSess, features: &RefCell, + attrs: &[ast::Attribute], frag_name: &str, frag_span: Span) -> bool { match frag_name { "item" | "block" | "stmt" | "expr" | "pat" | "path" | "ty" | "ident" | "meta" | "tt" | "" => true, "vis" => { - if !features.borrow().macro_vis_matcher { + if !features.borrow().macro_vis_matcher + && !attr::contains_name(attrs, "allow_internal_unstable") { let explain = feature_gate::EXPLAIN_VIS_MATCHER; emit_feature_err(sess, "macro_vis_matcher", diff --git a/src/libsyntax/ext/tt/quoted.rs b/src/libsyntax/ext/tt/quoted.rs index 4e9e30857b1e8..74fa85d130b02 100644 --- a/src/libsyntax/ext/tt/quoted.rs +++ b/src/libsyntax/ext/tt/quoted.rs @@ -196,7 +196,8 @@ fn parse_tree(tree: tokenstream::TokenTree, num_captures: name_captures, })) } - Some(tokenstream::TokenTree::Token(ident_span, token::Ident(ident))) => { + Some(tokenstream::TokenTree::Token(ident_span, ref token)) if token.is_ident() => { + let ident = token.ident().unwrap(); let span = Span { lo: span.lo, ..ident_span }; if ident.name == keywords::Crate.name() { let ident = ast::Ident { name: keywords::DollarCrate.name(), ..ident }; diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 093ab0073f0db..90d9ae383a491 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -1480,10 +1480,9 @@ impl<'a> Parser<'a> { match ty.node { TyKind::Rptr(ref lifetime, ref mut_ty) => { let sum_with_parens = pprust::to_string(|s| { - use print::pp::word; use print::pprust::PrintState; - word(&mut s.s, "&")?; + s.s.word("&")?; s.print_opt_lifetime(lifetime)?; s.print_mutability(mut_ty.mutbl)?; s.popen()?; @@ -1491,7 +1490,7 @@ impl<'a> Parser<'a> { s.print_bounds(" +", &bounds)?; s.pclose() }); - err.span_suggestion(sum_span, "try adding parentheses:", sum_with_parens); + err.span_suggestion(sum_span, "try adding parentheses", sum_with_parens); } TyKind::Ptr(..) | TyKind::BareFn(..) => { err.span_label(sum_span, "perhaps you forgot parentheses?"); @@ -2542,14 +2541,13 @@ impl<'a> Parser<'a> { }; let sugg = pprust::to_string(|s| { use print::pprust::PrintState; - use print::pp::word; s.popen()?; s.print_expr(&e)?; - word(&mut s.s, ".")?; + s.s.word( ".")?; s.print_usize(float.trunc() as usize)?; s.pclose()?; - word(&mut s.s, ".")?; - word(&mut s.s, fstr.splitn(2, ".").last().unwrap()) + s.s.word(".")?; + s.s.word(fstr.splitn(2, ".").last().unwrap()) }); err.span_suggestion( lo.to(self.prev_span), @@ -5282,7 +5280,7 @@ impl<'a> Parser<'a> { `pub(in path::to::module)`: visible only on the specified path"##; let path = self.parse_path(PathStyle::Mod)?; let path_span = self.prev_span; - let help_msg = format!("make this visible only to module `{}` with `in`:", path); + let help_msg = format!("make this visible only to module `{}` with `in`", path); self.expect(&token::CloseDelim(token::Paren))?; // `)` let mut err = self.span_fatal_help(path_span, msg, suggestion); err.span_suggestion(path_span, &help_msg, format!("in {}", path)); diff --git a/src/libsyntax/print/pp.rs b/src/libsyntax/print/pp.rs index 82b5d7e284bc6..3ce9e9d07b30c 100644 --- a/src/libsyntax/print/pp.rs +++ b/src/libsyntax/print/pp.rs @@ -262,7 +262,7 @@ pub fn mk_printer<'a>(out: Box, linewidth: usize) -> Printer<'a> { } pub struct Printer<'a> { - pub out: Box, + out: Box, buf_len: usize, /// Width of lines we're constrained to margin: isize, @@ -577,75 +577,75 @@ impl<'a> Printer<'a> { } } } -} -// Convenience functions to talk to the printer. + // Convenience functions to talk to the printer. -/// "raw box" -pub fn rbox(p: &mut Printer, indent: usize, b: Breaks) -> io::Result<()> { - p.pretty_print(Token::Begin(BeginToken { - offset: indent as isize, - breaks: b - })) -} + /// "raw box" + pub fn rbox(&mut self, indent: usize, b: Breaks) -> io::Result<()> { + self.pretty_print(Token::Begin(BeginToken { + offset: indent as isize, + breaks: b + })) + } -/// Inconsistent breaking box -pub fn ibox(p: &mut Printer, indent: usize) -> io::Result<()> { - rbox(p, indent, Breaks::Inconsistent) -} + /// Inconsistent breaking box + pub fn ibox(&mut self, indent: usize) -> io::Result<()> { + self.rbox(indent, Breaks::Inconsistent) + } -/// Consistent breaking box -pub fn cbox(p: &mut Printer, indent: usize) -> io::Result<()> { - rbox(p, indent, Breaks::Consistent) -} + /// Consistent breaking box + pub fn cbox(&mut self, indent: usize) -> io::Result<()> { + self.rbox(indent, Breaks::Consistent) + } -pub fn break_offset(p: &mut Printer, n: usize, off: isize) -> io::Result<()> { - p.pretty_print(Token::Break(BreakToken { - offset: off, - blank_space: n as isize - })) -} + pub fn break_offset(&mut self, n: usize, off: isize) -> io::Result<()> { + self.pretty_print(Token::Break(BreakToken { + offset: off, + blank_space: n as isize + })) + } -pub fn end(p: &mut Printer) -> io::Result<()> { - p.pretty_print(Token::End) -} + pub fn end(&mut self) -> io::Result<()> { + self.pretty_print(Token::End) + } -pub fn eof(p: &mut Printer) -> io::Result<()> { - p.pretty_print(Token::Eof) -} + pub fn eof(&mut self) -> io::Result<()> { + self.pretty_print(Token::Eof) + } -pub fn word(p: &mut Printer, wrd: &str) -> io::Result<()> { - p.pretty_print(Token::String(wrd.to_string(), wrd.len() as isize)) -} + pub fn word(&mut self, wrd: &str) -> io::Result<()> { + self.pretty_print(Token::String(wrd.to_string(), wrd.len() as isize)) + } -pub fn huge_word(p: &mut Printer, wrd: &str) -> io::Result<()> { - p.pretty_print(Token::String(wrd.to_string(), SIZE_INFINITY)) -} + pub fn huge_word(&mut self, wrd: &str) -> io::Result<()> { + self.pretty_print(Token::String(wrd.to_string(), SIZE_INFINITY)) + } -pub fn zero_word(p: &mut Printer, wrd: &str) -> io::Result<()> { - p.pretty_print(Token::String(wrd.to_string(), 0)) -} + pub fn zero_word(&mut self, wrd: &str) -> io::Result<()> { + self.pretty_print(Token::String(wrd.to_string(), 0)) + } -pub fn spaces(p: &mut Printer, n: usize) -> io::Result<()> { - break_offset(p, n, 0) -} + fn spaces(&mut self, n: usize) -> io::Result<()> { + self.break_offset(n, 0) + } -pub fn zerobreak(p: &mut Printer) -> io::Result<()> { - spaces(p, 0) -} + pub fn zerobreak(&mut self) -> io::Result<()> { + self.spaces(0) + } -pub fn space(p: &mut Printer) -> io::Result<()> { - spaces(p, 1) -} + pub fn space(&mut self) -> io::Result<()> { + self.spaces(1) + } -pub fn hardbreak(p: &mut Printer) -> io::Result<()> { - spaces(p, SIZE_INFINITY as usize) -} + pub fn hardbreak(&mut self) -> io::Result<()> { + self.spaces(SIZE_INFINITY as usize) + } -pub fn hardbreak_tok_offset(off: isize) -> Token { - Token::Break(BreakToken {offset: off, blank_space: SIZE_INFINITY}) -} + pub fn hardbreak_tok_offset(off: isize) -> Token { + Token::Break(BreakToken {offset: off, blank_space: SIZE_INFINITY}) + } -pub fn hardbreak_tok() -> Token { - hardbreak_tok_offset(0) + pub fn hardbreak_tok() -> Token { + Self::hardbreak_tok_offset(0) + } } diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 51c48f15f2975..b052b2cdbbb5a 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -21,8 +21,7 @@ use syntax_pos::{self, BytePos}; use parse::token::{self, BinOpToken, Token}; use parse::lexer::comments; use parse::{self, ParseSess}; -use print::pp::{self, break_offset, word, space, zerobreak, hardbreak}; -use print::pp::{Breaks, eof}; +use print::pp::{self, Breaks}; use print::pp::Breaks::{Consistent, Inconsistent}; use ptr::P; use std_inject; @@ -32,7 +31,8 @@ use tokenstream::{self, TokenStream, TokenTree}; use std::ascii; use std::io::{self, Write, Read}; -use std::iter; +use std::iter::{self, Peekable}; +use std::vec; pub enum AnnNode<'a> { NodeIdent(&'a ast::Ident), @@ -54,38 +54,23 @@ pub struct NoAnn; impl PpAnn for NoAnn {} -#[derive(Copy, Clone)] -pub struct CurrentCommentAndLiteral { - pub cur_cmnt: usize, - pub cur_lit: usize, -} - pub struct State<'a> { pub s: pp::Printer<'a>, cm: Option<&'a CodeMap>, comments: Option >, - literals: Option >, - cur_cmnt_and_lit: CurrentCommentAndLiteral, + literals: Peekable>, + cur_cmnt: usize, boxes: Vec, ann: &'a (PpAnn+'a), } -pub fn rust_printer<'a>(writer: Box) -> State<'a> { - static NO_ANN: NoAnn = NoAnn; - rust_printer_annotated(writer, &NO_ANN) -} - -pub fn rust_printer_annotated<'a>(writer: Box, - ann: &'a PpAnn) -> State<'a> { +fn rust_printer<'a>(writer: Box, ann: &'a PpAnn) -> State<'a> { State { s: pp::mk_printer(writer, DEFAULT_COLUMNS), cm: None, comments: None, - literals: None, - cur_cmnt_and_lit: CurrentCommentAndLiteral { - cur_cmnt: 0, - cur_lit: 0 - }, + literals: vec![].into_iter().peekable(), + cur_cmnt: 0, boxes: Vec::new(), ann: ann, } @@ -128,7 +113,7 @@ pub fn print_crate<'a>(cm: &'a CodeMap, s.print_mod(&krate.module, &krate.attrs)?; s.print_remaining_comments()?; - eof(&mut s.s) + s.s.eof() } impl<'a> State<'a> { @@ -161,11 +146,8 @@ impl<'a> State<'a> { s: pp::mk_printer(out, DEFAULT_COLUMNS), cm: Some(cm), comments: comments, - literals: literals, - cur_cmnt_and_lit: CurrentCommentAndLiteral { - cur_cmnt: 0, - cur_lit: 0 - }, + literals: literals.unwrap_or_default().into_iter().peekable(), + cur_cmnt: 0, boxes: Vec::new(), ann: ann, } @@ -177,14 +159,15 @@ pub fn to_string(f: F) -> String where { let mut wr = Vec::new(); { - let mut printer = rust_printer(Box::new(&mut wr)); + let ann = NoAnn; + let mut printer = rust_printer(Box::new(&mut wr), &ann); f(&mut printer).unwrap(); - eof(&mut printer.s).unwrap(); + printer.s.eof().unwrap(); } String::from_utf8(wr).unwrap() } -pub fn binop_to_string(op: BinOpToken) -> &'static str { +fn binop_to_string(op: BinOpToken) -> &'static str { match op { token::Plus => "+", token::Minus => "-", @@ -452,17 +435,18 @@ pub trait PrintState<'a> { fn writer(&mut self) -> &mut pp::Printer<'a>; fn boxes(&mut self) -> &mut Vec; fn comments(&mut self) -> &mut Option>; - fn cur_cmnt_and_lit(&mut self) -> &mut CurrentCommentAndLiteral; - fn literals(&self) -> &Option>; + fn cur_cmnt(&mut self) -> &mut usize; + fn cur_lit(&mut self) -> Option<&comments::Literal>; + fn bump_lit(&mut self) -> Option; fn word_space(&mut self, w: &str) -> io::Result<()> { - word(self.writer(), w)?; - space(self.writer()) + self.writer().word(w)?; + self.writer().space() } - fn popen(&mut self) -> io::Result<()> { word(self.writer(), "(") } + fn popen(&mut self) -> io::Result<()> { self.writer().word("(") } - fn pclose(&mut self) -> io::Result<()> { word(self.writer(), ")") } + fn pclose(&mut self) -> io::Result<()> { self.writer().word(")") } fn is_begin(&mut self) -> bool { match self.writer().last_token() { @@ -485,7 +469,7 @@ pub trait PrintState<'a> { fn hardbreak_if_not_bol(&mut self) -> io::Result<()> { if !self.is_bol() { - hardbreak(self.writer())? + self.writer().hardbreak()? } Ok(()) } @@ -493,17 +477,17 @@ pub trait PrintState<'a> { // "raw box" fn rbox(&mut self, u: usize, b: pp::Breaks) -> io::Result<()> { self.boxes().push(b); - pp::rbox(self.writer(), u, b) + self.writer().rbox(u, b) } fn ibox(&mut self, u: usize) -> io::Result<()> { self.boxes().push(pp::Breaks::Inconsistent); - pp::ibox(self.writer(), u) + self.writer().ibox(u) } fn end(&mut self) -> io::Result<()> { self.boxes().pop().unwrap(); - pp::end(self.writer()) + self.writer().end() } fn commasep(&mut self, b: Breaks, elts: &[T], mut op: F) -> io::Result<()> @@ -519,31 +503,24 @@ pub trait PrintState<'a> { } fn next_lit(&mut self, pos: BytePos) -> Option { - let mut cur_lit = self.cur_cmnt_and_lit().cur_lit; + while let Some(ltrl) = self.cur_lit().cloned() { + if ltrl.pos > pos { break; } - let mut result = None; - - if let Some(ref lits) = *self.literals() { - while cur_lit < lits.len() { - let ltrl = (*lits)[cur_lit].clone(); - if ltrl.pos > pos { break; } - cur_lit += 1; - if ltrl.pos == pos { - result = Some(ltrl); - break; - } + // we don't need the value here since we're forced to clone cur_lit + // due to lack of NLL. + self.bump_lit(); + if ltrl.pos == pos { + return Some(ltrl); } } - self.cur_cmnt_and_lit().cur_lit = cur_lit; - result + None } fn maybe_print_comment(&mut self, pos: BytePos) -> io::Result<()> { while let Some(ref cmnt) = self.next_comment() { if cmnt.pos < pos { self.print_comment(cmnt)?; - self.cur_cmnt_and_lit().cur_cmnt += 1; } else { break } @@ -553,12 +530,12 @@ pub trait PrintState<'a> { fn print_comment(&mut self, cmnt: &comments::Comment) -> io::Result<()> { - match cmnt.style { + let r = match cmnt.style { comments::Mixed => { assert_eq!(cmnt.lines.len(), 1); - zerobreak(self.writer())?; - word(self.writer(), &cmnt.lines[0])?; - zerobreak(self.writer()) + self.writer().zerobreak()?; + self.writer().word(&cmnt.lines[0])?; + self.writer().zerobreak() } comments::Isolated => { self.hardbreak_if_not_bol()?; @@ -566,26 +543,26 @@ pub trait PrintState<'a> { // Don't print empty lines because they will end up as trailing // whitespace if !line.is_empty() { - word(self.writer(), &line[..])?; + self.writer().word(&line[..])?; } - hardbreak(self.writer())?; + self.writer().hardbreak()?; } Ok(()) } comments::Trailing => { if !self.is_bol() { - word(self.writer(), " ")?; + self.writer().word(" ")?; } if cmnt.lines.len() == 1 { - word(self.writer(), &cmnt.lines[0])?; - hardbreak(self.writer()) + self.writer().word(&cmnt.lines[0])?; + self.writer().hardbreak() } else { self.ibox(0)?; for line in &cmnt.lines { if !line.is_empty() { - word(self.writer(), &line[..])?; + self.writer().word(&line[..])?; } - hardbreak(self.writer())?; + self.writer().hardbreak()?; } self.end() } @@ -597,15 +574,22 @@ pub trait PrintState<'a> { _ => false }; if is_semi || self.is_begin() || self.is_end() { - hardbreak(self.writer())?; + self.writer().hardbreak()?; } - hardbreak(self.writer()) + self.writer().hardbreak() } + }; + match r { + Ok(()) => { + *self.cur_cmnt() = *self.cur_cmnt() + 1; + Ok(()) + } + Err(e) => Err(e), } } fn next_comment(&mut self) -> Option { - let cur_cmnt = self.cur_cmnt_and_lit().cur_cmnt; + let cur_cmnt = *self.cur_cmnt(); match *self.comments() { Some(ref cmnts) => { if cur_cmnt < cmnts.len() { @@ -620,8 +604,8 @@ pub trait PrintState<'a> { fn print_literal(&mut self, lit: &ast::Lit) -> io::Result<()> { self.maybe_print_comment(lit.span.lo)?; - if let Some(ref ltrl) = self.next_lit(lit.span.lo) { - return word(self.writer(), &(*ltrl).lit); + if let Some(ltrl) = self.next_lit(lit.span.lo) { + return self.writer().word(<rl.lit); } match lit.node { ast::LitKind::Str(st, style) => self.print_string(&st.as_str(), style), @@ -629,37 +613,33 @@ pub trait PrintState<'a> { let mut res = String::from("b'"); res.extend(ascii::escape_default(byte).map(|c| c as char)); res.push('\''); - word(self.writer(), &res[..]) + self.writer().word(&res[..]) } ast::LitKind::Char(ch) => { let mut res = String::from("'"); res.extend(ch.escape_default()); res.push('\''); - word(self.writer(), &res[..]) + self.writer().word(&res[..]) } ast::LitKind::Int(i, t) => { match t { ast::LitIntType::Signed(st) => { - word(self.writer(), &st.val_to_string(i as i128)) + self.writer().word(&st.val_to_string(i as i128)) } ast::LitIntType::Unsigned(ut) => { - word(self.writer(), &ut.val_to_string(i)) + self.writer().word(&ut.val_to_string(i)) } ast::LitIntType::Unsuffixed => { - word(self.writer(), &format!("{}", i)) + self.writer().word(&format!("{}", i)) } } } ast::LitKind::Float(ref f, t) => { - word(self.writer(), - &format!( - "{}{}", - &f, - t.ty_to_string())) + self.writer().word(&format!("{}{}", &f, t.ty_to_string())) } - ast::LitKind::FloatUnsuffixed(ref f) => word(self.writer(), &f.as_str()), + ast::LitKind::FloatUnsuffixed(ref f) => self.writer().word(&f.as_str()), ast::LitKind::Bool(val) => { - if val { word(self.writer(), "true") } else { word(self.writer(), "false") } + if val { self.writer().word("true") } else { self.writer().word("false") } } ast::LitKind::ByteStr(ref v) => { let mut escaped: String = String::new(); @@ -667,7 +647,7 @@ pub trait PrintState<'a> { escaped.extend(ascii::escape_default(ch) .map(|c| c as char)); } - word(self.writer(), &format!("b\"{}\"", escaped)) + self.writer().word(&format!("b\"{}\"", escaped)) } } } @@ -684,7 +664,7 @@ pub trait PrintState<'a> { string=st)) } }; - word(self.writer(), &st[..]) + self.writer().word(&st[..]) } fn print_inner_attributes(&mut self, @@ -745,29 +725,29 @@ pub trait PrintState<'a> { } self.maybe_print_comment(attr.span.lo)?; if attr.is_sugared_doc { - word(self.writer(), &attr.value_str().unwrap().as_str())?; - hardbreak(self.writer()) + self.writer().word(&attr.value_str().unwrap().as_str())?; + self.writer().hardbreak() } else { match attr.style { - ast::AttrStyle::Inner => word(self.writer(), "#![")?, - ast::AttrStyle::Outer => word(self.writer(), "#[")?, + ast::AttrStyle::Inner => self.writer().word("#![")?, + ast::AttrStyle::Outer => self.writer().word("#[")?, } if let Some(mi) = attr.meta() { self.print_meta_item(&mi)? } else { for (i, segment) in attr.path.segments.iter().enumerate() { if i > 0 { - word(self.writer(), "::")? + self.writer().word("::")? } if segment.identifier.name != keywords::CrateRoot.name() && segment.identifier.name != keywords::DollarCrate.name() { - word(self.writer(), &segment.identifier.name.as_str())?; + self.writer().word(&segment.identifier.name.as_str())?; } } - space(self.writer())?; + self.writer().space()?; self.print_tts(attr.tokens.clone())?; } - word(self.writer(), "]") + self.writer().word("]") } } @@ -786,7 +766,7 @@ pub trait PrintState<'a> { self.ibox(INDENT_UNIT)?; match item.node { ast::MetaItemKind::Word => { - word(self.writer(), &item.name.as_str())?; + self.writer().word(&item.name.as_str())?; } ast::MetaItemKind::NameValue(ref value) => { self.word_space(&item.name.as_str())?; @@ -794,7 +774,7 @@ pub trait PrintState<'a> { self.print_literal(value)?; } ast::MetaItemKind::List(ref items) => { - word(self.writer(), &item.name.as_str())?; + self.writer().word(&item.name.as_str())?; self.popen()?; self.commasep(Consistent, &items[..], @@ -815,20 +795,20 @@ pub trait PrintState<'a> { fn print_tt(&mut self, tt: tokenstream::TokenTree) -> io::Result<()> { match tt { TokenTree::Token(_, ref tk) => { - word(self.writer(), &token_to_string(tk))?; + self.writer().word(&token_to_string(tk))?; match *tk { parse::token::DocComment(..) => { - hardbreak(self.writer()) + self.writer().hardbreak() } _ => Ok(()) } } TokenTree::Delimited(_, ref delimed) => { - word(self.writer(), &token_to_string(&delimed.open_token()))?; - space(self.writer())?; + self.writer().word(&token_to_string(&delimed.open_token()))?; + self.writer().space()?; self.print_tts(delimed.stream())?; - space(self.writer())?; - word(self.writer(), &token_to_string(&delimed.close_token())) + self.writer().space()?; + self.writer().word(&token_to_string(&delimed.close_token())) }, } } @@ -837,7 +817,7 @@ pub trait PrintState<'a> { self.ibox(0)?; for (i, tt) in tts.into_trees().enumerate() { if i != 0 { - space(self.writer())?; + self.writer().space()?; } self.print_tt(tt)?; } @@ -845,11 +825,11 @@ pub trait PrintState<'a> { } fn space_if_not_bol(&mut self) -> io::Result<()> { - if !self.is_bol() { space(self.writer())?; } + if !self.is_bol() { self.writer().space()?; } Ok(()) } - fn nbsp(&mut self) -> io::Result<()> { word(self.writer(), " ") } + fn nbsp(&mut self) -> io::Result<()> { self.writer().word(" ") } } impl<'a> PrintState<'a> for State<'a> { @@ -865,23 +845,27 @@ impl<'a> PrintState<'a> for State<'a> { &mut self.comments } - fn cur_cmnt_and_lit(&mut self) -> &mut CurrentCommentAndLiteral { - &mut self.cur_cmnt_and_lit + fn cur_cmnt(&mut self) -> &mut usize { + &mut self.cur_cmnt + } + + fn cur_lit(&mut self) -> Option<&comments::Literal> { + self.literals.peek() } - fn literals(&self) -> &Option> { - &self.literals + fn bump_lit(&mut self) -> Option { + self.literals.next() } } impl<'a> State<'a> { pub fn cbox(&mut self, u: usize) -> io::Result<()> { self.boxes.push(pp::Breaks::Consistent); - pp::cbox(&mut self.s, u) + self.s.cbox(u) } pub fn word_nbsp(&mut self, w: &str) -> io::Result<()> { - word(&mut self.s, w)?; + self.s.word(w)?; self.nbsp() } @@ -898,7 +882,7 @@ impl<'a> State<'a> { } pub fn bopen(&mut self) -> io::Result<()> { - word(&mut self.s, "{")?; + self.s.word("{")?; self.end() // close the head-box } @@ -910,7 +894,7 @@ impl<'a> State<'a> { indented: usize, close_box: bool) -> io::Result<()> { self.maybe_print_comment(span.hi)?; self.break_offset_if_not_bol(1, -(indented as isize))?; - word(&mut self.s, "}")?; + self.s.word("}")?; if close_box { self.end()?; // close the outer-box } @@ -930,13 +914,13 @@ impl<'a> State<'a> { pub fn break_offset_if_not_bol(&mut self, n: usize, off: isize) -> io::Result<()> { if !self.is_bol() { - break_offset(&mut self.s, n, off) + self.s.break_offset(n, off) } else { if off != 0 && self.s.last_token().is_hardbreak_tok() { // We do something pretty sketchy here: tuck the nonzero // offset-adjustment we were going to deposit along with the // break into the previous hardbreak. - self.s.replace_last_token(pp::hardbreak_tok_offset(off)); + self.s.replace_last_token(pp::Printer::hardbreak_tok_offset(off)); } Ok(()) } @@ -945,11 +929,11 @@ impl<'a> State<'a> { // Synthesizes a comment that was not textually present in the original source // file. pub fn synth_comment(&mut self, text: String) -> io::Result<()> { - word(&mut self.s, "/*")?; - space(&mut self.s)?; - word(&mut self.s, &text[..])?; - space(&mut self.s)?; - word(&mut self.s, "*/") + self.s.word("/*")?; + self.s.space()?; + self.s.word(&text[..])?; + self.s.space()?; + self.s.word("*/") } @@ -970,7 +954,7 @@ impl<'a> State<'a> { op(self, elt)?; i += 1; if i < len { - word(&mut self.s, ",")?; + self.s.word(",")?; self.maybe_print_trailing_comment(get_span(elt), Some(get_span(&elts[i]).hi))?; self.space_if_not_bol()?; @@ -1016,12 +1000,12 @@ impl<'a> State<'a> { self.ibox(0)?; match ty.node { ast::TyKind::Slice(ref ty) => { - word(&mut self.s, "[")?; + self.s.word("[")?; self.print_type(ty)?; - word(&mut self.s, "]")?; + self.s.word("]")?; } ast::TyKind::Ptr(ref mt) => { - word(&mut self.s, "*")?; + self.s.word("*")?; match mt.mutbl { ast::Mutability::Mutable => self.word_nbsp("mut")?, ast::Mutability::Immutable => self.word_nbsp("const")?, @@ -1029,19 +1013,19 @@ impl<'a> State<'a> { self.print_type(&mt.ty)?; } ast::TyKind::Rptr(ref lifetime, ref mt) => { - word(&mut self.s, "&")?; + self.s.word("&")?; self.print_opt_lifetime(lifetime)?; self.print_mt(mt)?; } ast::TyKind::Never => { - word(&mut self.s, "!")?; + self.s.word("!")?; }, ast::TyKind::Tup(ref elts) => { self.popen()?; self.commasep(Inconsistent, &elts[..], |s, ty| s.print_type(ty))?; if elts.len() == 1 { - word(&mut self.s, ",")?; + self.s.word(",")?; } self.pclose()?; } @@ -1079,25 +1063,25 @@ impl<'a> State<'a> { self.print_bounds("impl ", &bounds[..])?; } ast::TyKind::Array(ref ty, ref v) => { - word(&mut self.s, "[")?; + self.s.word("[")?; self.print_type(ty)?; - word(&mut self.s, "; ")?; + self.s.word("; ")?; self.print_expr(v)?; - word(&mut self.s, "]")?; + self.s.word("]")?; } ast::TyKind::Typeof(ref e) => { - word(&mut self.s, "typeof(")?; + self.s.word("typeof(")?; self.print_expr(e)?; - word(&mut self.s, ")")?; + self.s.word(")")?; } ast::TyKind::Infer => { - word(&mut self.s, "_")?; + self.s.word("_")?; } ast::TyKind::Err => { - word(&mut self.s, "?")?; + self.s.word("?")?; } ast::TyKind::ImplicitSelf => { - word(&mut self.s, "Self")?; + self.s.word("Self")?; } ast::TyKind::Mac(ref m) => { self.print_mac(m, token::Paren)?; @@ -1119,7 +1103,7 @@ impl<'a> State<'a> { Abi::Rust, Some(item.ident), generics, &item.vis)?; self.end()?; // end head-ibox - word(&mut self.s, ";")?; + self.s.word(";")?; self.end() // end the outer fn box } ast::ForeignItemKind::Static(ref t, m) => { @@ -1130,7 +1114,7 @@ impl<'a> State<'a> { self.print_ident(item.ident)?; self.word_space(":")?; self.print_type(t)?; - word(&mut self.s, ";")?; + self.s.word(";")?; self.end()?; // end the head-ibox self.end() // end the outer cbox } @@ -1144,17 +1128,17 @@ impl<'a> State<'a> { vis: &ast::Visibility) -> io::Result<()> { - word(&mut self.s, &visibility_qualified(vis, ""))?; + self.s.word(&visibility_qualified(vis, ""))?; self.word_space("const")?; self.print_ident(ident)?; self.word_space(":")?; self.print_type(ty)?; if let Some(expr) = default { - space(&mut self.s)?; + self.s.space()?; self.word_space("=")?; self.print_expr(expr)?; } - word(&mut self.s, ";") + self.s.word(";") } fn print_associated_type(&mut self, @@ -1168,11 +1152,11 @@ impl<'a> State<'a> { self.print_bounds(":", bounds)?; } if let Some(ty) = ty { - space(&mut self.s)?; + self.s.space()?; self.word_space("=")?; self.print_type(ty)?; } - word(&mut self.s, ";") + self.s.word(";") } /// Pretty-print an item @@ -1191,19 +1175,19 @@ impl<'a> State<'a> { } else { self.print_name(p)?; } - space(&mut self.s)?; - word(&mut self.s, "as")?; - space(&mut self.s)?; + self.s.space()?; + self.s.word("as")?; + self.s.space()?; } self.print_ident(item.ident)?; - word(&mut self.s, ";")?; + self.s.word(";")?; self.end()?; // end inner head-block self.end()?; // end outer head-block } ast::ItemKind::Use(ref vp) => { self.head(&visibility_qualified(&item.vis, "use"))?; self.print_view_path(vp)?; - word(&mut self.s, ";")?; + self.s.word(";")?; self.end()?; // end inner head-block self.end()?; // end outer head-block } @@ -1215,12 +1199,12 @@ impl<'a> State<'a> { self.print_ident(item.ident)?; self.word_space(":")?; self.print_type(ty)?; - space(&mut self.s)?; + self.s.space()?; self.end()?; // end the head-ibox self.word_space("=")?; self.print_expr(expr)?; - word(&mut self.s, ";")?; + self.s.word(";")?; self.end()?; // end the outer cbox } ast::ItemKind::Const(ref ty, ref expr) => { @@ -1228,12 +1212,12 @@ impl<'a> State<'a> { self.print_ident(item.ident)?; self.word_space(":")?; self.print_type(ty)?; - space(&mut self.s)?; + self.s.space()?; self.end()?; // end the head-ibox self.word_space("=")?; self.print_expr(expr)?; - word(&mut self.s, ";")?; + self.s.word(";")?; self.end()?; // end the outer cbox } ast::ItemKind::Fn(ref decl, unsafety, constness, abi, ref typarams, ref body) => { @@ -1247,7 +1231,7 @@ impl<'a> State<'a> { typarams, &item.vis )?; - word(&mut self.s, " ")?; + self.s.word(" ")?; self.print_block_with_attrs(body, &item.attrs)?; } ast::ItemKind::Mod(ref _mod) => { @@ -1267,7 +1251,7 @@ impl<'a> State<'a> { } ast::ItemKind::GlobalAsm(ref ga) => { self.head(&visibility_qualified(&item.vis, "global_asm!"))?; - word(&mut self.s, &ga.asm.as_str())?; + self.s.word(&ga.asm.as_str())?; self.end()?; } ast::ItemKind::Ty(ref ty, ref params) => { @@ -1279,10 +1263,10 @@ impl<'a> State<'a> { self.end()?; // end the inner ibox self.print_where_clause(¶ms.where_clause)?; - space(&mut self.s)?; + self.s.space()?; self.word_space("=")?; self.print_type(ty)?; - word(&mut self.s, ";")?; + self.s.word(";")?; self.end()?; // end the outer ibox } ast::ItemKind::Enum(ref enum_definition, ref params) => { @@ -1308,7 +1292,7 @@ impl<'a> State<'a> { self.print_unsafety(unsafety)?; self.word_nbsp("impl")?; self.print_trait_ref(trait_ref)?; - space(&mut self.s)?; + self.s.space()?; self.word_space("for")?; self.word_space("..")?; self.bopen()?; @@ -1329,23 +1313,23 @@ impl<'a> State<'a> { if generics.is_parameterized() { self.print_generics(generics)?; - space(&mut self.s)?; + self.s.space()?; } if polarity == ast::ImplPolarity::Negative { - word(&mut self.s, "!")?; + self.s.word("!")?; } if let Some(ref t) = *opt_trait { self.print_trait_ref(t)?; - space(&mut self.s)?; + self.s.space()?; self.word_space("for")?; } self.print_type(ty)?; self.print_where_clause(&generics.where_clause)?; - space(&mut self.s)?; + self.s.space()?; self.bopen()?; self.print_inner_attributes(&item.attrs)?; for impl_item in impl_items { @@ -1363,7 +1347,7 @@ impl<'a> State<'a> { let mut real_bounds = Vec::with_capacity(bounds.len()); for b in bounds.iter() { if let TraitTyParamBound(ref ptr, ast::TraitBoundModifier::Maybe) = *b { - space(&mut self.s)?; + self.s.space()?; self.word_space("for ?")?; self.print_trait_ref(&ptr.trait_ref)?; } else { @@ -1372,7 +1356,7 @@ impl<'a> State<'a> { } self.print_bounds(":", &real_bounds[..])?; self.print_where_clause(&generics.where_clause)?; - word(&mut self.s, " ")?; + self.s.word(" ")?; self.bopen()?; for trait_item in trait_items { self.print_trait_item(trait_item)?; @@ -1381,23 +1365,23 @@ impl<'a> State<'a> { } ast::ItemKind::Mac(codemap::Spanned { ref node, .. }) => { self.print_path(&node.path, false, 0, false)?; - word(&mut self.s, "! ")?; + self.s.word("! ")?; self.print_ident(item.ident)?; self.cbox(INDENT_UNIT)?; self.popen()?; self.print_tts(node.stream())?; self.pclose()?; - word(&mut self.s, ";")?; + self.s.word(";")?; self.end()?; } ast::ItemKind::MacroDef(ref tts) => { - word(&mut self.s, "macro_rules! ")?; + self.s.word("macro_rules! ")?; self.print_ident(item.ident)?; self.cbox(INDENT_UNIT)?; self.popen()?; self.print_tts(tts.stream())?; self.pclose()?; - word(&mut self.s, ";")?; + self.s.word(";")?; self.end()?; } } @@ -1410,7 +1394,7 @@ impl<'a> State<'a> { fn print_formal_lifetime_list(&mut self, lifetimes: &[ast::LifetimeDef]) -> io::Result<()> { if !lifetimes.is_empty() { - word(&mut self.s, "for<")?; + self.s.word("for<")?; let mut comma = false; for lifetime_def in lifetimes { if comma { @@ -1420,7 +1404,7 @@ impl<'a> State<'a> { self.print_lifetime_bounds(&lifetime_def.lifetime, &lifetime_def.bounds)?; comma = true; } - word(&mut self.s, ">")?; + self.s.word(">")?; } Ok(()) } @@ -1438,7 +1422,7 @@ impl<'a> State<'a> { self.print_ident(ident)?; self.print_generics(generics)?; self.print_where_clause(&generics.where_clause)?; - space(&mut self.s)?; + self.s.space()?; self.print_variants(&enum_definition.variants, span) } @@ -1452,7 +1436,7 @@ impl<'a> State<'a> { self.print_outer_attributes(&v.node.attrs)?; self.ibox(INDENT_UNIT)?; self.print_variant(v)?; - word(&mut self.s, ",")?; + self.s.word(",")?; self.end()?; self.maybe_print_trailing_comment(v.span, None)?; } @@ -1506,7 +1490,7 @@ impl<'a> State<'a> { } self.print_where_clause(&generics.where_clause)?; if print_finalizer { - word(&mut self.s, ";")?; + self.s.word(";")?; } self.end()?; self.end() // close the outer-box @@ -1524,7 +1508,7 @@ impl<'a> State<'a> { self.print_ident(field.ident.unwrap())?; self.word_nbsp(":")?; self.print_type(&field.ty)?; - word(&mut self.s, ",")?; + self.s.word(",")?; } self.bclose(span) @@ -1537,7 +1521,7 @@ impl<'a> State<'a> { self.print_struct(&v.node.data, &generics, v.node.name, v.span, false)?; match v.node.disr_expr { Some(ref d) => { - space(&mut self.s)?; + self.s.space()?; self.word_space("=")?; self.print_expr(d) } @@ -1580,7 +1564,7 @@ impl<'a> State<'a> { self.nbsp()?; self.print_block_with_attrs(body, &ti.attrs)?; } else { - word(&mut self.s, ";")?; + self.s.word(";")?; } } ast::TraitItemKind::Type(ref bounds, ref default) => { @@ -1590,12 +1574,12 @@ impl<'a> State<'a> { ast::TraitItemKind::Macro(codemap::Spanned { ref node, .. }) => { // code copied from ItemKind::Mac: self.print_path(&node.path, false, 0, false)?; - word(&mut self.s, "! ")?; + self.s.word("! ")?; self.cbox(INDENT_UNIT)?; self.popen()?; self.print_tts(node.stream())?; self.pclose()?; - word(&mut self.s, ";")?; + self.s.word(";")?; self.end()? } } @@ -1624,12 +1608,12 @@ impl<'a> State<'a> { ast::ImplItemKind::Macro(codemap::Spanned { ref node, .. }) => { // code copied from ItemKind::Mac: self.print_path(&node.path, false, 0, false)?; - word(&mut self.s, "! ")?; + self.s.word("! ")?; self.cbox(INDENT_UNIT)?; self.popen()?; self.print_tts(node.stream())?; self.pclose()?; - word(&mut self.s, ";")?; + self.s.word(";")?; self.end()? } } @@ -1653,7 +1637,7 @@ impl<'a> State<'a> { self.word_space("=")?; self.print_expr(init)?; } - word(&mut self.s, ";")?; + self.s.word(";")?; self.end()?; } ast::StmtKind::Item(ref item) => self.print_item(item)?, @@ -1661,13 +1645,13 @@ impl<'a> State<'a> { self.space_if_not_bol()?; self.print_expr_outer_attr_style(expr, false)?; if parse::classify::expr_requires_semi_to_be_stmt(expr) { - word(&mut self.s, ";")?; + self.s.word(";")?; } } ast::StmtKind::Semi(ref expr) => { self.space_if_not_bol()?; self.print_expr_outer_attr_style(expr, false)?; - word(&mut self.s, ";")?; + self.s.word(";")?; } ast::StmtKind::Mac(ref mac) => { let (ref mac, style, ref attrs) = **mac; @@ -1679,7 +1663,7 @@ impl<'a> State<'a> { }; self.print_mac(mac, delim)?; if style == ast::MacStmtStyle::Semicolon { - word(&mut self.s, ";")?; + self.s.word(";")?; } } } @@ -1750,9 +1734,9 @@ impl<'a> State<'a> { ast::ExprKind::If(ref i, ref then, ref e) => { self.cbox(INDENT_UNIT - 1)?; self.ibox(0)?; - word(&mut self.s, " else if ")?; + self.s.word(" else if ")?; self.print_expr(i)?; - space(&mut self.s)?; + self.s.space()?; self.print_block(then)?; self.print_else(e.as_ref().map(|e| &**e)) } @@ -1760,12 +1744,12 @@ impl<'a> State<'a> { ast::ExprKind::IfLet(ref pat, ref expr, ref then, ref e) => { self.cbox(INDENT_UNIT - 1)?; self.ibox(0)?; - word(&mut self.s, " else if let ")?; + self.s.word(" else if let ")?; self.print_pat(pat)?; - space(&mut self.s)?; + self.s.space()?; self.word_space("=")?; self.print_expr(expr)?; - space(&mut self.s)?; + self.s.space()?; self.print_block(then)?; self.print_else(e.as_ref().map(|e| &**e)) } @@ -1773,7 +1757,7 @@ impl<'a> State<'a> { ast::ExprKind::Block(ref b) => { self.cbox(INDENT_UNIT - 1)?; self.ibox(0)?; - word(&mut self.s, " else ")?; + self.s.word(" else ")?; self.print_block(b) } // BLEAH, constraints would be great here @@ -1790,7 +1774,7 @@ impl<'a> State<'a> { elseopt: Option<&ast::Expr>) -> io::Result<()> { self.head("if")?; self.print_expr(test)?; - space(&mut self.s)?; + self.s.space()?; self.print_block(blk)?; self.print_else(elseopt) } @@ -1799,10 +1783,10 @@ impl<'a> State<'a> { elseopt: Option<&ast::Expr>) -> io::Result<()> { self.head("if let")?; self.print_pat(pat)?; - space(&mut self.s)?; + self.s.space()?; self.word_space("=")?; self.print_expr(expr)?; - space(&mut self.s)?; + self.s.space()?; self.print_block(blk)?; self.print_else(elseopt) } @@ -1810,10 +1794,10 @@ impl<'a> State<'a> { pub fn print_mac(&mut self, m: &ast::Mac, delim: token::DelimToken) -> io::Result<()> { self.print_path(&m.node.path, false, 0, false)?; - word(&mut self.s, "!")?; + self.s.word("!")?; match delim { token::Paren => self.popen()?, - token::Bracket => word(&mut self.s, "[")?, + token::Bracket => self.s.word("[")?, token::Brace => { self.head("")?; self.bopen()?; @@ -1823,7 +1807,7 @@ impl<'a> State<'a> { self.print_tts(m.node.stream())?; match delim { token::Paren => self.pclose(), - token::Bracket => word(&mut self.s, "]"), + token::Bracket => self.s.word("]"), token::Brace => self.bclose(m.span), token::NoDelim => Ok(()), } @@ -1863,7 +1847,7 @@ impl<'a> State<'a> { place: &ast::Expr, expr: &ast::Expr) -> io::Result<()> { self.print_expr_maybe_paren(place)?; - space(&mut self.s)?; + self.s.space()?; self.word_space("<-")?; self.print_expr_maybe_paren(expr) } @@ -1871,10 +1855,10 @@ impl<'a> State<'a> { fn print_expr_vec(&mut self, exprs: &[P], attrs: &[Attribute]) -> io::Result<()> { self.ibox(INDENT_UNIT)?; - word(&mut self.s, "[")?; + self.s.word("[")?; self.print_inner_attributes_inline(attrs)?; self.commasep_exprs(Inconsistent, &exprs[..])?; - word(&mut self.s, "]")?; + self.s.word("]")?; self.end() } @@ -1883,12 +1867,12 @@ impl<'a> State<'a> { count: &ast::Expr, attrs: &[Attribute]) -> io::Result<()> { self.ibox(INDENT_UNIT)?; - word(&mut self.s, "[")?; + self.s.word("[")?; self.print_inner_attributes_inline(attrs)?; self.print_expr(element)?; self.word_space(";")?; self.print_expr(count)?; - word(&mut self.s, "]")?; + self.s.word("]")?; self.end() } @@ -1898,7 +1882,7 @@ impl<'a> State<'a> { wth: &Option>, attrs: &[Attribute]) -> io::Result<()> { self.print_path(path, true, 0, false)?; - word(&mut self.s, "{")?; + self.s.word("{")?; self.print_inner_attributes_inline(attrs)?; self.commasep_cmnt( Consistent, @@ -1917,18 +1901,18 @@ impl<'a> State<'a> { Some(ref expr) => { self.ibox(INDENT_UNIT)?; if !fields.is_empty() { - word(&mut self.s, ",")?; - space(&mut self.s)?; + self.s.word(",")?; + self.s.space()?; } - word(&mut self.s, "..")?; + self.s.word("..")?; self.print_expr(expr)?; self.end()?; } _ => if !fields.is_empty() { - word(&mut self.s, ",")? + self.s.word(",")? } } - word(&mut self.s, "}")?; + self.s.word("}")?; Ok(()) } @@ -1938,7 +1922,7 @@ impl<'a> State<'a> { self.print_inner_attributes_inline(attrs)?; self.commasep_exprs(Inconsistent, &exprs[..])?; if exprs.len() == 1 { - word(&mut self.s, ",")?; + self.s.word(",")?; } self.pclose() } @@ -1955,7 +1939,7 @@ impl<'a> State<'a> { args: &[P]) -> io::Result<()> { let base_args = &args[1..]; self.print_expr(&args[0])?; - word(&mut self.s, ".")?; + self.s.word(".")?; self.print_ident(segment.identifier)?; if let Some(ref parameters) = segment.parameters { self.print_path_parameters(parameters, true)?; @@ -1972,7 +1956,7 @@ impl<'a> State<'a> { } else { self.print_expr(lhs)?; } - space(&mut self.s)?; + self.s.space()?; self.word_space(op.node.to_string())?; if self.check_expr_bin_needs_paren(rhs, op) { self.print_expr_maybe_paren(rhs) @@ -1984,14 +1968,14 @@ impl<'a> State<'a> { fn print_expr_unary(&mut self, op: ast::UnOp, expr: &ast::Expr) -> io::Result<()> { - word(&mut self.s, ast::UnOp::to_string(op))?; + self.s.word(ast::UnOp::to_string(op))?; self.print_expr_maybe_paren(expr) } fn print_expr_addr_of(&mut self, mutability: ast::Mutability, expr: &ast::Expr) -> io::Result<()> { - word(&mut self.s, "&")?; + self.s.word("&")?; self.print_mutability(mutability)?; self.print_expr_maybe_paren(expr) } @@ -2058,7 +2042,7 @@ impl<'a> State<'a> { } else { self.print_expr_maybe_paren(expr)?; } - space(&mut self.s)?; + self.s.space()?; self.word_space("as")?; self.print_type(ty)?; } @@ -2080,7 +2064,7 @@ impl<'a> State<'a> { } self.head("while")?; self.print_expr(test)?; - space(&mut self.s)?; + self.s.space()?; self.print_block_with_attrs(blk, attrs)?; } ast::ExprKind::WhileLet(ref pat, ref expr, ref blk, opt_ident) => { @@ -2090,10 +2074,10 @@ impl<'a> State<'a> { } self.head("while let")?; self.print_pat(pat)?; - space(&mut self.s)?; + self.s.space()?; self.word_space("=")?; self.print_expr(expr)?; - space(&mut self.s)?; + self.s.space()?; self.print_block_with_attrs(blk, attrs)?; } ast::ExprKind::ForLoop(ref pat, ref iter, ref blk, opt_ident) => { @@ -2103,10 +2087,10 @@ impl<'a> State<'a> { } self.head("for")?; self.print_pat(pat)?; - space(&mut self.s)?; + self.s.space()?; self.word_space("in")?; self.print_expr(iter)?; - space(&mut self.s)?; + self.s.space()?; self.print_block_with_attrs(blk, attrs)?; } ast::ExprKind::Loop(ref blk, opt_ident) => { @@ -2115,7 +2099,7 @@ impl<'a> State<'a> { self.word_space(":")?; } self.head("loop")?; - space(&mut self.s)?; + self.s.space()?; self.print_block_with_attrs(blk, attrs)?; } ast::ExprKind::Match(ref expr, ref arms) => { @@ -2123,7 +2107,7 @@ impl<'a> State<'a> { self.ibox(4)?; self.word_nbsp("match")?; self.print_expr(expr)?; - space(&mut self.s)?; + self.s.space()?; self.bopen()?; self.print_inner_attributes_no_trailing_hardbreak(attrs)?; for arm in arms { @@ -2135,7 +2119,7 @@ impl<'a> State<'a> { self.print_capture_clause(capture_clause)?; self.print_fn_block_args(decl)?; - space(&mut self.s)?; + self.s.space()?; self.print_expr(body)?; self.end()?; // need to close a box @@ -2153,41 +2137,41 @@ impl<'a> State<'a> { } ast::ExprKind::Assign(ref lhs, ref rhs) => { self.print_expr(lhs)?; - space(&mut self.s)?; + self.s.space()?; self.word_space("=")?; self.print_expr(rhs)?; } ast::ExprKind::AssignOp(op, ref lhs, ref rhs) => { self.print_expr(lhs)?; - space(&mut self.s)?; - word(&mut self.s, op.node.to_string())?; + self.s.space()?; + self.s.word(op.node.to_string())?; self.word_space("=")?; self.print_expr(rhs)?; } ast::ExprKind::Field(ref expr, id) => { self.print_expr(expr)?; - word(&mut self.s, ".")?; + self.s.word(".")?; self.print_ident(id.node)?; } ast::ExprKind::TupField(ref expr, id) => { self.print_expr(expr)?; - word(&mut self.s, ".")?; + self.s.word(".")?; self.print_usize(id.node)?; } ast::ExprKind::Index(ref expr, ref index) => { self.print_expr(expr)?; - word(&mut self.s, "[")?; + self.s.word("[")?; self.print_expr(index)?; - word(&mut self.s, "]")?; + self.s.word("]")?; } ast::ExprKind::Range(ref start, ref end, limits) => { if let Some(ref e) = *start { self.print_expr(e)?; } if limits == ast::RangeLimits::HalfOpen { - word(&mut self.s, "..")?; + self.s.word("..")?; } else { - word(&mut self.s, "...")?; + self.s.word("...")?; } if let Some(ref e) = *end { self.print_expr(e)?; @@ -2200,34 +2184,34 @@ impl<'a> State<'a> { self.print_qpath(path, qself, true)? } ast::ExprKind::Break(opt_ident, ref opt_expr) => { - word(&mut self.s, "break")?; - space(&mut self.s)?; + self.s.word("break")?; + self.s.space()?; if let Some(ident) = opt_ident { self.print_ident(ident.node)?; - space(&mut self.s)?; + self.s.space()?; } if let Some(ref expr) = *opt_expr { self.print_expr(expr)?; - space(&mut self.s)?; + self.s.space()?; } } ast::ExprKind::Continue(opt_ident) => { - word(&mut self.s, "continue")?; - space(&mut self.s)?; + self.s.word("continue")?; + self.s.space()?; if let Some(ident) = opt_ident { self.print_ident(ident.node)?; - space(&mut self.s)? + self.s.space()? } } ast::ExprKind::Ret(ref result) => { - word(&mut self.s, "return")?; + self.s.word("return")?; if let Some(ref expr) = *result { - word(&mut self.s, " ")?; + self.s.word(" ")?; self.print_expr(expr)?; } } ast::ExprKind::InlineAsm(ref a) => { - word(&mut self.s, "asm!")?; + self.s.word("asm!")?; self.popen()?; self.print_string(&a.asm.as_str(), a.asm_str_style)?; self.word_space(":")?; @@ -2247,7 +2231,7 @@ impl<'a> State<'a> { s.pclose()?; Ok(()) })?; - space(&mut self.s)?; + self.s.space()?; self.word_space(":")?; self.commasep(Inconsistent, &a.inputs, |s, &(co, ref o)| { @@ -2257,7 +2241,7 @@ impl<'a> State<'a> { s.pclose()?; Ok(()) })?; - space(&mut self.s)?; + self.s.space()?; self.word_space(":")?; self.commasep(Inconsistent, &a.clobbers, @@ -2278,7 +2262,7 @@ impl<'a> State<'a> { } if !options.is_empty() { - space(&mut self.s)?; + self.s.space()?; self.word_space(":")?; self.commasep(Inconsistent, &options, |s, &co| { @@ -2298,11 +2282,11 @@ impl<'a> State<'a> { }, ast::ExprKind::Try(ref e) => { self.print_expr(e)?; - word(&mut self.s, "?")? + self.s.word("?")? } ast::ExprKind::Catch(ref blk) => { self.head("do catch")?; - space(&mut self.s)?; + self.s.space()?; self.print_block_with_attrs(blk, attrs)? } } @@ -2320,23 +2304,23 @@ impl<'a> State<'a> { } pub fn print_ident(&mut self, ident: ast::Ident) -> io::Result<()> { - word(&mut self.s, &ident.name.as_str())?; + self.s.word(&ident.name.as_str())?; self.ann.post(self, NodeIdent(&ident)) } pub fn print_usize(&mut self, i: usize) -> io::Result<()> { - word(&mut self.s, &i.to_string()) + self.s.word(&i.to_string()) } pub fn print_name(&mut self, name: ast::Name) -> io::Result<()> { - word(&mut self.s, &name.as_str())?; + self.s.word(&name.as_str())?; self.ann.post(self, NodeName(&name)) } pub fn print_for_decl(&mut self, loc: &ast::Local, coll: &ast::Expr) -> io::Result<()> { self.print_local_decl(loc)?; - space(&mut self.s)?; + self.s.space()?; self.word_space("in")?; self.print_expr(coll) } @@ -2356,7 +2340,7 @@ impl<'a> State<'a> { } for (i, segment) in segments.enumerate() { if i > 0 { - word(&mut self.s, "::")? + self.s.word("::")? } self.print_path_segment(segment, colons_before_params)?; } @@ -2385,16 +2369,16 @@ impl<'a> State<'a> { colons_before_params: bool) -> io::Result<()> { - word(&mut self.s, "<")?; + self.s.word("<")?; self.print_type(&qself.ty)?; if qself.position > 0 { - space(&mut self.s)?; + self.s.space()?; self.word_space("as")?; let depth = path.segments.len() - qself.position; self.print_path(path, false, depth, false)?; } - word(&mut self.s, ">")?; - word(&mut self.s, "::")?; + self.s.word(">")?; + self.s.word("::")?; let item_segment = path.segments.last().unwrap(); self.print_ident(item_segment.identifier)?; match item_segment.parameters { @@ -2409,12 +2393,12 @@ impl<'a> State<'a> { -> io::Result<()> { if colons_before_params { - word(&mut self.s, "::")? + self.s.word("::")? } match *parameters { ast::PathParameters::AngleBracketed(ref data) => { - word(&mut self.s, "<")?; + self.s.word("<")?; let mut comma = false; for lifetime in &data.lifetimes { @@ -2441,22 +2425,22 @@ impl<'a> State<'a> { self.word_space(",")? } self.print_ident(binding.ident)?; - space(&mut self.s)?; + self.s.space()?; self.word_space("=")?; self.print_type(&binding.ty)?; comma = true; } - word(&mut self.s, ">")? + self.s.word(">")? } ast::PathParameters::Parenthesized(ref data) => { - word(&mut self.s, "(")?; + self.s.word("(")?; self.commasep( Inconsistent, &data.inputs, |s, ty| s.print_type(ty))?; - word(&mut self.s, ")")?; + self.s.word(")")?; if let Some(ref ty) = data.output { self.space_if_not_bol()?; @@ -2475,7 +2459,7 @@ impl<'a> State<'a> { /* Pat isn't normalized, but the beauty of it is that it doesn't matter */ match pat.node { - PatKind::Wild => word(&mut self.s, "_")?, + PatKind::Wild => self.s.word("_")?, PatKind::Ident(binding_mode, ref path1, ref sub) => { match binding_mode { ast::BindingMode::ByRef(mutbl) => { @@ -2489,7 +2473,7 @@ impl<'a> State<'a> { } self.print_ident(path1.node)?; if let Some(ref p) = *sub { - word(&mut self.s, "@")?; + self.s.word("@")?; self.print_pat(p)?; } } @@ -2501,9 +2485,9 @@ impl<'a> State<'a> { if ddpos != 0 { self.word_space(",")?; } - word(&mut self.s, "..")?; + self.s.word("..")?; if ddpos != elts.len() { - word(&mut self.s, ",")?; + self.s.word(",")?; self.commasep(Inconsistent, &elts[ddpos..], |s, p| s.print_pat(p))?; } } else { @@ -2535,10 +2519,10 @@ impl<'a> State<'a> { |f| f.node.pat.span)?; if etc { if !fields.is_empty() { self.word_space(",")?; } - word(&mut self.s, "..")?; + self.s.word("..")?; } - space(&mut self.s)?; - word(&mut self.s, "}")?; + self.s.space()?; + self.s.word("}")?; } PatKind::Tuple(ref elts, ddpos) => { self.popen()?; @@ -2547,42 +2531,42 @@ impl<'a> State<'a> { if ddpos != 0 { self.word_space(",")?; } - word(&mut self.s, "..")?; + self.s.word("..")?; if ddpos != elts.len() { - word(&mut self.s, ",")?; + self.s.word(",")?; self.commasep(Inconsistent, &elts[ddpos..], |s, p| s.print_pat(p))?; } } else { self.commasep(Inconsistent, &elts[..], |s, p| s.print_pat(p))?; if elts.len() == 1 { - word(&mut self.s, ",")?; + self.s.word(",")?; } } self.pclose()?; } PatKind::Box(ref inner) => { - word(&mut self.s, "box ")?; + self.s.word("box ")?; self.print_pat(inner)?; } PatKind::Ref(ref inner, mutbl) => { - word(&mut self.s, "&")?; + self.s.word("&")?; if mutbl == ast::Mutability::Mutable { - word(&mut self.s, "mut ")?; + self.s.word("mut ")?; } self.print_pat(inner)?; } PatKind::Lit(ref e) => self.print_expr(&**e)?, PatKind::Range(ref begin, ref end, ref end_kind) => { self.print_expr(begin)?; - space(&mut self.s)?; + self.s.space()?; match *end_kind { - RangeEnd::Included => word(&mut self.s, "...")?, - RangeEnd::Excluded => word(&mut self.s, "..")?, + RangeEnd::Included => self.s.word("...")?, + RangeEnd::Excluded => self.s.word("..")?, } self.print_expr(end)?; } PatKind::Slice(ref before, ref slice, ref after) => { - word(&mut self.s, "[")?; + self.s.word("[")?; self.commasep(Inconsistent, &before[..], |s, p| s.print_pat(p))?; @@ -2591,13 +2575,13 @@ impl<'a> State<'a> { if p.node != PatKind::Wild { self.print_pat(p)?; } - word(&mut self.s, "..")?; + self.s.word("..")?; if !after.is_empty() { self.word_space(",")?; } } self.commasep(Inconsistent, &after[..], |s, p| s.print_pat(p))?; - word(&mut self.s, "]")?; + self.s.word("]")?; } PatKind::Mac(ref m) => self.print_mac(m, token::Paren)?, } @@ -2608,7 +2592,7 @@ impl<'a> State<'a> { // I have no idea why this check is necessary, but here it // is :( if arm.attrs.is_empty() { - space(&mut self.s)?; + self.s.space()?; } self.cbox(INDENT_UNIT)?; self.ibox(0)?; @@ -2619,16 +2603,16 @@ impl<'a> State<'a> { if first { first = false; } else { - space(&mut self.s)?; + self.s.space()?; self.word_space("|")?; } self.print_pat(p)?; } - space(&mut self.s)?; + self.s.space()?; if let Some(ref e) = arm.guard { self.word_space("if")?; self.print_expr(e)?; - space(&mut self.s)?; + self.s.space()?; } self.word_space("=>")?; @@ -2639,13 +2623,13 @@ impl<'a> State<'a> { // If it is a user-provided unsafe block, print a comma after it if let BlockCheckMode::Unsafe(ast::UserProvided) = blk.rules { - word(&mut self.s, ",")?; + self.s.word(",")?; } } _ => { self.end()?; // close the ibox for the pattern self.print_expr(&arm.body)?; - word(&mut self.s, ",")?; + self.s.word(",")?; } } self.end() // close enclosing cbox @@ -2655,17 +2639,17 @@ impl<'a> State<'a> { match explicit_self.node { SelfKind::Value(m) => { self.print_mutability(m)?; - word(&mut self.s, "self") + self.s.word("self") } SelfKind::Region(ref lt, m) => { - word(&mut self.s, "&")?; + self.s.word("&")?; self.print_opt_lifetime(lt)?; self.print_mutability(m)?; - word(&mut self.s, "self") + self.s.word("self") } SelfKind::Explicit(ref typ, m) => { self.print_mutability(m)?; - word(&mut self.s, "self")?; + self.s.word("self")?; self.word_space(":")?; self.print_type(typ) } @@ -2696,7 +2680,7 @@ impl<'a> State<'a> { self.popen()?; self.commasep(Inconsistent, &decl.inputs, |s, arg| s.print_arg(arg, false))?; if decl.variadic { - word(&mut self.s, ", ...")?; + self.s.word(", ...")?; } self.pclose()?; @@ -2707,9 +2691,9 @@ impl<'a> State<'a> { &mut self, decl: &ast::FnDecl) -> io::Result<()> { - word(&mut self.s, "|")?; + self.s.word("|")?; self.commasep(Inconsistent, &decl.inputs, |s, arg| s.print_arg(arg, true))?; - word(&mut self.s, "|")?; + self.s.word("|")?; if let ast::FunctionRetTy::Default(..) = decl.output { return Ok(()); @@ -2739,7 +2723,7 @@ impl<'a> State<'a> { bounds: &[ast::TyParamBound]) -> io::Result<()> { if !bounds.is_empty() { - word(&mut self.s, prefix)?; + self.s.word(prefix)?; let mut first = true; for bound in bounds { self.nbsp()?; @@ -2754,7 +2738,7 @@ impl<'a> State<'a> { self.print_poly_trait_ref(tref) } TraitTyParamBound(ref tref, TraitBoundModifier::Maybe) => { - word(&mut self.s, "?")?; + self.s.word("?")?; self.print_poly_trait_ref(tref) } RegionTyParamBound(ref lt) => { @@ -2782,10 +2766,10 @@ impl<'a> State<'a> { { self.print_lifetime(lifetime)?; if !bounds.is_empty() { - word(&mut self.s, ": ")?; + self.s.word(": ")?; for (i, bound) in bounds.iter().enumerate() { if i != 0 { - word(&mut self.s, " + ")?; + self.s.word(" + ")?; } self.print_lifetime(bound)?; } @@ -2802,7 +2786,7 @@ impl<'a> State<'a> { return Ok(()); } - word(&mut self.s, "<")?; + self.s.word("<")?; let mut ints = Vec::new(); for i in 0..total { @@ -2821,7 +2805,7 @@ impl<'a> State<'a> { } })?; - word(&mut self.s, ">")?; + self.s.word(">")?; Ok(()) } @@ -2831,7 +2815,7 @@ impl<'a> State<'a> { self.print_bounds(":", ¶m.bounds)?; match param.default { Some(ref default) => { - space(&mut self.s)?; + self.s.space()?; self.word_space("=")?; self.print_type(default) } @@ -2845,7 +2829,7 @@ impl<'a> State<'a> { return Ok(()) } - space(&mut self.s)?; + self.s.space()?; self.word_space("where")?; for (i, predicate) in where_clause.predicates.iter().enumerate() { @@ -2871,7 +2855,7 @@ impl<'a> State<'a> { ref rhs_ty, ..}) => { self.print_type(lhs_ty)?; - space(&mut self.s)?; + self.s.space()?; self.word_space("=")?; self.print_type(rhs_ty)?; } @@ -2888,7 +2872,7 @@ impl<'a> State<'a> { if path.segments.last().unwrap().identifier.name != ident.name { - space(&mut self.s)?; + self.s.space()?; self.word_space("as")?; self.print_ident(ident)?; } @@ -2898,26 +2882,26 @@ impl<'a> State<'a> { ast::ViewPathGlob(ref path) => { self.print_path(path, false, 0, true)?; - word(&mut self.s, "::*") + self.s.word("::*") } ast::ViewPathList(ref path, ref idents) => { if path.segments.is_empty() { - word(&mut self.s, "{")?; + self.s.word("{")?; } else { self.print_path(path, false, 0, true)?; - word(&mut self.s, "::{")?; + self.s.word("::{")?; } self.commasep(Inconsistent, &idents[..], |s, w| { s.print_ident(w.node.name)?; if let Some(ident) = w.node.rename { - space(&mut s.s)?; + s.s.space()?; s.word_space("as")?; s.print_ident(ident)?; } Ok(()) })?; - word(&mut self.s, "}") + self.s.word("}") } } } @@ -2950,8 +2934,8 @@ impl<'a> State<'a> { }; if !invalid { self.print_pat(&input.pat)?; - word(&mut self.s, ":")?; - space(&mut self.s)?; + self.s.word(":")?; + self.s.space()?; } self.print_type(&input.ty)?; } @@ -2990,7 +2974,7 @@ impl<'a> State<'a> { -> io::Result<()> { self.ibox(INDENT_UNIT)?; if !generics.lifetimes.is_empty() || !generics.ty_params.is_empty() { - word(&mut self.s, "for")?; + self.s.word("for")?; self.print_generics(generics)?; } let generics = ast::Generics { @@ -3026,7 +3010,6 @@ impl<'a> State<'a> { let next = next_pos.unwrap_or(cmnt.pos + BytePos(1)); if span.hi < cmnt.pos && cmnt.pos < next && span_line.line == comment_line.line { self.print_comment(cmnt)?; - self.cur_cmnt_and_lit.cur_cmnt += 1; } } Ok(()) @@ -3036,11 +3019,10 @@ impl<'a> State<'a> { // If there aren't any remaining comments, then we need to manually // make sure there is a line break at the end. if self.next_comment().is_none() { - hardbreak(&mut self.s)?; + self.s.hardbreak()?; } while let Some(ref cmnt) = self.next_comment() { self.print_comment(cmnt)?; - self.cur_cmnt_and_lit.cur_cmnt += 1; } Ok(()) } @@ -3074,7 +3056,7 @@ impl<'a> State<'a> { constness: ast::Constness, abi: Abi, vis: &ast::Visibility) -> io::Result<()> { - word(&mut self.s, &visibility_qualified(vis, ""))?; + self.s.word(&visibility_qualified(vis, ""))?; match constness { ast::Constness::NotConst => {} @@ -3088,7 +3070,7 @@ impl<'a> State<'a> { self.word_nbsp(&abi.to_string())?; } - word(&mut self.s, "fn") + self.s.word("fn") } pub fn print_unsafety(&mut self, s: ast::Unsafety) -> io::Result<()> { diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index 92cfb862b1669..bf71b11fc7766 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -35,9 +35,7 @@ #![feature(asm)] #![feature(libc)] -#![feature(rustc_private)] #![feature(set_stdio)] -#![feature(staged_api)] #![feature(panic_unwind)] extern crate getopts; diff --git a/src/llvm b/src/llvm index f0a23af57a176..a5ef0696d7c10 160000 --- a/src/llvm +++ b/src/llvm @@ -1 +1 @@ -Subproject commit f0a23af57a17658e75d6dc50568397590a0e6664 +Subproject commit a5ef0696d7c103006d3cb1f4263bad0ca13adca8 diff --git a/src/rustllvm/llvm-rebuild-trigger b/src/rustllvm/llvm-rebuild-trigger index b2d4c11329512..6b410502e491c 100644 --- a/src/rustllvm/llvm-rebuild-trigger +++ b/src/rustllvm/llvm-rebuild-trigger @@ -1,8 +1,4 @@ # If this file is modified, then llvm will be (optionally) cleaned and then rebuilt. # The actual contents of this file do not matter, but to trigger a change on the # build bots then the contents should be changed so git updates the mtime. -<<<<<<< 37849a002ed91ac2b80aeb2172364b4e19250e05 -2017-06-27 -======= -2017-06-26 ->>>>>>> rustc: Implement the #[global_allocator] attribute +2017-07-12 diff --git a/src/test/COMPILER_TESTS.md b/src/test/COMPILER_TESTS.md index 58df1aae6d3f0..0380454b8278d 100644 --- a/src/test/COMPILER_TESTS.md +++ b/src/test/COMPILER_TESTS.md @@ -37,7 +37,7 @@ The error levels that you can have are: Header commands specify something about the entire test file as a whole, instead of just a few lines inside the test. -* `ignore-X` where `X` is an architecture, OS or stage will ignore the test accordingly +* `ignore-X` where `X` is a target detail or stage will ignore the test accordingly (see below) * `ignore-pretty` will not compile the pretty-printed test (this is done to test the pretty-printer, but might not always work) * `ignore-test` always ignores the test * `ignore-lldb` and `ignore-gdb` will skip the debuginfo tests @@ -50,6 +50,14 @@ whole, instead of just a few lines inside the test. feature is attempted without the proper `#![feature(X)]` tag. Each unstable lang feature is required to have a gate test. +Some examples of `X` in `ignore-X`: + +* Architecture: `aarch64`, `arm`, `asmjs`, `mips`, `wasm32`, `x86_64`, `x86`, ... +* OS: `android`, `emscripten`, `freebsd`, `ios`, `linux`, `macos`, `windows`, ... +* Environment (fourth word of the target triple): `gnu`, `msvc`, `musl`. +* Pointer width: `32bit`, `64bit`. +* Stage: `stage0`, `stage1`, `stage2`. + ## Revisions Certain classes of tests support "revisions" (as of the time of this @@ -86,3 +94,66 @@ For example, the `ignore-test` header (and all "ignore" headers) currently only apply to the test as a whole, not to particular revisions. The only headers that are intended to really work when customized to a revision are error patterns and compiler flags. + +## Guide to the UI Tests + +The UI tests are intended to capture the compiler's complete output, +so that we can test all aspects of the presentation. They work by +compiling a file (e.g., `ui/hello_world/main.rs`), capturing the output, +and then applying some normalization (see below). This normalized +result is then compared against reference files named +`ui/hello_world/main.stderr` and `ui/hello_world/main.stdout`. If either of +those files doesn't exist, the output must be empty. If the test run +fails, we will print out the current output, but it is also saved in +`build//test/ui/hello_world/main.stdout` (this path is +printed as part of the test failure mesage), so you can run `diff` and +so forth. + +### Editing and updating the reference files + +If you have changed the compiler's output intentionally, or you are +making a new test, you can use the script `ui/update-references.sh` to +update the references. When you run the test framework, it will report +various errors: in those errors is a command you can use to run the +`ui/update-references.sh` script, which will then copy over the files +from the build directory and use them as the new reference. You can +also just run `ui/update-all-references.sh`. In both cases, you can run +the script with `--help` to get a help message. + +### Normalization + +The normalization applied is aimed at eliminating output difference +between platforms, mainly about filenames: + +- the test directory is replaced with `$DIR` +- all backslashes (`\`) are converted to forward slashes (`/`) (for Windows) +- all CR LF newlines are converted to LF + +Sometimes these built-in normalizations are not enough. In such cases, you +may provide custom normalization rules using the header commands, e.g. + +``` +// normalize-stderr-32bit: "fn() (32 bits)" -> "fn() ($PTR bits)" +// normalize-stderr-64bit: "fn() (64 bits)" -> "fn() ($PTR bits)" +``` + +This tells the test, on 32-bit platforms, whenever the compiler writes +`fn() (32 bits)` to stderr, it should be normalized to read `fn() ($PTR bits)` +instead. Similar for 64-bit. + +The corresponding reference file will use the normalized output to test both +32-bit and 64-bit platforms: + +``` +... + | + = note: source type: fn() ($PTR bits) + = note: target type: u16 (16 bits) +... +``` + +Please see `ui/transmute/main.rs` and `.stderr` for a concrete usage example. + +Besides `normalize-stderr-32bit` and `-64bit`, one may use any target +information or stage supported by `ignore-X` here as well (e.g. +`normalize-stderr-windows`). diff --git a/src/test/codegen/issue-37945.rs b/src/test/codegen/issue-37945.rs new file mode 100644 index 0000000000000..e7c91f309181a --- /dev/null +++ b/src/test/codegen/issue-37945.rs @@ -0,0 +1,36 @@ +// Copyright 2017 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. + +// min-llvm-version 4.0 +// compile-flags: -O +// ignore-x86 +// ignore-arm +// ignore-emscripten +// ignore 32-bit platforms (LLVM has a bug with them) + +// See issue #37945. + +#![crate_type = "lib"] + +use std::slice::Iter; + +// CHECK-LABEL: @is_empty_1 +#[no_mangle] +pub fn is_empty_1(xs: Iter) -> bool { +// CHECK-NOT: icmp eq float* {{.*}}, null + {xs}.next().is_none() +} + +// CHECK-LABEL: @is_empty_2 +#[no_mangle] +pub fn is_empty_2(xs: Iter) -> bool { +// CHECK-NOT: icmp eq float* {{.*}}, null + xs.map(|&x| x).next().is_none() +} diff --git a/src/test/compile-fail/E0036.rs b/src/test/compile-fail-fulldeps/proc-macro/auxiliary/bang_proc_macro2.rs similarity index 64% rename from src/test/compile-fail/E0036.rs rename to src/test/compile-fail-fulldeps/proc-macro/auxiliary/bang_proc_macro2.rs index ecb6dac66f218..5fc20bcda8856 100644 --- a/src/test/compile-fail/E0036.rs +++ b/src/test/compile-fail-fulldeps/proc-macro/auxiliary/bang_proc_macro2.rs @@ -8,17 +8,16 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -struct Test; +// force-host +// no-prefer-dynamic +#![feature(proc_macro)] +#![crate_type = "proc-macro"] -impl Test { - fn method(&self, v: &[T]) -> usize { - v.len() - } -} +extern crate proc_macro; + +use proc_macro::TokenStream; -fn main() { - let x = Test; - let v = &[0]; - x.method::(v); //~ ERROR E0036 - //~| NOTE Passed 2 type arguments, expected 1 +#[proc_macro] +pub fn bang_proc_macro2(_: TokenStream) -> TokenStream { + "let x = foobar2;".parse().unwrap() } diff --git a/src/test/compile-fail-fulldeps/proc-macro/lints_in_proc_macros.rs b/src/test/compile-fail-fulldeps/proc-macro/lints_in_proc_macros.rs new file mode 100644 index 0000000000000..93dead1a15685 --- /dev/null +++ b/src/test/compile-fail-fulldeps/proc-macro/lints_in_proc_macros.rs @@ -0,0 +1,26 @@ +// Copyright 2016 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:bang_proc_macro2.rs + +#![feature(proc_macro)] +#![allow(unused_macros)] + +extern crate bang_proc_macro2; + +use bang_proc_macro2::bang_proc_macro2; + +fn main() { + let foobar = 42; + bang_proc_macro2!(); + //~^ ERROR cannot find value `foobar2` in this scope + //~^^ did you mean `foobar`? + println!("{}", x); +} diff --git a/src/test/compile-fail/E0088.rs b/src/test/compile-fail/E0088.rs index de188677a1121..db84a4edc487c 100644 --- a/src/test/compile-fail/E0088.rs +++ b/src/test/compile-fail/E0088.rs @@ -9,14 +9,9 @@ // except according to those terms. fn f() {} -fn g<'a>() {} +fn g<'a>() -> &'a u8 { loop {} } fn main() { - f::<'static>(); - //~^ ERROR expected at most 0 lifetime parameters, found 1 lifetime parameter [E0088] - //~| NOTE expected 0 lifetime parameters - - g::<'static, 'static>(); - //~^ ERROR expected at most 0 lifetime parameters, found 2 lifetime parameters [E0088] - //~| NOTE expected 0 lifetime parameters + f::<'static>(); //~ ERROR E0088 + g::<'static, 'static>(); //~ ERROR E0088 } diff --git a/src/test/compile-fail/constructor-lifetime-args.rs b/src/test/compile-fail/constructor-lifetime-args.rs new file mode 100644 index 0000000000000..50db9707355f4 --- /dev/null +++ b/src/test/compile-fail/constructor-lifetime-args.rs @@ -0,0 +1,36 @@ +// Copyright 2017 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. + +// All lifetime parameters in struct constructors are currently considered early bound, +// i.e. `S::` is interpreted kinda like an associated item `S::::ctor`. +// This behavior is a bit weird, because if equivalent constructor were written manually +// it would get late bound lifetime parameters. +// Variant constructors behave in the same way, lifetime parameters are considered +// belonging to the enum and being early bound. +// https://github.com/rust-lang/rust/issues/30904 + +struct S<'a, 'b>(&'a u8, &'b u8); +enum E<'a, 'b> { + V(&'a u8), + U(&'b u8), +} + +fn main() { + S(&0, &0); // OK + S::<'static>(&0, &0); + //~^ ERROR expected 2 lifetime parameters, found 1 lifetime parameter + S::<'static, 'static, 'static>(&0, &0); + //~^ ERROR expected at most 2 lifetime parameters, found 3 lifetime parameters + E::V(&0); // OK + E::V::<'static>(&0); + //~^ ERROR expected 2 lifetime parameters, found 1 lifetime parameter + E::V::<'static, 'static, 'static>(&0); + //~^ ERROR expected at most 2 lifetime parameters, found 3 lifetime parameters +} diff --git a/src/test/compile-fail/dep-graph-struct-signature.rs b/src/test/compile-fail/dep-graph-struct-signature.rs index 3f568194e23d8..647605ae4383e 100644 --- a/src/test/compile-fail/dep-graph-struct-signature.rs +++ b/src/test/compile-fail/dep-graph-struct-signature.rs @@ -34,54 +34,64 @@ struct WontChange { mod signatures { use WillChange; - #[rustc_then_this_would_need(ItemSignature)] //~ ERROR no path + #[rustc_then_this_would_need(TypeOfItem)] //~ ERROR no path + #[rustc_then_this_would_need(AssociatedItems)] //~ ERROR no path + #[rustc_then_this_would_need(TraitDefOfItem)] //~ ERROR no path trait Bar { - #[rustc_then_this_would_need(ItemSignature)] //~ ERROR OK + #[rustc_then_this_would_need(FnSignature)] //~ ERROR OK fn do_something(x: WillChange); } - #[rustc_then_this_would_need(ItemSignature)] //~ ERROR OK + #[rustc_then_this_would_need(FnSignature)] //~ ERROR OK + #[rustc_then_this_would_need(TypeckTables)] //~ ERROR OK fn some_fn(x: WillChange) { } - #[rustc_then_this_would_need(ItemSignature)] //~ ERROR OK + #[rustc_then_this_would_need(FnSignature)] //~ ERROR OK + #[rustc_then_this_would_need(TypeckTables)] //~ ERROR OK fn new_foo(x: u32, y: u32) -> WillChange { WillChange { x: x, y: y } } - #[rustc_then_this_would_need(ItemSignature)] //~ ERROR OK + #[rustc_then_this_would_need(TypeOfItem)] //~ ERROR OK impl WillChange { + #[rustc_then_this_would_need(FnSignature)] //~ ERROR OK + #[rustc_then_this_would_need(TypeckTables)] //~ ERROR OK fn new(x: u32, y: u32) -> WillChange { loop { } } } - #[rustc_then_this_would_need(ItemSignature)] //~ ERROR OK + #[rustc_then_this_would_need(TypeOfItem)] //~ ERROR OK impl WillChange { + #[rustc_then_this_would_need(FnSignature)] //~ ERROR OK + #[rustc_then_this_would_need(TypeckTables)] //~ ERROR OK fn method(&self, x: u32) { } } struct WillChanges { - #[rustc_then_this_would_need(ItemSignature)] //~ ERROR OK + #[rustc_then_this_would_need(TypeOfItem)] //~ ERROR OK x: WillChange, - #[rustc_then_this_would_need(ItemSignature)] //~ ERROR OK + #[rustc_then_this_would_need(TypeOfItem)] //~ ERROR OK y: WillChange } // The fields change, not the type itself. - #[rustc_then_this_would_need(ItemSignature)] //~ ERROR no path + #[rustc_then_this_would_need(TypeOfItem)] //~ ERROR no path fn indirect(x: WillChanges) { } } mod invalid_signatures { use WontChange; - #[rustc_then_this_would_need(ItemSignature)] //~ ERROR no path + #[rustc_then_this_would_need(TypeOfItem)] //~ ERROR no path trait A { + #[rustc_then_this_would_need(FnSignature)] //~ ERROR no path fn do_something_else_twice(x: WontChange); } - #[rustc_then_this_would_need(ItemSignature)] //~ ERROR no path + #[rustc_then_this_would_need(FnSignature)] //~ ERROR no path + #[rustc_then_this_would_need(TypeckTables)] //~ ERROR no path fn b(x: WontChange) { } - #[rustc_then_this_would_need(ItemSignature)] //~ ERROR no path from `WillChange` + #[rustc_then_this_would_need(FnSignature)] //~ ERROR no path from `WillChange` + #[rustc_then_this_would_need(TypeckTables)] //~ ERROR no path from `WillChange` fn c(x: u32) { } } - diff --git a/src/test/compile-fail/dep-graph-type-alias.rs b/src/test/compile-fail/dep-graph-type-alias.rs index 56636a00a313a..dca1fa4d98f95 100644 --- a/src/test/compile-fail/dep-graph-type-alias.rs +++ b/src/test/compile-fail/dep-graph-type-alias.rs @@ -25,40 +25,42 @@ type TypeAlias = u32; // The type alias directly affects the type of the field, // not the enclosing struct: -#[rustc_then_this_would_need(ItemSignature)] //~ ERROR no path +#[rustc_then_this_would_need(TypeOfItem)] //~ ERROR no path struct Struct { - #[rustc_then_this_would_need(ItemSignature)] //~ ERROR OK + #[rustc_then_this_would_need(TypeOfItem)] //~ ERROR OK x: TypeAlias, y: u32 } -#[rustc_then_this_would_need(ItemSignature)] //~ ERROR no path +#[rustc_then_this_would_need(TypeOfItem)] //~ ERROR no path enum Enum { Variant1 { - #[rustc_then_this_would_need(ItemSignature)] //~ ERROR OK + #[rustc_then_this_would_need(TypeOfItem)] //~ ERROR OK t: TypeAlias }, Variant2(i32) } -#[rustc_then_this_would_need(ItemSignature)] //~ ERROR no path +#[rustc_then_this_would_need(TypeOfItem)] //~ ERROR no path trait Trait { - #[rustc_then_this_would_need(ItemSignature)] //~ ERROR OK + #[rustc_then_this_would_need(FnSignature)] //~ ERROR OK fn method(&self, _: TypeAlias); } struct SomeType; -#[rustc_then_this_would_need(ItemSignature)] //~ ERROR no path +#[rustc_then_this_would_need(TypeOfItem)] //~ ERROR no path impl SomeType { - #[rustc_then_this_would_need(ItemSignature)] //~ ERROR OK + #[rustc_then_this_would_need(FnSignature)] //~ ERROR OK + #[rustc_then_this_would_need(TypeckTables)] //~ ERROR OK fn method(&self, _: TypeAlias) {} } -#[rustc_then_this_would_need(ItemSignature)] //~ ERROR OK +#[rustc_then_this_would_need(TypeOfItem)] //~ ERROR OK type TypeAlias2 = TypeAlias; -#[rustc_then_this_would_need(ItemSignature)] //~ ERROR OK +#[rustc_then_this_would_need(FnSignature)] //~ ERROR OK +#[rustc_then_this_would_need(TypeckTables)] //~ ERROR OK fn function(_: TypeAlias) { } diff --git a/src/test/compile-fail/fail-simple.rs b/src/test/compile-fail/fail-simple.rs index e889d35477059..a20ff864705a1 100644 --- a/src/test/compile-fail/fail-simple.rs +++ b/src/test/compile-fail/fail-simple.rs @@ -9,5 +9,5 @@ // except according to those terms. fn main() { - panic!(@); //~ ERROR expected expression, found `@` + panic!(@); //~ ERROR no rules expected the token `@` } diff --git a/src/test/compile-fail/issue-35675.rs b/src/test/compile-fail/issue-35675.rs index 001c1f2eddca1..c09e56cbc5bca 100644 --- a/src/test/compile-fail/issue-35675.rs +++ b/src/test/compile-fail/issue-35675.rs @@ -12,14 +12,13 @@ enum Fruit { //~ HELP possible candidate is found in another module, you can import it into scope //~^ HELP possible candidate is found in another module, you can import it into scope Apple(i64), - //~^ HELP there is an enum variant `Fruit::Apple`, did you mean to use `Fruit`? - //~| HELP there is an enum variant `Fruit::Apple`, did you mean to use `Fruit`? Orange(i64), } fn should_return_fruit() -> Apple { //~^ ERROR cannot find type `Apple` in this scope //~| NOTE not found in this scope + //~| HELP you can try using the variant's enum Apple(5) //~^ ERROR cannot find function `Apple` in this scope //~| NOTE not found in this scope @@ -27,6 +26,7 @@ fn should_return_fruit() -> Apple { fn should_return_fruit_too() -> Fruit::Apple { //~^ ERROR expected type, found variant `Fruit::Apple` + //~| HELP you can try using the variant's enum //~| NOTE not a type Apple(5) //~^ ERROR cannot find function `Apple` in this scope @@ -43,6 +43,7 @@ fn foo() -> Ok { fn bar() -> Variant3 { //~^ ERROR cannot find type `Variant3` in this scope + //~| HELP you can try using the variant's enum //~| NOTE not found in this scope } @@ -61,7 +62,6 @@ mod x { Variant1, Variant2(), Variant3(usize), - //~^ HELP there is an enum variant `x::Enum::Variant3`, did you mean to use `x::Enum`? Variant4 {}, } } diff --git a/src/test/compile-fail/method-call-lifetime-args-lint.rs b/src/test/compile-fail/method-call-lifetime-args-lint.rs new file mode 100644 index 0000000000000..b2a94e0af420d --- /dev/null +++ b/src/test/compile-fail/method-call-lifetime-args-lint.rs @@ -0,0 +1,97 @@ +// Copyright 2017 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(late_bound_lifetime_arguments)] +#![allow(unused)] + +struct S; + +impl S { + fn late<'a, 'b>(self, _: &'a u8, _: &'b u8) {} + fn late_implicit(self, _: &u8, _: &u8) {} + fn late_early<'a, 'b>(self, _: &'a u8) -> &'b u8 { loop {} } + fn late_implicit_early<'b>(self, _: &u8) -> &'b u8 { loop {} } + + // 'late lifetimes here belong to nested types not to the tested functions. + fn early_tricky_explicit<'a>(_: for<'late> fn(&'late u8), + _: Box Fn(&'late u8)>) + -> &'a u8 { loop {} } + fn early_tricky_implicit<'a>(_: fn(&u8), + _: Box) + -> &'a u8 { loop {} } +} + +fn method_call() { + S.late(&0, &0); // OK + S.late::<'static>(&0, &0); + //~^ ERROR cannot specify lifetime arguments explicitly + //~| WARN this was previously accepted + S.late::<'static, 'static>(&0, &0); + //~^ ERROR cannot specify lifetime arguments explicitly + //~| WARN this was previously accepted + S.late::<'static, 'static, 'static>(&0, &0); + //~^ ERROR cannot specify lifetime arguments explicitly + //~| WARN this was previously accepted + S.late_early(&0); // OK + S.late_early::<'static>(&0); + //~^ ERROR cannot specify lifetime arguments explicitly + //~| WARN this was previously accepted + S.late_early::<'static, 'static>(&0); + //~^ ERROR cannot specify lifetime arguments explicitly + //~| WARN this was previously accepted + S.late_early::<'static, 'static, 'static>(&0); + //~^ ERROR cannot specify lifetime arguments explicitly + //~| WARN this was previously accepted + + S.late_implicit(&0, &0); // OK + S.late_implicit::<'static>(&0, &0); + //~^ ERROR cannot specify lifetime arguments explicitly + //~| WARN this was previously accepted + S.late_implicit::<'static, 'static>(&0, &0); + //~^ ERROR cannot specify lifetime arguments explicitly + //~| WARN this was previously accepted + S.late_implicit::<'static, 'static, 'static>(&0, &0); + //~^ ERROR cannot specify lifetime arguments explicitly + //~| WARN this was previously accepted + S.late_implicit_early(&0); // OK + S.late_implicit_early::<'static>(&0); + //~^ ERROR cannot specify lifetime arguments explicitly + //~| WARN this was previously accepted + S.late_implicit_early::<'static, 'static>(&0); + //~^ ERROR cannot specify lifetime arguments explicitly + //~| WARN this was previously accepted + S.late_implicit_early::<'static, 'static, 'static>(&0); + //~^ ERROR cannot specify lifetime arguments explicitly + //~| WARN this was previously accepted + + S::early_tricky_explicit::<'static>(loop {}, loop {}); // OK + S::early_tricky_implicit::<'static>(loop {}, loop {}); // OK +} + +fn ufcs() { + S::late_early::<'static>(S, &0); + //~^ ERROR cannot specify lifetime arguments explicitly + //~| WARN this was previously accepted + + S::late_implicit_early::<'static>(S, &0); + //~^ ERROR cannot specify lifetime arguments explicitly + //~| WARN this was previously accepted +} + +fn lint_not_inference_error() { + fn f<'early, 'late, T: 'early>() {} + + // Make sure `u8` is substituted and not replaced with an inference variable + f::<'static, u8>; + //~^ ERROR cannot specify lifetime arguments explicitly + //~| WARN this was previously accepted +} + +fn main() {} diff --git a/src/test/compile-fail/method-call-lifetime-args-subst-index.rs b/src/test/compile-fail/method-call-lifetime-args-subst-index.rs new file mode 100644 index 0000000000000..a9505e4f936a1 --- /dev/null +++ b/src/test/compile-fail/method-call-lifetime-args-subst-index.rs @@ -0,0 +1,25 @@ +// Copyright 2017 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)] +#![allow(unused)] + +struct S; + +impl S { + fn early_and_type<'a, T>(self) -> &'a T { loop {} } +} + +fn test() { + S.early_and_type::(); +} + +#[rustc_error] +fn main() {} //~ ERROR compilation successful diff --git a/src/test/compile-fail/method-call-lifetime-args-unresolved.rs b/src/test/compile-fail/method-call-lifetime-args-unresolved.rs new file mode 100644 index 0000000000000..4910bfaf4f60d --- /dev/null +++ b/src/test/compile-fail/method-call-lifetime-args-unresolved.rs @@ -0,0 +1,13 @@ +// Copyright 2017 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. + +fn main() { + 0.clone::<'a>(); //~ ERROR use of undeclared lifetime name `'a` +} diff --git a/src/test/compile-fail/method-call-lifetime-args.rs b/src/test/compile-fail/method-call-lifetime-args.rs new file mode 100644 index 0000000000000..f0a87c7470386 --- /dev/null +++ b/src/test/compile-fail/method-call-lifetime-args.rs @@ -0,0 +1,82 @@ +// Copyright 2017 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. + +struct S; + +impl S { + fn late<'a, 'b>(self, _: &'a u8, _: &'b u8) {} + fn late_implicit(self, _: &u8, _: &u8) {} + fn early<'a, 'b>(self) -> (&'a u8, &'b u8) { loop {} } + fn late_early<'a, 'b>(self, _: &'a u8) -> &'b u8 { loop {} } + fn late_implicit_early<'b>(self, _: &u8) -> &'b u8 { loop {} } + fn late_implicit_self_early<'b>(&self) -> &'b u8 { loop {} } + fn late_unused_early<'a, 'b>(self) -> &'b u8 { loop {} } + fn life_and_type<'a, T>(self) -> &'a T { loop {} } +} + +fn method_call() { + S.early(); // OK + S.early::<'static>(); + //~^ ERROR expected 2 lifetime parameters, found 1 lifetime parameter + S.early::<'static, 'static, 'static>(); + //~^ ERROR expected at most 2 lifetime parameters, found 3 lifetime parameters + let _: &u8 = S.life_and_type::<'static>(); + S.life_and_type::(); + S.life_and_type::<'static, u8>(); +} + +fn ufcs() { + S::late(S, &0, &0); // OK + S::late::<'static>(S, &0, &0); + //~^ ERROR cannot specify lifetime arguments explicitly + S::late::<'static, 'static>(S, &0, &0); + //~^ ERROR cannot specify lifetime arguments explicitly + S::late::<'static, 'static, 'static>(S, &0, &0); + //~^ ERROR cannot specify lifetime arguments explicitly + S::late_early(S, &0); // OK + S::late_early::<'static, 'static>(S, &0); + //~^ ERROR cannot specify lifetime arguments explicitly + S::late_early::<'static, 'static, 'static>(S, &0); + //~^ ERROR cannot specify lifetime arguments explicitly + + S::late_implicit(S, &0, &0); // OK + S::late_implicit::<'static>(S, &0, &0); + //~^ ERROR cannot specify lifetime arguments explicitly + S::late_implicit::<'static, 'static>(S, &0, &0); + //~^ ERROR cannot specify lifetime arguments explicitly + S::late_implicit::<'static, 'static, 'static>(S, &0, &0); + //~^ ERROR cannot specify lifetime arguments explicitly + S::late_implicit_early(S, &0); // OK + S::late_implicit_early::<'static, 'static>(S, &0); + //~^ ERROR cannot specify lifetime arguments explicitly + S::late_implicit_early::<'static, 'static, 'static>(S, &0); + //~^ ERROR cannot specify lifetime arguments explicitly + S::late_implicit_self_early(&S); // OK + S::late_implicit_self_early::<'static, 'static>(&S); + //~^ ERROR cannot specify lifetime arguments explicitly + S::late_implicit_self_early::<'static, 'static, 'static>(&S); + //~^ ERROR cannot specify lifetime arguments explicitly + S::late_unused_early(S); // OK + S::late_unused_early::<'static, 'static>(S); + //~^ ERROR cannot specify lifetime arguments explicitly + S::late_unused_early::<'static, 'static, 'static>(S); + //~^ ERROR cannot specify lifetime arguments explicitly + + S::early(S); // OK + S::early::<'static>(S); + //~^ ERROR expected 2 lifetime parameters, found 1 lifetime parameter + S::early::<'static, 'static, 'static>(S); + //~^ ERROR expected at most 2 lifetime parameters, found 3 lifetime parameters + let _: &u8 = S::life_and_type::<'static>(S); + S::life_and_type::(S); + S::life_and_type::<'static, u8>(S); +} + +fn main() {} diff --git a/src/test/compile-fail/method-call-type-binding.rs b/src/test/compile-fail/method-call-type-binding.rs index acffb06ebecf2..3ae878ed1cbc0 100644 --- a/src/test/compile-fail/method-call-type-binding.rs +++ b/src/test/compile-fail/method-call-type-binding.rs @@ -9,5 +9,5 @@ // except according to those terms. fn main() { - 0.clone::(); //~ ERROR type bindings cannot be used in method calls + 0.clone::(); //~ ERROR unexpected binding of associated item } diff --git a/src/test/compile-fail/trait-test-2.rs b/src/test/compile-fail/trait-test-2.rs index 2d4df77f96045..b08aab6da852a 100644 --- a/src/test/compile-fail/trait-test-2.rs +++ b/src/test/compile-fail/trait-test-2.rs @@ -15,9 +15,8 @@ impl bar for i32 { fn dup(&self) -> i32 { *self } fn blah(&self) {} } 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 given for this method: expected 1, found 2 + 10.dup::(); //~ ERROR expected at most 0 type parameters, found 1 type parameter + 10.blah::(); //~ ERROR expected at most 1 type parameter, found 2 type parameters (box 10 as Box).dup(); //~^ ERROR E0038 //~| ERROR E0038 diff --git a/src/test/compile-fail/vec-macro-with-comma-only.rs b/src/test/compile-fail/vec-macro-with-comma-only.rs index 96f58666fdff3..c79e67a376895 100644 --- a/src/test/compile-fail/vec-macro-with-comma-only.rs +++ b/src/test/compile-fail/vec-macro-with-comma-only.rs @@ -9,5 +9,5 @@ // except according to those terms. pub fn main() { - vec![,]; //~ ERROR expected expression, found `,` + vec![,]; //~ ERROR no rules expected the token `,` } diff --git a/src/test/incremental/hashes/inherent_impls.rs b/src/test/incremental/hashes/inherent_impls.rs index 899aefa24a033..daddc0c9f5459 100644 --- a/src/test/incremental/hashes/inherent_impls.rs +++ b/src/test/incremental/hashes/inherent_impls.rs @@ -369,7 +369,7 @@ impl Foo { impl Foo { #[rustc_dirty(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] - #[rustc_metadata_clean(cfg="cfail2")] // Apparently unused lifetimes don't show up in the type. + #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] pub fn add_lifetime_parameter_to_method<'a>(&self) { } } diff --git a/src/test/incremental/hashes/trait_defs.rs b/src/test/incremental/hashes/trait_defs.rs index e47556a790b62..44950ee8a601f 100644 --- a/src/test/incremental/hashes/trait_defs.rs +++ b/src/test/incremental/hashes/trait_defs.rs @@ -448,7 +448,7 @@ trait TraitAddLifetimeParameterToMethod { trait TraitAddLifetimeParameterToMethod { #[rustc_dirty(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] - #[rustc_metadata_clean(cfg="cfail2")] // Unused lifetimes don't seem to show up in type? + #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] fn method<'a>(); } diff --git a/src/test/incremental/spans_in_type_debuginfo.rs b/src/test/incremental/spans_in_type_debuginfo.rs new file mode 100644 index 0000000000000..7d8e6c9d9d7ef --- /dev/null +++ b/src/test/incremental/spans_in_type_debuginfo.rs @@ -0,0 +1,63 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test that moving a type definition within a source file does not affect +// re-compilation. + +// revisions:rpass1 rpass2 +// compile-flags: -Z query-dep-graph -g + +#![rustc_partition_reused(module="spans_in_type_debuginfo", cfg="rpass2")] +#![rustc_partition_reused(module="spans_in_type_debuginfo-structs", cfg="rpass2")] +#![rustc_partition_reused(module="spans_in_type_debuginfo-enums", cfg="rpass2")] + +#![feature(rustc_attrs)] + +mod structs { + #[cfg(rpass1)] + pub struct X { + pub x: u32, + } + + #[cfg(rpass2)] + pub struct X { + pub x: u32, + } + + pub fn foo(x: X) -> u32 { + x.x + } +} + +mod enums { + #[cfg(rpass1)] + pub enum X { + A { x: u32 }, + B(u32), + } + + #[cfg(rpass2)] + pub enum X { + A { x: u32 }, + B(u32), + } + + pub fn foo(x: X) -> u32 { + match x { + X::A { x } => x, + X::B(x) => x, + } + } +} + +pub fn main() { + let _ = structs::foo(structs::X { x: 1 }); + let _ = enums::foo(enums::X::A { x: 2 }); +} diff --git a/src/test/run-make/sanitizer-address/overflow.rs b/src/test/run-make/sanitizer-address/overflow.rs index e35c3873f7eb5..1f3c64c8c322d 100644 --- a/src/test/run-make/sanitizer-address/overflow.rs +++ b/src/test/run-make/sanitizer-address/overflow.rs @@ -10,5 +10,5 @@ fn main() { let xs = [0, 1, 2, 3]; - let y = unsafe { *xs.as_ptr().offset(4) }; + let _y = unsafe { *xs.as_ptr().offset(4) }; } diff --git a/src/test/run-make/sanitizer-cdylib-link/Makefile b/src/test/run-make/sanitizer-cdylib-link/Makefile new file mode 100644 index 0000000000000..9b0470fb277a9 --- /dev/null +++ b/src/test/run-make/sanitizer-cdylib-link/Makefile @@ -0,0 +1,19 @@ +-include ../tools.mk + +# This test builds a shared object, then an executable that links it as a native +# rust library (constrast to an rlib). The shared library and executable both +# are compiled with address sanitizer, and we assert that a fault in the cdylib +# is correctly detected. + +ifeq ($(TARGET),x86_64-unknown-linux-gnu) +ASAN_SUPPORT=$(SANITIZER_SUPPORT) +EXTRA_RUSTFLAG= +endif + +all: +ifeq ($(ASAN_SUPPORT),1) + $(RUSTC) -g -Z sanitizer=address --crate-type cdylib --target $(TARGET) library.rs + $(RUSTC) -g -Z sanitizer=address --crate-type bin --target $(TARGET) -llibrary program.rs + LD_LIBRARY_PATH=$(TMPDIR) $(TMPDIR)/program 2>&1 | grep -q stack-buffer-overflow +endif + diff --git a/src/test/run-make/sanitizer-cdylib-link/library.rs b/src/test/run-make/sanitizer-cdylib-link/library.rs new file mode 100644 index 0000000000000..4ceef5d3f5272 --- /dev/null +++ b/src/test/run-make/sanitizer-cdylib-link/library.rs @@ -0,0 +1,15 @@ +// Copyright 2017 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. + +#[no_mangle] +pub extern fn overflow() { + let xs = [0, 1, 2, 3]; + let _y = unsafe { *xs.as_ptr().offset(4) }; +} diff --git a/src/test/run-make/sanitizer-cdylib-link/program.rs b/src/test/run-make/sanitizer-cdylib-link/program.rs new file mode 100644 index 0000000000000..9f52817c85100 --- /dev/null +++ b/src/test/run-make/sanitizer-cdylib-link/program.rs @@ -0,0 +1,17 @@ +// Copyright 2017 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 overflow(); +} + +fn main() { + unsafe { overflow() } +} diff --git a/src/test/run-make/sanitizer-dylib-link/Makefile b/src/test/run-make/sanitizer-dylib-link/Makefile new file mode 100644 index 0000000000000..d75241f09710a --- /dev/null +++ b/src/test/run-make/sanitizer-dylib-link/Makefile @@ -0,0 +1,19 @@ +-include ../tools.mk + +# This test builds a shared object, then an executable that links it as a native +# rust library (constrast to an rlib). The shared library and executable both +# are compiled with address sanitizer, and we assert that a fault in the dylib +# is correctly detected. + +ifeq ($(TARGET),x86_64-unknown-linux-gnu) +ASAN_SUPPORT=$(SANITIZER_SUPPORT) +EXTRA_RUSTFLAG= +endif + +all: +ifeq ($(ASAN_SUPPORT),1) + $(RUSTC) -g -Z sanitizer=address --crate-type dylib --target $(TARGET) library.rs + $(RUSTC) -g -Z sanitizer=address --crate-type bin --target $(TARGET) -llibrary program.rs + LD_LIBRARY_PATH=$(TMPDIR) $(TMPDIR)/program 2>&1 | grep -q stack-buffer-overflow +endif + diff --git a/src/test/run-make/sanitizer-dylib-link/library.rs b/src/test/run-make/sanitizer-dylib-link/library.rs new file mode 100644 index 0000000000000..4ceef5d3f5272 --- /dev/null +++ b/src/test/run-make/sanitizer-dylib-link/library.rs @@ -0,0 +1,15 @@ +// Copyright 2017 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. + +#[no_mangle] +pub extern fn overflow() { + let xs = [0, 1, 2, 3]; + let _y = unsafe { *xs.as_ptr().offset(4) }; +} diff --git a/src/test/run-make/sanitizer-dylib-link/program.rs b/src/test/run-make/sanitizer-dylib-link/program.rs new file mode 100644 index 0000000000000..9f52817c85100 --- /dev/null +++ b/src/test/run-make/sanitizer-dylib-link/program.rs @@ -0,0 +1,17 @@ +// Copyright 2017 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 overflow(); +} + +fn main() { + unsafe { overflow() } +} diff --git a/src/test/run-make/sanitizer-dylib/Makefile b/src/test/run-make/sanitizer-dylib/Makefile deleted file mode 100644 index 835d5b0d9d8cd..0000000000000 --- a/src/test/run-make/sanitizer-dylib/Makefile +++ /dev/null @@ -1,8 +0,0 @@ --include ../tools.mk - -ifeq ($(TARGET),x86_64-unknown-linux-gnu) -all: - $(RUSTC) -Z sanitizer=leak --crate-type dylib --target $(TARGET) hello.rs 2>&1 | grep -q 'Only executables and rlibs can be compiled with `-Z sanitizer`' -else -all: -endif diff --git a/src/test/run-make/sanitizer-invalid-cratetype/Makefile b/src/test/run-make/sanitizer-invalid-cratetype/Makefile new file mode 100644 index 0000000000000..d03bbf84c1d11 --- /dev/null +++ b/src/test/run-make/sanitizer-invalid-cratetype/Makefile @@ -0,0 +1,18 @@ +-include ../tools.mk + +# NOTE the address sanitizer only supports x86_64 linux and macOS + +ifeq ($(TARGET),x86_64-apple-darwin) +ASAN_SUPPORT=$(SANITIZER_SUPPORT) +EXTRA_RUSTFLAG=-C rpath +else +ifeq ($(TARGET),x86_64-unknown-linux-gnu) +ASAN_SUPPORT=$(SANITIZER_SUPPORT) +EXTRA_RUSTFLAG= +endif +endif + +all: +ifeq ($(ASAN_SUPPORT),1) + $(RUSTC) -Z sanitizer=address --crate-type proc-macro --target $(TARGET) hello.rs 2>&1 | grep -q -- '-Z sanitizer' +endif diff --git a/src/test/run-make/sanitizer-dylib/hello.rs b/src/test/run-make/sanitizer-invalid-cratetype/hello.rs similarity index 100% rename from src/test/run-make/sanitizer-dylib/hello.rs rename to src/test/run-make/sanitizer-invalid-cratetype/hello.rs diff --git a/src/test/run-make/sanitizer-staticlib-link/Makefile b/src/test/run-make/sanitizer-staticlib-link/Makefile new file mode 100644 index 0000000000000..f92dc52b44575 --- /dev/null +++ b/src/test/run-make/sanitizer-staticlib-link/Makefile @@ -0,0 +1,18 @@ +-include ../tools.mk + +# This test builds a staticlib, then an executable that links to it. +# The staticlib and executable both are compiled with address sanitizer, +# and we assert that a fault in the staticlib is correctly detected. + +ifeq ($(TARGET),x86_64-unknown-linux-gnu) +ASAN_SUPPORT=$(SANITIZER_SUPPORT) +EXTRA_RUSTFLAG= +endif + +all: +ifeq ($(ASAN_SUPPORT),1) + $(RUSTC) -g -Z sanitizer=address --crate-type staticlib --target $(TARGET) library.rs + $(CC) program.c $(call STATICLIB,library) $(call OUT_EXE,program) $(EXTRACFLAGS) $(EXTRACXXFLAGS) + LD_LIBRARY_PATH=$(TMPDIR) $(TMPDIR)/program 2>&1 | grep -q stack-buffer-overflow +endif + diff --git a/src/test/run-make/sanitizer-staticlib-link/library.rs b/src/test/run-make/sanitizer-staticlib-link/library.rs new file mode 100644 index 0000000000000..4ceef5d3f5272 --- /dev/null +++ b/src/test/run-make/sanitizer-staticlib-link/library.rs @@ -0,0 +1,15 @@ +// Copyright 2017 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. + +#[no_mangle] +pub extern fn overflow() { + let xs = [0, 1, 2, 3]; + let _y = unsafe { *xs.as_ptr().offset(4) }; +} diff --git a/src/test/run-make/sanitizer-staticlib-link/program.c b/src/test/run-make/sanitizer-staticlib-link/program.c new file mode 100644 index 0000000000000..abd5d508e7295 --- /dev/null +++ b/src/test/run-make/sanitizer-staticlib-link/program.c @@ -0,0 +1,8 @@ +// ignore-license +void overflow(); + +int main() { + overflow(); + return 0; +} + diff --git a/src/test/run-make/type-mismatch-same-crate-name/Makefile b/src/test/run-make/type-mismatch-same-crate-name/Makefile new file mode 100644 index 0000000000000..1044d73fd1a36 --- /dev/null +++ b/src/test/run-make/type-mismatch-same-crate-name/Makefile @@ -0,0 +1,19 @@ +-include ../tools.mk + +all: + # compile two different versions of crateA + $(RUSTC) --crate-type=rlib crateA.rs -C metadata=-1 -C extra-filename=-1 + $(RUSTC) --crate-type=rlib crateA.rs -C metadata=-2 -C extra-filename=-2 + # make crateB depend on version 1 of crateA + $(RUSTC) --crate-type=rlib crateB.rs --extern crateA=$(TMPDIR)/libcrateA-1.rlib + # make crateC depend on version 2 of crateA + $(RUSTC) crateC.rs --extern crateA=$(TMPDIR)/libcrateA-2.rlib 2>&1 | \ + tr -d '\r\n' | grep \ + "mismatched types.*\ + crateB::try_foo(foo2);.*\ + expected struct \`crateA::foo::Foo\`, found struct \`crateA::Foo\`.*\ + different versions of crate \`crateA\`.*\ + mismatched types.*\ + crateB::try_bar(bar2);.*\ + expected trait \`crateA::bar::Bar\`, found trait \`crateA::Bar\`.*\ + different versions of crate \`crateA\`" diff --git a/src/test/run-make/type-mismatch-same-crate-name/crateA.rs b/src/test/run-make/type-mismatch-same-crate-name/crateA.rs new file mode 100644 index 0000000000000..e40266bb4cdaa --- /dev/null +++ b/src/test/run-make/type-mismatch-same-crate-name/crateA.rs @@ -0,0 +1,26 @@ +// Copyright 2017 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 { + pub struct Foo; +} + +mod bar { + pub trait Bar{} + + pub fn bar() -> Box { + unimplemented!() + } +} + +// This makes the publicly accessible path +// differ from the internal one. +pub use foo::Foo; +pub use bar::{Bar, bar}; diff --git a/src/test/run-make/type-mismatch-same-crate-name/crateB.rs b/src/test/run-make/type-mismatch-same-crate-name/crateB.rs new file mode 100644 index 0000000000000..da4ea1c9387e9 --- /dev/null +++ b/src/test/run-make/type-mismatch-same-crate-name/crateB.rs @@ -0,0 +1,14 @@ +// Copyright 2017 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 crateA; + +pub fn try_foo(x: crateA::Foo){} +pub fn try_bar(x: Box){} diff --git a/src/test/run-make/type-mismatch-same-crate-name/crateC.rs b/src/test/run-make/type-mismatch-same-crate-name/crateC.rs new file mode 100644 index 0000000000000..da869d2145fe1 --- /dev/null +++ b/src/test/run-make/type-mismatch-same-crate-name/crateC.rs @@ -0,0 +1,35 @@ +// Copyright 2017 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 tests the extra note reported when a type error deals with +// seemingly identical types. +// The main use case of this error is when there are two crates +// (generally different versions of the same crate) with the same name +// causing a type mismatch. + +// The test is nearly the same as the one in +// compile-fail/type-mismatch-same-crate-name.rs +// but deals with the case where one of the crates +// is only introduced as an indirect dependency. +// and the type is accessed via a reexport. +// This is similar to how the error can be introduced +// when using cargo's automatic dependency resolution. + +extern crate crateA; + +fn main() { + let foo2 = crateA::Foo; + let bar2 = crateA::bar(); + { + extern crate crateB; + crateB::try_foo(foo2); + crateB::try_bar(bar2); + } +} diff --git a/src/test/run-pass/i128-ffi.rs b/src/test/run-pass/i128-ffi.rs index d07fb7b4a7143..d989210dd71f2 100644 --- a/src/test/run-pass/i128-ffi.rs +++ b/src/test/run-pass/i128-ffi.rs @@ -13,12 +13,7 @@ // should look like. // ignore-windows - -// Ignore 32 bit targets: -// ignore-x86 -// ignore-arm - -// ignore-emscripten +// ignore-32bit #![feature(i128_type)] diff --git a/src/test/run-pass/i128.rs b/src/test/run-pass/i128.rs index c5057f70c065a..7c14d34b0ee12 100644 --- a/src/test/run-pass/i128.rs +++ b/src/test/run-pass/i128.rs @@ -109,4 +109,8 @@ fn main() { assert_eq!(b(-87559967289969187895646876466835277875_i128) / b(84285771033834995895337664386045050880_i128), -1i128); + + // iter-arithmetic traits + assert_eq!(10i128, [1i128, 2, 3, 4].iter().sum()); + assert_eq!(24i128, [1i128, 2, 3, 4].iter().product()); } diff --git a/src/test/run-pass/issue-40847.rs b/src/test/run-pass/issue-40847.rs new file mode 100644 index 0000000000000..2fa99984401c1 --- /dev/null +++ b/src/test/run-pass/issue-40847.rs @@ -0,0 +1,26 @@ +// Copyright 2017 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! gen { + ($name:ident ( $($dol:tt $var:ident)* ) $($body:tt)*) => { + macro_rules! $name { + ($($dol $var:ident)*) => { + $($body)* + } + } + } +} + +gen!(m($var) $var); + +fn main() { + let x = 1; + assert_eq!(m!(x), 1); +} diff --git a/src/test/run-pass/macro-first-set.rs b/src/test/run-pass/macro-first-set.rs new file mode 100644 index 0000000000000..99e5d22fb476e --- /dev/null +++ b/src/test/run-pass/macro-first-set.rs @@ -0,0 +1,245 @@ +// Copyright 2017 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(macro_vis_matcher)] + +//{{{ issue 40569 ============================================================== + +macro_rules! my_struct { + ($(#[$meta:meta])* $ident:ident) => { + $(#[$meta])* struct $ident; + } +} + +my_struct!(#[derive(Debug, PartialEq)] Foo40569); + +fn test_40569() { + assert_eq!(Foo40569, Foo40569); +} + +//}}} + +//{{{ issue 26444 ============================================================== + +macro_rules! foo_26444 { + ($($beginning:ident),*; $middle:ident; $($end:ident),*) => { + stringify!($($beginning,)* $middle $(,$end)*) + } +} + +fn test_26444() { + assert_eq!("a , b , c , d , e", foo_26444!(a, b; c; d, e)); + assert_eq!("f", foo_26444!(; f ;)); +} + +macro_rules! pat_26444 { + ($fname:ident $($arg:pat)* =) => {} +} + +pat_26444!(foo 1 2 5...7 =); +pat_26444!(bar Some(ref x) Ok(ref mut y) &(w, z) =); + +//}}} + +//{{{ issue 40984 ============================================================== + +macro_rules! thread_local_40984 { + () => {}; + ($(#[$attr:meta])* $vis:vis static $name:ident: $t:ty = $init:expr; $($rest:tt)*) => { + thread_local_40984!($($rest)*); + }; + ($(#[$attr:meta])* $vis:vis static $name:ident: $t:ty = $init:expr) => {}; +} + +thread_local_40984! { + // no docs + #[allow(unused)] + static FOO: i32 = 42; + /// docs + pub static BAR: String = String::from("bar"); + + // look at these restrictions!! + pub(crate) static BAZ: usize = 0; + pub(in foo) static QUUX: usize = 0; +} + +//}}} + +//{{{ issue 35650 ============================================================== + +macro_rules! size { + ($ty:ty) => { + std::mem::size_of::<$ty>() + }; + ($size:tt) => { + $size + }; +} + +fn test_35650() { + assert_eq!(size!(u64), 8); + assert_eq!(size!(5), 5); +} + +//}}} + +//{{{ issue 27832 ============================================================== + +macro_rules! m { + ( $i:ident ) => (); + ( $t:tt $j:tt ) => (); +} + +m!(c); +m!(t 9); +m!(0 9); +m!(struct); +m!(struct Foo); + +macro_rules! m2 { + ( $b:expr ) => (); + ( $t:tt $u:tt ) => (); +} + +m2!(3); +m2!(1 2); +m2!(_ 1); +m2!(enum Foo); + +//}}} + +//{{{ issue 39964 ============================================================== + +macro_rules! foo_39964 { + ($a:ident) => {}; + (_) => {}; +} + +foo_39964!(_); + +//}}} + +//{{{ issue 34030 ============================================================== + +macro_rules! foo_34030 { + ($($t:ident),* /) => {}; +} + +foo_34030!(a, b/); +foo_34030!(a/); +foo_34030!(/); + +//}}} + +//{{{ issue 24189 ============================================================== + +macro_rules! foo_24189 { + ( + pub enum $name:ident { + $( #[$attr:meta] )* $var:ident + } + ) => { + pub enum $name { + $( #[$attr] )* $var + } + }; +} + +foo_24189! { + pub enum Foo24189 { + #[doc = "Bar"] Baz + } +} + +macro_rules! serializable { + ( + $(#[$struct_meta:meta])* + pub struct $name:ident { + $( + $(#[$field_meta:meta])* + $field:ident: $type_:ty + ),* , + } + ) => { + $(#[$struct_meta])* + pub struct $name { + $( + $(#[$field_meta])* + $field: $type_ + ),* , + } + } +} + +serializable! { + #[allow(dead_code)] + /// This is a test + pub struct Tester { + #[allow(dead_code)] + name: String, + } +} + +macro_rules! foo_24189_c { + ( $( > )* $x:ident ) => { }; +} +foo_24189_c!( > a ); + +fn test_24189() { + let _ = Foo24189::Baz; + let _ = Tester { name: "".to_owned() }; +} + +//}}} + +//{{{ some more tests ========================================================== + +macro_rules! test_block { + (< $($b:block)* >) => {} +} + +test_block!(<>); +test_block!(<{}>); +test_block!(<{1}{2}>); + +macro_rules! test_ty { + ($($t:ty),* $(,)*) => {} +} + +test_ty!(); +test_ty!(,); +test_ty!(u8); +test_ty!(u8,); + +macro_rules! test_path { + ($($t:path),* $(,)*) => {} +} + +test_path!(); +test_path!(,); +test_path!(::std); +test_path!(std::u8,); +test_path!(any, super, super::super::self::path, X::Z<'a, T=U>); + +macro_rules! test_meta_block { + ($($m:meta)* $b:block) => {}; +} + +test_meta_block!(windows {}); + +//}}} + +fn main() { + test_26444(); + test_40569(); + test_35650(); + test_24189(); +} + diff --git a/src/test/run-pass/rfc1857-drop-order.rs b/src/test/run-pass/rfc1857-drop-order.rs new file mode 100644 index 0000000000000..42f989538c890 --- /dev/null +++ b/src/test/run-pass/rfc1857-drop-order.rs @@ -0,0 +1,231 @@ +// Copyright 2017 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(dead_code, unreachable_code)] + +use std::cell::RefCell; +use std::rc::Rc; +use std::panic::{self, AssertUnwindSafe, UnwindSafe}; + +// This struct is used to record the order in which elements are dropped +struct PushOnDrop { + vec: Rc>>, + val: u32 +} + +impl PushOnDrop { + fn new(val: u32, vec: Rc>>) -> PushOnDrop { + PushOnDrop { vec, val } + } +} + +impl Drop for PushOnDrop { + fn drop(&mut self) { + self.vec.borrow_mut().push(self.val) + } +} + +impl UnwindSafe for PushOnDrop { } + +// Structs +struct TestStruct { + x: PushOnDrop, + y: PushOnDrop, + z: PushOnDrop +} + +// Tuple structs +struct TestTupleStruct(PushOnDrop, PushOnDrop, PushOnDrop); + +// Enum variants +enum TestEnum { + Tuple(PushOnDrop, PushOnDrop, PushOnDrop), + Struct { x: PushOnDrop, y: PushOnDrop, z: PushOnDrop } +} + +fn test_drop_tuple() { + // Tuple fields are dropped in the same order they are declared + let dropped_fields = Rc::new(RefCell::new(Vec::new())); + let test_tuple = (PushOnDrop::new(1, dropped_fields.clone()), + PushOnDrop::new(2, dropped_fields.clone())); + drop(test_tuple); + assert_eq!(*dropped_fields.borrow(), &[1, 2]); + + // Panic during construction means that fields are treated as local variables + // Therefore they are dropped in reverse order of initialization + let dropped_fields = Rc::new(RefCell::new(Vec::new())); + let cloned = AssertUnwindSafe(dropped_fields.clone()); + panic::catch_unwind(|| { + (PushOnDrop::new(2, cloned.clone()), + PushOnDrop::new(1, cloned.clone()), + panic!("this panic is catched :D")); + }).err().unwrap(); + assert_eq!(*dropped_fields.borrow(), &[1, 2]); +} + +fn test_drop_struct() { + // Struct fields are dropped in the same order they are declared + let dropped_fields = Rc::new(RefCell::new(Vec::new())); + let test_struct = TestStruct { + x: PushOnDrop::new(1, dropped_fields.clone()), + y: PushOnDrop::new(2, dropped_fields.clone()), + z: PushOnDrop::new(3, dropped_fields.clone()), + }; + drop(test_struct); + assert_eq!(*dropped_fields.borrow(), &[1, 2, 3]); + + // The same holds for tuple structs + let dropped_fields = Rc::new(RefCell::new(Vec::new())); + let test_tuple_struct = TestTupleStruct(PushOnDrop::new(1, dropped_fields.clone()), + PushOnDrop::new(2, dropped_fields.clone()), + PushOnDrop::new(3, dropped_fields.clone())); + drop(test_tuple_struct); + assert_eq!(*dropped_fields.borrow(), &[1, 2, 3]); + + // Panic during struct construction means that fields are treated as local variables + // Therefore they are dropped in reverse order of initialization + let dropped_fields = Rc::new(RefCell::new(Vec::new())); + let cloned = AssertUnwindSafe(dropped_fields.clone()); + panic::catch_unwind(|| { + TestStruct { + x: PushOnDrop::new(2, cloned.clone()), + y: PushOnDrop::new(1, cloned.clone()), + z: panic!("this panic is catched :D") + }; + }).err().unwrap(); + assert_eq!(*dropped_fields.borrow(), &[1, 2]); + + // Test with different initialization order + let dropped_fields = Rc::new(RefCell::new(Vec::new())); + let cloned = AssertUnwindSafe(dropped_fields.clone()); + panic::catch_unwind(|| { + TestStruct { + y: PushOnDrop::new(2, cloned.clone()), + x: PushOnDrop::new(1, cloned.clone()), + z: panic!("this panic is catched :D") + }; + }).err().unwrap(); + assert_eq!(*dropped_fields.borrow(), &[1, 2]); + + // The same holds for tuple structs + let dropped_fields = Rc::new(RefCell::new(Vec::new())); + let cloned = AssertUnwindSafe(dropped_fields.clone()); + panic::catch_unwind(|| { + TestTupleStruct(PushOnDrop::new(2, cloned.clone()), + PushOnDrop::new(1, cloned.clone()), + panic!("this panic is catched :D")); + }).err().unwrap(); + assert_eq!(*dropped_fields.borrow(), &[1, 2]); +} + +fn test_drop_enum() { + // Enum variants are dropped in the same order they are declared + let dropped_fields = Rc::new(RefCell::new(Vec::new())); + let test_struct_enum = TestEnum::Struct { + x: PushOnDrop::new(1, dropped_fields.clone()), + y: PushOnDrop::new(2, dropped_fields.clone()), + z: PushOnDrop::new(3, dropped_fields.clone()) + }; + drop(test_struct_enum); + assert_eq!(*dropped_fields.borrow(), &[1, 2, 3]); + + // The same holds for tuple enum variants + let dropped_fields = Rc::new(RefCell::new(Vec::new())); + let test_tuple_enum = TestEnum::Tuple(PushOnDrop::new(1, dropped_fields.clone()), + PushOnDrop::new(2, dropped_fields.clone()), + PushOnDrop::new(3, dropped_fields.clone())); + drop(test_tuple_enum); + assert_eq!(*dropped_fields.borrow(), &[1, 2, 3]); + + // Panic during enum construction means that fields are treated as local variables + // Therefore they are dropped in reverse order of initialization + let dropped_fields = Rc::new(RefCell::new(Vec::new())); + let cloned = AssertUnwindSafe(dropped_fields.clone()); + panic::catch_unwind(|| { + TestEnum::Struct { + x: PushOnDrop::new(2, cloned.clone()), + y: PushOnDrop::new(1, cloned.clone()), + z: panic!("this panic is catched :D") + }; + }).err().unwrap(); + assert_eq!(*dropped_fields.borrow(), &[1, 2]); + + // Test with different initialization order + let dropped_fields = Rc::new(RefCell::new(Vec::new())); + let cloned = AssertUnwindSafe(dropped_fields.clone()); + panic::catch_unwind(|| { + TestEnum::Struct { + y: PushOnDrop::new(2, cloned.clone()), + x: PushOnDrop::new(1, cloned.clone()), + z: panic!("this panic is catched :D") + }; + }).err().unwrap(); + assert_eq!(*dropped_fields.borrow(), &[1, 2]); + + // The same holds for tuple enum variants + let dropped_fields = Rc::new(RefCell::new(Vec::new())); + let cloned = AssertUnwindSafe(dropped_fields.clone()); + panic::catch_unwind(|| { + TestEnum::Tuple(PushOnDrop::new(2, cloned.clone()), + PushOnDrop::new(1, cloned.clone()), + panic!("this panic is catched :D")); + }).err().unwrap(); + assert_eq!(*dropped_fields.borrow(), &[1, 2]); +} + +fn test_drop_list() { + // Elements in a Vec are dropped in the same order they are pushed + let dropped_fields = Rc::new(RefCell::new(Vec::new())); + let xs = vec![PushOnDrop::new(1, dropped_fields.clone()), + PushOnDrop::new(2, dropped_fields.clone()), + PushOnDrop::new(3, dropped_fields.clone())]; + drop(xs); + assert_eq!(*dropped_fields.borrow(), &[1, 2, 3]); + + // The same holds for arrays + let dropped_fields = Rc::new(RefCell::new(Vec::new())); + let xs = [PushOnDrop::new(1, dropped_fields.clone()), + PushOnDrop::new(2, dropped_fields.clone()), + PushOnDrop::new(3, dropped_fields.clone())]; + drop(xs); + assert_eq!(*dropped_fields.borrow(), &[1, 2, 3]); + + // Panic during vec construction means that fields are treated as local variables + // Therefore they are dropped in reverse order of initialization + let dropped_fields = Rc::new(RefCell::new(Vec::new())); + let cloned = AssertUnwindSafe(dropped_fields.clone()); + panic::catch_unwind(|| { + vec![ + PushOnDrop::new(2, cloned.clone()), + PushOnDrop::new(1, cloned.clone()), + panic!("this panic is catched :D") + ]; + }).err().unwrap(); + assert_eq!(*dropped_fields.borrow(), &[1, 2]); + + // The same holds for arrays + let dropped_fields = Rc::new(RefCell::new(Vec::new())); + let cloned = AssertUnwindSafe(dropped_fields.clone()); + panic::catch_unwind(|| { + [ + PushOnDrop::new(2, cloned.clone()), + PushOnDrop::new(1, cloned.clone()), + panic!("this panic is catched :D") + ]; + }).err().unwrap(); + assert_eq!(*dropped_fields.borrow(), &[1, 2]); +} + +fn main() { + test_drop_tuple(); + test_drop_struct(); + test_drop_enum(); + test_drop_list(); +} diff --git a/src/test/run-pass/thread-local-syntax.rs b/src/test/run-pass/thread-local-syntax.rs index a5967249b5454..373824122fd51 100644 --- a/src/test/run-pass/thread-local-syntax.rs +++ b/src/test/run-pass/thread-local-syntax.rs @@ -11,13 +11,21 @@ #![deny(missing_docs)] //! this tests the syntax of `thread_local!` -thread_local! { - // no docs - #[allow(unused)] - static FOO: i32 = 42; - /// docs - pub static BAR: String = String::from("bar"); +mod foo { + mod bar { + thread_local! { + // no docs + #[allow(unused)] + static FOO: i32 = 42; + /// docs + pub static BAR: String = String::from("bar"); + + // look at these restrictions!! + pub(crate) static BAZ: usize = 0; + pub(in foo) static QUUX: usize = 0; + } + thread_local!(static SPLOK: u32 = 0); + } } -thread_local!(static BAZ: u32 = 0); fn main() {} diff --git a/src/test/run-pass/tls-try-with.rs b/src/test/run-pass/tls-try-with.rs new file mode 100644 index 0000000000000..c072ec0679d73 --- /dev/null +++ b/src/test/run-pass/tls-try-with.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. + +// ignore-emscripten no threads support + +#![feature(thread_local_state)] + +use std::thread; + +static mut DROP_RUN: bool = false; + +struct Foo; + +thread_local!(static FOO: Foo = Foo {}); + +impl Drop for Foo { + fn drop(&mut self) { + assert!(FOO.try_with(|_| panic!("`try_with` closure run")).is_err()); + unsafe { DROP_RUN = true; } + } +} + +fn main() { + thread::spawn(|| { + assert_eq!(FOO.try_with(|_| { + 132 + }).expect("`try_with` failed"), 132); + }).join().unwrap(); + assert!(unsafe { DROP_RUN }); +} diff --git a/src/test/run-pass/u128.rs b/src/test/run-pass/u128.rs index cfd616c56b4f0..b16f6c7b6af55 100644 --- a/src/test/run-pass/u128.rs +++ b/src/test/run-pass/u128.rs @@ -122,4 +122,8 @@ fn main() { assert_eq!(b(0x679289ac23bb334f_36144401cf882172_u128) / b(0x7b0b271b64865f05_f54a7b72746c062f_u128), 0u128); + + // iter-arithmetic traits + assert_eq!(10u128, [1u128, 2, 3, 4].iter().sum()); + assert_eq!(24u128, [1u128, 2, 3, 4].iter().product()); } diff --git a/src/test/run-pass/unsized-tuple-impls.rs b/src/test/run-pass/unsized-tuple-impls.rs new file mode 100644 index 0000000000000..591b19f89e897 --- /dev/null +++ b/src/test/run-pass/unsized-tuple-impls.rs @@ -0,0 +1,29 @@ +// Copyright 2017 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(unsized_tuple_coercion)] + +use std::collections::HashSet; + +fn main() { + let x : &(i32, i32, [i32]) = &(0, 1, [2, 3]); + let y : &(i32, i32, [i32]) = &(0, 1, [2, 3, 4]); + let mut a = [y, x]; + a.sort(); + assert_eq!(a, [x, y]); + + assert_eq!(&format!("{:?}", a), "[(0, 1, [2, 3]), (0, 1, [2, 3, 4])]"); + + let mut h = HashSet::new(); + h.insert(x); + h.insert(y); + assert!(h.contains(x)); + assert!(h.contains(y)); +} diff --git a/src/test/ui-fulldeps/auxiliary/attr_proc_macro.rs b/src/test/ui-fulldeps/auxiliary/attr_proc_macro.rs new file mode 100644 index 0000000000000..db0c19e96f821 --- /dev/null +++ b/src/test/ui-fulldeps/auxiliary/attr_proc_macro.rs @@ -0,0 +1,23 @@ +// Copyright 2016 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. + +// force-host +// no-prefer-dynamic +#![feature(proc_macro)] +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_attribute] +pub fn attr_proc_macro(_: TokenStream, input: TokenStream) -> TokenStream { + input +} diff --git a/src/test/compile-fail/E0035.rs b/src/test/ui-fulldeps/auxiliary/bang_proc_macro.rs similarity index 67% rename from src/test/compile-fail/E0035.rs rename to src/test/ui-fulldeps/auxiliary/bang_proc_macro.rs index 9322d21d2a88d..89ac11b309d75 100644 --- a/src/test/compile-fail/E0035.rs +++ b/src/test/ui-fulldeps/auxiliary/bang_proc_macro.rs @@ -8,14 +8,16 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -struct Test; +// force-host +// no-prefer-dynamic +#![feature(proc_macro)] +#![crate_type = "proc-macro"] -impl Test { - fn method(&self) {} -} +extern crate proc_macro; + +use proc_macro::TokenStream; -fn main() { - let x = Test; - x.method::(); //~ ERROR E0035 - //~| NOTE called with unneeded type parameters +#[proc_macro] +pub fn bang_proc_macro(input: TokenStream) -> TokenStream { + input } diff --git a/src/test/ui-fulldeps/auxiliary/derive-clona.rs b/src/test/ui-fulldeps/auxiliary/derive-clona.rs new file mode 100644 index 0000000000000..719fbdb15ef2a --- /dev/null +++ b/src/test/ui-fulldeps/auxiliary/derive-clona.rs @@ -0,0 +1,23 @@ +// Copyright 2016 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. + +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_derive(Clona)] +pub fn derive_clonea(input: TokenStream) -> TokenStream { + "".parse().unwrap() +} diff --git a/src/test/ui-fulldeps/auxiliary/derive-foo.rs b/src/test/ui-fulldeps/auxiliary/derive-foo.rs new file mode 100644 index 0000000000000..64dcf72ba2029 --- /dev/null +++ b/src/test/ui-fulldeps/auxiliary/derive-foo.rs @@ -0,0 +1,23 @@ +// Copyright 2016 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. + +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_derive(FooWithLongName)] +pub fn derive_foo(input: TokenStream) -> TokenStream { + "".parse().unwrap() +} diff --git a/src/test/compile-fail-fulldeps/proc-macro/resolve-error.rs b/src/test/ui-fulldeps/resolve-error.rs similarity index 57% rename from src/test/compile-fail-fulldeps/proc-macro/resolve-error.rs rename to src/test/ui-fulldeps/resolve-error.rs index ddd8631f02e62..dfaa1d7a32e57 100644 --- a/src/test/compile-fail-fulldeps/proc-macro/resolve-error.rs +++ b/src/test/ui-fulldeps/resolve-error.rs @@ -35,46 +35,29 @@ macro_rules! attr_proc_mac { } #[derive(FooWithLongNan)] -//~^ ERROR cannot find derive macro `FooWithLongNan` in this scope -//~^^ HELP did you mean `FooWithLongName`? struct Foo; #[attr_proc_macra] -//~^ ERROR cannot find attribute macro `attr_proc_macra` in this scope -//~^^ HELP did you mean `attr_proc_macro`? struct Bar; #[FooWithLongNan] -//~^ ERROR cannot find attribute macro `FooWithLongNan` in this scope struct Asdf; #[derive(Dlone)] -//~^ ERROR cannot find derive macro `Dlone` in this scope -//~^^ HELP did you mean `Clone`? struct A; #[derive(Dlona)] -//~^ ERROR cannot find derive macro `Dlona` in this scope -//~^^ HELP did you mean `Clona`? struct B; #[derive(attr_proc_macra)] -//~^ ERROR cannot find derive macro `attr_proc_macra` in this scope struct C; fn main() { FooWithLongNama!(); - //~^ ERROR cannot find macro `FooWithLongNama!` in this scope - //~^^ HELP did you mean `FooWithLongNam!`? attr_proc_macra!(); - //~^ ERROR cannot find macro `attr_proc_macra!` in this scope - //~^^ HELP did you mean `attr_proc_mac!`? Dlona!(); - //~^ ERROR cannot find macro `Dlona!` in this scope bang_proc_macrp!(); - //~^ ERROR cannot find macro `bang_proc_macrp!` in this scope - //~^^ HELP did you mean `bang_proc_macro!`? } diff --git a/src/test/ui-fulldeps/resolve-error.stderr b/src/test/ui-fulldeps/resolve-error.stderr new file mode 100644 index 0000000000000..754f6bc4f1c1c --- /dev/null +++ b/src/test/ui-fulldeps/resolve-error.stderr @@ -0,0 +1,62 @@ +error: cannot find derive macro `FooWithLongNan` in this scope + --> $DIR/resolve-error.rs:37:10 + | +37 | #[derive(FooWithLongNan)] + | ^^^^^^^^^^^^^^ help: try: `FooWithLongName` + +error: cannot find attribute macro `attr_proc_macra` in this scope + --> $DIR/resolve-error.rs:40:3 + | +40 | #[attr_proc_macra] + | ^^^^^^^^^^^^^^^ help: try: `attr_proc_macro` + +error: cannot find attribute macro `FooWithLongNan` in this scope + --> $DIR/resolve-error.rs:43:3 + | +43 | #[FooWithLongNan] + | ^^^^^^^^^^^^^^ + +error: cannot find derive macro `Dlone` in this scope + --> $DIR/resolve-error.rs:46:10 + | +46 | #[derive(Dlone)] + | ^^^^^ help: try: `Clone` + +error: cannot find derive macro `Dlona` in this scope + --> $DIR/resolve-error.rs:49:10 + | +49 | #[derive(Dlona)] + | ^^^^^ help: try: `Clona` + +error: cannot find derive macro `attr_proc_macra` in this scope + --> $DIR/resolve-error.rs:52:10 + | +52 | #[derive(attr_proc_macra)] + | ^^^^^^^^^^^^^^^ + +error: cannot find macro `FooWithLongNama!` in this scope + --> $DIR/resolve-error.rs:56:5 + | +56 | FooWithLongNama!(); + | ^^^^^^^^^^^^^^^ help: you could try the macro: `FooWithLongNam!` + +error: cannot find macro `attr_proc_macra!` in this scope + --> $DIR/resolve-error.rs:58:5 + | +58 | attr_proc_macra!(); + | ^^^^^^^^^^^^^^^ help: you could try the macro: `attr_proc_mac!` + +error: cannot find macro `Dlona!` in this scope + --> $DIR/resolve-error.rs:60:5 + | +60 | Dlona!(); + | ^^^^^ + +error: cannot find macro `bang_proc_macrp!` in this scope + --> $DIR/resolve-error.rs:62:5 + | +62 | bang_proc_macrp!(); + | ^^^^^^^^^^^^^^^ help: you could try the macro: `bang_proc_macro!` + +error: aborting due to 10 previous errors + diff --git a/src/test/ui/README.md b/src/test/ui/README.md deleted file mode 100644 index dcdeabd80322f..0000000000000 --- a/src/test/ui/README.md +++ /dev/null @@ -1,31 +0,0 @@ -# Guide to the UI Tests - -The UI tests are intended to capture the compiler's complete output, -so that we can test all aspects of the presentation. They work by -compiling a file (e.g., `hello_world/main.rs`), capturing the output, -and then applying some normalization (see below). This normalized -result is then compared against reference files named -`hello_world/main.stderr` and `hello_world/main.stdout`. If either of -those files doesn't exist, the output must be empty. If the test run -fails, we will print out the current output, but it is also saved in -`build//test/ui/hello_world/main.stdout` (this path is -printed as part of the test failure mesage), so you can run `diff` and -so forth. - -# Editing and updating the reference files - -If you have changed the compiler's output intentionally, or you are -making a new test, you can use the script `update-references.sh` to -update the references. When you run the test framework, it will report -various errors: in those errors is a command you can use to run the -`update-references.sh` script, which will then copy over the files -from the build directory and use them as the new reference. You can -also just run `update-all-references.sh`. In both cases, you can run -the script with `--help` to get a help message. - -# Normalization - -The normalization applied is aimed at filenames: - -- the test directory is replaced with `$DIR` -- all backslashes (\) are converted to forward slashes (/) (for windows) diff --git a/src/test/compile-fail/cast-to-unsized-trait-object-suggestion.rs b/src/test/ui/cast-to-unsized-trait-object-suggestion.rs similarity index 67% rename from src/test/compile-fail/cast-to-unsized-trait-object-suggestion.rs rename to src/test/ui/cast-to-unsized-trait-object-suggestion.rs index d18746cdf0ba5..c793454798275 100644 --- a/src/test/compile-fail/cast-to-unsized-trait-object-suggestion.rs +++ b/src/test/ui/cast-to-unsized-trait-object-suggestion.rs @@ -10,11 +10,5 @@ fn main() { &1 as Send; - //~^ ERROR cast to unsized type - //~| HELP try casting to a reference instead: - //~| SUGGESTION &1 as &Send; Box::new(1) as Send; - //~^ ERROR cast to unsized type - //~| HELP try casting to a `Box` instead: - //~| SUGGESTION Box::new(1) as Box; } diff --git a/src/test/ui/cast-to-unsized-trait-object-suggestion.stderr b/src/test/ui/cast-to-unsized-trait-object-suggestion.stderr new file mode 100644 index 0000000000000..4d4eb7b4ecfdb --- /dev/null +++ b/src/test/ui/cast-to-unsized-trait-object-suggestion.stderr @@ -0,0 +1,18 @@ +error[E0620]: cast to unsized type: `&{integer}` as `std::marker::Send` + --> $DIR/cast-to-unsized-trait-object-suggestion.rs:12:5 + | +12 | &1 as Send; + | ^^^^^^---- + | | + | help: try casting to a reference instead: `&Send` + +error[E0620]: cast to unsized type: `std::boxed::Box<{integer}>` as `std::marker::Send` + --> $DIR/cast-to-unsized-trait-object-suggestion.rs:13:5 + | +13 | Box::new(1) as Send; + | ^^^^^^^^^^^^^^^---- + | | + | help: try casting to a `Box` instead: `Box` + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/check_match/issue-43253.rs b/src/test/ui/check_match/issue-43253.rs new file mode 100644 index 0000000000000..c77fa74f6e0e5 --- /dev/null +++ b/src/test/ui/check_match/issue-43253.rs @@ -0,0 +1,51 @@ +// Copyright 2017 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(exclusive_range_pattern)] + +fn main() { + // These cases should generate no warning. + match 10 { + 1..10 => {}, + 10 => {}, + _ => {}, + } + + match 10 { + 1..10 => {}, + 9...10 => {}, + _ => {}, + } + + match 10 { + 1..10 => {}, + 10...10 => {}, + _ => {}, + } + + // These cases should generate an "unreachable pattern" warning. + match 10 { + 1..10 => {}, + 9 => {}, + _ => {}, + } + + match 10 { + 1..10 => {}, + 8...9 => {}, + _ => {}, + } + + match 10 { + 1..10 => {}, + 9...9 => {}, + _ => {}, + } +} \ No newline at end of file diff --git a/src/test/ui/check_match/issue-43253.stderr b/src/test/ui/check_match/issue-43253.stderr new file mode 100644 index 0000000000000..0d4a2ecf512de --- /dev/null +++ b/src/test/ui/check_match/issue-43253.stderr @@ -0,0 +1,20 @@ +warning: unreachable pattern + --> $DIR/issue-43253.rs:36:9 + | +36 | 9 => {}, + | ^ + | + = note: #[warn(unreachable_patterns)] on by default + +warning: unreachable pattern + --> $DIR/issue-43253.rs:42:9 + | +42 | 8...9 => {}, + | ^^^^^ + +warning: unreachable pattern + --> $DIR/issue-43253.rs:48:9 + | +48 | 9...9 => {}, + | ^^^^^ + diff --git a/src/test/ui/enum-size-variance.rs b/src/test/ui/enum-size-variance.rs index 075bd9acf5f38..582998a986d00 100644 --- a/src/test/ui/enum-size-variance.rs +++ b/src/test/ui/enum-size-variance.rs @@ -9,10 +9,6 @@ // except according to those terms. // run-pass -// ignore-x86 -// ignore-arm -// ignore-emscripten -// ^ ignore 32-bit targets, as the error message is target-dependent. see PR #41968. #![warn(variant_size_differences)] #![allow(dead_code)] @@ -24,26 +20,26 @@ enum Enum1 { } enum Enum2 { A, B, C } -enum Enum3 { D(isize), E, F } +enum Enum3 { D(i64), E, F } -enum Enum4 { H(isize), I(isize), J } +enum Enum4 { H(i64), I(i64), J } enum Enum5 { - L(isize, isize, isize, isize), //~ WARNING three times larger - M(isize), + L(i64, i64, i64, i64), //~ WARNING three times larger + M(i64), N } enum Enum6 { O(T), P(U), - Q(isize) + Q(i64) } #[allow(variant_size_differences)] enum Enum7 { - R(isize, isize, isize, isize), - S(isize), + R(i64, i64, i64, i64), + S(i64), T } pub fn main() { } diff --git a/src/test/ui/enum-size-variance.stderr b/src/test/ui/enum-size-variance.stderr index 5745b9344b4a7..a21243a49907f 100644 --- a/src/test/ui/enum-size-variance.stderr +++ b/src/test/ui/enum-size-variance.stderr @@ -1,12 +1,12 @@ warning: enum variant is more than three times larger (32 bytes) than the next largest - --> $DIR/enum-size-variance.rs:32:5 + --> $DIR/enum-size-variance.rs:28:5 | -32 | L(isize, isize, isize, isize), //~ WARNING three times larger - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +28 | L(i64, i64, i64, i64), //~ WARNING three times larger + | ^^^^^^^^^^^^^^^^^^^^^ | note: lint level defined here - --> $DIR/enum-size-variance.rs:17:9 + --> $DIR/enum-size-variance.rs:13:9 | -17 | #![warn(variant_size_differences)] +13 | #![warn(variant_size_differences)] | ^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/issue-35675.rs b/src/test/ui/issue-35675.rs new file mode 100644 index 0000000000000..391e1f2db5c02 --- /dev/null +++ b/src/test/ui/issue-35675.rs @@ -0,0 +1,51 @@ +// Copyright 2017 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. + +// these two HELPs are actually in a new line between this line and the `enum Fruit` line +enum Fruit { //~ HELP possible candidate is found in another module, you can import it into scope + //~^ HELP possible candidate is found in another module, you can import it into scope + Apple(i64), + //~^ HELP there is an enum variant `Fruit::Apple`, did you mean to use `Fruit`? + //~| HELP there is an enum variant `Fruit::Apple`, did you mean to use `Fruit`? + Orange(i64), +} + +fn should_return_fruit() -> Apple { + //~^ ERROR cannot find type `Apple` in this scope + //~| NOTE not found in this scope + Apple(5) + //~^ ERROR cannot find function `Apple` in this scope + //~| NOTE not found in this scope +} + +fn should_return_fruit_too() -> Fruit::Apple { + //~^ ERROR expected type, found variant `Fruit::Apple` + //~| NOTE not a type + Apple(5) + //~^ ERROR cannot find function `Apple` in this scope + //~| NOTE not found in this scope +} + +fn bar() -> Variant3 { + //~^ ERROR cannot find type `Variant3` in this scope + //~| NOTE not found in this scope +} + +fn main() {} + +mod x { + enum Enum { + Variant1, + Variant2(), + Variant3(usize), + //~^ HELP there is an enum variant `x::Enum::Variant3`, did you mean to use `x::Enum`? + Variant4 {}, + } +} diff --git a/src/test/ui/issue-35675.stderr b/src/test/ui/issue-35675.stderr new file mode 100644 index 0000000000000..c2c10724646ef --- /dev/null +++ b/src/test/ui/issue-35675.stderr @@ -0,0 +1,51 @@ +error[E0412]: cannot find type `Apple` in this scope + --> $DIR/issue-35675.rs:20:29 + | +20 | fn should_return_fruit() -> Apple { + | ^^^^^ + | | + | not found in this scope + | help: you can try using the variant's enum: `Fruit` + +error[E0425]: cannot find function `Apple` in this scope + --> $DIR/issue-35675.rs:23:5 + | +23 | Apple(5) + | ^^^^^ not found in this scope + | +help: possible candidate is found in another module, you can import it into scope + | +12 | use Fruit::Apple; + | + +error[E0573]: expected type, found variant `Fruit::Apple` + --> $DIR/issue-35675.rs:28:33 + | +28 | fn should_return_fruit_too() -> Fruit::Apple { + | ^^^^^^^^^^^^ + | | + | not a type + | help: you can try using the variant's enum: `Fruit` + +error[E0425]: cannot find function `Apple` in this scope + --> $DIR/issue-35675.rs:31:5 + | +31 | Apple(5) + | ^^^^^ not found in this scope + | +help: possible candidate is found in another module, you can import it into scope + | +12 | use Fruit::Apple; + | + +error[E0412]: cannot find type `Variant3` in this scope + --> $DIR/issue-35675.rs:36:13 + | +36 | fn bar() -> Variant3 { + | ^^^^^^^^ + | | + | not found in this scope + | help: you can try using the variant's enum: `x::Enum` + +error: aborting due to 5 previous errors + diff --git a/src/test/ui/issue-40402-ref-hints/issue-40402-1.stderr b/src/test/ui/issue-40402-ref-hints/issue-40402-1.stderr index de110ac12b703..26f150811b7db 100644 --- a/src/test/ui/issue-40402-ref-hints/issue-40402-1.stderr +++ b/src/test/ui/issue-40402-ref-hints/issue-40402-1.stderr @@ -4,7 +4,7 @@ error[E0507]: cannot move out of indexed content 19 | let e = f.v[0]; | ^^^^^^ | | - | help: consider using a reference instead `&f.v[0]` + | help: consider using a reference instead: `&f.v[0]` | cannot move out of indexed content error: aborting due to previous error diff --git a/src/test/compile-fail/macro-name-typo.rs b/src/test/ui/macros/macro-name-typo.rs similarity index 87% rename from src/test/compile-fail/macro-name-typo.rs rename to src/test/ui/macros/macro-name-typo.rs index 4840205fee4c3..ec8d27f9138f7 100644 --- a/src/test/compile-fail/macro-name-typo.rs +++ b/src/test/ui/macros/macro-name-typo.rs @@ -10,6 +10,4 @@ fn main() { printlx!("oh noes!"); - //~^ ERROR cannot find macro - //~^^ HELP did you mean `println!`? } diff --git a/src/test/ui/macros/macro-name-typo.stderr b/src/test/ui/macros/macro-name-typo.stderr new file mode 100644 index 0000000000000..7c83250fe8ada --- /dev/null +++ b/src/test/ui/macros/macro-name-typo.stderr @@ -0,0 +1,8 @@ +error: cannot find macro `printlx!` in this scope + --> $DIR/macro-name-typo.rs:12:5 + | +12 | printlx!("oh noes!"); + | ^^^^^^^ help: you could try the macro: `println!` + +error: aborting due to previous error + diff --git a/src/test/compile-fail/macro_undefined.rs b/src/test/ui/macros/macro_undefined.rs similarity index 74% rename from src/test/compile-fail/macro_undefined.rs rename to src/test/ui/macros/macro_undefined.rs index 00c8d44f30602..db93ba5e2c41d 100644 --- a/src/test/compile-fail/macro_undefined.rs +++ b/src/test/ui/macros/macro_undefined.rs @@ -19,9 +19,5 @@ mod m { fn main() { k!(); - //~^ ERROR cannot find macro `k!` in this scope - //~^^ HELP did you mean `kl!`? kl!(); - //~^ ERROR cannot find macro `kl!` in this scope - //~^^ HELP have you added the `#[macro_use]` on the module/import? } diff --git a/src/test/ui/macros/macro_undefined.stderr b/src/test/ui/macros/macro_undefined.stderr new file mode 100644 index 0000000000000..5c33ae99734e8 --- /dev/null +++ b/src/test/ui/macros/macro_undefined.stderr @@ -0,0 +1,16 @@ +error: cannot find macro `kl!` in this scope + --> $DIR/macro_undefined.rs:22:5 + | +22 | kl!(); + | ^^ + | + = help: have you added the `#[macro_use]` on the module/import? + +error: cannot find macro `k!` in this scope + --> $DIR/macro_undefined.rs:21:5 + | +21 | k!(); + | ^ help: you could try the macro: `kl!` + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/mismatched_types/issue-19109.stderr b/src/test/ui/mismatched_types/issue-19109.stderr index 2b4b8242af6fb..2d8d557d9f35f 100644 --- a/src/test/ui/mismatched_types/issue-19109.stderr +++ b/src/test/ui/mismatched_types/issue-19109.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/issue-19109.rs:14:5 | 13 | fn function(t: &mut Trait) { - | - help: possibly return type missing here? `-> *mut Trait ` + | - help: possibly return type missing here?: `-> *mut Trait ` 14 | t as *mut Trait | ^^^^^^^^^^^^^^^ expected (), found *-ptr | diff --git a/src/test/compile-fail/on-unimplemented/bad-annotation.rs b/src/test/ui/on-unimplemented/bad-annotation.rs similarity index 100% rename from src/test/compile-fail/on-unimplemented/bad-annotation.rs rename to src/test/ui/on-unimplemented/bad-annotation.rs diff --git a/src/test/ui/on-unimplemented/bad-annotation.stderr b/src/test/ui/on-unimplemented/bad-annotation.stderr new file mode 100644 index 0000000000000..8599477e8ed7e --- /dev/null +++ b/src/test/ui/on-unimplemented/bad-annotation.stderr @@ -0,0 +1,22 @@ +error[E0232]: this attribute must have a value + --> $DIR/bad-annotation.rs:26:1 + | +26 | #[rustc_on_unimplemented] //~ ERROR this attribute must have a value + | ^^^^^^^^^^^^^^^^^^^^^^^^^ attribute requires a value + | + = note: eg `#[rustc_on_unimplemented = "foo"]` + +error[E0230]: there is no type parameter C on trait BadAnnotation2 + --> $DIR/bad-annotation.rs:30:1 + | +30 | #[rustc_on_unimplemented = "Unimplemented trait error on `{Self}` with params `<{A},{B},{C}>`"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0231]: only named substitution parameters are allowed + --> $DIR/bad-annotation.rs:35:1 + | +35 | #[rustc_on_unimplemented = "Unimplemented trait error on `{Self}` with params `<{A},{B},{}>`"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/src/test/compile-fail/on-unimplemented/multiple-impls.rs b/src/test/ui/on-unimplemented/multiple-impls.rs similarity index 100% rename from src/test/compile-fail/on-unimplemented/multiple-impls.rs rename to src/test/ui/on-unimplemented/multiple-impls.rs diff --git a/src/test/ui/on-unimplemented/multiple-impls.stderr b/src/test/ui/on-unimplemented/multiple-impls.stderr new file mode 100644 index 0000000000000..a1fa8b720a829 --- /dev/null +++ b/src/test/ui/on-unimplemented/multiple-impls.stderr @@ -0,0 +1,53 @@ +error[E0277]: the trait bound `[i32]: Index` is not satisfied + --> $DIR/multiple-impls.rs:43:5 + | +43 | Index::index(&[] as &[i32], 2u32); + | ^^^^^^^^^^^^ trait message + | + = help: the trait `Index` is not implemented for `[i32]` + = note: required by `Index::index` + +error[E0277]: the trait bound `[i32]: Index` is not satisfied + --> $DIR/multiple-impls.rs:43:5 + | +43 | Index::index(&[] as &[i32], 2u32); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ trait message + | + = help: the trait `Index` is not implemented for `[i32]` + +error[E0277]: the trait bound `[i32]: Index>` is not satisfied + --> $DIR/multiple-impls.rs:49:5 + | +49 | Index::index(&[] as &[i32], Foo(2u32)); + | ^^^^^^^^^^^^ on impl for Foo + | + = help: the trait `Index>` is not implemented for `[i32]` + = note: required by `Index::index` + +error[E0277]: the trait bound `[i32]: Index>` is not satisfied + --> $DIR/multiple-impls.rs:49:5 + | +49 | Index::index(&[] as &[i32], Foo(2u32)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ on impl for Foo + | + = help: the trait `Index>` is not implemented for `[i32]` + +error[E0277]: the trait bound `[i32]: Index>` is not satisfied + --> $DIR/multiple-impls.rs:55:5 + | +55 | Index::index(&[] as &[i32], Bar(2u32)); + | ^^^^^^^^^^^^ on impl for Bar + | + = help: the trait `Index>` is not implemented for `[i32]` + = note: required by `Index::index` + +error[E0277]: the trait bound `[i32]: Index>` is not satisfied + --> $DIR/multiple-impls.rs:55:5 + | +55 | Index::index(&[] as &[i32], Bar(2u32)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ on impl for Bar + | + = help: the trait `Index>` is not implemented for `[i32]` + +error: aborting due to 6 previous errors + diff --git a/src/test/compile-fail/on-unimplemented/on-impl.rs b/src/test/ui/on-unimplemented/on-impl.rs similarity index 100% rename from src/test/compile-fail/on-unimplemented/on-impl.rs rename to src/test/ui/on-unimplemented/on-impl.rs diff --git a/src/test/ui/on-unimplemented/on-impl.stderr b/src/test/ui/on-unimplemented/on-impl.stderr new file mode 100644 index 0000000000000..c8c06bf44fd6f --- /dev/null +++ b/src/test/ui/on-unimplemented/on-impl.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `[i32]: Index` is not satisfied + --> $DIR/on-impl.rs:32:5 + | +32 | Index::::index(&[1, 2, 3] as &[i32], 2u32); + | ^^^^^^^^^^^^^^^^^^^ a usize is required to index into a slice + | + = help: the trait `Index` is not implemented for `[i32]` + = note: required by `Index::index` + +error[E0277]: the trait bound `[i32]: Index` is not satisfied + --> $DIR/on-impl.rs:32:5 + | +32 | Index::::index(&[1, 2, 3] as &[i32], 2u32); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ a usize is required to index into a slice + | + = help: the trait `Index` is not implemented for `[i32]` + +error: aborting due to 2 previous errors + diff --git a/src/test/compile-fail/on-unimplemented/on-trait.rs b/src/test/ui/on-unimplemented/on-trait.rs similarity index 90% rename from src/test/compile-fail/on-unimplemented/on-trait.rs rename to src/test/ui/on-unimplemented/on-trait.rs index a8daef356a5cc..ed7ec9b143689 100644 --- a/src/test/compile-fail/on-unimplemented/on-trait.rs +++ b/src/test/ui/on-unimplemented/on-trait.rs @@ -11,9 +11,12 @@ #![feature(on_unimplemented)] -#[rustc_on_unimplemented = "test error `{Self}` with `{Bar}` `{Baz}` `{Quux}`"] -trait Foo -{} +pub mod Bar { + #[rustc_on_unimplemented = "test error `{Self}` with `{Bar}` `{Baz}` `{Quux}` in `{Foo}`"] + pub trait Foo {} +} + +use Bar::Foo; fn foobar>() -> T { panic!() diff --git a/src/test/ui/on-unimplemented/on-trait.stderr b/src/test/ui/on-unimplemented/on-trait.stderr new file mode 100644 index 0000000000000..84986c1ecfdd3 --- /dev/null +++ b/src/test/ui/on-unimplemented/on-trait.stderr @@ -0,0 +1,20 @@ +error[E0277]: the trait bound `std::option::Option>: MyFromIterator<&u8>` is not satisfied + --> $DIR/on-trait.rs:37:30 + | +37 | let y: Option> = collect(x.iter()); // this should give approximately the same error for x.iter().collect() + | ^^^^^^^ a collection of type `std::option::Option>` cannot be built from an iterator over elements of type `&u8` + | + = help: the trait `MyFromIterator<&u8>` is not implemented for `std::option::Option>` + = note: required by `collect` + +error[E0277]: the trait bound `std::string::String: Bar::Foo` is not satisfied + --> $DIR/on-trait.rs:42:21 + | +42 | let x: String = foobar(); //~ ERROR + | ^^^^^^ test error `std::string::String` with `u8` `_` `u32` in `Bar::Foo` + | + = help: the trait `Bar::Foo` is not implemented for `std::string::String` + = note: required by `foobar` + +error: aborting due to 2 previous errors + diff --git a/src/test/compile-fail/on-unimplemented/slice-index.rs b/src/test/ui/on-unimplemented/slice-index.rs similarity index 100% rename from src/test/compile-fail/on-unimplemented/slice-index.rs rename to src/test/ui/on-unimplemented/slice-index.rs diff --git a/src/test/ui/on-unimplemented/slice-index.stderr b/src/test/ui/on-unimplemented/slice-index.stderr new file mode 100644 index 0000000000000..68789f77f750c --- /dev/null +++ b/src/test/ui/on-unimplemented/slice-index.stderr @@ -0,0 +1,20 @@ +error[E0277]: the trait bound `i32: std::slice::SliceIndex<[i32]>` is not satisfied + --> $DIR/slice-index.rs:21:5 + | +21 | x[1i32]; //~ ERROR E0277 + | ^^^^^^^ slice indices are of type `usize` or ranges of `usize` + | + = help: the trait `std::slice::SliceIndex<[i32]>` is not implemented for `i32` + = note: required because of the requirements on the impl of `std::ops::Index` for `[i32]` + +error[E0277]: the trait bound `std::ops::RangeTo: std::slice::SliceIndex<[i32]>` is not satisfied + --> $DIR/slice-index.rs:24:5 + | +24 | x[..1i32]; //~ ERROR E0277 + | ^^^^^^^^^ slice indices are of type `usize` or ranges of `usize` + | + = help: the trait `std::slice::SliceIndex<[i32]>` is not implemented for `std::ops::RangeTo` + = note: required because of the requirements on the impl of `std::ops::Index>` for `[i32]` + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/resolve-error.stderr b/src/test/ui/resolve-error.stderr new file mode 100644 index 0000000000000..27f93939246c0 --- /dev/null +++ b/src/test/ui/resolve-error.stderr @@ -0,0 +1,62 @@ +error: cannot find derive macro `FooWithLongNan` in this scope + --> $DIR/resolve-error.rs:37:10 + | +37 | #[derive(FooWithLongNan)] + | ^^^^^^^^^^^^^^ help: try: `FooWithLongName` + +error: cannot find attribute macro `attr_proc_macra` in this scope + --> $DIR/resolve-error.rs:40:3 + | +40 | #[attr_proc_macra] + | ^^^^^^^^^^^^^^^ help: try: `attr_proc_macro` + +error: cannot find attribute macro `FooWithLongNan` in this scope + --> $DIR/resolve-error.rs:43:3 + | +43 | #[FooWithLongNan] + | ^^^^^^^^^^^^^^ + +error: cannot find derive macro `Dlone` in this scope + --> $DIR/resolve-error.rs:46:10 + | +46 | #[derive(Dlone)] + | ^^^^^ help: try: `Clone` + +error: cannot find derive macro `Dlona` in this scope + --> $DIR/resolve-error.rs:49:10 + | +49 | #[derive(Dlona)] + | ^^^^^ help: try: `Clona` + +error: cannot find derive macro `attr_proc_macra` in this scope + --> $DIR/resolve-error.rs:52:10 + | +52 | #[derive(attr_proc_macra)] + | ^^^^^^^^^^^^^^^ + +error: cannot find macro `FooWithLongNama!` in this scope + --> $DIR/resolve-error.rs:56:5 + | +56 | FooWithLongNama!(); + | ^^^^^^^^^^^^^^^ help: you could try the macro: `FooWithLongNam!` + +error: cannot find macro `attr_proc_macra!` in this scope + --> $DIR/resolve-error.rs:58:5 + | +58 | attr_proc_macra!(); + | ^^^^^^^^^^^^^^^ help: you could try the macro: `attr_proc_mac!` + +error: cannot find macro `Dlona!` in this scope + --> $DIR/resolve-error.rs:60:5 + | +60 | Dlona!(); + | ^^^^^ + +error: cannot find macro `bang_proc_macrp!` in this scope + --> $DIR/resolve-error.rs:62:5 + | +62 | bang_proc_macrp!(); + | ^^^^^^^^^^^^^^^ help: you could try the macro: `bang_proc_macro!` + +error: aborting due to previous error(s) + diff --git a/src/test/ui/resolve/issue-14254.stderr b/src/test/ui/resolve/issue-14254.stderr index 11268e593c413..7aa0c2707b56f 100644 --- a/src/test/ui/resolve/issue-14254.stderr +++ b/src/test/ui/resolve/issue-14254.stderr @@ -2,7 +2,7 @@ error[E0425]: cannot find function `baz` in this scope --> $DIR/issue-14254.rs:29:9 | 29 | baz(); - | ^^^ did you mean `self.baz(...)`? + | ^^^ help: try: `self.baz` error[E0425]: cannot find value `a` in this scope --> $DIR/issue-14254.rs:32:9 @@ -14,19 +14,19 @@ error[E0425]: cannot find function `baz` in this scope --> $DIR/issue-14254.rs:40:9 | 40 | baz(); - | ^^^ did you mean `self.baz(...)`? + | ^^^ help: try: `self.baz` error[E0425]: cannot find value `x` in this scope --> $DIR/issue-14254.rs:43:9 | 43 | x; - | ^ did you mean `self.x`? + | ^ help: try: `self.x` error[E0425]: cannot find value `y` in this scope --> $DIR/issue-14254.rs:46:9 | 46 | y; - | ^ did you mean `self.y`? + | ^ help: try: `self.y` error[E0425]: cannot find value `a` in this scope --> $DIR/issue-14254.rs:49:9 @@ -38,7 +38,7 @@ error[E0425]: cannot find value `bah` in this scope --> $DIR/issue-14254.rs:52:9 | 52 | bah; - | ^^^ did you mean `Self::bah`? + | ^^^ help: try: `Self::bah` error[E0425]: cannot find value `b` in this scope --> $DIR/issue-14254.rs:55:9 @@ -50,19 +50,19 @@ error[E0425]: cannot find function `baz` in this scope --> $DIR/issue-14254.rs:63:9 | 63 | baz(); - | ^^^ did you mean `self.baz(...)`? + | ^^^ help: try: `self.baz` error[E0425]: cannot find value `x` in this scope --> $DIR/issue-14254.rs:66:9 | 66 | x; - | ^ did you mean `self.x`? + | ^ help: try: `self.x` error[E0425]: cannot find value `y` in this scope --> $DIR/issue-14254.rs:69:9 | 69 | y; - | ^ did you mean `self.y`? + | ^ help: try: `self.y` error[E0425]: cannot find value `a` in this scope --> $DIR/issue-14254.rs:72:9 @@ -74,7 +74,7 @@ error[E0425]: cannot find value `bah` in this scope --> $DIR/issue-14254.rs:75:9 | 75 | bah; - | ^^^ did you mean `Self::bah`? + | ^^^ help: try: `Self::bah` error[E0425]: cannot find value `b` in this scope --> $DIR/issue-14254.rs:78:9 @@ -86,61 +86,61 @@ error[E0425]: cannot find function `baz` in this scope --> $DIR/issue-14254.rs:86:9 | 86 | baz(); - | ^^^ did you mean `self.baz(...)`? + | ^^^ help: try: `self.baz` error[E0425]: cannot find value `bah` in this scope --> $DIR/issue-14254.rs:89:9 | 89 | bah; - | ^^^ did you mean `Self::bah`? + | ^^^ help: try: `Self::bah` error[E0425]: cannot find function `baz` in this scope --> $DIR/issue-14254.rs:97:9 | 97 | baz(); - | ^^^ did you mean `self.baz(...)`? + | ^^^ help: try: `self.baz` error[E0425]: cannot find value `bah` in this scope --> $DIR/issue-14254.rs:100:9 | 100 | bah; - | ^^^ did you mean `Self::bah`? + | ^^^ help: try: `Self::bah` error[E0425]: cannot find function `baz` in this scope --> $DIR/issue-14254.rs:108:9 | 108 | baz(); - | ^^^ did you mean `self.baz(...)`? + | ^^^ help: try: `self.baz` error[E0425]: cannot find value `bah` in this scope --> $DIR/issue-14254.rs:111:9 | 111 | bah; - | ^^^ did you mean `Self::bah`? + | ^^^ help: try: `Self::bah` error[E0425]: cannot find function `baz` in this scope --> $DIR/issue-14254.rs:119:9 | 119 | baz(); - | ^^^ did you mean `self.baz(...)`? + | ^^^ help: try: `self.baz` error[E0425]: cannot find value `bah` in this scope --> $DIR/issue-14254.rs:122:9 | 122 | bah; - | ^^^ did you mean `Self::bah`? + | ^^^ help: try: `Self::bah` error[E0425]: cannot find function `baz` in this scope --> $DIR/issue-14254.rs:130:9 | 130 | baz(); - | ^^^ did you mean `self.baz(...)`? + | ^^^ help: try: `self.baz` error[E0425]: cannot find value `bah` in this scope --> $DIR/issue-14254.rs:133:9 | 133 | bah; - | ^^^ did you mean `Self::bah`? + | ^^^ help: try: `Self::bah` error[E0601]: main function not found diff --git a/src/test/ui/resolve/issue-2356.stderr b/src/test/ui/resolve/issue-2356.stderr index 039887d8da65f..9c683f4418972 100644 --- a/src/test/ui/resolve/issue-2356.stderr +++ b/src/test/ui/resolve/issue-2356.stderr @@ -8,13 +8,13 @@ error[E0425]: cannot find function `clone` in this scope --> $DIR/issue-2356.rs:35:5 | 35 | clone(); - | ^^^^^ did you mean `self.clone(...)`? + | ^^^^^ help: try: `self.clone` error[E0425]: cannot find function `default` in this scope --> $DIR/issue-2356.rs:43:5 | 43 | default(); - | ^^^^^^^ did you mean `Self::default`? + | ^^^^^^^ help: try: `Self::default` error[E0425]: cannot find value `whiskers` in this scope --> $DIR/issue-2356.rs:52:5 @@ -22,14 +22,14 @@ error[E0425]: cannot find value `whiskers` in this scope 52 | whiskers -= other; | ^^^^^^^^ | | - | did you mean `self.whiskers`? + | help: try: `self.whiskers` | `self` value is only available in methods with `self` parameter error[E0425]: cannot find function `shave` in this scope --> $DIR/issue-2356.rs:57:5 | 57 | shave(4); - | ^^^^^ did you mean `Self::shave`? + | ^^^^^ help: try: `Self::shave` error[E0425]: cannot find function `purr` in this scope --> $DIR/issue-2356.rs:60:5 @@ -83,7 +83,7 @@ error[E0425]: cannot find value `whiskers` in this scope --> $DIR/issue-2356.rs:104:5 | 104 | whiskers = 0; - | ^^^^^^^^ did you mean `self.whiskers`? + | ^^^^^^^^ help: try: `self.whiskers` error[E0425]: cannot find value `whiskers` in this scope --> $DIR/issue-2356.rs:110:5 @@ -91,7 +91,7 @@ error[E0425]: cannot find value `whiskers` in this scope 110 | whiskers = 4; | ^^^^^^^^ | | - | did you mean `self.whiskers`? + | help: try: `self.whiskers` | `self` value is only available in methods with `self` parameter error[E0425]: cannot find function `purr_louder` in this scope diff --git a/src/test/ui/resolve/resolve-assoc-suggestions.stderr b/src/test/ui/resolve/resolve-assoc-suggestions.stderr index 7975c168de7d4..77aa545e2ad6b 100644 --- a/src/test/ui/resolve/resolve-assoc-suggestions.stderr +++ b/src/test/ui/resolve/resolve-assoc-suggestions.stderr @@ -14,13 +14,13 @@ error[E0425]: cannot find value `field` in this scope --> $DIR/resolve-assoc-suggestions.rs:32:9 | 32 | field; - | ^^^^^ did you mean `self.field`? + | ^^^^^ help: try: `self.field` error[E0412]: cannot find type `Type` in this scope --> $DIR/resolve-assoc-suggestions.rs:36:16 | 36 | let _: Type; - | ^^^^ did you mean `Self::Type`? + | ^^^^ help: try: `Self::Type` error[E0531]: cannot find tuple struct/variant `Type` in this scope --> $DIR/resolve-assoc-suggestions.rs:39:13 @@ -50,7 +50,7 @@ error[E0425]: cannot find value `method` in this scope --> $DIR/resolve-assoc-suggestions.rs:52:9 | 52 | method; - | ^^^^^^ did you mean `self.method(...)`? + | ^^^^^^ help: try: `self.method` error: aborting due to 9 previous errors diff --git a/src/test/ui/resolve/resolve-speculative-adjustment.stderr b/src/test/ui/resolve/resolve-speculative-adjustment.stderr index e7df8140bc577..3e1b075679a50 100644 --- a/src/test/ui/resolve/resolve-speculative-adjustment.stderr +++ b/src/test/ui/resolve/resolve-speculative-adjustment.stderr @@ -14,13 +14,13 @@ error[E0425]: cannot find value `field` in this scope --> $DIR/resolve-speculative-adjustment.rs:35:9 | 35 | field; - | ^^^^^ did you mean `self.field`? + | ^^^^^ help: try: `self.field` error[E0425]: cannot find function `method` in this scope --> $DIR/resolve-speculative-adjustment.rs:38:9 | 38 | method(); - | ^^^^^^ did you mean `self.method(...)`? + | ^^^^^^ help: try: `self.method` error: aborting due to 4 previous errors diff --git a/src/test/ui/resolve/token-error-correct-3.stderr b/src/test/ui/resolve/token-error-correct-3.stderr index bd3bdf35da609..2e8cc40dc5175 100644 --- a/src/test/ui/resolve/token-error-correct-3.stderr +++ b/src/test/ui/resolve/token-error-correct-3.stderr @@ -35,7 +35,7 @@ error[E0308]: mismatched types --> $DIR/token-error-correct-3.rs:25:13 | 25 | fs::create_dir_all(path.as_ref()).map(|()| true) //~ ERROR: mismatched types - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- help: did you mean to add a semicolon here? `;` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- help: did you mean to add a semicolon here?: `;` | | | expected (), found enum `std::result::Result` | diff --git a/src/test/ui/resolve/unresolved_static_type_field.stderr b/src/test/ui/resolve/unresolved_static_type_field.stderr index 5fbaf66e014af..e598851e3628e 100644 --- a/src/test/ui/resolve/unresolved_static_type_field.stderr +++ b/src/test/ui/resolve/unresolved_static_type_field.stderr @@ -4,7 +4,7 @@ error[E0425]: cannot find value `cx` in this scope 19 | f(cx); | ^^ | | - | did you mean `self.cx`? + | help: try: `self.cx` | `self` value is only available in methods with `self` parameter error: aborting due to previous error diff --git a/src/test/ui/span/issue-39018.stderr b/src/test/ui/span/issue-39018.stderr index a0445eaee9162..d87fc122d8ee2 100644 --- a/src/test/ui/span/issue-39018.stderr +++ b/src/test/ui/span/issue-39018.stderr @@ -4,7 +4,7 @@ error[E0369]: binary operation `+` cannot be applied to type `&'static str` 12 | let x = "Hello " + "World!"; | ^^^^^^^^^^^^^^^^^^^ `+` can't be used to concatenate two `&str` strings | -help: `to_owned()` can be used to create an owned `String` from a string reference. String concatenation appends the string on the right to the string on the left and may require reallocation. This requires ownership of the string on the left. +help: `to_owned()` can be used to create an owned `String` from a string reference. String concatenation appends the string on the right to the string on the left and may require reallocation. This requires ownership of the string on the left | 12 | let x = "Hello ".to_owned() + "World!"; | ^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/span/suggestion-non-ascii.stderr b/src/test/ui/span/suggestion-non-ascii.stderr index c2ab7542d8a98..c67a8fe32b9dd 100644 --- a/src/test/ui/span/suggestion-non-ascii.stderr +++ b/src/test/ui/span/suggestion-non-ascii.stderr @@ -2,7 +2,7 @@ error[E0608]: cannot index into a value of type `({integer},)` --> $DIR/suggestion-non-ascii.rs:14:21 | 14 | println!("☃{}", tup[0]); - | ^^^^^^ help: to access tuple elements, use `tup.0` + | ^^^^^^ help: to access tuple elements, use: `tup.0` error: aborting due to previous error diff --git a/src/test/ui/suggestions/tuple-float-index.stderr b/src/test/ui/suggestions/tuple-float-index.stderr index 8a121b1453662..4b1be26c86b0e 100644 --- a/src/test/ui/suggestions/tuple-float-index.stderr +++ b/src/test/ui/suggestions/tuple-float-index.stderr @@ -5,7 +5,7 @@ error: unexpected token: `1.1` | ------------^^^ | | | | | unexpected token - | help: try parenthesizing the first index `((1, (2, 3)).1).1` + | help: try parenthesizing the first index: `((1, (2, 3)).1).1` error: aborting due to previous error diff --git a/src/test/ui/transmute/main.rs b/src/test/ui/transmute/main.rs index d5968a388dc1d..ab448de656e67 100644 --- a/src/test/ui/transmute/main.rs +++ b/src/test/ui/transmute/main.rs @@ -8,10 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-x86 -// ignore-arm -// ignore-emscripten -// ignore 32-bit platforms (test output is different) +// normalize-stderr-32bit: "&str (64 bits)" -> "&str ($STR bits)" +// normalize-stderr-64bit: "&str (128 bits)" -> "&str ($STR bits)" + + #![feature(untagged_unions)] use std::mem::transmute; diff --git a/src/test/ui/transmute/main.stderr b/src/test/ui/transmute/main.stderr index a7fc0808e1845..b7e34d3e0bc46 100644 --- a/src/test/ui/transmute/main.stderr +++ b/src/test/ui/transmute/main.stderr @@ -22,7 +22,7 @@ error[E0512]: transmute called with types of different sizes 34 | let x: u8 = transmute("test"); //~ ERROR transmute called with types of different sizes | ^^^^^^^^^ | - = note: source type: &str (128 bits) + = note: source type: &str ($STR bits) = note: target type: u8 (8 bits) error[E0512]: transmute called with types of different sizes diff --git a/src/test/ui/transmute/transmute-from-fn-item-types-error.rs b/src/test/ui/transmute/transmute-from-fn-item-types-error.rs index 98d2e1e3628f2..d60c97f1d59a8 100644 --- a/src/test/ui/transmute/transmute-from-fn-item-types-error.rs +++ b/src/test/ui/transmute/transmute-from-fn-item-types-error.rs @@ -8,14 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-x86 -// ignore-arm -// ignore-emscripten -// ignore 32-bit platforms (test output is different) - use std::mem; -unsafe fn foo() -> (i32, *const (), Option) { +unsafe fn foo() -> (i8, *const (), Option) { let i = mem::transmute(bar); //~^ ERROR is zero-sized and can't be transmuted //~^^ NOTE cast with `as` to a pointer instead @@ -46,7 +41,7 @@ unsafe fn bar() { //~^^ NOTE cast with `as` to a pointer instead // No error if a coercion would otherwise occur. - mem::transmute::(main); + mem::transmute::(main); } unsafe fn baz() { @@ -63,7 +58,7 @@ unsafe fn baz() { //~^^ NOTE cast with `as` to a pointer instead // No error if a coercion would otherwise occur. - mem::transmute::, u32>(Some(main)); + mem::transmute::, usize>(Some(main)); } fn main() { diff --git a/src/test/ui/transmute/transmute-from-fn-item-types-error.stderr b/src/test/ui/transmute/transmute-from-fn-item-types-error.stderr index 7f1929050bb8f..197daf1b79596 100644 --- a/src/test/ui/transmute/transmute-from-fn-item-types-error.stderr +++ b/src/test/ui/transmute/transmute-from-fn-item-types-error.stderr @@ -1,26 +1,26 @@ error[E0512]: transmute called with types of different sizes - --> $DIR/transmute-from-fn-item-types-error.rs:19:13 + --> $DIR/transmute-from-fn-item-types-error.rs:14:13 | -19 | let i = mem::transmute(bar); +14 | let i = mem::transmute(bar); | ^^^^^^^^^^^^^^ | = note: source type: unsafe fn() {bar} (0 bits) - = note: target type: i32 (32 bits) + = note: target type: i8 (8 bits) error[E0591]: can't transmute zero-sized type - --> $DIR/transmute-from-fn-item-types-error.rs:23:13 + --> $DIR/transmute-from-fn-item-types-error.rs:18:13 | -23 | let p = mem::transmute(foo); +18 | let p = mem::transmute(foo); | ^^^^^^^^^^^^^^ | - = note: source type: unsafe fn() -> (i32, *const (), std::option::Option) {foo} + = note: source type: unsafe fn() -> (i8, *const (), std::option::Option) {foo} = note: target type: *const () = help: cast with `as` to a pointer instead error[E0591]: can't transmute zero-sized type - --> $DIR/transmute-from-fn-item-types-error.rs:27:14 + --> $DIR/transmute-from-fn-item-types-error.rs:22:14 | -27 | let of = mem::transmute(main); +22 | let of = mem::transmute(main); | ^^^^^^^^^^^^^^ | = note: source type: fn() {main} @@ -28,57 +28,48 @@ error[E0591]: can't transmute zero-sized type = help: cast with `as` to a pointer instead error[E0512]: transmute called with types of different sizes - --> $DIR/transmute-from-fn-item-types-error.rs:36:5 + --> $DIR/transmute-from-fn-item-types-error.rs:31:5 | -36 | mem::transmute::<_, u8>(main); +31 | mem::transmute::<_, u8>(main); | ^^^^^^^^^^^^^^^^^^^^^^^ | = note: source type: fn() {main} (0 bits) = note: target type: u8 (8 bits) error[E0591]: can't transmute zero-sized type - --> $DIR/transmute-from-fn-item-types-error.rs:40:5 + --> $DIR/transmute-from-fn-item-types-error.rs:35:5 | -40 | mem::transmute::<_, *mut ()>(foo); +35 | mem::transmute::<_, *mut ()>(foo); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: source type: unsafe fn() -> (i32, *const (), std::option::Option) {foo} + = note: source type: unsafe fn() -> (i8, *const (), std::option::Option) {foo} = note: target type: *mut () = help: cast with `as` to a pointer instead error[E0591]: can't transmute zero-sized type - --> $DIR/transmute-from-fn-item-types-error.rs:44:5 + --> $DIR/transmute-from-fn-item-types-error.rs:39:5 | -44 | mem::transmute::<_, fn()>(bar); +39 | mem::transmute::<_, fn()>(bar); | ^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: source type: unsafe fn() {bar} = note: target type: fn() = help: cast with `as` to a pointer instead -error[E0512]: transmute called with types of different sizes - --> $DIR/transmute-from-fn-item-types-error.rs:49:5 - | -49 | mem::transmute::(main); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: source type: fn() (64 bits) - = note: target type: u32 (32 bits) - error[E0591]: can't transmute zero-sized type - --> $DIR/transmute-from-fn-item-types-error.rs:53:5 + --> $DIR/transmute-from-fn-item-types-error.rs:48:5 | -53 | mem::transmute::<_, *mut ()>(Some(foo)); +48 | mem::transmute::<_, *mut ()>(Some(foo)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: source type: unsafe fn() -> (i32, *const (), std::option::Option) {foo} + = note: source type: unsafe fn() -> (i8, *const (), std::option::Option) {foo} = note: target type: *mut () = help: cast with `as` to a pointer instead error[E0591]: can't transmute zero-sized type - --> $DIR/transmute-from-fn-item-types-error.rs:57:5 + --> $DIR/transmute-from-fn-item-types-error.rs:52:5 | -57 | mem::transmute::<_, fn()>(Some(bar)); +52 | mem::transmute::<_, fn()>(Some(bar)); | ^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: source type: unsafe fn() {bar} @@ -86,23 +77,14 @@ error[E0591]: can't transmute zero-sized type = help: cast with `as` to a pointer instead error[E0591]: can't transmute zero-sized type - --> $DIR/transmute-from-fn-item-types-error.rs:61:5 + --> $DIR/transmute-from-fn-item-types-error.rs:56:5 | -61 | mem::transmute::<_, Option>(Some(baz)); +56 | mem::transmute::<_, Option>(Some(baz)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: source type: unsafe fn() {baz} = note: target type: std::option::Option = help: cast with `as` to a pointer instead -error[E0512]: transmute called with types of different sizes - --> $DIR/transmute-from-fn-item-types-error.rs:66:5 - | -66 | mem::transmute::, u32>(Some(main)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: source type: std::option::Option (64 bits) - = note: target type: u32 (32 bits) - -error: aborting due to 11 previous errors +error: aborting due to 9 previous errors diff --git a/src/test/ui/transmute/transmute-type-parameters.rs b/src/test/ui/transmute/transmute-type-parameters.rs index fa83a10dc48e8..117fc2cc5df24 100644 --- a/src/test/ui/transmute/transmute-type-parameters.rs +++ b/src/test/ui/transmute/transmute-type-parameters.rs @@ -8,10 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-x86 -// ignore-arm -// ignore-emscripten -// ignore 32-bit platforms (test output is different) + + + + // Tests that `transmute` cannot be called on type parameters. diff --git a/src/test/ui/type-check/assignment-in-if.stderr b/src/test/ui/type-check/assignment-in-if.stderr index a077f37eae6ee..b740a1b776f75 100644 --- a/src/test/ui/type-check/assignment-in-if.stderr +++ b/src/test/ui/type-check/assignment-in-if.stderr @@ -4,7 +4,7 @@ error[E0308]: mismatched types 25 | if x = x { | ^^^^^ | | - | help: did you mean to compare equality? `x == x` + | help: did you mean to compare equality?: `x == x` | expected bool, found () | = note: expected type `bool` @@ -16,7 +16,7 @@ error[E0308]: mismatched types 31 | if (x = x) { | ^^^^^^^ | | - | help: did you mean to compare equality? `x == x` + | help: did you mean to compare equality?: `x == x` | expected bool, found () | = note: expected type `bool` @@ -28,7 +28,7 @@ error[E0308]: mismatched types 37 | if y = (Foo { foo: x }) { | ^^^^^^^^^^^^^^^^^^^^ | | - | help: did you mean to compare equality? `y == (Foo { foo: x })` + | help: did you mean to compare equality?: `y == (Foo { foo: x })` | expected bool, found () | = note: expected type `bool` @@ -40,7 +40,7 @@ error[E0308]: mismatched types 43 | if 3 = x { | ^^^^^ | | - | help: did you mean to compare equality? `3 == x` + | help: did you mean to compare equality?: `3 == x` | expected bool, found () | = note: expected type `bool` diff --git a/src/tools/cargo b/src/tools/cargo index eb6cf012a6cc2..f709c35a35687 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit eb6cf012a6cc23c9c89c4009564de9fccc38b9cb +Subproject commit f709c35a35687b2665eb290695825375be91410b diff --git a/src/tools/compiletest/Cargo.toml b/src/tools/compiletest/Cargo.toml index 543e6784a72ac..f8282cc5f8d9b 100644 --- a/src/tools/compiletest/Cargo.toml +++ b/src/tools/compiletest/Cargo.toml @@ -10,3 +10,4 @@ filetime = "0.1" getopts = "0.2" log = "0.3" rustc-serialize = "0.3" +libc = "0.2" diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index 5ac60d8f2c857..bb9bf57d55e2f 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -40,15 +40,8 @@ impl EarlyProps { None, &mut |ln| { props.ignore = - props.ignore || config.parse_name_directive(ln, "ignore-test") || - config.parse_name_directive(ln, &ignore_target(config)) || - config.parse_name_directive(ln, &ignore_architecture(config)) || - config.parse_name_directive(ln, &ignore_stage(config)) || - config.parse_name_directive(ln, &ignore_env(config)) || - (config.mode == common::Pretty && - config.parse_name_directive(ln, "ignore-pretty")) || - (config.target != config.host && - config.parse_name_directive(ln, "ignore-cross-compile")) || + props.ignore || + config.parse_cfg_name_directive(ln, "ignore") || ignore_gdb(config, ln) || ignore_lldb(config, ln) || ignore_llvm(config, ln); @@ -62,28 +55,11 @@ impl EarlyProps { return props; - fn ignore_target(config: &Config) -> String { - format!("ignore-{}", util::get_os(&config.target)) - } - fn ignore_architecture(config: &Config) -> String { - format!("ignore-{}", util::get_arch(&config.target)) - } - fn ignore_stage(config: &Config) -> String { - format!("ignore-{}", config.stage_id.split('-').next().unwrap()) - } - fn ignore_env(config: &Config) -> String { - format!("ignore-{}", - util::get_env(&config.target).unwrap_or("")) - } fn ignore_gdb(config: &Config, line: &str) -> bool { if config.mode != common::DebugInfoGdb { return false; } - if config.parse_name_directive(line, "ignore-gdb") { - return true; - } - if let Some(actual_version) = config.gdb_version { if line.starts_with("min-gdb-version") { let (start_ver, end_ver) = extract_gdb_version_range(line); @@ -144,10 +120,6 @@ impl EarlyProps { return false; } - if config.parse_name_directive(line, "ignore-lldb") { - return true; - } - if let Some(ref actual_version) = config.lldb_version { if line.starts_with("min-lldb-version") { let min_version = line.trim_right() @@ -239,6 +211,9 @@ pub struct TestProps { // The test must be compiled and run successfully. Only used in UI tests for // now. pub run_pass: bool, + // customized normalization rules + pub normalize_stdout: Vec<(String, String)>, + pub normalize_stderr: Vec<(String, String)>, } impl TestProps { @@ -265,6 +240,8 @@ impl TestProps { must_compile_successfully: false, check_test_line_numbers_match: false, run_pass: false, + normalize_stdout: vec![], + normalize_stderr: vec![], } } @@ -379,6 +356,13 @@ impl TestProps { if !self.run_pass { self.run_pass = config.parse_run_pass(ln); } + + if let Some(rule) = config.parse_custom_normalization(ln, "normalize-stdout") { + self.normalize_stdout.push(rule); + } + if let Some(rule) = config.parse_custom_normalization(ln, "normalize-stderr") { + self.normalize_stderr.push(rule); + } }); for key in &["RUST_TEST_NOCAPTURE", "RUST_TEST_THREADS"] { @@ -427,7 +411,6 @@ fn iter_header(testfile: &Path, cfg: Option<&str>, it: &mut FnMut(&str)) { } impl Config { - fn parse_error_pattern(&self, line: &str) -> Option { self.parse_name_value_directive(line, "error-pattern") } @@ -525,6 +508,46 @@ impl Config { } } + fn parse_custom_normalization(&self, mut line: &str, prefix: &str) -> Option<(String, String)> { + if self.parse_cfg_name_directive(line, prefix) { + let from = match parse_normalization_string(&mut line) { + Some(s) => s, + None => return None, + }; + let to = match parse_normalization_string(&mut line) { + Some(s) => s, + None => return None, + }; + Some((from, to)) + } else { + None + } + } + + /// Parses a name-value directive which contains config-specific information, e.g. `ignore-x86` + /// or `normalize-stderr-32bit`. Returns `true` if the line matches it. + fn parse_cfg_name_directive(&self, line: &str, prefix: &str) -> bool { + if line.starts_with(prefix) && line.as_bytes().get(prefix.len()) == Some(&b'-') { + let name = line[prefix.len()+1 ..].split(&[':', ' '][..]).next().unwrap(); + + name == "test" || + name == util::get_os(&self.target) || // target + name == util::get_arch(&self.target) || // architecture + name == util::get_pointer_width(&self.target) || // pointer width + name == self.stage_id.split('-').next().unwrap() || // stage + Some(name) == util::get_env(&self.target) || // env + match self.mode { + common::DebugInfoGdb => name == "gdb", + common::DebugInfoLldb => name == "lldb", + common::Pretty => name == "pretty", + _ => false, + } || + (self.target != self.host && name == "cross-compile") + } else { + false + } + } + fn parse_name_directive(&self, line: &str, directive: &str) -> bool { // Ensure the directive is a whole word. Do not match "ignore-x86" when // the line says "ignore-x86_64". @@ -572,3 +595,29 @@ fn expand_variables(mut value: String, config: &Config) -> String { value } + +/// Finds the next quoted string `"..."` in `line`, and extract the content from it. Move the `line` +/// variable after the end of the quoted string. +/// +/// # Examples +/// +/// ``` +/// let mut s = "normalize-stderr-32bit: \"something (32 bits)\" -> \"something ($WORD bits)\"."; +/// let first = parse_normalization_string(&mut s); +/// assert_eq!(first, Some("something (32 bits)".to_owned())); +/// assert_eq!(s, " -> \"something ($WORD bits)\"."); +/// ``` +fn parse_normalization_string(line: &mut &str) -> Option { + // FIXME support escapes in strings. + let begin = match line.find('"') { + Some(i) => i + 1, + None => return None, + }; + let end = match line[begin..].find('"') { + Some(i) => i + begin, + None => return None, + }; + let result = line[begin..end].to_owned(); + *line = &line[end+1..]; + Some(result) +} diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs index cc42544ef02b7..91f80a7afecdc 100644 --- a/src/tools/compiletest/src/main.rs +++ b/src/tools/compiletest/src/main.rs @@ -10,9 +10,7 @@ #![crate_name = "compiletest"] -#![feature(box_syntax)] #![feature(test)] -#![feature(libc)] #![deny(warnings)] diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 2254d6d23a83d..45a733d411ab9 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -2228,8 +2228,10 @@ actual:\n\ let expected_stdout_path = self.expected_output_path("stdout"); let expected_stdout = self.load_expected_output(&expected_stdout_path); - let normalized_stdout = self.normalize_output(&proc_res.stdout); - let normalized_stderr = self.normalize_output(&proc_res.stderr); + let normalized_stdout = + self.normalize_output(&proc_res.stdout, &self.props.normalize_stdout); + let normalized_stderr = + self.normalize_output(&proc_res.stderr, &self.props.normalize_stderr); let mut errors = 0; errors += self.compare_output("stdout", &normalized_stdout, &expected_stdout); @@ -2375,13 +2377,17 @@ actual:\n\ mir_dump_dir } - fn normalize_output(&self, output: &str) -> String { + fn normalize_output(&self, output: &str, custom_rules: &[(String, String)]) -> String { let parent_dir = self.testpaths.file.parent().unwrap(); let parent_dir_str = parent_dir.display().to_string(); - output.replace(&parent_dir_str, "$DIR") + let mut normalized = output.replace(&parent_dir_str, "$DIR") .replace("\\", "/") // normalize for paths on windows .replace("\r\n", "\n") // normalize for linebreaks on windows - .replace("\t", "\\t") // makes tabs visible + .replace("\t", "\\t"); // makes tabs visible + for rule in custom_rules { + normalized = normalized.replace(&rule.0, &rule.1); + } + normalized } fn expected_output_path(&self, kind: &str) -> PathBuf { diff --git a/src/tools/compiletest/src/util.rs b/src/tools/compiletest/src/util.rs index 4202356bd97a0..85fa38bbd3be7 100644 --- a/src/tools/compiletest/src/util.rs +++ b/src/tools/compiletest/src/util.rs @@ -72,6 +72,14 @@ pub fn get_env(triple: &str) -> Option<&str> { triple.split('-').nth(3) } +pub fn get_pointer_width(triple: &str) -> &'static str { + if triple.contains("64") || triple.starts_with("s390x") { + "64bit" + } else { + "32bit" + } +} + pub fn make_new_path(path: &str) -> String { assert!(cfg!(windows)); // Windows just uses PATH as the library search path, so we have to diff --git a/src/tools/rls b/src/tools/rls index 70b89fdd7e5e7..618f802f0dceb 160000 --- a/src/tools/rls +++ b/src/tools/rls @@ -1 +1 @@ -Subproject commit 70b89fdd7e5e77a3b88fc68982861d39d155be29 +Subproject commit 618f802f0dcebc9f23a527afd3cd228c1fa468f8 diff --git a/src/tools/rustbook/Cargo.toml b/src/tools/rustbook/Cargo.toml index 2d5d163d40305..e759e0bc13ac1 100644 --- a/src/tools/rustbook/Cargo.toml +++ b/src/tools/rustbook/Cargo.toml @@ -5,8 +5,8 @@ version = "0.1.0" license = "MIT/Apache-2.0" [dependencies] -clap = "2.19.3" +clap = "2.25.0" [dependencies.mdbook] -version = "0.0.21" +version = "0.0.22" default-features = false diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index ba02ee0c6d73b..8b7da2267cded 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -32,7 +32,6 @@ static EXCEPTIONS: &'static [&'static str] = &[ "openssl", // BSD+advertising clause, cargo, mdbook "pest", // MPL2, mdbook via handlebars "thread-id", // Apache-2.0, mdbook - "strings", // this is actually MIT/Apache-2.0 but it's not in the manifest yet ]; pub fn check(path: &Path, bad: &mut bool) {