deploy:
- provider: s3
+ edge:
+ branch: s3-eager-autoload
bucket: rust-lang-ci2
skip_cleanup: true
local_dir: deploy
# this is the same as the above deployment provider except that it uploads to
# a slightly different directory and has a different trigger
- provider: s3
+ edge:
+ branch: s3-eager-autoload
bucket: rust-lang-ci2
skip_cleanup: true
local_dir: deploy
# try branch. Travis does not appear to provide a way to use "or" in these
# conditions.
- provider: s3
+ edge:
+ branch: s3-eager-autoload
bucket: rust-lang-ci2
skip_cleanup: true
local_dir: deploy
condition: $DEPLOY = 1
- provider: s3
+ edge:
+ branch: s3-eager-autoload
bucket: rust-lang-ci2
skip_cleanup: true
local_dir: deploy
+Version 1.25.0 (2018-03-29)
+==========================
+
+Language
+--------
+- [Stabilised `#[repr(align(x))]`.][47006] [RFC 1358]
+- [You can now use nested groups of imports.][47948]
+ e.g. `use std::{fs::File, io::Read, path::{Path, PathBuf}};`
+- [You can now have `|` at the start of a match arm.][47947] e.g.
+```rust
+enum Foo { A, B, C }
+
+fn main() {
+ let x = Foo::A;
+ match x {
+ | Foo::A
+ | Foo::B => println!("AB"),
+ | Foo::C => println!("C"),
+ }
+}
+```
+
+Compiler
+--------
+- [Upgraded to LLVM 6.][47828]
+- [Added `-C lto=val` option.][47521]
+- [Added `i586-unknown-linux-musl` target][47282]
+
+Libraries
+---------
+- [Impl Send for `process::Command` on Unix.][47760]
+- [Impl PartialEq and Eq for `ParseCharError`.][47790]
+- [`UnsafeCell::into_inner` is now safe.][47204]
+- [Implement libstd for CloudABI.][47268]
+- [`Float::{from_bits, to_bits}` is now available in libcore.][46931]
+- [Implement `AsRef<Path>` for Component][46985]
+- [Implemented `Write` for `Cursor<&mut Vec<T>>`][46830]
+- [Moved `Duration` to libcore.][46666]
+
+Stabilized APIs
+---------------
+- [`Location::column`]
+- [`ptr::NonNull`]
+
+The following functions can now be used in a constant expression.
+eg. `static MINUTE: Duration = Duration::from_secs(60);`
+- [`Duration::new`][47300]
+- [`Duration::from_secs`][47300]
+- [`Duration::from_millis`][47300]
+- [`Duration::from_micros`][47300]
+- [`Duration::from_nanos`][47300]
+
+Cargo
+-----
+- [`cargo new` no longer removes `rust` or `rs` prefixs/suffixs.][cargo/5013]
+- [`cargo new` now defaults to creating a binary crate, instead of a
+ library crate.][cargo/5029]
+
+Misc
+----
+- [Rust by example is now shipped with new releases][46196]
+
+Compatibility Notes
+-------------------
+- [Deprecated `net::lookup_host`.][47510]
+- [`rustdoc` has switched to pulldown as the default markdown renderer.][47398]
+- The borrow checker was sometimes incorrectly permitting overlapping borrows
+ around indexing operations (see [#47349][47349]). This has been fixed (which also
+ enabled some correct code that used to cause errors (e.g. [#33903][33903] and [#46095][46095]).
+- [Removed deprecated unstable attribute `#[simd]`.][47251]
+
+[33903]: https://github.com/rust-lang/rust/pull/33903
+[47947]: https://github.com/rust-lang/rust/pull/47947
+[47948]: https://github.com/rust-lang/rust/pull/47948
+[47760]: https://github.com/rust-lang/rust/pull/47760
+[47790]: https://github.com/rust-lang/rust/pull/47790
+[47828]: https://github.com/rust-lang/rust/pull/47828
+[47398]: https://github.com/rust-lang/rust/pull/47398
+[47510]: https://github.com/rust-lang/rust/pull/47510
+[47521]: https://github.com/rust-lang/rust/pull/47521
+[47204]: https://github.com/rust-lang/rust/pull/47204
+[47251]: https://github.com/rust-lang/rust/pull/47251
+[47268]: https://github.com/rust-lang/rust/pull/47268
+[47282]: https://github.com/rust-lang/rust/pull/47282
+[47300]: https://github.com/rust-lang/rust/pull/47300
+[47349]: https://github.com/rust-lang/rust/pull/47349
+[46931]: https://github.com/rust-lang/rust/pull/46931
+[46985]: https://github.com/rust-lang/rust/pull/46985
+[47006]: https://github.com/rust-lang/rust/pull/47006
+[46830]: https://github.com/rust-lang/rust/pull/46830
+[46095]: https://github.com/rust-lang/rust/pull/46095
+[46666]: https://github.com/rust-lang/rust/pull/46666
+[46196]: https://github.com/rust-lang/rust/pull/46196
+[cargo/5013]: https://github.com/rust-lang/cargo/pull/5013
+[cargo/5029]: https://github.com/rust-lang/cargo/pull/5029
+[RFC 1358]: https://github.com/rust-lang/rfcs/pull/1358
+[`Location::column`]: https://doc.rust-lang.org/std/panic/struct.Location.html#method.column
+[`ptr::NonNull`]: https://doc.rust-lang.org/std/ptr/struct.NonNull.html
+
+
Version 1.24.0 (2018-02-15)
==========================
# Indicate whether submodules are managed and updated automatically.
#submodules = true
+# Update submodules only when the checked out commit in the submodules differs
+# from what is committed in the main rustc repo.
+#fast-submodules = true
+
# The path to (or name of) the GDB executable to use. This is only used for
# executing the debuginfo test suite.
#gdb = "gdb"
# compiler.
#codegen-units = 1
-# Whether to enable ThinLTO (and increase the codegen units to either a default
-# or the configured value). On by default. If we want the fastest possible
-# compiler, we should disable this.
-#thinlto = true
-
# Whether or not debug assertions are enabled for the compiler and standard
# library. Also enables compilation of debug! and trace! logging macros.
#debug-assertions = false
[[package]]
name = "ansi_term"
-version = "0.10.2"
+version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
+]
[[package]]
name = "ar"
dependencies = [
"atty 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"bufstream 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)",
"core-foundation 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"crates-io 0.16.0",
"crossbeam 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"crypto-hash 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"curl 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "docopt 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)",
"env_logger 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
"failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"filetime 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
"libgit2-sys 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"miow 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num-traits 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"same-file 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"scoped-tls 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
]
-[[package]]
-name = "cargo_metadata"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "semver 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
[[package]]
name = "cargo_metadata"
version = "0.5.3"
[[package]]
name = "clap"
-version = "2.29.0"
+version = "2.31.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
"atty 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"textwrap 0.9.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)",
[[package]]
name = "clippy"
-version = "0.0.186"
+version = "0.0.188"
dependencies = [
- "cargo_metadata 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cargo_metadata 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
"clippy-mini-macro-test 0.2.0",
- "clippy_lints 0.0.186",
- "compiletest_rs 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "duct 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "clippy_lints 0.0.188",
+ "compiletest_rs 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "derive-new 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "clippy_lints"
-version = "0.0.186"
-dependencies = [
- "if_chain 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "itertools 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "pulldown-cmark 0.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
- "quine-mc_cluskey 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "regex-syntax 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)",
- "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "unicode-normalization 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "clippy_lints"
-version = "0.0.187"
-source = "registry+https://github.com/rust-lang/crates.io-index"
+version = "0.0.188"
dependencies = [
"if_chain 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "itertools 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "itertools 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "pulldown-cmark 0.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pulldown-cmark 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"quine-mc_cluskey 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "regex-syntax 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex-syntax 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)",
"toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
[[package]]
name = "compiletest_rs"
-version = "0.3.6"
+version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
"filetime 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
"getopts 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
- "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "miow 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
"tempdir 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
"core 0.0.0",
]
-[[package]]
-name = "docopt"
-version = "0.8.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "regex 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)",
- "strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
[[package]]
name = "dtoa"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-[[package]]
-name = "duct"
-version = "0.8.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "error-chain 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "lazycell 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "os_pipe 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "shared_child 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
[[package]]
name = "either"
version = "1.4.0"
"regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)",
]
-[[package]]
-name = "env_logger"
-version = "0.4.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
- "regex 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
[[package]]
name = "env_logger"
version = "0.5.5"
"termcolor 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
-[[package]]
-name = "error-chain"
-version = "0.8.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "backtrace 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
[[package]]
name = "error-chain"
version = "0.11.0"
name = "installer"
version = "0.0.0"
dependencies = [
- "clap 2.29.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)",
"error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
"flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-[[package]]
-name = "itertools"
-version = "0.6.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "either 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
[[package]]
name = "itertools"
version = "0.7.6"
[[package]]
name = "languageserver-types"
-version = "0.30.0"
+version = "0.31.0"
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)",
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-[[package]]
-name = "lazycell"
-version = "0.5.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
[[package]]
name = "lazycell"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"chrono 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "clap 2.29.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)",
"env_logger 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
"error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
"handlebars 0.29.1 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
]
-[[package]]
-name = "miow"
-version = "0.2.1"
-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)",
- "net2 0.2.32 (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)",
-]
-
[[package]]
name = "miow"
version = "0.3.1"
dependencies = [
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"cargo_metadata 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "compiletest_rs 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "compiletest_rs 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
name = "multiple_bins"
version = "0.1.0"
-[[package]]
-name = "net2"
-version = "0.2.32"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
[[package]]
name = "nibble_vec"
version = "0.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-[[package]]
-name = "nix"
-version = "0.8.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
- "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
[[package]]
name = "nodrop"
version = "0.1.12"
"vcpkg 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
-[[package]]
-name = "os_pipe"
-version = "0.5.1"
-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)",
- "nix 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
[[package]]
name = "owning_ref"
version = "0.3.3"
"core 0.0.0",
]
-[[package]]
-name = "pulldown-cmark"
-version = "0.0.15"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "getopts 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
[[package]]
name = "pulldown-cmark"
version = "0.1.2"
version = "2.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "clap 2.29.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "clap 2.31.2 (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.11 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-[[package]]
-name = "regex-syntax"
-version = "0.4.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
[[package]]
name = "regex-syntax"
version = "0.5.0"
dependencies = [
"cargo 0.27.0",
"cargo_metadata 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "clippy_lints 0.0.187 (registry+https://github.com/rust-lang/crates.io-index)",
+ "clippy_lints 0.0.188",
"env_logger 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
"failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"json 0.11.12 (registry+https://github.com/rust-lang/crates.io-index)",
"jsonrpc-core 8.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "languageserver-types 0.30.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "languageserver-types 0.31.0 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rls-rustc 0.2.2 (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.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustfmt-nightly 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustfmt-nightly 0.4.1",
"serde 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
name = "rustbook"
version = "0.1.0"
dependencies = [
- "clap 2.29.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)",
"mdbook 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rustc-ap-rustc_cratesio_shim"
-version = "29.0.0"
+version = "67.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
[[package]]
name = "rustc-ap-rustc_data_structures"
-version = "29.0.0"
+version = "67.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "ena 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot_core 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-serialize 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-serialize 67.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rustc-ap-rustc_errors"
-version = "29.0.0"
+version = "67.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "rustc-ap-rustc_data_structures 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-serialize 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-syntax_pos 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "atty 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_data_structures 67.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-serialize 67.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-syntax_pos 67.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "termcolor 0.3.5 (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 = "rustc-ap-serialize"
-version = "29.0.0"
+version = "67.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "rustc-ap-syntax"
-version = "29.0.0"
+version = "67.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-rustc_cratesio_shim 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-rustc_data_structures 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-rustc_errors 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-serialize 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-syntax_pos 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_cratesio_shim 67.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_data_structures 67.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_errors 67.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-serialize 67.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-syntax_pos 67.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "scoped-tls 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rustc-ap-syntax_pos"
-version = "29.0.0"
+version = "67.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "rustc-ap-rustc_data_structures 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-serialize 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_data_structures 67.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-serialize 67.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "scoped-tls 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"term 0.4.6 (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 = "rustfmt-nightly"
-version = "0.3.8"
+version = "0.4.1"
dependencies = [
- "cargo_metadata 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cargo_metadata 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
"derive-new 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "env_logger 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
"getopts 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)",
- "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "itertools 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
- "regex 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-rustc_errors 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-syntax 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.10 (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.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "rustfmt-nightly"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "cargo_metadata 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "derive-new 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "diff 0.1.11 (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.15 (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.39 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-rustc_errors 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-syntax 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-syntax 67.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "term 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-[[package]]
-name = "semver"
-version = "0.6.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)",
-]
-
-[[package]]
-name = "semver"
-version = "0.8.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.29 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
[[package]]
name = "semver"
version = "0.9.0"
name = "serialize"
version = "0.0.0"
-[[package]]
-name = "shared_child"
-version = "0.2.1"
-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.39 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
[[package]]
name = "shell-escape"
version = "0.1.3"
[[package]]
name = "strsim"
-version = "0.6.0"
+version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
+[[package]]
+name = "term"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
[[package]]
name = "termcolor"
version = "0.3.5"
name = "workspace_symbol"
version = "0.1.0"
-[[package]]
-name = "ws2_32-sys"
-version = "0.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
[[package]]
name = "xattr"
version = "0.1.11"
"checksum advapi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e06588080cb19d0acb6739808aafa5f26bfb2ca015b2b6370028b44cf7cb8a9a"
"checksum aho-corasick 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ca972c2ea5f742bfce5687b9aef75506a764f61d37f8f649047846a9686ddb66"
"checksum aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d6531d44de723825aa81398a6415283229725a00fa30713812ab9323faa82fc4"
-"checksum ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6b3568b48b7cefa6b8ce125f9bb4989e52fbcc29ebea88df04cc7c5f12f70455"
+"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
"checksum ar 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "35c7a5669cb64f085739387e1308b74e6d44022464b7f1b63bbd4ceb6379ec31"
"checksum arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a1e964f9e24d588183fcb43503abda40d288c8657dfc27311516ce2f05675aef"
"checksum atty 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "af80143d6f7608d746df1520709e5d141c96f240b0e62b0aa41bdfb53374d9d4"
"checksum bufstream 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f2f382711e76b9de6c744cc00d0497baba02fb00a787f088c879f01d09468e32"
"checksum byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "652805b7e73fada9d85e9a6682a4abd490cb52d96aeecc12e33a0de34dfd0d23"
"checksum cargo_metadata 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "be1057b8462184f634c3a208ee35b0f935cfd94b694b26deadccd98732088d7b"
-"checksum cargo_metadata 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "20d6fb2b5574726329c85cdba0df0347fddfec3cf9c8b588f9931708280f5643"
"checksum cargo_metadata 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b5caae26de3704081ef638f87f05a6891b04f2b7d5ce9429a3de21095528ae22"
"checksum cc 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "fedf677519ac9e865c4ff43ef8f930773b37ed6e6ea61b6b83b400a7b5787f49"
"checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de"
"checksum chrono 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7c20ebe0b2b08b0aeddba49c609fe7957ba2e33449882cb186a180bc60682fa9"
-"checksum clap 2.29.0 (registry+https://github.com/rust-lang/crates.io-index)" = "110d43e343eb29f4f51c1db31beb879d546db27998577e5715270a54bcf41d3f"
-"checksum clippy_lints 0.0.187 (registry+https://github.com/rust-lang/crates.io-index)" = "f2227eeb80d00b3e6f67d27953224b2087a65e40597e3253b2a25493aac63859"
+"checksum clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f0f16b89cbb9ee36d87483dc939fe9f1e13c05898d56d7b230a0d4dff033a536"
"checksum cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)" = "56d741ea7a69e577f6d06b36b7dff4738f680593dc27a701ffa8506b73ce28bb"
"checksum commoncrypto 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d056a8586ba25a1e4d61cb090900e495952c7886786fc55f909ab2f819b69007"
"checksum commoncrypto-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1fed34f46747aa73dfaa578069fd8279d2818ade2b55f38f22a9401c7f4083e2"
-"checksum compiletest_rs 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "6c5aafb5d4a77c6b5fa384fe93c7a9a3561bd88c4b8b8e45187cf5e779b1badc"
+"checksum compiletest_rs 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "d47ca9a69772587159e1c7e20ee1e43dfe5f184d59591eac70e7d3603bdfe57a"
"checksum core-foundation 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "286e0b41c3a20da26536c6000a280585d519fd07b3956b43aed8a79e9edce980"
"checksum core-foundation-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "716c271e8613ace48344f723b60b900a93150271e5be206212d052bbc0883efa"
"checksum crossbeam 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "24ce9782d4d5c53674646a6a4c1863a21a8fc0cb649b3c94dfc16e45071dea19"
"checksum curl-sys 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f46e49c7125131f5afaded06944d6888b55cbdf8eba05dae73c954019b907961"
"checksum derive-new 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "92f8b8e1d6c8a5f5ea0849a0e4c55941576115c62d3fc425e96918bbbeb3d3c2"
"checksum diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "3c2b69f912779fbb121ceb775d74d51e915af17aaebc38d28a592843a2dd0a3a"
-"checksum docopt 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d8acd393692c503b168471874953a2531df0e9ab77d0b6bbc582395743300a4a"
"checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab"
-"checksum duct 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e45aa15fe0a8a8f511e6d834626afd55e49b62e5c8802e18328a87e8a8f6065c"
"checksum either 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "740178ddf48b1a9e878e6d6509a1442a2d42fd2928aae8e7a6f8a36fb01981b3"
"checksum ena 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f8b449f3b18c89d2dbe40548d2ee4fa58ea0a08b761992da6ecb9788e4688834"
"checksum endian-type 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d"
"checksum enum_primitive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "be4551092f4d519593039259a9ed8daedf0da12e5109c5280338073eaeb81180"
"checksum env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "15abd780e45b3ea4f76b4e9a26ff4843258dd8a3eed2775a0e7368c2e7936c2f"
-"checksum env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3ddf21e73e016298f5cb37d6ef8e8da8e39f91f9ec8b0df44b7deb16a9f8cd5b"
"checksum env_logger 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f0628f04f7c26ebccf40d7fc2c1cf92236c05ec88cf2132641cc956812312f0f"
"checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3"
-"checksum error-chain 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6930e04918388a9a2e41d518c25cf679ccafe26733fb4127dbf21993f2575d46"
"checksum failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "934799b6c1de475a012a02dab0ace1ace43789ee4b99bcfbf1a2e3e8ced5de82"
"checksum failure_derive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c7cdda555bb90c9bb67a3b670a0f42de8e73f5981524123ad8578aafec8ddb8b"
"checksum filetime 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "714653f3e34871534de23771ac7b26e999651a0a228f47beb324dfdf1dd4b10f"
"checksum if_chain 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "61bb90bdd39e3af69b0172dfc6130f6cd6332bf040fbb9bdd4401d37adbd48b8"
"checksum ignore 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "245bea0ba52531a3739cb8ba99f8689eda13d7faf8c36b6a73ce4421aab42588"
"checksum is-match 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7e5b386aef33a1c677be65237cb9d32c3f3ef56bd035949710c4bb13083eb053"
-"checksum itertools 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d3f2be4da1690a039e9ae5fd575f706a63ad5a2120f161b1d653c9da3930dd21"
"checksum itertools 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "b07332223953b5051bceb67e8c4700aa65291535568e1f12408c43c4a42c0394"
"checksum itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8324a32baf01e2ae060e9de58ed0bc2320c9a2833491ee36cd3b4c414de4db8c"
"checksum jobserver 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "9f2abd9fd3242accb0e2e30986f2cf30cda3e19eec5cc6d584b218ce2b1c0e3c"
"checksum json 0.11.12 (registry+https://github.com/rust-lang/crates.io-index)" = "39ebf0fac977ee3a4a3242b6446004ff64514889e3e2730bbd4f764a67a2e483"
"checksum jsonrpc-core 8.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ddf83704f4e79979a424d1082dd2c1e52683058056c9280efa19ac5f6bc9033c"
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
-"checksum languageserver-types 0.30.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1541f9b22687f060511d213036e1f058797c48e3501e177f01cb6e88de802f5b"
+"checksum languageserver-types 0.31.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d25086d59f44b80253d5ff96c66a692fb69de8485cf7a25b28677e89126de0d"
"checksum lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73"
"checksum lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c8f31047daa365f19be14b47c29df4f7c3b581832407daabe6ae77397619237d"
-"checksum lazycell 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3b585b7a6811fb03aa10e74b278a0f00f8dd9b45dc681f148bb29fa5cb61859b"
"checksum lazycell 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a6f08839bc70ef4a3fe1d566d5350f519c5912ea86be0df1740a7d247c7fc0ef"
"checksum libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)" = "f54263ad99207254cf58b5f701ecb432c717445ea2ee8af387334bdd1a03fdff"
"checksum libgit2-sys 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1ecbd6428006c321c29b6c8a895f0d90152f1cf4fd8faab69fc436a3d9594f63"
"checksum memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "796fba70e76612589ed2ce7f45282f5af869e0fdd7cc6199fa1aa1f1d591ba9d"
"checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3"
"checksum miniz-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "609ce024854aeb19a0ef7567d348aaa5a746b32fb72e336df7fcc16869d7e2b4"
-"checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919"
"checksum miow 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9224c91f82b3c47cf53dcf78dfaa20d6888fbcc5d272d5f2fcdf8a697f3c987d"
-"checksum net2 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)" = "9044faf1413a1057267be51b5afba8eb1090bd2231c693664aa1db716fe1eae0"
"checksum nibble_vec 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "62e678237a4c70c5f2b917cefd7d080dfbf800421f06e8a59d4e28ef5130fd9e"
-"checksum nix 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "47e49f6982987135c5e9620ab317623e723bd06738fd85377e8d55f57c8b6487"
"checksum nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "9a2228dca57108069a5262f2ed8bd2e82496d2e074a06d1ccc7ce1687b6ae0a2"
"checksum num 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "4703ad64153382334aa8db57c637364c322d3372e097840c72000dabdcf6156e"
"checksum num-integer 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)" = "f8d26da319fb45674985c78f1d1caf99aa4941f785d384a2ae36d0740bc3e2fe"
"checksum openssl 0.10.5 (registry+https://github.com/rust-lang/crates.io-index)" = "1636c9f1d78af9cbcc50e523bfff4a30274108aad5e86761afd4d31e4e184fa7"
"checksum openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de"
"checksum openssl-sys 0.9.27 (registry+https://github.com/rust-lang/crates.io-index)" = "d6fdc5c4a02e69ce65046f1763a0181107038e02176233acb0b3351d7cc588f9"
-"checksum os_pipe 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "998bfbb3042e715190fe2a41abfa047d7e8cb81374d2977d7f100eacd8619cb1"
"checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37"
"checksum parking_lot 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3e7f7c9857874e54afeb950eebeae662b1e51a2493666d2ea4c0a5d91dcf0412"
"checksum parking_lot_core 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "538ef00b7317875071d5e00f603f24d16f0b474c1a5fc0ccb8b454ca72eafa79"
"checksum pest 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0a6dda33d67c26f0aac90d324ab2eb7239c819fc7b2552fe9faa4fe88441edc8"
"checksum pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3a8b4c6b8165cd1a1cd4b9b120978131389f64bdaf456435caa41e630edba903"
"checksum proc-macro2 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cd07deb3c6d1d9ff827999c7f9b04cdfd66b1b17ae508e14fe47b620f2282ae0"
-"checksum pulldown-cmark 0.0.15 (registry+https://github.com/rust-lang/crates.io-index)" = "378e941dbd392c101f2cb88097fa4d7167bc421d4b88de3ff7dbee503bc3233b"
"checksum pulldown-cmark 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d6fdf85cda6cadfae5428a54661d431330b312bc767ddbc57adbedc24da66e32"
"checksum quick-error 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eda5fe9b71976e62bc81b781206aaa076401769b2143379d3eb2118388babac4"
"checksum quine-mc_cluskey 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "07589615d719a60c8dd8a4622e7946465dfef20d1a428f969e3443e7386d5f45"
"checksum regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)" = "4fd4ace6a8cf7860714a2c2280d6c1f7e6a413486c13298bbc86fd3da019402f"
"checksum regex 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a62bf8bb734ab90b7f234b681b01af396e5d39b028906c210dc04fa1d5e9e5b3"
"checksum regex-syntax 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "f9ec002c35e86791825ed294b50008eea9ddfc8def4420124fbc6b08db834957"
-"checksum regex-syntax 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8e931c58b93d86f080c734bfd2bce7dd0079ae2331235818133c8be7f422e20e"
"checksum regex-syntax 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "48d7391e7e90e06eaf3aefbe4652464153ecfec64806f3bf77ffc59638a63e77"
"checksum remove_dir_all 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b5d2f806b0fcdabd98acd380dc8daef485e22bcb7cddc811d1337967f2528cf5"
"checksum rls-analysis 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "fd4b9a3a3f2345854e39768e6425d1c893855da217183d1c0b3ff6f1664b6b6d"
"checksum rls-rustc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "885f66b92757420572cbb02e033d4a9558c7413ca9b7ac206f28fd58ffdb44ea"
"checksum rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d7c7046dc6a92f2ae02ed302746db4382e75131b9ce20ce967259f6b5867a6a"
"checksum rls-vfs 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "be231e1e559c315bc60ced5ad2cc2d7a9c208ed7d4e2c126500149836fda19bb"
-"checksum rustc-ap-rustc_cratesio_shim 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4ad5e562044ea78a6764dd75ae8afe4b21fde49f4548024b5fdf6345c21fb524"
-"checksum rustc-ap-rustc_data_structures 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c0d65325492aba7db72899e3edbab34d39af98c42ab7c7e450c9a288ffe4ad"
-"checksum rustc-ap-rustc_errors 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "87d4ab2e06a671b5b5c5b0359dac346f164c99d059dce6a22feb08f2f56bd182"
-"checksum rustc-ap-serialize 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e0745fa445ff41c4b6699936cf35ce3ca49502377dd7b3929c829594772c3a7b"
-"checksum rustc-ap-syntax 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "82efedabe30f393161e11214a9130edfa01ad476372d1c6f3fec1f8d30488c9d"
-"checksum rustc-ap-syntax_pos 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "db9de2e927e280c75b8efab9c5f591ad31082d5d2c4c562c68fdba2ee77286b0"
+"checksum rustc-ap-rustc_cratesio_shim 67.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "adc16e4a6e50a4ffbd4633d737aedbdfcb565bdf658159e0544266908180a919"
+"checksum rustc-ap-rustc_data_structures 67.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5ec5f0a018fbec07f64b689ac20f7343ed77939055ca07d2aceb37c832245b1b"
+"checksum rustc-ap-rustc_errors 67.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8301221cc07002666eed552a089b15000bc954c94b14a460c0653363a7f42f4c"
+"checksum rustc-ap-serialize 67.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5212ee40fc332d791cacf202ae5fb99197341857c0a14bcdf60541fea7dfc5ed"
+"checksum rustc-ap-syntax 67.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "168571b3878c6c61aef4bacef95c86d30fa61fb1cff04395d9535c80c196e559"
+"checksum rustc-ap-syntax_pos 67.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cd7a0486f56db583caa665c8b4ff02c4774fe279db1741509437bc8a84c53361"
"checksum rustc-demangle 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "11fb43a206a04116ffd7cfcf9bcb941f8eb6cc7ff667272246b0a1c74259a3cb"
"checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda"
-"checksum rustfmt-nightly 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "554256054eae37ead2f799ffa9cf8be8249496c6c3cf005c28b7cfa55f4efaa5"
"checksum same-file 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "cfb6eded0b06a0b512c8ddbcf04089138c9b4362c2f696f3c3d76039d68f3637"
"checksum schannel 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "fbaffce35eb61c5b00846e73128b0cd62717e7c0ec46abbec132370d013975b4"
"checksum scoped-tls 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8674d439c964889e2476f474a3bf198cc9e199e77499960893bac5de7e9218a4"
"checksum scopeguard 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "59a076157c1e2dc561d8de585151ee6965d910dd4dcb5dabb7ae3e83981a6c57"
"checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27"
-"checksum semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a3186ec9e65071a2095434b1f5bb24838d4e8e130f584c790f6033c79943537"
-"checksum semver 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bee2bc909ab2d8d60dab26e8cad85b25d795b14603a0dcb627b78b9d30b6454b"
"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
"checksum serde 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)" = "4763b773978e495252615e814d2ad04773b2c1f85421c7913869a537f35cb406"
"checksum serde_derive_internals 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1fc848d073be32cd982380c06587ea1d433bc1a4c4a111de07ec2286a3ddade8"
"checksum serde_ignored 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "190e9765dcedb56be63b6e0993a006c7e3b071a016a304736e4a315dc01fb142"
"checksum serde_json 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)" = "57781ed845b8e742fc2bf306aba8e3b408fe8c366b900e3769fbc39f49eb8b39"
-"checksum shared_child 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "099b38928dbe4a0a01fcd8c233183072f14a7d126a34bed05880869be66e14cc"
"checksum shell-escape 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "dd5cc96481d54583947bfe88bf30c23d53f883c6cd0145368b69989d97b84ef8"
"checksum shlex 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2"
"checksum smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44db0ecb22921ef790d17ae13a3f6d15784183ff5f2a01aa32098c7498d2b4b9"
"checksum socket2 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "78e4c1cde1adbc6bc4c394da2e7727c916b9b7d0b53d6984c890c65c1f4e6437"
"checksum stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "15132e0e364248108c5e2c02e3ab539be8d6f5d52a01ca9bbf27ed657316f02b"
-"checksum strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d15c810519a91cf877e7e36e63fe068815c678181439f2f29e2562147c3694"
+"checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550"
"checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad"
"checksum syn 0.12.14 (registry+https://github.com/rust-lang/crates.io-index)" = "8c5bc2d6ff27891209efa5f63e9de78648d7801f085e4653701a692ce938d6fd"
"checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6"
"checksum tar 0.4.14 (registry+https://github.com/rust-lang/crates.io-index)" = "1605d3388ceb50252952ffebab4b5dc43017ead7e4481b175961c283bb951195"
"checksum tempdir 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "f73eebdb68c14bcb24aef74ea96079830e7fa7b31a6106e42ea7ee887c1e134e"
"checksum term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "fa63644f74ce96fbeb9b794f66aff2a52d601cbd5e80f4b97123e3899f4570f1"
+"checksum term 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5e6b677dd1e8214ea1ef4297f85dbcbed8e8cdddb561040cc998ca2551c37561"
"checksum termcolor 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "56c456352e44f9f91f774ddeeed27c1ec60a2455ed66d692059acfb1d731bda1"
"checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096"
"checksum textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c0b59b6b4b44d867f1370ef1bd91bfb262bf07bf0ae65c202ea2fbc16153b693"
"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
"checksum wincolor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "eeb06499a3a4d44302791052df005d5232b927ed1a9658146d842165c4de7767"
-"checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e"
"checksum xattr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "5f04de8a1346489a2f9e9bd8526b73d135ec554227b17568456e86aa35b6f3fc"
"checksum xz2 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "98df591c3504d014dd791d998123ed00a476c7e26dc6b2e873cb55c6ac9e59fa"
"checksum yaml-rust 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e66366e18dc58b46801afbf2ca7661a9f59cc8c5962c29892b6039b4f86fa992"
# RLS depends on `rustfmt` from crates.io, so we put this in a `[patch]` section
# for crates.io
rustfmt-nightly = { path = "tools/rustfmt" }
+clippy_lints = { path = "tools/clippy/clippy_lints" }
self.cargo()))
args = [self.cargo(), "build", "--manifest-path",
os.path.join(self.rust_root, "src/bootstrap/Cargo.toml")]
- if self.verbose:
+ for _ in range(1, self.verbose):
args.append("--verbose")
- if self.verbose > 1:
- args.append("--verbose")
if self.use_locked_deps:
args.append("--locked")
if self.use_vendored_sources:
return config
return default_build_triple()
+ def check_submodule(self, module, slow_submodules):
+ if not slow_submodules:
+ checked_out = subprocess.Popen(["git", "rev-parse", "HEAD"],
+ cwd=os.path.join(self.rust_root, module),
+ stdout=subprocess.PIPE)
+ return checked_out
+ else:
+ return None
+
+ def update_submodule(self, module, checked_out, recorded_submodules):
+ module_path = os.path.join(self.rust_root, module)
+
+ if checked_out != None:
+ default_encoding = sys.getdefaultencoding()
+ checked_out = checked_out.communicate()[0].decode(default_encoding).strip()
+ if recorded_submodules[module] == checked_out:
+ return
+
+ print("Updating submodule", module)
+
+ run(["git", "submodule", "-q", "sync", module],
+ cwd=self.rust_root, verbose=self.verbose)
+ run(["git", "submodule", "update",
+ "--init", "--recursive", module],
+ cwd=self.rust_root, verbose=self.verbose)
+ run(["git", "reset", "-q", "--hard"],
+ cwd=module_path, verbose=self.verbose)
+ run(["git", "clean", "-qdfx"],
+ cwd=module_path, verbose=self.verbose)
+
def update_submodules(self):
"""Update submodules"""
if (not os.path.exists(os.path.join(self.rust_root, ".git"))) or \
self.get_toml('submodules') == "false":
return
- print('Updating submodules')
+ slow_submodules = self.get_toml('fast-submodule') == "false"
+ start_time = time()
+ if slow_submodules:
+ print('Unconditionally updating all submodules')
+ else:
+ print('Updating only changed submodules')
default_encoding = sys.getdefaultencoding()
- run(["git", "submodule", "-q", "sync"], cwd=self.rust_root, verbose=self.verbose)
submodules = [s.split(' ', 1)[1] for s in subprocess.check_output(
["git", "config", "--file",
os.path.join(self.rust_root, ".gitmodules"),
"--get-regexp", "path"]
).decode(default_encoding).splitlines()]
filtered_submodules = []
+ submodules_names = []
for module in submodules:
if module.endswith("llvm"):
if self.get_toml('llvm-config'):
config = self.get_toml('lld')
if config is None or config == 'false':
continue
- filtered_submodules.append(module)
- run(["git", "submodule", "update",
- "--init", "--recursive"] + filtered_submodules,
- cwd=self.rust_root, verbose=self.verbose)
- run(["git", "submodule", "-q", "foreach", "git",
- "reset", "-q", "--hard"],
- cwd=self.rust_root, verbose=self.verbose)
- run(["git", "submodule", "-q", "foreach", "git",
- "clean", "-qdfx"],
- cwd=self.rust_root, verbose=self.verbose)
+ check = self.check_submodule(module, slow_submodules)
+ filtered_submodules.append((module, check))
+ submodules_names.append(module)
+ recorded = subprocess.Popen(["git", "ls-tree", "HEAD"] + submodules_names,
+ cwd=self.rust_root, stdout=subprocess.PIPE)
+ recorded = recorded.communicate()[0].decode(default_encoding).strip().splitlines()
+ recorded_submodules = {}
+ for data in recorded:
+ data = data.split()
+ recorded_submodules[data[3]] = data[2]
+ for module in filtered_submodules:
+ self.update_submodule(module[0], module[1], recorded_submodules)
+ print("Submodules updated in %.2f seconds" % (time() - start_time))
def set_dev_environment(self):
"""Set download URL for development environment"""
parser.add_argument('--config')
parser.add_argument('--build')
parser.add_argument('--clean', action='store_true')
- parser.add_argument('-v', '--verbose', action='store_true')
+ parser.add_argument('-v', '--verbose', action='count', default=0)
args = [a for a in sys.argv if a != '-h' and a != '--help']
args, _ = parser.parse_known_args(args)
except (OSError, IOError):
pass
- if '\nverbose = 2' in build.config_toml:
- build.verbose = 2
- elif '\nverbose = 1' in build.config_toml:
- build.verbose = 1
+ match = re.search(r'\nverbose = (\d+)', build.config_toml)
+ if match is not None:
+ build.verbose = max(build.verbose, int(match.group(1)))
build.use_vendored_sources = '\nvendor = true' in build.config_toml
test::CompileFailFullDeps, test::IncrementalFullDeps, test::Rustdoc, test::Pretty,
test::RunPassPretty, test::RunFailPretty, test::RunPassValgrindPretty,
test::RunPassFullDepsPretty, test::RunFailFullDepsPretty, test::RunMake,
- test::Crate, test::CrateLibrustc, test::Rustdoc, test::Linkcheck, test::Cargotest,
- test::Cargo, test::Rls, test::ErrorIndex, test::Distcheck,
+ test::Crate, test::CrateLibrustc, test::CrateRustdoc, test::Linkcheck,
+ test::Cargotest, test::Cargo, test::Rls, test::ErrorIndex, test::Distcheck,
test::Nomicon, test::Reference, test::RustdocBook, test::RustByExample,
test::TheBook, test::UnstableBook,
test::Rustfmt, test::Miri, test::Clippy, test::RustdocJS, test::RustdocTheme),
cargo.env("WINAPI_NO_BUNDLED_LIBRARIES", "1");
}
- if self.is_very_verbose() {
+ for _ in 1..self.verbosity {
cargo.arg("-v");
}
.collect::<HashSet<_>>();
for target in targets.into_iter() {
let mut cfg = cc::Build::new();
- cfg.cargo_metadata(false).opt_level(0).warnings(false).debug(false)
+ cfg.cargo_metadata(false).opt_level(2).warnings(false).debug(false)
.target(&target).host(&build.build);
if target.contains("msvc") {
cfg.static_crt(true);
let hosts = build.hosts.iter().cloned().chain(iter::once(build.build)).collect::<HashSet<_>>();
for host in hosts.into_iter() {
let mut cfg = cc::Build::new();
- cfg.cargo_metadata(false).opt_level(0).warnings(false).debug(false).cpp(true)
+ cfg.cargo_metadata(false).opt_level(2).warnings(false).debug(false).cpp(true)
.target(&host).host(&build.build);
let config = build.config.target_config.get(&host);
if let Some(cxx) = config.and_then(|c| c.cxx.as_ref()) {
"libbcrypt.a",
"libcomctl32.a",
"libcomdlg32.a",
+ "libcredui.a",
"libcrypt32.a",
+ "libdbghelp.a",
"libgdi32.a",
"libimagehlp.a",
"libiphlpapi.a",
"libkernel32.a",
+ "libmsimg32.a",
"libmsvcrt.a",
"libodbc32.a",
"libole32.a",
"libopengl32.a",
"libpsapi.a",
"librpcrt4.a",
+ "libsecur32.a",
"libsetupapi.a",
"libshell32.a",
+ "libsynchronization.a",
"libuser32.a",
"libuserenv.a",
"libuuid.a",
"libwinspool.a",
"libws2_32.a",
"libwsock32.a",
- "libdbghelp.a",
- "libmsimg32.a",
];
//Find mingw artifacts we want to bundle
// state for RLS isn't testing.
let rls = builder.ensure(tool::Rls {
compiler: builder.compiler(stage, build.build),
- target
+ target, extra_features: Vec::new()
}).or_else(|| { println!("Unable to build RLS, skipping dist"); None })?;
install(&rls, &image.join("bin"), 0o755);
// Prepare the image directory
let rustfmt = builder.ensure(tool::Rustfmt {
compiler: builder.compiler(stage, build.build),
- target
+ target, extra_features: Vec::new()
}).or_else(|| { println!("Unable to build Rustfmt, skipping dist"); None })?;
let cargofmt = builder.ensure(tool::Cargofmt {
compiler: builder.compiler(stage, build.build),
- target
+ target, extra_features: Vec::new()
}).or_else(|| { println!("Unable to build Cargofmt, skipping dist"); None })?;
install(&rustfmt, &image.join("bin"), 0o755);
/// Deserialized version of all flags for this compile.
pub struct Flags {
- pub verbose: usize, // verbosity level: 0 == not verbose, 1 == verbose, 2 == very verbose
+ pub verbose: usize, // number of -v args; each extra -v after the first is passed to Cargo
pub on_fail: Option<String>,
pub stage: Option<u32>,
pub keep_stage: Option<u32>,
#![deny(warnings)]
#![feature(core_intrinsics)]
+#![feature(slice_concat_ext)]
#[macro_use]
extern crate build_helper;
self.verbosity > 0
}
- pub fn is_very_verbose(&self) -> bool {
- self.verbosity > 1
- }
-
/// Prints a message if this build is configured in verbose mode.
fn verbose(&self, msg: &str) {
if self.is_verbose() {
let host = self.host;
let compiler = builder.compiler(stage, host);
- builder.ensure(tool::Rls { compiler, target: self.host });
+ builder.ensure(tool::Rls { compiler, target: self.host, extra_features: Vec::new() });
let mut cargo = tool::prepare_tool_cargo(builder,
compiler,
host,
let host = self.host;
let compiler = builder.compiler(stage, host);
- builder.ensure(tool::Rustfmt { compiler, target: self.host });
+ builder.ensure(tool::Rustfmt { compiler, target: self.host, extra_features: Vec::new() });
let mut cargo = tool::prepare_tool_cargo(builder,
compiler,
host,
let host = self.host;
let compiler = builder.compiler(stage, host);
- if let Some(miri) = builder.ensure(tool::Miri { compiler, target: self.host }) {
+ let miri = builder.ensure(tool::Miri {
+ compiler,
+ target: self.host,
+ extra_features: Vec::new(),
+ });
+ if let Some(miri) = miri {
let mut cargo = builder.cargo(compiler, Mode::Tool, host, "test");
cargo.arg("--manifest-path").arg(build.src.join("src/tools/miri/Cargo.toml"));
let host = self.host;
let compiler = builder.compiler(stage, host);
- if let Some(clippy) = builder.ensure(tool::Clippy { compiler, target: self.host }) {
+ let clippy = builder.ensure(tool::Clippy {
+ compiler,
+ target: self.host,
+ extra_features: Vec::new(),
+ });
+ if let Some(clippy) = clippy {
let mut cargo = builder.cargo(compiler, Mode::Tool, host, "test");
cargo.arg("--manifest-path").arg(build.src.join("src/tools/clippy/Cargo.toml"));
use std::env;
use std::path::PathBuf;
use std::process::{Command, exit};
+use std::slice::SliceConcatExt;
use Mode;
use Compiler;
}
}
-#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
+#[derive(Debug, Clone, Hash, PartialEq, Eq)]
struct ToolBuild {
compiler: Compiler,
target: Interned<String>,
path: &'static str,
mode: Mode,
is_ext_tool: bool,
+ extra_features: Vec<String>,
}
impl Step for ToolBuild {
println!("Building stage{} tool {} ({})", compiler.stage, tool, target);
let mut cargo = prepare_tool_cargo(builder, compiler, target, "build", path);
+ cargo.arg("--features").arg(self.extra_features.join(" "));
let is_expected = build.try_run(&mut cargo);
build.save_toolstate(tool, if is_expected {
ToolState::TestFail
mode: $mode,
path: $path,
is_ext_tool: false,
+ extra_features: Vec::new(),
}).expect("expected to build -- essential tool")
}
}
mode: Mode::Libstd,
path: "src/tools/remote-test-server",
is_ext_tool: false,
+ extra_features: Vec::new(),
}).expect("expected to build -- essential tool")
}
}
mode: Mode::Librustc,
path: "src/tools/cargo",
is_ext_tool: false,
+ extra_features: Vec::new(),
}).expect("expected to build -- essential tool")
}
}
$tool_name:expr,
$extra_deps:block;)+) => {
$(
- #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
+ #[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub struct $name {
pub compiler: Compiler,
pub target: Interned<String>,
+ pub extra_features: Vec<String>,
}
impl Step for $name {
run.builder.ensure($name {
compiler: run.builder.compiler(run.builder.top_stage, run.builder.build.build),
target: run.target,
+ extra_features: Vec::new(),
});
}
- fn run($sel, $builder: &Builder) -> Option<PathBuf> {
+ #[allow(unused_mut)]
+ fn run(mut $sel, $builder: &Builder) -> Option<PathBuf> {
$extra_deps
$builder.ensure(ToolBuild {
compiler: $sel.compiler,
tool: $tool_name,
mode: Mode::Librustc,
path: $path,
+ extra_features: $sel.extra_features,
is_ext_tool: true,
})
}
};
Miri, miri, "src/tools/miri", "miri", {};
Rls, rls, "src/tools/rls", "rls", {
+ let clippy = builder.ensure(Clippy {
+ compiler: self.compiler,
+ target: self.target,
+ extra_features: Vec::new(),
+ });
+ if clippy.is_some() {
+ self.extra_features.push("clippy".to_owned());
+ }
builder.ensure(native::Openssl {
target: self.target,
});
ENV TARGETS=asmjs-unknown-emscripten
-ENV RUST_CONFIGURE_ARGS --enable-emscripten
+ENV RUST_CONFIGURE_ARGS --enable-emscripten --disable-optimize-tests
-ENV SCRIPT python2.7 ../x.py test --target $TARGETS
+ENV SCRIPT python2.7 ../x.py test --target $TARGETS \
+ src/test/run-pass \
+ src/test/run-fail \
+ src/libstd \
+ src/liballoc \
+ src/libcore
curl https://ftp.gnu.org/gnu/gcc/gcc-$GCC/gcc-$GCC.tar.bz2 | tar xjf -
cd gcc-$GCC
+
+# FIXME(#49246): Remove the `sed` below.
+#
+# On 2018 March 21st, two Travis builders' cache for Docker are suddenly invalidated. Normally this
+# is fine, because we just need to rebuild the Docker image. However, it reveals a network issue:
+# downloading from `ftp://gcc.gnu.org/` from Travis (using passive mode) often leads to "Connection
+# timed out" error, and even when the download completed, the file is usually corrupted. This causes
+# nothing to be landed that day.
+#
+# We observed that the `gcc-4.8.5.tar.bz2` above can be downloaded successfully, so as a stability
+# improvement we try to download from the HTTPS mirror instead. Turns out this uncovered the third
+# bug: the host `gcc.gnu.org` and `cygwin.com` share the same IP, and the TLS certificate of the
+# latter host is presented to `wget`! Therefore, we choose to download from the insecure HTTP server
+# instead here.
+#
+sed -i'' 's|ftp://gcc\.gnu\.org/|http://gcc.gnu.org/|g' ./contrib/download_prerequisites
+
./contrib/download_prerequisites
mkdir ../gcc-build
cd ../gcc-build
set -ex
source shared.sh
-curl https://www.kernel.org/pub/software/scm/git/git-2.10.0.tar.gz | tar xzf -
+curl -L https://www.kernel.org/pub/software/scm/git/git-2.10.0.tar.gz | tar xzf -
cd git-2.10.0
make configure
curl https://ftp.gnu.org/gnu/gcc/gcc-$GCC/gcc-$GCC.tar.bz2 | tar xjf -
cd gcc-$GCC
+
+# FIXME(#49246): Remove the `sed` below.
+#
+# On 2018 March 21st, two Travis builders' cache for Docker are suddenly invalidated. Normally this
+# is fine, because we just need to rebuild the Docker image. However, it reveals a network issue:
+# downloading from `ftp://gcc.gnu.org/` from Travis (using passive mode) often leads to "Connection
+# timed out" error, and even when the download completed, the file is usually corrupted. This causes
+# nothing to be landed that day.
+#
+# We observed that the `gcc-4.8.5.tar.bz2` above can be downloaded successfully, so as a stability
+# improvement we try to download from the HTTPS mirror instead. Turns out this uncovered the third
+# bug: the host `gcc.gnu.org` and `cygwin.com` share the same IP, and the TLS certificate of the
+# latter host is presented to `wget`! Therefore, we choose to download from the insecure HTTP server
+# instead here.
+#
+sed -i'' 's|ftp://gcc\.gnu\.org/|http://gcc.gnu.org/|g' ./contrib/download_prerequisites
+
./contrib/download_prerequisites
mkdir ../gcc-build
cd ../gcc-build
set -ex
source shared.sh
-curl https://www.kernel.org/pub/software/scm/git/git-2.10.0.tar.gz | tar xzf -
+curl -L https://www.kernel.org/pub/software/scm/git/git-2.10.0.tar.gz | tar xzf -
cd git-2.10.0
make configure
travis_fold end log-system-info
if [ ! -z "$SCRIPT" ]; then
- sh -x -c "$SCRIPT"
+ # FIXME(#49246): Re-enable these tools after #49246 has been merged and thus fixing the cache.
+ if [ "$DEPLOY_ALT" = 1 ]; then
+ sh -x -c "$SCRIPT \
+ --exclude src/tools/rls \
+ --exclude src/tools/rustfmt \
+ --exclude src/tools/clippy"
+ else
+ sh -x -c "$SCRIPT"
+ fi
else
do_make() {
travis_fold start "make-$1"
+++ /dev/null
-# `advanced_slice_patterns`
-
-The tracking issue for this feature is: [#23121]
-
-[#23121]: https://github.com/rust-lang/rust/issues/23121
-
-See also [`slice_patterns`](language-features/slice-patterns.html).
-
-------------------------
-
-
-The `advanced_slice_patterns` gate lets you use `..` to indicate any number of
-elements inside a pattern matching a slice. This wildcard can only be used once
-for a given array. If there's an identifier before the `..`, the result of the
-slice will be bound to that name. For example:
-
-```rust
-#![feature(advanced_slice_patterns, slice_patterns)]
-
-fn is_symmetric(list: &[u32]) -> bool {
- match list {
- &[] | &[_] => true,
- &[x, ref inside.., y] if x == y => is_symmetric(inside),
- _ => false
- }
-}
-
-fn main() {
- let sym = &[0, 1, 4, 2, 4, 1, 0];
- assert!(is_symmetric(sym));
-
- let not_sym = &[0, 1, 7, 2, 4, 1, 0];
- assert!(!is_symmetric(not_sym));
-}
-```
[#23121]: https://github.com/rust-lang/rust/issues/23121
-See also
-[`advanced_slice_patterns`](language-features/advanced-slice-patterns.html).
-
------------------------
-
-If you want to match against a slice or array, you can use `&` with the
-`slice_patterns` feature:
+The `slice_patterns` feature gate lets you use `..` to indicate any number of
+elements inside a pattern matching a slice. This wildcard can only be used once
+for a given array. If there's an pattern before the `..`, the subslice will be
+matched against that pattern. For example:
```rust
#![feature(slice_patterns)]
+fn is_symmetric(list: &[u32]) -> bool {
+ match list {
+ &[] | &[_] => true,
+ &[x, ref inside.., y] if x == y => is_symmetric(inside),
+ &[..] => false,
+ }
+}
+
fn main() {
- let v = vec!["match_this", "1"];
+ let sym = &[0, 1, 4, 2, 4, 1, 0];
+ assert!(is_symmetric(sym));
- match &v[..] {
- &["match_this", second] => println!("The second element is {}", second),
- _ => {},
- }
+ let not_sym = &[0, 1, 7, 2, 4, 1, 0];
+ assert!(!is_symmetric(not_sym));
}
```
-
use core::fmt;
use core::hash::{self, Hash, Hasher};
use core::iter::FusedIterator;
-use core::marker::{self, Unsize};
-use core::mem;
+use core::marker::{self, Unpin, Unsize};
+use core::mem::{self, Pin};
use core::ops::{CoerceUnsized, Deref, DerefMut, Generator, GeneratorState};
use core::ops::{BoxPlace, Boxed, InPlace, Place, Placer};
use core::ptr::{self, NonNull, Unique};
(**self).resume()
}
}
+
+/// A pinned, heap allocated reference.
+#[unstable(feature = "pin", issue = "49150")]
+#[fundamental]
+pub struct PinBox<T: ?Sized> {
+ inner: Box<T>,
+}
+
+#[unstable(feature = "pin", issue = "49150")]
+impl<T> PinBox<T> {
+ /// Allocate memory on the heap, move the data into it and pin it.
+ #[unstable(feature = "pin", issue = "49150")]
+ pub fn new(data: T) -> PinBox<T> {
+ PinBox { inner: Box::new(data) }
+ }
+}
+
+#[unstable(feature = "pin", issue = "49150")]
+impl<T: ?Sized> PinBox<T> {
+ /// Get a pinned reference to the data in this PinBox.
+ pub fn as_pin<'a>(&'a mut self) -> Pin<'a, T> {
+ unsafe { Pin::new_unchecked(&mut *self.inner) }
+ }
+
+ /// Get a mutable reference to the data inside this PinBox.
+ ///
+ /// This function is unsafe. Users must guarantee that the data is never
+ /// moved out of this reference.
+ pub unsafe fn get_mut<'a>(this: &'a mut PinBox<T>) -> &'a mut T {
+ &mut *this.inner
+ }
+
+ /// Convert this PinBox into an unpinned Box.
+ ///
+ /// This function is unsafe. Users must guarantee that the data is never
+ /// moved out of the box.
+ pub unsafe fn unpin(this: PinBox<T>) -> Box<T> {
+ this.inner
+ }
+}
+
+#[unstable(feature = "pin", issue = "49150")]
+impl<T: ?Sized> From<Box<T>> for PinBox<T> {
+ fn from(boxed: Box<T>) -> PinBox<T> {
+ PinBox { inner: boxed }
+ }
+}
+
+#[unstable(feature = "pin", issue = "49150")]
+impl<T: Unpin + ?Sized> From<PinBox<T>> for Box<T> {
+ fn from(pinned: PinBox<T>) -> Box<T> {
+ pinned.inner
+ }
+}
+
+#[unstable(feature = "pin", issue = "49150")]
+impl<T: ?Sized> Deref for PinBox<T> {
+ type Target = T;
+
+ fn deref(&self) -> &T {
+ &*self.inner
+ }
+}
+
+#[unstable(feature = "pin", issue = "49150")]
+impl<T: Unpin + ?Sized> DerefMut for PinBox<T> {
+ fn deref_mut(&mut self) -> &mut T {
+ &mut *self.inner
+ }
+}
+
+#[unstable(feature = "pin", issue = "49150")]
+impl<T: fmt::Display + ?Sized> fmt::Display for PinBox<T> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ fmt::Display::fmt(&*self.inner, f)
+ }
+}
+
+#[unstable(feature = "pin", issue = "49150")]
+impl<T: fmt::Debug + ?Sized> fmt::Debug for PinBox<T> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ fmt::Debug::fmt(&*self.inner, f)
+ }
+}
+
+#[unstable(feature = "pin", issue = "49150")]
+impl<T: ?Sized> fmt::Pointer for PinBox<T> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ // It's not possible to extract the inner Uniq directly from the Box,
+ // instead we cast it to a *const which aliases the Unique
+ let ptr: *const T = &*self.inner;
+ fmt::Pointer::fmt(&ptr, f)
+ }
+}
+
+#[unstable(feature = "pin", issue = "49150")]
+impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<PinBox<U>> for PinBox<T> {}
//!
//! * *nothing* ⇒ [`Display`]
//! * `?` ⇒ [`Debug`]
+//! * `x?` ⇒ [`Debug`] with lower-case hexadecimal integers
+//! * `X?` ⇒ [`Debug`] with upper-case hexadecimal integers
//! * `o` ⇒ [`Octal`](trait.Octal.html)
//! * `x` ⇒ [`LowerHex`](trait.LowerHex.html)
//! * `X` ⇒ [`UpperHex`](trait.UpperHex.html)
}
}
-/// An arbitrary non-null address to represent zero-size allocations.
-///
-/// This preserves the non-null invariant for types like `Box<T>`. The address
-/// may overlap with non-zero-size memory allocations.
-#[rustc_deprecated(since = "1.19.0", reason = "Use Unique/NonNull::empty() instead")]
-#[unstable(feature = "heap_api", issue = "27700")]
-pub const EMPTY: *mut () = 1 as *mut ();
-
/// The allocator for unique pointers.
// This function must not unwind. If it does, MIR trans will fail.
#[cfg(not(test))]
#![feature(offset_to)]
#![feature(optin_builtin_traits)]
#![feature(pattern)]
+#![feature(pin)]
#![feature(placement_in_syntax)]
#![feature(placement_new_protocol)]
#![feature(ptr_internals)]
#![feature(rustc_attrs)]
#![feature(slice_get_slice)]
-#![feature(slice_patterns)]
#![feature(slice_rsplit)]
#![feature(specialization)]
#![feature(staged_api)]
#![deny(warnings)]
#![feature(flt2dec)]
-#![feature(slice_patterns)]
#![feature(test)]
extern crate core;
/// A trait for borrowing data.
///
-/// In general, there may be several ways to "borrow" a piece of data. The
-/// typical ways of borrowing a type `T` are `&T` (a shared borrow) and `&mut T`
-/// (a mutable borrow). But types like `Vec<T>` provide additional kinds of
-/// borrows: the borrowed slices `&[T]` and `&mut [T]`.
+/// In Rust, it is common to provide different representations of a type for
+/// different use cases. For instance, storage location and management for a
+/// value can be specifically chosen as appropriate for a particular use via
+/// pointer types such as [`Box<T>`] or [`Rc<T>`]. Beyond these generic
+/// wrappers that can be used with any type, some types provide optional
+/// facets providing potentially costly functionality. An example for such a
+/// type is [`String`] which adds the ability to extend a string to the basic
+/// [`str`]. This requires keeping additional information unnecessary for a
+/// simple, immutable string.
///
-/// When writing generic code, it is often desirable to abstract over all ways
-/// of borrowing data from a given type. That is the role of the `Borrow`
-/// trait: if `T: Borrow<U>`, then `&U` can be borrowed from `&T`. A given
-/// type can be borrowed as multiple different types. In particular, `Vec<T>:
-/// Borrow<Vec<T>>` and `Vec<T>: Borrow<[T]>`.
+/// These types provide access to the underlying data through references
+/// to the type of that data. They are said to be ‘borrowed as’ that type.
+/// For instance, a [`Box<T>`] can be borrowed as `T` while a [`String`]
+/// can be borrowed as `str`.
///
-/// If you are implementing `Borrow` and both `Self` and `Borrowed` implement
-/// `Hash`, `Eq`, and/or `Ord`, they must produce the same result.
+/// Types express that they can be borrowed as some type `T` by implementing
+/// `Borrow<T>`, providing a reference to a `T` in the trait’s
+/// [`borrow`] method. A type is free to borrow as several different types.
+/// If it wishes to mutably borrow as the type – allowing the underlying data
+/// to be modified, it can additionally implement [`BorrowMut<T>`].
///
-/// `Borrow` is very similar to, but different than, `AsRef`. See
-/// [the book][book] for more.
+/// Further, when providing implementations for additional traits, it needs
+/// to be considered whether they should behave identical to those of the
+/// underlying type as a consequence of acting as a representation of that
+/// underlying type. Generic code typically uses `Borrow<T>` when it relies
+/// on the identical behavior of these additional trait implementations.
+/// These traits will likely appear as additional trait bounds.
///
-/// [book]: ../../book/first-edition/borrow-and-asref.html
+/// If generic code merely needs to work for all types that can
+/// provide a reference to related type `T`, it is often better to use
+/// [`AsRef<T>`] as more types can safely implement it.
+///
+/// [`AsRef<T>`]: ../../std/convert/trait.AsRef.html
+/// [`BorrowMut<T>`]: trait.BorrowMut.html
+/// [`Box<T>`]: ../../std/boxed/struct.Box.html
+/// [`Mutex<T>`]: ../../std/sync/struct.Mutex.html
+/// [`Rc<T>`]: ../../std/rc/struct.Rc.html
+/// [`str`]: ../../std/primitive.str.html
+/// [`String`]: ../../std/string/struct.String.html
+/// [`borrow`]: #tymethod.borrow
+///
+/// # Examples
+///
+/// As a data collection, [`HashMap<K, V>`] owns both keys and values. If
+/// the key’s actual data is wrapped in a managing type of some kind, it
+/// should, however, still be possible to search for a value using a
+/// reference to the key’s data. For instance, if the key is a string, then
+/// it is likely stored with the hash map as a [`String`], while it should
+/// be possible to search using a [`&str`][`str`]. Thus, `insert` needs to
+/// operate on a `String` while `get` needs to be able to use a `&str`.
+///
+/// Slightly simplified, the relevant parts of `HashMap<K, V>` look like
+/// this:
+///
+/// ```
+/// use std::borrow::Borrow;
+/// use std::hash::Hash;
+///
+/// pub struct HashMap<K, V> {
+/// # marker: ::std::marker::PhantomData<(K, V)>,
+/// // fields omitted
+/// }
+///
+/// impl<K, V> HashMap<K, V> {
+/// pub fn insert(&self, key: K, value: V) -> Option<V>
+/// where K: Hash + Eq
+/// {
+/// # unimplemented!()
+/// // ...
+/// }
+///
+/// pub fn get<Q>(&self, k: &Q) -> Option<&V>
+/// where
+/// K: Borrow<Q>,
+/// Q: Hash + Eq + ?Sized
+/// {
+/// # unimplemented!()
+/// // ...
+/// }
+/// }
+/// ```
+///
+/// The entire hash map is generic over a key type `K`. Because these keys
+/// are stored with the hash map, this type has to own the key’s data.
+/// When inserting a key-value pair, the map is given such a `K` and needs
+/// to find the correct hash bucket and check if the key is already present
+/// based on that `K`. It therefore requires `K: Hash + Eq`.
+///
+/// When searching for a value in the map, however, having to provide a
+/// reference to a `K` as the key to search for would require to always
+/// create such an owned value. For string keys, this would mean a `String`
+/// value needs to be created just for the search for cases where only a
+/// `str` is available.
+///
+/// Instead, the `get` method is generic over the type of the underlying key
+/// data, called `Q` in the method signature above. It states that `K`
+/// borrows as a `Q` by requiring that `K: Borrow<Q>`. By additionally
+/// requiring `Q: Hash + Eq`, it signals the requirement that `K` and `Q`
+/// have implementations of the `Hash` and `Eq` traits that produce identical
+/// results.
+///
+/// The implementation of `get` relies in particular on identical
+/// implementations of `Hash` by determining the key’s hash bucket by calling
+/// `Hash::hash` on the `Q` value even though it inserted the key based on
+/// the hash value calculated from the `K` value.
+///
+/// As a consequence, the hash map breaks if a `K` wrapping a `Q` value
+/// produces a different hash than `Q`. For instance, imagine you have a
+/// type that wraps a string but compares ASCII letters ignoring their case:
+///
+/// ```
+/// pub struct CaseInsensitiveString(String);
+///
+/// impl PartialEq for CaseInsensitiveString {
+/// fn eq(&self, other: &Self) -> bool {
+/// self.0.eq_ignore_ascii_case(&other.0)
+/// }
+/// }
+///
+/// impl Eq for CaseInsensitiveString { }
+/// ```
+///
+/// Because two equal values need to produce the same hash value, the
+/// implementation of `Hash` needs to ignore ASCII case, too:
+///
+/// ```
+/// # use std::hash::{Hash, Hasher};
+/// # pub struct CaseInsensitiveString(String);
+/// impl Hash for CaseInsensitiveString {
+/// fn hash<H: Hasher>(&self, state: &mut H) {
+/// for c in self.0.as_bytes() {
+/// c.to_ascii_lowercase().hash(state)
+/// }
+/// }
+/// }
+/// ```
+///
+/// Can `CaseInsensitiveString` implement `Borrow<str>`? It certainly can
+/// provide a reference to a string slice via its contained owned string.
+/// But because its `Hash` implementation differs, it behaves differently
+/// from `str` and therefore must not, in fact, implement `Borrow<str>`.
+/// If it wants to allow others access to the underlying `str`, it can do
+/// that via `AsRef<str>` which doesn’t carry any extra requirements.
+///
+/// [`Hash`]: ../../std/hash/trait.Hash.html
+/// [`HashMap<K, V>`]: ../../std/collections/struct.HashMap.html
+/// [`String`]: ../../std/string/struct.String.html
+/// [`str`]: ../../std/primitive.str.html
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Borrow<Borrowed: ?Sized> {
/// Immutably borrows from an owned value.
/// A trait for mutably borrowing data.
///
-/// Similar to `Borrow`, but for mutable borrows.
+/// As a companion to [`Borrow<T>`] this trait allows a type to borrow as
+/// an underlying type by providing a mutable reference. See [`Borrow<T>`]
+/// for more information on borrowing as another type.
+///
+/// [`Borrow<T>`]: trait.Borrow.html
#[stable(feature = "rust1", since = "1.0.0")]
pub trait BorrowMut<Borrowed: ?Sized> : Borrow<Borrowed> {
/// Mutably borrows from an owned value.
// flags available in the v1 format of format_args
#[derive(Copy, Clone)]
-enum FlagV1 { SignPlus, SignMinus, Alternate, SignAwareZeroPad, }
+enum FlagV1 { SignPlus, SignMinus, Alternate, SignAwareZeroPad, DebugLowerHex, DebugUpperHex }
impl<'a> Arguments<'a> {
/// When using the format_args!() macro, this function is used to generate the
self.flags & (1 << FlagV1::SignAwareZeroPad as u32) != 0
}
+ // FIXME: Decide what public API we want for these two flags.
+ // https://github.com/rust-lang/rust/issues/48584
+ fn debug_lower_hex(&self) -> bool { self.flags & (1 << FlagV1::DebugLowerHex as u32) != 0 }
+
+ fn debug_upper_hex(&self) -> bool { self.flags & (1 << FlagV1::DebugUpperHex as u32) != 0 }
+
/// Creates a [`DebugStruct`] builder designed to assist with creation of
/// [`fmt::Debug`] implementations for structs.
///
#[doc(hidden)]
trait GenericRadix {
/// The number of digits.
- fn base(&self) -> u8;
+ const BASE: u8;
/// A radix-specific prefix string.
- fn prefix(&self) -> &'static str {
- ""
- }
+ const PREFIX: &'static str;
/// Converts an integer to corresponding radix digit.
- fn digit(&self, x: u8) -> u8;
+ fn digit(x: u8) -> u8;
/// Format an integer using the radix using a formatter.
fn fmt_int<T: Int>(&self, mut x: T, f: &mut fmt::Formatter) -> fmt::Result {
let is_nonnegative = x >= zero;
let mut buf = [0; 128];
let mut curr = buf.len();
- let base = T::from_u8(self.base());
+ let base = T::from_u8(Self::BASE);
if is_nonnegative {
// Accumulate each digit of the number from the least significant
// to the most significant figure.
for byte in buf.iter_mut().rev() {
- let n = x % base; // Get the current place value.
- x = x / base; // Deaccumulate the number.
- *byte = self.digit(n.to_u8()); // Store the digit in the buffer.
+ let n = x % base; // Get the current place value.
+ x = x / base; // Deaccumulate the number.
+ *byte = Self::digit(n.to_u8()); // Store the digit in the buffer.
curr -= 1;
if x == zero {
// No more digits left to accumulate.
} else {
// Do the same as above, but accounting for two's complement.
for byte in buf.iter_mut().rev() {
- let n = zero - (x % base); // Get the current place value.
- x = x / base; // Deaccumulate the number.
- *byte = self.digit(n.to_u8()); // Store the digit in the buffer.
+ let n = zero - (x % base); // Get the current place value.
+ x = x / base; // Deaccumulate the number.
+ *byte = Self::digit(n.to_u8()); // Store the digit in the buffer.
curr -= 1;
if x == zero {
// No more digits left to accumulate.
}
}
let buf = unsafe { str::from_utf8_unchecked(&buf[curr..]) };
- f.pad_integral(is_nonnegative, self.prefix(), buf)
+ f.pad_integral(is_nonnegative, Self::PREFIX, buf)
}
}
macro_rules! radix {
($T:ident, $base:expr, $prefix:expr, $($x:pat => $conv:expr),+) => {
impl GenericRadix for $T {
- fn base(&self) -> u8 { $base }
- fn prefix(&self) -> &'static str { $prefix }
- fn digit(&self, x: u8) -> u8 {
+ const BASE: u8 = $base;
+ const PREFIX: &'static str = $prefix;
+ fn digit(x: u8) -> u8 {
match x {
$($x => $conv,)+
- x => panic!("number not in the range 0..{}: {}", self.base() - 1, x),
+ x => panic!("number not in the range 0..{}: {}", Self::BASE - 1, x),
}
}
}
impl fmt::Debug for $T {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- fmt::Display::fmt(self, f)
+ if f.debug_lower_hex() {
+ fmt::LowerHex::fmt(self, f)
+ } else if f.debug_upper_hex() {
+ fmt::UpperHex::fmt(self, f)
+ } else {
+ fmt::Display::fmt(self, f)
+ }
}
}
}
#[allow(deprecated)]
pub use self::sip::SipHasher;
-#[unstable(feature = "sip_hash_13", issue = "34767")]
+#[unstable(feature = "hashmap_internals", issue = "0")]
#[allow(deprecated)]
-pub use self::sip::{SipHasher13, SipHasher24};
+#[doc(hidden)]
+pub use self::sip::SipHasher13;
mod sip;
/// (eg. `collections::HashMap` uses it by default).
///
/// See: <https://131002.net/siphash>
-#[unstable(feature = "sip_hash_13", issue = "34767")]
+#[unstable(feature = "hashmap_internals", issue = "0")]
#[rustc_deprecated(since = "1.13.0",
reason = "use `std::collections::hash_map::DefaultHasher` instead")]
#[derive(Debug, Clone, Default)]
+#[doc(hidden)]
pub struct SipHasher13 {
hasher: Hasher<Sip13Rounds>,
}
/// An implementation of SipHash 2-4.
///
/// See: <https://131002.net/siphash/>
-#[unstable(feature = "sip_hash_13", issue = "34767")]
+#[unstable(feature = "hashmap_internals", issue = "0")]
#[rustc_deprecated(since = "1.13.0",
reason = "use `std::collections::hash_map::DefaultHasher` instead")]
#[derive(Debug, Clone, Default)]
-pub struct SipHasher24 {
+struct SipHasher24 {
hasher: Hasher<Sip24Rounds>,
}
#[rustc_deprecated(since = "1.13.0",
reason = "use `std::collections::hash_map::DefaultHasher` instead")]
pub fn new_with_keys(key0: u64, key1: u64) -> SipHasher {
- SipHasher(SipHasher24::new_with_keys(key0, key1))
+ SipHasher(SipHasher24 {
+ hasher: Hasher::new_with_keys(key0, key1)
+ })
}
}
impl SipHasher13 {
/// Creates a new `SipHasher13` with the two initial keys set to 0.
#[inline]
- #[unstable(feature = "sip_hash_13", issue = "34767")]
+ #[unstable(feature = "hashmap_internals", issue = "0")]
#[rustc_deprecated(since = "1.13.0",
reason = "use `std::collections::hash_map::DefaultHasher` instead")]
pub fn new() -> SipHasher13 {
/// Creates a `SipHasher13` that is keyed off the provided keys.
#[inline]
- #[unstable(feature = "sip_hash_13", issue = "34767")]
+ #[unstable(feature = "hashmap_internals", issue = "0")]
#[rustc_deprecated(since = "1.13.0",
reason = "use `std::collections::hash_map::DefaultHasher` instead")]
pub fn new_with_keys(key0: u64, key1: u64) -> SipHasher13 {
}
}
-impl SipHasher24 {
- /// Creates a new `SipHasher24` with the two initial keys set to 0.
- #[inline]
- #[unstable(feature = "sip_hash_13", issue = "34767")]
- #[rustc_deprecated(since = "1.13.0",
- reason = "use `std::collections::hash_map::DefaultHasher` instead")]
- pub fn new() -> SipHasher24 {
- SipHasher24::new_with_keys(0, 0)
- }
-
- /// Creates a `SipHasher24` that is keyed off the provided keys.
- #[inline]
- #[unstable(feature = "sip_hash_13", issue = "34767")]
- #[rustc_deprecated(since = "1.13.0",
- reason = "use `std::collections::hash_map::DefaultHasher` instead")]
- pub fn new_with_keys(key0: u64, key1: u64) -> SipHasher24 {
- SipHasher24 {
- hasher: Hasher::new_with_keys(key0, key1)
- }
- }
-}
-
impl<S: Sip> Hasher<S> {
#[inline]
fn new_with_keys(key0: u64, key1: u64) -> Hasher<S> {
impl super::Hasher for SipHasher {
#[inline]
fn write(&mut self, msg: &[u8]) {
- self.0.write(msg)
+ self.0.hasher.write(msg)
}
#[inline]
fn finish(&self) -> u64 {
- self.0.finish()
+ self.0.hasher.finish()
}
}
-#[unstable(feature = "sip_hash_13", issue = "34767")]
+#[unstable(feature = "hashmap_internals", issue = "0")]
impl super::Hasher for SipHasher13 {
#[inline]
fn write(&mut self, msg: &[u8]) {
}
}
-#[unstable(feature = "sip_hash_13", issue = "34767")]
-impl super::Hasher for SipHasher24 {
- #[inline]
- fn write(&mut self, msg: &[u8]) {
- self.hasher.write(msg)
- }
-
- #[inline]
- fn finish(&self) -> u64 {
- self.hasher.finish()
- }
-}
-
impl<S: Sip> super::Hasher for Hasher<S> {
// see short_write comment for explanation
#[inline]
/// ```
#[macro_export]
#[stable(feature = "rust1", since = "1.0.0")]
+#[cfg(stage0)]
macro_rules! assert {
($cond:expr) => (
if !$cond {
($file:expr) => ({ /* compiler built-in */ });
($file:expr,) => ({ /* compiler built-in */ });
}
+
+ /// Ensure that a boolean expression is `true` at runtime.
+ ///
+ /// For more information, see the documentation for [`std::assert!`].
+ ///
+ /// [`std::assert!`]: ../std/macro.assert.html
+ #[macro_export]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ #[cfg(dox)]
+ macro_rules! assert {
+ ($cond:expr) => ({ /* compiler built-in */ });
+ ($cond:expr,) => ({ /* compiler built-in */ });
+ ($cond:expr, $($arg:tt)+) => ({ /* compiler built-in */ });
+ }
}
unsafe impl<T: ?Sized> Freeze for *mut T {}
unsafe impl<'a, T: ?Sized> Freeze for &'a T {}
unsafe impl<'a, T: ?Sized> Freeze for &'a mut T {}
+
+/// Types which can be moved out of a `Pin`.
+///
+/// The `Unpin` trait is used to control the behavior of the [`Pin`] type. If a
+/// type implements `Unpin`, it is safe to move a value of that type out of the
+/// `Pin` pointer.
+///
+/// This trait is automatically implemented for almost every type.
+#[unstable(feature = "pin", issue = "49150")]
+pub unsafe auto trait Unpin {}
use fmt;
use hash;
use intrinsics;
-use marker::{Copy, PhantomData, Sized};
+use marker::{Copy, PhantomData, Sized, Unpin, Unsize};
use ptr;
-use ops::{Deref, DerefMut};
+use ops::{Deref, DerefMut, CoerceUnsized};
#[stable(feature = "rust1", since = "1.0.0")]
pub use intrinsics::transmute;
pub unsafe fn unreachable() -> ! {
intrinsics::unreachable()
}
+
+/// A pinned reference.
+///
+/// A pinned reference is a lot like a mutable reference, except that it is not
+/// safe to move a value out of a pinned reference unless the type of that
+/// value implements the `Unpin` trait.
+#[unstable(feature = "pin", issue = "49150")]
+#[fundamental]
+pub struct Pin<'a, T: ?Sized + 'a> {
+ inner: &'a mut T,
+}
+
+#[unstable(feature = "pin", issue = "49150")]
+impl<'a, T: ?Sized + Unpin> Pin<'a, T> {
+ /// Construct a new `Pin` around a reference to some data of a type that
+ /// implements `Unpin`.
+ #[unstable(feature = "pin", issue = "49150")]
+ pub fn new(reference: &'a mut T) -> Pin<'a, T> {
+ Pin { inner: reference }
+ }
+}
+
+
+#[unstable(feature = "pin", issue = "49150")]
+impl<'a, T: ?Sized> Pin<'a, T> {
+ /// Construct a new `Pin` around a reference to some data of a type that
+ /// may or may not implement `Unpin`.
+ ///
+ /// This constructor is unsafe because we do not know what will happen with
+ /// that data after the reference ends. If you cannot guarantee that the
+ /// data will never move again, calling this constructor is invalid.
+ #[unstable(feature = "pin", issue = "49150")]
+ pub unsafe fn new_unchecked(reference: &'a mut T) -> Pin<'a, T> {
+ Pin { inner: reference }
+ }
+
+ /// Borrow a Pin for a shorter lifetime than it already has.
+ #[unstable(feature = "pin", issue = "49150")]
+ pub fn borrow<'b>(this: &'b mut Pin<'a, T>) -> Pin<'b, T> {
+ Pin { inner: this.inner }
+ }
+
+ /// Get a mutable reference to the data inside of this `Pin`.
+ ///
+ /// This function is unsafe. You must guarantee that you will never move
+ /// the data out of the mutable reference you receive when you call this
+ /// function.
+ #[unstable(feature = "pin", issue = "49150")]
+ pub unsafe fn get_mut<'b>(this: &'b mut Pin<'a, T>) -> &'b mut T {
+ this.inner
+ }
+
+ /// Construct a new pin by mapping the interior value.
+ ///
+ /// For example, if you wanted to get a `Pin` of a field of something, you
+ /// could use this to get access to that field in one line of code.
+ ///
+ /// This function is unsafe. You must guarantee that the data you return
+ /// will not move so long as the argument value does not move (for example,
+ /// because it is one of the fields of that value), and also that you do
+ /// not move out of the argument you receive to the interior function.
+ #[unstable(feature = "pin", issue = "49150")]
+ pub unsafe fn map<'b, U, F>(this: &'b mut Pin<'a, T>, f: F) -> Pin<'b, U> where
+ F: FnOnce(&mut T) -> &mut U
+ {
+ Pin { inner: f(this.inner) }
+ }
+}
+
+#[unstable(feature = "pin", issue = "49150")]
+impl<'a, T: ?Sized> Deref for Pin<'a, T> {
+ type Target = T;
+
+ fn deref(&self) -> &T {
+ &*self.inner
+ }
+}
+
+#[unstable(feature = "pin", issue = "49150")]
+impl<'a, T: ?Sized + Unpin> DerefMut for Pin<'a, T> {
+ fn deref_mut(&mut self) -> &mut T {
+ self.inner
+ }
+}
+
+#[unstable(feature = "pin", issue = "49150")]
+impl<'a, T: fmt::Debug + ?Sized> fmt::Debug for Pin<'a, T> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ fmt::Debug::fmt(&**self, f)
+ }
+}
+
+#[unstable(feature = "pin", issue = "49150")]
+impl<'a, T: fmt::Display + ?Sized> fmt::Display for Pin<'a, T> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ fmt::Display::fmt(&**self, f)
+ }
+}
+
+#[unstable(feature = "pin", issue = "49150")]
+impl<'a, T: ?Sized> fmt::Pointer for Pin<'a, T> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ fmt::Pointer::fmt(&(&*self.inner as *const T), f)
+ }
+}
+
+#[unstable(feature = "pin", issue = "49150")]
+impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Pin<'a, U>> for Pin<'a, T> {}
}
forward_ref_unop! { impl Neg, neg for Wrapping<$t>,
#[stable(feature = "wrapping_ref", since = "1.14.0")] }
+
)*)
}
wrapping_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
+macro_rules! wrapping_int_impl {
+ ($($t:ty)*) => ($(
+ impl Wrapping<$t> {
+ /// Returns the number of ones in the binary representation of
+ /// `self`.
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// #![feature(wrapping_int_impl)]
+ /// use std::num::Wrapping;
+ ///
+ /// let n: Wrapping<i8> = Wrapping(-0b1000_0000);
+ ///
+ /// assert_eq!(n.count_ones(), 1);
+ /// ```
+ #[inline]
+ #[unstable(feature = "wrapping_int_impl", issue = "32463")]
+ pub fn count_ones(self) -> u32 {
+ self.0.count_ones()
+ }
+
+ /// Returns the number of zeros in the binary representation of
+ /// `self`.
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// #![feature(wrapping_int_impl)]
+ /// use std::num::Wrapping;
+ ///
+ /// let n: Wrapping<i8> = Wrapping(-0b1000_0000);
+ ///
+ /// assert_eq!(n.count_zeros(), 7);
+ /// ```
+ #[inline]
+ #[unstable(feature = "wrapping_int_impl", issue = "32463")]
+ pub fn count_zeros(self) -> u32 {
+ self.0.count_zeros()
+ }
+
+ /// Returns the number of leading zeros in the binary representation
+ /// of `self`.
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// #![feature(wrapping_int_impl)]
+ /// use std::num::Wrapping;
+ ///
+ /// let n: Wrapping<i16> = Wrapping(-1);
+ ///
+ /// assert_eq!(n.leading_zeros(), 0);
+ /// ```
+ #[inline]
+ #[unstable(feature = "wrapping_int_impl", issue = "32463")]
+ pub fn leading_zeros(self) -> u32 {
+ self.0.leading_zeros()
+ }
+
+ /// Returns the number of trailing zeros in the binary representation
+ /// of `self`.
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// #![feature(wrapping_int_impl)]
+ /// use std::num::Wrapping;
+ ///
+ /// let n: Wrapping<i8> = Wrapping(-4);
+ ///
+ /// assert_eq!(n.trailing_zeros(), 2);
+ /// ```
+ #[inline]
+ #[unstable(feature = "wrapping_int_impl", issue = "32463")]
+ pub fn trailing_zeros(self) -> u32 {
+ self.0.trailing_zeros()
+ }
+
+ /// Shifts the bits to the left by a specified amount, `n`,
+ /// wrapping the truncated bits to the end of the resulting
+ /// integer.
+ ///
+ /// Please note this isn't the same operation as `>>`!
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// #![feature(wrapping_int_impl)]
+ /// use std::num::Wrapping;
+ ///
+ /// let n: Wrapping<i64> = Wrapping(0x0123456789ABCDEF);
+ /// let m: Wrapping<i64> = Wrapping(-0x76543210FEDCBA99);
+ ///
+ /// assert_eq!(n.rotate_left(32), m);
+ /// ```
+ #[inline]
+ #[unstable(feature = "wrapping_int_impl", issue = "32463")]
+ pub fn rotate_left(self, n: u32) -> Self {
+ Wrapping(self.0.rotate_left(n))
+ }
+
+ /// Shifts the bits to the right by a specified amount, `n`,
+ /// wrapping the truncated bits to the beginning of the resulting
+ /// integer.
+ ///
+ /// Please note this isn't the same operation as `<<`!
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// #![feature(wrapping_int_impl)]
+ /// use std::num::Wrapping;
+ ///
+ /// let n: Wrapping<i64> = Wrapping(0x0123456789ABCDEF);
+ /// let m: Wrapping<i64> = Wrapping(-0xFEDCBA987654322);
+ ///
+ /// assert_eq!(n.rotate_right(4), m);
+ /// ```
+ #[inline]
+ #[unstable(feature = "wrapping_int_impl", issue = "32463")]
+ pub fn rotate_right(self, n: u32) -> Self {
+ Wrapping(self.0.rotate_right(n))
+ }
+
+ /// Reverses the byte order of the integer.
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// #![feature(wrapping_int_impl)]
+ /// use std::num::Wrapping;
+ ///
+ /// let n: Wrapping<i16> = Wrapping(0b0000000_01010101);
+ /// assert_eq!(n, Wrapping(85));
+ ///
+ /// let m = n.swap_bytes();
+ ///
+ /// assert_eq!(m, Wrapping(0b01010101_00000000));
+ /// assert_eq!(m, Wrapping(21760));
+ /// ```
+ #[inline]
+ #[unstable(feature = "wrapping_int_impl", issue = "32463")]
+ pub fn swap_bytes(self) -> Self {
+ Wrapping(self.0.swap_bytes())
+ }
+
+ /// Converts an integer from big endian to the target's endianness.
+ ///
+ /// On big endian this is a no-op. On little endian the bytes are
+ /// swapped.
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// #![feature(wrapping_int_impl)]
+ /// use std::num::Wrapping;
+ ///
+ /// let n: Wrapping<i64> = Wrapping(0x0123456789ABCDEF);
+ ///
+ /// if cfg!(target_endian = "big") {
+ /// assert_eq!(Wrapping::<i64>::from_be(n), n);
+ /// } else {
+ /// assert_eq!(Wrapping::<i64>::from_be(n), n.swap_bytes());
+ /// }
+ /// ```
+ #[inline]
+ #[unstable(feature = "wrapping_int_impl", issue = "32463")]
+ pub fn from_be(x: Self) -> Self {
+ Wrapping(<$t>::from_be(x.0))
+ }
+
+ /// Converts an integer from little endian to the target's endianness.
+ ///
+ /// On little endian this is a no-op. On big endian the bytes are
+ /// swapped.
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// #![feature(wrapping_int_impl)]
+ /// use std::num::Wrapping;
+ ///
+ /// let n: Wrapping<i64> = Wrapping(0x0123456789ABCDEF);
+ ///
+ /// if cfg!(target_endian = "little") {
+ /// assert_eq!(Wrapping::<i64>::from_le(n), n);
+ /// } else {
+ /// assert_eq!(Wrapping::<i64>::from_le(n), n.swap_bytes());
+ /// }
+ /// ```
+ #[inline]
+ #[unstable(feature = "wrapping_int_impl", issue = "32463")]
+ pub fn from_le(x: Self) -> Self {
+ Wrapping(<$t>::from_le(x.0))
+ }
+
+ /// Converts `self` to big endian from the target's endianness.
+ ///
+ /// On big endian this is a no-op. On little endian the bytes are
+ /// swapped.
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// #![feature(wrapping_int_impl)]
+ /// use std::num::Wrapping;
+ ///
+ /// let n: Wrapping<i64> = Wrapping(0x0123456789ABCDEF);
+ ///
+ /// if cfg!(target_endian = "big") {
+ /// assert_eq!(n.to_be(), n);
+ /// } else {
+ /// assert_eq!(n.to_be(), n.swap_bytes());
+ /// }
+ /// ```
+ #[inline]
+ #[unstable(feature = "wrapping_int_impl", issue = "32463")]
+ pub fn to_be(self) -> Self {
+ Wrapping(self.0.to_be())
+ }
+
+ /// Converts `self` to little endian from the target's endianness.
+ ///
+ /// On little endian this is a no-op. On big endian the bytes are
+ /// swapped.
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// #![feature(wrapping_int_impl)]
+ /// use std::num::Wrapping;
+ ///
+ /// let n: Wrapping<i64> = Wrapping(0x0123456789ABCDEF);
+ ///
+ /// if cfg!(target_endian = "little") {
+ /// assert_eq!(n.to_le(), n);
+ /// } else {
+ /// assert_eq!(n.to_le(), n.swap_bytes());
+ /// }
+ /// ```
+ #[inline]
+ #[unstable(feature = "wrapping_int_impl", issue = "32463")]
+ pub fn to_le(self) -> Self {
+ Wrapping(self.0.to_le())
+ }
+
+ /// Raises self to the power of `exp`, using exponentiation by
+ /// squaring.
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// #![feature(wrapping_int_impl)]
+ /// use std::num::Wrapping;
+ ///
+ /// let x: Wrapping<i32> = Wrapping(2); // or any other integer type
+ ///
+ /// assert_eq!(x.pow(4), Wrapping(16));
+ /// ```
+ ///
+ /// Results that are too large are wrapped:
+ ///
+ /// ```
+ /// #![feature(wrapping_int_impl)]
+ /// use std::num::Wrapping;
+ ///
+ /// // 5 ^ 4 = 625, which is too big for a u8
+ /// let x: Wrapping<u8> = Wrapping(5);
+ ///
+ /// assert_eq!(x.pow(4).0, 113);
+ /// ```
+ #[inline]
+ #[unstable(feature = "wrapping_int_impl", issue = "32463")]
+ pub fn pow(self, exp: u32) -> Self {
+ Wrapping(self.0.wrapping_pow(exp))
+ }
+ }
+ )*)
+}
+
+wrapping_int_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
+
+
mod shift_max {
#![allow(non_upper_case_globals)]
assert!(format!("{}", i32::MIN) == "-2147483648");
assert!(format!("{}", i64::MIN) == "-9223372036854775808");
}
+
+#[test]
+fn test_format_debug_hex() {
+ assert!(format!("{:02x?}", b"Foo\0") == "[46, 6f, 6f, 00]");
+ assert!(format!("{:02X?}", b"Foo\0") == "[46, 6F, 6F, 00]");
+}
#![allow(deprecated)]
use core::hash::{Hash, Hasher};
-use core::hash::{SipHasher, SipHasher13, SipHasher24};
+use core::hash::{SipHasher, SipHasher13};
use core::{slice, mem};
// Hash just the bytes of the slice, without length prefix
let k1 = 0x_0f_0e_0d_0c_0b_0a_09_08;
let mut buf = Vec::new();
let mut t = 0;
- let mut state_inc = SipHasher24::new_with_keys(k0, k1);
+ let mut state_inc = SipHasher::new_with_keys(k0, k1);
while t < 64 {
let vec = u8to64_le!(vecs[t], 0);
- let out = hash_with(SipHasher24::new_with_keys(k0, k1), &Bytes(&buf));
+ let out = hash_with(SipHasher::new_with_keys(k0, k1), &Bytes(&buf));
assert_eq!(vec, out);
- let full = hash_with(SipHasher24::new_with_keys(k0, k1), &Bytes(&buf));
+ let full = hash_with(SipHasher::new_with_keys(k0, k1), &Bytes(&buf));
let i = state_inc.finish();
assert_eq!(full, i);
#[test]
fn test_write_short_works() {
let test_usize = 0xd0c0b0a0usize;
- let mut h1 = SipHasher24::new();
+ let mut h1 = SipHasher::new();
h1.write_usize(test_usize);
h1.write(b"bytes");
h1.write(b"string");
h1.write_u8(0xFFu8);
h1.write_u8(0x01u8);
- let mut h2 = SipHasher24::new();
+ let mut h2 = SipHasher::new();
h2.write(unsafe {
slice::from_raw_parts(&test_usize as *const _ as *const u8,
mem::size_of::<usize>())
#![feature(fixed_size_array)]
#![feature(flt2dec)]
#![feature(fmt_internals)]
+#![feature(hashmap_internals)]
#![feature(iterator_step_by)]
#![feature(i128_type)]
#![cfg_attr(stage0, feature(inclusive_range_syntax))]
#![feature(range_is_empty)]
#![feature(raw)]
#![feature(refcell_replace_swap)]
-#![feature(sip_hash_13)]
#![feature(slice_patterns)]
+#![feature(slice_rotate)]
#![feature(sort_internals)]
#![feature(specialization)]
#![feature(step_trait)]
/// For numbers, this means that the number will be padded with zeroes,
/// and the sign (`+` or `-`) will precede them.
FlagSignAwareZeroPad,
+ /// For Debug / `?`, format integers in lower-case hexadecimal.
+ FlagDebugLowerHex,
+ /// For Debug / `?`, format integers in upper-case hexadecimal.
+ FlagDebugUpperHex,
}
/// A count is used for the precision and width parameters of an integer, and
spec.precision = self.count();
}
}
- // Finally the actual format specifier
- if self.consume('?') {
+ // Optional radix followed by the actual format specifier
+ if self.consume('x') {
+ if self.consume('?') {
+ spec.flags |= 1 << (FlagDebugLowerHex as u32);
+ spec.ty = "?";
+ } else {
+ spec.ty = "x";
+ }
+ } else if self.consume('X') {
+ if self.consume('?') {
+ spec.flags |= 1 << (FlagDebugUpperHex as u32);
+ spec.ty = "?";
+ } else {
+ spec.ty = "X";
+ }
+ } else if self.consume('?') {
spec.ty = "?";
} else {
spec.ty = self.word();
Pound => op!('#'),
Dollar => op!('$'),
Question => op!('?'),
- Underscore => op!('_'),
Ident(ident) | Lifetime(ident) => TokenNode::Term(Term(ident.name)),
Literal(..) | DocComment(..) => TokenNode::Literal(self::Literal(token)),
'#' => Pound,
'$' => Dollar,
'?' => Question,
- '_' => Underscore,
_ => panic!("unsupported character {}", op),
};
#![deny(warnings)]
-#![feature(slice_patterns)]
#![feature(test)]
extern crate test;
-# Dependency graph for incremental compilation
+To learn more about how dependency tracking works in rustc, see the [rustc
+guide].
-This module contains the infrastructure for managing the incremental
-compilation dependency graph. This README aims to explain how it ought
-to be used. In this document, we'll first explain the overall
-strategy, and then share some tips for handling specific scenarios.
-
-The high-level idea is that we want to instrument the compiler to
-track which parts of the AST and other IR are read/written by what.
-This way, when we come back later, we can look at this graph and
-determine what work needs to be redone.
-
-### The dependency graph
-
-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 `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
- performing some kind of check for errors. You can think of them as
- computed values where the value being computed is `()` (and the
- value may fail to be computed, if an error results).
-
-An edge `N1 -> N2` is added between two nodes if either:
-
-- the value of `N1` is used to compute `N2`;
-- `N1` is read by the procedure `N2`;
-- the procedure `N1` writes the value `N2`.
-
-The latter two conditions are equivalent to the first one if you think
-of procedures as values.
-
-### Basic tracking
-
-There is a very general strategy to ensure that you have a correct, if
-sometimes overconservative, dependency graph. The two main things you have
-to do are (a) identify shared state and (b) identify the current tasks.
-
-### Identifying shared state
-
-Identify "shared state" that will be written by one pass and read by
-another. In particular, we need to identify shared state that will be
-read "across items" -- that is, anything where changes in one item
-could invalidate work done for other items. So, for example:
-
-1. The signature for a function is "shared state".
-2. The computed type of some expression in the body of a function is
- not shared state, because if it changes it does not itself
- invalidate other functions (though it may be that it causes new
- monomorphizations to occur, but that's handled independently).
-
-Put another way: if the HIR for an item changes, we are going to
-recompile that item for sure. But we need the dep tracking map to tell
-us what *else* we have to recompile. Shared state is anything that is
-used to communicate results from one item to another.
-
-### Identifying the current task, tracking reads/writes, etc
-
-FIXME(#42293). This text needs to be rewritten for the new red-green
-system, which doesn't fully exist yet.
-
-#### Dependency tracking map
-
-`DepTrackingMap` is a particularly convenient way to correctly store
-shared state. A `DepTrackingMap` is a special hashmap that will add
-edges automatically when `get` and `insert` are called. The idea is
-that, when you get/insert a value for the key `K`, we will add an edge
-from/to the node `DepNode::Variant(K)` (for some variant specific to
-the map).
-
-Each `DepTrackingMap` is parameterized by a special type `M` that
-implements `DepTrackingMapConfig`; this trait defines the key and value
-types of the map, and also defines a fn for converting from the key to
-a `DepNode` label. You don't usually have to muck about with this by
-hand, there is a macro for creating it. You can see the complete set
-of `DepTrackingMap` definitions in `librustc/middle/ty/maps.rs`.
-
-As an example, let's look at the `adt_defs` map. The `adt_defs` map
-maps from the def-id of a struct/enum to its `AdtDef`. It is defined
-using this macro:
-
-```rust
-dep_map_ty! { AdtDefs: ItemSignature(DefId) -> ty::AdtDefMaster<'tcx> }
-// ~~~~~~~ ~~~~~~~~~~~~~ ~~~~~ ~~~~~~~~~~~~~~~~~~~~~~
-// | | Key type Value type
-// | DepNode variant
-// Name of map id type
-```
-
-this indicates that a map id type `AdtDefs` will be created. The key
-of the map will be a `DefId` and value will be
-`ty::AdtDefMaster<'tcx>`. The `DepNode` will be created by
-`DepNode::ItemSignature(K)` for a given key.
-
-Once that is done, you can just use the `DepTrackingMap` like any
-other map:
-
-```rust
-let mut map: DepTrackingMap<M> = DepTrackingMap::new(dep_graph);
-map.insert(key, value); // registers dep_graph.write
-map.get(key; // registers dep_graph.read
-```
-
-#### Memoization
-
-One particularly interesting case is memoization. If you have some
-shared state that you compute in a memoized fashion, the correct thing
-to do is to define a `RefCell<DepTrackingMap>` for it and use the
-`memoize` helper:
-
-```rust
-map.memoize(key, || /* compute value */)
-```
-
-This will create a graph that looks like
-
- ... -> MapVariant(key) -> CurrentTask
-
-where `MapVariant` is the `DepNode` variant that the map is associated with,
-and `...` are whatever edges the `/* compute value */` closure creates.
-
-In particular, using the memoize helper is much better than writing
-the obvious code yourself:
-
-```rust
-if let Some(result) = map.get(key) {
- return result;
-}
-let value = /* compute value */;
-map.insert(key, value);
-```
-
-If you write that code manually, the dependency graph you get will
-include artificial edges that are not necessary. For example, imagine that
-two tasks, A and B, both invoke the manual memoization code, but A happens
-to go first. The resulting graph will be:
-
- ... -> A -> MapVariant(key) -> B
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~ // caused by A writing to MapVariant(key)
- ~~~~~~~~~~~~~~~~~~~~ // caused by B reading from MapVariant(key)
-
-This graph is not *wrong*, but it encodes a path from A to B that
-should not exist. In contrast, using the memoized helper, you get:
-
- ... -> MapVariant(key) -> A
- |
- +----------> B
-
-which is much cleaner.
-
-**Be aware though that the closure is executed with `MapVariant(key)`
-pushed onto the stack as the current task!** That means that you must
-add explicit `read` calls for any shared state that it accesses
-implicitly from its environment. See the section on "explicit calls to
-read and write when starting a new subtask" above for more details.
-
-### How to decide where to introduce a new task
-
-Certainly, you need at least one task on the stack: any attempt to
-`read` or `write` shared state will panic if there is no current
-task. But where does it make sense to introduce subtasks? The basic
-rule is that a subtask makes sense for any discrete unit of work you
-may want to skip in the future. Adding a subtask separates out the
-reads/writes from *that particular subtask* versus the larger
-context. An example: you might have a 'meta' task for all of borrow
-checking, and then subtasks for borrow checking individual fns. (Seen
-in this light, memoized computations are just a special case where we
-may want to avoid redoing the work even within the context of one
-compilation.)
-
-The other case where you might want a subtask is to help with refining
-the reads/writes for some later bit of work that needs to be memoized.
-For example, we create a subtask for type-checking the body of each
-fn. However, in the initial version of incr. comp. at least, we do
-not expect to actually *SKIP* type-checking -- we only expect to skip
-trans. However, it's still useful to create subtasks for type-checking
-individual items, because, otherwise, if a fn sig changes, we won't
-know which callers are affected -- in fact, because the graph would be
-so coarse, we'd just have to retrans everything, since we can't
-distinguish which fns used which fn sigs.
-
-### Testing the dependency graph
-
-There are various ways to write tests against the dependency graph.
-The simplest mechanism are the
-`#[rustc_if_this_changed]` and `#[rustc_then_this_would_need]`
-annotations. These are used in compile-fail tests to test whether the
-expected set of paths exist in the dependency graph. As an example,
-see `src/test/compile-fail/dep-graph-caller-callee.rs`.
-
-The idea is that you can annotate a test like:
-
-```rust
-#[rustc_if_this_changed]
-fn foo() { }
-
-#[rustc_then_this_would_need(TypeckTables)] //~ ERROR OK
-fn bar() { foo(); }
-
-#[rustc_then_this_would_need(TypeckTables)] //~ ERROR no path
-fn baz() { }
-```
-
-This will check whether there is a path in the dependency graph from
-`Hir(foo)` to `TypeckTables(bar)`. An error is reported for each
-`#[rustc_then_this_would_need]` annotation that indicates whether a
-path exists. `//~ ERROR` annotations can then be used to test if a
-path is found (as demonstrated above).
-
-### Debugging the dependency graph
-
-#### Dumping the graph
-
-The compiler is also capable of dumping the dependency graph for your
-debugging pleasure. To do so, pass the `-Z dump-dep-graph` flag. The
-graph will be dumped to `dep_graph.{txt,dot}` in the current
-directory. You can override the filename with the `RUST_DEP_GRAPH`
-environment variable.
-
-Frequently, though, the full dep graph is quite overwhelming and not
-particularly helpful. Therefore, the compiler also allows you to filter
-the graph. You can filter in three ways:
-
-1. All edges originating in a particular set of nodes (usually a single node).
-2. All edges reaching a particular set of nodes.
-3. All edges that lie between given start and end nodes.
-
-To filter, use the `RUST_DEP_GRAPH_FILTER` environment variable, which should
-look like one of the following:
-
-```
-source_filter // nodes originating from source_filter
--> target_filter // nodes that can reach target_filter
-source_filter -> target_filter // nodes in between source_filter and target_filter
-```
-
-`source_filter` and `target_filter` are a `&`-separated list of strings.
-A node is considered to match a filter if all of those strings appear in its
-label. So, for example:
-
-```
-RUST_DEP_GRAPH_FILTER='-> TypeckTables'
-```
-
-would select the predecessors of all `TypeckTables` nodes. Usually though you
-want the `TypeckTables` node for some particular fn, so you might write:
-
-```
-RUST_DEP_GRAPH_FILTER='-> TypeckTables & bar'
-```
-
-This will select only the `TypeckTables` nodes for fns with `bar` in their name.
-
-Perhaps you are finding that when you change `foo` you need to re-type-check `bar`,
-but you don't think you should have to. In that case, you might do:
-
-```
-RUST_DEP_GRAPH_FILTER='Hir&foo -> TypeckTables & bar'
-```
-
-This will dump out all the nodes that lead from `Hir(foo)` to
-`TypeckTables(bar)`, from which you can (hopefully) see the source
-of the erroneous edge.
-
-#### Tracking down incorrect edges
-
-Sometimes, after you dump the dependency graph, you will find some
-path that should not exist, but you will not be quite sure how it came
-to be. **When the compiler is built with debug assertions,** it can
-help you track that down. Simply set the `RUST_FORBID_DEP_GRAPH_EDGE`
-environment variable to a filter. Every edge created in the dep-graph
-will be tested against that filter -- if it matches, a `bug!` is
-reported, so you can easily see the backtrace (`RUST_BACKTRACE=1`).
-
-The syntax for these filters is the same as described in the previous
-section. However, note that this filter is applied to every **edge**
-and doesn't handle longer paths in the graph, unlike the previous
-section.
-
-Example:
-
-You find that there is a path from the `Hir` of `foo` to the type
-check of `bar` and you don't think there should be. You dump the
-dep-graph as described in the previous section and open `dep-graph.txt`
-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!
+[rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/query.html
[] GetSymbolExportLevel(DefId),
[input] Features,
+
+ [] ProgramClausesFor(DefId),
);
trait DepNodeParams<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> : fmt::Debug {
return None
}
None => {
- bug!("try_mark_green() - Forcing the DepNode \
- should have set its color")
+ if !tcx.sess.has_errors() {
+ bug!("try_mark_green() - Forcing the DepNode \
+ should have set its color")
+ } else {
+ // If the query we just forced has resulted
+ // in some kind of compilation error, we
+ // don't expect that the corresponding
+ // dep-node color has been updated.
+ }
}
}
} else {
transparent wrapper around a float. This can make a difference for the ABI.
"##,
+E0909: r##"
+The `impl Trait` return type captures lifetime parameters that do not
+appear within the `impl Trait` itself.
+
+Erroneous code example:
+
+```compile-fail,E0909
+#![feature(conservative_impl_trait)]
+
+use std::cell::Cell;
+
+trait Trait<'a> { }
+
+impl<'a, 'b> Trait<'b> for Cell<&'a u32> { }
+
+fn foo<'x, 'y>(x: Cell<&'x u32>) -> impl Trait<'y>
+where 'x: 'y
+{
+ x
+}
+```
+
+Here, the function `foo` returns a value of type `Cell<&'x u32>`,
+which references the lifetime `'x`. However, the return type is
+declared as `impl Trait<'y>` -- this indicates that `foo` returns
+"some type that implements `Trait<'y>`", but it also indicates that
+the return type **only captures data referencing the lifetime `'y`**.
+In this case, though, we are referencing data with lifetime `'x`, so
+this function is in error.
+
+To fix this, you must reference the lifetime `'x` from the return
+type. For example, changing the return type to `impl Trait<'y> + 'x`
+would work:
+
+```
+#![feature(conservative_impl_trait)]
+
+use std::cell::Cell;
+
+trait Trait<'a> { }
+
+impl<'a,'b> Trait<'b> for Cell<&'a u32> { }
+
+fn foo<'x, 'y>(x: Cell<&'x u32>) -> impl Trait<'y> + 'x
+where 'x: 'y
+{
+ x
+}
+```
+"##,
+
+
}
visitor.visit_vis(&item.vis);
visitor.visit_name(item.span, item.name);
match item.node {
- ItemExternCrate(opt_name) => {
+ ItemExternCrate(orig_name) => {
visitor.visit_id(item.id);
- if let Some(name) = opt_name {
- visitor.visit_name(item.span, name);
+ if let Some(orig_name) = orig_name {
+ visitor.visit_name(item.span, orig_name);
}
}
ItemUse(ref path, _) => {
TyKind::Slice(ref ty) => hir::TySlice(self.lower_ty(ty, itctx)),
TyKind::Ptr(ref mt) => hir::TyPtr(self.lower_mt(mt, itctx)),
TyKind::Rptr(ref region, ref mt) => {
- let span = t.span.with_hi(t.span.lo());
+ let span = t.span.shrink_to_lo();
let lifetime = match *region {
Some(ref lt) => self.lower_lifetime(lt),
None => self.elided_lifetime(span)
id: NodeId,
p: &Path,
name: Option<Name>,
- param_mode: ParamMode,
- defaults_to_global: bool)
+ param_mode: ParamMode)
-> hir::Path {
- let mut segments = p.segments.iter();
- if defaults_to_global && p.is_global() {
- segments.next();
- }
-
hir::Path {
def: self.expect_full_def(id),
- segments: segments.map(|segment| {
+ segments: p.segments.iter().map(|segment| {
self.lower_path_segment(p.span, segment, param_mode, 0,
ParenthesizedGenericArgs::Err,
ImplTraitContext::Disallowed)
fn lower_path(&mut self,
id: NodeId,
p: &Path,
- param_mode: ParamMode,
- defaults_to_global: bool)
+ param_mode: ParamMode)
-> hir::Path {
- self.lower_path_extra(id, p, None, param_mode, defaults_to_global)
+ self.lower_path_extra(id, p, None, param_mode)
}
fn lower_path_segment(&mut self,
i: &ItemKind)
-> hir::Item_ {
match *i {
- ItemKind::ExternCrate(string) => hir::ItemExternCrate(string),
+ ItemKind::ExternCrate(orig_name) => hir::ItemExternCrate(orig_name),
ItemKind::Use(ref use_tree) => {
// Start with an empty prefix
let prefix = Path {
let path = &tree.prefix;
match tree.kind {
- UseTreeKind::Simple(ident) => {
- *name = ident.name;
+ UseTreeKind::Simple(rename) => {
+ *name = tree.ident().name;
// First apply the prefix to the path
let mut path = Path {
if path.segments.len() > 1 &&
path.segments.last().unwrap().identifier.name == keywords::SelfValue.name() {
let _ = path.segments.pop();
- if ident.name == keywords::SelfValue.name() {
+ if rename.is_none() {
*name = path.segments.last().unwrap().identifier.name;
}
}
- let path = P(self.lower_path(id, &path, ParamMode::Explicit, true));
+ let path = P(self.lower_path(id, &path, ParamMode::Explicit));
hir::ItemUse(path, hir::UseKind::Single)
}
UseTreeKind::Glob => {
.cloned()
.collect(),
span: path.span,
- }, ParamMode::Explicit, true));
+ }, ParamMode::Explicit));
hir::ItemUse(path, hir::UseKind::Glob)
}
UseTreeKind::Nested(ref trees) => {
// Privatize the degenerate import base, used only to check
// the stability of `use a::{};`, to avoid it showing up as
// a re-export by accident when `pub`, e.g. in documentation.
- let path = P(self.lower_path(id, &prefix, ParamMode::Explicit, true));
+ let path = P(self.lower_path(id, &prefix, ParamMode::Explicit));
*vis = hir::Inherited;
hir::ItemUse(path, hir::UseKind::ListStem)
}
VisibilityKind::Crate(..) => hir::Visibility::Crate,
VisibilityKind::Restricted { ref path, id, .. } => {
hir::Visibility::Restricted {
- path: P(self.lower_path(id, path, ParamMode::Explicit, true)),
+ path: P(self.lower_path(id, path, ParamMode::Explicit)),
id: if let Some(owner) = explicit_owner {
self.lower_node_id_with_owner(id, owner).node_id
} else {
use self::LifetimeName::*;
match *self {
Implicit => keywords::Invalid.name(),
- Underscore => Symbol::intern("'_"),
+ Underscore => keywords::UnderscoreLifetime.name(),
Static => keywords::StaticLifetime.name(),
Name(name) => name,
}
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub enum Item_ {
- /// An `extern crate` item, with optional original crate name,
+ /// An `extern crate` item, with optional *original* crate name if the crate was renamed.
///
- /// e.g. `extern crate foo` or `extern crate foo_bar as foo`
+ /// E.g. `extern crate foo` or `extern crate foo_bar as foo`
ItemExternCrate(Option<Name>),
/// `use foo::bar::*;` or `use foo::bar::baz as quux;`
self.print_outer_attributes(&item.attrs)?;
self.ann.pre(self, NodeItem(item))?;
match item.node {
- hir::ItemExternCrate(ref optional_path) => {
+ hir::ItemExternCrate(orig_name) => {
self.head(&visibility_qualified(&item.vis, "extern crate"))?;
- if let Some(p) = *optional_path {
- let val = p.as_str();
- if val.contains("-") {
- self.print_string(&val, ast::StrStyle::Cooked)?;
- } else {
- self.print_name(p)?;
- }
+ if let Some(orig_name) = orig_name {
+ self.print_name(orig_name)?;
self.s.space()?;
self.s.word("as")?;
self.s.space()?;
}
impl_stable_hash_for!(enum hir::Item_ {
- ItemExternCrate(name),
+ ItemExternCrate(orig_name),
ItemUse(path, use_kind),
ItemStatic(ty, mutability, body_id),
ItemConst(ty, body_id),
token::Token::Pound |
token::Token::Dollar |
token::Token::Question |
- token::Token::Underscore |
token::Token::Whitespace |
token::Token::Comment |
token::Token::Eof => {}
src_hash.hash_stable(hcx, hasher);
// We only hash the relative position within this filemap
- let lines = lines.borrow();
- lines.len().hash_stable(hcx, hasher);
- for &line in lines.iter() {
- stable_byte_pos(line, start_pos).hash_stable(hcx, hasher);
- }
+ lines.with_lock(|lines| {
+ lines.len().hash_stable(hcx, hasher);
+ for &line in lines.iter() {
+ stable_byte_pos(line, start_pos).hash_stable(hcx, hasher);
+ }
+ });
// We only hash the relative position within this filemap
- let multibyte_chars = multibyte_chars.borrow();
- multibyte_chars.len().hash_stable(hcx, hasher);
- for &char_pos in multibyte_chars.iter() {
- stable_multibyte_char(char_pos, start_pos).hash_stable(hcx, hasher);
- }
+ multibyte_chars.with_lock(|multibyte_chars| {
+ multibyte_chars.len().hash_stable(hcx, hasher);
+ for &char_pos in multibyte_chars.iter() {
+ stable_multibyte_char(char_pos, start_pos).hash_stable(hcx, hasher);
+ }
+ });
- let non_narrow_chars = non_narrow_chars.borrow();
- non_narrow_chars.len().hash_stable(hcx, hasher);
- for &char_pos in non_narrow_chars.iter() {
- stable_non_narrow_char(char_pos, start_pos).hash_stable(hcx, hasher);
- }
+ non_narrow_chars.with_lock(|non_narrow_chars| {
+ non_narrow_chars.len().hash_stable(hcx, hasher);
+ for &char_pos in non_narrow_chars.iter() {
+ stable_non_narrow_char(char_pos, start_pos).hash_stable(hcx, hasher);
+ }
+ });
}
}
TyForeign(def_id) => {
def_id.hash_stable(hcx, hasher);
}
- TyInfer(..) => {
- bug!("ty::TypeVariants::hash_stable() - Unexpected variant {:?}.", *self)
+ TyInfer(infer_ty) => {
+ infer_ty.hash_stable(hcx, hasher);
}
}
}
}
+impl_stable_hash_for!(enum ty::InferTy {
+ TyVar(a),
+ IntVar(a),
+ FloatVar(a),
+ FreshTy(a),
+ FreshIntTy(a),
+ FreshFloatTy(a),
+ CanonicalTy(a),
+});
+
+impl<'a, 'gcx> HashStable<StableHashingContext<'a>>
+for ty::TyVid
+{
+ fn hash_stable<W: StableHasherResult>(&self,
+ _hcx: &mut StableHashingContext<'a>,
+ _hasher: &mut StableHasher<W>) {
+ // TyVid values are confined to an inference context and hence
+ // should not be hashed.
+ bug!("ty::TypeVariants::hash_stable() - can't hash a TyVid {:?}.", *self)
+ }
+}
+
+impl<'a, 'gcx> HashStable<StableHashingContext<'a>>
+for ty::IntVid
+{
+ fn hash_stable<W: StableHasherResult>(&self,
+ _hcx: &mut StableHashingContext<'a>,
+ _hasher: &mut StableHasher<W>) {
+ // IntVid values are confined to an inference context and hence
+ // should not be hashed.
+ bug!("ty::TypeVariants::hash_stable() - can't hash an IntVid {:?}.", *self)
+ }
+}
+
+impl<'a, 'gcx> HashStable<StableHashingContext<'a>>
+for ty::FloatVid
+{
+ fn hash_stable<W: StableHasherResult>(&self,
+ _hcx: &mut StableHashingContext<'a>,
+ _hasher: &mut StableHasher<W>) {
+ // FloatVid values are confined to an inference context and hence
+ // should not be hashed.
+ bug!("ty::TypeVariants::hash_stable() - can't hash a FloatVid {:?}.", *self)
+ }
+}
+
impl_stable_hash_for!(struct ty::ParamTy {
idx,
name
impl_stable_hash_for!(enum infer::canonical::Certainty {
Proven, Ambiguous
});
+
+impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for traits::WhereClauseAtom<'tcx> {
+ fn hash_stable<W: StableHasherResult>(&self,
+ hcx: &mut StableHashingContext<'a>,
+ hasher: &mut StableHasher<W>) {
+ use traits::WhereClauseAtom::*;
+
+ mem::discriminant(self).hash_stable(hcx, hasher);
+ match self {
+ Implemented(trait_ref) => trait_ref.hash_stable(hcx, hasher),
+ ProjectionEq(projection) => projection.hash_stable(hcx, hasher),
+ }
+ }
+}
+
+impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for traits::DomainGoal<'tcx> {
+ fn hash_stable<W: StableHasherResult>(&self,
+ hcx: &mut StableHashingContext<'a>,
+ hasher: &mut StableHasher<W>) {
+ use traits::DomainGoal::*;
+
+ mem::discriminant(self).hash_stable(hcx, hasher);
+ match self {
+ Holds(where_clause) |
+ WellFormed(where_clause) |
+ FromEnv(where_clause) => where_clause.hash_stable(hcx, hasher),
+
+ WellFormedTy(ty) => ty.hash_stable(hcx, hasher),
+ FromEnvTy(ty) => ty.hash_stable(hcx, hasher),
+ RegionOutlives(predicate) => predicate.hash_stable(hcx, hasher),
+ TypeOutlives(predicate) => predicate.hash_stable(hcx, hasher),
+ }
+ }
+}
+
+impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for traits::Goal<'tcx> {
+ fn hash_stable<W: StableHasherResult>(&self,
+ hcx: &mut StableHashingContext<'a>,
+ hasher: &mut StableHasher<W>) {
+ use traits::Goal::*;
+
+ mem::discriminant(self).hash_stable(hcx, hasher);
+ match self {
+ Implies(hypotheses, goal) => {
+ hypotheses.hash_stable(hcx, hasher);
+ goal.hash_stable(hcx, hasher);
+ },
+ And(goal1, goal2) => {
+ goal1.hash_stable(hcx, hasher);
+ goal2.hash_stable(hcx, hasher);
+ }
+ Not(goal) => goal.hash_stable(hcx, hasher),
+ DomainGoal(domain_goal) => domain_goal.hash_stable(hcx, hasher),
+ Quantified(quantifier, goal) => {
+ quantifier.hash_stable(hcx, hasher);
+ goal.hash_stable(hcx, hasher);
+ },
+ }
+ }
+}
+
+impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for traits::Clause<'tcx> {
+ fn hash_stable<W: StableHasherResult>(&self,
+ hcx: &mut StableHashingContext<'a>,
+ hasher: &mut StableHasher<W>) {
+ use traits::Clause::*;
+
+ mem::discriminant(self).hash_stable(hcx, hasher);
+ match self {
+ Implies(hypotheses, goal) => {
+ hypotheses.hash_stable(hcx, hasher);
+ goal.hash_stable(hcx, hasher);
+ }
+ DomainGoal(domain_goal) => domain_goal.hash_stable(hcx, hasher),
+ ForAll(clause) => clause.hash_stable(hcx, hasher),
+ }
+ }
+}
+
+impl_stable_hash_for!(enum traits::QuantifierKind {
+ Universal,
+ Existential
+});
use rustc_data_structures::fx::FxHashMap;
use syntax::ast;
use traits::{self, PredicateObligation};
-use ty::{self, Ty};
-use ty::fold::{BottomUpFolder, TypeFoldable};
+use ty::{self, Ty, TyCtxt};
+use ty::fold::{BottomUpFolder, TypeFoldable, TypeFolder};
use ty::outlives::Component;
-use ty::subst::{Kind, UnpackedKind, Substs};
+use ty::subst::{Kind, Substs, UnpackedKind};
use util::nodemap::DefIdMap;
pub type AnonTypeMap<'tcx> = DefIdMap<AnonTypeDecl<'tcx>>;
) -> InferOk<'tcx, (T, AnonTypeMap<'tcx>)> {
debug!(
"instantiate_anon_types(value={:?}, parent_def_id={:?}, body_id={:?}, param_env={:?})",
- value,
- parent_def_id,
- body_id,
- param_env,
+ value, parent_def_id, body_id, param_env,
);
let mut instantiator = Instantiator {
infcx: self,
// Convert the type from the function into a type valid outside
// the function, by replacing invalid regions with 'static,
// after producing an error for each of them.
- let definition_ty = gcx.fold_regions(&instantiated_ty, &mut false, |r, _| {
- match *r {
- // 'static and early-bound regions are valid.
- ty::ReStatic | ty::ReEmpty => r,
-
- // All other regions, we map them appropriately to their adjusted
- // indices, erroring if we find any lifetimes that were not mapped
- // into the new set.
- _ => if let Some(UnpackedKind::Lifetime(r1)) = map.get(&r.into())
- .map(|k| k.unpack()) {
- r1
- } else {
- // No mapping was found. This means that
- // it is either a disallowed lifetime,
- // which will be caught by regionck, or it
- // is a region in a non-upvar closure
- // generic, which is explicitly
- // allowed. If that surprises you, read
- // on.
- //
- // The case of closure is a somewhat
- // subtle (read: hacky) consideration. The
- // problem is that our closure types
- // currently include all the lifetime
- // parameters declared on the enclosing
- // function, even if they are unused by
- // the closure itself. We can't readily
- // filter them out, so here we replace
- // those values with `'empty`. This can't
- // really make a difference to the rest of
- // the compiler; those regions are ignored
- // for the outlives relation, and hence
- // don't affect trait selection or auto
- // traits, and they are erased during
- // trans.
- gcx.types.re_empty
- },
- }
- });
-
+ let definition_ty =
+ instantiated_ty.fold_with(&mut ReverseMapper::new(
+ self.tcx,
+ self.is_tainted_by_errors(),
+ def_id,
+ map,
+ instantiated_ty,
+ ));
debug!(
"infer_anon_definition_from_instantiation: definition_ty={:?}",
definition_ty
);
+ // We can unwrap here because our reverse mapper always
+ // produces things with 'gcx lifetime, though the type folder
+ // obscures that.
+ let definition_ty = gcx.lift(&definition_ty).unwrap();
+
definition_ty
}
}
+struct ReverseMapper<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
+ tcx: TyCtxt<'cx, 'gcx, 'tcx>,
+
+ /// If errors have already been reported in this fn, we suppress
+ /// our own errors because they are sometimes derivative.
+ tainted_by_errors: bool,
+
+ anon_type_def_id: DefId,
+ map: FxHashMap<Kind<'tcx>, Kind<'gcx>>,
+ map_missing_regions_to_empty: bool,
+
+ /// initially `Some`, set to `None` once error has been reported
+ hidden_ty: Option<Ty<'tcx>>,
+}
+
+impl<'cx, 'gcx, 'tcx> ReverseMapper<'cx, 'gcx, 'tcx> {
+ fn new(
+ tcx: TyCtxt<'cx, 'gcx, 'tcx>,
+ tainted_by_errors: bool,
+ anon_type_def_id: DefId,
+ map: FxHashMap<Kind<'tcx>, Kind<'gcx>>,
+ hidden_ty: Ty<'tcx>,
+ ) -> Self {
+ Self {
+ tcx,
+ tainted_by_errors,
+ anon_type_def_id,
+ map,
+ map_missing_regions_to_empty: false,
+ hidden_ty: Some(hidden_ty),
+ }
+ }
+
+ fn fold_kind_mapping_missing_regions_to_empty(&mut self, kind: Kind<'tcx>) -> Kind<'tcx> {
+ assert!(!self.map_missing_regions_to_empty);
+ self.map_missing_regions_to_empty = true;
+ let kind = kind.fold_with(self);
+ self.map_missing_regions_to_empty = false;
+ kind
+ }
+
+ fn fold_kind_normally(&mut self, kind: Kind<'tcx>) -> Kind<'tcx> {
+ assert!(!self.map_missing_regions_to_empty);
+ kind.fold_with(self)
+ }
+}
+
+impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for ReverseMapper<'cx, 'gcx, 'tcx> {
+ fn tcx(&self) -> TyCtxt<'_, 'gcx, 'tcx> {
+ self.tcx
+ }
+
+ fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
+ match r {
+ // ignore bound regions that appear in the type (e.g., this
+ // would ignore `'r` in a type like `for<'r> fn(&'r u32)`.
+ ty::ReLateBound(..) => return r,
+
+ // ignore `'static`, as that can appear anywhere
+ ty::ReStatic => return r,
+
+ _ => { }
+ }
+
+ match self.map.get(&r.into()).map(|k| k.unpack()) {
+ Some(UnpackedKind::Lifetime(r1)) => r1,
+ Some(u) => panic!("region mapped to unexpected kind: {:?}", u),
+ None => {
+ if !self.map_missing_regions_to_empty && !self.tainted_by_errors {
+ if let Some(hidden_ty) = self.hidden_ty.take() {
+ let span = self.tcx.def_span(self.anon_type_def_id);
+ let mut err = struct_span_err!(
+ self.tcx.sess,
+ span,
+ E0909,
+ "hidden type for `impl Trait` captures lifetime that \
+ does not appear in bounds",
+ );
+
+ // Assuming regionck succeeded, then we must
+ // be capturing *some* region from the fn
+ // header, and hence it must be free, so it's
+ // ok to invoke this fn (which doesn't accept
+ // all regions, and would ICE if an
+ // inappropriate region is given). We check
+ // `is_tainted_by_errors` by errors above, so
+ // we don't get in here unless regionck
+ // succeeded. (Note also that if regionck
+ // failed, then the regions we are attempting
+ // to map here may well be giving errors
+ // *because* the constraints were not
+ // satisfiable.)
+ self.tcx.note_and_explain_free_region(
+ &mut err,
+ &format!("hidden type `{}` captures ", hidden_ty),
+ r,
+ ""
+ );
+
+ err.emit();
+ }
+ }
+ self.tcx.types.re_empty
+ },
+ }
+ }
+
+ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
+ match ty.sty {
+ ty::TyClosure(def_id, substs) => {
+ // I am a horrible monster and I pray for death. When
+ // we encounter a closure here, it is always a closure
+ // from within the function that we are currently
+ // type-checking -- one that is now being encapsulated
+ // in an existential abstract type. Ideally, we would
+ // go through the types/lifetimes that it references
+ // and treat them just like we would any other type,
+ // which means we would error out if we find any
+ // reference to a type/region that is not in the
+ // "reverse map".
+ //
+ // **However,** in the case of closures, there is a
+ // somewhat subtle (read: hacky) consideration. The
+ // problem is that our closure types currently include
+ // all the lifetime parameters declared on the
+ // enclosing function, even if they are unused by the
+ // closure itself. We can't readily filter them out,
+ // so here we replace those values with `'empty`. This
+ // can't really make a difference to the rest of the
+ // compiler; those regions are ignored for the
+ // outlives relation, and hence don't affect trait
+ // selection or auto traits, and they are erased
+ // during trans.
+
+ let generics = self.tcx.generics_of(def_id);
+ let parent_len = generics.parent_count();
+ let substs = self.tcx.mk_substs(substs.substs.iter().enumerate().map(
+ |(index, &kind)| {
+ if index < parent_len {
+ // Accommodate missing regions in the parent kinds...
+ self.fold_kind_mapping_missing_regions_to_empty(kind)
+ } else {
+ // ...but not elsewhere.
+ self.fold_kind_normally(kind)
+ }
+ },
+ ));
+
+ self.tcx.mk_closure(def_id, ty::ClosureSubsts { substs })
+ }
+
+ _ => ty.super_fold_with(self),
+ }
+ }
+}
+
struct Instantiator<'a, 'gcx: 'tcx, 'tcx: 'a> {
infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
parent_def_id: DefId,
return self.fold_anon_ty(ty, def_id, substs);
}
- debug!("instantiate_anon_types_in_map: \
- encountered anon with wrong parent \
- def_id={:?} \
- anon_parent_def_id={:?}",
- def_id,
- anon_parent_def_id);
+ debug!(
+ "instantiate_anon_types_in_map: \
+ encountered anon with wrong parent \
+ def_id={:?} \
+ anon_parent_def_id={:?}",
+ def_id, anon_parent_def_id
+ );
}
}
debug!(
"instantiate_anon_types: TyAnon(def_id={:?}, substs={:?})",
- def_id,
- substs
+ def_id, substs
);
// Use the same type variable if the exact same TyAnon appears more
return anon_defn.concrete_ty;
}
let span = tcx.def_span(def_id);
- let ty_var = infcx.next_ty_var(ty::UniverseIndex::ROOT,
- TypeVariableOrigin::TypeInference(span));
+ let ty_var = infcx.next_ty_var(
+ ty::UniverseIndex::ROOT,
+ TypeVariableOrigin::TypeInference(span),
+ );
let predicates_of = tcx.predicates_of(def_id);
let bounds = predicates_of.instantiate(tcx, substs);
use ty::{self, CanonicalVar, Lift, Region, Slice, Ty, TyCtxt, TypeFlags};
use ty::subst::{Kind, UnpackedKind};
use ty::fold::{TypeFoldable, TypeFolder};
+use util::captures::Captures;
use util::common::CellUsizeExt;
use rustc_data_structures::indexed_vec::IndexVec;
param_env: ty::ParamEnv<'tcx>,
unsubstituted_region_constraints: &'a QueryRegionConstraints<'tcx>,
result_subst: &'a CanonicalVarValues<'tcx>,
- ) -> impl Iterator<Item = PredicateObligation<'tcx>> + 'a {
+ ) -> impl Iterator<Item = PredicateObligation<'tcx>> + Captures<'gcx> + 'a {
let QueryRegionConstraints {
region_outlives,
ty_outlives,
/// the pop occurs as part of the rollback, so an explicit call is not
/// needed (but is also permitted).
///
- /// See `README.md` for more details.
+ /// For more information about how skolemization for HRTBs works, see
+ /// the [rustc guide].
+ ///
+ /// [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/trait-hrtb.html
pub fn skolemize_late_bound_regions<T>(&self,
binder: &ty::Binder<T>,
snapshot: &CombinedSnapshot<'a, 'tcx>)
# Region inference
+> WARNING: This README is obsolete and will be removed soon! For
+> more info on how the current borrowck works, see the [rustc guide].
+
+[rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/mir-borrowck.html
+
## Terminology
Note that we use the terms region and lifetime interchangeably.
## Introduction
-See the [general inference README](../README.md) for an overview of
-how lexical-region-solving fits into the bigger picture.
-
Region inference uses a somewhat more involved algorithm than type
inference. It is not the most efficient thing ever written though it
seems to work well enough in practice (famous last words). The reason
# Region constraint collection
+> WARNING: This README is obsolete and will be removed soon! For
+> more info on how the current borrowck works, see the [rustc guide].
+
+[rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/mir-borrowck.html
+
## Terminology
Note that we use the terms region and lifetime interchangeably.
## Introduction
-As described in the [inference README](../README.md), and unlike
+As described in the rustc guide [chapter on type inference][ti], and unlike
normal type inference, which is similar in spirit to H-M and thus
works progressively, the region type inference works by accumulating
constraints over the course of a function. Finally, at the end of
processing a function, we process and solve the constraints all at
once.
+[ti]: https://rust-lang-nursery.github.io/rustc-guide/type-inference.html
+
The constraints are always of one of three possible forms:
- `ConstrainVarSubVar(Ri, Rj)` states that region variable Ri must be
/// the APIs in `higher_ranked/mod.rs`, such as
/// `skolemize_late_bound_regions` and `plug_leaks`, which will
/// guide you on this path (ensure that the `SkolemizationMap` is
- /// consumed and you are good). There are also somewhat extensive
- /// comments in `higher_ranked/README.md`.
+ /// consumed and you are good). For more info on how skolemization
+ /// for HRTBs works, see the [rustc guide].
+ ///
+ /// [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/trait-hrtb.html
///
/// The `snapshot` argument to this function is not really used;
/// it's just there to make it explicit which snapshot bounds the
pub mod ty;
pub mod util {
+ pub mod captures;
pub mod common;
pub mod ppaux;
pub mod nodemap;
#[macro_export]
macro_rules! impl_stable_hash_for {
- (enum $enum_name:path { $( $variant:ident $( ( $($arg:ident),* ) )* ),* }) => {
+ (enum $enum_name:path { $( $variant:ident $( ( $($arg:ident),* ) )* ),* $(,)* }) => {
impl<'a, 'tcx> ::rustc_data_structures::stable_hasher::HashStable<$crate::ich::StableHashingContext<'a>> for $enum_name {
#[inline]
fn hash_stable<W: ::rustc_data_structures::stable_hasher::StableHasherResult>(&self,
fn visit_arm<'a, 'tcx>(ir: &mut IrMaps<'a, 'tcx>, arm: &'tcx hir::Arm) {
for pat in &arm.pats {
- // for struct patterns, take note of which fields used shorthand (`x`
- // rather than `x: x`)
+ // for struct patterns, take note of which fields used shorthand (`x` rather than `x: x`)
//
- // FIXME: according to the rust-lang-nursery/rustc-guide book and
- // librustc/README.md, `NodeId`s are to be phased out in favor of
- // `HirId`s; however, we need to match the signature of `each_binding`,
+ // FIXME: according to the rust-lang-nursery/rustc-guide book, `NodeId`s are to be phased
+ // out in favor of `HirId`s; however, we need to match the signature of `each_binding`,
// which uses `NodeIds`.
let mut shorthand_field_ids = NodeSet();
if let hir::PatKind::Struct(_, ref fields, _) = pat.node {
//! This file builds up the `ScopeTree`, which describes
//! the parent links in the region hierarchy.
//!
-//! Most of the documentation on regions can be found in
-//! `middle/infer/region_constraints/README.md`
+//! For more information about how MIR-based region-checking works,
+//! see the [rustc guide].
+//!
+//! [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/mir-borrowck.html
use ich::{StableHashingContext, NodeIdHashingMode};
use util::nodemap::{FxHashMap, FxHashSet};
use hir::def::Def;
use hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
use hir::ItemLocalId;
+use hir::LifetimeName;
use ty::{self, TyCtxt};
use std::cell::Cell;
for bound in bounds {
self.visit_poly_trait_ref(bound, hir::TraitBoundModifier::None);
}
- if lifetime.is_elided() {
- self.resolve_object_lifetime_default(lifetime)
- } else {
- self.visit_lifetime(lifetime);
+ match lifetime.name {
+ LifetimeName::Implicit => {
+ // If the user does not write *anything*, we
+ // use the object lifetime defaulting
+ // rules. So e.g. `Box<dyn Debug>` becomes
+ // `Box<dyn Debug + 'static>`.
+ self.resolve_object_lifetime_default(lifetime)
+ }
+ LifetimeName::Underscore => {
+ // If the user writes `'_`, we use the *ordinary* elision
+ // rules. So the `'_` in e.g. `Box<dyn Debug + '_>` will be
+ // resolved the same as the `'_` in `&'_ Foo`.
+ //
+ // cc #48468
+ self.resolve_elided_lifetimes(slice::from_ref(lifetime), false)
+ }
+ LifetimeName::Static | LifetimeName::Name(_) => {
+ // If the user wrote an explicit name, use that.
+ self.visit_lifetime(lifetime);
+ }
}
}
hir::TyRptr(ref lifetime_ref, ref mt) => {
impl<'tcx> From<EvalErrorKind<'tcx>> for EvalError<'tcx> {
fn from(kind: EvalErrorKind<'tcx>) -> Self {
- let backtrace = match env::var("RUST_BACKTRACE") {
+ let backtrace = match env::var("MIRI_BACKTRACE") {
Ok(ref val) if !val.is_empty() => Some(Backtrace::new_unresolved()),
_ => None
};
use std::collections::BTreeMap;
use std::fmt;
use mir;
-use ty;
+use hir::def_id::DefId;
+use ty::{self, TyCtxt};
use ty::layout::{self, Align, HasDataLayout};
use middle::region;
use std::iter;
use syntax::ast::Mutability;
+use rustc_serialize::{Encoder, Decoder, Decodable, Encodable};
#[derive(Clone, Debug, PartialEq)]
pub enum Lock {
impl ::rustc_serialize::UseSpecializedEncodable for AllocId {}
impl ::rustc_serialize::UseSpecializedDecodable for AllocId {}
+pub const ALLOC_DISCRIMINANT: usize = 0;
+pub const FN_DISCRIMINANT: usize = 1;
+pub const EXTERN_STATIC_DISCRIMINANT: usize = 2;
+pub const SHORTHAND_START: usize = 3;
+
+pub fn specialized_encode_alloc_id<
+ 'a, 'tcx,
+ E: Encoder,
+>(
+ encoder: &mut E,
+ tcx: TyCtxt<'a, 'tcx, 'tcx>,
+ alloc_id: AllocId,
+ shorthand: Option<usize>,
+) -> Result<(), E::Error> {
+ if let Some(shorthand) = shorthand {
+ return shorthand.encode(encoder);
+ }
+ if let Some(alloc) = tcx.interpret_interner.get_alloc(alloc_id) {
+ trace!("encoding {:?} with {:#?}", alloc_id, alloc);
+ ALLOC_DISCRIMINANT.encode(encoder)?;
+ alloc.encode(encoder)?;
+ // encode whether this allocation is the root allocation of a static
+ tcx.interpret_interner
+ .get_corresponding_static_def_id(alloc_id)
+ .encode(encoder)?;
+ } else if let Some(fn_instance) = tcx.interpret_interner.get_fn(alloc_id) {
+ trace!("encoding {:?} with {:#?}", alloc_id, fn_instance);
+ FN_DISCRIMINANT.encode(encoder)?;
+ fn_instance.encode(encoder)?;
+ } else if let Some(did) = tcx.interpret_interner.get_corresponding_static_def_id(alloc_id) {
+ // extern "C" statics don't have allocations, just encode its def_id
+ EXTERN_STATIC_DISCRIMINANT.encode(encoder)?;
+ did.encode(encoder)?;
+ } else {
+ bug!("alloc id without corresponding allocation: {}", alloc_id);
+ }
+ Ok(())
+}
+
+pub fn specialized_decode_alloc_id<
+ 'a, 'tcx,
+ D: Decoder,
+ CACHE: FnOnce(&mut D, usize, AllocId),
+ SHORT: FnOnce(&mut D, usize) -> Result<AllocId, D::Error>
+>(
+ decoder: &mut D,
+ tcx: TyCtxt<'a, 'tcx, 'tcx>,
+ pos: usize,
+ cache: CACHE,
+ short: SHORT,
+) -> Result<AllocId, D::Error> {
+ match usize::decode(decoder)? {
+ ALLOC_DISCRIMINANT => {
+ let alloc_id = tcx.interpret_interner.reserve();
+ trace!("creating alloc id {:?} at {}", alloc_id, pos);
+ // insert early to allow recursive allocs
+ cache(decoder, pos, alloc_id);
+
+ let allocation = Allocation::decode(decoder)?;
+ trace!("decoded alloc {:?} {:#?}", alloc_id, allocation);
+ let allocation = tcx.intern_const_alloc(allocation);
+ tcx.interpret_interner.intern_at_reserved(alloc_id, allocation);
+
+ if let Some(glob) = Option::<DefId>::decode(decoder)? {
+ tcx.interpret_interner.cache(glob, alloc_id);
+ }
+
+ Ok(alloc_id)
+ },
+ FN_DISCRIMINANT => {
+ trace!("creating fn alloc id at {}", pos);
+ let instance = ty::Instance::decode(decoder)?;
+ trace!("decoded fn alloc instance: {:?}", instance);
+ let id = tcx.interpret_interner.create_fn_alloc(instance);
+ trace!("created fn alloc id: {:?}", id);
+ cache(decoder, pos, id);
+ Ok(id)
+ },
+ EXTERN_STATIC_DISCRIMINANT => {
+ trace!("creating extern static alloc id at {}", pos);
+ let did = DefId::decode(decoder)?;
+ let alloc_id = tcx.interpret_interner.reserve();
+ tcx.interpret_interner.cache(did, alloc_id);
+ Ok(alloc_id)
+ },
+ shorthand => {
+ trace!("loading shorthand {}", shorthand);
+ short(decoder, shorthand)
+ },
+ }
+}
+
impl fmt::Display for AllocId {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.0)
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-//! MIR datatypes and passes. See the module-level [README] for details.
+//! MIR datatypes and passes. See the [rustc guide] for more info.
//!
-//! [README]: https://github.com/rust-lang/rust/blob/master/src/librustc/mir/README.md
+//! [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/mir.html
use graphviz::IntoCow;
use middle::const_val::ConstVal;
externs: Externs [UNTRACKED],
crate_name: Option<String> [TRACKED],
// An optional name to use as the crate for std during std injection,
- // written `extern crate std = "name"`. Default to "std". Used by
+ // written `extern crate name as std`. Defaults to `std`. Used by
// out-of-tree drivers.
alt_std_name: Option<String> [TRACKED],
// Indicates how the compiler should treat unstable features
"run `dsymutil` and delete intermediate object files"),
ui_testing: bool = (false, parse_bool, [UNTRACKED],
"format compiler diagnostics in a way that's better suitable for UI testing"),
+ embed_bitcode: bool = (false, parse_bool, [TRACKED],
+ "embed LLVM bitcode in object files"),
}
pub fn default_lib_output() -> CrateType {
}
self.suggest_borrow_on_unsized_slice(&obligation.cause.code, &mut err);
+ self.suggest_remove_reference(&obligation, &mut err, &trait_ref);
// Try to report a help message
if !trait_ref.has_infer_types() &&
}
}
+ /// Whenever references are used by mistake, like `for (i, e) in &vec.iter().enumerate()`,
+ /// suggest removing these references until we reach a type that implements the trait.
+ fn suggest_remove_reference(&self,
+ obligation: &PredicateObligation<'tcx>,
+ err: &mut DiagnosticBuilder<'tcx>,
+ trait_ref: &ty::Binder<ty::TraitRef<'tcx>>) {
+ let ty::Binder(trait_ref) = trait_ref;
+ let span = obligation.cause.span;
+
+ if let Ok(snippet) = self.tcx.sess.codemap().span_to_snippet(span) {
+ let refs_number = snippet.chars()
+ .filter(|c| !c.is_whitespace())
+ .take_while(|c| *c == '&')
+ .count();
+
+ let mut trait_type = trait_ref.self_ty();
+ let mut selcx = SelectionContext::new(self);
+
+ for refs_remaining in 0..refs_number {
+ if let ty::TypeVariants::TyRef(_, ty::TypeAndMut{ ty: t_type, mutbl: _ }) =
+ trait_type.sty {
+
+ trait_type = t_type;
+
+ let substs = self.tcx.mk_substs_trait(trait_type, &[]);
+ let new_trait_ref = ty::TraitRef::new(trait_ref.def_id, substs);
+ let new_obligation = Obligation::new(ObligationCause::dummy(),
+ obligation.param_env,
+ new_trait_ref.to_predicate());
+
+ if selcx.evaluate_obligation(&new_obligation) {
+ let sp = self.tcx.sess.codemap()
+ .span_take_while(span, |c| c.is_whitespace() || *c == '&');
+
+ let remove_refs = refs_remaining + 1;
+ let format_str = format!("consider removing {} leading `&`-references",
+ remove_refs);
+
+ err.span_suggestion_short(sp, &format_str, String::from(""));
+ break;
+ }
+ } else {
+ break;
+ }
+ }
+ }
+ }
+
/// Given some node representing a fn-like thing in the HIR map,
/// returns a span and `ArgKind` information that describes the
/// arguments it expects. This can be supplied to
use rustc_data_structures::sync::Lrc;
use std::rc::Rc;
+use std::convert::From;
use syntax::ast;
use syntax_pos::{Span, DUMMY_SP};
pub type PredicateObligations<'tcx> = Vec<PredicateObligation<'tcx>>;
pub type TraitObligations<'tcx> = Vec<TraitObligation<'tcx>>;
+/// The following types:
+/// * `WhereClauseAtom`
+/// * `DomainGoal`
+/// * `Goal`
+/// * `Clause`
+/// are used for representing the trait system in the form of
+/// logic programming clauses. They are part of the interface
+/// for the chalk SLG solver.
+#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
+pub enum WhereClauseAtom<'tcx> {
+ Implemented(ty::TraitPredicate<'tcx>),
+ ProjectionEq(ty::ProjectionPredicate<'tcx>),
+}
+
+#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
+pub enum DomainGoal<'tcx> {
+ Holds(WhereClauseAtom<'tcx>),
+ WellFormed(WhereClauseAtom<'tcx>),
+ FromEnv(WhereClauseAtom<'tcx>),
+ WellFormedTy(Ty<'tcx>),
+ FromEnvTy(Ty<'tcx>),
+ RegionOutlives(ty::RegionOutlivesPredicate<'tcx>),
+ TypeOutlives(ty::TypeOutlivesPredicate<'tcx>),
+}
+
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
+pub enum QuantifierKind {
+ Universal,
+ Existential,
+}
+
+#[derive(Clone, PartialEq, Eq, Hash, Debug)]
+pub enum Goal<'tcx> {
+ // FIXME: use interned refs instead of `Box`
+ Implies(Vec<Clause<'tcx>>, Box<Goal<'tcx>>),
+ And(Box<Goal<'tcx>>, Box<Goal<'tcx>>),
+ Not(Box<Goal<'tcx>>),
+ DomainGoal(DomainGoal<'tcx>),
+ Quantified(QuantifierKind, Box<ty::Binder<Goal<'tcx>>>)
+}
+
+impl<'tcx> From<DomainGoal<'tcx>> for Goal<'tcx> {
+ fn from(domain_goal: DomainGoal<'tcx>) -> Self {
+ Goal::DomainGoal(domain_goal)
+ }
+}
+
+impl<'tcx> From<DomainGoal<'tcx>> for Clause<'tcx> {
+ fn from(domain_goal: DomainGoal<'tcx>) -> Self {
+ Clause::DomainGoal(domain_goal)
+ }
+}
+
+/// This matches the definition from Page 7 of "A Proof Procedure for the Logic of Hereditary
+/// Harrop Formulas".
+#[derive(Clone, PartialEq, Eq, Hash, Debug)]
+pub enum Clause<'tcx> {
+ // FIXME: again, use interned refs instead of `Box`
+ Implies(Vec<Goal<'tcx>>, DomainGoal<'tcx>),
+ DomainGoal(DomainGoal<'tcx>),
+ ForAll(Box<ty::Binder<Clause<'tcx>>>),
+}
+
pub type Selection<'tcx> = Vtable<'tcx, PredicateObligation<'tcx>>;
#[derive(Clone,Debug)]
let gcx = tcx.global_tcx();
let (c_ty, orig_values) = self.infcx.canonicalize_query(&self.param_env.and(ty));
let span = self.cause.span;
+ debug!("c_ty = {:?}", c_ty);
match &gcx.dropck_outlives(c_ty) {
Ok(result) if result.is_proven() => {
match self.infcx.instantiate_query_result(
use ty::fast_reject::{self, SimplifiedType};
use rustc_data_structures::sync::Lrc;
use syntax::ast::Name;
+use util::captures::Captures;
use util::nodemap::{DefIdMap, FxHashMap};
/// A per-trait graph of impls in specialization order. At the moment, this
/// parents of a given specializing impl, which is needed for extracting
/// default items amongst other things. In the simple "chain" rule, every impl
/// has at most one parent.
+#[derive(RustcEncodable, RustcDecodable)]
pub struct Graph {
// all impls have a parent; the "root" impls have as their parent the def_id
// of the trait
/// Children of a given impl, grouped into blanket/non-blanket varieties as is
/// done in `TraitDef`.
+#[derive(RustcEncodable, RustcDecodable)]
struct Children {
// Impls of a trait (or specializations of a given impl). To allow for
// quicker lookup, the impls are indexed by a simplified version of their
}
/// Iterate over the items defined directly by the given (impl or trait) node.
- #[inline] // FIXME(#35870) Avoid closures being unexported due to impl Trait.
- pub fn items(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>)
- -> impl Iterator<Item = ty::AssociatedItem> + 'a {
+ pub fn items(
+ &self,
+ tcx: TyCtxt<'a, 'gcx, 'tcx>,
+ ) -> impl Iterator<Item = ty::AssociatedItem> + 'a {
tcx.associated_items(self.def_id())
}
/// Search the items from the given ancestors, returning each definition
/// with the given name and the given kind.
#[inline] // FIXME(#35870) Avoid closures being unexported due to impl Trait.
- pub fn defs(self, tcx: TyCtxt<'a, 'gcx, 'tcx>, trait_item_name: Name,
- trait_item_kind: ty::AssociatedKind, trait_def_id: DefId)
- -> impl Iterator<Item = NodeItem<ty::AssociatedItem>> + 'a {
+ pub fn defs(
+ self,
+ tcx: TyCtxt<'a, 'gcx, 'tcx>,
+ trait_item_name: Name,
+ trait_item_kind: ty::AssociatedKind,
+ trait_def_id: DefId,
+ ) -> impl Iterator<Item = NodeItem<ty::AssociatedItem>> + Captures<'gcx> + Captures<'tcx> + 'a {
self.flat_map(move |node| {
node.items(tcx).filter(move |impl_item| {
impl_item.kind == trait_item_kind &&
obligations
} where T: TypeFoldable<'tcx>
}
+
+impl<'tcx> fmt::Display for traits::WhereClauseAtom<'tcx> {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ use traits::WhereClauseAtom::*;
+
+ match self {
+ Implemented(trait_ref) => write!(fmt, "Implemented({})", trait_ref),
+ ProjectionEq(projection) => write!(fmt, "ProjectionEq({})", projection),
+ }
+ }
+}
+
+impl<'tcx> fmt::Display for traits::DomainGoal<'tcx> {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ use traits::DomainGoal::*;
+ use traits::WhereClauseAtom::*;
+
+ match self {
+ Holds(wc) => write!(fmt, "{}", wc),
+ WellFormed(Implemented(trait_ref)) => write!(fmt, "WellFormed({})", trait_ref),
+ WellFormed(ProjectionEq(projection)) => write!(fmt, "WellFormed({})", projection),
+ FromEnv(Implemented(trait_ref)) => write!(fmt, "FromEnv({})", trait_ref),
+ FromEnv(ProjectionEq(projection)) => write!(fmt, "FromEnv({})", projection),
+ WellFormedTy(ty) => write!(fmt, "WellFormed({})", ty),
+ FromEnvTy(ty) => write!(fmt, "FromEnv({})", ty),
+ RegionOutlives(predicate) => write!(fmt, "RegionOutlives({})", predicate),
+ TypeOutlives(predicate) => write!(fmt, "TypeOutlives({})", predicate),
+ }
+ }
+}
+
+impl fmt::Display for traits::QuantifierKind {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ use traits::QuantifierKind::*;
+
+ match self {
+ Universal => write!(fmt, "forall"),
+ Existential => write!(fmt, "exists"),
+ }
+ }
+}
+
+impl<'tcx> fmt::Display for traits::Goal<'tcx> {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ use traits::Goal::*;
+
+ match self {
+ Implies(hypotheses, goal) => {
+ write!(fmt, "if (")?;
+ for (index, hyp) in hypotheses.iter().enumerate() {
+ if index > 0 {
+ write!(fmt, ", ")?;
+ }
+ write!(fmt, "{}", hyp)?;
+ }
+ write!(fmt, ") {{ {} }}", goal)
+ }
+ And(goal1, goal2) => write!(fmt, "({} && {})", goal1, goal2),
+ Not(goal) => write!(fmt, "not {{ {} }}", goal),
+ DomainGoal(goal) => write!(fmt, "{}", goal),
+ Quantified(qkind, goal) => {
+ // FIXME: appropriate binder names
+ write!(fmt, "{}<> {{ {} }}", qkind, goal.skip_binder())
+ }
+ }
+ }
+}
+
+impl<'tcx> fmt::Display for traits::Clause<'tcx> {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ use traits::Clause::*;
+
+ match self {
+ Implies(hypotheses, goal) => {
+ write!(fmt, "{}", goal)?;
+ if !hypotheses.is_empty() {
+ write!(fmt, " :- ")?;
+ for (index, condition) in hypotheses.iter().enumerate() {
+ if index > 0 {
+ write!(fmt, ", ")?;
+ }
+ write!(fmt, "{}", condition)?;
+ }
+ }
+ write!(fmt, ".")
+ }
+ DomainGoal(domain_goal) => write!(fmt, "{}.", domain_goal),
+ ForAll(clause) => {
+ // FIXME: appropriate binder names
+ write!(fmt, "forall<> {{ {} }}", clause.skip_binder())
+ }
+ }
+ }
+}
+
+EnumTypeFoldableImpl! {
+ impl<'tcx> TypeFoldable<'tcx> for traits::WhereClauseAtom<'tcx> {
+ (traits::WhereClauseAtom::Implemented)(trait_ref),
+ (traits::WhereClauseAtom::ProjectionEq)(projection),
+ }
+}
+
+EnumTypeFoldableImpl! {
+ impl<'tcx> TypeFoldable<'tcx> for traits::DomainGoal<'tcx> {
+ (traits::DomainGoal::Holds)(wc),
+ (traits::DomainGoal::WellFormed)(wc),
+ (traits::DomainGoal::FromEnv)(wc),
+ (traits::DomainGoal::WellFormedTy)(ty),
+ (traits::DomainGoal::FromEnvTy)(ty),
+ (traits::DomainGoal::RegionOutlives)(predicate),
+ (traits::DomainGoal::TypeOutlives)(predicate),
+ }
+}
+
+CloneTypeFoldableImpls! {
+ traits::QuantifierKind,
+}
+
+EnumTypeFoldableImpl! {
+ impl<'tcx> TypeFoldable<'tcx> for traits::Goal<'tcx> {
+ (traits::Goal::Implies)(hypotheses, goal),
+ (traits::Goal::And)(goal1, goal2),
+ (traits::Goal::Not)(goal),
+ (traits::Goal::DomainGoal)(domain_goal),
+ (traits::Goal::Quantified)(qkind, goal),
+ }
+}
+
+EnumTypeFoldableImpl! {
+ impl<'tcx> TypeFoldable<'tcx> for traits::Clause<'tcx> {
+ (traits::Clause::Implies)(hypotheses, goal),
+ (traits::Clause::DomainGoal)(domain_goal),
+ (traits::Clause::ForAll)(clause),
+ }
+}
/// because we sometimes need to use SimplifiedTypeGen values as stable sorting
/// keys (in which case we use a DefPathHash as id-type) but in the general case
/// the non-stable but fast to construct DefId-version is the better choice.
-#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, RustcEncodable, RustcDecodable)]
pub enum SimplifiedTypeGen<D>
where D: Copy + Debug + Ord + Eq + Hash
{
}
}
+impl<'tcx> QueryDescription<'tcx> for queries::program_clauses_for<'tcx> {
+ fn describe(_tcx: TyCtxt, _: DefId) -> String {
+ format!("generating chalk-style clauses")
+ }
+}
+
macro_rules! impl_disk_cacheable_query(
($query_name:ident, |$key:tt| $cond:expr) => {
impl<'tcx> QueryDescription<'tcx> for queries::$query_name<'tcx> {
impl_disk_cacheable_query!(predicates_of, |def_id| def_id.is_local());
impl_disk_cacheable_query!(used_trait_imports, |def_id| def_id.is_local());
impl_disk_cacheable_query!(trans_fn_attrs, |_| true);
+impl_disk_cacheable_query!(specialization_graph_of, |_| true);
use traits::query::dropck_outlives::{DtorckConstraint, DropckOutlivesResult};
use traits::query::normalize::NormalizationResult;
use traits::specialization_graph;
+use traits::Clause;
use ty::{self, CrateInherentImpls, ParamEnvAnd, Ty, TyCtxt};
use ty::steal::Steal;
use ty::subst::Substs;
-> usize,
[] fn features_query: features_node(CrateNum) -> Lrc<feature_gate::Features>,
+
+ [] fn program_clauses_for: ProgramClausesFor(DefId) -> Lrc<Vec<Clause<'tcx>>>,
}
//////////////////////////////////////////////////////////////////////
// A map from dep-node to the position of any associated diagnostics in
// `serialized_data`.
prev_diagnostics_index: FxHashMap<SerializedDepNodeIndex, AbsoluteBytePos>,
+
+ // A cache to ensure we don't read allocations twice
+ interpret_alloc_cache: RefCell<FxHashMap<usize, interpret::AllocId>>,
+
+ // A map from positions to size of the serialized allocation
+ // so we can skip over already processed allocations
+ interpret_alloc_size: RefCell<FxHashMap<usize, usize>>,
}
// This type is used only for (de-)serialization.
query_result_index: footer.query_result_index.into_iter().collect(),
prev_diagnostics_index: footer.diagnostics_index.into_iter().collect(),
synthetic_expansion_infos: RefCell::new(FxHashMap()),
+ interpret_alloc_cache: RefCell::new(FxHashMap::default()),
+ interpret_alloc_size: RefCell::new(FxHashMap::default()),
}
}
query_result_index: FxHashMap(),
prev_diagnostics_index: FxHashMap(),
synthetic_expansion_infos: RefCell::new(FxHashMap()),
+ interpret_alloc_cache: RefCell::new(FxHashMap::default()),
+ interpret_alloc_size: RefCell::new(FxHashMap::default()),
}
}
encode_query_results::<symbol_name, _>(tcx, enc, qri)?;
encode_query_results::<check_match, _>(tcx, enc, qri)?;
encode_query_results::<trans_fn_attrs, _>(tcx, enc, qri)?;
+ encode_query_results::<specialization_graph_of, _>(tcx, enc, qri)?;
// const eval is special, it only encodes successfully evaluated constants
use ty::maps::plumbing::GetCacheInternal;
file_index_to_file: &self.file_index_to_file,
file_index_to_stable_id: &self.file_index_to_stable_id,
synthetic_expansion_infos: &self.synthetic_expansion_infos,
- interpret_alloc_cache: FxHashMap::default(),
+ interpret_alloc_cache: &self.interpret_alloc_cache,
+ interpret_alloc_size: &self.interpret_alloc_size,
};
match decode_tagged(&mut decoder, dep_node_index) {
synthetic_expansion_infos: &'x RefCell<FxHashMap<AbsoluteBytePos, SyntaxContext>>,
file_index_to_file: &'x RefCell<FxHashMap<FileMapIndex, Lrc<FileMap>>>,
file_index_to_stable_id: &'x FxHashMap<FileMapIndex, StableFilemapId>,
- interpret_alloc_cache: FxHashMap<usize, interpret::AllocId>,
+ interpret_alloc_cache: &'x RefCell<FxHashMap<usize, interpret::AllocId>>,
+ interpret_alloc_size: &'x RefCell<FxHashMap<usize, usize>>,
}
impl<'a, 'tcx, 'x> CacheDecoder<'a, 'tcx, 'x> {
impl<'a, 'tcx, 'x> SpecializedDecoder<interpret::AllocId> for CacheDecoder<'a, 'tcx, 'x> {
fn specialized_decode(&mut self) -> Result<interpret::AllocId, Self::Error> {
- const MAX1: usize = usize::max_value() - 1;
let tcx = self.tcx;
let pos = TyDecoder::position(self);
- match usize::decode(self)? {
- ::std::usize::MAX => {
- let alloc_id = tcx.interpret_interner.reserve();
- trace!("creating alloc id {:?} at {}", alloc_id, pos);
- // insert early to allow recursive allocs
- self.interpret_alloc_cache.insert(pos, alloc_id);
-
- let allocation = interpret::Allocation::decode(self)?;
- trace!("decoded alloc {:?} {:#?}", alloc_id, allocation);
- let allocation = self.tcx.intern_const_alloc(allocation);
- tcx.interpret_interner.intern_at_reserved(alloc_id, allocation);
-
- if let Some(glob) = Option::<DefId>::decode(self)? {
- trace!("connecting alloc {:?} with {:?}", alloc_id, glob);
- tcx.interpret_interner.cache(glob, alloc_id);
- }
-
- Ok(alloc_id)
- },
- MAX1 => {
- trace!("creating fn alloc id at {}", pos);
- let instance = ty::Instance::decode(self)?;
- trace!("decoded fn alloc instance: {:?}", instance);
- let id = tcx.interpret_interner.create_fn_alloc(instance);
- trace!("created fn alloc id: {:?}", id);
- self.interpret_alloc_cache.insert(pos, id);
- Ok(id)
+ trace!("specialized_decode_alloc_id: {:?}", pos);
+ if let Some(cached) = self.interpret_alloc_cache.borrow().get(&pos).cloned() {
+ // if there's no end position we are currently deserializing a recursive
+ // allocation
+ if let Some(end) = self.interpret_alloc_size.borrow().get(&pos).cloned() {
+ trace!("{} already cached as {:?}", pos, cached);
+ // skip ahead
+ self.opaque.set_position(end);
+ return Ok(cached)
+ }
+ }
+ let id = interpret::specialized_decode_alloc_id(
+ self,
+ tcx,
+ pos,
+ |this, pos, alloc_id| {
+ assert!(this.interpret_alloc_cache.borrow_mut().insert(pos, alloc_id).is_none());
},
- shorthand => {
- trace!("loading shorthand {}", shorthand);
- if let Some(&alloc_id) = self.interpret_alloc_cache.get(&shorthand) {
- return Ok(alloc_id);
- }
- trace!("shorthand {} not cached, loading entire allocation", shorthand);
+ |this, shorthand| {
// need to load allocation
- self.with_position(shorthand, |this| interpret::AllocId::decode(this))
- },
- }
+ this.with_position(shorthand, |this| interpret::AllocId::decode(this))
+ }
+ )?;
+ assert!(self
+ .interpret_alloc_size
+ .borrow_mut()
+ .insert(pos, TyDecoder::position(self))
+ .is_none());
+ Ok(id)
}
}
impl<'a, 'tcx, 'x> SpecializedDecoder<Span> for CacheDecoder<'a, 'tcx, 'x> {
where E: 'enc + ty_codec::TyEncoder
{
fn specialized_encode(&mut self, alloc_id: &interpret::AllocId) -> Result<(), Self::Error> {
- trace!("encoding {:?} at {}", alloc_id, self.position());
- if let Some(shorthand) = self.interpret_alloc_shorthands.get(alloc_id).cloned() {
- trace!("encoding {:?} as shorthand to {}", alloc_id, shorthand);
- return shorthand.encode(self);
- }
- let start = self.position();
- // cache the allocation shorthand now, because the allocation itself might recursively
- // point to itself.
- self.interpret_alloc_shorthands.insert(*alloc_id, start);
- if let Some(alloc) = self.tcx.interpret_interner.get_alloc(*alloc_id) {
- trace!("encoding {:?} with {:#?}", alloc_id, alloc);
- usize::max_value().encode(self)?;
- alloc.encode(self)?;
- self.tcx.interpret_interner
- .get_corresponding_static_def_id(*alloc_id)
- .encode(self)?;
- } else if let Some(fn_instance) = self.tcx.interpret_interner.get_fn(*alloc_id) {
- trace!("encoding {:?} with {:#?}", alloc_id, fn_instance);
- (usize::max_value() - 1).encode(self)?;
- fn_instance.encode(self)?;
- } else {
- bug!("alloc id without corresponding allocation: {}", alloc_id);
- }
- Ok(())
+ use std::collections::hash_map::Entry;
+ let tcx = self.tcx;
+ let pos = self.position();
+ let shorthand = match self.interpret_alloc_shorthands.entry(*alloc_id) {
+ Entry::Occupied(entry) => Some(entry.get().clone()),
+ Entry::Vacant(entry) => {
+ // ensure that we don't place any AllocIds at the very beginning
+ // of the metadata file, because that would end up making our indices
+ // not special. It is essentially impossible for that to happen,
+ // but let's make sure
+ assert!(pos >= interpret::SHORTHAND_START);
+ entry.insert(pos);
+ None
+ },
+ };
+ interpret::specialized_encode_alloc_id(
+ self,
+ tcx,
+ *alloc_id,
+ shorthand,
+ )
}
}
DepKind::GetSymbolExportLevel => { force!(symbol_export_level, def_id!()); }
DepKind::Features => { force!(features_query, LOCAL_CRATE); }
+
+ DepKind::ProgramClausesFor => { force!(program_clauses_for, def_id!()); }
}
true
PredicatesOfItem => predicates_of,
UsedTraitImports => used_trait_imports,
TransFnAttrs => trans_fn_attrs,
+ SpecializationGraph => specialization_graph_of,
);
use ty::subst::{Subst, Substs};
use ty::util::{IntTypeExt, Discr};
use ty::walk::TypeWalker;
+use util::captures::Captures;
use util::nodemap::{NodeSet, DefIdMap, FxHashMap};
use serialize::{self, Encodable, Encoder};
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
pub struct OutlivesPredicate<A,B>(pub A, pub B); // `A : B`
pub type PolyOutlivesPredicate<A,B> = ty::Binder<OutlivesPredicate<A,B>>;
-pub type PolyRegionOutlivesPredicate<'tcx> = PolyOutlivesPredicate<ty::Region<'tcx>,
- ty::Region<'tcx>>;
-pub type PolyTypeOutlivesPredicate<'tcx> = PolyOutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>;
+pub type RegionOutlivesPredicate<'tcx> = OutlivesPredicate<ty::Region<'tcx>,
+ ty::Region<'tcx>>;
+pub type TypeOutlivesPredicate<'tcx> = OutlivesPredicate<Ty<'tcx>,
+ ty::Region<'tcx>>;
+pub type PolyRegionOutlivesPredicate<'tcx> = ty::Binder<RegionOutlivesPredicate<'tcx>>;
+pub type PolyTypeOutlivesPredicate<'tcx> = ty::Binder<TypeOutlivesPredicate<'tcx>>;
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
pub struct SubtypePredicate<'tcx> {
}
#[inline]
- pub fn discriminants(&'a self, tcx: TyCtxt<'a, 'gcx, 'tcx>)
- -> impl Iterator<Item=Discr<'tcx>> + 'a {
+ pub fn discriminants(
+ &'a self,
+ tcx: TyCtxt<'a, 'gcx, 'tcx>,
+ ) -> impl Iterator<Item=Discr<'tcx>> + Captures<'gcx> + 'a {
let repr_type = self.repr.discr_type();
let initial = repr_type.initial_discriminant(tcx.global_tcx());
let mut prev_discr = None::<Discr<'tcx>>;
/// Returns an iterator of the def-ids for all body-owners in this
/// crate. If you would prefer to iterate over the bodies
/// themselves, you can do `self.hir.krate().body_ids.iter()`.
- pub fn body_owners(self) -> impl Iterator<Item = DefId> + 'a {
+ pub fn body_owners(
+ self,
+ ) -> impl Iterator<Item = DefId> + Captures<'tcx> + Captures<'gcx> + 'a {
self.hir.krate()
.body_ids
.iter()
}
}
- #[inline] // FIXME(#35870) Avoid closures being unexported due to impl Trait.
- pub fn associated_items(self, def_id: DefId)
- -> impl Iterator<Item = ty::AssociatedItem> + 'a {
+ pub fn associated_items(
+ self,
+ def_id: DefId,
+ ) -> impl Iterator<Item = ty::AssociatedItem> + 'a {
let def_ids = self.associated_item_def_ids(def_id);
- (0..def_ids.len()).map(move |i| self.associated_item(def_ids[i]))
+ Box::new((0..def_ids.len()).map(move |i| self.associated_item(def_ids[i])))
+ as Box<dyn Iterator<Item = ty::AssociatedItem> + 'a>
}
/// Returns true if the impls are the same polarity and are implementing
use ty::subst::{Substs, Subst, Kind, UnpackedKind};
use ty::{self, AdtDef, TypeFlags, Ty, TyCtxt, TypeFoldable};
use ty::{Slice, TyS};
+use util::captures::Captures;
use std::iter;
use std::cmp::Ordering;
/// This returns the types of the MIR locals which had to be stored across suspension points.
/// It is calculated in rustc_mir::transform::generator::StateTransform.
/// All the types here must be in the tuple in GeneratorInterior.
- pub fn state_tys(self, def_id: DefId, tcx: TyCtxt<'a, 'gcx, 'tcx>) ->
- impl Iterator<Item=Ty<'tcx>> + 'a
- {
+ pub fn state_tys(
+ self,
+ def_id: DefId,
+ tcx: TyCtxt<'a, 'gcx, 'tcx>,
+ ) -> impl Iterator<Item=Ty<'tcx>> + Captures<'gcx> + 'a {
let state = tcx.generator_layout(def_id).fields.iter();
state.map(move |d| d.ty.subst(tcx, self.substs))
}
/// This is the types of all the fields stored in a generator.
/// It includes the upvars, state types and the state discriminant which is u32.
pub fn field_tys(self, def_id: DefId, tcx: TyCtxt<'a, 'gcx, 'tcx>) ->
- impl Iterator<Item=Ty<'tcx>> + 'a
+ impl Iterator<Item=Ty<'tcx>> + Captures<'gcx> + 'a
{
self.pre_transforms_tys(def_id, tcx).chain(self.state_tys(def_id, tcx))
}
/// the inference variable is supposed to satisfy the relation
/// *for every value of the skolemized region*. To ensure that doesn't
/// happen, you can use `leak_check`. This is more clearly explained
-/// by infer/higher_ranked/README.md.
+/// by the [rustc guide].
///
/// [1]: http://smallcultfollowing.com/babysteps/blog/2013/10/29/intermingled-parameter-lists/
/// [2]: http://smallcultfollowing.com/babysteps/blog/2013/11/04/intermingled-parameter-lists/
+/// [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/trait-hrtb.html
#[derive(Clone, PartialEq, Eq, Hash, Copy, RustcEncodable, RustcDecodable, PartialOrd, Ord)]
pub enum RegionKind {
// Region bound in a type or fn declaration which will be
--- /dev/null
+// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+/// "Signaling" trait used in impl trait to tag lifetimes that you may
+/// need to capture but don't really need for other reasons.
+/// Basically a workaround; see [this comment] for details.
+///
+/// [this comment]: https://github.com/rust-lang/rust/issues/34511#issuecomment-373423999
+pub trait Captures<'a> { }
+
+impl<'a, T: ?Sized> Captures<'a> for T { }
f.cx.item_extern_crate(f.span, f.alloc),
f.cx.item_use_simple(
f.span,
- respan(f.span.empty(), VisibilityKind::Inherited),
+ respan(f.span.shrink_to_lo(), VisibilityKind::Inherited),
super_path,
),
];
#![forbid(unsafe_code)]
#![feature(i128_type)]
-#![feature(slice_patterns)]
+#![cfg_attr(stage0, feature(slice_patterns))]
#![feature(try_from)]
// See librustc_cratesio_shim/Cargo.toml for a comment explaining this.
-NB: This crate is part of the Rust compiler. For an overview of the
-compiler as a whole, see
-[the README.md file found in `librustc`](../librustc/README.md).
-
`librustc_back` contains some very low-level details that are
specific to different LLVM targets and so forth.
+
+For more information about how trans works, see the [rustc guide].
+
+[rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/trans.html
/// The default visibility for symbols in this target should be "hidden"
/// rather than "default"
pub default_hidden_visibility: bool,
+
+ /// Whether or not bitcode is embedded in object files
+ pub embed_bitcode: bool,
}
impl Default for TargetOptions {
i128_lowering: false,
codegen_backend: "llvm".to_string(),
default_hidden_visibility: false,
+ embed_bitcode: false,
}
}
}
key!(no_builtins, bool);
key!(codegen_backend);
key!(default_hidden_visibility, bool);
+ key!(embed_bitcode, bool);
if let Some(array) = obj.find("abi-blacklist").and_then(Json::as_array) {
for name in array.iter().filter_map(|abi| abi.as_string()) {
target_option_val!(no_builtins);
target_option_val!(codegen_backend);
target_option_val!(default_hidden_visibility);
+ target_option_val!(embed_bitcode);
if default.abi_blacklist != self.options.abi_blacklist {
d.insert("abi-blacklist".to_string(), self.options.abi_blacklist.iter()
% The Borrow Checker
+> WARNING: This README is more or less obsolete, and will be removed
+> soon! The new system is described in the [rustc guide].
+
+[rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/mir-borrowck.html
+
This pass has the job of enforcing memory safety. This is a subtle
topic. This docs aim to explain both the practice and the theory
behind the borrow checker. They start with a high-level overview of
used_mut_nodes: RefCell<FxHashSet<HirId>>,
}
-impl<'b, 'tcx: 'b> BorrowckErrors for BorrowckCtxt<'b, 'tcx> {
- fn struct_span_err_with_code<'a, S: Into<MultiSpan>>(&'a self,
- sp: S,
- msg: &str,
- code: DiagnosticId)
- -> DiagnosticBuilder<'a>
+impl<'a, 'b, 'tcx: 'b> BorrowckErrors<'a> for &'a BorrowckCtxt<'b, 'tcx> {
+ fn struct_span_err_with_code<S: Into<MultiSpan>>(self,
+ sp: S,
+ msg: &str,
+ code: DiagnosticId)
+ -> DiagnosticBuilder<'a>
{
self.tcx.sess.struct_span_err_with_code(sp, msg, code)
}
- fn struct_span_err<'a, S: Into<MultiSpan>>(&'a self,
- sp: S,
- msg: &str)
- -> DiagnosticBuilder<'a>
+ fn struct_span_err<S: Into<MultiSpan>>(self,
+ sp: S,
+ msg: &str)
+ -> DiagnosticBuilder<'a>
{
self.tcx.sess.struct_span_err(sp, msg)
}
- fn cancel_if_wrong_origin<'a>(&'a self,
- mut diag: DiagnosticBuilder<'a>,
- o: Origin)
- -> DiagnosticBuilder<'a>
+ fn cancel_if_wrong_origin(self,
+ mut diag: DiagnosticBuilder<'a>,
+ o: Origin)
+ -> DiagnosticBuilder<'a>
{
if !o.should_emit_errors(self.tcx.borrowck_mode()) {
self.tcx.sess.diagnostic().cancel(&mut diag);
#![deny(warnings)]
#![feature(rustc_diagnostic_macros)]
-#![feature(slice_patterns)]
#![feature(box_patterns)]
#![feature(box_syntax)]
#![feature(macro_lifetime_matcher)]
-NB: This crate is part of the Rust compiler. For an overview of the
-compiler as a whole, see
-[the README.md file found in `librustc`](../librustc/README.md).
-
The `driver` crate is effectively the "main" function for the rust
compiler. It orchestrates the compilation process and "knits together"
the code from the other crates within rustc. This crate itself does
have some code related to pretty printing or other minor compiler
options).
+For more information about how the driver works, see the [rustc guide].
+[rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/rustc-driver.html
});
krate = time(sess, "crate injection", || {
- let alt_std_name = sess.opts.alt_std_name.clone();
+ let alt_std_name = sess.opts.alt_std_name.as_ref().map(|s| &**s);
syntax::std_inject::maybe_inject_crates_ref(krate, alt_std_name)
});
Ok(())
})?;
- if resolver.found_unresolved_macro {
- sess.parse_sess.span_diagnostic.abort_if_errors();
- }
-
// Needs to go *after* expansion to be able to check the results of macro expansion.
time(sess, "complete gated feature checking", || {
sess.track_errors(|| {
})
})?;
+ // Unresolved macros might be due to mistyped `#[macro_use]`,
+ // so abort after checking for unknown attributes. (#49074)
+ if resolver.found_unresolved_macro {
+ sess.parse_sess.span_diagnostic.abort_if_errors();
+ }
+
// Lower ast -> hir.
// First, we need to collect the dep_graph.
let dep_graph = match future_dep_graph {
time(sess, "lint checking", || lint::check_crate(tcx));
+ time(sess,
+ "dumping chalk-like clauses",
+ || rustc_traits::lowering::dump_program_clauses(tcx));
+
return Ok(f(tcx, analysis, rx, tcx.sess.compile_status()));
})
}
// The FileLoader provides a way to load files from sources other than the file system.
pub fn run_compiler<'a>(args: &[String],
callbacks: &mut CompilerCalls<'a>,
- file_loader: Option<Box<FileLoader + 'static>>,
+ file_loader: Option<Box<FileLoader + Send + Sync + 'static>>,
emitter_dest: Option<Box<Write + Send>>)
-> (CompileResult, Option<Session>)
{
fn run_compiler_impl<'a>(args: &[String],
callbacks: &mut CompilerCalls<'a>,
- file_loader: Option<Box<FileLoader + 'static>>,
+ file_loader: Option<Box<FileLoader + Send + Sync + 'static>>,
emitter_dest: Option<Box<Write + Send>>)
-> (CompileResult, Option<Session>)
{
use syntax_pos::{DUMMY_SP, FileMap, Span, MultiSpan};
-use {Level, CodeSuggestion, DiagnosticBuilder, SubDiagnostic, CodeMapper, DiagnosticId};
+use {Level, CodeSuggestion, DiagnosticBuilder, SubDiagnostic, CodeMapperDyn, DiagnosticId};
use snippet::{Annotation, AnnotationType, Line, MultilineAnnotation, StyledString, Style};
use styled_buffer::StyledBuffer;
pub struct EmitterWriter {
dst: Destination,
- cm: Option<Lrc<CodeMapper>>,
+ cm: Option<Lrc<CodeMapperDyn>>,
short_message: bool,
teach: bool,
ui_testing: bool,
impl EmitterWriter {
pub fn stderr(color_config: ColorConfig,
- code_map: Option<Lrc<CodeMapper>>,
+ code_map: Option<Lrc<CodeMapperDyn>>,
short_message: bool,
teach: bool)
-> EmitterWriter {
}
pub fn new(dst: Box<Write + Send>,
- code_map: Option<Lrc<CodeMapper>>,
+ code_map: Option<Lrc<CodeMapperDyn>>,
short_message: bool,
teach: bool)
-> EmitterWriter {
level: &Level,
max_line_num_len: usize)
-> io::Result<()> {
- use std::borrow::Borrow;
-
if let Some(ref cm) = self.cm {
let mut buffer = StyledBuffer::new();
Some(Style::HeaderMsg));
// Render the replacements for each suggestion
- let suggestions = suggestion.splice_lines(cm.borrow());
+ let suggestions = suggestion.splice_lines(&**cm);
let mut row_num = 2;
for &(ref complete, ref parts) in suggestions.iter().take(MAX_SUGGESTIONS) {
use emitter::{Emitter, EmitterWriter};
-use rustc_data_structures::sync::Lrc;
+use rustc_data_structures::sync::{self, Lrc};
use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::stable_hasher::StableHasher;
pub snippet: String,
}
+pub type CodeMapperDyn = CodeMapper + sync::Send + sync::Sync;
+
pub trait CodeMapper {
fn lookup_char_pos(&self, pos: BytePos) -> Loc;
fn span_to_lines(&self, sp: Span) -> FileLinesResult;
impl CodeSuggestion {
/// Returns the assembled code suggestions and whether they should be shown with an underline.
- pub fn splice_lines(&self, cm: &CodeMapper) -> Vec<(String, Vec<SubstitutionPart>)> {
+ pub fn splice_lines(&self, cm: &CodeMapperDyn)
+ -> Vec<(String, Vec<SubstitutionPart>)> {
use syntax_pos::{CharPos, Loc, Pos};
fn push_trailing(buf: &mut String,
pub fn with_tty_emitter(color_config: ColorConfig,
can_emit_warnings: bool,
treat_err_as_bug: bool,
- cm: Option<Lrc<CodeMapper>>)
+ cm: Option<Lrc<CodeMapperDyn>>)
-> Handler {
Handler::with_tty_emitter_and_flags(
color_config,
}
pub fn with_tty_emitter_and_flags(color_config: ColorConfig,
- cm: Option<Lrc<CodeMapper>>,
+ cm: Option<Lrc<CodeMapperDyn>>,
flags: HandlerFlags)
-> Handler {
let emitter = Box::new(EmitterWriter::stderr(color_config, cm, false, false));
if !cx.access_levels.is_reachable(it.id) {
let msg = "function is marked #[no_mangle], but not exported";
let mut err = cx.struct_span_lint(PRIVATE_NO_MANGLE_FNS, it.span, msg);
- let insertion_span = it.span.with_hi(it.span.lo());
+ let insertion_span = it.span.shrink_to_lo();
if it.vis == hir::Visibility::Inherited {
err.span_suggestion(insertion_span,
"try making it public",
!cx.access_levels.is_reachable(it.id) {
let msg = "static is marked #[no_mangle], but not exported";
let mut err = cx.struct_span_lint(PRIVATE_NO_MANGLE_STATICS, it.span, msg);
- let insertion_span = it.span.with_hi(it.span.lo());
+ let insertion_span = it.span.shrink_to_lo();
if it.vis == hir::Visibility::Inherited {
err.span_suggestion(insertion_span,
"try making it public",
#![feature(macro_vis_matcher)]
#![feature(quote)]
#![feature(rustc_diagnostic_macros)]
-#![feature(slice_patterns)]
#![cfg_attr(stage0, feature(never_type))]
#[macro_use]
// Trigger the lint if the nested item is a non-self single item
let node_ident;
match items[0].0.kind {
- ast::UseTreeKind::Simple(ident) => {
- if ident.name == keywords::SelfValue.name() {
+ ast::UseTreeKind::Simple(rename) => {
+ let orig_ident = items[0].0.prefix.segments.last().unwrap().identifier;
+ if orig_ident.name == keywords::SelfValue.name() {
return;
} else {
- node_ident = ident;
+ node_ident = rename.unwrap_or(orig_ident);
}
}
ast::UseTreeKind::Glob => {
pub fn LLVMConstIntGetSExtValue(ConstantVal: ValueRef) -> c_longlong;
pub fn LLVMRustConstInt128Get(ConstantVal: ValueRef, SExt: bool,
high: *mut u64, low: *mut u64) -> bool;
+ pub fn LLVMConstRealGetDouble (ConstantVal: ValueRef, losesInfo: *mut Bool) -> f64;
// Operations on composite constants
Name: *const c_char)
-> ValueRef;
+ pub fn LLVMRustBuildVectorReduceFAdd(B: BuilderRef,
+ Acc: ValueRef,
+ Src: ValueRef)
+ -> ValueRef;
+ pub fn LLVMRustBuildVectorReduceFMul(B: BuilderRef,
+ Acc: ValueRef,
+ Src: ValueRef)
+ -> ValueRef;
+ pub fn LLVMRustBuildVectorReduceAdd(B: BuilderRef,
+ Src: ValueRef)
+ -> ValueRef;
+ pub fn LLVMRustBuildVectorReduceMul(B: BuilderRef,
+ Src: ValueRef)
+ -> ValueRef;
+ pub fn LLVMRustBuildVectorReduceAnd(B: BuilderRef,
+ Src: ValueRef)
+ -> ValueRef;
+ pub fn LLVMRustBuildVectorReduceOr(B: BuilderRef,
+ Src: ValueRef)
+ -> ValueRef;
+ pub fn LLVMRustBuildVectorReduceXor(B: BuilderRef,
+ Src: ValueRef)
+ -> ValueRef;
+ pub fn LLVMRustBuildVectorReduceMin(B: BuilderRef,
+ Src: ValueRef,
+ IsSigned: bool)
+ -> ValueRef;
+ pub fn LLVMRustBuildVectorReduceMax(B: BuilderRef,
+ Src: ValueRef,
+ IsSigned: bool)
+ -> ValueRef;
+ pub fn LLVMRustBuildVectorReduceFMin(B: BuilderRef,
+ Src: ValueRef,
+ IsNaN: bool)
+ -> ValueRef;
+ pub fn LLVMRustBuildVectorReduceFMax(B: BuilderRef,
+ Src: ValueRef,
+ IsNaN: bool)
+ -> ValueRef;
+
pub fn LLVMBuildIsNull(B: BuilderRef, Val: ValueRef, Name: *const c_char) -> ValueRef;
pub fn LLVMBuildIsNotNull(B: BuilderRef, Val: ValueRef, Name: *const c_char) -> ValueRef;
pub fn LLVMBuildPtrDiff(B: BuilderRef,
pub fn LLVMRustWriteValueToString(value_ref: ValueRef, s: RustStringRef);
pub fn LLVMIsAConstantInt(value_ref: ValueRef) -> ValueRef;
+ pub fn LLVMIsAConstantFP(value_ref: ValueRef) -> ValueRef;
pub fn LLVMRustPassKind(Pass: PassRef) -> PassKind;
pub fn LLVMRustFindAndCreatePass(Pass: *const c_char) -> PassRef;
use locator::{self, CratePaths};
use native_libs::relevant_lib;
use schema::CrateRoot;
-use rustc_data_structures::sync::Lrc;
+use rustc_data_structures::sync::{Lrc, RwLock, Lock};
use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX};
use rustc::hir::svh::Svh;
use rustc::util::nodemap::FxHashSet;
use rustc::hir::map::Definitions;
-use std::cell::{RefCell, Cell};
use std::ops::Deref;
use std::path::PathBuf;
use std::{cmp, fs};
info!(" name: {}", data.name());
info!(" cnum: {}", data.cnum);
info!(" hash: {}", data.hash());
- info!(" reqd: {:?}", data.dep_kind.get());
+ info!(" reqd: {:?}", *data.dep_kind.lock());
let CrateSource { dylib, rlib, rmeta } = data.source.clone();
dylib.map(|dl| info!(" dylib: {}", dl.0.display()));
rlib.map(|rl| info!(" rlib: {}", rl.0.display()));
let mut cmeta = cstore::CrateMetadata {
name,
- extern_crate: Cell::new(None),
+ extern_crate: Lock::new(None),
def_path_table: Lrc::new(def_path_table),
trait_impls,
proc_macros: crate_root.macro_derive_registrar.map(|_| {
}),
root: crate_root,
blob: metadata,
- cnum_map: RefCell::new(cnum_map),
+ cnum_map: Lock::new(cnum_map),
cnum,
- codemap_import_info: RefCell::new(vec![]),
- attribute_cache: RefCell::new([Vec::new(), Vec::new()]),
- dep_kind: Cell::new(dep_kind),
+ codemap_import_info: RwLock::new(vec![]),
+ attribute_cache: Lock::new([Vec::new(), Vec::new()]),
+ dep_kind: Lock::new(dep_kind),
source: cstore::CrateSource {
dylib,
rlib,
if data.root.macro_derive_registrar.is_some() {
dep_kind = DepKind::UnexportedMacrosOnly;
}
- data.dep_kind.set(cmp::max(data.dep_kind.get(), dep_kind));
+ data.dep_kind.with_lock(|data_dep_kind| {
+ *data_dep_kind = cmp::max(*data_dep_kind, dep_kind);
+ });
(cnum, data)
}
LoadResult::Loaded(library) => {
if !visited.insert((cnum, extern_crate.direct)) { return }
let cmeta = self.cstore.get_crate_data(cnum);
- let old_extern_crate = cmeta.extern_crate.get();
+ let mut old_extern_crate = cmeta.extern_crate.borrow_mut();
// Prefer:
// - something over nothing (tuple.0);
// - direct extern crate to indirect (tuple.1);
// - shorter paths to longer (tuple.2).
let new_rank = (true, extern_crate.direct, !extern_crate.path_len);
- let old_rank = match old_extern_crate {
+ let old_rank = match *old_extern_crate {
None => (false, false, !0),
Some(ref c) => (true, c.direct, !c.path_len),
};
return; // no change needed
}
- cmeta.extern_crate.set(Some(extern_crate));
+ *old_extern_crate = Some(extern_crate);
+ drop(old_extern_crate);
+
// Propagate the extern crate info to dependencies.
extern_crate.direct = false;
for &dep_cnum in cmeta.cnum_map.borrow().iter() {
// #![panic_runtime] crate.
self.inject_dependency_if(cnum, "a panic runtime",
&|data| data.needs_panic_runtime(sess));
- runtime_found = runtime_found || data.dep_kind.get() == DepKind::Explicit;
+ runtime_found = runtime_found || *data.dep_kind.lock() == DepKind::Explicit;
}
});
fn process_item(&mut self, item: &ast::Item, definitions: &Definitions) {
match item.node {
- ast::ItemKind::ExternCrate(rename) => {
- debug!("resolving extern crate stmt. ident: {} rename: {:?}", item.ident, rename);
- let rename = match rename {
- Some(rename) => {
- validate_crate_name(Some(self.sess), &rename.as_str(), Some(item.span));
- rename
+ ast::ItemKind::ExternCrate(orig_name) => {
+ debug!("resolving extern crate stmt. ident: {} orig_name: {:?}",
+ item.ident, orig_name);
+ let orig_name = match orig_name {
+ Some(orig_name) => {
+ validate_crate_name(Some(self.sess), &orig_name.as_str(),
+ Some(item.span));
+ orig_name
}
None => item.ident.name,
};
};
let (cnum, ..) = self.resolve_crate(
- &None, item.ident.name, rename, None, item.span, PathKind::Crate, dep_kind,
+ &None, item.ident.name, orig_name, None, item.span, PathKind::Crate, dep_kind,
);
let def_id = definitions.opt_local_def_id(item.id).unwrap();
use rustc_data_structures::indexed_vec::IndexVec;
use rustc::util::nodemap::{FxHashMap, FxHashSet, NodeMap};
-use std::cell::{RefCell, Cell};
-use rustc_data_structures::sync::Lrc;
+use rustc_data_structures::sync::{Lrc, RwLock, Lock};
use syntax::{ast, attr};
use syntax::ext::base::SyntaxExtension;
use syntax::symbol::Symbol;
/// Information about the extern crate that caused this crate to
/// be loaded. If this is `None`, then the crate was injected
/// (e.g., by the allocator)
- pub extern_crate: Cell<Option<ExternCrate>>,
+ pub extern_crate: Lock<Option<ExternCrate>>,
pub blob: MetadataBlob,
- pub cnum_map: RefCell<CrateNumMap>,
+ pub cnum_map: Lock<CrateNumMap>,
pub cnum: CrateNum,
- pub codemap_import_info: RefCell<Vec<ImportedFileMap>>,
- pub attribute_cache: RefCell<[Vec<Option<Lrc<[ast::Attribute]>>>; 2]>,
+ pub codemap_import_info: RwLock<Vec<ImportedFileMap>>,
+ pub attribute_cache: Lock<[Vec<Option<Lrc<[ast::Attribute]>>>; 2]>,
pub root: schema::CrateRoot,
pub trait_impls: FxHashMap<(u32, DefIndex), schema::LazySeq<DefIndex>>,
- pub dep_kind: Cell<DepKind>,
+ pub dep_kind: Lock<DepKind>,
pub source: CrateSource,
pub proc_macros: Option<Vec<(ast::Name, Lrc<SyntaxExtension>)>>,
}
pub struct CStore {
- metas: RefCell<IndexVec<CrateNum, Option<Lrc<CrateMetadata>>>>,
+ metas: RwLock<IndexVec<CrateNum, Option<Lrc<CrateMetadata>>>>,
/// Map from NodeId's of local extern crate statements to crate numbers
- extern_mod_crate_map: RefCell<NodeMap<CrateNum>>,
- pub metadata_loader: Box<MetadataLoader>,
+ extern_mod_crate_map: Lock<NodeMap<CrateNum>>,
+ pub metadata_loader: Box<MetadataLoader + Sync>,
}
impl CStore {
- pub fn new(metadata_loader: Box<MetadataLoader>) -> CStore {
+ pub fn new(metadata_loader: Box<MetadataLoader + Sync>) -> CStore {
CStore {
- metas: RefCell::new(IndexVec::new()),
- extern_mod_crate_map: RefCell::new(FxHashMap()),
+ metas: RwLock::new(IndexVec::new()),
+ extern_mod_crate_map: Lock::new(FxHashMap()),
metadata_loader,
}
}
+ /// You cannot use this function to allocate a CrateNum in a thread-safe manner.
+ /// It is currently only used in CrateLoader which is single-threaded code.
pub fn next_crate_num(&self) -> CrateNum {
CrateNum::new(self.metas.borrow().len() + 1)
}
is_sanitizer_runtime => { cdata.is_sanitizer_runtime(tcx.sess) }
is_profiler_runtime => { cdata.is_profiler_runtime(tcx.sess) }
panic_strategy => { cdata.panic_strategy() }
- extern_crate => { Lrc::new(cdata.extern_crate.get()) }
+ extern_crate => {
+ let r = Lrc::new(*cdata.extern_crate.lock());
+ r
+ }
is_no_builtins => { cdata.is_no_builtins(tcx.sess) }
impl_defaultness => { cdata.get_impl_defaultness(def_id.index) }
reachable_non_generics => {
cdata.is_dllimport_foreign_item(def_id.index)
}
visibility => { cdata.get_visibility(def_id.index) }
- dep_kind => { cdata.dep_kind.get() }
+ dep_kind => {
+ let r = *cdata.dep_kind.lock();
+ r
+ }
crate_name => { cdata.name }
item_children => {
let mut result = vec![];
}
missing_extern_crate_item => {
- match cdata.extern_crate.get() {
+ let r = match *cdata.extern_crate.borrow() {
Some(extern_crate) if !extern_crate.direct => true,
_ => false,
- }
+ };
+ r
}
used_crate_source => { Lrc::new(cdata.source.clone()) }
fn dep_kind_untracked(&self, cnum: CrateNum) -> DepKind
{
- self.get_crate_data(cnum).dep_kind.get()
+ let data = self.get_crate_data(cnum);
+ let r = *data.dep_kind.lock();
+ r
}
fn export_macros_untracked(&self, cnum: CrateNum) {
let data = self.get_crate_data(cnum);
- if data.dep_kind.get() == DepKind::UnexportedMacrosOnly {
- data.dep_kind.set(DepKind::MacrosOnly)
+ let mut dep_kind = data.dep_kind.lock();
+ if *dep_kind == DepKind::UnexportedMacrosOnly {
+ *dep_kind = DepKind::MacrosOnly;
}
}
tokens: body.into(),
legacy: def.legacy,
}),
- vis: codemap::respan(local_span.empty(), ast::VisibilityKind::Inherited),
+ vis: codemap::respan(local_span.shrink_to_lo(), ast::VisibilityKind::Inherited),
tokens: None,
})
}
use cstore::{self, CrateMetadata, MetadataBlob, NativeLibrary};
use schema::*;
-use rustc_data_structures::sync::Lrc;
+use rustc_data_structures::sync::{Lrc, ReadGuard};
use rustc::hir::map::{DefKey, DefPath, DefPathData, DefPathHash};
use rustc::hir;
use rustc::middle::cstore::{LinkagePreference, ExternConstBody,
use rustc::ty::{self, Ty, TyCtxt};
use rustc::ty::codec::TyDecoder;
use rustc::mir::Mir;
+use rustc::util::captures::Captures;
use rustc::util::nodemap::FxHashMap;
-use std::cell::Ref;
use std::collections::BTreeMap;
use std::io;
use std::mem;
// interpreter allocation cache
interpret_alloc_cache: FxHashMap<usize, interpret::AllocId>,
+ // a cache for sizes of interpreter allocations
+ // needed to skip already deserialized allocations
+ interpret_alloc_size: FxHashMap<usize, usize>,
}
/// Abstract over the various ways one can create metadata decoders.
last_filemap_index: 0,
lazy_state: LazyState::NoNode,
interpret_alloc_cache: FxHashMap::default(),
+ interpret_alloc_size: FxHashMap::default(),
}
}
}
}
impl<'a, 'tcx: 'a, T: Decodable> LazySeq<T> {
- pub fn decode<M: Metadata<'a, 'tcx>>(self, meta: M) -> impl Iterator<Item = T> + 'a {
+ pub fn decode<M: Metadata<'a, 'tcx>>(
+ self,
+ meta: M,
+ ) -> impl Iterator<Item = T> + Captures<'tcx> + 'a {
let mut dcx = meta.decoder(self.position);
dcx.lazy_state = LazyState::NodeStart(self.position);
(0..self.len).map(move |_| T::decode(&mut dcx).unwrap())
impl<'a, 'tcx> SpecializedDecoder<interpret::AllocId> for DecodeContext<'a, 'tcx> {
fn specialized_decode(&mut self) -> Result<interpret::AllocId, Self::Error> {
- const MAX1: usize = usize::max_value() - 1;
- let tcx = self.tcx.unwrap();
+ let tcx = self.tcx.expect("need tcx for AllocId decoding");
let pos = self.position();
- match usize::decode(self)? {
- ::std::usize::MAX => {
- let alloc_id = tcx.interpret_interner.reserve();
- trace!("creating alloc id {:?} at {}", alloc_id, pos);
- // insert early to allow recursive allocs
- self.interpret_alloc_cache.insert(pos, alloc_id);
-
- let allocation = interpret::Allocation::decode(self)?;
- trace!("decoded alloc {:?} {:#?}", alloc_id, allocation);
- let allocation = self.tcx.unwrap().intern_const_alloc(allocation);
- tcx.interpret_interner.intern_at_reserved(alloc_id, allocation);
-
- if let Some(glob) = Option::<DefId>::decode(self)? {
- tcx.interpret_interner.cache(glob, alloc_id);
- }
-
- Ok(alloc_id)
- },
- MAX1 => {
- trace!("creating fn alloc id at {}", pos);
- let instance = ty::Instance::decode(self)?;
- trace!("decoded fn alloc instance: {:?}", instance);
- let id = tcx.interpret_interner.create_fn_alloc(instance);
- trace!("created fn alloc id: {:?}", id);
- self.interpret_alloc_cache.insert(pos, id);
- Ok(id)
- },
- shorthand => {
- trace!("loading shorthand {}", shorthand);
- if let Some(&alloc_id) = self.interpret_alloc_cache.get(&shorthand) {
- return Ok(alloc_id);
- }
- trace!("shorthand {} not cached, loading entire allocation", shorthand);
- // need to load allocation
- self.with_position(shorthand, |this| interpret::AllocId::decode(this))
- },
+ if let Some(cached) = self.interpret_alloc_cache.get(&pos).cloned() {
+ // if there's no end position we are currently deserializing a recursive
+ // allocation
+ if let Some(end) = self.interpret_alloc_size.get(&pos).cloned() {
+ trace!("{} already cached as {:?}", pos, cached);
+ // skip ahead
+ self.opaque.set_position(end);
+ return Ok(cached)
+ }
}
+ let id = interpret::specialized_decode_alloc_id(
+ self,
+ tcx,
+ pos,
+ |this, pos, alloc_id| { this.interpret_alloc_cache.insert(pos, alloc_id); },
+ |this, shorthand| {
+ // need to load allocation
+ this.with_position(shorthand, |this| interpret::AllocId::decode(this))
+ }
+ )?;
+ let end_pos = self.position();
+ assert!(self
+ .interpret_alloc_size
+ .insert(pos, end_pos)
+ .is_none());
+ Ok(id)
}
}
};
// Iterate over all children.
- let macros_only = self.dep_kind.get().macros_only();
+ let macros_only = self.dep_kind.lock().macros_only();
for child_index in item.children.decode((self, sess)) {
if macros_only {
continue
if vec_.len() < node_index + 1 {
vec_.resize(node_index + 1, None);
}
+ // This can overwrite the result produced by another thread, but the value
+ // written should be the same
vec_[node_index] = Some(result.clone());
result
}
/// for items inlined from other crates.
pub fn imported_filemaps(&'a self,
local_codemap: &codemap::CodeMap)
- -> Ref<'a, Vec<cstore::ImportedFileMap>> {
+ -> ReadGuard<'a, Vec<cstore::ImportedFileMap>> {
{
let filemaps = self.codemap_import_info.borrow();
if !filemaps.is_empty() {
}
}
+ // Lock the codemap_import_info to ensure this only happens once
+ let mut codemap_import_info = self.codemap_import_info.borrow_mut();
+
+ if !codemap_import_info.is_empty() {
+ drop(codemap_import_info);
+ return self.codemap_import_info.borrow();
+ }
+
let external_codemap = self.root.codemap.decode(self);
let imported_filemaps = external_codemap.map(|filemap_to_import| {
}
}).collect();
+ *codemap_import_info = imported_filemaps;
+ drop(codemap_import_info);
+
// This shouldn't borrow twice, but there is no way to downgrade RefMut to Ref.
- *self.codemap_import_info.borrow_mut() = imported_filemaps;
self.codemap_import_info.borrow()
}
}
impl<'a, 'tcx> SpecializedEncoder<interpret::AllocId> for EncodeContext<'a, 'tcx> {
fn specialized_encode(&mut self, alloc_id: &interpret::AllocId) -> Result<(), Self::Error> {
- trace!("encoding {:?} at {}", alloc_id, self.position());
- if let Some(shorthand) = self.interpret_alloc_shorthands.get(alloc_id).cloned() {
- trace!("encoding {:?} as shorthand to {}", alloc_id, shorthand);
- return shorthand.encode(self);
- }
- let start = self.position();
- // cache the allocation shorthand now, because the allocation itself might recursively
- // point to itself.
- self.interpret_alloc_shorthands.insert(*alloc_id, start);
- if let Some(alloc) = self.tcx.interpret_interner.get_alloc(*alloc_id) {
- trace!("encoding {:?} with {:#?}", alloc_id, alloc);
- usize::max_value().encode(self)?;
- alloc.encode(self)?;
- self.tcx.interpret_interner
- .get_corresponding_static_def_id(*alloc_id)
- .encode(self)?;
- } else if let Some(fn_instance) = self.tcx.interpret_interner.get_fn(*alloc_id) {
- trace!("encoding {:?} with {:#?}", alloc_id, fn_instance);
- (usize::max_value() - 1).encode(self)?;
- fn_instance.encode(self)?;
- } else {
- bug!("alloc id without corresponding allocation: {}", alloc_id);
- }
- Ok(())
+ use std::collections::hash_map::Entry;
+ let tcx = self.tcx;
+ let pos = self.position();
+ let shorthand = match self.interpret_alloc_shorthands.entry(*alloc_id) {
+ Entry::Occupied(entry) => Some(entry.get().clone()),
+ Entry::Vacant(entry) => {
+ // ensure that we don't place any AllocIds at the very beginning
+ // of the metadata file, because that would end up making our indices
+ // not special. This is essentially impossible, but let's make sure
+ assert!(pos >= interpret::SHORTHAND_START);
+ entry.insert(pos);
+ None
+ },
+ };
+ interpret::specialized_encode_alloc_id(
+ self,
+ tcx,
+ *alloc_id,
+ shorthand,
+ )
}
}
builder.args_and_body(block, &arguments, arg_scope, &body.value)
}));
// Attribute epilogue to function's closing brace
- let fn_end = span.with_lo(span.hi());
+ let fn_end = span.shrink_to_hi();
let source_info = builder.source_info(fn_end);
let return_block = builder.return_block();
builder.cfg.terminate(block, source_info,
};
tcx.hir.krate().visit_all_item_likes(&mut visitor);
+
+ visitor.push_extra_entry_roots();
}
// We can only translate items that are instantiable - items all of
let instance = Instance::mono(self.tcx, def_id);
self.output.push(create_fn_mono_item(instance));
-
- self.push_extra_entry_roots(def_id);
}
}
/// monomorphized copy of the start lang item based on
/// the return type of `main`. This is not needed when
/// the user writes their own `start` manually.
- fn push_extra_entry_roots(&mut self, def_id: DefId) {
- if self.entry_fn != Some(def_id) {
- return;
- }
-
+ fn push_extra_entry_roots(&mut self) {
if self.tcx.sess.entry_type.get() != Some(config::EntryMain) {
- return;
+ return
}
+ let main_def_id = if let Some(def_id) = self.entry_fn {
+ def_id
+ } else {
+ return
+ };
+
let start_def_id = match self.tcx.lang_items().require(StartFnLangItem) {
Ok(s) => s,
Err(err) => self.tcx.sess.fatal(&err),
};
- let main_ret_ty = self.tcx.fn_sig(def_id).output();
+ let main_ret_ty = self.tcx.fn_sig(main_def_id).output();
// Given that `main()` has no arguments,
// then its return type cannot have
def_id_to_string(tcx, impl_def_id));
if let Some(trait_ref) = tcx.impl_trait_ref(impl_def_id) {
- let callee_substs = tcx.erase_regions(&trait_ref.substs);
let overridden_methods: FxHashSet<_> =
impl_item_refs.iter()
.map(|iiref| iiref.name)
continue;
}
+ let substs = Substs::for_item(tcx,
+ method.def_id,
+ |_, _| tcx.types.re_erased,
+ |def, _| trait_ref.substs.type_for_def(def));
+
let instance = ty::Instance::resolve(tcx,
ty::ParamEnv::reveal_all(),
method.def_id,
- callee_substs).unwrap();
+ substs).unwrap();
let mono_item = create_fn_mono_item(instance);
if mono_item.is_instantiable(tcx)
}
}
-pub trait BorrowckErrors {
- fn struct_span_err_with_code<'a, S: Into<MultiSpan>>(&'a self,
- sp: S,
- msg: &str,
- code: DiagnosticId)
- -> DiagnosticBuilder<'a>;
-
- fn struct_span_err<'a, S: Into<MultiSpan>>(&'a self,
- sp: S,
- msg: &str)
- -> DiagnosticBuilder<'a>;
+pub trait BorrowckErrors<'cx>: Sized + Copy {
+ fn struct_span_err_with_code<S: Into<MultiSpan>>(self,
+ sp: S,
+ msg: &str,
+ code: DiagnosticId)
+ -> DiagnosticBuilder<'cx>;
+
+ fn struct_span_err<S: Into<MultiSpan>>(self,
+ sp: S,
+ msg: &str)
+ -> DiagnosticBuilder<'cx>;
/// Cancels the given error if we shouldn't emit errors for a given
/// origin in the current mode.
///
/// Always make sure that the error gets passed through this function
/// before you return it.
- fn cancel_if_wrong_origin<'a>(&'a self,
- diag: DiagnosticBuilder<'a>,
- o: Origin)
- -> DiagnosticBuilder<'a>;
+ fn cancel_if_wrong_origin(self,
+ diag: DiagnosticBuilder<'cx>,
+ o: Origin)
+ -> DiagnosticBuilder<'cx>;
- fn cannot_move_when_borrowed(&self, span: Span, desc: &str, o: Origin)
- -> DiagnosticBuilder<'_>
+ fn cannot_move_when_borrowed(self, span: Span, desc: &str, o: Origin)
+ -> DiagnosticBuilder<'cx>
{
let err = struct_span_err!(self, span, E0505,
"cannot move out of `{}` because it is borrowed{OGN}",
self.cancel_if_wrong_origin(err, o)
}
- fn cannot_use_when_mutably_borrowed(&self,
+ fn cannot_use_when_mutably_borrowed(self,
span: Span,
desc: &str,
borrow_span: Span,
borrow_desc: &str,
o: Origin)
- -> DiagnosticBuilder<'_>
+ -> DiagnosticBuilder<'cx>
{
let mut err = struct_span_err!(self, span, E0503,
"cannot use `{}` because it was mutably borrowed{OGN}",
self.cancel_if_wrong_origin(err, o)
}
- fn cannot_act_on_uninitialized_variable(&self,
+ fn cannot_act_on_uninitialized_variable(self,
span: Span,
verb: &str,
desc: &str,
o: Origin)
- -> DiagnosticBuilder
+ -> DiagnosticBuilder<'cx>
{
let err = struct_span_err!(self, span, E0381,
"{} of possibly uninitialized variable: `{}`{OGN}",
self.cancel_if_wrong_origin(err, o)
}
- fn cannot_mutably_borrow_multiply(&self,
+ fn cannot_mutably_borrow_multiply(self,
new_loan_span: Span,
desc: &str,
opt_via: &str,
old_opt_via: &str,
old_load_end_span: Option<Span>,
o: Origin)
- -> DiagnosticBuilder
+ -> DiagnosticBuilder<'cx>
{
let mut err = struct_span_err!(self, new_loan_span, E0499,
"cannot borrow `{}`{} as mutable more than once at a time{OGN}",
self.cancel_if_wrong_origin(err, o)
}
- fn cannot_uniquely_borrow_by_two_closures(&self,
+ fn cannot_uniquely_borrow_by_two_closures(self,
new_loan_span: Span,
desc: &str,
old_loan_span: Span,
old_load_end_span: Option<Span>,
o: Origin)
- -> DiagnosticBuilder
+ -> DiagnosticBuilder<'cx>
{
let mut err = struct_span_err!(self, new_loan_span, E0524,
"two closures require unique access to `{}` at the same time{OGN}",
self.cancel_if_wrong_origin(err, o)
}
- fn cannot_uniquely_borrow_by_one_closure(&self,
+ fn cannot_uniquely_borrow_by_one_closure(self,
new_loan_span: Span,
desc_new: &str,
opt_via: &str,
old_opt_via: &str,
previous_end_span: Option<Span>,
o: Origin)
- -> DiagnosticBuilder
+ -> DiagnosticBuilder<'cx>
{
let mut err = struct_span_err!(self, new_loan_span, E0500,
"closure requires unique access to `{}` but {} is already borrowed{}{OGN}",
self.cancel_if_wrong_origin(err, o)
}
- fn cannot_reborrow_already_uniquely_borrowed(&self,
+ fn cannot_reborrow_already_uniquely_borrowed(self,
new_loan_span: Span,
desc_new: &str,
opt_via: &str,
old_opt_via: &str,
previous_end_span: Option<Span>,
o: Origin)
- -> DiagnosticBuilder
+ -> DiagnosticBuilder<'cx>
{
let mut err = struct_span_err!(self, new_loan_span, E0501,
"cannot borrow `{}`{} as {} because previous closure \
self.cancel_if_wrong_origin(err, o)
}
- fn cannot_reborrow_already_borrowed(&self,
+ fn cannot_reborrow_already_borrowed(self,
span: Span,
desc_new: &str,
msg_new: &str,
msg_old: &str,
old_load_end_span: Option<Span>,
o: Origin)
- -> DiagnosticBuilder
+ -> DiagnosticBuilder<'cx>
{
let mut err = struct_span_err!(self, span, E0502,
"cannot borrow `{}`{} as {} because {} is also borrowed as {}{}{OGN}",
self.cancel_if_wrong_origin(err, o)
}
- fn cannot_assign_to_borrowed(&self, span: Span, borrow_span: Span, desc: &str, o: Origin)
- -> DiagnosticBuilder
+ fn cannot_assign_to_borrowed(self, span: Span, borrow_span: Span, desc: &str, o: Origin)
+ -> DiagnosticBuilder<'cx>
{
let mut err = struct_span_err!(self, span, E0506,
"cannot assign to `{}` because it is borrowed{OGN}",
self.cancel_if_wrong_origin(err, o)
}
- fn cannot_move_into_closure(&self, span: Span, desc: &str, o: Origin)
- -> DiagnosticBuilder
+ fn cannot_move_into_closure(self, span: Span, desc: &str, o: Origin)
+ -> DiagnosticBuilder<'cx>
{
let err = struct_span_err!(self, span, E0504,
"cannot move `{}` into closure because it is borrowed{OGN}",
self.cancel_if_wrong_origin(err, o)
}
- fn cannot_reassign_immutable(&self, span: Span, desc: &str, is_arg: bool, o: Origin)
- -> DiagnosticBuilder
+ fn cannot_reassign_immutable(self, span: Span, desc: &str, is_arg: bool, o: Origin)
+ -> DiagnosticBuilder<'cx>
{
let msg = if is_arg {
"to immutable argument"
self.cancel_if_wrong_origin(err, o)
}
- fn cannot_assign(&self, span: Span, desc: &str, o: Origin) -> DiagnosticBuilder
+ fn cannot_assign(self, span: Span, desc: &str, o: Origin) -> DiagnosticBuilder<'cx>
{
let err = struct_span_err!(self, span, E0594,
"cannot assign to {}{OGN}",
self.cancel_if_wrong_origin(err, o)
}
- fn cannot_assign_static(&self, span: Span, desc: &str, o: Origin)
- -> DiagnosticBuilder
+ fn cannot_assign_static(self, span: Span, desc: &str, o: Origin)
+ -> DiagnosticBuilder<'cx>
{
self.cannot_assign(span, &format!("immutable static item `{}`", desc), o)
}
- fn cannot_move_out_of(&self, move_from_span: Span, move_from_desc: &str, o: Origin)
- -> DiagnosticBuilder
+ fn cannot_move_out_of(self, move_from_span: Span, move_from_desc: &str, o: Origin)
+ -> DiagnosticBuilder<'cx>
{
let mut err = struct_span_err!(self, move_from_span, E0507,
"cannot move out of {}{OGN}",
self.cancel_if_wrong_origin(err, o)
}
- fn cannot_move_out_of_interior_noncopy(&self,
+ fn cannot_move_out_of_interior_noncopy(self,
move_from_span: Span,
ty: ty::Ty,
is_index: bool,
o: Origin)
- -> DiagnosticBuilder
+ -> DiagnosticBuilder<'cx>
{
let type_name = match (&ty.sty, is_index) {
(&ty::TyArray(_, _), true) => "array",
self.cancel_if_wrong_origin(err, o)
}
- fn cannot_move_out_of_interior_of_drop(&self,
+ fn cannot_move_out_of_interior_of_drop(self,
move_from_span: Span,
container_ty: ty::Ty,
o: Origin)
- -> DiagnosticBuilder
+ -> DiagnosticBuilder<'cx>
{
let mut err = struct_span_err!(self, move_from_span, E0509,
"cannot move out of type `{}`, \
self.cancel_if_wrong_origin(err, o)
}
- fn cannot_act_on_moved_value(&self,
+ fn cannot_act_on_moved_value(self,
use_span: Span,
verb: &str,
optional_adverb_for_moved: &str,
moved_path: &str,
o: Origin)
- -> DiagnosticBuilder
+ -> DiagnosticBuilder<'cx>
{
let err = struct_span_err!(self, use_span, E0382,
"{} of {}moved value: `{}`{OGN}",
self.cancel_if_wrong_origin(err, o)
}
- fn cannot_partially_reinit_an_uninit_struct(&self,
+ fn cannot_partially_reinit_an_uninit_struct(self,
span: Span,
uninit_path: &str,
o: Origin)
- -> DiagnosticBuilder
+ -> DiagnosticBuilder<'cx>
{
let err = struct_span_err!(self,
span,
self.cancel_if_wrong_origin(err, o)
}
- fn closure_cannot_assign_to_borrowed(&self,
+ fn closure_cannot_assign_to_borrowed(self,
span: Span,
descr: &str,
o: Origin)
- -> DiagnosticBuilder
+ -> DiagnosticBuilder<'cx>
{
let err = struct_span_err!(self, span, E0595, "closure cannot assign to {}{OGN}",
descr, OGN=o);
self.cancel_if_wrong_origin(err, o)
}
- fn cannot_borrow_path_as_mutable(&self,
+ fn cannot_borrow_path_as_mutable(self,
span: Span,
path: &str,
o: Origin)
- -> DiagnosticBuilder
+ -> DiagnosticBuilder<'cx>
{
let err = struct_span_err!(self, span, E0596, "cannot borrow {} as mutable{OGN}",
path, OGN=o);
self.cancel_if_wrong_origin(err, o)
}
- fn cannot_borrow_across_generator_yield(&self,
+ fn cannot_borrow_across_generator_yield(self,
span: Span,
yield_span: Span,
o: Origin)
- -> DiagnosticBuilder
+ -> DiagnosticBuilder<'cx>
{
let mut err = struct_span_err!(self,
span,
self.cancel_if_wrong_origin(err, o)
}
- fn path_does_not_live_long_enough(&self,
+ fn path_does_not_live_long_enough(self,
span: Span,
path: &str,
o: Origin)
- -> DiagnosticBuilder
+ -> DiagnosticBuilder<'cx>
{
let err = struct_span_err!(self, span, E0597, "{} does not live long enough{OGN}",
path, OGN=o);
self.cancel_if_wrong_origin(err, o)
}
- fn lifetime_too_short_for_reborrow(&self,
+ fn lifetime_too_short_for_reborrow(self,
span: Span,
path: &str,
o: Origin)
- -> DiagnosticBuilder
+ -> DiagnosticBuilder<'cx>
{
let err = struct_span_err!(self, span, E0598,
"lifetime of {} is too short to guarantee \
self.cancel_if_wrong_origin(err, o)
}
- fn cannot_act_on_capture_in_sharable_fn(&self,
+ fn cannot_act_on_capture_in_sharable_fn(self,
span: Span,
bad_thing: &str,
help: (Span, &str),
o: Origin)
- -> DiagnosticBuilder
+ -> DiagnosticBuilder<'cx>
{
let (help_span, help_msg) = help;
let mut err = struct_span_err!(self, span, E0387,
self.cancel_if_wrong_origin(err, o)
}
- fn cannot_assign_into_immutable_reference(&self,
+ fn cannot_assign_into_immutable_reference(self,
span: Span,
bad_thing: &str,
o: Origin)
- -> DiagnosticBuilder
+ -> DiagnosticBuilder<'cx>
{
let mut err = struct_span_err!(self, span, E0389, "{} in a `&` reference{OGN}",
bad_thing, OGN=o);
self.cancel_if_wrong_origin(err, o)
}
- fn cannot_capture_in_long_lived_closure(&self,
+ fn cannot_capture_in_long_lived_closure(self,
closure_span: Span,
borrowed_path: &str,
capture_span: Span,
o: Origin)
- -> DiagnosticBuilder
+ -> DiagnosticBuilder<'cx>
{
let mut err = struct_span_err!(self, closure_span, E0373,
"closure may outlive the current function, \
}
}
-impl<'b, 'gcx, 'tcx> BorrowckErrors for TyCtxt<'b, 'gcx, 'tcx> {
- fn struct_span_err_with_code<'a, S: Into<MultiSpan>>(&'a self,
- sp: S,
- msg: &str,
- code: DiagnosticId)
- -> DiagnosticBuilder<'a>
+impl<'cx, 'gcx, 'tcx> BorrowckErrors<'cx> for TyCtxt<'cx, 'gcx, 'tcx> {
+ fn struct_span_err_with_code<S: Into<MultiSpan>>(self,
+ sp: S,
+ msg: &str,
+ code: DiagnosticId)
+ -> DiagnosticBuilder<'cx>
{
self.sess.struct_span_err_with_code(sp, msg, code)
}
- fn struct_span_err<'a, S: Into<MultiSpan>>(&'a self,
- sp: S,
- msg: &str)
- -> DiagnosticBuilder<'a>
+ fn struct_span_err<S: Into<MultiSpan>>(self,
+ sp: S,
+ msg: &str)
+ -> DiagnosticBuilder<'cx>
{
self.sess.struct_span_err(sp, msg)
}
- fn cancel_if_wrong_origin<'a>(&'a self,
- mut diag: DiagnosticBuilder<'a>,
- o: Origin)
- -> DiagnosticBuilder<'a>
+ fn cancel_if_wrong_origin(self,
+ mut diag: DiagnosticBuilder<'cx>,
+ o: Origin)
+ -> DiagnosticBuilder<'cx>
{
if !o.should_emit_errors(self.borrowck_mode()) {
self.sess.diagnostic().cancel(&mut diag);
}
fn check_lifetime(&self, lifetime: &Lifetime) {
- let valid_names = [keywords::StaticLifetime.name(), keywords::Invalid.name()];
+ let valid_names = [keywords::UnderscoreLifetime.name(),
+ keywords::StaticLifetime.name(),
+ keywords::Invalid.name()];
if !valid_names.contains(&lifetime.ident.name) &&
token::Ident(lifetime.ident.without_first_quote()).is_reserved_ident() {
self.err_handler().span_err(lifetime.span, "lifetimes cannot use keyword names");
}
fn check_label(&self, label: Ident, span: Span) {
- if token::Ident(label.without_first_quote()).is_reserved_ident() || label.name == "'_" {
+ if token::Ident(label.without_first_quote()).is_reserved_ident() {
self.err_handler().span_err(span, &format!("invalid label name `{}`", label.name));
}
}
E0449,
"unnecessary visibility qualifier");
if vis.node == VisibilityKind::Public {
- err.span_label(vis.span, "`pub` not needed here");
+ err.span_label(vis.span, "`pub` not permitted here because it's implied");
}
if let Some(note) = note {
err.note(note);
expander,
def_info: _,
allow_internal_unstable,
- allow_internal_unsafe
+ allow_internal_unsafe,
+ unstable_feature
} => {
let nid = ast::CRATE_NODE_ID;
NormalTT {
expander,
def_info: Some((nid, self.krate_span)),
allow_internal_unstable,
- allow_internal_unsafe
+ allow_internal_unsafe,
+ unstable_feature
}
}
IdentTT(ext, _, allow_internal_unstable) => {
def_info: None,
allow_internal_unstable: false,
allow_internal_unsafe: false,
+ unstable_feature: None,
});
}
.collect();
match use_tree.kind {
- ast::UseTreeKind::Simple(mut ident) => {
+ ast::UseTreeKind::Simple(rename) => {
+ let mut ident = use_tree.ident();
let mut source = module_path.pop().unwrap().node;
let mut type_ns_only = false;
// Replace `use foo::self;` with `use foo;`
let _ = module_path.pop();
source = last_segment.node;
- if ident.name == keywords::SelfValue.name() {
+ if rename.is_none() {
ident = last_segment.node;
}
}
ModuleKind::Block(..) => unreachable!(),
};
source.name = crate_name;
- if ident.name == keywords::DollarCrate.name() {
+ if rename.is_none() {
ident.name = crate_name;
}
// Ensure there is at most one `self` in the list
let self_spans = items.iter().filter_map(|&(ref use_tree, _)| {
- if let ast::UseTreeKind::Simple(ident) = use_tree.kind {
- if ident.name == keywords::SelfValue.name() {
+ if let ast::UseTreeKind::Simple(..) = use_tree.kind {
+ if use_tree.ident().name == keywords::SelfValue.name() {
return Some(use_tree.span);
}
}
match item.node {
ItemKind::Use(ref use_tree) => {
- // Just an empty prefix to start out
+ // Imports are resolved as global by default, add starting root segment.
let prefix = ast::Path {
- segments: vec![],
+ segments: use_tree.prefix.make_root().into_iter().collect(),
span: use_tree.span,
};
);
}
- ItemKind::ExternCrate(as_name) => {
+ ItemKind::ExternCrate(orig_name) => {
self.crate_loader.process_item(item, &self.definitions);
// n.b. we don't need to look at the path option here, because cstore already did
id: item.id,
parent,
imported_module: Cell::new(Some(module)),
- subclass: ImportDirectiveSubclass::ExternCrate(as_name),
+ subclass: ImportDirectiveSubclass::ExternCrate(orig_name),
span: item.span,
module_path: Vec::new(),
vis: Cell::new(vis),
// don't suggest placing a use before the prelude
// import or other generated ones
if item.span.ctxt().outer().expn_info().is_none() {
- self.span = Some(item.span.with_hi(item.span.lo()));
+ self.span = Some(item.span.shrink_to_lo());
self.found_use = true;
return;
}
if item.span.ctxt().outer().expn_info().is_none() {
// don't insert between attributes and an item
if item.attrs.is_empty() {
- self.span = Some(item.span.with_hi(item.span.lo()));
+ self.span = Some(item.span.shrink_to_lo());
} else {
// find the first attribute on the item
for attr in &item.attrs {
if self.span.map_or(true, |span| attr.span < span) {
- self.span = Some(attr.span.with_hi(attr.span.lo()));
+ self.span = Some(attr.span.shrink_to_lo());
}
}
}
}
ItemKind::Use(ref use_tree) => {
+ // Imports are resolved as global by default, add starting root segment.
let path = Path {
- segments: vec![],
+ segments: use_tree.prefix.make_root().into_iter().collect(),
span: use_tree.span,
};
self.resolve_use_tree(item.id, use_tree, &path);
None,
&path,
trait_ref.path.span,
- trait_ref.path.segments.last().unwrap().span,
PathSource::Trait(AliasPossibility::No)
).base_def();
if def != Def::Err {
let segments = &path.segments.iter()
.map(|seg| respan(seg.span, seg.identifier))
.collect::<Vec<_>>();
- let ident_span = path.segments.last().map_or(path.span, |seg| seg.span);
- self.smart_resolve_path_fragment(id, qself, segments, path.span, ident_span, source)
+ self.smart_resolve_path_fragment(id, qself, segments, path.span, source)
}
fn smart_resolve_path_fragment(&mut self,
qself: Option<&QSelf>,
path: &[SpannedIdent],
span: Span,
- ident_span: Span,
source: PathSource)
-> PathResolution {
+ let ident_span = path.last().map_or(span, |ident| ident.span);
let ns = source.namespace();
let is_expected = &|def| source.is_expected(def);
let is_enum_variant = &|def| if let Def::Variant(..) = def { true } else { false };
// Make sure `A::B` in `<T as A>::B::C` is a trait item.
let ns = if qself.position + 1 == path.len() { ns } else { TypeNS };
let res = self.smart_resolve_path_fragment(id, None, &path[..qself.position + 1],
- span, span, PathSource::TraitItem(ns));
+ span, PathSource::TraitItem(ns));
return Some(PathResolution::with_unresolved_segments(
res.base_def(), res.unresolved_segments() + path.len() - qself.position - 1
));
ty::Visibility::Restricted(self.current_module.normal_ancestor_id)
}
ast::VisibilityKind::Restricted { ref path, id, .. } => {
- let def = self.smart_resolve_path(id, None, path,
- PathSource::Visibility).base_def();
+ // Visibilities are resolved as global by default, add starting root segment.
+ let segments = path.make_root().iter().chain(path.segments.iter())
+ .map(|seg| respan(seg.span, seg.identifier))
+ .collect::<Vec<_>>();
+ let def = self.smart_resolve_path_fragment(id, None, &segments, path.span,
+ PathSource::Visibility).base_def();
if def == Def::Err {
ty::Visibility::Public
} else {
}
PathResult::Failed(span, msg, true) => {
let (mut self_path, mut self_result) = (module_path.clone(), None);
- if !self_path.is_empty() &&
- !token::Ident(self_path[0].node).is_path_segment_keyword() &&
- !(self_path.len() > 1 &&
- token::Ident(self_path[1].node).is_path_segment_keyword())
- {
+ let is_special = |ident| token::Ident(ident).is_path_segment_keyword() &&
+ ident.name != keywords::CrateRoot.name();
+ if !self_path.is_empty() && !is_special(self_path[0].node) &&
+ !(self_path.len() > 1 && is_special(self_path[1].node)) {
self_path[0].node.name = keywords::SelfValue.name();
self_result = Some(self.resolve_path(&self_path, None, false, span));
}
fn process_trait_item(&mut self, trait_item: &'l ast::TraitItem, trait_id: DefId) {
self.process_macro_use(trait_item.span);
- let vis_span = trait_item.span.empty();
+ let vis_span = trait_item.span.shrink_to_lo();
match trait_item.node {
ast::TraitItemKind::Const(ref ty, ref expr) => {
self.process_assoc_const(
.map(::id_from_def_id);
match use_tree.kind {
- ast::UseTreeKind::Simple(ident) => {
+ ast::UseTreeKind::Simple(..) => {
+ let ident = use_tree.ident();
let path = ast::Path {
segments: prefix.segments
.iter()
mod normalize_projection_ty;
mod normalize_erasing_regions;
mod util;
+pub mod lowering;
use rustc::ty::maps::Providers;
normalize_projection_ty: normalize_projection_ty::normalize_projection_ty,
normalize_ty_after_erasing_regions:
normalize_erasing_regions::normalize_ty_after_erasing_regions,
+ program_clauses_for: lowering::program_clauses_for,
..*p
};
}
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use rustc::hir::{self, ImplPolarity};
+use rustc::hir::def_id::DefId;
+use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor};
+use rustc::ty::{self, TyCtxt};
+use rustc::traits::{QuantifierKind, Goal, DomainGoal, Clause, WhereClauseAtom};
+use syntax::ast;
+use rustc_data_structures::sync::Lrc;
+
+trait Lower<T> {
+ /// Lower a rustc construction (e.g. `ty::TraitPredicate`) to a chalk-like type.
+ fn lower(&self) -> T;
+}
+
+impl<T, U> Lower<Vec<U>> for Vec<T> where T: Lower<U> {
+ fn lower(&self) -> Vec<U> {
+ self.iter().map(|item| item.lower()).collect()
+ }
+}
+
+impl<'tcx> Lower<WhereClauseAtom<'tcx>> for ty::TraitPredicate<'tcx> {
+ fn lower(&self) -> WhereClauseAtom<'tcx> {
+ WhereClauseAtom::Implemented(*self)
+ }
+}
+
+impl<'tcx> Lower<WhereClauseAtom<'tcx>> for ty::ProjectionPredicate<'tcx> {
+ fn lower(&self) -> WhereClauseAtom<'tcx> {
+ WhereClauseAtom::ProjectionEq(*self)
+ }
+}
+
+impl<'tcx, T> Lower<DomainGoal<'tcx>> for T where T: Lower<WhereClauseAtom<'tcx>> {
+ fn lower(&self) -> DomainGoal<'tcx> {
+ DomainGoal::Holds(self.lower())
+ }
+}
+
+impl<'tcx> Lower<DomainGoal<'tcx>> for ty::RegionOutlivesPredicate<'tcx> {
+ fn lower(&self) -> DomainGoal<'tcx> {
+ DomainGoal::RegionOutlives(*self)
+ }
+}
+
+impl<'tcx> Lower<DomainGoal<'tcx>> for ty::TypeOutlivesPredicate<'tcx> {
+ fn lower(&self) -> DomainGoal<'tcx> {
+ DomainGoal::TypeOutlives(*self)
+ }
+}
+
+/// `ty::Binder` is used for wrapping a rustc construction possibly containing generic
+/// lifetimes, e.g. `for<'a> T: Fn(&'a i32)`. Instead of representing higher-ranked things
+/// in that leaf-form (i.e. `Holds(Implemented(Binder<TraitPredicate>))` in the previous
+/// example), we model them with quantified goals, e.g. as for the previous example:
+/// `forall<'a> { T: Fn(&'a i32) }` which corresponds to something like
+/// `Binder<Holds(Implemented(TraitPredicate))>`.
+///
+/// Also, if `self` does not contain generic lifetimes, we can safely drop the binder and we
+/// can directly lower to a leaf goal instead of a quantified goal.
+impl<'tcx, T> Lower<Goal<'tcx>> for ty::Binder<T>
+ where T: Lower<DomainGoal<'tcx>> + ty::fold::TypeFoldable<'tcx> + Copy
+{
+ fn lower(&self) -> Goal<'tcx> {
+ match self.no_late_bound_regions() {
+ Some(p) => p.lower().into(),
+ None => Goal::Quantified(
+ QuantifierKind::Universal,
+ Box::new(self.map_bound(|p| p.lower().into()))
+ ),
+ }
+ }
+}
+
+impl<'tcx> Lower<Goal<'tcx>> for ty::Predicate<'tcx> {
+ fn lower(&self) -> Goal<'tcx> {
+ use rustc::ty::Predicate::*;
+
+ match self {
+ Trait(predicate) => predicate.lower(),
+ RegionOutlives(predicate) => predicate.lower(),
+ TypeOutlives(predicate) => predicate.lower(),
+ Projection(predicate) => predicate.lower(),
+ WellFormed(ty) => DomainGoal::WellFormedTy(*ty).into(),
+ ObjectSafe(..) |
+ ClosureKind(..) |
+ Subtype(..) |
+ ConstEvaluatable(..) => unimplemented!(),
+ }
+ }
+}
+
+crate fn program_clauses_for<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
+ -> Lrc<Vec<Clause<'tcx>>>
+{
+ let node_id = tcx.hir.as_local_node_id(def_id).unwrap();
+ let item = tcx.hir.expect_item(node_id);
+ match item.node {
+ hir::ItemImpl(..) => program_clauses_for_impl(tcx, def_id),
+
+ // FIXME: other constructions e.g. traits, associated types...
+ _ => Lrc::new(vec![]),
+ }
+}
+
+fn program_clauses_for_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
+ -> Lrc<Vec<Clause<'tcx>>>
+{
+ if let ImplPolarity::Negative = tcx.impl_polarity(def_id) {
+ return Lrc::new(vec![]);
+ }
+
+ // Rule Implemented-From-Impl
+ //
+ // (see rustc guide)
+
+ let trait_ref = tcx.impl_trait_ref(def_id).unwrap();
+ let trait_ref = ty::TraitPredicate { trait_ref }.lower();
+ let where_clauses = tcx.predicates_of(def_id).predicates.lower();
+
+ let clause = Clause::Implies(where_clauses, trait_ref);
+ Lrc::new(vec![clause])
+}
+
+pub fn dump_program_clauses<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
+ if !tcx.features().rustc_attrs {
+ return;
+ }
+
+ let mut visitor = ClauseDumper { tcx };
+ tcx.hir.krate().visit_all_item_likes(&mut visitor.as_deep_visitor());
+}
+
+struct ClauseDumper<'a, 'tcx: 'a> {
+ tcx: TyCtxt<'a, 'tcx, 'tcx>,
+}
+
+impl <'a, 'tcx> ClauseDumper<'a, 'tcx > {
+ fn process_attrs(&mut self, node_id: ast::NodeId, attrs: &[ast::Attribute]) {
+ let def_id = self.tcx.hir.local_def_id(node_id);
+ for attr in attrs {
+ if attr.check_name("rustc_dump_program_clauses") {
+ let clauses = self.tcx.program_clauses_for(def_id);
+ for clause in &*clauses {
+ self.tcx.sess.struct_span_err(attr.span, &format!("{}", clause)).emit();
+ }
+ }
+ }
+ }
+}
+
+impl<'a, 'tcx> Visitor<'tcx> for ClauseDumper<'a, 'tcx> {
+ fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+ NestedVisitorMap::OnlyBodies(&self.tcx.hir)
+ }
+
+ fn visit_item(&mut self, item: &'tcx hir::Item) {
+ self.process_attrs(item.id, &item.attrs);
+ intravisit::walk_item(self, item);
+ }
+
+ fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem) {
+ self.process_attrs(trait_item.id, &trait_item.attrs);
+ intravisit::walk_trait_item(self, trait_item);
+ }
+
+ fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) {
+ self.process_attrs(impl_item.id, &impl_item.attrs);
+ intravisit::walk_impl_item(self, impl_item);
+ }
+
+ fn visit_struct_field(&mut self, s: &'tcx hir::StructField) {
+ self.process_attrs(s.id, &s.attrs);
+ intravisit::walk_struct_field(self, s);
+ }
+}
-NB: This crate is part of the Rust compiler. For an overview of the
-compiler as a whole, see
-[the README.md file found in `librustc`](../librustc/README.md).
-
The `trans` crate contains the code to convert from MIR into LLVM IR,
and then from LLVM IR into machine code. In general it contains code
that runs towards the end of the compilation process.
+
+For more information about how trans works, see the [rustc guide].
+
+[rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/trans.html
use syntax_pos::symbol::Symbol;
use type_::Type;
use context::{is_pie_binary, get_reloc_model};
+use common::{C_bytes_in_context, val_ty};
use jobserver::{Client, Acquired};
use rustc_demangle;
// emscripten's ecc compiler, when used as the linker.
obj_is_bitcode: bool,
no_integrated_as: bool,
+ embed_bitcode: bool,
+ embed_bitcode_marker: bool,
}
impl ModuleConfig {
emit_asm: false,
emit_obj: false,
obj_is_bitcode: false,
+ embed_bitcode: false,
+ embed_bitcode_marker: false,
no_integrated_as: false,
no_verify: false,
self.time_passes = sess.time_passes();
self.inline_threshold = sess.opts.cg.inline_threshold;
self.obj_is_bitcode = sess.target.target.options.obj_is_bitcode;
+ let embed_bitcode = sess.target.target.options.embed_bitcode ||
+ sess.opts.debugging_opts.embed_bitcode;
+ if embed_bitcode {
+ match sess.opts.optimize {
+ config::OptLevel::No |
+ config::OptLevel::Less => {
+ self.embed_bitcode_marker = embed_bitcode;
+ }
+ _ => self.embed_bitcode = embed_bitcode,
+ }
+ }
// Copy what clang does by turning on loop vectorization at O2 and
// slp vectorization at O3. Otherwise configure other optimization aspects
let obj_out = cgcx.output_filenames.temp_path(OutputType::Object, module_name);
- if write_bc || config.emit_bc_compressed {
+ if write_bc || config.emit_bc_compressed || config.embed_bitcode {
let thin;
let old;
let data = if llvm::LLVMRustThinLTOAvailable() {
timeline.record("write-bc");
}
+ if config.embed_bitcode {
+ embed_bitcode(cgcx, llcx, llmod, Some(data));
+ timeline.record("embed-bc");
+ }
+
if config.emit_bc_compressed {
let dst = bc_out.with_extension(RLIB_BYTECODE_EXTENSION);
let data = bytecode::encode(&mtrans.llmod_id, data);
}
timeline.record("compress-bc");
}
+ } else if config.embed_bitcode_marker {
+ embed_bitcode(cgcx, llcx, llmod, None);
}
time_ext(config.time_passes, None, &format!("codegen passes [{}]", module_name.unwrap()),
&cgcx.output_filenames))
}
+/// Embed the bitcode of an LLVM module in the LLVM module itself.
+///
+/// This is done primarily for iOS where it appears to be standard to compile C
+/// code at least with `-fembed-bitcode` which creates two sections in the
+/// executable:
+///
+/// * __LLVM,__bitcode
+/// * __LLVM,__cmdline
+///
+/// It appears *both* of these sections are necessary to get the linker to
+/// recognize what's going on. For us though we just always throw in an empty
+/// cmdline section.
+///
+/// Furthermore debug/O1 builds don't actually embed bitcode but rather just
+/// embed an empty section.
+///
+/// Basically all of this is us attempting to follow in the footsteps of clang
+/// on iOS. See #35968 for lots more info.
+unsafe fn embed_bitcode(cgcx: &CodegenContext,
+ llcx: ContextRef,
+ llmod: ModuleRef,
+ bitcode: Option<&[u8]>) {
+ let llconst = C_bytes_in_context(llcx, bitcode.unwrap_or(&[]));
+ let llglobal = llvm::LLVMAddGlobal(
+ llmod,
+ val_ty(llconst).to_ref(),
+ "rustc.embedded.module\0".as_ptr() as *const _,
+ );
+ llvm::LLVMSetInitializer(llglobal, llconst);
+ let section = if cgcx.opts.target_triple.contains("-ios") {
+ "__LLVM,__bitcode\0"
+ } else {
+ ".llvmbc\0"
+ };
+ llvm::LLVMSetSection(llglobal, section.as_ptr() as *const _);
+ llvm::LLVMRustSetLinkage(llglobal, llvm::Linkage::PrivateLinkage);
+
+ let llconst = C_bytes_in_context(llcx, &[]);
+ let llglobal = llvm::LLVMAddGlobal(
+ llmod,
+ val_ty(llconst).to_ref(),
+ "rustc.embedded.cmdline\0".as_ptr() as *const _,
+ );
+ llvm::LLVMSetInitializer(llglobal, llconst);
+ let section = if cgcx.opts.target_triple.contains("-ios") {
+ "__LLVM,__cmdline\0"
+ } else {
+ ".llvmcmd\0"
+ };
+ llvm::LLVMSetSection(llglobal, section.as_ptr() as *const _);
+ llvm::LLVMRustSetLinkage(llglobal, llvm::Linkage::PrivateLinkage);
+}
+
pub(crate) struct CompiledModules {
pub modules: Vec<CompiledModule>,
pub metadata_module: CompiledModule,
}
}
+ pub fn vector_reduce_fadd_fast(&self, acc: ValueRef, src: ValueRef) -> ValueRef {
+ self.count_insn("vector.reduce.fadd_fast");
+ unsafe {
+ // FIXME: add a non-fast math version once
+ // https://bugs.llvm.org/show_bug.cgi?id=36732
+ // is fixed.
+ let instr = llvm::LLVMRustBuildVectorReduceFAdd(self.llbuilder, acc, src);
+ if instr.is_null() {
+ bug!("LLVMRustBuildVectorReduceFAdd is not available in LLVM version < 5.0");
+ }
+ llvm::LLVMRustSetHasUnsafeAlgebra(instr);
+ instr
+ }
+ }
+ pub fn vector_reduce_fmul_fast(&self, acc: ValueRef, src: ValueRef) -> ValueRef {
+ self.count_insn("vector.reduce.fmul_fast");
+ unsafe {
+ // FIXME: add a non-fast math version once
+ // https://bugs.llvm.org/show_bug.cgi?id=36732
+ // is fixed.
+ let instr = llvm::LLVMRustBuildVectorReduceFMul(self.llbuilder, acc, src);
+ if instr.is_null() {
+ bug!("LLVMRustBuildVectorReduceFMul is not available in LLVM version < 5.0");
+ }
+ llvm::LLVMRustSetHasUnsafeAlgebra(instr);
+ instr
+ }
+ }
+ pub fn vector_reduce_add(&self, src: ValueRef) -> ValueRef {
+ self.count_insn("vector.reduce.add");
+ unsafe {
+ let instr = llvm::LLVMRustBuildVectorReduceAdd(self.llbuilder, src);
+ if instr.is_null() {
+ bug!("LLVMRustBuildVectorReduceAdd is not available in LLVM version < 5.0");
+ }
+ instr
+ }
+ }
+ pub fn vector_reduce_mul(&self, src: ValueRef) -> ValueRef {
+ self.count_insn("vector.reduce.mul");
+ unsafe {
+ let instr = llvm::LLVMRustBuildVectorReduceMul(self.llbuilder, src);
+ if instr.is_null() {
+ bug!("LLVMRustBuildVectorReduceMul is not available in LLVM version < 5.0");
+ }
+ instr
+ }
+ }
+ pub fn vector_reduce_and(&self, src: ValueRef) -> ValueRef {
+ self.count_insn("vector.reduce.and");
+ unsafe {
+ let instr = llvm::LLVMRustBuildVectorReduceAnd(self.llbuilder, src);
+ if instr.is_null() {
+ bug!("LLVMRustBuildVectorReduceAnd is not available in LLVM version < 5.0");
+ }
+ instr
+ }
+ }
+ pub fn vector_reduce_or(&self, src: ValueRef) -> ValueRef {
+ self.count_insn("vector.reduce.or");
+ unsafe {
+ let instr = llvm::LLVMRustBuildVectorReduceOr(self.llbuilder, src);
+ if instr.is_null() {
+ bug!("LLVMRustBuildVectorReduceOr is not available in LLVM version < 5.0");
+ }
+ instr
+ }
+ }
+ pub fn vector_reduce_xor(&self, src: ValueRef) -> ValueRef {
+ self.count_insn("vector.reduce.xor");
+ unsafe {
+ let instr = llvm::LLVMRustBuildVectorReduceXor(self.llbuilder, src);
+ if instr.is_null() {
+ bug!("LLVMRustBuildVectorReduceXor is not available in LLVM version < 5.0");
+ }
+ instr
+ }
+ }
+ pub fn vector_reduce_fmin(&self, src: ValueRef) -> ValueRef {
+ self.count_insn("vector.reduce.fmin");
+ unsafe {
+ let instr = llvm::LLVMRustBuildVectorReduceFMin(self.llbuilder, src, true);
+ if instr.is_null() {
+ bug!("LLVMRustBuildVectorReduceFMin is not available in LLVM version < 5.0");
+ }
+ instr
+ }
+ }
+ pub fn vector_reduce_fmax(&self, src: ValueRef) -> ValueRef {
+ self.count_insn("vector.reduce.fmax");
+ unsafe {
+ let instr = llvm::LLVMRustBuildVectorReduceFMax(self.llbuilder, src, true);
+ if instr.is_null() {
+ bug!("LLVMRustBuildVectorReduceFMax is not available in LLVM version < 5.0");
+ }
+ instr
+ }
+ }
+ pub fn vector_reduce_fmin_fast(&self, src: ValueRef) -> ValueRef {
+ self.count_insn("vector.reduce.fmin_fast");
+ unsafe {
+ let instr = llvm::LLVMRustBuildVectorReduceFMin(self.llbuilder, src, false);
+ if instr.is_null() {
+ bug!("LLVMRustBuildVectorReduceFMin is not available in LLVM version < 5.0");
+ }
+ llvm::LLVMRustSetHasUnsafeAlgebra(instr);
+ instr
+ }
+ }
+ pub fn vector_reduce_fmax_fast(&self, src: ValueRef) -> ValueRef {
+ self.count_insn("vector.reduce.fmax_fast");
+ unsafe {
+ let instr = llvm::LLVMRustBuildVectorReduceFMax(self.llbuilder, src, false);
+ if instr.is_null() {
+ bug!("LLVMRustBuildVectorReduceFMax is not available in LLVM version < 5.0");
+ }
+ llvm::LLVMRustSetHasUnsafeAlgebra(instr);
+ instr
+ }
+ }
+ pub fn vector_reduce_min(&self, src: ValueRef, is_signed: bool) -> ValueRef {
+ self.count_insn("vector.reduce.min");
+ unsafe {
+ let instr = llvm::LLVMRustBuildVectorReduceMin(self.llbuilder, src, is_signed);
+ if instr.is_null() {
+ bug!("LLVMRustBuildVectorReduceMin is not available in LLVM version < 5.0");
+ }
+ instr
+ }
+ }
+ pub fn vector_reduce_max(&self, src: ValueRef, is_signed: bool) -> ValueRef {
+ self.count_insn("vector.reduce.max");
+ unsafe {
+ let instr = llvm::LLVMRustBuildVectorReduceMax(self.llbuilder, src, is_signed);
+ if instr.is_null() {
+ bug!("LLVMRustBuildVectorReduceMax is not available in LLVM version < 5.0");
+ }
+ instr
+ }
+ }
+
pub fn extract_value(&self, agg_val: ValueRef, idx: u64) -> ValueRef {
self.count_insn("extractvalue");
assert_eq!(idx as c_uint as u64, idx);
}
}
+pub fn const_get_real(v: ValueRef) -> Option<(f64, bool)> {
+ unsafe {
+ if is_const_real(v) {
+ let mut loses_info: llvm::Bool = ::std::mem::uninitialized();
+ let r = llvm::LLVMConstRealGetDouble(v, &mut loses_info as *mut llvm::Bool);
+ let loses_info = if loses_info == 1 { true } else { false };
+ Some((r, loses_info))
+ } else {
+ None
+ }
+ }
+}
+
pub fn const_to_uint(v: ValueRef) -> u64 {
unsafe {
llvm::LLVMConstIntGetZExtValue(v)
}
}
+pub fn is_const_real(v: ValueRef) -> bool {
+ unsafe {
+ !llvm::LLVMIsAConstantFP(v).is_null()
+ }
+}
+
+
#[inline]
fn hi_lo_to_u128(lo: u64, hi: u64) -> u128 {
((hi as u128) << 64) | (lo as u128)
name, $($fmt)*));
}
}
- macro_rules! require {
- ($cond: expr, $($fmt: tt)*) => {
- if !$cond {
+ macro_rules! return_error {
+ ($($fmt: tt)*) => {
+ {
emit_error!($($fmt)*);
return Err(());
}
}
}
+
+ macro_rules! require {
+ ($cond: expr, $($fmt: tt)*) => {
+ if !$cond {
+ return_error!($($fmt)*);
+ }
+ };
+ }
macro_rules! require_simd {
($ty: expr, $position: expr) => {
require!($ty.is_simd(), "expected SIMD {} type, found non-SIMD `{}`", $position, $ty)
return Ok(bx.extract_element(args[0].immediate(), args[1].immediate()))
}
+ macro_rules! arith_red {
+ ($name:tt : $integer_reduce:ident, $float_reduce:ident, $ordered:expr) => {
+ if name == $name {
+ require!(ret_ty == in_elem,
+ "expected return type `{}` (element of input `{}`), found `{}`",
+ in_elem, in_ty, ret_ty);
+ return match in_elem.sty {
+ ty::TyInt(_) | ty::TyUint(_) => {
+ let r = bx.$integer_reduce(args[0].immediate());
+ if $ordered {
+ // if overflow occurs, the result is the
+ // mathematical result modulo 2^n:
+ if name.contains("mul") {
+ Ok(bx.mul(args[1].immediate(), r))
+ } else {
+ Ok(bx.add(args[1].immediate(), r))
+ }
+ } else {
+ Ok(bx.$integer_reduce(args[0].immediate()))
+ }
+ },
+ ty::TyFloat(f) => {
+ // ordered arithmetic reductions take an accumulator
+ let acc = if $ordered {
+ let acc = args[1].immediate();
+ // FIXME: https://bugs.llvm.org/show_bug.cgi?id=36734
+ // * if the accumulator of the fadd isn't 0, incorrect
+ // code is generated
+ // * if the accumulator of the fmul isn't 1, incorrect
+ // code is generated
+ match const_get_real(acc) {
+ None => return_error!("accumulator of {} is not a constant", $name),
+ Some((v, loses_info)) => {
+ if $name.contains("mul") && v != 1.0_f64 {
+ return_error!("accumulator of {} is not 1.0", $name);
+ } else if $name.contains("add") && v != 0.0_f64 {
+ return_error!("accumulator of {} is not 0.0", $name);
+ } else if loses_info {
+ return_error!("accumulator of {} loses information", $name);
+ }
+ }
+ }
+ acc
+ } else {
+ // unordered arithmetic reductions do not:
+ match f.bit_width() {
+ 32 => C_undef(Type::f32(bx.cx)),
+ 64 => C_undef(Type::f64(bx.cx)),
+ v => {
+ return_error!(r#"
+unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#,
+ $name, in_ty, in_elem, v, ret_ty
+ )
+ }
+ }
+
+ };
+ Ok(bx.$float_reduce(acc, args[0].immediate()))
+ }
+ _ => {
+ return_error!(
+ "unsupported {} from `{}` with element `{}` to `{}`",
+ $name, in_ty, in_elem, ret_ty
+ )
+ },
+ }
+ }
+ }
+ }
+
+ arith_red!("simd_reduce_add_ordered": vector_reduce_add, vector_reduce_fadd_fast, true);
+ arith_red!("simd_reduce_mul_ordered": vector_reduce_mul, vector_reduce_fmul_fast, true);
+ arith_red!("simd_reduce_add_unordered": vector_reduce_add, vector_reduce_fadd_fast, false);
+ arith_red!("simd_reduce_mul_unordered": vector_reduce_mul, vector_reduce_fmul_fast, false);
+
+ macro_rules! minmax_red {
+ ($name:tt: $int_red:ident, $float_red:ident) => {
+ if name == $name {
+ require!(ret_ty == in_elem,
+ "expected return type `{}` (element of input `{}`), found `{}`",
+ in_elem, in_ty, ret_ty);
+ return match in_elem.sty {
+ ty::TyInt(_i) => {
+ Ok(bx.$int_red(args[0].immediate(), true))
+ },
+ ty::TyUint(_u) => {
+ Ok(bx.$int_red(args[0].immediate(), false))
+ },
+ ty::TyFloat(_f) => {
+ Ok(bx.$float_red(args[0].immediate()))
+ }
+ _ => {
+ return_error!("unsupported {} from `{}` with element `{}` to `{}`",
+ $name, in_ty, in_elem, ret_ty)
+ },
+ }
+ }
+
+ }
+ }
+
+ minmax_red!("simd_reduce_min": vector_reduce_min, vector_reduce_fmin);
+ minmax_red!("simd_reduce_max": vector_reduce_max, vector_reduce_fmax);
+
+ minmax_red!("simd_reduce_min_nanless": vector_reduce_min, vector_reduce_fmin_fast);
+ minmax_red!("simd_reduce_max_nanless": vector_reduce_max, vector_reduce_fmax_fast);
+
+ macro_rules! bitwise_red {
+ ($name:tt : $red:ident, $boolean:expr) => {
+ if name == $name {
+ let input = if !$boolean {
+ require!(ret_ty == in_elem,
+ "expected return type `{}` (element of input `{}`), found `{}`",
+ in_elem, in_ty, ret_ty);
+ args[0].immediate()
+ } else {
+ match in_elem.sty {
+ ty::TyInt(_) | ty::TyUint(_) => {},
+ _ => {
+ return_error!("unsupported {} from `{}` with element `{}` to `{}`",
+ $name, in_ty, in_elem, ret_ty)
+ }
+ }
+
+ // boolean reductions operate on vectors of i1s:
+ let i1 = Type::i1(bx.cx);
+ let i1xn = Type::vector(&i1, in_len as u64);
+ bx.trunc(args[0].immediate(), i1xn)
+ };
+ return match in_elem.sty {
+ ty::TyInt(_) | ty::TyUint(_) => {
+ let r = bx.$red(input);
+ Ok(
+ if !$boolean {
+ r
+ } else {
+ bx.zext(r, Type::bool(bx.cx))
+ }
+ )
+ },
+ _ => {
+ return_error!("unsupported {} from `{}` with element `{}` to `{}`",
+ $name, in_ty, in_elem, ret_ty)
+ },
+ }
+ }
+ }
+ }
+
+ bitwise_red!("simd_reduce_and": vector_reduce_and, false);
+ bitwise_red!("simd_reduce_or": vector_reduce_or, false);
+ bitwise_red!("simd_reduce_xor": vector_reduce_xor, false);
+ bitwise_red!("simd_reduce_all": vector_reduce_and, true);
+ bitwise_red!("simd_reduce_any": vector_reduce_or, true);
+
if name == "simd_cast" {
require_simd!(ret_ty, "return");
let out_len = ret_ty.simd_size(tcx);
#![feature(libc)]
#![feature(quote)]
#![feature(rustc_diagnostic_macros)]
-#![feature(slice_patterns)]
+#![cfg_attr(stage0, feature(slice_patterns))]
#![feature(conservative_impl_trait)]
#![feature(optin_builtin_traits)]
#![feature(inclusive_range_fields)]
target_features(sess)
}
- fn metadata_loader(&self) -> Box<MetadataLoader> {
+ fn metadata_loader(&self) -> Box<MetadataLoader + Sync> {
box metadata::LlvmMetadataLoader
}
#![feature(i128_type)]
#![feature(quote)]
#![feature(rustc_diagnostic_macros)]
-#![feature(slice_patterns)]
#![feature(conservative_impl_trait)]
extern crate ar;
fn print_version(&self) {}
fn diagnostics(&self) -> &[(&'static str, &'static str)] { &[] }
- fn metadata_loader(&self) -> Box<MetadataLoader>;
+ fn metadata_loader(&self) -> Box<MetadataLoader + Sync>;
fn provide(&self, _providers: &mut Providers);
fn provide_extern(&self, _providers: &mut Providers);
fn trans_crate<'a, 'tcx>(
pub struct DummyTransCrate;
impl TransCrate for DummyTransCrate {
- fn metadata_loader(&self) -> Box<MetadataLoader> {
+ fn metadata_loader(&self) -> Box<MetadataLoader + Sync> {
box DummyMetadataLoader(())
}
}
}
- fn metadata_loader(&self) -> Box<MetadataLoader> {
+ fn metadata_loader(&self) -> Box<MetadataLoader + Sync> {
box NoLlvmMetadataLoader
}
use syntax::util::parser::PREC_POSTFIX;
use syntax_pos::{self, Span};
use rustc::hir;
-use rustc::hir::print;
use rustc::hir::def::Def;
+use rustc::hir::map::NodeItem;
+use rustc::hir::{Item, ItemConst, print};
use rustc::ty::{self, Ty, AssociatedItem};
use errors::{DiagnosticBuilder, CodeMapper};
checked_ty: Ty<'tcx>,
expected_ty: Ty<'tcx>)
-> bool {
+ let parent_id = self.tcx.hir.get_parent_node(expr.id);
+ match self.tcx.hir.find(parent_id) {
+ Some(parent) => {
+ // Shouldn't suggest `.into()` on `const`s.
+ if let NodeItem(Item { node: ItemConst(_, _), .. }) = parent {
+ // FIXME(estebank): modify once we decide to suggest `as` casts
+ return false;
+ }
+ }
+ None => {}
+ };
+
let will_truncate = "will truncate the source value";
let depending_on_isize = "will truncate or zero-extend depending on the bit width of \
`isize`";
"simd_insert" => (2, vec![param(0), tcx.types.u32, param(1)], param(0)),
"simd_extract" => (2, vec![param(0), tcx.types.u32], param(1)),
"simd_cast" => (2, vec![param(0)], param(1)),
+ "simd_reduce_all" | "simd_reduce_any" => (1, vec![param(0)], tcx.types.bool),
+ "simd_reduce_add_ordered" | "simd_reduce_mul_ordered"
+ => (2, vec![param(0), param(1)], param(1)),
+ "simd_reduce_add_unordered" | "simd_reduce_mul_unordered" |
+ "simd_reduce_and" | "simd_reduce_or" | "simd_reduce_xor" |
+ "simd_reduce_min" | "simd_reduce_max" |
+ "simd_reduce_min_nanless" | "simd_reduce_max_nanless"
+ => (2, vec![param(0)], param(1)),
name if name.starts_with("simd_shuffle") => {
match name["simd_shuffle".len()..].parse() {
Ok(n) => {
// don't suggest placing a use before the prelude
// import or other generated ones
if item.span.ctxt().outer().expn_info().is_none() {
- self.span = Some(item.span.with_hi(item.span.lo()));
+ self.span = Some(item.span.shrink_to_lo());
self.found_use = true;
return;
}
if item.span.ctxt().outer().expn_info().is_none() {
// don't insert between attributes and an item
if item.attrs.is_empty() {
- self.span = Some(item.span.with_hi(item.span.lo()));
+ self.span = Some(item.span.shrink_to_lo());
} else {
// find the first attribute on the item
for attr in &item.attrs {
if self.span.map_or(true, |span| attr.span < span) {
- self.span = Some(attr.span.with_hi(attr.span.lo()));
+ self.span = Some(attr.span.shrink_to_lo());
}
}
}
if sugg_unit {
let sugg_span = sess.codemap().end_point(expr_sp);
// remove closing `)` from the span
- let sugg_span = sugg_span.with_hi(sugg_span.lo());
+ let sugg_span = sugg_span.shrink_to_lo();
err.span_suggestion(
sugg_span,
"expected the unit value `()`; create it with empty parentheses",
.upvar_tys(closure_def_id, self.tcx)
.zip(final_upvar_tys)
{
- self.demand_eqtype(span, final_upvar_ty, upvar_ty);
+ self.demand_suptype(span, upvar_ty, final_upvar_ty);
}
// If we are also inferred the closure kind here,
use rustc::ty::{self, AdtKind, ToPolyTraitRef, Ty, TyCtxt};
use rustc::ty::maps::Providers;
use rustc::ty::util::IntTypeExt;
-use rustc::util::nodemap::{FxHashSet, FxHashMap};
use rustc::ty::util::Discr;
+use rustc::util::captures::Captures;
+use rustc::util::nodemap::{FxHashSet, FxHashMap};
use syntax::{abi, ast};
use syntax::ast::MetaItemKind;
fn early_bound_lifetimes_from_generics<'a, 'tcx>(
tcx: TyCtxt<'a, 'tcx, 'tcx>,
ast_generics: &'a hir::Generics)
- -> impl Iterator<Item=&'a hir::LifetimeDef>
+ -> impl Iterator<Item=&'a hir::LifetimeDef> + Captures<'tcx>
{
ast_generics
.lifetimes()
Example of erroneous code:
```compile_fail,E0527
-#![feature(slice_patterns)]
-
let r = &[1, 2, 3, 4];
match r {
&[a, b] => { // error: pattern requires 2 elements but array
Example of erroneous code:
```compile_fail,E0529
-#![feature(slice_patterns)]
-
let r: f32 = 1.0;
match r {
[a, b] => { // error: expected an array or slice, found `f32`
types:
```
-#![feature(slice_patterns)]
-
let r = [1.0, 2.0];
match r {
[a, b] => { // ok!
#![allow(non_camel_case_types)]
-#![feature(advanced_slice_patterns)]
+#![cfg_attr(stage0, feature(advanced_slice_patterns))]
#![feature(box_patterns)]
#![feature(box_syntax)]
#![feature(conservative_impl_trait)]
// except according to those terms.
use rustc::ty::TypeFoldable;
+use std::fmt::Debug;
use super::*;
return None;
}
+ let mut bounds_vec = bounds.into_iter().collect();
+ self.sort_where_bounds(&mut bounds_vec);
+
Some(WherePredicate::BoundPredicate {
ty,
- bounds: bounds.into_iter().collect(),
+ bounds: bounds_vec,
})
})
.chain(
lifetime_to_bounds
.into_iter()
.filter(|&(_, ref bounds)| !bounds.is_empty())
- .map(|(lifetime, bounds)| WherePredicate::RegionPredicate {
- lifetime,
- bounds: bounds.into_iter().collect(),
+ .map(|(lifetime, bounds)| {
+ let mut bounds_vec = bounds.into_iter().collect();
+ self.sort_where_lifetimes(&mut bounds_vec);
+ WherePredicate::RegionPredicate {
+ lifetime,
+ bounds: bounds_vec,
+ }
}),
)
.collect()
// a given set of predicates always appears in the same order -
// both for visual consistency between 'rustdoc' runs, and to
// make writing tests much easier
- fn sort_where_predicates(&self, predicates: &mut Vec<WherePredicate>) {
+ #[inline]
+ fn sort_where_predicates(&self, mut predicates: &mut Vec<WherePredicate>) {
// We should never have identical bounds - and if we do,
// they're visually identical as well. Therefore, using
// an unstable sort is fine.
- predicates.sort_unstable_by(|first, second| {
- // This might look horrendously hacky, but it's actually not that bad.
- //
- // For performance reasons, we use several different FxHashMaps
- // in the process of computing the final set of where predicates.
- // However, the iteration order of a HashMap is completely unspecified.
- // In fact, the iteration of an FxHashMap can even vary between platforms,
- // since FxHasher has different behavior for 32-bit and 64-bit platforms.
- //
- // Obviously, it's extremely undesireable for documentation rendering
- // to be depndent on the platform it's run on. Apart from being confusing
- // to end users, it makes writing tests much more difficult, as predicates
- // can appear in any order in the final result.
- //
- // To solve this problem, we sort WherePredicates by their Debug
- // string. The thing to keep in mind is that we don't really
- // care what the final order is - we're synthesizing an impl
- // ourselves, so any order can be considered equally valid.
- // By sorting the predicates, however, we ensure that for
- // a given codebase, all auto-trait impls always render
- // in exactly the same way.
- //
- // Using the Debug impementation for sorting prevents
- // us from needing to write quite a bit of almost
- // entirely useless code (e.g. how should two
- // Types be sorted relative to each other).
- // This approach is probably somewhat slower, but
- // the small number of items involved (impls
- // rarely have more than a few bounds) means
- // that it shouldn't matter in practice.
+ self.unstable_debug_sort(&mut predicates);
+ }
+
+ // Ensure that the bounds are in a consistent order. The precise
+ // ordering doesn't actually matter, but it's important that
+ // a given set of bounds always appears in the same order -
+ // both for visual consistency between 'rustdoc' runs, and to
+ // make writing tests much easier
+ #[inline]
+ fn sort_where_bounds(&self, mut bounds: &mut Vec<TyParamBound>) {
+ // We should never have identical bounds - and if we do,
+ // they're visually identical as well. Therefore, using
+ // an unstable sort is fine.
+ self.unstable_debug_sort(&mut bounds);
+ }
+
+ #[inline]
+ fn sort_where_lifetimes(&self, mut bounds: &mut Vec<Lifetime>) {
+ // We should never have identical bounds - and if we do,
+ // they're visually identical as well. Therefore, using
+ // an unstable sort is fine.
+ self.unstable_debug_sort(&mut bounds);
+ }
+
+ // This might look horrendously hacky, but it's actually not that bad.
+ //
+ // For performance reasons, we use several different FxHashMaps
+ // in the process of computing the final set of where predicates.
+ // However, the iteration order of a HashMap is completely unspecified.
+ // In fact, the iteration of an FxHashMap can even vary between platforms,
+ // since FxHasher has different behavior for 32-bit and 64-bit platforms.
+ //
+ // Obviously, it's extremely undesireable for documentation rendering
+ // to be depndent on the platform it's run on. Apart from being confusing
+ // to end users, it makes writing tests much more difficult, as predicates
+ // can appear in any order in the final result.
+ //
+ // To solve this problem, we sort WherePredicates and TyParamBounds
+ // by their Debug string. The thing to keep in mind is that we don't really
+ // care what the final order is - we're synthesizing an impl or bound
+ // ourselves, so any order can be considered equally valid. By sorting the
+ // predicates and bounds, however, we ensure that for a given codebase, all
+ // auto-trait impls always render in exactly the same way.
+ //
+ // Using the Debug impementation for sorting prevents us from needing to
+ // write quite a bit of almost entirely useless code (e.g. how should two
+ // Types be sorted relative to each other). It also allows us to solve the
+ // problem for both WherePredicates and TyParamBounds at the same time. This
+ // approach is probably somewhat slower, but the small number of items
+ // involved (impls rarely have more than a few bounds) means that it
+ // shouldn't matter in practice.
+ fn unstable_debug_sort<T: Debug>(&self, vec: &mut Vec<T>) {
+ vec.sort_unstable_by(|first, second| {
format!("{:?}", first).cmp(&format!("{:?}", second))
});
}
/// Renders the configuration for human display, as a short HTML description.
pub(crate) fn render_short_html(&self) -> String {
- let mut msg = Html(self).to_string();
+ let mut msg = ShortHtml(self).to_string();
if self.should_capitalize_first_letter() {
if let Some(i) = msg.find(|c: char| c.is_ascii_alphanumeric()) {
msg[i .. i+1].make_ascii_uppercase();
/// Renders the configuration for long display, as a long HTML description.
pub(crate) fn render_long_html(&self) -> String {
- let mut msg = format!("This is supported on <strong>{}</strong>", Html(self));
+ let on = if self.should_use_with_in_description() {
+ "with"
+ } else {
+ "on"
+ };
+
+ let mut msg = format!("This is supported {} <strong>{}</strong>", on, Html(self));
if self.should_append_only_to_description() {
msg.push_str(" only");
}
}
}
}
+
+ fn should_use_with_in_description(&self) -> bool {
+ match *self {
+ Cfg::Cfg(ref name, _) if name == &"target_feature" => true,
+ _ => false,
+ }
+ }
}
impl ops::Not for Cfg {
},
("target_endian", Some(endian)) => return write!(fmt, "{}-endian", endian),
("target_pointer_width", Some(bits)) => return write!(fmt, "{}-bit", bits),
+ ("target_feature", Some(feat)) =>
+ return write!(fmt, "target feature <code>{}</code>", feat),
_ => "",
};
if !human_readable.is_empty() {
}
}
+struct ShortHtml<'a>(&'a Cfg);
+
+impl<'a> fmt::Display for ShortHtml<'a> {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ match *self.0 {
+ Cfg::Cfg(ref name, Some(ref vendor)) if name == &"target_feature" => {
+ write!(fmt, "<code>{}</code>", vendor)
+ },
+ ref cfg => write!(fmt, "{}", Html(cfg)),
+ }
+ }
+}
+
#[cfg(test)]
mod test {
use super::Cfg;
).render_short_html(),
"(Debug-assertions enabled or Windows) and Unix"
);
+ assert_eq!(
+ name_value_cfg("target_feature", "sse2").render_short_html(),
+ "<code>sse2</code>"
+ );
})
}
"This is supported on <strong>(debug-assertions enabled or Windows) and Unix\
</strong> only."
);
+ assert_eq!(
+ name_value_cfg("target_feature", "sse2").render_long_html(),
+ "This is supported with <strong>target feature <code>sse2</code></strong> only."
+ );
})
}
}
})
}).collect();
+ // treat #[target_feature(enable = "feat")] attributes as if they were
+ // #[doc(cfg(target_feature = "feat"))] attributes as well
+ for attr in attrs.lists("target_feature") {
+ if attr.check_name("enable") {
+ if let Some(feat) = attr.value_str() {
+ let meta = attr::mk_name_value_item_str("target_feature".into(), feat);
+ if let Ok(feat_cfg) = Cfg::parse(&meta) {
+ cfg &= feat_cfg;
+ }
+ }
+ }
+ }
+
Attributes {
doc_strings,
other_attrs,
token::Lifetime(..) => Class::Lifetime,
- token::Underscore | token::Eof | token::Interpolated(..) |
+ token::Eof | token::Interpolated(..) |
token::Tilde | token::At | token::DotEq => Class::None,
};
//! use rustdoc::html::markdown::Markdown;
//!
//! let s = "My *markdown* _text_";
-//! let html = format!("{}", Markdown(s));
+//! let html = format!("{}", Markdown(s, &[]));
//! // ... something using html
//! ```
#![allow(non_camel_case_types)]
+use rustc::session;
use std::cell::RefCell;
use std::collections::{HashMap, VecDeque};
use std::default::Default;
}
}
-pub fn find_testable_code(doc: &str, tests: &mut ::test::Collector, position: Span) {
+pub fn find_testable_code(doc: &str, tests: &mut ::test::Collector, position: Span,
+ sess: Option<&session::Session>) {
tests.set_position(position);
let mut parser = Parser::new(doc);
line, filename, block_info.allow_fail);
prev_offset = offset;
} else {
+ if let Some(ref sess) = sess {
+ sess.span_warn(position, "invalid start of a new code block");
+ }
break;
}
}
}
}
- function handleShortcut(ev) {
- if (document.activeElement.tagName === "INPUT" &&
- hasClass(document.getElementById('main'), "hidden")) {
- return;
+ function handleEscape(ev, help) {
+ hideModal();
+ var search = document.getElementById("search");
+ if (!hasClass(help, "hidden")) {
+ displayHelp(false, ev);
+ } else if (!hasClass(search, "hidden")) {
+ ev.preventDefault();
+ addClass(search, "hidden");
+ removeClass(document.getElementById("main"), "hidden");
}
+ defocusSearchBar();
+ }
+ function handleShortcut(ev) {
// Don't interfere with browser shortcuts
if (ev.ctrlKey || ev.altKey || ev.metaKey) {
return;
}
var help = document.getElementById("help");
- switch (getVirtualKey(ev)) {
- case "Escape":
- hideModal();
- var search = document.getElementById("search");
- if (!hasClass(help, "hidden")) {
- displayHelp(false, ev);
- } else if (!hasClass(search, "hidden")) {
- ev.preventDefault();
- addClass(search, "hidden");
- removeClass(document.getElementById("main"), "hidden");
+ if (document.activeElement.tagName === "INPUT") {
+ switch (getVirtualKey(ev)) {
+ case "Escape":
+ handleEscape(ev, help);
+ break;
}
- defocusSearchBar();
- break;
+ } else {
+ switch (getVirtualKey(ev)) {
+ case "Escape":
+ handleEscape(ev, help);
+ break;
- case "s":
- case "S":
- displayHelp(false, ev);
- hideModal();
- ev.preventDefault();
- focusSearchBar();
- break;
+ case "s":
+ case "S":
+ displayHelp(false, ev);
+ hideModal();
+ ev.preventDefault();
+ focusSearchBar();
+ break;
- case "+":
- case "-":
- ev.preventDefault();
- toggleAllDocs();
- break;
+ case "+":
+ case "-":
+ ev.preventDefault();
+ toggleAllDocs();
+ break;
- case "?":
- if (ev.shiftKey) {
- hideModal();
- displayHelp(true, ev);
+ case "?":
+ if (ev.shiftKey) {
+ hideModal();
+ displayHelp(true, ev);
+ }
+ break;
}
- break;
}
}
#![feature(box_syntax)]
#![feature(fs_read_write)]
#![feature(set_stdio)]
-#![feature(slice_patterns)]
+#![cfg_attr(stage0, feature(slice_patterns))]
#![feature(test)]
#![feature(unicode)]
#![feature(vec_remove_item)]
true, opts, maybe_sysroot, None,
Some(PathBuf::from(input)),
linker);
- find_testable_code(&input_str, &mut collector, DUMMY_SP);
+ find_testable_code(&input_str, &mut collector, DUMMY_SP, None);
test_args.insert(0, "rustdoctest".to_string());
testing::test_main(&test_args, collector.tests,
testing::Options::new().display_output(display_warnings));
// the collapse-docs pass won't combine sugared/raw doc attributes, or included files with
// anything else, this will combine them for us
if let Some(doc) = attrs.collapsed_doc_value() {
- markdown::find_testable_code(&doc, self.collector,
- attrs.span.unwrap_or(DUMMY_SP));
+ markdown::find_testable_code(&doc,
+ self.collector,
+ attrs.span.unwrap_or(DUMMY_SP),
+ Some(self.sess));
}
nested(self);
// If we're inlining, skip private items.
_ if self.inlining && item.vis != hir::Public => {}
hir::ItemGlobalAsm(..) => {}
- hir::ItemExternCrate(ref p) => {
+ hir::ItemExternCrate(orig_name) => {
let def_id = self.cx.tcx.hir.local_def_id(item.id);
om.extern_crates.push(ExternCrate {
cnum: self.cx.tcx.extern_mod_stmt_cnum(def_id)
.unwrap_or(LOCAL_CRATE),
name,
- path: p.map(|x|x.to_string()),
+ path: orig_name.map(|x|x.to_string()),
vis: item.vis.clone(),
attrs: item.attrs.clone(),
whence: item.span,
fn build_libbacktrace(host: &str, target: &str) -> Result<(), ()> {
let native = native_lib_boilerplate("libbacktrace", "libbacktrace", "backtrace", ".libs")?;
+ let cflags = env::var("CFLAGS").unwrap_or_default() + " -fvisibility=hidden -O2";
run(Command::new("sh")
.current_dir(&native.out_dir)
.arg("--disable-host-shared")
.arg(format!("--host={}", build_helper::gnu_target(target)))
.arg(format!("--build={}", build_helper::gnu_target(host)))
- .env("CFLAGS", env::var("CFLAGS").unwrap_or_default() + " -fvisibility=hidden"));
+ .env("CFLAGS", cflags));
run(Command::new(build_helper::make(host))
.current_dir(&native.out_dir)
/// # }
/// ```
#[unstable(feature = "bufreader_is_empty", issue = "45323", reason = "recently added")]
+ #[rustc_deprecated(since = "1.26.0", reason = "use .buffer().is_empty() instead")]
pub fn is_empty(&self) -> bool {
- self.pos == self.cap
+ self.buffer().is_empty()
+ }
+
+ /// Returns a reference to the internally buffered data.
+ ///
+ /// Unlike `fill_buf`, this will not attempt to fill the buffer if it is empty.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # #![feature(bufreader_buffer)]
+ /// use std::io::{BufReader, BufRead};
+ /// use std::fs::File;
+ ///
+ /// # fn foo() -> std::io::Result<()> {
+ /// let f = File::open("log.txt")?;
+ /// let mut reader = BufReader::new(f);
+ /// assert!(reader.buffer().is_empty());
+ ///
+ /// if reader.fill_buf()?.len() > 0 {
+ /// assert!(!reader.buffer().is_empty());
+ /// }
+ /// # Ok(())
+ /// # }
+ /// ```
+ #[unstable(feature = "bufreader_buffer", issue = "45323")]
+ pub fn buffer(&self) -> &[u8] {
+ &self.buf[self.pos..self.cap]
}
/// Unwraps this `BufReader`, returning the underlying reader.
#![feature(fn_traits)]
#![feature(fnbox)]
#![feature(generic_param_attrs)]
-#![feature(hashmap_hasher)]
+#![feature(hashmap_internals)]
#![feature(heap_api)]
#![feature(i128)]
#![feature(i128_type)]
#![feature(raw)]
#![feature(rustc_attrs)]
#![feature(stdsimd)]
-#![feature(sip_hash_13)]
#![feature(slice_bytes)]
#![feature(slice_concat_ext)]
#![feature(slice_internals)]
// We want to re-export a few macros from core but libcore has already been
// imported by the compiler (via our #[no_std] attribute) In this case we just
// add a new crate name so we can attach the re-exports to it.
-#[macro_reexport(assert, assert_eq, assert_ne, debug_assert, debug_assert_eq,
+#[macro_reexport(assert_eq, assert_ne, debug_assert, debug_assert_eq,
debug_assert_ne, unreachable, unimplemented, write, writeln, try)]
+#[cfg_attr(stage0, macro_reexport(assert))]
extern crate core as __core;
#[macro_use]
($file:expr) => ({ /* compiler built-in */ });
($file:expr,) => ({ /* compiler built-in */ });
}
+
+ /// Ensure that a boolean expression is `true` at runtime.
+ ///
+ /// This will invoke the [`panic!`] macro if the provided expression cannot be
+ /// evaluated to `true` at runtime.
+ ///
+ /// # Uses
+ ///
+ /// Assertions are always checked in both debug and release builds, and cannot
+ /// be disabled. See [`debug_assert!`] for assertions that are not enabled in
+ /// release builds by default.
+ ///
+ /// Unsafe code relies on `assert!` to enforce run-time invariants that, if
+ /// violated could lead to unsafety.
+ ///
+ /// Other use-cases of `assert!` include [testing] and enforcing run-time
+ /// invariants in safe code (whose violation cannot result in unsafety).
+ ///
+ /// # Custom Messages
+ ///
+ /// This macro has a second form, where a custom panic message can
+ /// be provided with or without arguments for formatting. See [`std::fmt`]
+ /// for syntax for this form.
+ ///
+ /// [`panic!`]: macro.panic.html
+ /// [`debug_assert!`]: macro.debug_assert.html
+ /// [testing]: ../book/second-edition/ch11-01-writing-tests.html#checking-results-with-the-assert-macro
+ /// [`std::fmt`]: ../std/fmt/index.html
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// // the panic message for these assertions is the stringified value of the
+ /// // expression given.
+ /// assert!(true);
+ ///
+ /// fn some_computation() -> bool { true } // a very simple function
+ ///
+ /// assert!(some_computation());
+ ///
+ /// // assert with a custom message
+ /// let x = true;
+ /// assert!(x, "x wasn't true!");
+ ///
+ /// let a = 3; let b = 27;
+ /// assert!(a + b == 30, "a = {}, b = {}", a, b);
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
+ #[macro_export]
+ macro_rules! assert {
+ ($cond:expr) => ({ /* compiler built-in */ });
+ ($cond:expr,) => ({ /* compiler built-in */ });
+ ($cond:expr, $($arg:tt)+) => ({ /* compiler built-in */ });
+ }
}
/// A macro for defining #[cfg] if-else statements.
-NB: This crate is part of the Rust compiler. For an overview of the
-compiler as a whole, see
-[the README.md file found in `librustc`](../librustc/README.md).
-
The `syntax` crate contains those things concerned purely with syntax
– that is, the AST ("abstract syntax tree"), parser, pretty-printer,
lexer, macro expander, and utilities for traversing ASTs.
+
+For more information about how these things work in rustc, see the
+rustc guide:
+
+- [Parsing](https://rust-lang-nursery.github.io/rustc-guide/the-parser.html)
+- [Macro Expansion](https://rust-lang-nursery.github.io/rustc-guide/macro-expansion.html)
}
}
- // Add starting "crate root" segment to all paths except those that
- // already have it or start with `self`, `super`, `Self` or `$crate`.
- pub fn default_to_global(mut self) -> Path {
- if !self.is_global() {
- let ident = self.segments[0].identifier;
- if !::parse::token::Ident(ident).is_path_segment_keyword() ||
- ident.name == keywords::Crate.name() {
- self.segments.insert(0, PathSegment::crate_root(self.span));
+ // Make a "crate root" segment for this path unless it already has it
+ // or starts with something like `self`/`super`/`$crate`/etc.
+ pub fn make_root(&self) -> Option<PathSegment> {
+ if let Some(ident) = self.segments.get(0).map(|seg| seg.identifier) {
+ if ::parse::token::Ident(ident).is_path_segment_keyword() &&
+ ident.name != keywords::Crate.name() {
+ return None;
}
}
- self
+ Some(PathSegment::crate_root(self.span.shrink_to_lo()))
}
pub fn is_global(&self) -> bool {
pub type Variant = Spanned<Variant_>;
+/// Part of `use` item to the right of its prefix.
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub enum UseTreeKind {
- Simple(Ident),
- Glob,
+ /// `use prefix` or `use prefix as rename`
+ Simple(Option<Ident>),
+ /// `use prefix::{...}`
Nested(Vec<(UseTree, NodeId)>),
+ /// `use prefix::*`
+ Glob,
}
+/// A tree of paths sharing common prefixes.
+/// Used in `use` items both at top-level and inside of braces in import groups.
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub struct UseTree {
- pub kind: UseTreeKind,
pub prefix: Path,
+ pub kind: UseTreeKind,
pub span: Span,
}
+impl UseTree {
+ pub fn ident(&self) -> Ident {
+ match self.kind {
+ UseTreeKind::Simple(Some(rename)) => rename,
+ UseTreeKind::Simple(None) =>
+ self.prefix.segments.last().expect("empty prefix in a simple import").identifier,
+ _ => panic!("`UseTree::ident` can only be used on a simple import"),
+ }
+ }
+}
+
/// Distinguishes between Attributes that decorate items and Attributes that
/// are contained as statements within items. These two cases need to be
/// distinguished for pretty-printing.
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub enum ItemKind {
- /// An `extern crate` item, with optional original crate name.
+ /// An `extern crate` item, with optional *original* crate name if the crate was renamed.
///
/// E.g. `extern crate foo` or `extern crate foo_bar as foo`
ExternCrate(Option<Name>),
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::stable_hasher::StableHasher;
-use rustc_data_structures::sync::Lrc;
-use std::cell::{RefCell, Ref};
+use rustc_data_structures::sync::{Lrc, Lock, LockGuard};
use std::cmp;
use std::hash::Hash;
use std::path::{Path, PathBuf};
// CodeMap
//
+pub(super) struct CodeMapFiles {
+ pub(super) file_maps: Vec<Lrc<FileMap>>,
+ stable_id_to_filemap: FxHashMap<StableFilemapId, Lrc<FileMap>>
+}
+
pub struct CodeMap {
- pub(super) files: RefCell<Vec<Lrc<FileMap>>>,
- file_loader: Box<FileLoader>,
+ pub(super) files: Lock<CodeMapFiles>,
+ file_loader: Box<FileLoader + Sync + Send>,
// This is used to apply the file path remapping as specified via
// --remap-path-prefix to all FileMaps allocated within this CodeMap.
path_mapping: FilePathMapping,
- stable_id_to_filemap: RefCell<FxHashMap<StableFilemapId, Lrc<FileMap>>>,
/// In case we are in a doctest, replace all file names with the PathBuf,
/// and add the given offsets to the line info
doctest_offset: Option<(FileName, isize)>,
impl CodeMap {
pub fn new(path_mapping: FilePathMapping) -> CodeMap {
CodeMap {
- files: RefCell::new(Vec::new()),
+ files: Lock::new(CodeMapFiles {
+ file_maps: Vec::new(),
+ stable_id_to_filemap: FxHashMap(),
+ }),
file_loader: Box::new(RealFileLoader),
path_mapping,
- stable_id_to_filemap: RefCell::new(FxHashMap()),
doctest_offset: None,
}
}
}
- pub fn with_file_loader(file_loader: Box<FileLoader>,
+ pub fn with_file_loader(file_loader: Box<FileLoader + Sync + Send>,
path_mapping: FilePathMapping)
-> CodeMap {
CodeMap {
- files: RefCell::new(Vec::new()),
- file_loader,
+ files: Lock::new(CodeMapFiles {
+ file_maps: Vec::new(),
+ stable_id_to_filemap: FxHashMap(),
+ }),
+ file_loader: file_loader,
path_mapping,
- stable_id_to_filemap: RefCell::new(FxHashMap()),
doctest_offset: None,
}
}
Ok(self.new_filemap(filename, src))
}
- pub fn files(&self) -> Ref<Vec<Lrc<FileMap>>> {
- self.files.borrow()
+ pub fn files(&self) -> LockGuard<Vec<Lrc<FileMap>>> {
+ LockGuard::map(self.files.borrow(), |files| &mut files.file_maps)
}
pub fn filemap_by_stable_id(&self, stable_id: StableFilemapId) -> Option<Lrc<FileMap>> {
- self.stable_id_to_filemap.borrow().get(&stable_id).map(|fm| fm.clone())
+ self.files.borrow().stable_id_to_filemap.get(&stable_id).map(|fm| fm.clone())
}
fn next_start_pos(&self) -> usize {
- let files = self.files.borrow();
- match files.last() {
+ match self.files.borrow().file_maps.last() {
None => 0,
// Add one so there is some space between files. This lets us distinguish
// positions in the codemap, even in the presence of zero-length files.
/// Creates a new filemap without setting its line information. If you don't
/// intend to set the line information yourself, you should use new_filemap_and_lines.
+ /// This does not ensure that only one FileMap exists per file name.
pub fn new_filemap(&self, filename: FileName, src: String) -> Lrc<FileMap> {
let start_pos = self.next_start_pos();
- let mut files = self.files.borrow_mut();
// The path is used to determine the directory for loading submodules and
// include files, so it must be before remapping.
Pos::from_usize(start_pos),
));
- files.push(filemap.clone());
+ let mut files = self.files.borrow_mut();
- self.stable_id_to_filemap
- .borrow_mut()
- .insert(StableFilemapId::new(&filemap), filemap.clone());
+ files.file_maps.push(filemap.clone());
+ files.stable_id_to_filemap.insert(StableFilemapId::new(&filemap), filemap.clone());
filemap
}
/// Creates a new filemap and sets its line information.
+ /// This does not ensure that only one FileMap exists per file name.
pub fn new_filemap_and_lines(&self, filename: &Path, src: &str) -> Lrc<FileMap> {
let fm = self.new_filemap(filename.to_owned().into(), src.to_owned());
let mut byte_pos: u32 = fm.start_pos.0;
mut file_local_non_narrow_chars: Vec<NonNarrowChar>)
-> Lrc<FileMap> {
let start_pos = self.next_start_pos();
- let mut files = self.files.borrow_mut();
let end_pos = Pos::from_usize(start_pos + source_len);
let start_pos = Pos::from_usize(start_pos);
crate_of_origin,
src: None,
src_hash,
- external_src: RefCell::new(ExternalSource::AbsentOk),
+ external_src: Lock::new(ExternalSource::AbsentOk),
start_pos,
end_pos,
- lines: RefCell::new(file_local_lines),
- multibyte_chars: RefCell::new(file_local_multibyte_chars),
- non_narrow_chars: RefCell::new(file_local_non_narrow_chars),
+ lines: Lock::new(file_local_lines),
+ multibyte_chars: Lock::new(file_local_multibyte_chars),
+ non_narrow_chars: Lock::new(file_local_non_narrow_chars),
name_hash,
});
- files.push(filemap.clone());
+ let mut files = self.files.borrow_mut();
- self.stable_id_to_filemap
- .borrow_mut()
- .insert(StableFilemapId::new(&filemap), filemap.clone());
+ files.file_maps.push(filemap.clone());
+ files.stable_id_to_filemap.insert(StableFilemapId::new(&filemap), filemap.clone());
filemap
}
pub fn lookup_line(&self, pos: BytePos) -> Result<FileMapAndLine, Lrc<FileMap>> {
let idx = self.lookup_filemap_idx(pos);
- let files = self.files.borrow();
- let f = (*files)[idx].clone();
+ let f = (*self.files.borrow().file_maps)[idx].clone();
match f.lookup_line(pos) {
Some(line) => Ok(FileMapAndLine { fm: f, line: line }),
}
pub fn span_to_string(&self, sp: Span) -> String {
- if self.files.borrow().is_empty() && sp.source_equal(&DUMMY_SP) {
+ if self.files.borrow().file_maps.is_empty() && sp.source_equal(&DUMMY_SP) {
return "no-location".to_string();
}
self.span_to_source(sp, |src, start_index, _| src[..start_index].to_string())
}
- /// Given a `Span`, try to get a shorter span ending before the first occurrence of `c` `char`
- pub fn span_until_char(&self, sp: Span, c: char) -> Span {
- match self.span_to_snippet(sp) {
- Ok(snippet) => {
- let snippet = snippet.split(c).nth(0).unwrap_or("").trim_right();
- if !snippet.is_empty() && !snippet.contains('\n') {
- sp.with_hi(BytePos(sp.lo().0 + snippet.len() as u32))
- } else {
- sp
- }
- }
- _ => sp,
- }
- }
-
/// Extend the given `Span` to just after the previous occurrence of `c`. Return the same span
/// if no character could be found or if an error occurred while retrieving the code snippet.
pub fn span_extend_to_prev_char(&self, sp: Span, c: char) -> Span {
sp
}
+ /// Given a `Span`, try to get a shorter span ending before the first occurrence of `c` `char`
+ pub fn span_until_char(&self, sp: Span, c: char) -> Span {
+ match self.span_to_snippet(sp) {
+ Ok(snippet) => {
+ let snippet = snippet.split(c).nth(0).unwrap_or("").trim_right();
+ if !snippet.is_empty() && !snippet.contains('\n') {
+ sp.with_hi(BytePos(sp.lo().0 + snippet.len() as u32))
+ } else {
+ sp
+ }
+ }
+ _ => sp,
+ }
+ }
+
+ /// Given a `Span`, try to get a shorter span ending just after the first occurrence of `char`
+ /// `c`.
+ pub fn span_through_char(&self, sp: Span, c: char) -> Span {
+ if let Ok(snippet) = self.span_to_snippet(sp) {
+ if let Some(offset) = snippet.find(c) {
+ return sp.with_hi(BytePos(sp.lo().0 + (offset + c.len_utf8()) as u32));
+ }
+ }
+ sp
+ }
+
/// Given a `Span`, get a new `Span` covering the first token and all its trailing whitespace or
/// the original `Span`.
///
/// If `sp` points to `"let mut x"`, then a span pointing at `"let "` will be returned.
pub fn span_until_non_whitespace(&self, sp: Span) -> Span {
- if let Ok(snippet) = self.span_to_snippet(sp) {
- let mut offset = 0;
- // get the bytes width of all the non-whitespace characters
- for c in snippet.chars().take_while(|c| !c.is_whitespace()) {
- offset += c.len_utf8();
- }
- // get the bytes width of all the whitespace characters after that
- for c in snippet[offset..].chars().take_while(|c| c.is_whitespace()) {
- offset += c.len_utf8();
+ let mut whitespace_found = false;
+
+ self.span_take_while(sp, |c| {
+ if !whitespace_found && c.is_whitespace() {
+ whitespace_found = true;
}
- if offset > 1 {
- return sp.with_hi(BytePos(sp.lo().0 + offset as u32));
+
+ if whitespace_found && !c.is_whitespace() {
+ false
+ } else {
+ true
}
- }
- sp
+ })
}
/// Given a `Span`, get a new `Span` covering the first token without its trailing whitespace or
///
/// If `sp` points to `"let mut x"`, then a span pointing at `"let"` will be returned.
pub fn span_until_whitespace(&self, sp: Span) -> Span {
- if let Ok(snippet) = self.span_to_snippet(sp) {
- let mut offset = 0;
- // Get the bytes width of all the non-whitespace characters
- for c in snippet.chars().take_while(|c| !c.is_whitespace()) {
- offset += c.len_utf8();
- }
- if offset > 1 {
- return sp.with_hi(BytePos(sp.lo().0 + offset as u32));
- }
- }
- sp
+ self.span_take_while(sp, |c| !c.is_whitespace())
}
- /// Given a `Span`, try to get a shorter span ending just after the first occurrence of `char`
- /// `c`.
- pub fn span_through_char(&self, sp: Span, c: char) -> Span {
+ /// Given a `Span`, get a shorter one until `predicate` yields false.
+ pub fn span_take_while<P>(&self, sp: Span, predicate: P) -> Span
+ where P: for <'r> FnMut(&'r char) -> bool
+ {
if let Ok(snippet) = self.span_to_snippet(sp) {
- if let Some(offset) = snippet.find(c) {
- return sp.with_hi(BytePos(sp.lo().0 + (offset + c.len_utf8()) as u32));
- }
+ let offset = snippet.chars()
+ .take_while(predicate)
+ .map(|c| c.len_utf8())
+ .sum::<usize>();
+
+ sp.with_hi(BytePos(sp.lo().0 + (offset as u32)))
+ } else {
+ sp
}
- sp
}
pub fn def_span(&self, sp: Span) -> Span {
}
pub fn get_filemap(&self, filename: &FileName) -> Option<Lrc<FileMap>> {
- for fm in self.files.borrow().iter() {
+ for fm in self.files.borrow().file_maps.iter() {
if *filename == fm.name {
return Some(fm.clone());
}
/// For a global BytePos compute the local offset within the containing FileMap
pub fn lookup_byte_offset(&self, bpos: BytePos) -> FileMapAndBytePos {
let idx = self.lookup_filemap_idx(bpos);
- let fm = (*self.files.borrow())[idx].clone();
+ let fm = (*self.files.borrow().file_maps)[idx].clone();
let offset = bpos - fm.start_pos;
FileMapAndBytePos {fm: fm, pos: offset}
}
/// Converts an absolute BytePos to a CharPos relative to the filemap.
pub fn bytepos_to_file_charpos(&self, bpos: BytePos) -> CharPos {
let idx = self.lookup_filemap_idx(bpos);
- let files = self.files.borrow();
- let map = &(*files)[idx];
+ let map = &(*self.files.borrow().file_maps)[idx];
// The number of extra bytes due to multibyte chars in the FileMap
let mut total_extra_bytes = 0;
// Return the index of the filemap (in self.files) which contains pos.
pub fn lookup_filemap_idx(&self, pos: BytePos) -> usize {
let files = self.files.borrow();
- let files = &*files;
+ let files = &files.file_maps;
let count = files.len();
// Binary search for the filemap.
use ext::build::AstBuilder;
use parse::token;
use ptr::P;
-use symbol::Symbol;
+use symbol::{keywords, Symbol};
use tokenstream::{TokenTree};
use util::small_vector::SmallVector;
(descriptions.len(), ecx.expr_vec(span, descriptions))
});
- let static_ = ecx.lifetime(span, Ident::from_str("'static"));
+ let static_ = ecx.lifetime(span, keywords::StaticLifetime.ident());
let ty_str = ecx.ty_rptr(
span,
ecx.ty_ident(span, ecx.ident_of("str")),
ty,
expr,
),
- vis: codemap::respan(span.empty(), ast::VisibilityKind::Public),
+ vis: codemap::respan(span.shrink_to_lo(), ast::VisibilityKind::Public),
span,
tokens: None,
})
/// Whether the contents of the macro can use `unsafe`
/// without triggering the `unsafe_code` lint.
allow_internal_unsafe: bool,
+ /// The macro's feature name if it is unstable, and the stability feature
+ unstable_feature: Option<(Symbol, u32)>,
},
/// A function-like syntax extension that has an extra ident before
pub depth: usize,
pub module: Rc<ModuleData>,
pub directory_ownership: DirectoryOwnership,
+ pub crate_span: Option<Span>,
}
/// One of these is made during expansion and incrementally updated as we go;
depth: 0,
module: Rc::new(ModuleData { mod_path: Vec::new(), directory: PathBuf::new() }),
directory_ownership: DirectoryOwnership::Owned { relative: None },
+ crate_span: None,
},
expansions: HashMap::new(),
}
vis: ast::Visibility, vp: P<ast::UseTree>) -> P<ast::Item>;
fn item_use_simple(&self, sp: Span, vis: ast::Visibility, path: ast::Path) -> P<ast::Item>;
fn item_use_simple_(&self, sp: Span, vis: ast::Visibility,
- ident: ast::Ident, path: ast::Path) -> P<ast::Item>;
+ ident: Option<ast::Ident>, path: ast::Path) -> P<ast::Item>;
fn item_use_list(&self, sp: Span, vis: ast::Visibility,
path: Vec<ast::Ident>, imports: &[ast::Ident]) -> P<ast::Item>;
fn item_use_glob(&self, sp: Span,
None
};
segments.push(ast::PathSegment { identifier: last_identifier, span, parameters });
- let path = ast::Path { span, segments };
-
- if global { path.default_to_global() } else { path }
+ let mut path = ast::Path { span, segments };
+ if global {
+ if let Some(seg) = path.make_root() {
+ path.segments.insert(0, seg);
+ }
+ }
+ path
}
/// Constructs a qualified path.
attrs,
id: ast::DUMMY_NODE_ID,
node,
- vis: respan(span.empty(), ast::VisibilityKind::Inherited),
+ vis: respan(span.shrink_to_lo(), ast::VisibilityKind::Inherited),
span,
tokens: None,
})
span: ty.span,
ty,
ident: None,
- vis: respan(span.empty(), ast::VisibilityKind::Inherited),
+ vis: respan(span.shrink_to_lo(), ast::VisibilityKind::Inherited),
attrs: Vec::new(),
id: ast::DUMMY_NODE_ID,
}
}
fn item_use_simple(&self, sp: Span, vis: ast::Visibility, path: ast::Path) -> P<ast::Item> {
- let last = path.segments.last().unwrap().identifier;
- self.item_use_simple_(sp, vis, last, path)
+ self.item_use_simple_(sp, vis, None, path)
}
fn item_use_simple_(&self, sp: Span, vis: ast::Visibility,
- ident: ast::Ident, path: ast::Path) -> P<ast::Item> {
+ rename: Option<ast::Ident>, path: ast::Path) -> P<ast::Item> {
self.item_use(sp, vis, P(ast::UseTree {
span: sp,
prefix: path,
- kind: ast::UseTreeKind::Simple(ident),
+ kind: ast::UseTreeKind::Simple(rename),
}))
}
(ast::UseTree {
span: sp,
prefix: self.path(sp, vec![*id]),
- kind: ast::UseTreeKind::Simple(*id),
+ kind: ast::UseTreeKind::Simple(None),
}, ast::DUMMY_NODE_ID)
}).collect();
use ext::derive::{add_derived_markers, collect_derives};
use ext::hygiene::{Mark, SyntaxContext};
use ext::placeholders::{placeholder, PlaceholderExpander};
-use feature_gate::{self, Features, is_builtin_attr};
+use feature_gate::{self, Features, GateIssue, is_builtin_attr, emit_feature_err};
use fold;
use fold::*;
use parse::{DirectoryOwnership, PResult};
module.directory.pop();
self.cx.root_path = module.directory.clone();
self.cx.current_expansion.module = Rc::new(module);
+ self.cx.current_expansion.crate_span = Some(krate.span);
let orig_mod_span = krate.module.inner;
node: ast::ItemKind::Mod(krate.module),
ident: keywords::Invalid.ident(),
id: ast::DUMMY_NODE_ID,
- vis: respan(krate.span.empty(), ast::VisibilityKind::Public),
+ vis: respan(krate.span.shrink_to_lo(), ast::VisibilityKind::Public),
tokens: None,
})));
let path = &mac.node.path;
let ident = ident.unwrap_or_else(|| keywords::Invalid.ident());
- let validate_and_set_expn_info = |def_site_span,
+ let validate_and_set_expn_info = |this: &mut Self, // arg instead of capture
+ def_site_span: Option<Span>,
allow_internal_unstable,
- allow_internal_unsafe| {
+ allow_internal_unsafe,
+ // can't infer this type
+ unstable_feature: Option<(Symbol, u32)>| {
+
+ // feature-gate the macro invocation
+ if let Some((feature, issue)) = unstable_feature {
+ let crate_span = this.cx.current_expansion.crate_span.unwrap();
+ // don't stability-check macros in the same crate
+ // (the only time this is null is for syntax extensions registered as macros)
+ if def_site_span.map_or(false, |def_span| !crate_span.contains(def_span))
+ && !span.allows_unstable() && this.cx.ecfg.features.map_or(true, |feats| {
+ // macro features will count as lib features
+ !feats.declared_lib_features.iter().any(|&(feat, _)| feat == feature)
+ }) {
+ let explain = format!("macro {}! is unstable", path);
+ emit_feature_err(this.cx.parse_sess, &*feature.as_str(), span,
+ GateIssue::Library(Some(issue)), &explain);
+ this.cx.trace_macros_diag();
+ return Err(kind.dummy(span));
+ }
+ }
+
if ident.name != keywords::Invalid.name() {
- return Err(format!("macro {}! expects no ident argument, given '{}'", path, ident));
+ let msg = format!("macro {}! expects no ident argument, given '{}'", path, ident);
+ this.cx.span_err(path.span, &msg);
+ this.cx.trace_macros_diag();
+ return Err(kind.dummy(span));
}
mark.set_expn_info(ExpnInfo {
call_site: span,
let opt_expanded = match *ext {
DeclMacro(ref expand, def_span) => {
- if let Err(msg) = validate_and_set_expn_info(def_span.map(|(_, s)| s),
- false, false) {
- self.cx.span_err(path.span, &msg);
- self.cx.trace_macros_diag();
- kind.dummy(span)
+ if let Err(dummy_span) = validate_and_set_expn_info(self, def_span.map(|(_, s)| s),
+ false, false, None) {
+ dummy_span
} else {
kind.make_from(expand.expand(self.cx, span, mac.node.stream()))
}
ref expander,
def_info,
allow_internal_unstable,
- allow_internal_unsafe
+ allow_internal_unsafe,
+ unstable_feature,
} => {
- if let Err(msg) = validate_and_set_expn_info(def_info.map(|(_, s)| s),
- allow_internal_unstable,
- allow_internal_unsafe) {
- self.cx.span_err(path.span, &msg);
- self.cx.trace_macros_diag();
- kind.dummy(span)
+ if let Err(dummy_span) = validate_and_set_expn_info(self, def_info.map(|(_, s)| s),
+ allow_internal_unstable,
+ allow_internal_unsafe,
+ unstable_feature) {
+ dummy_span
} else {
kind.make_from(expander.expand(self.cx, span, mac.node.stream()))
}
token::Pound => "Pound",
token::Dollar => "Dollar",
token::Question => "Question",
- token::Underscore => "Underscore",
token::Eof => "Eof",
token::Whitespace | token::Comment | token::Shebang(_) => {
let path = path.iter().map(|s| s.to_string()).collect();
let use_item = cx.item_use_glob(
sp,
- respan(sp.empty(), ast::VisibilityKind::Inherited),
+ respan(sp.shrink_to_lo(), ast::VisibilityKind::Inherited),
ids_ext(path),
);
cx.stmt_item(sp, use_item)
use ast::Ident;
use syntax_pos::{self, BytePos, Span};
-use codemap::Spanned;
+use codemap::respan;
use errors::FatalError;
use ext::tt::quoted::{self, TokenTree};
use parse::{Directory, ParseSess};
}
}
+/// The token is an identifier, but not `_`.
+/// We prohibit passing `_` to macros expecting `ident` for now.
+fn get_macro_ident(token: &Token) -> Option<Ident> {
+ match *token {
+ token::Ident(ident) if ident.name != keywords::Underscore.name() => Some(ident),
+ _ => None,
+ }
+}
+
/// 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
match name {
"expr" => token.can_begin_expr(),
"ty" => token.can_begin_type(),
- "ident" => token.is_ident(),
+ "ident" => get_macro_ident(token).is_some(),
"vis" => match *token {
// The follow-set of :vis + "priv" keyword + interpolated
Token::Comma | Token::Ident(_) | Token::Interpolated(_) => true,
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::BinOp(token::Shl) => true, // path (double UFCS)
Token::Interpolated(ref nt) => may_be_ident(&nt.0),
_ => false,
},
"expr" => token::NtExpr(panictry!(p.parse_expr())),
"ty" => token::NtTy(panictry!(p.parse_ty())),
// this could be handled like a token, since it is one
- "ident" => match p.token {
- token::Ident(sn) => {
- p.bump();
- token::NtIdent(Spanned::<Ident> {
- node: sn,
- span: p.prev_span,
- })
- }
- _ => {
- let token_str = pprust::token_to_string(&p.token);
- p.fatal(&format!("expected ident, found {}", &token_str[..]))
- .emit();
- FatalError.raise()
- }
- },
+ "ident" => if let Some(ident) = get_macro_ident(&p.token) {
+ p.bump();
+ token::NtIdent(respan(p.prev_span, ident))
+ } else {
+ let token_str = pprust::token_to_string(&p.token);
+ p.fatal(&format!("expected ident, found {}", &token_str)).emit();
+ FatalError.raise()
+ }
"path" => token::NtPath(panictry!(p.parse_path_common(PathStyle::Type, false))),
"meta" => token::NtMeta(panictry!(p.parse_meta_item())),
"vis" => token::NtVis(panictry!(p.parse_visibility(true))),
if body.legacy {
let allow_internal_unstable = attr::contains_name(&def.attrs, "allow_internal_unstable");
let allow_internal_unsafe = attr::contains_name(&def.attrs, "allow_internal_unsafe");
+
+ let unstable_feature = attr::find_stability(&sess.span_diagnostic,
+ &def.attrs, def.span).and_then(|stability| {
+ if let attr::StabilityLevel::Unstable { issue, .. } = stability.level {
+ Some((stability.feature, issue))
+ } else {
+ None
+ }
+ });
+
NormalTT {
expander,
def_info: Some((def.id, def.span)),
allow_internal_unstable,
- allow_internal_unsafe
+ allow_internal_unsafe,
+ unstable_feature
}
} else {
SyntaxExtension::DeclMacro(expander, Some((def.id, def.span)))
// rustc internal
(active, rustc_diagnostic_macros, "1.0.0", None, None),
(active, rustc_const_unstable, "1.0.0", None, None),
- (active, advanced_slice_patterns, "1.0.0", Some(23121), None),
(active, box_syntax, "1.0.0", Some(27779), None),
(active, placement_in_syntax, "1.0.0", Some(27779), None),
(active, unboxed_closures, "1.0.0", Some(29625), None),
(removed, allocator, "1.0.0", None, None),
// Allows the `#[simd]` attribute -- removed in favor of `#[repr(simd)]`
(removed, simd, "1.0.0", Some(27731), None),
+ // Merged into `slice_patterns`
+ (removed, advanced_slice_patterns, "1.0.0", Some(23121), None),
);
declare_features! (
across crates and will never be stable",
cfg_fn!(rustc_attrs))),
+ ("rustc_dump_program_clauses", Whitelisted, Gated(Stability::Unstable,
+ "rustc_attrs",
+ "the `#[rustc_dump_program_clauses]` \
+ attribute is just used for rustc unit \
+ tests and will never be stable",
+ cfg_fn!(rustc_attrs))),
+
// RFC #2094
("nll", Whitelisted, Gated(Stability::Unstable,
"nll",
}
fn visit_use_tree(&mut self, use_tree: &'a ast::UseTree, id: NodeId, _nested: bool) {
- if let ast::UseTreeKind::Simple(ident) = use_tree.kind {
+ if let ast::UseTreeKind::Simple(Some(ident)) = use_tree.kind {
if ident.name == "_" {
gate_feature_post!(&self, underscore_imports, use_tree.span,
"renaming imports with `_` is unstable");
fn visit_pat(&mut self, pattern: &'a ast::Pat) {
match pattern.node {
- PatKind::Slice(_, Some(_), ref last) if !last.is_empty() => {
- gate_feature_post!(&self, advanced_slice_patterns,
- pattern.span,
- "multiple-element slice matches anywhere \
- but at the end of a slice (e.g. \
- `[0, ..xs, 0]`) are experimental")
- }
- PatKind::Slice(..) => {
+ PatKind::Slice(_, Some(ref subslice), _) => {
gate_feature_post!(&self, slice_patterns,
- pattern.span,
- "slice pattern syntax is experimental");
+ subslice.span,
+ "syntax for subslices in slice patterns is not yet stabilized");
}
PatKind::Box(..) => {
gate_feature_post!(&self, box_patterns,
}
fn visit_lifetime(&mut self, lt: &'a ast::Lifetime) {
- if lt.ident.name == "'_" {
+ if lt.ident.name == keywords::UnderscoreLifetime.name() {
gate_feature_post!(&self, underscore_lifetimes, lt.span,
"underscore lifetimes are unstable");
}
span: fld.new_span(use_tree.span),
prefix: fld.fold_path(use_tree.prefix),
kind: match use_tree.kind {
- UseTreeKind::Simple(ident) => UseTreeKind::Simple(fld.fold_ident(ident)),
+ UseTreeKind::Simple(rename) =>
+ UseTreeKind::Simple(rename.map(|ident| fld.fold_ident(ident))),
UseTreeKind::Glob => UseTreeKind::Glob,
UseTreeKind::Nested(items) => UseTreeKind::Nested(items.move_map(|(tree, id)| {
(fld.fold_use_tree(tree), fld.new_id(id))
pub fn noop_fold_item_kind<T: Folder>(i: ItemKind, folder: &mut T) -> ItemKind {
match i {
- ItemKind::ExternCrate(string) => ItemKind::ExternCrate(string),
+ ItemKind::ExternCrate(orig_name) => ItemKind::ExternCrate(orig_name),
ItemKind::Use(use_tree) => {
ItemKind::Use(use_tree.map(|tree| folder.fold_use_tree(tree)))
}
ident: keywords::Invalid.ident(),
attrs,
id: ast::DUMMY_NODE_ID,
- vis: respan(span.empty(), ast::VisibilityKind::Public),
+ vis: respan(span.shrink_to_lo(), ast::VisibilityKind::Public),
span,
node: ast::ItemKind::Mod(module),
tokens: None,
use errors::DiagnosticId;
use errors::emitter::{Emitter, EmitterWriter};
-use rustc_data_structures::sync::Lrc;
+use rustc_data_structures::sync::{self, Lrc};
use std::io::{self, Write};
use std::vec;
use std::sync::{Arc, Mutex};
pub struct JsonEmitter {
dst: Box<Write + Send>,
registry: Option<Registry>,
- cm: Lrc<CodeMapper + 'static>,
+ cm: Lrc<CodeMapper + sync::Send + sync::Sync>,
pretty: bool,
/// Whether "approximate suggestions" are enabled in the config
approximate_suggestions: bool,
debug!("parse_attribute_with_inner_parse_policy: inner_parse_policy={:?} self.token={:?}",
inner_parse_policy,
self.token);
- let (span, path, tokens, mut style) = match self.token {
+ let (span, path, tokens, style) = match self.token {
token::Pound => {
let lo = self.span;
self.bump();
}
};
- if inner_parse_policy == InnerAttributeParsePolicy::Permitted &&
- self.token == token::Semi {
- self.bump();
- self.span_warn(span,
- "this inner attribute syntax is deprecated. The new syntax is \
- `#![foo]`, with a bang and no semicolon");
- style = ast::AttrStyle::Inner;
- }
-
Ok(ast::Attribute {
id: attr::mk_attr_id(),
style,
impl Default for TokenAndSpan {
fn default() -> Self {
- TokenAndSpan { tok: token::Underscore, sp: syntax_pos::DUMMY_SP }
+ TokenAndSpan { tok: token::Whitespace, sp: syntax_pos::DUMMY_SP }
}
}
pub fn try_next_token(&mut self) -> Result<TokenAndSpan, ()> {
assert!(self.fatal_errs.is_empty());
let ret_val = TokenAndSpan {
- tok: replace(&mut self.peek_tok, token::Underscore),
+ tok: replace(&mut self.peek_tok, token::Whitespace),
sp: self.peek_span,
};
self.advance_token()?;
// Make the range zero-length if the span is invalid.
if span.lo() > span.hi() || begin.fm.start_pos != end.fm.start_pos {
- span = span.with_hi(span.lo());
+ span = span.shrink_to_lo();
}
let mut sr = StringReader::new_raw_internal(sess, begin.fm);
// I guess this is the only way to figure out if
// we're at the beginning of the file...
let cmap = CodeMap::new(FilePathMapping::empty());
- cmap.files.borrow_mut().push(self.filemap.clone());
+ cmap.files.borrow_mut().file_maps.push(self.filemap.clone());
let loc = cmap.lookup_char_pos_adj(self.pos);
debug!("Skipping a shebang");
if loc.line == 1 && loc.col == CharPos(0) {
self.bump();
}
- return Ok(self.with_str_from(start, |string| {
- if string == "_" {
- token::Underscore
- } else {
- // FIXME: perform NFKC normalization here. (Issue #2253)
- token::Ident(self.mk_ident(string))
- }
- }));
+ // FIXME: perform NFKC normalization here. (Issue #2253)
+ return Ok(self.with_str_from(start, |string| token::Ident(self.mk_ident(string))));
}
if is_dec_digit(c) {
id: ast::DUMMY_NODE_ID,
node: ast::ExprKind::Path(None, ast::Path {
span: sp(0, 6),
- segments: vec![ast::PathSegment::crate_root(sp(0, 2)),
+ segments: vec![ast::PathSegment::crate_root(sp(0, 0)),
str2seg("a", 2, 3),
str2seg("b", 5, 6)]
}),
-> Self {
let mut parser = Parser {
sess,
- token: token::Underscore,
+ token: token::Whitespace,
span: syntax_pos::DUMMY_SP,
prev_span: syntax_pos::DUMMY_SP,
meta_var_span: None,
Err(if self.prev_token_kind == PrevTokenKind::DocComment {
self.span_fatal_err(self.prev_span, Error::UselessDocComment)
} else {
- let mut err = self.expected_ident_found();
- if self.token == token::Underscore {
- err.note("`_` is a wildcard pattern, not an identifier");
- }
- err
+ self.expected_ident_found()
})
}
}
if self.eat(&token::RArrow) {
Ok(FunctionRetTy::Ty(self.parse_ty_common(allow_plus, true)?))
} else {
- Ok(FunctionRetTy::Default(self.span.with_hi(self.span.lo())))
+ Ok(FunctionRetTy::Default(self.span.shrink_to_lo()))
}
}
let e = self.parse_expr()?;
self.expect(&token::CloseDelim(token::Paren))?;
TyKind::Typeof(e)
- } else if self.eat(&token::Underscore) {
+ } else if self.eat_keyword(keywords::Underscore) {
// A type to be inferred `_`
TyKind::Infer
} else if self.token_is_bare_fn_keyword() {
_ => 0,
};
- self.look_ahead(offset, |t| t.is_ident() || t == &token::Underscore) &&
+ self.look_ahead(offset, |t| t.is_ident()) &&
self.look_ahead(offset + 1, |t| t == &token::Colon)
}
let lo = self.meta_var_span.unwrap_or(self.span);
let mut segments = Vec::new();
if self.eat(&token::ModSep) {
- segments.push(PathSegment::crate_root(lo));
+ segments.push(PathSegment::crate_root(lo.shrink_to_lo()));
}
self.parse_path_segments(&mut segments, style, enable_warning)?;
loop {
segments.push(self.parse_path_segment(style, enable_warning)?);
- if self.is_import_coupler(false) || !self.eat(&token::ModSep) {
+ if self.is_import_coupler() || !self.eat(&token::ModSep) {
return Ok(());
}
}
},
token::CloseDelim(_) | token::Eof => unreachable!(),
_ => {
- let (token, span) = (mem::replace(&mut self.token, token::Underscore), self.span);
+ let (token, span) = (mem::replace(&mut self.token, token::Whitespace), self.span);
self.bump();
TokenTree::Token(span, token)
}
slice = Some(P(Pat {
id: ast::DUMMY_NODE_ID,
node: PatKind::Wild,
- span: self.span,
+ span: self.prev_span,
}));
before_slice = false;
}
let lo = self.span;
let pat;
match self.token {
- token::Underscore => {
- // Parse _
- self.bump();
- pat = PatKind::Wild;
- }
token::BinOp(token::And) | token::AndAnd => {
// Parse &pat / &mut pat
self.expect_and()?;
self.expect(&token::CloseDelim(token::Bracket))?;
pat = PatKind::Slice(before, slice, after);
}
- // At this point, token != _, &, &&, (, [
- _ => if self.eat_keyword(keywords::Mut) {
+ // At this point, token != &, &&, (, [
+ _ => if self.eat_keyword(keywords::Underscore) {
+ // Parse _
+ pat = PatKind::Wild;
+ } else if self.eat_keyword(keywords::Mut) {
// Parse mut ident @ pat / mut ref ident @ pat
let mutref_span = self.prev_span.to(self.span);
let binding_mode = if self.eat_keyword(keywords::Ref) {
// `pub(in path)`
self.bump(); // `(`
self.bump(); // `in`
- let path = self.parse_path(PathStyle::Mod)?.default_to_global(); // `path`
+ let path = self.parse_path(PathStyle::Mod)?; // `path`
self.expect(&token::CloseDelim(token::Paren))?; // `)`
let vis = respan(lo.to(self.prev_span), VisibilityKind::Restricted {
path: P(path),
{
// `pub(self)` or `pub(super)`
self.bump(); // `(`
- let path = self.parse_path(PathStyle::Mod)?.default_to_global(); // `super`/`self`
+ let path = self.parse_path(PathStyle::Mod)?; // `super`/`self`
self.expect(&token::CloseDelim(token::Paren))?; // `)`
let vis = respan(lo.to(self.prev_span), VisibilityKind::Restricted {
path: P(path),
lo: Span,
visibility: Visibility,
attrs: Vec<Attribute>)
- -> PResult<'a, P<Item>> {
-
- let crate_name = self.parse_ident()?;
- let (maybe_path, ident) = if let Some(ident) = self.parse_rename()? {
- (Some(crate_name.name), ident)
+ -> PResult<'a, P<Item>> {
+ let orig_name = self.parse_ident()?;
+ let (item_name, orig_name) = if let Some(rename) = self.parse_rename()? {
+ (rename, Some(orig_name.name))
} else {
- (None, crate_name)
+ (orig_name, None)
};
self.expect(&token::Semi)?;
- let prev_span = self.prev_span;
-
- Ok(self.mk_item(lo.to(prev_span),
- ident,
- ItemKind::ExternCrate(maybe_path),
- visibility,
- attrs))
+ let span = lo.to(self.prev_span);
+ Ok(self.mk_item(span, item_name, ItemKind::ExternCrate(orig_name), visibility, attrs))
}
/// Parse `extern` for foreign ABIs
if self.eat_keyword(keywords::Use) {
// USE ITEM
- let item_ = ItemKind::Use(P(self.parse_use_tree(false)?));
+ let item_ = ItemKind::Use(P(self.parse_use_tree()?));
self.expect(&token::Semi)?;
- let prev_span = self.prev_span;
- let invalid = keywords::Invalid.ident();
- let item = self.mk_item(lo.to(prev_span), invalid, item_, visibility, attrs);
+ let span = lo.to(self.prev_span);
+ let item = self.mk_item(span, keywords::Invalid.ident(), item_, visibility, attrs);
return Ok(Some(item));
}
}))
}
- /// `{` or `::{` or `*` or `::*`
- /// `::{` or `::*` (also `{` or `*` if unprefixed is true)
- fn is_import_coupler(&mut self, unprefixed: bool) -> bool {
- self.is_import_coupler_inner(&token::OpenDelim(token::Brace), unprefixed) ||
- self.is_import_coupler_inner(&token::BinOp(token::Star), unprefixed)
- }
-
- fn is_import_coupler_inner(&mut self, token: &token::Token, unprefixed: bool) -> bool {
- if self.check(&token::ModSep) {
- self.look_ahead(1, |t| t == token)
- } else if unprefixed {
- self.check(token)
- } else {
- false
- }
+ /// `::{` or `::*`
+ fn is_import_coupler(&mut self) -> bool {
+ self.check(&token::ModSep) &&
+ self.look_ahead(1, |t| *t == token::OpenDelim(token::Brace) ||
+ *t == token::BinOp(token::Star))
}
/// Parse UseTree
///
- /// USE_TREE = `*` |
- /// `{` USE_TREE_LIST `}` |
+ /// USE_TREE = [`::`] `*` |
+ /// [`::`] `{` USE_TREE_LIST `}` |
/// PATH `::` `*` |
/// PATH `::` `{` USE_TREE_LIST `}` |
/// PATH [`as` IDENT]
- fn parse_use_tree(&mut self, nested: bool) -> PResult<'a, UseTree> {
+ fn parse_use_tree(&mut self) -> PResult<'a, UseTree> {
let lo = self.span;
- let mut prefix = ast::Path {
- segments: vec![],
- span: lo.to(self.span),
- };
-
- let kind = if self.is_import_coupler(true) {
- // `use *;` or `use ::*;` or `use {...};` `use ::{...};`
-
- // Remove the first `::`
+ let mut prefix = ast::Path { segments: Vec::new(), span: lo.shrink_to_lo() };
+ let kind = if self.check(&token::OpenDelim(token::Brace)) ||
+ self.check(&token::BinOp(token::Star)) ||
+ self.is_import_coupler() {
+ // `use *;` or `use ::*;` or `use {...};` or `use ::{...};`
if self.eat(&token::ModSep) {
- prefix.segments.push(PathSegment::crate_root(self.prev_span));
- } else if !nested {
- prefix.segments.push(PathSegment::crate_root(self.span));
+ prefix.segments.push(PathSegment::crate_root(lo.shrink_to_lo()));
}
if self.eat(&token::BinOp(token::Star)) {
- // `use *;`
UseTreeKind::Glob
- } else if self.check(&token::OpenDelim(token::Brace)) {
- // `use {...};`
- UseTreeKind::Nested(self.parse_use_tree_list()?)
} else {
- return self.unexpected();
+ UseTreeKind::Nested(self.parse_use_tree_list()?)
}
} else {
- // `use path::...;`
- let mut parsed = self.parse_path(PathStyle::Mod)?;
- if !nested {
- parsed = parsed.default_to_global();
- }
-
- prefix.segments.append(&mut parsed.segments);
- prefix.span = prefix.span.to(parsed.span);
+ // `use path::*;` or `use path::{...};` or `use path;` or `use path as bar;`
+ prefix = self.parse_path(PathStyle::Mod)?;
if self.eat(&token::ModSep) {
if self.eat(&token::BinOp(token::Star)) {
- // `use path::*;`
UseTreeKind::Glob
- } else if self.check(&token::OpenDelim(token::Brace)) {
- // `use path::{...};`
- UseTreeKind::Nested(self.parse_use_tree_list()?)
} else {
- return self.unexpected();
+ UseTreeKind::Nested(self.parse_use_tree_list()?)
}
} else {
- // `use path::foo;` or `use path::foo as bar;`
- let rename = self.parse_rename()?.
- unwrap_or(prefix.segments.last().unwrap().identifier);
- UseTreeKind::Simple(rename)
+ UseTreeKind::Simple(self.parse_rename()?)
}
};
- Ok(UseTree {
- span: lo.to(self.prev_span),
- kind,
- prefix,
- })
+ Ok(UseTree { prefix, kind, span: lo.to(self.prev_span) })
}
/// Parse UseTreeKind::Nested(list)
self.parse_unspanned_seq(&token::OpenDelim(token::Brace),
&token::CloseDelim(token::Brace),
SeqSep::trailing_allowed(token::Comma), |this| {
- Ok((this.parse_use_tree(true)?, ast::DUMMY_NODE_ID))
+ Ok((this.parse_use_tree()?, ast::DUMMY_NODE_ID))
})
}
fn parse_rename(&mut self) -> PResult<'a, Option<Ident>> {
if self.eat_keyword(keywords::As) {
- if self.eat(&token::Underscore) {
- Ok(Some(Ident::with_empty_ctxt(Symbol::gensym("_"))))
- } else {
- self.parse_ident().map(Some)
+ match self.token {
+ token::Ident(ident) if ident.name == keywords::Underscore.name() => {
+ self.bump(); // `_`
+ Ok(Some(Ident { name: ident.name.gensymed(), ..ident }))
+ }
+ _ => self.parse_ident().map(Some),
}
} else {
Ok(None)
!ident_token.is_reserved_ident() ||
ident_token.is_path_segment_keyword() ||
[
+ keywords::Underscore.name(),
keywords::For.name(),
keywords::Impl.name(),
keywords::Fn.name(),
/* Name components */
Ident(ast::Ident),
- Underscore,
Lifetime(ast::Ident),
// The `LazyTokenStream` is a pure function of the `Nonterminal`,
Ident(ident) => ident_can_begin_type(ident), // type name or keyword
OpenDelim(Paren) | // tuple
OpenDelim(Bracket) | // array
- Underscore | // placeholder
Not | // never
BinOp(Star) | // raw pointer
BinOp(And) | // reference
id.name == keywords::SelfType.name() ||
id.name == keywords::Extern.name() ||
id.name == keywords::Crate.name() ||
+ id.name == keywords::CrateRoot.name() ||
id.name == keywords::DollarCrate.name(),
None => false,
}
// unnamed method parameters, crate root module, error recovery etc.
pub fn is_special_ident(&self) -> bool {
match self.ident() {
- Some(id) => id.name <= keywords::DollarCrate.name(),
+ Some(id) => id.name <= keywords::Underscore.name(),
_ => false,
}
}
Le | EqEq | Ne | Ge | AndAnd | OrOr | Tilde | BinOpEq(..) | At | DotDotDot | DotEq |
DotDotEq | Comma | Semi | ModSep | RArrow | LArrow | FatArrow | Pound | Dollar |
- Question | OpenDelim(..) | CloseDelim(..) | Underscore => return None,
+ Question | OpenDelim(..) | CloseDelim(..) => return None,
Literal(..) | Ident(..) | Lifetime(..) | Interpolated(..) | DocComment(..) |
Whitespace | Comment | Shebang(..) | Eof => return None,
pub fn is_op(tok: &Token) -> bool {
match *tok {
OpenDelim(..) | CloseDelim(..) | Literal(..) | DocComment(..) |
- Ident(..) | Underscore | Lifetime(..) | Interpolated(..) |
+ Ident(..) | Lifetime(..) | Interpolated(..) |
Whitespace | Comment | Shebang(..) | Eof => false,
_ => true,
}
/* Name components */
token::Ident(s) => s.to_string(),
token::Lifetime(s) => s.to_string(),
- token::Underscore => "_".to_string(),
/* Other */
token::DocComment(s) => s.to_string(),
}
pub fn path_to_string(p: &ast::Path) -> String {
- to_string(|s| s.print_path(p, false, 0, false))
+ to_string(|s| s.print_path(p, false, 0))
}
pub fn path_segment_to_string(p: &ast::PathSegment) -> String {
&f.generic_params)?;
}
ast::TyKind::Path(None, ref path) => {
- self.print_path(path, false, 0, false)?;
+ self.print_path(path, false, 0)?;
}
ast::TyKind::Path(Some(ref qself), ref path) => {
self.print_qpath(path, qself, false)?
self.print_outer_attributes(&item.attrs)?;
self.ann.pre(self, NodeItem(item))?;
match item.node {
- ast::ItemKind::ExternCrate(ref optional_path) => {
+ ast::ItemKind::ExternCrate(orig_name) => {
self.head(&visibility_qualified(&item.vis, "extern crate"))?;
- if let Some(p) = *optional_path {
- let val = p.as_str();
- if val.contains('-') {
- self.print_string(&val, ast::StrStyle::Cooked)?;
- } else {
- self.print_name(p)?;
- }
+ if let Some(orig_name) = orig_name {
+ self.print_name(orig_name)?;
self.s.space()?;
self.s.word("as")?;
self.s.space()?;
self.s.word(";")?;
}
ast::ItemKind::Mac(codemap::Spanned { ref node, .. }) => {
- self.print_path(&node.path, false, 0, false)?;
+ self.print_path(&node.path, false, 0)?;
self.s.word("! ")?;
self.print_ident(item.ident)?;
self.cbox(INDENT_UNIT)?;
}
fn print_trait_ref(&mut self, t: &ast::TraitRef) -> io::Result<()> {
- self.print_path(&t.path, false, 0, false)
+ self.print_path(&t.path, false, 0)
}
fn print_formal_generic_params(
ast::CrateSugar::JustCrate => self.word_nbsp("crate")
}
ast::VisibilityKind::Restricted { ref path, .. } => {
- let path = to_string(|s| s.print_path(path, false, 0, true));
+ let path = to_string(|s| s.print_path(path, false, 0));
if path == "self" || path == "super" {
self.word_nbsp(&format!("pub({})", path))
} else {
ti.ident,
ty,
default.as_ref().map(|expr| &**expr),
- &codemap::respan(ti.span.empty(), ast::VisibilityKind::Inherited),
+ &codemap::respan(ti.span.shrink_to_lo(), ast::VisibilityKind::Inherited),
)?;
}
ast::TraitItemKind::Method(ref sig, ref body) => {
ti.ident,
&ti.generics,
sig,
- &codemap::respan(ti.span.empty(), ast::VisibilityKind::Inherited),
+ &codemap::respan(ti.span.shrink_to_lo(), ast::VisibilityKind::Inherited),
)?;
if let Some(ref body) = *body {
self.nbsp()?;
}
ast::TraitItemKind::Macro(codemap::Spanned { ref node, .. }) => {
// code copied from ItemKind::Mac:
- self.print_path(&node.path, false, 0, false)?;
+ self.print_path(&node.path, false, 0)?;
self.s.word("! ")?;
self.cbox(INDENT_UNIT)?;
self.popen()?;
}
ast::ImplItemKind::Macro(codemap::Spanned { ref node, .. }) => {
// code copied from ItemKind::Mac:
- self.print_path(&node.path, false, 0, false)?;
+ self.print_path(&node.path, false, 0)?;
self.s.word("! ")?;
self.cbox(INDENT_UNIT)?;
self.popen()?;
pub fn print_mac(&mut self, m: &ast::Mac, delim: token::DelimToken)
-> io::Result<()> {
- self.print_path(&m.node.path, false, 0, false)?;
+ self.print_path(&m.node.path, false, 0)?;
self.s.word("!")?;
match delim {
token::Paren => self.popen()?,
fields: &[ast::Field],
wth: &Option<P<ast::Expr>>,
attrs: &[Attribute]) -> io::Result<()> {
- self.print_path(path, true, 0, false)?;
+ self.print_path(path, true, 0)?;
self.s.word("{")?;
self.print_inner_attributes_inline(attrs)?;
self.commasep_cmnt(
}
}
ast::ExprKind::Path(None, ref path) => {
- self.print_path(path, true, 0, false)?
+ self.print_path(path, true, 0)?
}
ast::ExprKind::Path(Some(ref qself), ref path) => {
self.print_qpath(path, qself, true)?
fn print_path(&mut self,
path: &ast::Path,
colons_before_params: bool,
- depth: usize,
- defaults_to_global: bool)
+ depth: usize)
-> io::Result<()>
{
self.maybe_print_comment(path.span.lo())?;
- let mut segments = path.segments[..path.segments.len()-depth].iter();
- if defaults_to_global && path.is_global() {
- segments.next();
- }
- for (i, segment) in segments.enumerate() {
+ for (i, segment) in path.segments[..path.segments.len() - depth].iter().enumerate() {
if i > 0 {
self.s.word("::")?
}
self.s.space()?;
self.word_space("as")?;
let depth = path.segments.len() - qself.position;
- self.print_path(path, false, depth, false)?;
+ self.print_path(path, false, depth)?;
}
self.s.word(">")?;
self.s.word("::")?;
}
}
PatKind::TupleStruct(ref path, ref elts, ddpos) => {
- self.print_path(path, true, 0, false)?;
+ self.print_path(path, true, 0)?;
self.popen()?;
if let Some(ddpos) = ddpos {
self.commasep(Inconsistent, &elts[..ddpos], |s, p| s.print_pat(p))?;
self.pclose()?;
}
PatKind::Path(None, ref path) => {
- self.print_path(path, true, 0, false)?;
+ self.print_path(path, true, 0)?;
}
PatKind::Path(Some(ref qself), ref path) => {
self.print_qpath(path, qself, false)?;
}
PatKind::Struct(ref path, ref fields, etc) => {
- self.print_path(path, true, 0, false)?;
+ self.print_path(path, true, 0)?;
self.nbsp()?;
self.word_space("{")?;
self.commasep_cmnt(
pub fn print_use_tree(&mut self, tree: &ast::UseTree) -> io::Result<()> {
match tree.kind {
- ast::UseTreeKind::Simple(ref ident) => {
- self.print_path(&tree.prefix, false, 0, true)?;
-
- if tree.prefix.segments.last().unwrap().identifier.name != ident.name {
+ ast::UseTreeKind::Simple(rename) => {
+ self.print_path(&tree.prefix, false, 0)?;
+ if let Some(rename) = rename {
self.s.space()?;
self.word_space("as")?;
- self.print_ident(*ident)?;
+ self.print_ident(rename)?;
}
}
ast::UseTreeKind::Glob => {
if !tree.prefix.segments.is_empty() {
- self.print_path(&tree.prefix, false, 0, true)?;
+ self.print_path(&tree.prefix, false, 0)?;
self.s.word("::")?;
}
self.s.word("*")?;
if tree.prefix.segments.is_empty() {
self.s.word("{")?;
} else {
- self.print_path(&tree.prefix, false, 0, true)?;
+ self.print_path(&tree.prefix, false, 0)?;
self.s.word("::{")?;
}
self.commasep(Inconsistent, &items[..], |this, &(ref tree, _)| {
static INJECTED_CRATE_NAME: Cell<Option<&'static str>> = Cell::new(None);
}
-pub fn maybe_inject_crates_ref(mut krate: ast::Crate, alt_std_name: Option<String>) -> ast::Crate {
+pub fn maybe_inject_crates_ref(mut krate: ast::Crate, alt_std_name: Option<&str>) -> ast::Crate {
let name = if attr::contains_name(&krate.attrs, "no_core") {
return krate;
} else if attr::contains_name(&krate.attrs, "no_std") {
INJECTED_CRATE_NAME.with(|opt_name| opt_name.set(Some(name)));
- let crate_name = Symbol::intern(&alt_std_name.unwrap_or_else(|| name.to_string()));
-
krate.module.items.insert(0, P(ast::Item {
attrs: vec![attr::mk_attr_outer(DUMMY_SP,
attr::mk_attr_id(),
attr::mk_word_item(Symbol::intern("macro_use")))],
vis: dummy_spanned(ast::VisibilityKind::Inherited),
- node: ast::ItemKind::ExternCrate(Some(crate_name)),
+ node: ast::ItemKind::ExternCrate(alt_std_name.map(Symbol::intern)),
ident: ast::Ident::from_str(name),
id: ast::DUMMY_NODE_ID,
span: DUMMY_SP,
is_sugared_doc: false,
span,
}],
- vis: respan(span.empty(), ast::VisibilityKind::Inherited),
+ vis: respan(span.shrink_to_lo(), ast::VisibilityKind::Inherited),
node: ast::ItemKind::Use(P(ast::UseTree {
prefix: ast::Path {
- segments: ["{{root}}", name, "prelude", "v1"].into_iter().map(|name| {
+ segments: [name, "prelude", "v1"].into_iter().map(|name| {
ast::PathSegment::from_ident(ast::Ident::from_str(name), DUMMY_SP)
}).collect(),
span,
span_diagnostic: &errors::Handler,
features: &Features) -> ast::Crate {
// Check for #[reexport_test_harness_main = "some_name"] which
- // creates a `use some_name = __test::main;`. This needs to be
+ // creates a `use __test::main as some_name;`. This needs to be
// unconditional, so that the attribute is still marked as used in
// non-test builds.
let reexport_test_harness_main =
cx.ext_cx.path(DUMMY_SP, vec![super_, r]))
}).chain(tested_submods.into_iter().map(|(r, sym)| {
let path = cx.ext_cx.path(DUMMY_SP, vec![super_, r, sym]);
- cx.ext_cx.item_use_simple_(DUMMY_SP, dummy_spanned(ast::VisibilityKind::Public), r, path)
+ cx.ext_cx.item_use_simple_(DUMMY_SP, dummy_spanned(ast::VisibilityKind::Public),
+ Some(r), path)
})).collect();
let reexport_mod = ast::Mod {
(ast::ItemKind::Use(P(ast::UseTree {
span: DUMMY_SP,
prefix: path_node(vec![id_test]),
- kind: ast::UseTreeKind::Simple(id_test),
+ kind: ast::UseTreeKind::Simple(None),
})),
ast::VisibilityKind::Public, keywords::Invalid.ident())
} else {
tokens: None,
})).pop().unwrap();
let reexport = cx.reexport_test_harness_main.map(|s| {
- // building `use <ident> = __test::main`
- let reexport_ident = Ident::with_empty_ctxt(s);
+ // building `use __test::main as <ident>;`
+ let rename = Ident::with_empty_ctxt(s);
let use_path = ast::UseTree {
span: DUMMY_SP,
prefix: path_node(vec![mod_ident, Ident::from_str("main")]),
- kind: ast::UseTreeKind::Simple(reexport_ident),
+ kind: ast::UseTreeKind::Simple(Some(rename)),
};
expander.fold_item(P(ast::Item {
visitor.visit_vis(&item.vis);
visitor.visit_ident(item.span, item.ident);
match item.node {
- ItemKind::ExternCrate(opt_name) => {
- if let Some(name) = opt_name {
- visitor.visit_name(item.span, name);
+ ItemKind::ExternCrate(orig_name) => {
+ if let Some(orig_name) = orig_name {
+ visitor.visit_name(item.span, orig_name);
}
}
ItemKind::Use(ref use_tree) => {
visitor: &mut V, use_tree: &'a UseTree, id: NodeId,
) {
visitor.visit_path(&use_tree.prefix, id);
-
match use_tree.kind {
- UseTreeKind::Simple(ident) => {
- visitor.visit_ident(use_tree.span, ident);
+ UseTreeKind::Simple(rename) => {
+ if let Some(rename) = rename {
+ visitor.visit_ident(use_tree.span, rename);
+ }
}
UseTreeKind::Glob => {},
UseTreeKind::Nested(ref use_trees) => {
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use syntax::ast::*;
+use syntax::codemap::Spanned;
+use syntax::ext::base::*;
+use syntax::ext::build::AstBuilder;
+use syntax::parse::token;
+use syntax::print::pprust;
+use syntax::tokenstream::{TokenStream, TokenTree};
+use syntax_pos::{Span, DUMMY_SP};
+
+pub fn expand_assert<'cx>(
+ cx: &'cx mut ExtCtxt,
+ sp: Span,
+ tts: &[TokenTree],
+) -> Box<MacResult + 'cx> {
+ let mut parser = cx.new_parser_from_tts(tts);
+ let cond_expr = panictry!(parser.parse_expr());
+ let custom_msg_args = if parser.eat(&token::Comma) {
+ let ts = parser.parse_tokens();
+ if !ts.is_empty() {
+ Some(ts)
+ } else {
+ None
+ }
+ } else {
+ None
+ };
+
+ let sp = sp.with_ctxt(sp.ctxt().apply_mark(cx.current_expansion.mark));
+ let panic_call = Mac_ {
+ path: Path::from_ident(sp, Ident::from_str("panic")),
+ tts: if let Some(ts) = custom_msg_args {
+ ts.into()
+ } else {
+ // `expr_to_string` escapes the string literals with `.escape_default()`
+ // which escapes all non-ASCII characters with `\u`.
+ let escaped_expr = escape_format_string(&unescape_printable_unicode(
+ &pprust::expr_to_string(&cond_expr),
+ ));
+
+ TokenStream::from(TokenTree::Token(
+ DUMMY_SP,
+ token::Literal(
+ token::Lit::Str_(Name::intern(&format!("assertion failed: {}", escaped_expr))),
+ None,
+ ),
+ )).into()
+ },
+ };
+ let if_expr = cx.expr_if(
+ sp,
+ cx.expr(sp, ExprKind::Unary(UnOp::Not, cond_expr)),
+ cx.expr(
+ sp,
+ ExprKind::Mac(Spanned {
+ span: sp,
+ node: panic_call,
+ }),
+ ),
+ None,
+ );
+ MacEager::expr(if_expr)
+}
+
+/// Escapes a string for use as a formatting string.
+fn escape_format_string(s: &str) -> String {
+ let mut res = String::with_capacity(s.len());
+ for c in s.chars() {
+ res.extend(c.escape_debug());
+ match c {
+ '{' | '}' => res.push(c),
+ _ => {}
+ }
+ }
+ res
+}
+
+#[test]
+fn test_escape_format_string() {
+ assert!(escape_format_string(r"foo{}\") == r"foo{{}}\\");
+}
+
+/// Unescapes the escaped unicodes (`\u{...}`) that are printable.
+fn unescape_printable_unicode(mut s: &str) -> String {
+ use std::{char, u32};
+
+ let mut res = String::with_capacity(s.len());
+
+ loop {
+ if let Some(start) = s.find(r"\u{") {
+ res.push_str(&s[0..start]);
+ s = &s[start..];
+ s.find('}')
+ .and_then(|end| {
+ let v = u32::from_str_radix(&s[3..end], 16).ok()?;
+ let c = char::from_u32(v)?;
+ // Escape unprintable characters.
+ res.extend(c.escape_debug());
+ s = &s[end + 1..];
+ Some(())
+ })
+ .expect("lexer should have rejected invalid escape sequences");
+ } else {
+ res.push_str(s);
+ return res;
+ }
+ }
+}
+
+#[test]
+fn test_unescape_printable_unicode() {
+ assert!(unescape_printable_unicode(r"\u{2603}\n\u{0}") == r"☃\n\u{0}");
+}
id: ast::DUMMY_NODE_ID,
span: self.span,
ident,
- vis: respan(self.span.empty(), ast::VisibilityKind::Inherited),
+ vis: respan(self.span.shrink_to_lo(), ast::VisibilityKind::Inherited),
defaultness: ast::Defaultness::Final,
attrs: Vec::new(),
generics: Generics::default(),
attrs: self.attributes.clone(),
generics: fn_generics,
span: trait_.span,
- vis: respan(trait_.span.empty(), ast::VisibilityKind::Inherited),
+ vis: respan(trait_.span.shrink_to_lo(), ast::VisibilityKind::Inherited),
defaultness: ast::Defaultness::Final,
ident: method_ident,
node: ast::ImplItemKind::Method(ast::MethodSig {
use syntax::ext::base::*;
use syntax::ext::base;
use syntax::ext::build::AstBuilder;
-use syntax::symbol::Symbol;
+use syntax::symbol::{keywords, Symbol};
use syntax_pos::Span;
use syntax::tokenstream;
let sp = sp.with_ctxt(sp.ctxt().apply_mark(cx.current_expansion.mark));
let e = match env::var(&*var.as_str()) {
Err(..) => {
+ let lt = cx.lifetime(sp, keywords::StaticLifetime.ident());
cx.expr_path(cx.path_all(sp,
true,
cx.std_path(&["option", "Option", "None"]),
Vec::new(),
vec![cx.ty_rptr(sp,
cx.ty_ident(sp, Ident::from_str("str")),
- Some(cx.lifetime(sp,
- Ident::from_str("'static"))),
+ Some(lt),
ast::Mutability::Immutable)],
Vec::new()))
}
asm,
ctxt: cx.backtrace(),
})),
- vis: respan(sp.empty(), ast::VisibilityKind::Inherited),
+ vis: respan(sp.shrink_to_lo(), ast::VisibilityKind::Inherited),
span: sp,
tokens: None,
})))
#![feature(proc_macro_internals)]
#![feature(decl_macro)]
+#![feature(str_escape)]
extern crate fmt_macros;
#[macro_use]
extern crate rustc_data_structures;
extern crate rustc_errors as errors;
+mod assert;
mod asm;
mod cfg;
mod compile_error;
def_info: None,
allow_internal_unstable: false,
allow_internal_unsafe: false,
+ unstable_feature: None,
});
)* }
}
log_syntax: log_syntax::expand_syntax_ext,
trace_macros: trace_macros::expand_trace_macros,
compile_error: compile_error::expand_compile_error,
+ assert: assert::expand_assert,
}
// format_args uses `unstable` things internally.
def_info: None,
allow_internal_unstable: true,
allow_internal_unsafe: false,
+ unstable_feature: None
});
for (name, ext) in user_exts {
#![feature(specialization)]
use std::borrow::Cow;
-use std::cell::{Cell, RefCell};
+use std::cell::Cell;
use std::cmp::{self, Ordering};
use std::fmt;
use std::hash::{Hasher, Hash};
/// Returns a new span representing an empty span at the beginning of this span
#[inline]
- pub fn empty(self) -> Span {
- self.with_hi(self.lo())
+ pub fn shrink_to_lo(self) -> Span {
+ let span = self.data();
+ span.with_hi(span.lo)
+ }
+ /// Returns a new span representing an empty span at the end of this span
+ #[inline]
+ pub fn shrink_to_hi(self) -> Span {
+ let span = self.data();
+ span.with_lo(span.hi)
}
/// Returns `self` if `self` is not the dummy span, and `other` otherwise.
pub src_hash: u128,
/// The external source code (used for external crates, which will have a `None`
/// value as `self.src`.
- pub external_src: RefCell<ExternalSource>,
+ pub external_src: Lock<ExternalSource>,
/// The start position of this source in the CodeMap
pub start_pos: BytePos,
/// The end position of this source in the CodeMap
pub end_pos: BytePos,
/// Locations of lines beginnings in the source code
- pub lines: RefCell<Vec<BytePos>>,
+ pub lines: Lock<Vec<BytePos>>,
/// Locations of multi-byte characters in the source code
- pub multibyte_chars: RefCell<Vec<MultiByteChar>>,
+ pub multibyte_chars: Lock<Vec<MultiByteChar>>,
/// Width of characters that are not narrow in the source code
- pub non_narrow_chars: RefCell<Vec<NonNarrowChar>>,
+ pub non_narrow_chars: Lock<Vec<NonNarrowChar>>,
/// A hash of the filename, used for speeding up the incr. comp. hashing.
pub name_hash: u128,
}
end_pos,
src: None,
src_hash,
- external_src: RefCell::new(ExternalSource::AbsentOk),
- lines: RefCell::new(lines),
- multibyte_chars: RefCell::new(multibyte_chars),
- non_narrow_chars: RefCell::new(non_narrow_chars),
+ external_src: Lock::new(ExternalSource::AbsentOk),
+ lines: Lock::new(lines),
+ multibyte_chars: Lock::new(multibyte_chars),
+ non_narrow_chars: Lock::new(non_narrow_chars),
name_hash,
})
})
crate_of_origin: 0,
src: Some(Lrc::new(src)),
src_hash,
- external_src: RefCell::new(ExternalSource::Unneeded),
+ external_src: Lock::new(ExternalSource::Unneeded),
start_pos,
end_pos: Pos::from_usize(end_pos),
- lines: RefCell::new(Vec::new()),
- multibyte_chars: RefCell::new(Vec::new()),
- non_narrow_chars: RefCell::new(Vec::new()),
+ lines: Lock::new(Vec::new()),
+ multibyte_chars: Lock::new(Vec::new()),
+ non_narrow_chars: Lock::new(Vec::new()),
name_hash,
}
}
if *self.external_src.borrow() == ExternalSource::AbsentOk {
let src = get_src();
let mut external_src = self.external_src.borrow_mut();
- if let Some(src) = src {
- let mut hasher: StableHasher<u128> = StableHasher::new();
- hasher.write(src.as_bytes());
-
- if hasher.finish() == self.src_hash {
- *external_src = ExternalSource::Present(src);
- return true;
+ // Check that no-one else have provided the source while we were getting it
+ if *external_src == ExternalSource::AbsentOk {
+ if let Some(src) = src {
+ let mut hasher: StableHasher<u128> = StableHasher::new();
+ hasher.write(src.as_bytes());
+
+ if hasher.finish() == self.src_hash {
+ *external_src = ExternalSource::Present(src);
+ return true;
+ }
+ } else {
+ *external_src = ExternalSource::AbsentErr;
}
+
+ false
} else {
- *external_src = ExternalSource::AbsentErr;
+ self.src.is_some() || external_src.get_source().is_some()
}
-
- false
} else {
self.src.is_some() || self.external_src.borrow().get_source().is_some()
}
}
}
- let lines = self.lines.borrow();
- let line = if let Some(line) = lines.get(line_number) {
- line
- } else {
- return None;
+ let begin = {
+ let lines = self.lines.borrow();
+ let line = if let Some(line) = lines.get(line_number) {
+ line
+ } else {
+ return None;
+ };
+ let begin: BytePos = *line - self.start_pos;
+ begin.to_usize()
};
- let begin: BytePos = *line - self.start_pos;
- let begin = begin.to_usize();
if let Some(ref src) = self.src {
Some(Cow::from(get_until_newline(src, begin)))
declare_keywords! {
// Special reserved identifiers used internally for elided lifetimes,
// unnamed method parameters, crate root module, error recovery etc.
- (0, Invalid, "")
- (1, CrateRoot, "{{root}}")
- (2, DollarCrate, "$crate")
+ (0, Invalid, "")
+ (1, CrateRoot, "{{root}}")
+ (2, DollarCrate, "$crate")
+ (3, Underscore, "_")
// Keywords used in the language.
- (3, As, "as")
- (4, Box, "box")
- (5, Break, "break")
- (6, Const, "const")
- (7, Continue, "continue")
- (8, Crate, "crate")
- (9, Else, "else")
- (10, Enum, "enum")
- (11, Extern, "extern")
- (12, False, "false")
- (13, Fn, "fn")
- (14, For, "for")
- (15, If, "if")
- (16, Impl, "impl")
- (17, In, "in")
- (18, Let, "let")
- (19, Loop, "loop")
- (20, Match, "match")
- (21, Mod, "mod")
- (22, Move, "move")
- (23, Mut, "mut")
- (24, Pub, "pub")
- (25, Ref, "ref")
- (26, Return, "return")
- (27, SelfValue, "self")
- (28, SelfType, "Self")
- (29, Static, "static")
- (30, Struct, "struct")
- (31, Super, "super")
- (32, Trait, "trait")
- (33, True, "true")
- (34, Type, "type")
- (35, Unsafe, "unsafe")
- (36, Use, "use")
- (37, Where, "where")
- (38, While, "while")
+ (4, As, "as")
+ (5, Box, "box")
+ (6, Break, "break")
+ (7, Const, "const")
+ (8, Continue, "continue")
+ (9, Crate, "crate")
+ (10, Else, "else")
+ (11, Enum, "enum")
+ (12, Extern, "extern")
+ (13, False, "false")
+ (14, Fn, "fn")
+ (15, For, "for")
+ (16, If, "if")
+ (17, Impl, "impl")
+ (18, In, "in")
+ (19, Let, "let")
+ (20, Loop, "loop")
+ (21, Match, "match")
+ (22, Mod, "mod")
+ (23, Move, "move")
+ (24, Mut, "mut")
+ (25, Pub, "pub")
+ (26, Ref, "ref")
+ (27, Return, "return")
+ (28, SelfValue, "self")
+ (29, SelfType, "Self")
+ (30, Static, "static")
+ (31, Struct, "struct")
+ (32, Super, "super")
+ (33, Trait, "trait")
+ (34, True, "true")
+ (35, Type, "type")
+ (36, Unsafe, "unsafe")
+ (37, Use, "use")
+ (38, Where, "where")
+ (39, While, "while")
// Keywords reserved for future use.
- (39, Abstract, "abstract")
- (40, Alignof, "alignof")
- (41, Become, "become")
- (42, Do, "do")
- (43, Final, "final")
- (44, Macro, "macro")
- (45, Offsetof, "offsetof")
- (46, Override, "override")
- (47, Priv, "priv")
- (48, Proc, "proc")
- (49, Pure, "pure")
- (50, Sizeof, "sizeof")
- (51, Typeof, "typeof")
- (52, Unsized, "unsized")
- (53, Virtual, "virtual")
- (54, Yield, "yield")
+ (40, Abstract, "abstract")
+ (41, Alignof, "alignof")
+ (42, Become, "become")
+ (43, Do, "do")
+ (44, Final, "final")
+ (45, Macro, "macro")
+ (46, Offsetof, "offsetof")
+ (47, Override, "override")
+ (48, Priv, "priv")
+ (49, Proc, "proc")
+ (50, Pure, "pure")
+ (51, Sizeof, "sizeof")
+ (52, Typeof, "typeof")
+ (53, Unsized, "unsized")
+ (54, Virtual, "virtual")
+ (55, Yield, "yield")
+
+ // Special lifetime names
+ (56, UnderscoreLifetime, "'_")
+ (57, StaticLifetime, "'static")
// Weak keywords, have special meaning only in specific contexts.
- (55, Auto, "auto")
- (56, Catch, "catch")
- (57, Default, "default")
- (58, Dyn, "dyn")
- (59, StaticLifetime, "'static")
- (60, Union, "union")
+ (58, Auto, "auto")
+ (59, Catch, "catch")
+ (60, Default, "default")
+ (61, Dyn, "dyn")
+ (62, Union, "union")
}
// If an interner exists, return it. Otherwise, prepare a fresh one.
#if LLVM_VERSION_GE(5, 0)
#include "llvm/ADT/Optional.h"
+#else
+#include <cstdlib>
#endif
//===----------------------------------------------------------------------===
auto f = unwrap(M)->functions();
return std::distance(std::begin(f), std::end(f));
}
+
+// Vector reductions:
+#if LLVM_VERSION_GE(5, 0)
+extern "C" LLVMValueRef
+LLVMRustBuildVectorReduceFAdd(LLVMBuilderRef B, LLVMValueRef Acc, LLVMValueRef Src) {
+ return wrap(unwrap(B)->CreateFAddReduce(unwrap(Acc),unwrap(Src)));
+}
+extern "C" LLVMValueRef
+LLVMRustBuildVectorReduceFMul(LLVMBuilderRef B, LLVMValueRef Acc, LLVMValueRef Src) {
+ return wrap(unwrap(B)->CreateFMulReduce(unwrap(Acc),unwrap(Src)));
+}
+extern "C" LLVMValueRef
+LLVMRustBuildVectorReduceAdd(LLVMBuilderRef B, LLVMValueRef Src) {
+ return wrap(unwrap(B)->CreateAddReduce(unwrap(Src)));
+}
+extern "C" LLVMValueRef
+LLVMRustBuildVectorReduceMul(LLVMBuilderRef B, LLVMValueRef Src) {
+ return wrap(unwrap(B)->CreateMulReduce(unwrap(Src)));
+}
+extern "C" LLVMValueRef
+LLVMRustBuildVectorReduceAnd(LLVMBuilderRef B, LLVMValueRef Src) {
+ return wrap(unwrap(B)->CreateAndReduce(unwrap(Src)));
+}
+extern "C" LLVMValueRef
+LLVMRustBuildVectorReduceOr(LLVMBuilderRef B, LLVMValueRef Src) {
+ return wrap(unwrap(B)->CreateOrReduce(unwrap(Src)));
+}
+extern "C" LLVMValueRef
+LLVMRustBuildVectorReduceXor(LLVMBuilderRef B, LLVMValueRef Src) {
+ return wrap(unwrap(B)->CreateXorReduce(unwrap(Src)));
+}
+extern "C" LLVMValueRef
+LLVMRustBuildVectorReduceMin(LLVMBuilderRef B, LLVMValueRef Src, bool IsSigned) {
+ return wrap(unwrap(B)->CreateIntMinReduce(unwrap(Src), IsSigned));
+}
+extern "C" LLVMValueRef
+LLVMRustBuildVectorReduceMax(LLVMBuilderRef B, LLVMValueRef Src, bool IsSigned) {
+ return wrap(unwrap(B)->CreateIntMaxReduce(unwrap(Src), IsSigned));
+}
+extern "C" LLVMValueRef
+LLVMRustBuildVectorReduceFMin(LLVMBuilderRef B, LLVMValueRef Src, bool NoNaN) {
+ return wrap(unwrap(B)->CreateFPMinReduce(unwrap(Src), NoNaN));
+}
+extern "C" LLVMValueRef
+LLVMRustBuildVectorReduceFMax(LLVMBuilderRef B, LLVMValueRef Src, bool NoNaN) {
+ return wrap(unwrap(B)->CreateFPMaxReduce(unwrap(Src), NoNaN));
+}
+
+#else
+
+extern "C" LLVMValueRef
+LLVMRustBuildVectorReduceFAdd(LLVMBuilderRef, LLVMValueRef, LLVMValueRef) {
+ return nullptr;
+}
+extern "C" LLVMValueRef
+LLVMRustBuildVectorReduceFMul(LLVMBuilderRef, LLVMValueRef, LLVMValueRef) {
+ return nullptr;
+}
+extern "C" LLVMValueRef
+LLVMRustBuildVectorReduceAdd(LLVMBuilderRef, LLVMValueRef) {
+ return nullptr;
+}
+extern "C" LLVMValueRef
+LLVMRustBuildVectorReduceMul(LLVMBuilderRef, LLVMValueRef) {
+ return nullptr;
+}
+extern "C" LLVMValueRef
+LLVMRustBuildVectorReduceAnd(LLVMBuilderRef, LLVMValueRef) {
+ return nullptr;
+}
+extern "C" LLVMValueRef
+LLVMRustBuildVectorReduceOr(LLVMBuilderRef, LLVMValueRef) {
+ return nullptr;
+}
+extern "C" LLVMValueRef
+LLVMRustBuildVectorReduceXor(LLVMBuilderRef, LLVMValueRef) {
+ return nullptr;
+}
+extern "C" LLVMValueRef
+LLVMRustBuildVectorReduceMin(LLVMBuilderRef, LLVMValueRef, bool) {
+ return nullptr;
+}
+extern "C" LLVMValueRef
+LLVMRustBuildVectorReduceMax(LLVMBuilderRef, LLVMValueRef, bool) {
+ return nullptr;
+}
+extern "C" LLVMValueRef
+LLVMRustBuildVectorReduceFMin(LLVMBuilderRef, LLVMValueRef, bool) {
+ return nullptr;
+}
+extern "C" LLVMValueRef
+LLVMRustBuildVectorReduceFMax(LLVMBuilderRef, LLVMValueRef, bool) {
+ return nullptr;
+}
+#endif
# source tarball for a stable release you'll likely see `1.x.0` for rustc and
# `0.x.0` for Cargo where they were released on `date`.
-date: 2018-02-20
+date: 2018-03-18
rustc: beta
cargo: beta
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(staged_api)]
+#![stable(feature = "unit_test", since = "0.0.0")]
+
+#[unstable(feature = "unstable_macros", issue = "0")]
+#[macro_export]
+macro_rules! unstable_macro{ () => () }
//[mir]compile-flags: -Z borrowck=mir
#![feature(slice_patterns)]
-#![feature(advanced_slice_patterns)]
pub struct Foo {
x: u32
// Test that immutable pattern bindings cannot be reassigned.
-#![feature(slice_patterns)]
-
enum E {
Foo(isize)
}
// revisions: ast mir
//[mir]compile-flags: -Z borrowck=mir
-#![feature(box_syntax, slice_patterns, advanced_slice_patterns)]
+#![feature(box_syntax)]
+#![feature(slice_patterns)]
fn move_out_from_begin_and_end() {
let a = [box 1, box 2];
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(advanced_slice_patterns)]
#![feature(slice_patterns)]
fn a<'a>() -> &'a [isize] {
// except according to those terms.
#![feature(slice_patterns)]
-#![allow(unused_variables)]
#![deny(unreachable_patterns)]
fn main() {
// compile-flags:-Z verbose
-#![feature(slice_patterns)]
-
fn main() {
let x = [1,2];
let y = match x {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(slice_patterns)]
-
fn main() {
let x = [1,2];
let y = match x {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(slice_patterns)]
-
fn main() {
let values: Vec<u8> = vec![1,2,3,4,5,6,7,8];
// Matching against float literals should result in a linter error
-#![feature(slice_patterns)]
#![feature(exclusive_range_pattern)]
#![allow(unused)]
#![forbid(illegal_floating_point_literal_pattern)]
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Make sure that the mono-item collector does not crash when trying to
+// instantiate a default impl of a method with lifetime parameters.
+// See https://github.com/rust-lang/rust/issues/47309
+
+// compile-flags:-Clink-dead-code
+// must-compile-successfully
+
+#![crate_type="rlib"]
+
+pub trait EnvFuture {
+ type Item;
+
+ fn boxed_result<'a>(self) where Self: Sized, Self::Item: 'a, {
+ }
+}
+
+struct Foo;
+
+impl<'a> EnvFuture for &'a Foo {
+ type Item = ();
+}
// Matching against NaN should result in a warning
-#![feature(slice_patterns)]
#![allow(unused)]
#![deny(illegal_floating_point_literal_pattern)]
// except according to those terms.
#![deny(unused_import_braces)]
-#![allow(dead_code)]
-#![allow(unused_imports)]
use test::{A}; //~ ERROR braces around A is unnecessary
mod test {
+ use test::{self}; // OK
+ use test::{self as rename}; // OK
pub struct A;
}
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:unstable-macros.rs
+
+#![feature(staged_api)]
+#[macro_use] extern crate unstable_macros;
+
+#[unstable(feature = "local_unstable", issue = "0")]
+macro_rules! local_unstable { () => () }
+
+fn main() {
+ local_unstable!();
+ unstable_macro!(); //~ ERROR: macro unstable_macro! is unstable
+}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(advanced_slice_patterns, slice_patterns)]
-
fn main() {
let buf = &[0, 1, 2, 3];
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(advanced_slice_patterns, slice_patterns)]
+#![feature(slice_patterns)]
#![deny(unreachable_patterns)]
fn main() {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(slice_patterns)]
#![deny(unreachable_patterns)]
// The arity of `ref x` is always 1. If the pattern is compared to some non-structural type whose
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(advanced_slice_patterns, slice_patterns)]
+#![feature(slice_patterns)]
fn check(list: &[Option<()>]) {
match list {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(slice_patterns)]
#![deny(unreachable_patterns)]
fn a() {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(slice_patterns)]
-
fn main() {
match () {
[()] => { }
#![feature(slice_patterns)]
#![deny(unreachable_patterns)]
-#![allow(unused_variables)]
fn main() {
let x: Vec<(isize, isize)> = Vec::new();
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(slice_patterns, box_patterns)]
+#![feature(box_patterns)]
struct A;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(slice_patterns)]
-
fn assert_static<T: 'static>(_t: T) {}
fn main() {
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// min-llvm-version 5.0
+// ignore-emscripten
+
+// Test that the simd_reduce_{op} intrinsics produce ok-ish error
+// messages when misused.
+
+#![feature(repr_simd, platform_intrinsics)]
+#![allow(non_camel_case_types)]
+
+#[repr(simd)]
+#[derive(Copy, Clone)]
+pub struct f32x4(pub f32, pub f32, pub f32, pub f32);
+
+#[repr(simd)]
+#[derive(Copy, Clone)]
+pub struct u32x4(pub u32, pub u32, pub u32, pub u32);
+
+
+extern "platform-intrinsic" {
+ fn simd_reduce_add_ordered<T, U>(x: T, y: U) -> U;
+ fn simd_reduce_mul_ordered<T, U>(x: T, y: U) -> U;
+ fn simd_reduce_and<T, U>(x: T) -> U;
+ fn simd_reduce_or<T, U>(x: T) -> U;
+ fn simd_reduce_xor<T, U>(x: T) -> U;
+ fn simd_reduce_all<T>(x: T) -> bool;
+ fn simd_reduce_any<T>(x: T) -> bool;
+}
+
+fn main() {
+ let x = u32x4(0, 0, 0, 0);
+ let z = f32x4(0.0, 0.0, 0.0, 0.0);
+
+ unsafe {
+ simd_reduce_add_ordered(z, 0_f32);
+ simd_reduce_mul_ordered(z, 1_f32);
+
+ simd_reduce_add_ordered(z, 2_f32);
+ //~^ ERROR accumulator of simd_reduce_add_ordered is not 0.0
+ simd_reduce_mul_ordered(z, 3_f32);
+ //~^ ERROR accumulator of simd_reduce_mul_ordered is not 1.0
+
+ let _: f32 = simd_reduce_and(x);
+ //~^ ERROR expected return type `u32` (element of input `u32x4`), found `f32`
+ let _: f32 = simd_reduce_or(x);
+ //~^ ERROR expected return type `u32` (element of input `u32x4`), found `f32`
+ let _: f32 = simd_reduce_xor(x);
+ //~^ ERROR expected return type `u32` (element of input `u32x4`), found `f32`
+
+ let _: f32 = simd_reduce_and(z);
+ //~^ ERROR unsupported simd_reduce_and from `f32x4` with element `f32` to `f32`
+ let _: f32 = simd_reduce_or(z);
+ //~^ ERROR unsupported simd_reduce_or from `f32x4` with element `f32` to `f32`
+ let _: f32 = simd_reduce_xor(z);
+ //~^ ERROR unsupported simd_reduce_xor from `f32x4` with element `f32` to `f32`
+
+ let _: bool = simd_reduce_all(z);
+ //~^ ERROR unsupported simd_reduce_all from `f32x4` with element `f32` to `bool`
+ let _: bool = simd_reduce_any(z);
+ //~^ ERROR unsupported simd_reduce_any from `f32x4` with element `f32` to `bool`
+
+ foo(0_f32);
+ }
+}
+
+#[inline(never)]
+unsafe fn foo(x: f32) {
+ let z = f32x4(0.0, 0.0, 0.0, 0.0);
+ simd_reduce_add_ordered(z, x);
+ //~^ ERROR accumulator of simd_reduce_add_ordered is not a constant
+ simd_reduce_mul_ordered(z, x);
+ //~^ ERROR accumulator of simd_reduce_mul_ordered is not a constant
+}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(slice_patterns)]
-
enum Void {}
fn main() {
// except according to those terms.
#![feature(box_patterns)]
-#![feature(slice_patterns)]
#![feature(box_syntax)]
#![feature(exhaustive_patterns)]
+#![feature(slice_patterns)]
#![deny(unreachable_patterns)]
mod foo {
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// https://github.com/rust-lang/rust/issues/49153
+
+// revisions:rpass1 rpass2
+
+extern "C" {
+ pub static __ImageBase: u8;
+}
+
+pub static FOO: &'static u8 = unsafe { &__ImageBase };
+
+fn main() {}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Regression test for hashing involving canonical variables. In this
+// test -- which has an intensional error -- the type of the value
+// being dropped winds up including a type variable. Canonicalization
+// would then produce a `?0` which -- in turn -- triggered an ICE in
+// hashing.
+
+// revisions:cfail1
+
+fn main() {
+ println!("Hello, world! {}",*thread_rng().choose(&[0, 1, 2, 3]).unwrap());
+ //[cfail1]~^ ERROR cannot find function `thread_rng`
+}
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// https://github.com/rust-lang/rust/issues/49081
+
+// revisions:rpass1 rpass2
+
+pub static A: i32 = 42;
+pub static B: &i32 = &A;
+
+fn main() {}
// let _2: &'21_1rs D;
// ...
// let mut _3: ();
-// let mut _4: [closure@NodeId(22) r:&'21_1rs D];
+// let mut _4: [closure@NodeId(22) r:&'19s D];
// let mut _5: &'21_1rs D;
// bb0: {
// StorageLive(_1);
// resume;
// }
// bb2: {
+// EndRegion('19s);
// StorageDead(_4);
// _0 = ();
// EndRegion('21_1rs);
// drop(_1) -> [return: bb4, unwind: bb1];
// }
// bb3: {
+// EndRegion('19s);
// EndRegion('21_1rs);
// drop(_1) -> bb1;
// }
// END rustc.main.SimplifyCfg-qualify-consts.after.mir
// START rustc.main-{{closure}}.SimplifyCfg-qualify-consts.after.mir
-// fn main::{{closure}}(_1: [closure@NodeId(22) r:&'21_1rs D]) -> i32 {
+// fn main::{{closure}}(_1: [closure@NodeId(22) r:&'19s D]) -> i32 {
// let mut _0: i32;
// let mut _2: i32;
//
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(box_syntax, slice_patterns, advanced_slice_patterns)]
+#![feature(box_syntax)]
+#![feature(slice_patterns)]
fn move_out_from_end() {
let a = [box 1, box 2];
let _ = 0;
let mut b = 0;
let mut _b = 0;
- let mut _ = 0; //~ ERROR expected identifier, found `_`
- //~^ NOTE `_` is a wildcard pattern, not an identifier
- //~| NOTE expected identifier
+ let mut _ = 0; //~ ERROR expected identifier, found reserved identifier `_`
}
}
}
// still recover later
- let bad_syntax = _; //~ ERROR: found `_`
+ let bad_syntax = _; //~ ERROR: expected expression, found reserved identifier `_`
}
// except according to those terms.
fn main() {
- let a = 42._; //~ ERROR unexpected token: `_`
+ let a = 42._; //~ ERROR expected identifier, found reserved identifier `_`
+ //~^ ERROR `{integer}` is a primitive type and therefore doesn't have fields
}
struct TheBackend(Box<TransCrate>);
impl TransCrate for TheBackend {
- fn metadata_loader(&self) -> Box<MetadataLoader> {
+ fn metadata_loader(&self) -> Box<MetadataLoader + Sync> {
self.0.metadata_loader()
}
def_info: None,
allow_internal_unstable: false,
allow_internal_unsafe: false,
+ unstable_feature: None,
});
}
#![crate_type="dylib"]
#![feature(plugin_registrar, rustc_private)]
-#![feature(slice_patterns)]
extern crate syntax;
extern crate syntax_pos;
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+ assert!(r#"☃\backslash"#.contains("\\"));
+}
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(staged_api)]
+#![stable(feature = "unit_test", since = "0.0.0")]
+
+#[unstable(feature = "unstable_macros", issue = "0")]
+#[macro_export]
+macro_rules! unstable_macro{ () => () }
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
-
-
+// ignore-emscripten apparently blows the stack
fn f(x: isize) -> isize {
if x == 1 { return 1; } else { let y: isize = 1 + f(x - 1); return y; }
// Ensure that we can do a destructuring bind of a fixed-size array,
// even when the element type has a destructor.
-
-#![feature(slice_patterns)]
-
struct D { x: u8 }
impl Drop for D { fn drop(&mut self) { } }
// ignore-wasm32-bare compiled with panic=abort by default
-#![feature(generators, generator_trait, untagged_unions, slice_patterns, advanced_slice_patterns)]
+#![feature(generators, generator_trait, untagged_unions)]
+#![feature(slice_patterns)]
use std::cell::{Cell, RefCell};
use std::ops::Generator;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+// ignore-emscripten no i128 support
+
#![feature(i128_type)]
#![deny(const_err)]
// pretty-expanded FIXME #23616
-#![feature(advanced_slice_patterns)]
#![feature(slice_patterns)]
struct Foo(isize, isize, isize, isize);
let Foo(..) = Foo(5, 5, 5, 5);
let Foo(..) = Foo(5, 5, 5, 5);
let Bar{..} = Bar{a: 5, b: 5, c: 5, d: 5};
- //let (..) = (5, 5, 5, 5);
- //let Foo(a, b, ..) = Foo(5, 5, 5, 5);
- //let Foo(.., d) = Foo(5, 5, 5, 5);
- //let (a, b, ..) = (5, 5, 5, 5);
- //let (.., c, d) = (5, 5, 5, 5);
+ let (..) = (5, 5, 5, 5);
+ let Foo(a, b, ..) = Foo(5, 5, 5, 5);
+ let Foo(.., d) = Foo(5, 5, 5, 5);
+ let (a, b, ..) = (5, 5, 5, 5);
+ let (.., c, d) = (5, 5, 5, 5);
let Bar{b: b, ..} = Bar{a: 5, b: 5, c: 5, d: 5};
match [5, 5, 5, 5] {
[..] => { }
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+// ignore-emscripten no i128 support
+
#![feature(intrinsics, i128_type)]
mod rusti {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+// ignore-emscripten fma not implemented in emscripten
+
macro_rules! assert_approx_eq {
($a:expr, $b:expr) => ({
let (a, b) = (&$a, &$b);
// Tests that match expression handles overlapped literal and range
// properly in the presence of guard function.
-#![feature(slice_patterns)]
-
fn val() -> usize { 1 }
static CONST: usize = 1;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
#![feature(slice_patterns)]
fn main() {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
#![feature(slice_patterns)]
fn main() {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
-#![feature(slice_patterns)]
-
fn main() {
let x: (isize, &[isize]) = (2, &[1, 2]);
assert_eq!(match x {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
#![feature(slice_patterns)]
fn main() {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+// ignore-emscripten FIXME(#45351)
+
#![feature(repr_simd, test)]
extern crate test;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(advanced_slice_patterns, slice_patterns)]
+#![feature(slice_patterns)]
fn check(list: &[u8]) {
match list {
// Check that constant ADTs are translated OK, part k of N.
-#![feature(slice_patterns)]
-
enum Bar {
C
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+// ignore-emscripten FIXME(#45351)
+
#![feature(platform_intrinsics, repr_simd)]
extern "platform-intrinsic" {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+// ignore-emscripten FIXME(#45351)
+
#![feature(repr_simd, platform_intrinsics)]
#[repr(C)]
// compile-flags: -Zmir-opt-level=1
-#![feature(slice_patterns)]
-
use std::mem;
#[derive(Copy, Clone)]
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
-#![feature(advanced_slice_patterns)]
#![feature(slice_patterns)]
use std::ops::Add;
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:unstable-macros.rs
+
+#![feature(unstable_macros)]
+
+#[macro_use] extern crate unstable_macros;
+
+#[unstable(feature = "local_unstable", issue = "0")]
+macro_rules! local_unstable { () => () }
+
+fn main() {
+ unstable_macro!();
+ local_unstable!();
+}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
-#![feature(advanced_slice_patterns)]
#![feature(slice_patterns)]
fn match_vecs<'a, T>(l1: &'a [T], l2: &'a [T]) -> &'static str {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+// ignore-emscripten apparently only works in optimized mode
+
const TEST_DATA: [u8; 32 * 1024 * 1024] = [42; 32 * 1024 * 1024];
// Check that the promoted copy of TEST_DATA doesn't
// compile-flags: -C debug_assertions=yes
// ignore-wasm32-bare compiled with panic=abort by default
+// ignore-emscripten dies with an LLVM error
#![feature(i128_type)]
// except according to those terms.
// compile-flags: -C debug_assertions=no
+// ignore-emscripten dies with an LLVM error
#![feature(i128_type)]
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+// ignore-emscripten weird assertion?
#[repr(packed)]
struct Foo {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(slice_patterns)]
#![feature(match_default_bindings)]
+#![feature(slice_patterns)]
fn slice_pat() {
let sl: &[u8] = b"foo";
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+// ignore-emscripten FIXME(#45351) hits an LLVM assert
+
#![feature(repr_simd, platform_intrinsics)]
#[repr(simd)]
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+// ignore-emscripten FIXME(#45351) hits an LLVM assert
+
#![feature(repr_simd, platform_intrinsics, concat_idents)]
#![allow(non_camel_case_types)]
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+// ignore-emscripten FIXME(#45351) hits an LLVM assert
+
#![feature(repr_simd, platform_intrinsics)]
#[repr(simd)]
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// min-llvm-version 5.0
+// ignore-emscripten
+
+// Test that the simd_reduce_{op} intrinsics produce the correct results.
+
+#![feature(repr_simd, platform_intrinsics)]
+#[allow(non_camel_case_types)]
+
+#[repr(simd)]
+#[derive(Copy, Clone)]
+struct i32x4(pub i32, pub i32, pub i32, pub i32);
+
+#[repr(simd)]
+#[derive(Copy, Clone)]
+struct u32x4(pub u32, pub u32, pub u32, pub u32);
+
+#[repr(simd)]
+#[derive(Copy, Clone)]
+struct f32x4(pub f32, pub f32, pub f32, pub f32);
+
+#[repr(simd)]
+#[derive(Copy, Clone)]
+struct b8x4(pub i8, pub i8, pub i8, pub i8);
+
+#[repr(simd)]
+#[derive(Copy, Clone)]
+struct b8x16(
+ pub i8, pub i8, pub i8, pub i8,
+ pub i8, pub i8, pub i8, pub i8,
+ pub i8, pub i8, pub i8, pub i8,
+ pub i8, pub i8, pub i8, pub i8
+);
+
+extern "platform-intrinsic" {
+ fn simd_reduce_add_unordered<T, U>(x: T) -> U;
+ fn simd_reduce_mul_unordered<T, U>(x: T) -> U;
+ fn simd_reduce_add_ordered<T, U>(x: T, acc: U) -> U;
+ fn simd_reduce_mul_ordered<T, U>(x: T, acc: U) -> U;
+ fn simd_reduce_min<T, U>(x: T) -> U;
+ fn simd_reduce_max<T, U>(x: T) -> U;
+ fn simd_reduce_min_nanless<T, U>(x: T) -> U;
+ fn simd_reduce_max_nanless<T, U>(x: T) -> U;
+ fn simd_reduce_and<T, U>(x: T) -> U;
+ fn simd_reduce_or<T, U>(x: T) -> U;
+ fn simd_reduce_xor<T, U>(x: T) -> U;
+ fn simd_reduce_all<T>(x: T) -> bool;
+ fn simd_reduce_any<T>(x: T) -> bool;
+}
+
+fn main() {
+ unsafe {
+ let x = i32x4(1, -2, 3, 4);
+ let r: i32 = simd_reduce_add_unordered(x);
+ assert_eq!(r, 6_i32);
+ let r: i32 = simd_reduce_mul_unordered(x);
+ assert_eq!(r, -24_i32);
+ let r: i32 = simd_reduce_add_ordered(x, -1);
+ assert_eq!(r, 5_i32);
+ let r: i32 = simd_reduce_mul_ordered(x, -1);
+ assert_eq!(r, 24_i32);
+
+ let r: i32 = simd_reduce_min(x);
+ assert_eq!(r, -2_i32);
+ let r: i32 = simd_reduce_max(x);
+ assert_eq!(r, 4_i32);
+
+ let x = i32x4(-1, -1, -1, -1);
+ let r: i32 = simd_reduce_and(x);
+ assert_eq!(r, -1_i32);
+ let r: i32 = simd_reduce_or(x);
+ assert_eq!(r, -1_i32);
+ let r: i32 = simd_reduce_xor(x);
+ assert_eq!(r, 0_i32);
+
+ let x = i32x4(-1, -1, 0, -1);
+ let r: i32 = simd_reduce_and(x);
+ assert_eq!(r, 0_i32);
+ let r: i32 = simd_reduce_or(x);
+ assert_eq!(r, -1_i32);
+ let r: i32 = simd_reduce_xor(x);
+ assert_eq!(r, -1_i32);
+ }
+
+ unsafe {
+ let x = u32x4(1, 2, 3, 4);
+ let r: u32 = simd_reduce_add_unordered(x);
+ assert_eq!(r, 10_u32);
+ let r: u32 = simd_reduce_mul_unordered(x);
+ assert_eq!(r, 24_u32);
+ let r: u32 = simd_reduce_add_ordered(x, 1);
+ assert_eq!(r, 11_u32);
+ let r: u32 = simd_reduce_mul_ordered(x, 2);
+ assert_eq!(r, 48_u32);
+
+ let r: u32 = simd_reduce_min(x);
+ assert_eq!(r, 1_u32);
+ let r: u32 = simd_reduce_max(x);
+ assert_eq!(r, 4_u32);
+
+ let t = u32::max_value();
+ let x = u32x4(t, t, t, t);
+ let r: u32 = simd_reduce_and(x);
+ assert_eq!(r, t);
+ let r: u32 = simd_reduce_or(x);
+ assert_eq!(r, t);
+ let r: u32 = simd_reduce_xor(x);
+ assert_eq!(r, 0_u32);
+
+ let x = u32x4(t, t, 0, t);
+ let r: u32 = simd_reduce_and(x);
+ assert_eq!(r, 0_u32);
+ let r: u32 = simd_reduce_or(x);
+ assert_eq!(r, t);
+ let r: u32 = simd_reduce_xor(x);
+ assert_eq!(r, t);
+ }
+
+ unsafe {
+ let x = f32x4(1., -2., 3., 4.);
+ let r: f32 = simd_reduce_add_unordered(x);
+ assert_eq!(r, 6_f32);
+ let r: f32 = simd_reduce_mul_unordered(x);
+ assert_eq!(r, -24_f32);
+ // FIXME: only works correctly for accumulator, 0:
+ // https://bugs.llvm.org/show_bug.cgi?id=36734
+ let r: f32 = simd_reduce_add_ordered(x, 0.);
+ assert_eq!(r, 6_f32);
+ // FIXME: only works correctly for accumulator, 1:
+ // https://bugs.llvm.org/show_bug.cgi?id=36734
+ let r: f32 = simd_reduce_mul_ordered(x, 1.);
+ assert_eq!(r, -24_f32);
+
+ let r: f32 = simd_reduce_min(x);
+ assert_eq!(r, -2_f32);
+ let r: f32 = simd_reduce_max(x);
+ assert_eq!(r, 4_f32);
+ let r: f32 = simd_reduce_min_nanless(x);
+ assert_eq!(r, -2_f32);
+ let r: f32 = simd_reduce_max_nanless(x);
+ assert_eq!(r, 4_f32);
+ }
+
+ unsafe {
+ let x = b8x4(!0, !0, !0, !0);
+ let r: bool = simd_reduce_all(x);
+ assert_eq!(r, true);
+ let r: bool = simd_reduce_any(x);
+ assert_eq!(r, true);
+
+ let x = b8x4(!0, !0, 0, !0);
+ let r: bool = simd_reduce_all(x);
+ assert_eq!(r, false);
+ let r: bool = simd_reduce_any(x);
+ assert_eq!(r, true);
+
+ let x = b8x4(0, 0, 0, 0);
+ let r: bool = simd_reduce_all(x);
+ assert_eq!(r, false);
+ let r: bool = simd_reduce_any(x);
+ assert_eq!(r, false);
+ }
+}
// pretty-expanded FIXME #23616
-#![feature(advanced_slice_patterns,)]
#![feature(slice_patterns)]
fn f<T,>(_: T,) {}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
-#![feature(slice_patterns)]
-
pub fn main() {
let x = [1, 2, 3];
match x {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
-#![feature(advanced_slice_patterns)]
#![feature(slice_patterns)]
fn a() {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
-#![feature(advanced_slice_patterns)]
#![feature(slice_patterns)]
use std::fmt::Debug;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
-#![feature(advanced_slice_patterns)]
#![feature(slice_patterns)]
fn a() {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
-
#![feature(slice_patterns)]
struct Foo {
// except according to those terms.
#![feature(doc_cfg)]
+#![feature(target_feature, cfg_target_feature)]
// @has doc_cfg/struct.Portable.html
// @!has - '//*[@id="main"]/*[@class="stability"]/*[@class="stab portability"]' ''
fn unix_and_arm_only_function() {}
}
}
+
+// tagging a function with `#[target_feature]` creates a doc(cfg(target_feature)) node for that
+// item as well
+
+// the portability header is different on the module view versus the full view
+// @has doc_cfg/index.html
+// @matches - '//*[@class=" module-item"]//*[@class="stab portability"]' '\Aavx\Z'
+
+// @has doc_cfg/fn.uses_target_feature.html
+// @has - '//*[@id="main"]/*[@class="stability"]/*[@class="stab portability"]' \
+// 'This is supported with target feature avx only.'
+#[target_feature(enable = "avx")]
+pub unsafe fn uses_target_feature() {
+ content::should::be::irrelevant();
+}
+
+// @has doc_cfg/fn.uses_cfg_target_feature.html
+// @has - '//*[@id="main"]/*[@class="stability"]/*[@class="stab portability"]' \
+// 'This is supported with target feature avx only.'
+#[doc(cfg(target_feature = "avx"))]
+pub fn uses_cfg_target_feature() {
+ uses_target_feature();
+}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(advanced_slice_patterns)]
#![feature(box_patterns)]
#![feature(box_syntax)]
#![feature(slice_patterns)]
error[E0506]: cannot assign to `vec[..]` because it is borrowed
- --> $DIR/borrowck-vec-pattern-nesting.rs:21:13
+ --> $DIR/borrowck-vec-pattern-nesting.rs:20:13
|
LL | [box ref _a, _, _] => {
| ------ borrow of `vec[..]` occurs here
| ^^^^^^^^^^^^^^ assignment to borrowed `vec[..]` occurs here
error[E0506]: cannot assign to `vec[..]` because it is borrowed
- --> $DIR/borrowck-vec-pattern-nesting.rs:33:13
+ --> $DIR/borrowck-vec-pattern-nesting.rs:32:13
|
LL | &mut [ref _b..] => {
| ------ borrow of `vec[..]` occurs here
| ^^^^^^^^^^^^^^ assignment to borrowed `vec[..]` occurs here
error[E0508]: cannot move out of type `[std::boxed::Box<isize>]`, a non-copy slice
- --> $DIR/borrowck-vec-pattern-nesting.rs:43:14
+ --> $DIR/borrowck-vec-pattern-nesting.rs:42:14
|
LL | &mut [_a, //~ ERROR cannot move out
| ^-- hint: to prevent move, use `ref _a` or `ref mut _a`
| |_________^ cannot move out of here
error[E0508]: cannot move out of type `[std::boxed::Box<isize>]`, a non-copy slice
- --> $DIR/borrowck-vec-pattern-nesting.rs:56:13
+ --> $DIR/borrowck-vec-pattern-nesting.rs:55:13
|
LL | let a = vec[0]; //~ ERROR cannot move out
| ^^^^^^
| help: consider using a reference instead: `&vec[0]`
error[E0508]: cannot move out of type `[std::boxed::Box<isize>]`, a non-copy slice
- --> $DIR/borrowck-vec-pattern-nesting.rs:64:14
+ --> $DIR/borrowck-vec-pattern-nesting.rs:63:14
|
LL | &mut [ //~ ERROR cannot move out
| ______________^
| hint: to prevent move, use `ref _b` or `ref mut _b`
error[E0508]: cannot move out of type `[std::boxed::Box<isize>]`, a non-copy slice
- --> $DIR/borrowck-vec-pattern-nesting.rs:69:13
+ --> $DIR/borrowck-vec-pattern-nesting.rs:68:13
|
LL | let a = vec[0]; //~ ERROR cannot move out
| ^^^^^^
| help: consider using a reference instead: `&vec[0]`
error[E0508]: cannot move out of type `[std::boxed::Box<isize>]`, a non-copy slice
- --> $DIR/borrowck-vec-pattern-nesting.rs:77:14
+ --> $DIR/borrowck-vec-pattern-nesting.rs:76:14
|
LL | &mut [_a, _b, _c] => {} //~ ERROR cannot move out
| ^--^^--^^--^
| cannot move out of here
error[E0508]: cannot move out of type `[std::boxed::Box<isize>]`, a non-copy slice
- --> $DIR/borrowck-vec-pattern-nesting.rs:81:13
+ --> $DIR/borrowck-vec-pattern-nesting.rs:80:13
|
LL | let a = vec[0]; //~ ERROR cannot move out
| ^^^^^^
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(rustc_attrs)]
+
+trait Foo { }
+
+#[rustc_dump_program_clauses] //~ ERROR Implemented(T: Foo) :-
+impl<T: 'static> Foo for T where T: Iterator<Item = i32> { }
+
+fn main() {
+ println!("hello");
+}
--- /dev/null
+error: Implemented(T: Foo) :- ProjectionEq(<T as std::iter::Iterator>::Item == i32), TypeOutlives(T : 'static), Implemented(T: std::iter::Iterator), Implemented(T: std::marker::Sized).
+ --> $DIR/lower_impl.rs:15:1
+ |
+LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(T: Foo) :-
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
fn main() {
assert!("foo");
+ //~^ ERROR cannot apply unary operator `!`
}
|
LL | assert!("foo");
| ^^^^^^^^^^^^^^^
- |
- = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
error: aborting due to previous error
-error: expected expression, found `_`
+error: expected expression, found reserved identifier `_`
--> $DIR/underscore.rs:18:9
|
LL | _
--> $DIR/E0449.rs:17:1
|
LL | pub impl Bar {} //~ ERROR E0449
- | ^^^ `pub` not needed here
+ | ^^^ `pub` not permitted here because it's implied
|
= note: place qualifiers on individual impl items instead
--> $DIR/E0449.rs:19:1
|
LL | pub impl Foo for Bar { //~ ERROR E0449
- | ^^^ `pub` not needed here
+ | ^^^ `pub` not permitted here because it's implied
error[E0449]: unnecessary visibility qualifier
--> $DIR/E0449.rs:20:5
|
LL | pub fn foo() {} //~ ERROR E0449
- | ^^^ `pub` not needed here
+ | ^^^ `pub` not permitted here because it's implied
error: aborting due to 3 previous errors
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(slice_patterns)]
-
fn main() {
let r = &[1, 2, 3, 4];
match r {
error[E0527]: pattern requires 2 elements but array has 4
- --> $DIR/E0527.rs:16:10
+ --> $DIR/E0527.rs:14:10
|
LL | &[a, b] => {
| ^^^^^^ expected 4 elements
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(slice_patterns)]
-
fn main() {
let r: f32 = 1.0;
match r {
error[E0529]: expected an array or slice, found `f32`
- --> $DIR/E0529.rs:16:9
+ --> $DIR/E0529.rs:14:9
|
LL | [a, b] => {
| ^^^^^^ pattern cannot match with input type `f32`
+++ /dev/null
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// gate-test-advanced_slice_patterns
-
-#![feature(slice_patterns)]
-
-fn main() {
- let x = [ 1, 2, 3, 4, 5 ];
- match x {
- [ xs.., 4, 5 ] => {} //~ ERROR multiple-element slice matches
- [ 1, xs.., 5 ] => {} //~ ERROR multiple-element slice matches
- [ 1, 2, xs.. ] => {} // OK without feature gate
- }
-}
+++ /dev/null
-error[E0658]: multiple-element slice matches anywhere but at the end of a slice (e.g. `[0, ..xs, 0]`) are experimental (see issue #23121)
- --> $DIR/feature-gate-advanced-slice-features.rs:18:9
- |
-LL | [ xs.., 4, 5 ] => {} //~ ERROR multiple-element slice matches
- | ^^^^^^^^^^^^^^
- |
- = help: add #![feature(advanced_slice_patterns)] to the crate attributes to enable
-
-error[E0658]: multiple-element slice matches anywhere but at the end of a slice (e.g. `[0, ..xs, 0]`) are experimental (see issue #23121)
- --> $DIR/feature-gate-advanced-slice-features.rs:19:9
- |
-LL | [ 1, xs.., 5 ] => {} //~ ERROR multiple-element slice matches
- | ^^^^^^^^^^^^^^
- |
- = help: add #![feature(advanced_slice_patterns)] to the crate attributes to enable
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0658`.
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// Test that slice pattern syntax is gated by `slice_patterns` feature gate
+// Test that slice pattern syntax with `..` is gated by `slice_patterns` feature gate
fn main() {
let x = [1, 2, 3, 4, 5];
match x {
- [1, 2, xs..] => {} //~ ERROR slice pattern syntax is experimental
+ [1, 2, ..] => {} //~ ERROR syntax for subslices in slice patterns is not yet stabilized
+ [1, .., 5] => {} //~ ERROR syntax for subslices in slice patterns is not yet stabilized
+ [.., 4, 5] => {} //~ ERROR syntax for subslices in slice patterns is not yet stabilized
+ }
+
+ let x = [ 1, 2, 3, 4, 5 ];
+ match x {
+ [ xs.., 4, 5 ] => {} //~ ERROR syntax for subslices in slice patterns is not yet stabilized
+ [ 1, xs.., 5 ] => {} //~ ERROR syntax for subslices in slice patterns is not yet stabilized
+ [ 1, 2, xs.. ] => {} //~ ERROR syntax for subslices in slice patterns is not yet stabilized
}
}
-error[E0658]: slice pattern syntax is experimental (see issue #23121)
- --> $DIR/feature-gate-slice-patterns.rs:16:9
+error[E0658]: syntax for subslices in slice patterns is not yet stabilized (see issue #23121)
+ --> $DIR/feature-gate-slice-patterns.rs:16:16
|
-LL | [1, 2, xs..] => {} //~ ERROR slice pattern syntax is experimental
- | ^^^^^^^^^^^^
+LL | [1, 2, ..] => {} //~ ERROR syntax for subslices in slice patterns is not yet stabilized
+ | ^^
|
= help: add #![feature(slice_patterns)] to the crate attributes to enable
-error: aborting due to previous error
+error[E0658]: syntax for subslices in slice patterns is not yet stabilized (see issue #23121)
+ --> $DIR/feature-gate-slice-patterns.rs:17:13
+ |
+LL | [1, .., 5] => {} //~ ERROR syntax for subslices in slice patterns is not yet stabilized
+ | ^^
+ |
+ = help: add #![feature(slice_patterns)] to the crate attributes to enable
+
+error[E0658]: syntax for subslices in slice patterns is not yet stabilized (see issue #23121)
+ --> $DIR/feature-gate-slice-patterns.rs:18:10
+ |
+LL | [.., 4, 5] => {} //~ ERROR syntax for subslices in slice patterns is not yet stabilized
+ | ^^
+ |
+ = help: add #![feature(slice_patterns)] to the crate attributes to enable
+
+error[E0658]: syntax for subslices in slice patterns is not yet stabilized (see issue #23121)
+ --> $DIR/feature-gate-slice-patterns.rs:23:11
+ |
+LL | [ xs.., 4, 5 ] => {} //~ ERROR syntax for subslices in slice patterns is not yet stabilized
+ | ^^
+ |
+ = help: add #![feature(slice_patterns)] to the crate attributes to enable
+
+error[E0658]: syntax for subslices in slice patterns is not yet stabilized (see issue #23121)
+ --> $DIR/feature-gate-slice-patterns.rs:24:14
+ |
+LL | [ 1, xs.., 5 ] => {} //~ ERROR syntax for subslices in slice patterns is not yet stabilized
+ | ^^
+ |
+ = help: add #![feature(slice_patterns)] to the crate attributes to enable
+
+error[E0658]: syntax for subslices in slice patterns is not yet stabilized (see issue #23121)
+ --> $DIR/feature-gate-slice-patterns.rs:25:17
+ |
+LL | [ 1, 2, xs.. ] => {} //~ ERROR syntax for subslices in slice patterns is not yet stabilized
+ | ^^
+ |
+ = help: add #![feature(slice_patterns)] to the crate attributes to enable
+
+error: aborting due to 6 previous errors
For more information about this error, try `rustc --explain E0658`.
-error[E0277]: the trait bound `No: Foo` is not satisfied in `[generator@$DIR/auto-trait-regions.rs:35:15: 39:6 x:&&'static OnlyFooIfStaticRef for<'r> {&'r OnlyFooIfStaticRef, ()}]`
+error[E0277]: the trait bound `No: Foo` is not satisfied in `[generator@$DIR/auto-trait-regions.rs:35:15: 39:6 x:&&OnlyFooIfStaticRef for<'r> {&'r OnlyFooIfStaticRef, ()}]`
--> $DIR/auto-trait-regions.rs:40:5
|
LL | assert_foo(gen); //~ ERROR the trait bound `No: Foo` is not satisfied
- | ^^^^^^^^^^ within `[generator@$DIR/auto-trait-regions.rs:35:15: 39:6 x:&&'static OnlyFooIfStaticRef for<'r> {&'r OnlyFooIfStaticRef, ()}]`, the trait `Foo` is not implemented for `No`
+ | ^^^^^^^^^^ within `[generator@$DIR/auto-trait-regions.rs:35:15: 39:6 x:&&OnlyFooIfStaticRef for<'r> {&'r OnlyFooIfStaticRef, ()}]`, the trait `Foo` is not implemented for `No`
|
= help: the following implementations were found:
<No as Foo>
= note: required because it appears within the type `OnlyFooIfStaticRef`
= note: required because it appears within the type `&OnlyFooIfStaticRef`
= note: required because it appears within the type `for<'r> {&'r OnlyFooIfStaticRef, ()}`
- = note: required because it appears within the type `[generator@$DIR/auto-trait-regions.rs:35:15: 39:6 x:&&'static OnlyFooIfStaticRef for<'r> {&'r OnlyFooIfStaticRef, ()}]`
+ = note: required because it appears within the type `[generator@$DIR/auto-trait-regions.rs:35:15: 39:6 x:&&OnlyFooIfStaticRef for<'r> {&'r OnlyFooIfStaticRef, ()}]`
note: required by `assert_foo`
--> $DIR/auto-trait-regions.rs:30:1
|
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// In contrast to `region-escape-via-bound-invariant`, in this case we
+// *can* return a value of type `&'x u32`, even though `'x` does not
+// appear in the bounds. This is because `&` is contravariant, and so
+// we are *actually* returning a `&'y u32`.
+//
+// See https://github.com/rust-lang/rust/issues/46541 for more details.
+
+// run-pass
+
+#![allow(dead_code)]
+#![feature(conservative_impl_trait)]
+#![feature(in_band_lifetimes)]
+#![feature(nll)]
+
+fn foo(x: &'x u32) -> impl Fn() -> &'y u32
+where 'x: 'y
+{
+ move || x
+}
+
+fn main() { }
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// In contrast to `region-escape-via-bound-invariant`, in this case we
+// *can* return a value of type `&'x u32`, even though `'x` does not
+// appear in the bounds. This is because `&` is contravariant, and so
+// we are *actually* returning a `&'y u32`.
+//
+// See https://github.com/rust-lang/rust/issues/46541 for more details.
+
+// run-pass
+
+#![allow(dead_code)]
+#![feature(conservative_impl_trait)]
+#![feature(in_band_lifetimes)]
+#![feature(nll)]
+
+trait Trait<'a> { }
+
+impl Trait<'b> for &'a u32 { }
+
+fn foo(x: &'x u32) -> impl Trait<'y>
+where 'x: 'y
+{
+ x
+}
+
+fn main() { }
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test that we do not allow the region `'x` to escape in the impl
+// trait **even though** `'y` escapes, which outlives `'x`.
+//
+// See https://github.com/rust-lang/rust/issues/46541 for more details.
+
+#![allow(dead_code)]
+#![feature(conservative_impl_trait)]
+#![feature(in_band_lifetimes)]
+#![feature(nll)]
+
+use std::cell::Cell;
+
+trait Trait<'a> { }
+
+impl Trait<'b> for Cell<&'a u32> { }
+
+fn foo(x: Cell<&'x u32>) -> impl Trait<'y>
+ //~^ ERROR hidden type for `impl Trait` captures lifetime that does not appear in bounds [E0909]
+where 'x: 'y
+{
+ x
+}
+
+fn main() { }
--- /dev/null
+error[E0909]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
+ --> $DIR/region-escape-via-bound.rs:27:29
+ |
+LL | fn foo(x: Cell<&'x u32>) -> impl Trait<'y>
+ | ^^^^^^^^^^^^^^
+ |
+note: hidden type `std::cell::Cell<&'x u32>` captures the lifetime 'x as defined on the function body at 27:1
+ --> $DIR/region-escape-via-bound.rs:27:1
+ |
+LL | / fn foo(x: Cell<&'x u32>) -> impl Trait<'y>
+LL | | //~^ ERROR hidden type for `impl Trait` captures lifetime that does not appear in bounds [E0909]
+LL | | where 'x: 'y
+LL | | {
+LL | | x
+LL | | }
+ | |_^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0909`.
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![allow(unused_variables)]; //~ ERROR expected item, found `;`
+fn main() {}
--- /dev/null
+error: expected item, found `;`
+ --> $DIR/issue-49040.rs:11:28
+ |
+LL | #![allow(unused_variables)]; //~ ERROR expected item, found `;`
+ | ^ help: consider removing this semicolon
+
+error: aborting due to previous error
+
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Check that unknown attribute error is shown even if there are unresolved macros.
+
+#[marco_use] // typo
+//~^ ERROR The attribute `marco_use` is currently unknown to the compiler
+mod foo {
+ macro_rules! bar {
+ () => ();
+ }
+}
+
+fn main() {
+ bar!();
+ //~^ ERROR cannot find macro `bar!`
+}
--- /dev/null
+error: cannot find macro `bar!` in this scope
+ --> $DIR/issue-49074.rs:22:4
+ |
+LL | bar!();
+ | ^^^
+ |
+ = help: have you added the `#[macro_use]` on the module/import?
+
+error[E0658]: The attribute `marco_use` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+ --> $DIR/issue-49074.rs:13:1
+ |
+LL | #[marco_use] // typo
+ | ^^^^^^^^^^^^
+ |
+ = help: add #![feature(custom_attribute)] to the crate attributes to enable
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(slice_patterns)]
-
struct Foo {
}
error[E0308]: mismatched types
- --> $DIR/issue-38371.rs:16:8
+ --> $DIR/issue-38371.rs:14:8
|
LL | fn foo(&foo: Foo) { //~ ERROR mismatched types
| ^^^^ expected struct `Foo`, found reference
= help: did you mean `foo: &Foo`?
error[E0308]: mismatched types
- --> $DIR/issue-38371.rs:30:9
+ --> $DIR/issue-38371.rs:28:9
|
LL | fn agh(&&bar: &u32) { //~ ERROR mismatched types
| ^^^^ expected u32, found reference
= help: did you mean `bar: &u32`?
error[E0308]: mismatched types
- --> $DIR/issue-38371.rs:33:8
+ --> $DIR/issue-38371.rs:31:8
|
LL | fn bgh(&&bar: u32) { //~ ERROR mismatched types
| ^^^^^ expected u32, found reference
found type `&_`
error[E0529]: expected an array or slice, found `u32`
- --> $DIR/issue-38371.rs:36:9
+ --> $DIR/issue-38371.rs:34:9
|
LL | fn ugh(&[bar]: &u32) { //~ ERROR expected an array or slice
| ^^^^^ pattern cannot match with input type `u32`
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(advanced_slice_patterns)]
#![feature(slice_patterns)]
struct Foo {
error[E0004]: non-exhaustive patterns: `Foo { first: false, second: Some([_, _, _, _]) }` not covered
- --> $DIR/non-exhaustive-pattern-witness.rs:20:11
+ --> $DIR/non-exhaustive-pattern-witness.rs:19:11
|
LL | match (Foo { first: true, second: None }) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `Foo { first: false, second: Some([_, _, _, _]) }` not covered
error[E0004]: non-exhaustive patterns: `Red` not covered
- --> $DIR/non-exhaustive-pattern-witness.rs:36:11
+ --> $DIR/non-exhaustive-pattern-witness.rs:35:11
|
LL | match Color::Red {
| ^^^^^^^^^^ pattern `Red` not covered
error[E0004]: non-exhaustive patterns: `East`, `South` and `West` not covered
- --> $DIR/non-exhaustive-pattern-witness.rs:48:11
+ --> $DIR/non-exhaustive-pattern-witness.rs:47:11
|
LL | match Direction::North {
| ^^^^^^^^^^^^^^^^ patterns `East`, `South` and `West` not covered
error[E0004]: non-exhaustive patterns: `Second`, `Third`, `Fourth` and 8 more not covered
- --> $DIR/non-exhaustive-pattern-witness.rs:59:11
+ --> $DIR/non-exhaustive-pattern-witness.rs:58:11
|
LL | match ExcessiveEnum::First {
| ^^^^^^^^^^^^^^^^^^^^ patterns `Second`, `Third`, `Fourth` and 8 more not covered
error[E0004]: non-exhaustive patterns: `CustomRGBA { a: true, .. }` not covered
- --> $DIR/non-exhaustive-pattern-witness.rs:67:11
+ --> $DIR/non-exhaustive-pattern-witness.rs:66:11
|
LL | match Color::Red {
| ^^^^^^^^^^ pattern `CustomRGBA { a: true, .. }` not covered
error[E0004]: non-exhaustive patterns: `[Second(true), Second(false)]` not covered
- --> $DIR/non-exhaustive-pattern-witness.rs:83:11
+ --> $DIR/non-exhaustive-pattern-witness.rs:82:11
|
LL | match *x {
| ^^ pattern `[Second(true), Second(false)]` not covered
error[E0004]: non-exhaustive patterns: `((), false)` not covered
- --> $DIR/non-exhaustive-pattern-witness.rs:96:11
+ --> $DIR/non-exhaustive-pattern-witness.rs:95:11
|
LL | match ((), false) {
| ^^^^^^^^^^^ pattern `((), false)` not covered
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(slice_patterns)]
-
// NB: this test was introduced in #23121 and will have to change when default match binding modes
// stabilizes.
+#![feature(slice_patterns)]
+
fn slice_pat(x: &[u8]) {
// OLD!
match x {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(slice_patterns)]
#![feature(match_default_bindings)]
+#![feature(slice_patterns)]
pub fn main() {
let sl: &[u8] = b"foo";
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+ let v = vec![0, 1, 2, 3];
+
+ for (i, n) in &v.iter().enumerate() {
+ //~^ ERROR the trait bound
+ println!("{}", i);
+ }
+}
--- /dev/null
+error[E0277]: the trait bound `&std::iter::Enumerate<std::slice::Iter<'_, {integer}>>: std::iter::Iterator` is not satisfied
+ --> $DIR/suggest-remove-refs-1.rs:14:19
+ |
+LL | for (i, n) in &v.iter().enumerate() {
+ | -^^^^^^^^^^^^^^^^^^^^
+ | |
+ | `&std::iter::Enumerate<std::slice::Iter<'_, {integer}>>` is not an iterator; maybe try calling `.iter()` or a similar method
+ | help: consider removing 1 leading `&`-references
+ |
+ = help: the trait `std::iter::Iterator` is not implemented for `&std::iter::Enumerate<std::slice::Iter<'_, {integer}>>`
+ = note: required by `std::iter::IntoIterator::into_iter`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+ let v = vec![0, 1, 2, 3];
+
+ for (i, n) in & & & & &v.iter().enumerate() {
+ //~^ ERROR the trait bound
+ println!("{}", i);
+ }
+}
--- /dev/null
+error[E0277]: the trait bound `&&&&&std::iter::Enumerate<std::slice::Iter<'_, {integer}>>: std::iter::Iterator` is not satisfied
+ --> $DIR/suggest-remove-refs-2.rs:14:19
+ |
+LL | for (i, n) in & & & & &v.iter().enumerate() {
+ | ---------^^^^^^^^^^^^^^^^^^^^
+ | |
+ | `&&&&&std::iter::Enumerate<std::slice::Iter<'_, {integer}>>` is not an iterator; maybe try calling `.iter()` or a similar method
+ | help: consider removing 5 leading `&`-references
+ |
+ = help: the trait `std::iter::Iterator` is not implemented for `&&&&&std::iter::Enumerate<std::slice::Iter<'_, {integer}>>`
+ = note: required by `std::iter::IntoIterator::into_iter`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+ let v = vec![0, 1, 2, 3];
+
+ for (i, n) in & & &
+ & &v
+ .iter()
+ .enumerate() {
+ //~^^^^ ERROR the trait bound
+ println!("{}", i);
+ }
+}
--- /dev/null
+error[E0277]: the trait bound `&&&&&std::iter::Enumerate<std::slice::Iter<'_, {integer}>>: std::iter::Iterator` is not satisfied
+ --> $DIR/suggest-remove-refs-3.rs:14:19
+ |
+LL | for (i, n) in & & &
+ | ___________________^
+ | |___________________|
+ | ||
+LL | || & &v
+ | ||___________- help: consider removing 5 leading `&`-references
+LL | | .iter()
+LL | | .enumerate() {
+ | |_____________________^ `&&&&&std::iter::Enumerate<std::slice::Iter<'_, {integer}>>` is not an iterator; maybe try calling `.iter()` or a similar method
+ |
+ = help: the trait `std::iter::Iterator` is not implemented for `&&&&&std::iter::Enumerate<std::slice::Iter<'_, {integer}>>`
+ = note: required by `std::iter::IntoIterator::into_iter`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// `const`s shouldn't suggest `.into()`
+
+const TEN: u8 = 10;
+const TWELVE: u16 = TEN + 2;
+//~^ ERROR mismatched types [E0308]
+
+fn main() {
+ const TEN: u8 = 10;
+ const ALSO_TEN: u16 = TEN;
+ //~^ ERROR mismatched types [E0308]
+}
--- /dev/null
+error[E0308]: mismatched types
+ --> $DIR/const-type-mismatch.rs:14:21
+ |
+LL | const TWELVE: u16 = TEN + 2;
+ | ^^^^^^^ expected u16, found u8
+
+error[E0308]: mismatched types
+ --> $DIR/const-type-mismatch.rs:19:27
+ |
+LL | const ALSO_TEN: u16 = TEN;
+ | ^^^ expected u16, found u8
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+macro_rules! identity {
+ ($i: ident) => (
+ $i
+ )
+}
+
+fn main() {
+ let identity!(_) = 10; //~ ERROR no rules expected the token `_`
+}
--- /dev/null
+error: no rules expected the token `_`
+ --> $DIR/underscore-ident-matcher.rs:18:19
+ |
+LL | let identity!(_) = 10; //~ ERROR no rules expected the token `_`
+ | ^
+
+error: aborting due to previous error
+
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Check that the `'_` in `dyn Trait + '_` acts like ordinary elision,
+// and not like an object lifetime default.
+//
+// cc #48468
+
+#![feature(dyn_trait)]
+#![feature(underscore_lifetimes)]
+
+fn a<T>(items: &[T]) -> Box<dyn Iterator<Item=&T>> {
+ // ^^^^^^^^^^^^^^^^^^^^^ bound *here* defaults to `'static`
+ Box::new(items.iter()) //~ ERROR cannot infer an appropriate lifetime
+}
+
+fn b<T>(items: &[T]) -> Box<dyn Iterator<Item=&T> + '_> {
+ Box::new(items.iter()) // OK, equivalent to c
+}
+
+fn c<'a, T>(items: &'a [T]) -> Box<dyn Iterator<Item=&'a T> + 'a> {
+ Box::new(items.iter()) // OK, equivalent to b
+}
+
+fn main() { }
--- /dev/null
+error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
+ --> $DIR/dyn-trait-underscore.rs:21:20
+ |
+LL | Box::new(items.iter()) //~ ERROR cannot infer an appropriate lifetime
+ | ^^^^
+ |
+note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the function body at 19:1...
+ --> $DIR/dyn-trait-underscore.rs:19:1
+ |
+LL | / fn a<T>(items: &[T]) -> Box<dyn Iterator<Item=&T>> {
+LL | | // ^^^^^^^^^^^^^^^^^^^^^ bound *here* defaults to `'static`
+LL | | Box::new(items.iter()) //~ ERROR cannot infer an appropriate lifetime
+LL | | }
+ | |_^
+note: ...so that reference does not outlive borrowed content
+ --> $DIR/dyn-trait-underscore.rs:21:14
+ |
+LL | Box::new(items.iter()) //~ ERROR cannot infer an appropriate lifetime
+ | ^^^^^
+ = note: but, the lifetime must be valid for the static lifetime...
+ = note: ...so that the expression is assignable:
+ expected std::boxed::Box<std::iter::Iterator<Item=&T> + 'static>
+ found std::boxed::Box<std::iter::Iterator<Item=&T>>
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0495`.
-Subproject commit 5f83bb4044f32b60d06717c609610f67411fc671
+Subproject commit d10ec661b06420654bbc4ed0ccd32295698aa1dc
-Subproject commit d5e233a720495c52af25d8f6dcc9e55e1193beb9
+Subproject commit 4edd140e57cce900fa930e1439bab469f5bbce46
-Subproject commit 61833b9aeab8bf8f0c0c0e42b7c96b6eceb37d0d
+Subproject commit d4712ca37500f26bbcbf97edcb27820717f769f7
-Subproject commit b6c52443424977bd92cf7ed127f7771fe9c285da
+Subproject commit 567fb6d74cca9ccbfae2440c688035400b51e3c6
-Subproject commit 346238f49740d6c98102a6a59811b1625c73a9d7
+Subproject commit 87180d9065e7c8070c0ba46eb48ddf8779ef89ac