[submodule "src/binaryen"]
path = src/binaryen
url = https://github.com/alexcrichton/binaryen.git
+[submodule "src/doc/rust-by-example"]
+ path = src/doc/rust-by-example
+ url = https://github.com/rust-lang/rust-by-example
if: branch = auto
- env: IMAGE=dist-armv7-linux DEPLOY=1
if: branch = auto
- - env: IMAGE=dist-i586-gnu-i686-musl DEPLOY=1
+ - env: IMAGE=dist-i586-gnu-i586-i686-musl DEPLOY=1
if: branch = auto
- env: IMAGE=dist-i686-freebsd DEPLOY=1
if: branch = auto
Cargo
-----
-- [Cargo now supports alternative registries][cargo/4506]
- [Cargo now supports uninstallation of multiple packages][cargo/4561]
eg. `cargo uninstall foo bar` uninstalls `foo` and `bar`.
- [Added unit test checking to `cargo check`][cargo/4592]
----
- [Releases now ship with the Cargo book documentation.][45692]
- [rustdoc now prints rendering warnings on every run.][45324]
-- [Release tarballs now come with rustfmt][45903]
Compatibility Notes
-------------------
[45852]: https://github.com/rust-lang/rust/issues/45852
[45853]: https://github.com/rust-lang/rust/pull/45853
[45887]: https://github.com/rust-lang/rust/pull/45887
-[45903]: https://github.com/rust-lang/rust/pull/45903
[45920]: https://github.com/rust-lang/rust/pull/45920
-[cargo/4506]: https://github.com/rust-lang/cargo/pull/4506
[cargo/4561]: https://github.com/rust-lang/cargo/pull/4561
[cargo/4592]: https://github.com/rust-lang/cargo/pull/4592
[cargo/4637]: https://github.com/rust-lang/cargo/pull/4637
a warning.
- [From the pound escape, lines consisting of multiple `#`s are
now visible][41785]
-- [It is an error to reexport private enum variants][42460]. This is
+- [It is an error to re-export private enum variants][42460]. This is
known to break a number of crates that depend on an older version of
mustache.
- [On Windows, if `VCINSTALLDIR` is set incorrectly, `rustc` will try
-------
* [Fix empty implementation section on some module pages](https://github.com/rust-lang/rust/pull/34536)
-* [Fix inlined renamed reexports in import lists](https://github.com/rust-lang/rust/pull/34479)
+* [Fix inlined renamed re-exports in import lists](https://github.com/rust-lang/rust/pull/34479)
* [Fix search result layout for enum variants and struct fields](https://github.com/rust-lang/rust/pull/34477)
* [Fix issues with source links to external crates](https://github.com/rust-lang/rust/pull/34387)
-* [Fix redirect pages for renamed reexports](https://github.com/rust-lang/rust/pull/34245)
+* [Fix redirect pages for renamed re-exports](https://github.com/rust-lang/rust/pull/34245)
Tooling
-------
* std: The `vec` module has been renamed to `slice`.
* std: A new vector type, `Vec<T>`, has been added in preparation for DST.
This will become the only growable vector in the future.
- * std: `std::io` now has more public-reexports. Types such as `BufferedReader`
+ * std: `std::io` now has more public re-exports. Types such as `BufferedReader`
are now found at `std::io::BufferedReader` instead of
`std::io::buffered::BufferedReader`.
* std: `print` and `println` are no longer in the prelude, the `print!` and
* render standalone markdown files.
* the --test flag tests all code blocks by default.
* exported macros are displayed.
- * reexported types have their documentation inlined at the location of the
- first reexport.
+ * re-exported types have their documentation inlined at the location of the
+ first re-export.
* search works across crates that have been rendered to the same output
directory.
incl. `any`, `all`. removed.
* std: The `finalize` method of `Drop` renamed to `drop`.
* std: The `drop` method now takes `&mut self` instead of `&self`.
- * std: The prelude no longer reexports any modules, only types and traits.
+ * std: The prelude no longer re-exports any modules, only types and traits.
* std: Prelude additions: `print`, `println`, `FromStr`, `ApproxEq`, `Equiv`,
`Iterator`, `IteratorUtil`, many numeric traits, many tuple traits.
* std: New numeric traits: `Fractional`, `Real`, `RealExt`, `Integer`, `Ratio`,
version = "0.0.0"
dependencies = [
"core 0.0.0",
- "rand 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)",
"std_unicode 0.0.0",
]
"alloc 0.0.0",
"alloc_system 0.0.0",
"build_helper 0.1.0",
- "cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
"core 0.0.0",
"libc 0.0.0",
]
[[package]]
name = "atty"
-version = "0.2.3"
+version = "0.2.6"
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.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
"termion 1.5.1 (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]]
name = "backtrace"
-version = "0.3.4"
+version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"backtrace-sys 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)",
"cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-demangle 0.1.5 (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.1.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
version = "0.0.0"
dependencies = [
"build_helper 0.1.0",
- "cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
"cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
- "filetime 0.1.14 (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)",
"lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
- "num_cpus 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
"toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
name = "build-manifest"
version = "0.1.0"
dependencies = [
- "serde 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
"toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
name = "build_helper"
version = "0.1.0"
dependencies = [
- "filetime 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
+ "filetime 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
[[package]]
name = "cargo"
-version = "0.25.0"
+version = "0.26.0"
dependencies = [
- "atty 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "atty 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
"bufstream 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
"cargotest 0.1.0",
"core-foundation 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "crates-io 0.14.0",
- "crossbeam 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "crates-io 0.15.0",
+ "crossbeam 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"crypto-hash 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "curl 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "docopt 0.8.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.4.3 (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.14 (registry+https://github.com/rust-lang/crates.io-index)",
+ "filetime 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
"flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "fs2 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "git2 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "fs2 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "git2 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)",
"git2-curl 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
"hamcrest 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "hex 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "hex 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"home 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "ignore 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "jobserver 0.1.8 (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.34 (registry+https://github.com/rust-lang/crates.io-index)",
- "libgit2-sys 0.6.18 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "ignore 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "jobserver 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libgit2-sys 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "num_cpus 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "psapi-sys 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "same-file 0.1.3 (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.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.25 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.25 (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.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_ignored 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
"shell-escape 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
"tar 0.4.14 (registry+https://github.com/rust-lang/crates.io-index)",
"tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
"termcolor 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
"url 1.6.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.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "serde 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
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.25 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "cargotest"
version = "0.1.0"
dependencies = [
- "cargo 0.25.0",
- "filetime 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cargo 0.26.0",
+ "filetime 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
"flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "git2 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "git2 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)",
"hamcrest 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"hex 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
"tar 0.4.14 (registry+https://github.com/rust-lang/crates.io-index)",
"url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "cc"
-version = "1.0.3"
+version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
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)",
- "atty 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "atty 0.2.6 (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)",
"textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
"compiletest_rs 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"duct 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "regex 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
"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.1 (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.25 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.27 (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.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
version = "0.1.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "compiler_builtins"
version = "0.0.0"
dependencies = [
- "cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
"core 0.0.0",
]
dependencies = [
"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)",
- "filetime 0.1.14 (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.34 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "regex 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
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.14 (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.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.36 (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)",
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"core-foundation-sys 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "crates-io"
-version = "0.14.0"
+version = "0.15.0"
dependencies = [
- "curl 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "curl 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
"failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
"url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "crossbeam"
-version = "0.2.10"
+version = "0.2.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "crossbeam"
-version = "0.3.0"
+version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
[[package]]
name = "curl"
-version = "0.4.8"
+version = "0.4.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "curl-sys 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "curl-sys 0.4.1 (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.36 (registry+https://github.com/rust-lang/crates.io-index)",
"openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "openssl-sys 0.9.23 (registry+https://github.com/rust-lang/crates.io-index)",
- "socket2 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "openssl-sys 0.9.24 (registry+https://github.com/rust-lang/crates.io-index)",
+ "schannel 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "socket2 0.3.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 = "curl-sys"
-version = "0.3.15"
+version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
"libz-sys 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
- "openssl-sys 0.9.23 (registry+https://github.com/rust-lang/crates.io-index)",
+ "openssl-sys 0.9.24 (registry+https://github.com/rust-lang/crates.io-index)",
"pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"vcpkg 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "dbghelp-sys"
-version = "0.2.0"
-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)",
+ "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
[[package]]
name = "docopt"
-version = "0.8.1"
+version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "regex 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.25 (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.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
"strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
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.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "backtrace 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "backtrace 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "backtrace 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "backtrace 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "backtrace 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "backtrace 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
"failure_derive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "filetime"
-version = "0.1.14"
+version = "0.1.15"
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.34 (registry+https://github.com/rust-lang/crates.io-index)",
- "redox_syscall 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
+ "redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
"miniz-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "fs2"
-version = "0.4.2"
+version = "0.4.3"
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.34 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "fuchsia-zircon"
-version = "0.3.2"
+version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "fuchsia-zircon-sys 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "fuchsia-zircon-sys"
-version = "0.3.2"
+version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
[[package]]
name = "git2"
-version = "0.6.10"
+version = "0.6.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
- "libgit2-sys 0.6.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libgit2-sys 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)",
"openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "openssl-sys 0.9.23 (registry+https://github.com/rust-lang/crates.io-index)",
+ "openssl-sys 0.9.24 (registry+https://github.com/rust-lang/crates.io-index)",
"url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "curl 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "git2 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "curl 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "git2 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
"fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "regex 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"pest 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"quick-error 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "regex 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
+[[package]]
+name = "hex"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
[[package]]
name = "home"
version = "0.3.0"
[[package]]
name = "html-diff"
-version = "0.0.5"
+version = "0.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"kuchiki 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
[[package]]
name = "ignore"
-version = "0.2.2"
+version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "crossbeam 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "crossbeam 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)",
"globset 0.2.1 (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)",
- "memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "regex 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "same-file 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "walkdir 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "walkdir 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
"flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rayon 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
"tar 0.4.14 (registry+https://github.com/rust-lang/crates.io-index)",
"walkdir 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "xz2 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "xz2 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
[[package]]
name = "jobserver"
-version = "0.1.8"
+version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
- "rand 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
dependencies = [
"futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"enum_primitive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
"url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
"url_serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "libc"
-version = "0.2.34"
+version = "0.2.36"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "libgit2-sys"
-version = "0.6.18"
+version = "0.6.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
"cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
- "curl-sys 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "curl-sys 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
"libssh2-sys 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
"libz-sys 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
- "openssl-sys 0.9.23 (registry+https://github.com/rust-lang/crates.io-index)",
+ "openssl-sys 0.9.24 (registry+https://github.com/rust-lang/crates.io-index)",
"pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
]
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
"libz-sys 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
- "openssl-sys 0.9.23 (registry+https://github.com/rust-lang/crates.io-index)",
+ "openssl-sys 0.9.24 (registry+https://github.com/rust-lang/crates.io-index)",
"pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
]
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
"pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"vcpkg 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "filetime 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "filetime 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
"pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
]
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"open 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"pulldown-cmark 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "regex 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
"tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
"toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "memchr"
-version = "1.0.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
"cargo_metadata 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"compiletest_rs 0.3.3 (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.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
dependencies = [
"cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.36 (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)",
]
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.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
"void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
dependencies = [
"num-integer 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
"num-traits 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)",
- "rand 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "num_cpus"
-version = "1.7.0"
+version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
"bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
"foreign-types 0.3.2 (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.34 (registry+https://github.com/rust-lang/crates.io-index)",
- "openssl-sys 0.9.23 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
+ "openssl-sys 0.9.24 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
[[package]]
name = "openssl-sys"
-version = "0.9.23"
+version = "0.9.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
"pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"vcpkg 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
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.34 (registry+https://github.com/rust-lang/crates.io-index)",
- "rand 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)",
"smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
- "rand 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "profiler_builtins"
version = "0.0.0"
dependencies = [
- "cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
"core 0.0.0",
]
-[[package]]
-name = "psapi-sys"
-version = "0.1.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 = "pulldown-cmark"
version = "0.0.15"
[[package]]
name = "rand"
-version = "0.3.19"
+version = "0.3.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "fuchsia-zircon 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
dependencies = [
"coco 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
- "num_cpus 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rand 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "redox_syscall"
-version = "0.1.32"
+version = "0.1.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "redox_syscall 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)",
+ "redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
[[package]]
name = "regex"
-version = "0.2.3"
+version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
"memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex-syntax 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
"utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "regex-syntax"
-version = "0.4.1"
+version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "rls"
version = "0.124.0"
dependencies = [
- "cargo 0.25.0",
+ "cargo 0.26.0",
"env_logger 0.4.3 (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)",
"rls-rustc 0.1.1 (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.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustfmt-nightly 0.3.4",
- "serde 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustfmt-nightly 0.3.6",
+ "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
"url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
dependencies = [
"rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
version = "0.0.0"
dependencies = [
"arena 0.0.0",
- "backtrace 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "backtrace 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
"bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"fmt_macros 0.0.0",
"graphviz 0.0.0",
- "jobserver 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "jobserver 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc_apfloat 0.0.0",
"rustc_back 0.0.0",
"rustc_const_math 0.0.0",
"syntax_pos 0.0.0",
]
+[[package]]
+name = "rustc-ap-rustc_cratesio_shim"
+version = "12.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)",
+ "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "rustc-ap-rustc_data_structures"
+version = "12.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)",
+ "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.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-serialize 12.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 = "12.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "rustc-ap-rustc_data_structures 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-serialize 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-syntax_pos 12.0.0 (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 = "rustc-ap-serialize"
+version = "12.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "rustc-ap-syntax"
+version = "12.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 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_data_structures 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_errors 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-serialize 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-syntax_pos 12.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-syntax_pos"
+version = "12.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "rustc-ap-rustc_data_structures 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-serialize 12.0.0 (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 = "rustc-demangle"
version = "0.1.5"
name = "rustc_back"
version = "0.0.0"
dependencies = [
- "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
- "rand 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)",
"serialize 0.0.0",
"syntax 0.0.0",
]
name = "rustc_binaryen"
version = "0.0.0"
dependencies = [
- "cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
"cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
version = "0.0.0"
dependencies = [
"graphviz 0.0.0",
- "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)",
"rustc 0.0.0",
"rustc_errors 0.0.0",
"rustc_mir 0.0.0",
version = "0.0.0"
dependencies = [
"arena 0.0.0",
- "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)",
"rustc 0.0.0",
"rustc_const_math 0.0.0",
"rustc_data_structures 0.0.0",
version = "0.0.0"
dependencies = [
"cfg-if 0.1.2 (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)",
"parking_lot 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot_core 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
"serialize 0.0.0",
"arena 0.0.0",
"env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
"graphviz 0.0.0",
- "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)",
"rustc 0.0.0",
"rustc_allocator 0.0.0",
"rustc_back 0.0.0",
version = "0.0.0"
dependencies = [
"graphviz 0.0.0",
- "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
- "rand 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc 0.0.0",
"rustc_data_structures 0.0.0",
"serialize 0.0.0",
name = "rustc_lint"
version = "0.0.0"
dependencies = [
- "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)",
"rustc 0.0.0",
"rustc_const_eval 0.0.0",
"syntax 0.0.0",
dependencies = [
"bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"build_helper 0.1.0",
- "cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc_cratesio_shim 0.0.0",
]
version = "0.0.0"
dependencies = [
"flate2 1.0.1 (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)",
"proc_macro 0.0.0",
"rustc 0.0.0",
"rustc_back 0.0.0",
"bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"graphviz 0.0.0",
- "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)",
"log_settings 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc 0.0.0",
"rustc_apfloat 0.0.0",
name = "rustc_passes"
version = "0.0.0"
dependencies = [
- "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)",
"rustc 0.0.0",
"rustc_const_eval 0.0.0",
"rustc_const_math 0.0.0",
version = "0.0.0"
dependencies = [
"arena 0.0.0",
- "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)",
"rustc 0.0.0",
"rustc_data_structures 0.0.0",
"rustc_errors 0.0.0",
name = "rustc_save_analysis"
version = "0.0.0"
dependencies = [
- "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)",
"rls-data 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc 0.0.0",
version = "0.0.0"
dependencies = [
"bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
"flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "jobserver 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
- "num_cpus 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "jobserver 0.1.9 (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)",
"rustc 0.0.0",
"rustc-demangle 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc_allocator 0.0.0",
dependencies = [
"ar 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"flate2 1.0.1 (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)",
"rustc 0.0.0",
"rustc_back 0.0.0",
"rustc_data_structures 0.0.0",
dependencies = [
"arena 0.0.0",
"fmt_macros 0.0.0",
- "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)",
"rustc 0.0.0",
"rustc_const_math 0.0.0",
"rustc_data_structures 0.0.0",
version = "0.0.0"
dependencies = [
"build_helper 0.1.0",
- "cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "html-diff 0.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "html-diff 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
"pulldown-cmark 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rustfmt-nightly"
-version = "0.3.4"
+version = "0.3.6"
dependencies = [
"cargo_metadata 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"derive-new 0.5.0 (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.34 (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.36 (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.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_errors 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-syntax 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.9 (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 = "same-file"
+version = "1.0.2"
+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 = "schannel"
+version = "0.1.10"
+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)",
+ "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
[[package]]
name = "scoped-tls"
version = "0.1.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.25 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "semver"
+version = "0.9.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.27 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
[[package]]
name = "serde"
-version = "1.0.25"
+version = "1.0.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "serde_derive"
-version = "1.0.25"
+version = "1.0.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive_internals 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive_internals 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "serde_derive_internals"
-version = "0.18.1"
+version = "0.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)",
version = "0.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "serde 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "serde_json"
-version = "1.0.8"
+version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
"num-traits 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
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.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "socket2"
-version = "0.2.4"
+version = "0.3.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)",
- "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.34 (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)",
+ "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
"panic_abort 0.0.0",
"panic_unwind 0.0.0",
"profiler_builtins 0.0.0",
- "rand 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc_asan 0.0.0",
"rustc_lsan 0.0.0",
"rustc_msan 0.0.0",
"lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
"phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
"precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
"string_cache_codegen 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
version = "0.0.0"
dependencies = [
"bitflags 1.0.1 (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)",
"rustc_cratesio_shim 0.0.0",
"rustc_data_structures 0.0.0",
"rustc_errors 0.0.0",
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
"syntex_pos 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)",
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
"syntex_errors 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)",
version = "0.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "filetime 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
- "redox_syscall 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)",
+ "filetime 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
+ "redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
"xattr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
]
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "rand 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
version = "1.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
- "redox_syscall 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
+ "redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
"redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
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.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "serde 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "serde 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
"url 1.6.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 = "walkdir"
+version = "2.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "same-file 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
[[package]]
name = "winapi"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
+[[package]]
+name = "winapi"
+version = "0.3.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
[[package]]
name = "winapi-build"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
+[[package]]
+name = "winapi-i686-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "winapi-x86_64-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
[[package]]
name = "wincolor"
version = "0.1.4"
version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "xz2"
-version = "0.1.3"
+version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"lzma-sys 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
"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 ar 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "35c7a5669cb64f085739387e1308b74e6d44022464b7f1b63bbd4ceb6379ec31"
-"checksum atty 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "21e50800ec991574876040fff8ee46b136a53e985286fbe6a3bdfe6421b78860"
-"checksum backtrace 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8709cc7ec06f6f0ae6c2c7e12f6ed41540781f72b488d83734978295ceae182e"
+"checksum atty 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "8352656fd42c30a0c3c89d26dea01e3b77c0ab2af18230835c15e2e13cd51859"
+"checksum backtrace 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ebbbf59b1c43eefa8c3ede390fcc36820b4999f7914104015be25025e0d62af2"
"checksum backtrace-sys 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "44585761d6161b0f57afc49482ab6bd067e4edef48c12a152c237eb0203f7661"
"checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d"
"checksum bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5"
"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 cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a9b13a57efd6b30ecd6598ebdb302cca617930b5470647570468a65d12ef9719"
+"checksum cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "deaf9ec656256bb25b404c51ef50097207b9cbb29c933d31f92cae5a8a0ffee0"
"checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de"
"checksum clap 2.29.0 (registry+https://github.com/rust-lang/crates.io-index)" = "110d43e343eb29f4f51c1db31beb879d546db27998577e5715270a54bcf41d3f"
"checksum cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)" = "56d741ea7a69e577f6d06b36b7dff4738f680593dc27a701ffa8506b73ce28bb"
"checksum compiletest_rs 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "562bafeec9aef1e3e08f1c5b0c542220bb80ff2894e5373a1f9d17c346412c66"
"checksum core-foundation 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "8047f547cd6856d45b1cdd75ef8d2f21f3d0e4bf1dab0a0041b0ae9a5dda9c0e"
"checksum core-foundation-sys 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "152195421a2e6497a8179195672e9d4ee8e45ed8c465b626f1606d27a08ebcd5"
-"checksum crossbeam 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "0c5ea215664ca264da8a9d9c3be80d2eaf30923c259d03e870388eb927508f97"
-"checksum crossbeam 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8837ab96533202c5b610ed44bc7f4183e7957c1c8f56e8cc78bb098593c8ba0a"
+"checksum crossbeam 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)" = "bd66663db5a988098a89599d4857919b3acf7f61402e61365acfd3919857b9be"
+"checksum crossbeam 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "24ce9782d4d5c53674646a6a4c1863a21a8fc0cb649b3c94dfc16e45071dea19"
"checksum crypto-hash 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "34903878eec1694faf53cae8473a088df333181de421d4d3d48061d6559fe602"
"checksum cssparser 0.13.7 (registry+https://github.com/rust-lang/crates.io-index)" = "ef6124306e5ebc5ab11891d063aeafdd0cdc308079b708c8b566125f3680292b"
"checksum cssparser-macros 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "079adec4af52bb5275eadd004292028c79eb3c5f5b4ee8086a36d4197032f6df"
-"checksum curl 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7034c534a1d7d22f7971d6088aa9d281d219ef724026c3428092500f41ae9c2c"
-"checksum curl-sys 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "4bee31aa3a079d5f3ff9579ea4dcfb1b1a17a40886f5f467436d383e78134b55"
-"checksum dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "97590ba53bcb8ac28279161ca943a924d1fd4a8fb3fa63302591647c4fc5b850"
+"checksum curl 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b70fd6394677d3c0e239ff4be6f2b3176e171ffd1c23ffdc541e78dea2b8bb5e"
+"checksum curl-sys 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f46e49c7125131f5afaded06944d6888b55cbdf8eba05dae73c954019b907961"
"checksum debug_unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9a032eac705ca39214d169f83e3d3da290af06d8d1d344d1baad2fd002dca4b3"
"checksum derive-new 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "415f627ab054041c3eb748c2e1da0ef751989f5f0c386b63a098e545854a98ba"
"checksum diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "3c2b69f912779fbb121ceb775d74d51e915af17aaebc38d28a592843a2dd0a3a"
-"checksum docopt 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3b5b93718f8b3e5544fcc914c43de828ca6c6ace23e0332c6080a2977b49787a"
+"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 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.14 (registry+https://github.com/rust-lang/crates.io-index)" = "aa75ec8f7927063335a9583e7fa87b0110bb888cf766dc01b54c0ff70d760c8e"
+"checksum filetime 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "714653f3e34871534de23771ac7b26e999651a0a228f47beb324dfdf1dd4b10f"
"checksum flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9fac2277e84e5e858483756647a9d0aa8d9a2b7cba517fd84325a0aaa69a0909"
"checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3"
"checksum foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
"checksum foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
-"checksum fs2 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9ab76cfd2aaa59b7bf6688ad9ba15bbae64bff97f04ea02144cfd3443e5c2866"
-"checksum fuchsia-zircon 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bd510087c325af53ba24f3be8f1c081b0982319adcb8b03cad764512923ccc19"
-"checksum fuchsia-zircon-sys 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "08b3a6f13ad6b96572b53ce7af74543132f1a7055ccceb6d073dd36c54481859"
+"checksum fs2 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213"
+"checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82"
+"checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
"checksum futf 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "51f93f3de6ba1794dcd5810b3546d004600a59a98266487c8407bc4b24e398f3"
"checksum futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "118b49cac82e04121117cbd3121ede3147e885627d82c4546b87c702debb90c1"
"checksum getopts 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)" = "65922871abd2f101a2eb0eaebadc66668e54a87ad9c3dd82520b5f86ede5eff9"
-"checksum git2 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "40a111aecd59985496012976beca164b4f6c930d507a099831e06b07f19d54f1"
+"checksum git2 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "ee5b4bb7cd2a44e6e5ee3a26ba6a9ca10d4ce2771cdc3839bbc54b47b7d1be84"
"checksum git2-curl 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "68676bc784bf0bef83278898929bf64a251e87c0340723d0b93fa096c9c5bf8e"
"checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb"
"checksum globset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "464627f948c3190ae3d04b1bc6d7dca2f785bda0ac01278e6db129ad383dbeb6"
"checksum hamcrest 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bf088f042a467089e9baa4972f57f9247e42a0cc549ba264c7a04fbb8ecb89d4"
"checksum handlebars 0.29.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fb04af2006ea09d985fef82b81e0eb25337e51b691c76403332378a53d521edc"
"checksum hex 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d6a22814455d41612f41161581c2883c0c6a1c41852729b17d5ed88f01e153aa"
+"checksum hex 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "459d3cf58137bb02ad4adeef5036377ff59f066dbb82517b7192e3a5462a2abc"
"checksum home 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9f25ae61099d8f3fee8b483df0bd4ecccf4b2731897aad40d50eca1b641fe6db"
-"checksum html-diff 0.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "9778743e3b3c3679f471f0ed1833c690f19f4a0919e33b281f12ef5f77ad64c6"
+"checksum html-diff 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ee4cfdf62a484a3ac0d9b80f562d37f99366db08a63621b917ea3056565345f7"
"checksum html5ever 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5bfb46978eb757a603b7dfe2dafb1c62cb4dee3428d8ac1de734d83d6b022d06"
"checksum idna 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "014b298351066f1512874135335d62a789ffe78a9974f94b43ed5621951eaf7d"
"checksum if_chain 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "61bb90bdd39e3af69b0172dfc6130f6cd6332bf040fbb9bdd4401d37adbd48b8"
-"checksum ignore 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b3fcaf2365eb14b28ec7603c98c06cc531f19de9eb283d89a3dff8417c8c99f5"
+"checksum ignore 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bb2f0238094bd1b41800fb6eb9b16fdd5e9832ed6053ed91409f0cd5bf28dcfd"
"checksum itertools 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d3f2be4da1690a039e9ae5fd575f706a63ad5a2120f161b1d653c9da3930dd21"
"checksum itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8324a32baf01e2ae060e9de58ed0bc2320c9a2833491ee36cd3b4c414de4db8c"
-"checksum jobserver 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "931b04e5e57d88cc909528f0d701db36a870b72a052648ded8baf80f9f445e0f"
+"checksum jobserver 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "565f6106bd87b394398f813bea4e5ecad6d6b0f6aa077592d088f882a506481d"
"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 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 libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)" = "36fbc8a8929c632868295d0178dd8f63fc423fd7537ad0738372bd010b3ac9b0"
-"checksum libgit2-sys 0.6.18 (registry+https://github.com/rust-lang/crates.io-index)" = "82fc20bd8beefe7c9f98aae2d3cff78e57f544cdd83d58fe181ec37a5fbe0c77"
+"checksum libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)" = "1e5d97d6708edaa407429faa671b942dc0f2727222fb6b6539bf1db936e4b121"
+"checksum libgit2-sys 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)" = "6eeae66e7b1c995de45cb4e65c5ab438a96a7b4077e448645d4048dc753ad357"
"checksum libssh2-sys 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0db4ec23611747ef772db1c4d650f8bd762f07b461727ec998f953c614024b75"
"checksum libz-sys 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)" = "87f737ad6cc6fd6eefe3d9dc5412f1573865bded441300904d2f42269e140f16"
"checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b"
"checksum matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "100aabe6b8ff4e4a7e32c1c13523379802df0772b82466207ac25b013f193376"
"checksum mdbook 0.0.26 (registry+https://github.com/rust-lang/crates.io-index)" = "8a1ac668292d1e5c7b1c6fd64f70d3a85105b8069a89558a0d67bdb2ff298ca1"
"checksum memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d8b629fb514376c675b98c1421e80b151d3817ac42d7c667717d282761418d20"
-"checksum memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "148fab2e51b4f1cfc66da2a7c32981d1d3c083a803978268bb11fe4b86925e7a"
"checksum memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "796fba70e76612589ed2ce7f45282f5af869e0fdd7cc6199fa1aa1f1d591ba9d"
"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 num-iter 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)" = "7485fcc84f85b4ecd0ea527b14189281cf27d60e583ae65ebc9c088b13dffe01"
"checksum num-rational 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "0c7cb72a95250d8a370105c828f388932373e0e94414919891a0f945222310fe"
"checksum num-traits 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "cacfcab5eb48250ee7d0c7896b51a2c5eec99c1feea5f32025635f5ae4b00070"
-"checksum num_cpus 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "514f0d73e64be53ff320680ca671b64fe3fb91da01e1ae2ddc99eb51d453b20d"
+"checksum num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c51a3322e4bca9d212ad9a158a02abc6934d005490c054a2778df73a70aa0a30"
"checksum open 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c281318d992e4432cfa799969467003d05921582a7489a8325e37f8a450d5113"
"checksum openssl 0.9.23 (registry+https://github.com/rust-lang/crates.io-index)" = "169a4b9160baf9b9b1ab975418c673686638995ba921683a7f1e01470dcb8854"
"checksum openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de"
-"checksum openssl-sys 0.9.23 (registry+https://github.com/rust-lang/crates.io-index)" = "2200ffec628e3f14c39fc0131a301db214f1a7d584e36507ee8700b0c7fb7a46"
+"checksum openssl-sys 0.9.24 (registry+https://github.com/rust-lang/crates.io-index)" = "14ba54ac7d5a4eabd1d5f2c1fdeb7e7c14debfa669d94b983d01b465e767ba9e"
"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 pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3a8b4c6b8165cd1a1cd4b9b120978131389f64bdaf456435caa41e630edba903"
"checksum precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
"checksum procedural-masquerade 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "dc1bcafee1590f81acb329ae45ec627b318123f085153913620316ae9a144b2a"
-"checksum psapi-sys 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1f71c7e142c25f297077a8ebc21f10847096b5d21ad7619d7bf0c1fcecb40bb0"
"checksum pulldown-cmark 0.0.15 (registry+https://github.com/rust-lang/crates.io-index)" = "378e941dbd392c101f2cb88097fa4d7167bc421d4b88de3ff7dbee503bc3233b"
"checksum pulldown-cmark 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a656fdb8b6848f896df5e478a0eb9083681663e37dcb77dd16981ff65329fe8b"
"checksum quick-error 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eda5fe9b71976e62bc81b781206aaa076401769b2143379d3eb2118388babac4"
"checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a"
"checksum racer 2.0.12 (registry+https://github.com/rust-lang/crates.io-index)" = "034f1c4528581c40a60e96875467c03315868084e08ff4ceb46a00f7be3b16b4"
"checksum radix_trie 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "211c49b6a9995cac0fd1dd9ca60b42cf3a51e151a12eb954b3a9e75513426ee8"
-"checksum rand 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)" = "9e7944d95d25ace8f377da3ac7068ce517e4c646754c43a1b1849177bbf72e59"
+"checksum rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)" = "512870020642bb8c221bf68baa1b2573da814f6ccfe5c9699b1c303047abe9b1"
"checksum rayon 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ed02d09394c94ffbdfdc755ad62a132e94c3224a8354e78a1200ced34df12edf"
"checksum rayon-core 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e64b609139d83da75902f88fd6c01820046840a18471e4dfcd5ac7c0f46bea53"
-"checksum redox_syscall 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "ab105df655884ede59d45b7070c8a65002d921461ee813a024558ca16030eea0"
+"checksum redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "0d92eecebad22b767915e4d529f89f28ee96dbbf5a4810d2b844373f136417fd"
"checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76"
"checksum regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)" = "4fd4ace6a8cf7860714a2c2280d6c1f7e6a413486c13298bbc86fd3da019402f"
-"checksum regex 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ac6ab4e9218ade5b423358bbd2567d1617418403c7a512603630181813316322"
+"checksum regex 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "744554e01ccbd98fff8c457c3b092cd67af62a555a43bfe97ae8a0451f7799fa"
"checksum regex-syntax 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "f9ec002c35e86791825ed294b50008eea9ddfc8def4420124fbc6b08db834957"
-"checksum regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad890a5eef7953f55427c50575c680c42841653abd2b028b68cd223d157f62db"
+"checksum regex-syntax 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8e931c58b93d86f080c734bfd2bce7dd0079ae2331235818133c8be7f422e20e"
"checksum rls-analysis 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "38841e3c5271715a574ac220d9b408b59ed9e2626909c3bc54b5853b4eaadb7b"
"checksum rls-data 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8024f1feaca72d0aa4ae1e2a8d454a31b9a33ed02f8d0e9c8559bf53c267ec3c"
"checksum rls-rustc 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b21ea952e9bf1569929abf1bb920262cde04b7b1b26d8e0260286302807299d2"
"checksum rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d7c7046dc6a92f2ae02ed302746db4382e75131b9ce20ce967259f6b5867a6a"
"checksum rls-vfs 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ffd34691a510938bb67fe0444fb363103c73ffb31c121d1e16bc92d8945ea8ff"
+"checksum rustc-ap-rustc_cratesio_shim 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f1a51c10af5abd5d698b7e3487e869e6d15f6feb04cbedb5c792e2824f9d845e"
+"checksum rustc-ap-rustc_data_structures 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1aa227490501072780d57f74b1164d361833ff8e172f817da0da2cdf2e4280cc"
+"checksum rustc-ap-rustc_errors 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "21ff6c6e13ac4fc04b7d4d398828b024c4b6577045cb3175b33d35fea35ff6d0"
+"checksum rustc-ap-serialize 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6b4e7f51e298675c2bf830f7265621a8936fb09e63b825b58144cbaac969e604"
+"checksum rustc-ap-syntax 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8bf5639869ba2f7fa581939cd217cb71a85506b82ad0ea520614fb0dceb2386c"
+"checksum rustc-ap-syntax_pos 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1c020cdb7379e1c733ae0a311ae47c748337ba584d2dd7b7f53baaae78de6f8b"
"checksum rustc-demangle 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "aee45432acc62f7b9a108cc054142dac51f979e69e71ddce7d6fc7adf29e817e"
"checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda"
"checksum same-file 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d931a44fdaa43b8637009e7632a02adc4f2b2e0733c08caa4cf00e8da4a117a7"
+"checksum same-file 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "cfb6eded0b06a0b512c8ddbcf04089138c9b4362c2f696f3c3d76039d68f3637"
+"checksum schannel 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "acece75e0f987c48863a6c792ec8b7d6c4177d4a027f8ccc72f849794f437016"
"checksum scoped-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f417c22df063e9450888a7561788e9bd46d3bb3c1466435b4eccb903807f147d"
"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 selectors 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e3c89b1c6a3c029c82263f7dd2d44d0005ee7374eb09e254ab59dede4353a8c0"
"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.25 (registry+https://github.com/rust-lang/crates.io-index)" = "386122ba68c214599c44587e0c0b411e8d90894503a95425b4f9508e4317901f"
-"checksum serde_derive 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "ec0bfa6c5784e7d110514448da0e1dbad41ea5514c3e68be755b23858b83a399"
-"checksum serde_derive_internals 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)" = "730fe9f29fe8db69a601837f416e46cba07792031ed6b27557a43e49d62d89ae"
+"checksum serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)" = "db99f3919e20faa51bb2996057f5031d8685019b5a06139b1ce761da671b8526"
+"checksum serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)" = "f4ba7591cfe93755e89eeecdbcc668885624829b020050e6aec99c2a03bd3fd0"
+"checksum serde_derive_internals 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6e03f1c9530c3fb0a0a5c9b826bdd9246a5921ae995d75f512ac917fc4dd55b5"
"checksum serde_ignored 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "190e9765dcedb56be63b6e0993a006c7e3b071a016a304736e4a315dc01fb142"
-"checksum serde_json 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7cf5b0b5b4bd22eeecb7e01ac2e1225c7ef5e4272b79ee28a8392a8c8489c839"
+"checksum serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c9db7266c7d63a4c4b7fe8719656ccdd51acf1bed6124b174f933b009fb10bcb"
"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 siphasher 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0df90a788073e8d0235a67e50441d47db7c8ad9debd91cbf43736a2a92d36537"
"checksum smallvec 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4f8266519bc1d17d0b5b16f6c21295625d562841c708f6376f49028a43e9c11e"
"checksum smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44db0ecb22921ef790d17ae13a3f6d15784183ff5f2a01aa32098c7498d2b4b9"
-"checksum socket2 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "36b4896961171cd3317c7e9603d88f379f8c6e45342212235d356496680c68fd"
+"checksum socket2 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cf5d5aa364bf61a0d744a293da20381617b6445b89eb524800fab857c5aed2d8"
"checksum stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "15132e0e364248108c5e2c02e3ab539be8d6f5d52a01ca9bbf27ed657316f02b"
"checksum string_cache 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "413fc7852aeeb5472f1986ef755f561ddf0c789d3d796e65f0b6fe293ecd4ef8"
"checksum string_cache_codegen 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "479cde50c3539481f33906a387f2bd17c8e87cb848c35b6021d41fb81ff9b4d7"
"checksum vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "887b5b631c2ad01628bbbaa7dd4c869f80d3186688f8d0b6f58774fbe324988c"
"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
"checksum walkdir 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "bb08f9e670fab86099470b97cd2b252d6527f0b3cc1401acdb595ffc9dd288ff"
+"checksum walkdir 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "40b6d201f4f8998a837196b6de9c73e35af14c992cbb92c4ab641d2c2dce52de"
"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
+"checksum winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "04e3bd221fcbe8a271359c04f21a76db7d0c6028862d1bb5512d85e1e2eb5bb3"
"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
+"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.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a39ee4464208f6430992ff20154216ab2357772ac871d994c51628d60e58b8b0"
"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.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e9510bdf100731599107c61f77daf46713a69a568f75458999c1f9dbf6ba25b0"
+"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"
debug = false
debug-assertions = false
+# We want the RLS to use the version of Cargo that we've got vendored in this
+# repository to ensure that the same exact version of Cargo is used by both the
+# RLS and the Cargo binary itself. The RLS depends on Cargo as a git repository
+# so we use a `[patch]` here to override the github repository with our local
+# vendored copy.
[patch."https://github.com/rust-lang/cargo"]
cargo = { path = "tools/cargo" }
[patch.crates-io]
+# Similar to Cargo above we want the RLS to use a vendored version of `rustfmt`
+# that we're shipping as well (to ensure that the rustfmt in RLS and the
+# `rustfmt` executable are the same exact vesion). Unlike Cargo, however, the
+# RLS depends on `rustfmt` from crates.io, so we put this in a `[patch]` section
+# for crates.io
rustfmt-nightly = { path = "tools/rustfmt" }
fn main() {
let args = env::args_os().skip(1).collect::<Vec<_>>();
let rustdoc = env::var_os("RUSTDOC_REAL").expect("RUSTDOC_REAL was not set");
- let libdir = env::var_os("RUSTC_LIBDIR").expect("RUSTC_LIBDIR was not set");
+ let libdir = env::var_os("RUSTDOC_LIBDIR").expect("RUSTDOC_LIBDIR was not set");
let stage = env::var("RUSTC_STAGE").expect("RUSTC_STAGE was not set");
let sysroot = env::var_os("RUSTC_SYSROOT").expect("RUSTC_SYSROOT was not set");
+ use std::str::FromStr;
+
+ let verbose = match env::var("RUSTC_VERBOSE") {
+ Ok(s) => usize::from_str(&s).expect("RUSTC_VERBOSE should be an integer"),
+ Err(_) => 0,
+ };
+
let mut dylib_path = bootstrap::util::dylib_path();
dylib_path.insert(0, PathBuf::from(libdir));
cmd.arg("--deny-render-differences");
}
+ if verbose > 1 {
+ eprintln!("rustdoc command: {:?}", cmd);
+ }
+
std::process::exit(match cmd.status() {
Ok(s) => s.code().unwrap_or(1),
Err(e) => panic!("\n\nfailed to run {:?}: {}\n\n", cmd, e),
with open(self.rustc_stamp(), 'w') as rust_stamp:
rust_stamp.write(self.date)
- if "pc-windows-gnu" in self.build:
- filename = "rust-mingw-{}-{}.tar.gz".format(
- rustc_channel, self.build)
- self._download_stage0_helper(filename, "rust-mingw")
-
if self.cargo().startswith(self.bin_root()) and \
(not os.path.exists(self.cargo()) or
self.program_out_of_date(self.cargo_stamp())):
Kind::Test => describe!(check::Tidy, check::Bootstrap, check::DefaultCompiletest,
check::HostCompiletest, check::Crate, check::CrateLibrustc, check::Rustdoc,
check::Linkcheck, check::Cargotest, check::Cargo, check::Rls, check::Docs,
- check::ErrorIndex, check::Distcheck, check::Rustfmt, check::Miri, check::Clippy),
+ check::ErrorIndex, check::Distcheck, check::Rustfmt, check::Miri, check::Clippy,
+ check::RustdocJS),
+
Kind::Bench => describe!(check::Crate, check::CrateLibrustc),
Kind::Doc => describe!(doc::UnstableBook, doc::UnstableBookGen, doc::TheBook,
doc::Standalone, doc::Std, doc::Test, doc::Rustc, doc::ErrorIndex, doc::Nomicon,
- doc::Reference, doc::Rustdoc, doc::CargoBook),
+ doc::Reference, doc::Rustdoc, doc::RustByExample, doc::CargoBook),
Kind::Dist => describe!(dist::Docs, dist::Mingw, dist::Rustc, dist::DebuggerScripts,
dist::Std, dist::Analysis, dist::Src, dist::PlainSourceTarball, dist::Cargo,
dist::Rls, dist::Rustfmt, dist::Extended, dist::HashSign,
fn run(self, builder: &Builder) -> Interned<PathBuf> {
let compiler = self.compiler;
- let lib = if compiler.stage >= 2 && builder.build.config.libdir_relative.is_some() {
- builder.build.config.libdir_relative.clone().unwrap()
+ let lib = if compiler.stage >= 1 && builder.build.config.libdir.is_some() {
+ builder.build.config.libdir.clone().unwrap()
} else {
PathBuf::from("lib")
};
let compiler = self.compiler(self.top_stage, host);
cmd.env("RUSTC_STAGE", compiler.stage.to_string())
.env("RUSTC_SYSROOT", self.sysroot(compiler))
- .env("RUSTC_LIBDIR", self.sysroot_libdir(compiler, self.build.build))
+ .env("RUSTDOC_LIBDIR", self.sysroot_libdir(compiler, self.build.build))
.env("CFG_RELEASE_CHANNEL", &self.build.config.channel)
.env("RUSTDOC_REAL", self.rustdoc(host))
- .env("RUSTDOC_CRATE_VERSION", self.build.rust_version());
+ .env("RUSTDOC_CRATE_VERSION", self.build.rust_version())
+ .env("RUSTC_BOOTSTRAP", "1");
if let Some(linker) = self.build.linker(host) {
cmd.env("RUSTC_TARGET_LINKER", linker);
}
let out_dir = self.stage_out(compiler, mode);
cargo.env("CARGO_TARGET_DIR", out_dir)
.arg(cmd)
- .arg("--target").arg(target);
+ .arg("--target")
+ .arg(target);
// If we were invoked from `make` then that's already got a jobserver
// set up for us so no need to tell Cargo about jobs all over again.
} else {
PathBuf::from("/path/to/nowhere/rustdoc/not/required")
})
- .env("TEST_MIRI", self.config.test_miri.to_string());
-
+ .env("TEST_MIRI", self.config.test_miri.to_string())
+ .env("RUSTC_ERROR_METADATA_DST", self.extended_error_dir());
if let Some(n) = self.config.rust_codegen_units {
cargo.env("RUSTC_CODEGEN_UNITS", n.to_string());
}
if let Some(target_linker) = self.build.linker(target) {
cargo.env("RUSTC_TARGET_LINKER", target_linker);
}
+ if cmd != "build" {
+ cargo.env("RUSTDOC_LIBDIR", self.rustc_libdir(self.compiler(2, self.build.build)));
+ }
if mode != Mode::Tool {
// Tools don't get debuginfo right now, e.g. cargo and rls don't
// Set this for all builds to make sure doc builds also get it.
cargo.env("CFG_RELEASE_CHANNEL", &self.build.config.channel);
+ // This one's a bit tricky. As of the time of this writing the compiler
+ // links to the `winapi` crate on crates.io. This crate provides raw
+ // bindings to Windows system functions, sort of like libc does for
+ // Unix. This crate also, however, provides "import libraries" for the
+ // MinGW targets. There's an import library per dll in the windows
+ // distribution which is what's linked to. These custom import libraries
+ // are used because the winapi crate can reference Windows functions not
+ // present in the MinGW import libraries.
+ //
+ // For example MinGW may ship libdbghelp.a, but it may not have
+ // references to all the functions in the dbghelp dll. Instead the
+ // custom import library for dbghelp in the winapi crates has all this
+ // information.
+ //
+ // Unfortunately for us though the import libraries are linked by
+ // default via `-ldylib=winapi_foo`. That is, they're linked with the
+ // `dylib` type with a `winapi_` prefix (so the winapi ones don't
+ // conflict with the system MinGW ones). This consequently means that
+ // the binaries we ship of things like rustc_trans (aka the rustc_trans
+ // DLL) when linked against *again*, for example with procedural macros
+ // or plugins, will trigger the propagation logic of `-ldylib`, passing
+ // `-lwinapi_foo` to the linker again. This isn't actually available in
+ // our distribution, however, so the link fails.
+ //
+ // To solve this problem we tell winapi to not use its bundled import
+ // libraries. This means that it will link to the system MinGW import
+ // libraries by default, and the `-ldylib=foo` directives will still get
+ // passed to the final linker, but they'll look like `-lfoo` which can
+ // be resolved because MinGW has the import library. The downside is we
+ // don't get newer functions from Windows, but we don't use any of them
+ // anyway.
+ cargo.env("WINAPI_NO_BUNDLED_LIBRARIES", "1");
+
if self.is_very_verbose() {
cargo.arg("-v");
}
use config::Config;
// The version number
-pub const CFG_RELEASE_NUM: &str = "1.24.0";
+pub const CFG_RELEASE_NUM: &str = "1.25.0";
// An optional number to put after the label, e.g. '.2' -> '-beta.2'
// Be sure to make this starts with a dot to conform to semver pre-release
env::join_paths(iter::once(path).chain(env::split_paths(&old_path))).expect("")
}
+#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
+pub struct RustdocJS {
+ pub host: Interned<String>,
+ pub target: Interned<String>,
+}
+
+impl Step for RustdocJS {
+ type Output = ();
+ const DEFAULT: bool = true;
+ const ONLY_HOSTS: bool = true;
+
+ fn should_run(run: ShouldRun) -> ShouldRun {
+ run.path("src/test/rustdoc-js")
+ }
+
+ fn make_run(run: RunConfig) {
+ run.builder.ensure(RustdocJS {
+ host: run.host,
+ target: run.target,
+ });
+ }
+
+ fn run(self, builder: &Builder) {
+ if let Some(ref nodejs) = builder.config.nodejs {
+ let mut command = Command::new(nodejs);
+ command.args(&["src/tools/rustdoc-js/tester.js", &*self.host]);
+ builder.ensure(::doc::Std {
+ target: self.target,
+ stage: builder.top_stage,
+ });
+ builder.run(&mut command);
+ } else {
+ println!("No nodejs found, skipping \"src/test/rustdoc-js\" tests");
+ }
+ }
+}
+
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct Tidy {
host: Interned<String>,
mode: "compile-fail",
suite: "compile-fail-fulldeps",
},
+ Test {
+ path: "src/test/incremental-fulldeps",
+ mode: "incremental",
+ suite: "incremental-fulldeps",
+ },
Test { path: "src/test/run-make", mode: "run-make", suite: "run-make" },
Test { path: "src/test/rustdoc", mode: "rustdoc", suite: "rustdoc" },
build.run(builder.tool_cmd(Tool::ErrorIndex)
.arg("markdown")
.arg(&output)
- .env("CFG_BUILD", &build.build));
+ .env("CFG_BUILD", &build.build)
+ .env("RUSTC_ERROR_METADATA_DST", build.extended_error_dir()));
markdown_test(builder, compiler, &output);
}
}
Mode::Librustc => {
builder.ensure(compile::Rustc { compiler, target });
- compile::rustc_cargo(build, &compiler, target, &mut cargo);
+ compile::rustc_cargo(build, target, &mut cargo);
("librustc", "rustc-main")
}
_ => panic!("can only test libraries"),
build.clear_if_dirty(&stage_out, &libtest_stamp(build, compiler, target));
let mut cargo = builder.cargo(compiler, Mode::Librustc, target, "build");
- rustc_cargo(build, &compiler, target, &mut cargo);
+ rustc_cargo(build, target, &mut cargo);
run_cargo(build,
&mut cargo,
&librustc_stamp(build, compiler, target));
/// Same as `std_cargo`, but for libtest
pub fn rustc_cargo(build: &Build,
- compiler: &Compiler,
target: Interned<String>,
cargo: &mut Command) {
cargo.arg("--features").arg(build.rustc_features())
.env("CFG_VERSION", build.rust_version())
.env("CFG_PREFIX", build.config.prefix.clone().unwrap_or_default());
- if compiler.stage == 0 {
- cargo.env("CFG_LIBDIR_RELATIVE", "lib");
- } else {
- let libdir_relative =
- build.config.libdir_relative.clone().unwrap_or(PathBuf::from("lib"));
- cargo.env("CFG_LIBDIR_RELATIVE", libdir_relative);
- }
+ let libdir_relative =
+ build.config.libdir.clone().unwrap_or(PathBuf::from("lib"));
+ cargo.env("CFG_LIBDIR_RELATIVE", libdir_relative);
// If we're not building a compiler with debugging information then remove
// these two env vars which would be set otherwise.
pub docdir: Option<PathBuf>,
pub bindir: Option<PathBuf>,
pub libdir: Option<PathBuf>,
- pub libdir_relative: Option<PathBuf>,
pub mandir: Option<PathBuf>,
pub codegen_tests: bool,
pub nodejs: Option<PathBuf>,
"MUSL root installation directory (deprecated)")
v("musl-root-x86_64", "target.x86_64-unknown-linux-musl.musl-root",
"x86_64-unknown-linux-musl install directory")
+v("musl-root-i586", "target.i586-unknown-linux-musl.musl-root",
+ "i586-unknown-linux-musl install directory")
v("musl-root-i686", "target.i686-unknown-linux-musl.musl-root",
"i686-unknown-linux-musl install directory")
v("musl-root-arm", "target.arm-unknown-linux-musleabi.musl-root",
"libwinspool.a",
"libws2_32.a",
"libwsock32.a",
+ "libdbghelp.a",
+ "libmsimg32.a",
];
//Find mingw artifacts we want to bundle
//!
//! This module implements generation for all bits and pieces of documentation
//! for the Rust project. This notably includes suites like the rust book, the
-//! nomicon, standalone documentation, etc.
+//! nomicon, rust by example, standalone documentation, etc.
//!
//! Everything here is basically just a shim around calling either `rustbook` or
//! `rustdoc`.
Nomicon, "src/doc/nomicon", "nomicon";
Reference, "src/doc/reference", "reference";
Rustdoc, "src/doc/rustdoc", "rustdoc";
+ RustByExample, "src/doc/rust-by-example", "rust-by-example";
);
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
let target = self.target;
let name = self.name;
- let src = build.src.join("src/tools/cargo/src/doc/book");
+ let src = build.src.join("src/tools/cargo/src/doc");
let out = build.doc_out(target);
t!(fs::create_dir_all(&out));
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct Std {
- stage: u32,
- target: Interned<String>,
+ pub stage: u32,
+ pub target: Interned<String>,
}
impl Step for Std {
t!(symlink_dir_force(&my_out, &out_dir));
let mut cargo = builder.cargo(compiler, Mode::Librustc, target, "doc");
- compile::rustc_cargo(build, &compiler, target, &mut cargo);
+ compile::rustc_cargo(build, target, &mut cargo);
if build.config.compiler_docs {
// src/rustc/Cargo.toml contains a bin crate called rustc which
index.arg(out.join("error-index.html"));
// FIXME: shouldn't have to pass this env var
- index.env("CFG_BUILD", &build.build);
+ index.env("CFG_BUILD", &build.build)
+ .env("RUSTC_ERROR_METADATA_DST", build.extended_error_dir());
build.run(&mut index);
}
self.config.python.as_ref().unwrap()
}
+ /// Temporary directory that extended error information is emitted to.
+ fn extended_error_dir(&self) -> PathBuf {
+ self.out.join("tmp/extended-error-metadata")
+ }
+
/// Tests whether the `compiler` compiling for `target` should be forced to
/// use a stage1 compiler instead.
///
"arm-unknown-linux-gnueabihf" => "linux-armv4",
"armv7-linux-androideabi" => "android-armv7",
"armv7-unknown-linux-gnueabihf" => "linux-armv4",
+ "i586-unknown-linux-gnu" => "linux-elf",
+ "i586-unknown-linux-musl" => "linux-elf",
"i686-apple-darwin" => "darwin-i386-cc",
"i686-linux-android" => "android-x86",
"i686-unknown-freebsd" => "BSD-x86-elf",
use std::collections::HashMap;
use std::env;
use std::ffi::{OsString, OsStr};
-use std::fs;
-use std::process::Command;
+use std::fs::{self, File};
+use std::io::Read;
use std::path::PathBuf;
+use std::process::Command;
use build_helper::output;
if let Some(ref s) = build.config.ccache {
cmd_finder.must_have(s);
}
+
+ if build.config.channel == "stable" {
+ let mut stage0 = String::new();
+ t!(t!(File::open(build.src.join("src/stage0.txt")))
+ .read_to_string(&mut stage0));
+ if stage0.contains("\ndev:") {
+ panic!("bootstrapping from a dev compiler in a stable release, but \
+ should only be bootstrapping from a released compiler!");
+ }
+ }
}
let mut data = [0u8; MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
let db = data.as_mut_ptr()
as *mut REPARSE_MOUNTPOINT_DATA_BUFFER;
- let buf = &mut (*db).ReparseTarget as *mut _;
+ let buf = &mut (*db).ReparseTarget as *mut u16;
let mut i = 0;
// FIXME: this conversion is very hacky
let v = br"\??\";
--- /dev/null
+FROM ubuntu:16.04
+
+RUN apt-get update && apt-get install -y --no-install-recommends \
+ g++-multilib \
+ make \
+ file \
+ curl \
+ ca-certificates \
+ python2.7 \
+ git \
+ cmake \
+ xz-utils \
+ sudo \
+ gdb \
+ patch \
+ libssl-dev \
+ pkg-config
+
+WORKDIR /build/
+COPY scripts/musl.sh /build/
+RUN CC=gcc CFLAGS="-m32 -fPIC -Wa,-mrelax-relocations=no" \
+ CXX=g++ CXXFLAGS="-m32 -Wa,-mrelax-relocations=no" \
+ bash musl.sh i686 --target=i686 && \
+ CC=gcc CFLAGS="-march=pentium -m32 -fPIC -Wa,-mrelax-relocations=no" \
+ CXX=g++ CXXFLAGS="-march=pentium -m32 -Wa,-mrelax-relocations=no" \
+ bash musl.sh i586 --target=i586 && \
+ rm -rf /build
+
+COPY scripts/sccache.sh /scripts/
+RUN sh /scripts/sccache.sh
+
+ENV RUST_CONFIGURE_ARGS \
+ --target=i686-unknown-linux-musl,i586-unknown-linux-gnu \
+ --musl-root-i586=/musl-i586 \
+ --musl-root-i686=/musl-i686 \
+ --enable-extended
+
+# Newer binutils broke things on some vms/distros (i.e., linking against
+# unknown relocs disabled by the following flag), so we need to go out of our
+# way to produce "super compatible" binaries.
+#
+# See: https://github.com/rust-lang/rust/issues/34978
+ENV CFLAGS_i686_unknown_linux_musl=-Wa,-mrelax-relocations=no
+ENV CFLAGS_i586_unknown_linux_gnu=-Wa,-mrelax-relocations=no
+# FIXME remove -Wl,-melf_i386 after cc is updated to include
+# https://github.com/alexcrichton/cc-rs/pull/281
+ENV CFLAGS_i586_unknown_linux_musl="-Wa,-mrelax-relocations=no -Wl,-melf_i386"
+
+ENV TARGETS=i586-unknown-linux-gnu
+ENV TARGETS=$TARGETS,i686-unknown-linux-musl
+
+ENV SCRIPT \
+ python2.7 ../x.py test --target $TARGETS && \
+ python2.7 ../x.py dist --target $TARGETS,i586-unknown-linux-musl
+++ /dev/null
-FROM ubuntu:16.04
-
-RUN apt-get update && apt-get install -y --no-install-recommends \
- g++-multilib \
- make \
- file \
- curl \
- ca-certificates \
- python2.7 \
- git \
- cmake \
- xz-utils \
- sudo \
- gdb \
- patch \
- libssl-dev \
- pkg-config
-
-WORKDIR /build/
-COPY dist-i586-gnu-i686-musl/musl-libunwind-patch.patch dist-i586-gnu-i686-musl/build-musl.sh /build/
-RUN sh /build/build-musl.sh && rm -rf /build
-
-COPY scripts/sccache.sh /scripts/
-RUN sh /scripts/sccache.sh
-
-ENV RUST_CONFIGURE_ARGS \
- --target=i686-unknown-linux-musl,i586-unknown-linux-gnu \
- --musl-root-i686=/musl-i686 \
- --enable-extended
-
-# Newer binutils broke things on some vms/distros (i.e., linking against
-# unknown relocs disabled by the following flag), so we need to go out of our
-# way to produce "super compatible" binaries.
-#
-# See: https://github.com/rust-lang/rust/issues/34978
-ENV CFLAGS_i686_unknown_linux_musl=-Wa,-mrelax-relocations=no
-ENV CFLAGS_i586_unknown_linux_gnu=-Wa,-mrelax-relocations=no
-
-ENV SCRIPT \
- python2.7 ../x.py test \
- --target i686-unknown-linux-musl \
- --target i586-unknown-linux-gnu \
- && \
- python2.7 ../x.py dist \
- --target i686-unknown-linux-musl \
- --target i586-unknown-linux-gnu
+++ /dev/null
-#!/bin/sh
-# 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.
-
-set -ex
-
-# We need to mitigate rust-lang/rust#34978 when compiling musl itself as well
-export CFLAGS="-fPIC -Wa,-mrelax-relocations=no"
-export CXXFLAGS="-Wa,-mrelax-relocations=no"
-
-MUSL=musl-1.1.17
-curl https://www.musl-libc.org/releases/$MUSL.tar.gz | tar xzf -
-cd $MUSL
-CC=gcc \
- CFLAGS="$CFLAGS -m32" \
- ./configure --prefix=/musl-i686 --disable-shared \
- --target=i686
-make AR=ar RANLIB=ranlib -j10
-make install
-cd ..
-
-# To build MUSL we're going to need a libunwind lying around, so acquire that
-# here and build it.
-curl -L https://github.com/llvm-mirror/llvm/archive/release_37.tar.gz | tar xzf -
-curl -L https://github.com/llvm-mirror/libunwind/archive/release_37.tar.gz | tar xzf -
-
-# Whoa what's this mysterious patch we're applying to libunwind! Why are we
-# swapping the values of ESP/EBP in libunwind?!
-#
-# Discovered in #35599 it turns out that the vanilla build of libunwind is not
-# suitable for unwinding 32-bit musl. After some investigation it ended up
-# looking like the register values for ESP/EBP were indeed incorrect (swapped)
-# in the source. Similar commits in libunwind (r280099 and r282589) have noticed
-# this for other platforms, and we just need to realize it for musl linux as
-# well.
-#
-# More technical info can be found at #35599
-cd libunwind-release_37
-patch -Np1 < /build/musl-libunwind-patch.patch
-cd ..
-
-mkdir libunwind-build
-cd libunwind-build
-CFLAGS="$CFLAGS -m32" CXXFLAGS="$CXXFLAGS -m32" cmake ../libunwind-release_37 \
- -DLLVM_PATH=/build/llvm-release_37 \
- -DLIBUNWIND_ENABLE_SHARED=0
-make -j10
-cp lib/libunwind.a /musl-i686/lib
+++ /dev/null
-diff --git a/include/libunwind.h b/include/libunwind.h
-index c5b9633..1360eb2 100644
---- a/include/libunwind.h
-+++ b/include/libunwind.h
-@@ -151,8 +151,8 @@ enum {
- UNW_X86_ECX = 1,
- UNW_X86_EDX = 2,
- UNW_X86_EBX = 3,
-- UNW_X86_EBP = 4,
-- UNW_X86_ESP = 5,
-+ UNW_X86_ESP = 4,
-+ UNW_X86_EBP = 5,
- UNW_X86_ESI = 6,
- UNW_X86_EDI = 7
- };
libssl-dev \
pkg-config
-WORKDIR /tmp
+WORKDIR /build
-COPY dist-various-1/build-rumprun.sh /tmp/
+COPY dist-various-1/build-rumprun.sh /build
RUN ./build-rumprun.sh
-COPY dist-various-1/build-arm-musl.sh /tmp/
-RUN ./build-arm-musl.sh
+COPY dist-various-1/install-x86_64-redox.sh /build
+RUN ./install-x86_64-redox.sh
+
+COPY scripts/musl.sh /build
+RUN env \
+ CC=arm-linux-gnueabi-gcc CFLAGS="-march=armv6 -marm" \
+ CXX=arm-linux-gnueabi-g++ CXXFLAGS="-march=armv6 -marm" \
+ bash musl.sh arm && \
+ env \
+ CC=arm-linux-gnueabihf-gcc CFLAGS="-march=armv6 -marm" \
+ CXX=arm-linux-gnueabihf-g++ CXXFLAGS="-march=armv6 -marm" \
+ bash musl.sh armhf && \
+ env \
+ CC=arm-linux-gnueabihf-gcc CFLAGS="-march=armv7-a" \
+ CXX=arm-linux-gnueabihf-g++ CXXFLAGS="-march=armv7-a" \
+ bash musl.sh armv7 && \
+ env \
+ CC=aarch64-linux-gnu-gcc \
+ CXX=aarch64-linux-gnu-g++ \
+ bash musl.sh aarch64 && \
+ rm -rf /build/*
-COPY dist-various-1/install-mips-musl.sh /tmp/
+COPY dist-various-1/install-mips-musl.sh /build
RUN ./install-mips-musl.sh
-COPY dist-various-1/install-mipsel-musl.sh /tmp/
+COPY dist-various-1/install-mipsel-musl.sh /build
RUN ./install-mipsel-musl.sh
-COPY dist-various-1/install-x86_64-redox.sh /tmp/
-RUN ./install-x86_64-redox.sh
-
ENV TARGETS=asmjs-unknown-emscripten
ENV TARGETS=$TARGETS,wasm32-unknown-emscripten
ENV TARGETS=$TARGETS,x86_64-rumprun-netbsd
ENV RUST_CONFIGURE_ARGS \
--enable-extended \
--target=$TARGETS \
- --musl-root-arm=/usr/local/arm-linux-musleabi \
- --musl-root-armhf=/usr/local/arm-linux-musleabihf \
- --musl-root-armv7=/usr/local/armv7-linux-musleabihf \
- --musl-root-aarch64=/usr/local/aarch64-linux-musl
+ --musl-root-arm=/musl-arm \
+ --musl-root-armhf=/musl-armhf \
+ --musl-root-armv7=/musl-armv7 \
+ --musl-root-aarch64=/musl-aarch64
ENV SCRIPT python2.7 ../x.py dist --target $TARGETS
# sccache
+++ /dev/null
-#!/usr/bin/env bash
-# Copyright 2017 The Rust Project Developers. See the COPYRIGHT
-# file at the top-level directory of this distribution and at
-# http://rust-lang.org/COPYRIGHT.
-#
-# Licensed under the Apache License, Version 2.0 <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.
-
-set -ex
-
-MUSL=1.1.17
-
-hide_output() {
- set +x
- on_err="
-echo ERROR: An error was encountered with the build.
-cat /tmp/build.log
-exit 1
-"
- trap "$on_err" ERR
- bash -c "while true; do sleep 30; echo \$(date) - building ...; done" &
- PING_LOOP_PID=$!
- $@ &> /tmp/build.log
- trap - ERR
- kill $PING_LOOP_PID
- rm /tmp/build.log
- set -x
-}
-
-curl -O https://www.musl-libc.org/releases/musl-$MUSL.tar.gz
-tar xf musl-$MUSL.tar.gz
-cd musl-$MUSL
-CC=arm-linux-gnueabi-gcc \
-CFLAGS="-march=armv6 -marm" \
- hide_output ./configure \
- --prefix=/usr/local/arm-linux-musleabi \
- --enable-wrapper=gcc
-hide_output make -j$(nproc)
-hide_output make install
-cd ..
-rm -rf musl-$MUSL
-
-tar xf musl-$MUSL.tar.gz
-cd musl-$MUSL
-CC=arm-linux-gnueabihf-gcc \
-CFLAGS="-march=armv6 -marm" \
- hide_output ./configure \
- --prefix=/usr/local/arm-linux-musleabihf \
- --enable-wrapper=gcc
-hide_output make -j$(nproc)
-hide_output make install
-cd ..
-rm -rf musl-$MUSL
-
-tar xf musl-$MUSL.tar.gz
-cd musl-$MUSL
-CC=arm-linux-gnueabihf-gcc \
-CFLAGS="-march=armv7-a" \
- hide_output ./configure \
- --prefix=/usr/local/armv7-linux-musleabihf \
- --enable-wrapper=gcc
-hide_output make -j$(nproc)
-hide_output make install
-cd ..
-rm -rf musl-$MUSL
-
-tar xf musl-$MUSL.tar.gz
-cd musl-$MUSL
-CC=aarch64-linux-gnu-gcc \
-CFLAGS="" \
- hide_output ./configure \
- --prefix=/usr/local/aarch64-linux-musl \
- --enable-wrapper=gcc
-hide_output make -j$(nproc)
-hide_output make install
-cd ..
-rm -rf musl-$MUSL*
-
-ln -nsf ../arm-linux-musleabi/bin/musl-gcc /usr/local/bin/arm-linux-musleabi-gcc
-ln -nsf ../arm-linux-musleabihf/bin/musl-gcc /usr/local/bin/arm-linux-musleabihf-gcc
-ln -nsf ../armv7-linux-musleabihf/bin/musl-gcc /usr/local/bin/armv7-linux-musleabihf-gcc
-ln -nsf ../aarch64-linux-musl/bin/musl-gcc /usr/local/bin/aarch64-unknown-linux-musl-gcc
-
-curl -L https://github.com/llvm-mirror/llvm/archive/release_39.tar.gz | tar xzf -
-curl -L https://github.com/llvm-mirror/libunwind/archive/release_39.tar.gz | tar xzf -
-
-mkdir libunwind-build
-cd libunwind-build
-cmake ../libunwind-release_39 \
- -DLLVM_PATH=/tmp/llvm-release_39 \
- -DLIBUNWIND_ENABLE_SHARED=0 \
- -DCMAKE_C_COMPILER=arm-linux-gnueabi-gcc \
- -DCMAKE_CXX_COMPILER=arm-linux-gnueabi-g++ \
- -DCMAKE_C_FLAGS="-march=armv6 -marm" \
- -DCMAKE_CXX_FLAGS="-march=armv6 -marm"
-make -j$(nproc)
-cp lib/libunwind.a /usr/local/arm-linux-musleabi/lib
-cd ..
-rm -rf libunwind-build
-
-mkdir libunwind-build
-cd libunwind-build
-cmake ../libunwind-release_39 \
- -DLLVM_PATH=/tmp/llvm-release_39 \
- -DLIBUNWIND_ENABLE_SHARED=0 \
- -DCMAKE_C_COMPILER=arm-linux-gnueabihf-gcc \
- -DCMAKE_CXX_COMPILER=arm-linux-gnueabihf-g++ \
- -DCMAKE_C_FLAGS="-march=armv6 -marm" \
- -DCMAKE_CXX_FLAGS="-march=armv6 -marm"
-make -j$(nproc)
-cp lib/libunwind.a /usr/local/arm-linux-musleabihf/lib
-cd ..
-rm -rf libunwind-build
-
-mkdir libunwind-build
-cd libunwind-build
-cmake ../libunwind-release_39 \
- -DLLVM_PATH=/tmp/llvm-release_39 \
- -DLIBUNWIND_ENABLE_SHARED=0 \
- -DCMAKE_C_COMPILER=arm-linux-gnueabihf-gcc \
- -DCMAKE_CXX_COMPILER=arm-linux-gnueabihf-g++ \
- -DCMAKE_C_FLAGS="-march=armv7-a" \
- -DCMAKE_CXX_FLAGS="-march=armv7-a"
-make -j$(nproc)
-cp lib/libunwind.a /usr/local/armv7-linux-musleabihf/lib
-cd ..
-rm -rf libunwind-build
-
-mkdir libunwind-build
-cd libunwind-build
-cmake ../libunwind-release_39 \
- -DLLVM_PATH=/tmp/llvm-release_39 \
- -DLIBUNWIND_ENABLE_SHARED=0 \
- -DCMAKE_C_COMPILER=aarch64-linux-gnu-gcc \
- -DCMAKE_CXX_COMPILER=aarch64-linux-gnu-g++ \
- -DCMAKE_C_FLAGS="" \
- -DCMAKE_CXX_FLAGS=""
-make -j$(nproc)
-cp lib/libunwind.a /usr/local/aarch64-linux-musl/lib
-cd ..
-rm -rf libunwind-build
-
-rm -rf libunwind-release_39
-rm -rf llvm-release_39
-FROM ubuntu:16.04
+FROM ubuntu:17.10
COPY scripts/cross-apt-packages.sh /scripts/
RUN sh /scripts/cross-apt-packages.sh
RUN add-apt-repository -y 'deb http://apt.dilos.org/dilos dilos2-testing main'
WORKDIR /tmp
-COPY dist-various-2/shared.sh dist-various-2/build-fuchsia-toolchain.sh /tmp/
-COPY dist-various-2/build-solaris-toolchain.sh /tmp/
+COPY dist-various-2/shared.sh /tmp/
+COPY dist-various-2/build-cloudabi-toolchain.sh /tmp/
+RUN /tmp/build-cloudabi-toolchain.sh x86_64-unknown-cloudabi
+COPY dist-various-2/build-fuchsia-toolchain.sh /tmp/
RUN /tmp/build-fuchsia-toolchain.sh
+COPY dist-various-2/build-solaris-toolchain.sh /tmp/
RUN /tmp/build-solaris-toolchain.sh x86_64 amd64 solaris-i386
RUN /tmp/build-solaris-toolchain.sh sparcv9 sparcv9 solaris-sparc
CC_x86_64_sun_solaris=x86_64-sun-solaris2.10-gcc \
CXX_x86_64_sun_solaris=x86_64-sun-solaris2.10-g++
+# FIXME(EdSchouten): Remove this once cc ≥1.0.4 has been merged. It can
+# automatically pick the right compiler path.
+ENV \
+ AR_x86_64_unknown_cloudabi=x86_64-unknown-cloudabi-ar \
+ CC_x86_64_unknown_cloudabi=x86_64-unknown-cloudabi-clang \
+ CXX_x86_64_unknown_cloudabi=x86_64-unknown-cloudabi-clang++
+
ENV TARGETS=x86_64-unknown-fuchsia
ENV TARGETS=$TARGETS,aarch64-unknown-fuchsia
ENV TARGETS=$TARGETS,sparcv9-sun-solaris
ENV TARGETS=$TARGETS,wasm32-unknown-unknown
ENV TARGETS=$TARGETS,x86_64-sun-solaris
ENV TARGETS=$TARGETS,x86_64-unknown-linux-gnux32
+ENV TARGETS=$TARGETS,x86_64-unknown-cloudabi
ENV RUST_CONFIGURE_ARGS --target=$TARGETS --enable-extended
ENV SCRIPT python2.7 ../x.py dist --target $TARGETS
--- /dev/null
+#!/bin/bash
+# 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.
+
+set -eux
+
+# Install prerequisites.
+apt-get update
+apt-get install -y --no-install-recommends \
+ apt-transport-https \
+ ca-certificates \
+ clang-5.0 \
+ cmake \
+ curl \
+ file \
+ g++ \
+ gdb \
+ git \
+ lld-5.0 \
+ make \
+ python \
+ sudo \
+ xz-utils
+
+# Set up a Clang-based cross compiler toolchain.
+# Based on the steps described at https://nuxi.nl/cloudabi/debian/
+target=$1
+for tool in ar nm objdump ranlib size; do
+ ln -s ../lib/llvm-5.0/bin/llvm-${tool} /usr/bin/${target}-${tool}
+done
+ln -s ../lib/llvm-5.0/bin/clang /usr/bin/${target}-cc
+ln -s ../lib/llvm-5.0/bin/clang /usr/bin/${target}-c++
+ln -s ../lib/llvm-5.0/bin/lld /usr/bin/${target}-ld
+ln -s ../../${target} /usr/lib/llvm-5.0/${target}
+
+# FIXME(EdSchouten): Remove this once cc ≥1.0.4 has been merged. It
+# can make use of ${target}-cc and ${target}-c++, without incorrectly
+# assuming it's MSVC.
+ln -s ../lib/llvm-5.0/bin/clang /usr/bin/${target}-clang
+ln -s ../lib/llvm-5.0/bin/clang /usr/bin/${target}-clang++
+
+# Install the C++ runtime libraries from CloudABI Ports.
+echo deb https://nuxi.nl/distfiles/cloudabi-ports/debian/ cloudabi cloudabi > \
+ /etc/apt/sources.list.d/cloudabi.list
+curl 'https://pgp.mit.edu/pks/lookup?op=get&search=0x0DA51B8531344B15' | \
+ apt-key add -
+apt-get update
+apt-get install -y $(echo ${target} | sed -e s/_/-/g)-cxx-runtime
pkg-config
WORKDIR /build/
-COPY dist-x86_64-musl/build-musl.sh /build/
-RUN sh /build/build-musl.sh && rm -rf /build
+
+COPY scripts/musl.sh /build/
+# We need to mitigate rust-lang/rust#34978 when compiling musl itself as well
+RUN CC=gcc \
+ CFLAGS="-fPIC -Wa,-mrelax-relocations=no" \
+ CXX=g++ \
+ CXXFLAGS="-Wa,-mrelax-relocations=no" \
+ bash musl.sh x86_64 && rm -rf /build
COPY scripts/sccache.sh /scripts/
RUN sh /scripts/sccache.sh
+++ /dev/null
-#!/bin/sh
-# 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.
-
-set -ex
-
-# We need to mitigate rust-lang/rust#34978 when compiling musl itself as well
-export CFLAGS="-fPIC -Wa,-mrelax-relocations=no"
-export CXXFLAGS="-Wa,-mrelax-relocations=no"
-
-MUSL=musl-1.1.17
-curl https://www.musl-libc.org/releases/$MUSL.tar.gz | tar xzf -
-cd $MUSL
-./configure --prefix=/musl-x86_64 --disable-shared
-make -j10
-make install
-
-cd ..
-rm -rf $MUSL
-
-# To build MUSL we're going to need a libunwind lying around, so acquire that
-# here and build it.
-curl -L https://github.com/llvm-mirror/llvm/archive/release_37.tar.gz | tar xzf -
-curl -L https://github.com/llvm-mirror/libunwind/archive/release_37.tar.gz | tar xzf -
-
-mkdir libunwind-build
-cd libunwind-build
-cmake ../libunwind-release_37 -DLLVM_PATH=/build/llvm-release_37 \
- -DLIBUNWIND_ENABLE_SHARED=0
-make -j10
-cp lib/libunwind.a /musl-x86_64/lib
--- /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.
+
+set -ex
+
+hide_output() {
+ set +x
+ on_err="
+echo ERROR: An error was encountered with the build.
+cat /tmp/build.log
+exit 1
+"
+ trap "$on_err" ERR
+ bash -c "while true; do sleep 30; echo \$(date) - building ...; done" &
+ PING_LOOP_PID=$!
+ $@ &> /tmp/build.log
+ trap - ERR
+ kill $PING_LOOP_PID
+ rm /tmp/build.log
+ set -x
+}
+
+TAG=$1
+shift
+
+MUSL=musl-1.1.18
+
+# may have been downloaded in a previous run
+if [ ! -d $MUSL ]; then
+ curl https://www.musl-libc.org/releases/$MUSL.tar.gz | tar xzf -
+fi
+
+cd $MUSL
+./configure --disable-shared --prefix=/musl-$TAG $@
+if [ "$TAG" = "i586" -o "$TAG" = "i686" ]; then
+ hide_output make -j$(nproc) AR=ar RANLIB=ranlib
+else
+ hide_output make -j$(nproc)
+fi
+hide_output make install
+hide_output make clean
+
+cd ..
+
+LLVM=39
+# may have been downloaded in a previous run
+if [ ! -d libunwind-release_$LLVM ]; then
+ curl -L https://github.com/llvm-mirror/llvm/archive/release_$LLVM.tar.gz | tar xzf -
+ curl -L https://github.com/llvm-mirror/libunwind/archive/release_$LLVM.tar.gz | tar xzf -
+ # Whoa what's this mysterious patch we're applying to libunwind! Why are we
+ # swapping the values of ESP/EBP in libunwind?!
+ #
+ # Discovered in #35599 it turns out that the vanilla build of libunwind is not
+ # suitable for unwinding i686 musl. After some investigation it ended up
+ # looking like the register values for ESP/EBP were indeed incorrect (swapped)
+ # in the source. Similar commits in libunwind (r280099 and r282589) have noticed
+ # this for other platforms, and we just need to realize it for musl linux as
+ # well.
+ #
+ # More technical info can be found at #35599
+ cd libunwind-release_$LLVM
+ patch -Np1 << EOF
+diff --git a/include/libunwind.h b/include/libunwind.h
+index c5b9633..1360eb2 100644
+--- a/include/libunwind.h
++++ b/include/libunwind.h
+@@ -151,8 +151,8 @@ enum {
+ UNW_X86_ECX = 1,
+ UNW_X86_EDX = 2,
+ UNW_X86_EBX = 3,
+- UNW_X86_EBP = 4,
+- UNW_X86_ESP = 5,
++ UNW_X86_ESP = 4,
++ UNW_X86_EBP = 5,
+ UNW_X86_ESI = 6,
+ UNW_X86_EDI = 7
+ };
+fi
+EOF
+ cd ..
+fi
+
+mkdir libunwind-build
+cd libunwind-build
+cmake ../libunwind-release_$LLVM \
+ -DLLVM_PATH=/build/llvm-release_$LLVM \
+ -DLIBUNWIND_ENABLE_SHARED=0 \
+ -DCMAKE_C_COMPILER=$CC \
+ -DCMAKE_CXX_COMPILER=$CXX \
+ -DCMAKE_C_FLAGS="$CFLAGS" \
+ -DCMAKE_CXX_FLAGS="$CXXFLAGS"
+
+hide_output make -j$(nproc)
+cp lib/libunwind.a /musl-$TAG/lib
+cd ../ && rm -rf libunwind-build
ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu
ENV RUSTFLAGS -Zincremental=/tmp/rust-incr-cache
ENV RUST_CHECK_TARGET check
+ENV CARGO_INCREMENTAL 0
-Subproject commit 2f7b05fd5939aa49d52c4ab309b9a47776ba7bd8
+Subproject commit fec3182d0b0a3cf8122e192b3270064a5b19be5b
--- /dev/null
+Subproject commit 4ebb8169dfe569b3dcbeab560607800bb717978a
* except according to those terms.
*/
@font-face {
- font-family: 'Fira Sans';
- font-style: normal;
- font-weight: 400;
- src: local('Fira Sans'), url("FiraSans-Regular.woff") format('woff');
+ font-family: 'Fira Sans';
+ font-style: normal;
+ font-weight: 400;
+ src: local('Fira Sans'), url("FiraSans-Regular.woff") format('woff');
}
@font-face {
- font-family: 'Fira Sans';
- font-style: normal;
- font-weight: 500;
- src: local('Fira Sans Medium'), url("FiraSans-Medium.woff") format('woff');
+ font-family: 'Fira Sans';
+ font-style: normal;
+ font-weight: 500;
+ src: local('Fira Sans Medium'), url("FiraSans-Medium.woff") format('woff');
}
@font-face {
- font-family: 'Source Serif Pro';
- font-style: normal;
- font-weight: 400;
- src: local('Source Serif Pro'), url("SourceSerifPro-Regular.woff") format('woff');
+ font-family: 'Source Serif Pro';
+ font-style: normal;
+ font-weight: 400;
+ src: local('Source Serif Pro'), url("SourceSerifPro-Regular.woff") format('woff');
}
@font-face {
- font-family: 'Source Serif Pro';
- font-style: italic;
- font-weight: 400;
- src: url("Heuristica-Italic.woff") format('woff');
+ font-family: 'Source Serif Pro';
+ font-style: italic;
+ font-weight: 400;
+ src: url("Heuristica-Italic.woff") format('woff');
}
@font-face {
- font-family: 'Source Serif Pro';
- font-style: normal;
- font-weight: 700;
- src: local('Source Serif Pro Bold'), url("SourceSerifPro-Bold.woff") format('woff');
+ font-family: 'Source Serif Pro';
+ font-style: normal;
+ font-weight: 700;
+ src: local('Source Serif Pro Bold'), url("SourceSerifPro-Bold.woff") format('woff');
}
@font-face {
- font-family: 'Source Code Pro';
- font-style: normal;
- font-weight: 400;
- /* Avoid using locally installed font because bad versions are in circulation:
- * see https://github.com/rust-lang/rust/issues/24355 */
- src: url("SourceCodePro-Regular.woff") format('woff');
+ font-family: 'Source Code Pro';
+ font-style: normal;
+ font-weight: 400;
+ /* Avoid using locally installed font because bad versions are in circulation:
+ * see https://github.com/rust-lang/rust/issues/24355 */
+ src: url("SourceCodePro-Regular.woff") format('woff');
}
*:not(body) {
-webkit-box-sizing: border-box;
- -moz-box-sizing: border-box;
- box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
}
/* General structure */
body {
- background-color: white;
- margin: 0 auto;
- padding: 0 15px;
- font-family: "Source Serif Pro", Georgia, Times, "Times New Roman", serif;
- font-size: 18px;
- color: #333;
- line-height: 1.428571429;
-
- -webkit-font-feature-settings: "kern", "liga";
- -moz-font-feature-settings: "kern", "liga";
- font-feature-settings: "kern", "liga";
+ background-color: white;
+ margin: 0 auto;
+ padding: 0 15px;
+ font-family: "Source Serif Pro", Georgia, Times, "Times New Roman", serif;
+ font-size: 18px;
+ color: #333;
+ line-height: 1.428571429;
+
+ -webkit-font-feature-settings: "kern", "liga";
+ -moz-font-feature-settings: "kern", "liga";
+ font-feature-settings: "kern", "liga";
}
@media (min-width: 768px) {
- body {
- max-width: 750px;
- }
+ body {
+ max-width: 750px;
+ }
}
h1, h2, h3, h4, h5, h6, nav, #versioninfo {
- font-family: "Fira Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-family: "Fira Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
}
h1, h2, h3, h4, h5, h6 {
- color: black;
- font-weight: 400;
- line-height: 1.1;
+ color: black;
+ font-weight: 400;
+ line-height: 1.1;
}
h1, h2, h3 {
- margin-top: 20px;
- margin-bottom: 15px;
+ margin-top: 20px;
+ margin-bottom: 15px;
}
h1 {
- margin-bottom: 20px;
+ margin-bottom: 20px;
}
h4, h5, h6 {
- margin-top: 12px;
- margin-bottom: 10px;
- padding: 5px 10px;
+ margin-top: 12px;
+ margin-bottom: 10px;
+ padding: 5px 10px;
}
h5, h6 {
- text-decoration: underline;
+ text-decoration: underline;
}
h1 {
- font-size: 28px;
- font-weight: 500;
- padding: .1em .4em;
- border-bottom: 2px solid #ddd;
+ font-size: 28px;
+ font-weight: 500;
+ padding: .1em .4em;
+ border-bottom: 2px solid #ddd;
}
h1.title {
- line-height: 1.5em;
+ line-height: 1.5em;
}
h2 {
- font-size: 26px;
- padding: .2em .5em;
- border-bottom: 1px solid #ddd;
+ font-size: 26px;
+ padding: .2em .5em;
+ border-bottom: 1px solid #ddd;
}
h3 {
- font-size: 24px;
- padding: .2em .7em;
- border-bottom: 1px solid #DDE8FC;
+ font-size: 24px;
+ padding: .2em .7em;
+ border-bottom: 1px solid #DDE8FC;
}
h4 {
- font-size: 22px;
+ font-size: 22px;
}
h5 {
- font-size: 20px;
+ font-size: 20px;
}
h6 {
- font-size: 18px;
+ font-size: 18px;
}
@media (min-width: 992px) {
- h1 {
- font-size: 36px;
- }
- h2 {
- font-size: 30px;
- }
- h3 {
- font-size: 26px;
- }
+ h1 {
+ font-size: 36px;
+ }
+ h2 {
+ font-size: 30px;
+ }
+ h3 {
+ font-size: 26px;
+ }
}
nav {
- column-count: 2;
- -moz-column-count: 2;
- -webkit-column-count: 2;
- font-size: 15px;
- margin: 0 0 1em 0;
+ column-count: 2;
+ -moz-column-count: 2;
+ -webkit-column-count: 2;
+ font-size: 15px;
+ margin: 0 0 1em 0;
}
p {
- margin: 0 0 1em 0;
+ margin: 0 0 1em 0;
}
strong {
- font-weight: bold;
+ font-weight: bold;
}
em {
- font-style: italic;
+ font-style: italic;
}
footer {
- border-top: 1px solid #ddd;
- font-size: 14px;
- font-style: italic;
- padding-top: 5px;
- margin-top: 3em;
- margin-bottom: 1em;
+ border-top: 1px solid #ddd;
+ font-size: 14px;
+ font-style: italic;
+ padding-top: 5px;
+ margin-top: 3em;
+ margin-bottom: 1em;
}
/* Links layout */
a {
- text-decoration: none;
- color: #428BCA;
- background: transparent;
+ text-decoration: none;
+ color: #428BCA;
+ background: transparent;
}
a:hover, a:focus {
- color: #2A6496;
- text-decoration: underline;
+ color: #2A6496;
+ text-decoration: underline;
}
a:focus {
- outline: thin dotted #333;
- outline: 5px auto -webkit-focus-ring-color;
- outline-offset: -2px;
+ outline: thin dotted #333;
+ outline: 5px auto -webkit-focus-ring-color;
+ outline-offset: -2px;
}
a:hover, a:active {
- outline: 0;
+ outline: 0;
}
h1 a:link, h1 a:visited, h2 a:link, h2 a:visited,
/* Code */
pre, code {
- font-family: "Source Code Pro", Menlo, Monaco, Consolas, "DejaVu Sans Mono", monospace;
- word-wrap: break-word;
+ font-family: "Source Code Pro", Menlo, Monaco, Consolas, "DejaVu Sans Mono", monospace;
+ word-wrap: break-word;
}
pre {
- border-left: 2px solid #eee;
- white-space: pre-wrap;
- padding: 14px;
- padding-right: 0;
- margin: 20px 0;
- font-size: 13px;
- word-break: break-all;
+ border-left: 2px solid #eee;
+ white-space: pre-wrap;
+ padding: 14px;
+ padding-right: 0;
+ margin: 20px 0;
+ font-size: 15px;
+ word-break: break-all;
}
code {
- padding: 0 2px;
- color: #8D1A38;
+ padding: 0 2px;
+ color: #8D1A38;
}
pre code {
- padding: 0;
- font-size: inherit;
- color: inherit;
+ padding: 0;
+ font-size: inherit;
+ color: inherit;
}
a > code {
- color: #428BCA;
+ color: #428BCA;
}
.section-header > a > code {
- color: #8D1A38;
+ color: #8D1A38;
}
/* Code highlighting */
/* The rest */
#versioninfo {
- text-align: center;
- margin: 0.5em;
- font-size: 1.1em;
+ text-align: center;
+ margin: 0.5em;
+ font-size: 1.1em;
}
@media (min-width: 992px) {
- #versioninfo {
- font-size: 0.8em;
- position: fixed;
- bottom: 0px;
- right: 0px;
- }
- .white-sticker {
- background-color: #fff;
- margin: 2px;
- padding: 0 2px;
- border-radius: .2em;
- }
+ #versioninfo {
+ font-size: 0.8em;
+ position: fixed;
+ bottom: 0px;
+ right: 0px;
+ }
+ .white-sticker {
+ background-color: #fff;
+ margin: 2px;
+ padding: 0 2px;
+ border-radius: .2em;
+ }
}
#versioninfo a.hash {
- color: gray;
- font-size: 80%;
+ color: gray;
+ font-size: 80%;
}
blockquote {
- color: #000;
- margin: 20px 0;
- padding: 15px 20px;
- background-color: #f2f7f9;
- border-top: .1em solid #e5eef2;
- border-bottom: .1em solid #e5eef2;
+ color: #000;
+ margin: 20px 0;
+ padding: 15px 20px;
+ background-color: #f2f7f9;
+ border-top: .1em solid #e5eef2;
+ border-bottom: .1em solid #e5eef2;
}
blockquote p {
- font-size: 17px;
- font-weight: 300;
- line-height: 1.4;
+ font-size: 17px;
+ font-weight: 300;
+ line-height: 1.4;
}
blockquote p:last-child {
- margin-bottom: 0;
+ margin-bottom: 0;
}
ul, ol {
- padding-left: 25px;
+ padding-left: 25px;
}
ul ul, ol ul, ul ol, ol ol {
- margin-bottom: 0;
+ margin-bottom: 0;
}
dl {
- margin-bottom: 20px;
+ margin-bottom: 20px;
}
dd {
- margin-left: 0;
+ margin-left: 0;
}
nav ul {
- list-style-type: none;
- margin: 0;
- padding-left: 0px;
+ list-style-type: none;
+ margin: 0;
+ padding-left: 0px;
}
/* Only display one level of hierarchy in the TOC */
nav ul ul {
- display: none;
+ display: none;
}
sub,
sup {
- font-size: 75%;
- line-height: 0;
- position: relative;
+ font-size: 75%;
+ line-height: 0;
+ position: relative;
}
hr {
- margin-top: 20px;
- margin-bottom: 20px;
- border: 0;
- border-top: 1px solid #eeeeee;
+ margin-top: 20px;
+ margin-bottom: 20px;
+ border: 0;
+ border-top: 1px solid #eeeeee;
}
table {
- border-collapse: collapse;
- border-spacing: 0;
- overflow-x: auto;
- display: block;
+ border-collapse: collapse;
+ border-spacing: 0;
+ overflow-x: auto;
+ display: block;
}
table tr.odd {
- background: #eee;
+ background: #eee;
}
table td,
table th {
- border: 1px solid #ddd;
- padding: 5px;
+ border: 1px solid #ddd;
+ padding: 5px;
}
/* Code snippets */
pre.rust { position: relative; }
a.test-arrow {
- background-color: rgba(78, 139, 202, 0.2);
- display: inline-block;
- position: absolute;
- color: #f5f5f5;
- padding: 5px 10px 5px 10px;
- border-radius: 5px;
- font-size: 130%;
- top: 5px;
- right: 5px;
+ background-color: rgba(78, 139, 202, 0.2);
+ display: inline-block;
+ position: absolute;
+ color: #f5f5f5;
+ padding: 5px 10px 5px 10px;
+ border-radius: 5px;
+ font-size: 130%;
+ top: 5px;
+ right: 5px;
}
a.test-arrow:hover{
- background-color: #4e8bca;
- text-decoration: none;
+ background-color: #4e8bca;
+ text-decoration: none;
}
.unstable-feature {
- border: 2px solid red;
- padding: 5px;
+ border: 2px solid red;
+ padding: 5px;
}
@media (min-width: 1170px) {
- pre {
- font-size: 15px;
- }
+ pre {
+ font-size: 15px;
+ }
}
@media print {
- * {
- text-shadow: none !important;
- color: #000 !important;
- background: transparent !important;
- box-shadow: none !important;
- }
- a, a:visited {
- text-decoration: underline;
- }
- p a[href]:after {
- content: " (" attr(href) ")";
- }
- footer a[href]:after {
- content: "";
- }
- a[href^="javascript:"]:after, a[href^="#"]:after {
- content: "";
- }
- pre, blockquote {
- border: 1px solid #999;
- page-break-inside: avoid;
- }
- @page {
- margin: 2cm .5cm;
- }
- h1:not(.title), h2, h3 {
- border-bottom: 0px none;
- }
- p, h2, h3 {
- orphans: 3;
- widows: 3;
- }
- h2, h3 {
- page-break-after: avoid;
- }
- table {
- border-collapse: collapse !important;
- }
- table td, table th {
- background-color: #fff !important;
- }
+ * {
+ text-shadow: none !important;
+ color: #000 !important;
+ background: transparent !important;
+ box-shadow: none !important;
+ }
+ a, a:visited {
+ text-decoration: underline;
+ }
+ p a[href]:after {
+ content: " (" attr(href) ")";
+ }
+ footer a[href]:after {
+ content: "";
+ }
+ a[href^="javascript:"]:after, a[href^="#"]:after {
+ content: "";
+ }
+ pre, blockquote {
+ border: 1px solid #999;
+ page-break-inside: avoid;
+ }
+ @page {
+ margin: 2cm .5cm;
+ }
+ h1:not(.title), h2, h3 {
+ border-bottom: 0px none;
+ }
+ p, h2, h3 {
+ orphans: 3;
+ widows: 3;
+ }
+ h2, h3 {
+ page-break-after: avoid;
+ }
+ table {
+ border-collapse: collapse !important;
+ }
+ table td, table th {
+ background-color: #fff !important;
+ }
}
#keyword-table-marker + table thead { display: none; }
#keyword-table-marker + table td { border: none; }
#keyword-table-marker + table {
- margin-left: 2em;
- margin-bottom: 1em;
+ margin-left: 2em;
+ margin-bottom: 1em;
+}
+
+.error-described {
+ position: relative;
+}
+
+.information {
+ position: absolute;
+ left: -25px;
+ margin-top: 7px;
+ z-index: 1;
+}
+
+.tooltip {
+ position: relative;
+ display: inline-block;
+ cursor: pointer;
+}
+
+.tooltip .tooltiptext {
+ width: 120px;
+ display: none;
+ text-align: center;
+ padding: 5px 3px;
+ border-radius: 6px;
+ margin-left: 5px;
+ top: -5px;
+ left: 105%;
+ z-index: 1;
+}
+
+.tooltip:hover .tooltiptext {
+ display: inline;
+}
+
+.tooltip .tooltiptext::after {
+ content: " ";
+ position: absolute;
+ top: 50%;
+ left: 13px;
+ margin-top: -5px;
+ border-width: 5px;
+ border-style: solid;
}
# The `#[doc]` attribute
The `#[doc]` attribute lets you control various aspects of how `rustdoc` does
-its job.
+its job.
The most basic function of `#[doc]` is to handle the actual documentation
text. That is, `///` is syntax sugar for `#[doc]`. This means that these two
}
```
-The documentation will generate a "Reexports" section, and say `pub use bar::Bar;`, where
+The documentation will generate a "Re-exports" section, and say `pub use bar::Bar;`, where
`Bar` is a link to its page.
If we change the `use` line like this:
}
```
-Now we'll have a `Reexports` line, and `Bar` will not link to anywhere.
+Now we'll have a `Re-exports` line, and `Bar` will not link to anywhere.
## `#[doc(hidden)]`
--- /dev/null
+# `crate_in_paths`
+
+The tracking issue for this feature is: [#44660]
+
+[#44660]: https://github.com/rust-lang/rust/issues/44660
+
+------------------------
+
+The `crate_in_paths` feature allows to explicitly refer to the crate root in absolute paths
+using keyword `crate`.
+
+`crate` can be used *only* in absolute paths, i.e. either in `::crate::a::b::c` form or in `use`
+items where the starting `::` is added implicitly.
+Paths like `crate::a::b::c` are not accepted currently.
+
+This feature is required in `feature(extern_absolute_paths)` mode to refer to any absolute path
+in the local crate (absolute paths refer to extern crates by default in that mode), but can be
+used without `feature(extern_absolute_paths)` as well.
+
+```rust
+#![feature(crate_in_paths)]
+
+// Imports, `::` is added implicitly
+use crate::m::f;
+use crate as root;
+
+mod m {
+ pub fn f() -> u8 { 1 }
+ pub fn g() -> u8 { 2 }
+ pub fn h() -> u8 { 3 }
+
+ // OK, visibilities implicitly add starting `::` as well, like imports
+ pub(in crate::m) struct S;
+}
+
+mod n
+{
+ use crate::m::f;
+ use crate as root;
+ pub fn check() {
+ assert_eq!(f(), 1);
+ // `::` is required in non-import paths
+ assert_eq!(::crate::m::g(), 2);
+ assert_eq!(root::m::h(), 3);
+ }
+}
+
+fn main() {
+ assert_eq!(f(), 1);
+ assert_eq!(::crate::m::g(), 2);
+ assert_eq!(root::m::h(), 3);
+ n::check();
+}
+```
--- /dev/null
+# `extern_absolute_paths`
+
+The tracking issue for this feature is: [#44660]
+
+[#44660]: https://github.com/rust-lang/rust/issues/44660
+
+------------------------
+
+The `extern_absolute_paths` feature enables mode allowing to refer to names from other crates
+"inline", without introducing `extern crate` items, using absolute paths like `::my_crate::a::b`.
+
+`::my_crate::a::b` will resolve to path `a::b` in crate `my_crate`.
+
+`feature(crate_in_paths)` can be used in `feature(extern_absolute_paths)` mode for referring
+to absolute paths in the local crate (`::crate::a::b`).
+
+`feature(extern_in_paths)` provides the same effect by using keyword `extern` to refer to
+paths from other crates (`extern::my_crate::a::b`).
+
+```rust,ignore
+#![feature(extern_absolute_paths)]
+
+// Suppose we have a dependency crate `xcrate` available through `Cargo.toml`, or `--extern`
+// options, or standard Rust distribution, or some other means.
+
+use xcrate::Z;
+
+fn f() {
+ use xcrate;
+ use xcrate as ycrate;
+ let s = xcrate::S;
+ assert_eq!(format!("{:?}", s), "S");
+ let z = ycrate::Z;
+ assert_eq!(format!("{:?}", z), "Z");
+}
+
+fn main() {
+ let s = ::xcrate::S;
+ assert_eq!(format!("{:?}", s), "S");
+ let z = Z;
+ assert_eq!(format!("{:?}", z), "Z");
+}
+```
--- /dev/null
+# `extern_in_paths`
+
+The tracking issue for this feature is: [#44660]
+
+[#44660]: https://github.com/rust-lang/rust/issues/44660
+
+------------------------
+
+The `extern_in_paths` feature allows to refer to names from other crates "inline", without
+introducing `extern crate` items, using keyword `extern`.
+
+For example, `extern::my_crat::a::b` will resolve to path `a::b` in crate `my_crate`.
+
+`feature(extern_absolute_paths)` mode provides the same effect by resolving absolute paths like
+`::my_crate::a::b` to paths from extern crates by default.
+
+```rust,ignore
+#![feature(extern_in_paths)]
+
+// Suppose we have a dependency crate `xcrate` available through `Cargo.toml`, or `--extern`
+// options, or standard Rust distribution, or some other means.
+
+use extern::xcrate::Z;
+
+fn f() {
+ use extern::xcrate;
+ use extern::xcrate as ycrate;
+ let s = xcrate::S;
+ assert_eq!(format!("{:?}", s), "S");
+ let z = ycrate::Z;
+ assert_eq!(format!("{:?}", z), "Z");
+}
+
+fn main() {
+ let s = extern::xcrate::S;
+ assert_eq!(format!("{:?}", s), "S");
+ let z = Z;
+ assert_eq!(format!("{:?}", z), "Z");
+}
+```
--- /dev/null
+# `match_default_bindings`
+
+The tracking issue for this feature is: [#42640]
+
+[#42640]: https://github.com/rust-lang/rust/issues/42640
+
+------------------------
+
+Match default bindings (also called "default binding modes in match") improves ergonomics for
+pattern-matching on references by introducing automatic dereferencing (and a corresponding shift
+in binding modes) for large classes of patterns that would otherwise not compile.
+
+For example, under match default bindings,
+
+```rust
+#![feature(match_default_bindings)]
+
+fn main() {
+ let x: &Option<_> = &Some(0);
+
+ match x {
+ Some(y) => {
+ println!("y={}", *y);
+ },
+ None => {},
+ }
+}
+```
+
+compiles and is equivalent to either of the below:
+
+```rust
+fn main() {
+ let x: &Option<_> = &Some(0);
+
+ match *x {
+ Some(ref y) => {
+ println!("y={}", *y);
+ },
+ None => {},
+ }
+}
+```
+
+or
+
+```rust
+fn main() {
+ let x: &Option<_> = &Some(0);
+
+ match x {
+ &Some(ref y) => {
+ println!("y={}", *y);
+ },
+ &None => {},
+ }
+}
+```
+++ /dev/null
-# `match_default_bindings`
-
-The tracking issue for this feature is: [#42640]
-
-[#42640]: https://github.com/rust-lang/rust/issues/42640
-
-------------------------
-
-Match default bindings (also called "default binding modes in match") improves ergonomics for
-pattern-matching on references by introducing automatic dereferencing (and a corresponding shift
-in binding modes) for large classes of patterns that would otherwise not compile.
-
-For example, under match default bindings,
-
-```rust
-#![feature(match_default_bindings)]
-
-fn main() {
- let x: &Option<_> = &Some(0);
-
- match x {
- Some(y) => {
- println!("y={}", *y);
- },
- None => {},
- }
-}
-```
-
-compiles and is equivalent to either of the below:
-
-```rust
-fn main() {
- let x: &Option<_> = &Some(0);
-
- match *x {
- Some(ref y) => {
- println!("y={}", *y);
- },
- None => {},
- }
-}
-```
-
-or
-
-```rust
-fn main() {
- let x: &Option<_> = &Some(0);
-
- match x {
- &Some(ref y) => {
- println!("y={}", *y);
- },
- &None => {},
- }
-}
-```
use core::fmt;
use core::mem;
use core::usize;
-use core::ptr::{self, Unique};
+use core::ptr::{self, NonNull};
/// Represents the combination of a starting address and
/// a total capacity of the returned block.
/// Clients wishing to abort computation in response to an
/// allocation error are encouraged to call the allocator's `oom`
/// method, rather than directly invoking `panic!` or similar.
- fn alloc_one<T>(&mut self) -> Result<Unique<T>, AllocErr>
+ fn alloc_one<T>(&mut self) -> Result<NonNull<T>, AllocErr>
where Self: Sized
{
let k = Layout::new::<T>();
if k.size() > 0 {
- unsafe { self.alloc(k).map(|p| Unique::new_unchecked(p as *mut T)) }
+ unsafe { self.alloc(k).map(|p| NonNull::new_unchecked(p as *mut T)) }
} else {
Err(AllocErr::invalid_input("zero-sized type invalid for alloc_one"))
}
/// * `ptr` must denote a block of memory currently allocated via this allocator
///
/// * the layout of `T` must *fit* that block of memory.
- unsafe fn dealloc_one<T>(&mut self, ptr: Unique<T>)
+ unsafe fn dealloc_one<T>(&mut self, ptr: NonNull<T>)
where Self: Sized
{
let raw_ptr = ptr.as_ptr() as *mut u8;
/// Clients wishing to abort computation in response to an
/// allocation error are encouraged to call the allocator's `oom`
/// method, rather than directly invoking `panic!` or similar.
- fn alloc_array<T>(&mut self, n: usize) -> Result<Unique<T>, AllocErr>
+ fn alloc_array<T>(&mut self, n: usize) -> Result<NonNull<T>, AllocErr>
where Self: Sized
{
match Layout::array::<T>(n) {
unsafe {
self.alloc(layout.clone())
.map(|p| {
- Unique::new_unchecked(p as *mut T)
+ NonNull::new_unchecked(p as *mut T)
})
}
}
/// reallocation error are encouraged to call the allocator's `oom`
/// method, rather than directly invoking `panic!` or similar.
unsafe fn realloc_array<T>(&mut self,
- ptr: Unique<T>,
+ ptr: NonNull<T>,
n_old: usize,
- n_new: usize) -> Result<Unique<T>, AllocErr>
+ n_new: usize) -> Result<NonNull<T>, AllocErr>
where Self: Sized
{
match (Layout::array::<T>(n_old), Layout::array::<T>(n_new), ptr.as_ptr()) {
(Some(ref k_old), Some(ref k_new), ptr) if k_old.size() > 0 && k_new.size() > 0 => {
self.realloc(ptr as *mut u8, k_old.clone(), k_new.clone())
- .map(|p|Unique::new_unchecked(p as *mut T))
+ .map(|p| NonNull::new_unchecked(p as *mut T))
}
_ => {
Err(AllocErr::invalid_input("invalid layout for realloc_array"))
/// constraints.
///
/// Always returns `Err` on arithmetic overflow.
- unsafe fn dealloc_array<T>(&mut self, ptr: Unique<T>, n: usize) -> Result<(), AllocErr>
+ unsafe fn dealloc_array<T>(&mut self, ptr: NonNull<T>, n: usize) -> Result<(), AllocErr>
where Self: Sized
{
let raw_ptr = ptr.as_ptr() as *mut u8;
use core::mem::{self, align_of_val, size_of_val, uninitialized};
use core::ops::Deref;
use core::ops::CoerceUnsized;
-use core::ptr::{self, Shared};
+use core::ptr::{self, NonNull};
use core::marker::{Unsize, PhantomData};
use core::hash::{Hash, Hasher};
use core::{isize, usize};
/// [rc_examples]: ../../std/rc/index.html#examples
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Arc<T: ?Sized> {
- ptr: Shared<ArcInner<T>>,
+ ptr: NonNull<ArcInner<T>>,
phantom: PhantomData<T>,
}
/// [`None`]: ../../std/option/enum.Option.html#variant.None
#[stable(feature = "arc_weak", since = "1.4.0")]
pub struct Weak<T: ?Sized> {
- ptr: Shared<ArcInner<T>>,
+ ptr: NonNull<ArcInner<T>>,
}
#[stable(feature = "arc_weak", since = "1.4.0")]
weak: atomic::AtomicUsize::new(1),
data,
};
- Arc { ptr: Shared::from(Box::into_unique(x)), phantom: PhantomData }
+ Arc { ptr: Box::into_raw_non_null(x), phantom: PhantomData }
}
/// Returns the contained value, if the `Arc` has exactly one strong reference.
let arc_ptr = set_data_ptr(fake_ptr, (ptr as *mut u8).offset(-offset));
Arc {
- ptr: Shared::new_unchecked(arc_ptr),
+ ptr: NonNull::new_unchecked(arc_ptr),
phantom: PhantomData,
}
}
// Free the allocation without dropping its contents
box_free(bptr);
- Arc { ptr: Shared::new_unchecked(ptr), phantom: PhantomData }
+ Arc { ptr: NonNull::new_unchecked(ptr), phantom: PhantomData }
}
}
}
&mut (*ptr).data as *mut [T] as *mut T,
v.len());
- Arc { ptr: Shared::new_unchecked(ptr), phantom: PhantomData }
+ Arc { ptr: NonNull::new_unchecked(ptr), phantom: PhantomData }
}
}
// All clear. Forget the guard so it doesn't free the new ArcInner.
mem::forget(guard);
- Arc { ptr: Shared::new_unchecked(ptr), phantom: PhantomData }
+ Arc { ptr: NonNull::new_unchecked(ptr), phantom: PhantomData }
}
}
}
pub fn new() -> Weak<T> {
unsafe {
Weak {
- ptr: Shared::from(Box::into_unique(box ArcInner {
+ ptr: Box::into_raw_non_null(box ArcInner {
strong: atomic::AtomicUsize::new(0),
weak: atomic::AtomicUsize::new(1),
data: uninitialized(),
- })),
+ }),
}
}
}
fn $name(b: &mut Bencher) {
let size = mem::size_of_val(&$gen(1)[0]);
let mut v = $gen($len * 8 / size);
- b.iter(|| black_box(&mut v).rotate(($mid*8+size-1)/size));
+ b.iter(|| black_box(&mut v).rotate_left(($mid*8+size-1)/size));
b.bytes = (v.len() * size) as u64;
}
}
use core::mem;
use core::ops::{CoerceUnsized, Deref, DerefMut, Generator, GeneratorState};
use core::ops::{BoxPlace, Boxed, InPlace, Place, Placer};
-use core::ptr::{self, Unique};
+use core::ptr::{self, NonNull, Unique};
use core::convert::From;
use str::from_boxed_utf8_unchecked;
#[stable(feature = "box_raw", since = "1.4.0")]
#[inline]
pub unsafe fn from_raw(raw: *mut T) -> Self {
- Box::from_unique(Unique::new_unchecked(raw))
- }
-
- /// Constructs a `Box` from a `Unique<T>` pointer.
- ///
- /// After calling this function, the memory is owned by a `Box` and `T` can
- /// then be destroyed and released upon drop.
- ///
- /// # Safety
- ///
- /// A `Unique<T>` can be safely created via [`Unique::new`] and thus doesn't
- /// necessarily own the data pointed to nor is the data guaranteed to live
- /// as long as the pointer.
- ///
- /// [`Unique::new`]: ../../core/ptr/struct.Unique.html#method.new
- ///
- /// # Examples
- ///
- /// ```
- /// #![feature(unique)]
- ///
- /// fn main() {
- /// let x = Box::new(5);
- /// let ptr = Box::into_unique(x);
- /// let x = unsafe { Box::from_unique(ptr) };
- /// }
- /// ```
- #[unstable(feature = "unique", reason = "needs an RFC to flesh out design",
- issue = "27730")]
- #[inline]
- pub unsafe fn from_unique(u: Unique<T>) -> Self {
- Box(u)
+ Box(Unique::new_unchecked(raw))
}
/// Consumes the `Box`, returning the wrapped raw pointer.
#[stable(feature = "box_raw", since = "1.4.0")]
#[inline]
pub fn into_raw(b: Box<T>) -> *mut T {
- Box::into_unique(b).as_ptr()
+ Box::into_raw_non_null(b).as_ptr()
}
- /// Consumes the `Box`, returning the wrapped pointer as `Unique<T>`.
+ /// Consumes the `Box`, returning the wrapped pointer as `NonNull<T>`.
///
/// After calling this function, the caller is responsible for the
/// memory previously managed by the `Box`. In particular, the
/// caller should properly destroy `T` and release the memory. The
- /// proper way to do so is to either convert the `Unique<T>` pointer:
- ///
- /// - Into a `Box` with the [`Box::from_unique`] function.
- ///
- /// - Into a raw pointer and back into a `Box` with the [`Box::from_raw`]
- /// function.
+ /// proper way to do so is to convert the `NonNull<T>` pointer
+ /// into a raw pointer and back into a `Box` with the [`Box::from_raw`]
+ /// function.
///
/// Note: this is an associated function, which means that you have
- /// to call it as `Box::into_unique(b)` instead of `b.into_unique()`. This
+ /// to call it as `Box::into_raw_non_null(b)`
+ /// instead of `b.into_raw_non_null()`. This
/// is so that there is no conflict with a method on the inner type.
///
- /// [`Box::from_unique`]: struct.Box.html#method.from_unique
/// [`Box::from_raw`]: struct.Box.html#method.from_raw
///
/// # Examples
///
/// ```
- /// #![feature(unique)]
+ /// #![feature(box_into_raw_non_null)]
///
/// fn main() {
/// let x = Box::new(5);
- /// let ptr = Box::into_unique(x);
+ /// let ptr = Box::into_raw_non_null(x);
/// }
/// ```
- #[unstable(feature = "unique", reason = "needs an RFC to flesh out design",
- issue = "27730")]
+ #[unstable(feature = "box_into_raw_non_null", issue = "47336")]
+ #[inline]
+ pub fn into_raw_non_null(b: Box<T>) -> NonNull<T> {
+ Box::into_unique(b).into()
+ }
+
+ #[unstable(feature = "ptr_internals", issue = "0", reason = "use into_raw_non_null instead")]
#[inline]
pub fn into_unique(b: Box<T>) -> Unique<T> {
let unique = b.0;
pub fn new() -> BTreeSet<T> {
BTreeSet { map: BTreeMap::new() }
}
-}
-impl<T> BTreeSet<T> {
- /// Gets an iterator that visits the values in the `BTreeSet` in ascending order.
- ///
- /// # Examples
- ///
- /// ```
- /// use std::collections::BTreeSet;
- ///
- /// let set: BTreeSet<usize> = [1, 2, 3].iter().cloned().collect();
- /// let mut set_iter = set.iter();
- /// assert_eq!(set_iter.next(), Some(&1));
- /// assert_eq!(set_iter.next(), Some(&2));
- /// assert_eq!(set_iter.next(), Some(&3));
- /// assert_eq!(set_iter.next(), None);
- /// ```
- ///
- /// Values returned by the iterator are returned in ascending order:
- ///
- /// ```
- /// use std::collections::BTreeSet;
- ///
- /// let set: BTreeSet<usize> = [3, 1, 2].iter().cloned().collect();
- /// let mut set_iter = set.iter();
- /// assert_eq!(set_iter.next(), Some(&1));
- /// assert_eq!(set_iter.next(), Some(&2));
- /// assert_eq!(set_iter.next(), Some(&3));
- /// assert_eq!(set_iter.next(), None);
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
- pub fn iter(&self) -> Iter<T> {
- Iter { iter: self.map.keys() }
- }
-}
-
-impl<T: Ord> BTreeSet<T> {
/// Constructs a double-ended iterator over a sub-range of elements in the set.
/// The simplest way is to use the range syntax `min..max`, thus `range(min..max)` will
/// yield elements from min (inclusive) to max (exclusive).
{
Range { iter: self.map.range(range) }
}
-}
-impl<T: Ord> BTreeSet<T> {
/// Visits the values representing the difference,
/// i.e. the values that are in `self` but not in `other`,
/// in ascending order.
}
}
- /// Returns the number of elements in the set.
- ///
- /// # Examples
- ///
- /// ```
- /// use std::collections::BTreeSet;
- ///
- /// let mut v = BTreeSet::new();
- /// assert_eq!(v.len(), 0);
- /// v.insert(1);
- /// assert_eq!(v.len(), 1);
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
- pub fn len(&self) -> usize {
- self.map.len()
- }
-
- /// Returns `true` if the set contains no elements.
- ///
- /// # Examples
- ///
- /// ```
- /// use std::collections::BTreeSet;
- ///
- /// let mut v = BTreeSet::new();
- /// assert!(v.is_empty());
- /// v.insert(1);
- /// assert!(!v.is_empty());
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
- pub fn is_empty(&self) -> bool {
- self.len() == 0
- }
-
/// Clears the set, removing all values.
///
/// # Examples
/// The value may be any borrowed form of the set's value type,
/// but the ordering on the borrowed form *must* match the
/// ordering on the value type.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::collections::BTreeSet;
+ ///
+ /// let set: BTreeSet<_> = [1, 2, 3].iter().cloned().collect();
+ /// assert_eq!(set.get(&2), Some(&2));
+ /// assert_eq!(set.get(&4), None);
+ /// ```
#[stable(feature = "set_recovery", since = "1.9.0")]
pub fn get<Q: ?Sized>(&self, value: &Q) -> Option<&T>
where T: Borrow<Q>,
/// Adds a value to the set, replacing the existing value, if any, that is equal to the given
/// one. Returns the replaced value.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::collections::BTreeSet;
+ ///
+ /// let mut set = BTreeSet::new();
+ /// set.insert(Vec::<i32>::new());
+ ///
+ /// assert_eq!(set.get(&[][..]).unwrap().capacity(), 0);
+ /// set.replace(Vec::with_capacity(10));
+ /// assert_eq!(set.get(&[][..]).unwrap().capacity(), 10);
+ /// ```
#[stable(feature = "set_recovery", since = "1.9.0")]
pub fn replace(&mut self, value: T) -> Option<T> {
Recover::replace(&mut self.map, value)
/// The value may be any borrowed form of the set's value type,
/// but the ordering on the borrowed form *must* match the
/// ordering on the value type.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::collections::BTreeSet;
+ ///
+ /// let mut set: BTreeSet<_> = [1, 2, 3].iter().cloned().collect();
+ /// assert_eq!(set.take(&2), Some(2));
+ /// assert_eq!(set.take(&2), None);
+ /// ```
#[stable(feature = "set_recovery", since = "1.9.0")]
pub fn take<Q: ?Sized>(&mut self, value: &Q) -> Option<T>
where T: Borrow<Q>,
}
}
+impl<T> BTreeSet<T> {
+ /// Gets an iterator that visits the values in the `BTreeSet` in ascending order.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::collections::BTreeSet;
+ ///
+ /// let set: BTreeSet<usize> = [1, 2, 3].iter().cloned().collect();
+ /// let mut set_iter = set.iter();
+ /// assert_eq!(set_iter.next(), Some(&1));
+ /// assert_eq!(set_iter.next(), Some(&2));
+ /// assert_eq!(set_iter.next(), Some(&3));
+ /// assert_eq!(set_iter.next(), None);
+ /// ```
+ ///
+ /// Values returned by the iterator are returned in ascending order:
+ ///
+ /// ```
+ /// use std::collections::BTreeSet;
+ ///
+ /// let set: BTreeSet<usize> = [3, 1, 2].iter().cloned().collect();
+ /// let mut set_iter = set.iter();
+ /// assert_eq!(set_iter.next(), Some(&1));
+ /// assert_eq!(set_iter.next(), Some(&2));
+ /// assert_eq!(set_iter.next(), Some(&3));
+ /// assert_eq!(set_iter.next(), None);
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn iter(&self) -> Iter<T> {
+ Iter { iter: self.map.keys() }
+ }
+
+ /// Returns the number of elements in the set.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::collections::BTreeSet;
+ ///
+ /// let mut v = BTreeSet::new();
+ /// assert_eq!(v.len(), 0);
+ /// v.insert(1);
+ /// assert_eq!(v.len(), 1);
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn len(&self) -> usize {
+ self.map.len()
+ }
+
+ /// Returns `true` if the set contains no elements.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::collections::BTreeSet;
+ ///
+ /// let mut v = BTreeSet::new();
+ /// assert!(v.is_empty());
+ /// v.insert(1);
+ /// assert!(!v.is_empty());
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn is_empty(&self) -> bool {
+ self.len() == 0
+ }
+}
+
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: Ord> FromIterator<T> for BTreeSet<T> {
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> BTreeSet<T> {
///
/// 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", reason = "Use Unique/Shared::empty() instead")]
+#[rustc_deprecated(since = "1.19", reason = "Use Unique/NonNull::empty() instead")]
#[unstable(feature = "heap_api", issue = "27700")]
pub const EMPTY: *mut () = 1 as *mut ();
//!
//! This library, like libcore, is not intended for general usage, but rather as
//! a building block of other libraries. The types and interfaces in this
-//! library are reexported through the [standard library](../std/index.html),
+//! library are re-exported through the [standard library](../std/index.html),
//! and should not be used through this library.
//!
//! ## Boxed values
//! ## Collections
//!
//! Implementations of the most common general purpose data structures are
-//! defined in this library. They are reexported through the
+//! defined in this library. They are re-exported through the
//! [standard collections library](../std/collections/index.html).
//!
//! ## Heap interfaces
#![cfg_attr(test, feature(rand, test))]
#![feature(allow_internal_unstable)]
#![feature(ascii_ctype)]
+#![feature(box_into_raw_non_null)]
#![feature(box_patterns)]
#![feature(box_syntax)]
#![feature(cfg_target_has_atomic)]
#![feature(pattern)]
#![feature(placement_in_syntax)]
#![feature(placement_new_protocol)]
+#![feature(ptr_internals)]
#![feature(rustc_attrs)]
-#![feature(shared)]
#![feature(slice_get_slice)]
#![feature(slice_patterns)]
#![feature(slice_rsplit)]
#![feature(trusted_len)]
#![feature(unboxed_closures)]
#![feature(unicode)]
-#![feature(unique)]
#![feature(unsize)]
#![feature(allocator_internals)]
#![feature(on_unimplemented)]
+#![feature(exact_chunks)]
#![cfg_attr(not(test), feature(fused, fn_traits, placement_new_protocol, swap_with_slice, i128))]
#![cfg_attr(test, feature(test, box_heap))]
use core::marker::PhantomData;
use core::mem;
use core::ops::{BoxPlace, InPlace, Place, Placer};
-use core::ptr::{self, Shared};
+use core::ptr::{self, NonNull};
use boxed::{Box, IntermediateBox};
use super::SpecExtend;
/// more memory efficient and make better use of CPU cache.
#[stable(feature = "rust1", since = "1.0.0")]
pub struct LinkedList<T> {
- head: Option<Shared<Node<T>>>,
- tail: Option<Shared<Node<T>>>,
+ head: Option<NonNull<Node<T>>>,
+ tail: Option<NonNull<Node<T>>>,
len: usize,
marker: PhantomData<Box<Node<T>>>,
}
struct Node<T> {
- next: Option<Shared<Node<T>>>,
- prev: Option<Shared<Node<T>>>,
+ next: Option<NonNull<Node<T>>>,
+ prev: Option<NonNull<Node<T>>>,
element: T,
}
/// [`LinkedList`]: struct.LinkedList.html
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Iter<'a, T: 'a> {
- head: Option<Shared<Node<T>>>,
- tail: Option<Shared<Node<T>>>,
+ head: Option<NonNull<Node<T>>>,
+ tail: Option<NonNull<Node<T>>>,
len: usize,
marker: PhantomData<&'a Node<T>>,
}
#[stable(feature = "rust1", since = "1.0.0")]
pub struct IterMut<'a, T: 'a> {
list: &'a mut LinkedList<T>,
- head: Option<Shared<Node<T>>>,
- tail: Option<Shared<Node<T>>>,
+ head: Option<NonNull<Node<T>>>,
+ tail: Option<NonNull<Node<T>>>,
len: usize,
}
unsafe {
node.next = self.head;
node.prev = None;
- let node = Some(Shared::from(Box::into_unique(node)));
+ let node = Some(Box::into_raw_non_null(node));
match self.head {
None => self.tail = node,
unsafe {
node.next = None;
node.prev = self.tail;
- let node = Some(Shared::from(Box::into_unique(node)));
+ let node = Some(Box::into_raw_non_null(node));
match self.tail {
None => self.head = node,
///
/// Warning: this will not check that the provided node belongs to the current list.
#[inline]
- unsafe fn unlink_node(&mut self, mut node: Shared<Node<T>>) {
+ unsafe fn unlink_node(&mut self, mut node: NonNull<Node<T>>) {
let node = node.as_mut();
match node.prev {
Some(prev) => prev,
};
- let node = Some(Shared::from(Box::into_unique(box Node {
+ let node = Some(Box::into_raw_non_null(box Node {
next: Some(head),
prev: Some(prev),
element,
- })));
+ }));
prev.as_mut().next = node;
head.as_mut().prev = node;
where F: FnMut(&mut T) -> bool,
{
list: &'a mut LinkedList<T>,
- it: Option<Shared<Node<T>>>,
+ it: Option<NonNull<Node<T>>>,
pred: F,
idx: usize,
old_len: usize,
// would cause overflow
let new_cap = if elem_size > (!0) / 8 { 1 } else { 4 };
match self.a.alloc_array::<T>(new_cap) {
- Ok(ptr) => (new_cap, ptr),
+ Ok(ptr) => (new_cap, ptr.into()),
Err(e) => self.a.oom(e),
}
}
use core::mem::{self, align_of_val, forget, size_of_val, uninitialized};
use core::ops::Deref;
use core::ops::CoerceUnsized;
-use core::ptr::{self, Shared};
+use core::ptr::{self, NonNull};
use core::convert::From;
use heap::{Heap, Alloc, Layout, box_free};
/// [get_mut]: #method.get_mut
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Rc<T: ?Sized> {
- ptr: Shared<RcBox<T>>,
+ ptr: NonNull<RcBox<T>>,
phantom: PhantomData<T>,
}
// pointers, which ensures that the weak destructor never frees
// the allocation while the strong destructor is running, even
// if the weak pointer is stored inside the strong one.
- ptr: Shared::from(Box::into_unique(box RcBox {
+ ptr: Box::into_raw_non_null(box RcBox {
strong: Cell::new(1),
weak: Cell::new(1),
value,
- })),
+ }),
phantom: PhantomData,
}
}
let rc_ptr = set_data_ptr(fake_ptr, (ptr as *mut u8).offset(-offset));
Rc {
- ptr: Shared::new_unchecked(rc_ptr),
+ ptr: NonNull::new_unchecked(rc_ptr),
phantom: PhantomData,
}
}
let raw: *const RcBox<Any> = self.ptr.as_ptr();
forget(self);
Ok(Rc {
- ptr: Shared::new_unchecked(raw as *const RcBox<T> as *mut _),
+ ptr: NonNull::new_unchecked(raw as *const RcBox<T> as *mut _),
phantom: PhantomData,
})
}
// Free the allocation without dropping its contents
box_free(bptr);
- Rc { ptr: Shared::new_unchecked(ptr), phantom: PhantomData }
+ Rc { ptr: NonNull::new_unchecked(ptr), phantom: PhantomData }
}
}
}
&mut (*ptr).value as *mut [T] as *mut T,
v.len());
- Rc { ptr: Shared::new_unchecked(ptr), phantom: PhantomData }
+ Rc { ptr: NonNull::new_unchecked(ptr), phantom: PhantomData }
}
}
// All clear. Forget the guard so it doesn't free the new RcBox.
forget(guard);
- Rc { ptr: Shared::new_unchecked(ptr), phantom: PhantomData }
+ Rc { ptr: NonNull::new_unchecked(ptr), phantom: PhantomData }
}
}
}
/// [`None`]: ../../std/option/enum.Option.html#variant.None
#[stable(feature = "rc_weak", since = "1.4.0")]
pub struct Weak<T: ?Sized> {
- ptr: Shared<RcBox<T>>,
+ ptr: NonNull<RcBox<T>>,
}
#[stable(feature = "rc_weak", since = "1.4.0")]
pub fn new() -> Weak<T> {
unsafe {
Weak {
- ptr: Shared::from(Box::into_unique(box RcBox {
+ ptr: Box::into_raw_non_null(box RcBox {
strong: Cell::new(0),
weak: Cell::new(1),
value: uninitialized(),
- })),
+ }),
}
}
}
pub use core::slice::{from_ref, from_ref_mut};
#[unstable(feature = "slice_get_slice", issue = "35729")]
pub use core::slice::SliceIndex;
+#[unstable(feature = "exact_chunks", issue = "47115")]
+pub use core::slice::{ExactChunks, ExactChunksMut};
////////////////////////////////////////////////////////////////////////////////
// Basic slice extension methods
/// not divide the length of the slice, then the last chunk will
/// not have length `chunk_size`.
///
+ /// See [`exact_chunks`] for a variant of this iterator that returns chunks
+ /// of always exactly `chunk_size` elements.
+ ///
/// # Panics
///
/// Panics if `chunk_size` is 0.
core_slice::SliceExt::chunks(self, chunk_size)
}
+ /// Returns an iterator over `chunk_size` elements of the slice at a
+ /// time. The chunks are slices and do not overlap. If `chunk_size` does
+ /// not divide the length of the slice, then the last up to `chunk_size-1`
+ /// elements will be omitted.
+ ///
+ /// Due to each chunk having exactly `chunk_size` elements, the compiler
+ /// can often optimize the resulting code better than in the case of
+ /// [`chunks`].
+ ///
+ /// # Panics
+ ///
+ /// Panics if `chunk_size` is 0.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(exact_chunks)]
+ ///
+ /// let slice = ['l', 'o', 'r', 'e', 'm'];
+ /// let mut iter = slice.exact_chunks(2);
+ /// assert_eq!(iter.next().unwrap(), &['l', 'o']);
+ /// assert_eq!(iter.next().unwrap(), &['r', 'e']);
+ /// assert!(iter.next().is_none());
+ /// ```
+ #[unstable(feature = "exact_chunks", issue = "47115")]
+ #[inline]
+ pub fn exact_chunks(&self, chunk_size: usize) -> ExactChunks<T> {
+ core_slice::SliceExt::exact_chunks(self, chunk_size)
+ }
+
/// Returns an iterator over `chunk_size` elements of the slice at a time.
/// The chunks are mutable slices, and do not overlap. If `chunk_size` does
/// not divide the length of the slice, then the last chunk will not
/// have length `chunk_size`.
///
+ /// See [`exact_chunks_mut`] for a variant of this iterator that returns chunks
+ /// of always exactly `chunk_size` elements.
+ ///
/// # Panics
///
/// Panics if `chunk_size` is 0.
core_slice::SliceExt::chunks_mut(self, chunk_size)
}
+ /// Returns an iterator over `chunk_size` elements of the slice at a time.
+ /// The chunks are mutable slices, and do not overlap. If `chunk_size` does
+ /// not divide the length of the slice, then the last up to `chunk_size-1`
+ /// elements will be omitted.
+ ///
+ ///
+ /// Due to each chunk having exactly `chunk_size` elements, the compiler
+ /// can often optimize the resulting code better than in the case of
+ /// [`chunks_mut`].
+ ///
+ /// # Panics
+ ///
+ /// Panics if `chunk_size` is 0.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(exact_chunks)]
+ ///
+ /// let v = &mut [0, 0, 0, 0, 0];
+ /// let mut count = 1;
+ ///
+ /// for chunk in v.exact_chunks_mut(2) {
+ /// for elem in chunk.iter_mut() {
+ /// *elem += count;
+ /// }
+ /// count += 1;
+ /// }
+ /// assert_eq!(v, &[1, 1, 2, 2, 0]);
+ /// ```
+ #[unstable(feature = "exact_chunks", issue = "47115")]
+ #[inline]
+ pub fn exact_chunks_mut(&mut self, chunk_size: usize) -> ExactChunksMut<T> {
+ core_slice::SliceExt::exact_chunks_mut(self, chunk_size)
+ }
+
/// Divides one slice into two at an index.
///
/// The first will contain all indices from `[0, mid)` (excluding
core_slice::SliceExt::sort_unstable_by_key(self, f);
}
- /// Permutes the slice in-place such that `self[mid..]` moves to the
- /// beginning of the slice while `self[..mid]` moves to the end of the
- /// slice. Equivalently, rotates the slice `mid` places to the left
- /// or `k = self.len() - mid` places to the right.
+ /// Rotates the slice in-place such that the first `mid` elements of the
+ /// slice move to the end while the last `self.len() - mid` elements move to
+ /// the front. After calling `rotate_left`, the element previously at index
+ /// `mid` will become the first element in the slice.
///
- /// This is a "k-rotation", a permutation in which item `i` moves to
- /// position `i + k`, modulo the length of the slice. See _Elements
- /// of Programming_ [§10.4][eop].
+ /// # Panics
///
- /// Rotation by `mid` and rotation by `k` are inverse operations.
+ /// This function will panic if `mid` is greater than the length of the
+ /// slice. Note that `mid == self.len()` does _not_ panic and is a no-op
+ /// rotation.
///
- /// [eop]: https://books.google.com/books?id=CO9ULZGINlsC&pg=PA178&q=k-rotation
+ /// # Complexity
+ ///
+ /// Takes linear (in `self.len()`) time.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(slice_rotate)]
+ ///
+ /// let mut a = ['a', 'b', 'c', 'd', 'e', 'f'];
+ /// a.rotate_left(2);
+ /// assert_eq!(a, ['c', 'd', 'e', 'f', 'a', 'b']);
+ /// ```
+ ///
+ /// Rotating a subslice:
+ ///
+ /// ```
+ /// #![feature(slice_rotate)]
+ ///
+ /// let mut a = ['a', 'b', 'c', 'd', 'e', 'f'];
+ /// a[1..5].rotate_left(1);
+ /// assert_eq!(a, ['a', 'c', 'd', 'e', 'b', 'f']);
+ /// ```
+ #[unstable(feature = "slice_rotate", issue = "41891")]
+ pub fn rotate_left(&mut self, mid: usize) {
+ core_slice::SliceExt::rotate_left(self, mid);
+ }
+
+ #[unstable(feature = "slice_rotate", issue = "41891")]
+ #[rustc_deprecated(since = "", reason = "renamed to `rotate_left`")]
+ pub fn rotate(&mut self, mid: usize) {
+ core_slice::SliceExt::rotate_left(self, mid);
+ }
+
+ /// Rotates the slice in-place such that the first `self.len() - k`
+ /// elements of the slice move to the end while the last `k` elements move
+ /// to the front. After calling `rotate_right`, the element previously at
+ /// index `self.len() - k` will become the first element in the slice.
///
/// # Panics
///
- /// This function will panic if `mid` is greater than the length of the
- /// slice. (Note that `mid == self.len()` does _not_ panic; it's a nop
- /// rotation with `k == 0`, the inverse of a rotation with `mid == 0`.)
+ /// This function will panic if `k` is greater than the length of the
+ /// slice. Note that `k == self.len()` does _not_ panic and is a no-op
+ /// rotation.
///
/// # Complexity
///
/// ```
/// #![feature(slice_rotate)]
///
- /// let mut a = [1, 2, 3, 4, 5, 6, 7];
- /// let mid = 2;
- /// a.rotate(mid);
- /// assert_eq!(&a, &[3, 4, 5, 6, 7, 1, 2]);
- /// let k = a.len() - mid;
- /// a.rotate(k);
- /// assert_eq!(&a, &[1, 2, 3, 4, 5, 6, 7]);
- ///
- /// use std::ops::Range;
- /// fn slide<T>(slice: &mut [T], range: Range<usize>, to: usize) {
- /// if to < range.start {
- /// slice[to..range.end].rotate(range.start-to);
- /// } else if to > range.end {
- /// slice[range.start..to].rotate(range.end-range.start);
- /// }
- /// }
- /// let mut v: Vec<_> = (0..10).collect();
- /// slide(&mut v, 1..4, 7);
- /// assert_eq!(&v, &[0, 4, 5, 6, 1, 2, 3, 7, 8, 9]);
- /// slide(&mut v, 6..8, 1);
- /// assert_eq!(&v, &[0, 3, 7, 4, 5, 6, 1, 2, 8, 9]);
+ /// let mut a = ['a', 'b', 'c', 'd', 'e', 'f'];
+ /// a.rotate_right(2);
+ /// assert_eq!(a, ['e', 'f', 'a', 'b', 'c', 'd']);
+ /// ```
+ ///
+ /// Rotate a subslice:
+ ///
+ /// ```
+ /// #![feature(slice_rotate)]
+ ///
+ /// let mut a = ['a', 'b', 'c', 'd', 'e', 'f'];
+ /// a[1..5].rotate_right(1);
+ /// assert_eq!(a, ['a', 'e', 'b', 'c', 'd', 'f']);
/// ```
#[unstable(feature = "slice_rotate", issue = "41891")]
- pub fn rotate(&mut self, mid: usize) {
- core_slice::SliceExt::rotate(self, mid);
+ pub fn rotate_right(&mut self, k: usize) {
+ core_slice::SliceExt::rotate_right(self, k);
}
/// Copies the elements from `src` into `self`.
/// let x = s.to_vec();
/// // Here, `s` and `x` can be modified independently.
/// ```
+ #[rustc_conversion_suggestion]
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn to_vec(&self) -> Vec<T>
///
/// assert_eq!(five, i.to_string());
/// ```
+ #[rustc_conversion_suggestion]
#[stable(feature = "rust1", since = "1.0.0")]
fn to_string(&self) -> String;
}
#![feature(string_retain)]
#![feature(unboxed_closures)]
#![feature(unicode)]
+#![feature(exact_chunks)]
extern crate alloc_system;
extern crate std_unicode;
}
#[test]
-fn test_rotate() {
+fn test_rotate_left() {
let expected: Vec<_> = (0..13).collect();
let mut v = Vec::new();
// no-ops
v.clone_from(&expected);
- v.rotate(0);
+ v.rotate_left(0);
assert_eq!(v, expected);
- v.rotate(expected.len());
+ v.rotate_left(expected.len());
assert_eq!(v, expected);
let mut zst_array = [(), (), ()];
- zst_array.rotate(2);
+ zst_array.rotate_left(2);
// happy path
v = (5..13).chain(0..5).collect();
- v.rotate(8);
+ v.rotate_left(8);
assert_eq!(v, expected);
let expected: Vec<_> = (0..1000).collect();
// small rotations in large slice, uses ptr::copy
v = (2..1000).chain(0..2).collect();
- v.rotate(998);
+ v.rotate_left(998);
assert_eq!(v, expected);
v = (998..1000).chain(0..998).collect();
- v.rotate(2);
+ v.rotate_left(2);
assert_eq!(v, expected);
// non-small prime rotation, has a few rounds of swapping
v = (389..1000).chain(0..389).collect();
- v.rotate(1000-389);
+ v.rotate_left(1000-389);
+ assert_eq!(v, expected);
+}
+
+#[test]
+fn test_rotate_right() {
+ let expected: Vec<_> = (0..13).collect();
+ let mut v = Vec::new();
+
+ // no-ops
+ v.clone_from(&expected);
+ v.rotate_right(0);
+ assert_eq!(v, expected);
+ v.rotate_right(expected.len());
+ assert_eq!(v, expected);
+ let mut zst_array = [(), (), ()];
+ zst_array.rotate_right(2);
+
+ // happy path
+ v = (5..13).chain(0..5).collect();
+ v.rotate_right(5);
+ assert_eq!(v, expected);
+
+ let expected: Vec<_> = (0..1000).collect();
+
+ // small rotations in large slice, uses ptr::copy
+ v = (2..1000).chain(0..2).collect();
+ v.rotate_right(2);
+ assert_eq!(v, expected);
+ v = (998..1000).chain(0..998).collect();
+ v.rotate_right(998);
+ assert_eq!(v, expected);
+
+ // non-small prime rotation, has a few rounds of swapping
+ v = (389..1000).chain(0..389).collect();
+ v.rotate_right(389);
assert_eq!(v, expected);
}
let _it = v.chunks(0);
}
+#[test]
+fn test_exact_chunksator() {
+ let v = &[1, 2, 3, 4, 5];
+
+ assert_eq!(v.exact_chunks(2).len(), 2);
+
+ let chunks: &[&[_]] = &[&[1, 2], &[3, 4]];
+ assert_eq!(v.exact_chunks(2).collect::<Vec<_>>(), chunks);
+ let chunks: &[&[_]] = &[&[1, 2, 3]];
+ assert_eq!(v.exact_chunks(3).collect::<Vec<_>>(), chunks);
+ let chunks: &[&[_]] = &[];
+ assert_eq!(v.exact_chunks(6).collect::<Vec<_>>(), chunks);
+
+ let chunks: &[&[_]] = &[&[3, 4], &[1, 2]];
+ assert_eq!(v.exact_chunks(2).rev().collect::<Vec<_>>(), chunks);
+}
+
+#[test]
+#[should_panic]
+fn test_exact_chunksator_0() {
+ let v = &[1, 2, 3, 4];
+ let _it = v.exact_chunks(0);
+}
+
#[test]
fn test_reverse_part() {
let mut values = [1, 2, 3, 4, 5];
}
}
let result = [0, 0, 0, 1, 1, 1, 2];
- assert!(v == result);
+ assert_eq!(v, result);
}
#[test]
}
}
let result = [2, 2, 2, 1, 1, 1, 0];
- assert!(v == result);
+ assert_eq!(v, result);
}
#[test]
let _it = v.chunks_mut(0);
}
+#[test]
+fn test_mut_exact_chunks() {
+ let mut v = [0, 1, 2, 3, 4, 5, 6];
+ assert_eq!(v.exact_chunks_mut(2).len(), 3);
+ for (i, chunk) in v.exact_chunks_mut(3).enumerate() {
+ for x in chunk {
+ *x = i as u8;
+ }
+ }
+ let result = [0, 0, 0, 1, 1, 1, 6];
+ assert_eq!(v, result);
+}
+
+#[test]
+fn test_mut_exact_chunks_rev() {
+ let mut v = [0, 1, 2, 3, 4, 5, 6];
+ for (i, chunk) in v.exact_chunks_mut(3).rev().enumerate() {
+ for x in chunk {
+ *x = i as u8;
+ }
+ }
+ let result = [1, 1, 1, 0, 0, 0, 6];
+ assert_eq!(v, result);
+}
+
+#[test]
+#[should_panic]
+fn test_mut_exact_chunks_0() {
+ let mut v = [1, 2, 3, 4];
+ let _it = v.exact_chunks_mut(0);
+}
+
#[test]
fn test_mut_last() {
let mut x = [1, 2, 3, 4, 5];
use core::ops::{InPlace, Index, IndexMut, Place, Placer};
use core::ops;
use core::ptr;
-use core::ptr::Shared;
+use core::ptr::NonNull;
use core::slice;
use borrow::ToOwned;
tail_start: end,
tail_len: len - end,
iter: range_slice.iter(),
- vec: Shared::from(self),
+ vec: NonNull::from(self),
}
}
}
let cap = self.buf.cap();
mem::forget(self);
IntoIter {
- buf: Shared::new_unchecked(begin),
+ buf: NonNull::new_unchecked(begin),
phantom: PhantomData,
cap,
ptr: begin,
/// [`IntoIterator`]: ../../std/iter/trait.IntoIterator.html
#[stable(feature = "rust1", since = "1.0.0")]
pub struct IntoIter<T> {
- buf: Shared<T>,
+ buf: NonNull<T>,
phantom: PhantomData<T>,
cap: usize,
ptr: *const T,
tail_len: usize,
/// Current remaining range to remove
iter: slice::Iter<'a, T>,
- vec: Shared<Vec<T>>,
+ vec: NonNull<Vec<T>>,
}
#[stable(feature = "collection_debug", since = "1.17.0")]
use core::mem;
use core::ops::{Index, IndexMut, Place, Placer, InPlace};
use core::ptr;
-use core::ptr::Shared;
+use core::ptr::NonNull;
use core::slice;
use core::hash::{Hash, Hasher};
self.head = drain_tail;
Drain {
- deque: Shared::from(&mut *self),
+ deque: NonNull::from(&mut *self),
after_tail: drain_head,
after_head: head,
iter: Iter {
after_tail: usize,
after_head: usize,
iter: Iter<'a, T>,
- deque: Shared<VecDeque<T>>,
+ deque: NonNull<VecDeque<T>>,
}
#[stable(feature = "collection_debug", since = "1.17.0")]
if other.is_contiguous() {
ptr::copy(buf.offset(tail as isize), buf, len);
} else {
- if (tail - head) >= cmp::min((cap - tail), head) {
+ if (tail - head) >= cmp::min(cap - tail, head) {
// There is enough free space in the centre for the shortest block so we can
// do this in at most three copy moves.
if (cap - tail) > head {
#![feature(core_intrinsics)]
#![feature(staged_api)]
#![feature(rustc_attrs)]
-#![cfg_attr(any(unix, target_os = "redox"), feature(libc))]
+#![cfg_attr(any(unix, target_os = "cloudabi", target_os = "redox"), feature(libc))]
#![rustc_alloc_kind = "lib"]
// The minimum alignment guaranteed by the architecture. This value is used to
}
}
-#[cfg(any(unix, target_os = "redox"))]
+#[cfg(any(unix, target_os = "cloudabi", target_os = "redox"))]
mod platform {
extern crate libc;
struct Stderr;
impl Write for Stderr {
+ #[cfg(target_os = "cloudabi")]
+ fn write_str(&mut self, _: &str) -> fmt::Result {
+ // CloudABI does not have any reserved file descriptor
+ // numbers. We should not attempt to write to file
+ // descriptor #2, as it may be associated with any kind of
+ // resource.
+ Ok(())
+ }
+
+ #[cfg(not(target_os = "cloudabi"))]
fn write_str(&mut self, s: &str) -> fmt::Result {
unsafe {
libc::write(libc::STDERR_FILENO,
impl<T> TypedArenaChunk<T> {
#[inline]
unsafe fn new(capacity: usize) -> TypedArenaChunk<T> {
- TypedArenaChunk { storage: RawVec::with_capacity(capacity) }
+ TypedArenaChunk {
+ storage: RawVec::with_capacity(capacity),
+ }
}
/// Destroys this arena chunk.
unsafe {
if mem::size_of::<T>() == 0 {
- self.ptr.set(intrinsics::arith_offset(self.ptr.get() as *mut u8, 1) as *mut T);
+ self.ptr
+ .set(intrinsics::arith_offset(self.ptr.get() as *mut u8, 1)
+ as *mut T);
let ptr = mem::align_of::<T>() as *mut T;
// Don't drop the object. This `write` is equivalent to `forget`.
ptr::write(ptr, object);
/// - Zero-length slices
#[inline]
pub fn alloc_slice(&self, slice: &[T]) -> &mut [T]
- where T: Copy {
+ where
+ T: Copy,
+ {
assert!(mem::size_of::<T>() != 0);
assert!(slice.len() != 0);
let (chunk, mut new_capacity);
if let Some(last_chunk) = chunks.last_mut() {
let used_bytes = self.ptr.get() as usize - last_chunk.start() as usize;
- if last_chunk.storage.reserve_in_place(used_bytes, needed_bytes) {
+ if last_chunk
+ .storage
+ .reserve_in_place(used_bytes, needed_bytes)
+ {
self.end.set(last_chunk.end());
return;
} else {
let ptr = self.ptr.get();
// Set the pointer past ourselves
- self.ptr.set(intrinsics::arith_offset(
- self.ptr.get(), mem::size_of::<T>() as isize
- ) as *mut u8);
+ self.ptr.set(
+ intrinsics::arith_offset(self.ptr.get(), mem::size_of::<T>() as isize) as *mut u8,
+ );
// Write into uninitialized memory.
ptr::write(ptr as *mut T, object);
&mut *(ptr as *mut T)
/// - Zero-length slices
#[inline]
pub fn alloc_slice<T>(&self, slice: &[T]) -> &mut [T]
- where T: Copy {
+ where
+ T: Copy,
+ {
assert!(!mem::needs_drop::<T>());
assert!(mem::size_of::<T>() != 0);
assert!(slice.len() != 0);
unsafe {
let arena_slice = slice::from_raw_parts_mut(self.ptr.get() as *mut T, slice.len());
self.ptr.set(intrinsics::arith_offset(
- self.ptr.get(), (slice.len() * mem::size_of::<T>()) as isize
+ self.ptr.get(),
+ (slice.len() * mem::size_of::<T>()) as isize,
) as *mut u8);
arena_slice.copy_from_slice(slice);
arena_slice
let arena = Wrap(TypedArena::new());
- let result =
- arena.alloc_outer(|| Outer { inner: arena.alloc_inner(|| Inner { value: 10 }) });
+ let result = arena.alloc_outer(|| Outer {
+ inner: arena.alloc_inner(|| Inner { value: 10 }),
+ });
assert_eq!(result.inner.value, 10);
}
/// some other means.
///
/// An important thing to remember is that the type `fmt::Error` should not be
-/// confused with `std::io::Error` or `std::error::Error`, which you may also
+/// confused with [`std::io::Error`] or [`std::error::Error`], which you may also
/// have in scope.
///
+/// [`std::io::Error`]: ../../std/io/struct.Error.html
+/// [`std::error::Error`]: ../../std/error/trait.Error.html
+///
/// # Examples
///
/// ```rust
/// Emits a `!nontemporal` store according to LLVM (see their docs).
/// Probably will never become stable.
- #[cfg(not(stage0))]
pub fn nontemporal_store<T>(ptr: *mut T, val: T);
}
self.start = self.end.clone();
None
}
+
+ #[inline]
+ fn last(mut self) -> Option<A> {
+ self.next_back()
+ }
+
+ #[inline]
+ fn min(mut self) -> Option<A> {
+ self.next()
+ }
+
+ #[inline]
+ fn max(mut self) -> Option<A> {
+ self.next_back()
+ }
}
// These macros generate `ExactSizeIterator` impls for various range types.
self.end.replace_zero();
None
}
+
+ #[inline]
+ fn last(mut self) -> Option<A> {
+ self.next_back()
+ }
+
+ #[inline]
+ fn min(mut self) -> Option<A> {
+ self.next()
+ }
+
+ #[inline]
+ fn max(mut self) -> Option<A> {
+ self.next_back()
+ }
}
#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")]
/// // The prefered method of quick returning Errors
/// fn write_to_file_question() -> Result<(), MyError> {
/// let mut file = File::create("my_best_friends.txt")?;
+/// file.write_all(b"This is a list of my best friends.")?;
/// Ok(())
/// }
///
/// [ub]: ../../reference/behavior-considered-undefined.html
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_on_unimplemented = "`{Self}` cannot be sent between threads safely"]
-pub unsafe trait Send {
+pub unsafe auto trait Send {
// empty.
}
-#[stable(feature = "rust1", since = "1.0.0")]
-#[allow(unknown_lints)]
-#[allow(auto_impl)]
-unsafe impl Send for .. { }
-
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> !Send for *const T { }
#[stable(feature = "rust1", since = "1.0.0")]
#[stable(feature = "rust1", since = "1.0.0")]
#[lang = "sync"]
#[rustc_on_unimplemented = "`{Self}` cannot be shared between threads safely"]
-pub unsafe trait Sync {
+pub unsafe auto trait Sync {
// Empty
}
-#[stable(feature = "rust1", since = "1.0.0")]
-#[allow(unknown_lints)]
-#[allow(auto_impl)]
-unsafe impl Sync for .. { }
-
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> !Sync for *const T { }
#[stable(feature = "rust1", since = "1.0.0")]
/// This affects, for example, whether a `static` of that type is
/// placed in read-only static memory or writable static memory.
#[lang = "freeze"]
-unsafe trait Freeze {}
-
-#[allow(unknown_lints)]
-#[allow(auto_impl)]
-unsafe impl Freeze for .. {}
+unsafe auto trait Freeze {}
impl<T: ?Sized> !Freeze for UnsafeCell<T> {}
unsafe impl<T: ?Sized> Freeze for PhantomData<T> {}
}
}
-#[stable(feature = "manually_drop", since = "1.20.0")]
+#[stable(feature = "manually_drop_impls", since = "1.22.0")]
impl<T: Clone> Clone for ManuallyDrop<T> {
fn clone(&self) -> Self {
ManuallyDrop::new(self.deref().clone())
}
}
-#[stable(feature = "manually_drop", since = "1.20.0")]
+#[stable(feature = "manually_drop_impls", since = "1.22.0")]
impl<T: Default> Default for ManuallyDrop<T> {
fn default() -> Self {
ManuallyDrop::new(Default::default())
}
}
-#[stable(feature = "manually_drop", since = "1.20.0")]
+#[stable(feature = "manually_drop_impls", since = "1.22.0")]
impl<T: PartialEq> PartialEq for ManuallyDrop<T> {
fn eq(&self, other: &Self) -> bool {
self.deref().eq(other)
}
}
-#[stable(feature = "manually_drop", since = "1.20.0")]
+#[stable(feature = "manually_drop_impls", since = "1.22.0")]
impl<T: Eq> Eq for ManuallyDrop<T> {}
-#[stable(feature = "manually_drop", since = "1.20.0")]
+#[stable(feature = "manually_drop_impls", since = "1.22.0")]
impl<T: PartialOrd> PartialOrd for ManuallyDrop<T> {
fn partial_cmp(&self, other: &Self) -> Option<::cmp::Ordering> {
self.deref().partial_cmp(other)
}
}
-#[stable(feature = "manually_drop", since = "1.20.0")]
+#[stable(feature = "manually_drop_impls", since = "1.22.0")]
impl<T: Ord> Ord for ManuallyDrop<T> {
fn cmp(&self, other: &Self) -> ::cmp::Ordering {
self.deref().cmp(other)
}
}
-#[stable(feature = "manually_drop", since = "1.20.0")]
+#[stable(feature = "manually_drop_impls", since = "1.22.0")]
impl<T: ::hash::Hash> ::hash::Hash for ManuallyDrop<T> {
fn hash<H: ::hash::Hasher>(&self, state: &mut H) {
self.deref().hash(state);
}
/// Checked integer division. Computes `self / rhs`, returning `None`
- /// if `rhs == 0` or the operation results in overflow.
+ /// if `rhs == 0` or the division results in overflow.
///
/// # Examples
///
}
/// Checked integer remainder. Computes `self % rhs`, returning `None`
- /// if `rhs == 0` or the operation results in overflow.
+ /// if `rhs == 0` or the division results in overflow.
///
/// # Examples
///
}
/// Checked integer division. Computes `self / rhs`, returning `None`
- /// if `rhs == 0` or the operation results in overflow.
+ /// if `rhs == 0`.
///
/// # Examples
///
}
/// Checked integer remainder. Computes `self % rhs`, returning `None`
- /// if `rhs == 0` or the operation results in overflow.
+ /// if `rhs == 0`.
///
/// # Examples
///
}
/// Applies a function to the contained value (if any),
- /// or returns a [`default`][] (if not).
- ///
- /// [`default`]: ../default/trait.Default.html#tymethod.default
+ /// or returns the provided default (if not).
///
/// # Examples
///
}
/// Applies a function to the contained value (if any),
- /// or computes a [`default`][] (if not).
- ///
- /// [`default`]: ../default/trait.Default.html#tymethod.default
+ /// or computes a default (if not).
///
/// # Examples
///
/// Returns the contained value or a default
///
/// Consumes the `self` argument then, if [`Some`], returns the contained
- /// value, otherwise if [`None`], returns the default value for that
+ /// value, otherwise if [`None`], returns the [default value] for that
/// type.
///
/// # Examples
///
/// [`Some`]: #variant.Some
/// [`None`]: #variant.None
+ /// [default value]: ../default/trait.Default.html#tymethod.default
/// [`parse`]: ../../std/primitive.str.html#method.parse
/// [`FromStr`]: ../../std/str/trait.FromStr.html
#[inline]
#![stable(feature = "core_prelude", since = "1.4.0")]
-// Reexported core operators
+// Re-exported core operators
#[stable(feature = "core_prelude", since = "1.4.0")]
#[doc(no_inline)]
pub use marker::{Copy, Send, Sized, Sync};
#[doc(no_inline)]
pub use ops::{Drop, Fn, FnMut, FnOnce};
-// Reexported functions
+// Re-exported functions
#[stable(feature = "core_prelude", since = "1.4.0")]
#[doc(no_inline)]
pub use mem::drop;
-// Reexported types and traits
+// Re-exported types and traits
#[stable(feature = "core_prelude", since = "1.4.0")]
#[doc(no_inline)]
pub use clone::Clone;
#[doc(no_inline)]
pub use result::Result::{self, Ok, Err};
-// Reexported extension traits for primitive types
+// Re-exported extension traits for primitive types
#[stable(feature = "core_prelude", since = "1.4.0")]
#[doc(no_inline)]
pub use slice::SliceExt;
/// its owning Unique.
///
/// If you're uncertain of whether it's correct to use `Unique` for your purposes,
-/// consider using `Shared`, which has weaker semantics.
+/// consider using `NonNull`, which has weaker semantics.
///
/// Unlike `*mut T`, the pointer must always be non-null, even if the pointer
/// is never dereferenced. This is so that enums may use this forbidden value
///
/// Unlike `*mut T`, `Unique<T>` is covariant over `T`. This should always be correct
/// for any type which upholds Unique's aliasing requirements.
-#[allow(missing_debug_implementations)]
-#[unstable(feature = "unique", reason = "needs an RFC to flesh out design",
- issue = "27730")]
+#[unstable(feature = "ptr_internals", issue = "0",
+ reason = "use NonNull instead and consider PhantomData<T> \
+ (if you also use #[may_dangle]), Send, and/or Sync")]
pub struct Unique<T: ?Sized> {
pointer: NonZero<*const T>,
// NOTE: this marker has no consequences for variance, but is necessary
_marker: PhantomData<T>,
}
+#[unstable(feature = "ptr_internals", issue = "0")]
+impl<T: ?Sized> fmt::Debug for Unique<T> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ fmt::Pointer::fmt(&self.as_ptr(), f)
+ }
+}
+
/// `Unique` pointers are `Send` if `T` is `Send` because the data they
/// reference is unaliased. Note that this aliasing invariant is
/// unenforced by the type system; the abstraction using the
/// `Unique` must enforce it.
-#[unstable(feature = "unique", issue = "27730")]
+#[unstable(feature = "ptr_internals", issue = "0")]
unsafe impl<T: Send + ?Sized> Send for Unique<T> { }
/// `Unique` pointers are `Sync` if `T` is `Sync` because the data they
/// reference is unaliased. Note that this aliasing invariant is
/// unenforced by the type system; the abstraction using the
/// `Unique` must enforce it.
-#[unstable(feature = "unique", issue = "27730")]
+#[unstable(feature = "ptr_internals", issue = "0")]
unsafe impl<T: Sync + ?Sized> Sync for Unique<T> { }
-#[unstable(feature = "unique", issue = "27730")]
+#[unstable(feature = "ptr_internals", issue = "0")]
impl<T: Sized> Unique<T> {
/// Creates a new `Unique` that is dangling, but well-aligned.
///
/// This is useful for initializing types which lazily allocate, like
/// `Vec::new` does.
+ // FIXME: rename to dangling() to match NonNull?
pub fn empty() -> Self {
unsafe {
let ptr = mem::align_of::<T>() as *mut T;
}
}
-#[unstable(feature = "unique", issue = "27730")]
+#[unstable(feature = "ptr_internals", issue = "0")]
impl<T: ?Sized> Unique<T> {
/// Creates a new `Unique`.
///
/// # Safety
///
/// `ptr` must be non-null.
- #[unstable(feature = "unique", issue = "27730")]
pub const unsafe fn new_unchecked(ptr: *mut T) -> Self {
Unique { pointer: NonZero::new_unchecked(ptr), _marker: PhantomData }
}
///
/// The resulting lifetime is bound to self so this behaves "as if"
/// it were actually an instance of T that is getting borrowed. If a longer
- /// (unbound) lifetime is needed, use `&*my_ptr.ptr()`.
+ /// (unbound) lifetime is needed, use `&*my_ptr.as_ptr()`.
pub unsafe fn as_ref(&self) -> &T {
&*self.as_ptr()
}
///
/// The resulting lifetime is bound to self so this behaves "as if"
/// it were actually an instance of T that is getting borrowed. If a longer
- /// (unbound) lifetime is needed, use `&mut *my_ptr.ptr()`.
+ /// (unbound) lifetime is needed, use `&mut *my_ptr.as_ptr()`.
pub unsafe fn as_mut(&mut self) -> &mut T {
&mut *self.as_ptr()
}
}
-#[unstable(feature = "unique", issue = "27730")]
+#[unstable(feature = "ptr_internals", issue = "0")]
impl<T: ?Sized> Clone for Unique<T> {
fn clone(&self) -> Self {
*self
}
}
-#[unstable(feature = "unique", issue = "27730")]
+#[unstable(feature = "ptr_internals", issue = "0")]
impl<T: ?Sized> Copy for Unique<T> { }
-#[unstable(feature = "unique", issue = "27730")]
+#[unstable(feature = "ptr_internals", issue = "0")]
impl<T: ?Sized, U: ?Sized> CoerceUnsized<Unique<U>> for Unique<T> where T: Unsize<U> { }
-#[unstable(feature = "unique", issue = "27730")]
+#[unstable(feature = "ptr_internals", issue = "0")]
impl<T: ?Sized> fmt::Pointer for Unique<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Pointer::fmt(&self.as_ptr(), f)
}
}
-#[unstable(feature = "unique", issue = "27730")]
+#[unstable(feature = "ptr_internals", issue = "0")]
impl<'a, T: ?Sized> From<&'a mut T> for Unique<T> {
fn from(reference: &'a mut T) -> Self {
Unique { pointer: NonZero::from(reference), _marker: PhantomData }
}
}
-#[unstable(feature = "unique", issue = "27730")]
+#[unstable(feature = "ptr_internals", issue = "0")]
impl<'a, T: ?Sized> From<&'a T> for Unique<T> {
fn from(reference: &'a T) -> Self {
Unique { pointer: NonZero::from(reference), _marker: PhantomData }
}
}
+#[unstable(feature = "ptr_internals", issue = "0")]
+impl<'a, T: ?Sized> From<NonNull<T>> for Unique<T> {
+ fn from(p: NonNull<T>) -> Self {
+ Unique { pointer: p.pointer, _marker: PhantomData }
+ }
+}
+
+/// Previous name of `NonNull`.
+#[rustc_deprecated(since = "1.24", reason = "renamed to `NonNull`")]
+#[unstable(feature = "shared", issue = "27730")]
+pub type Shared<T> = NonNull<T>;
+
/// `*mut T` but non-zero and covariant.
///
/// This is often the correct thing to use when building data structures using
/// raw pointers, but is ultimately more dangerous to use because of its additional
-/// properties. If you're not sure if you should use `Shared<T>`, just use `*mut T`!
+/// properties. If you're not sure if you should use `NonNull<T>`, just use `*mut T`!
///
/// Unlike `*mut T`, the pointer must always be non-null, even if the pointer
/// is never dereferenced. This is so that enums may use this forbidden value
-/// as a discriminant -- `Option<Shared<T>>` has the same size as `Shared<T>`.
+/// as a discriminant -- `Option<NonNull<T>>` has the same size as `NonNull<T>`.
/// However the pointer may still dangle if it isn't dereferenced.
///
-/// Unlike `*mut T`, `Shared<T>` is covariant over `T`. If this is incorrect
+/// Unlike `*mut T`, `NonNull<T>` is covariant over `T`. If this is incorrect
/// for your use case, you should include some PhantomData in your type to
/// provide invariance, such as `PhantomData<Cell<T>>` or `PhantomData<&'a mut T>`.
/// Usually this won't be necessary; covariance is correct for most safe abstractions,
/// such as Box, Rc, Arc, Vec, and LinkedList. This is the case because they
/// provide a public API that follows the normal shared XOR mutable rules of Rust.
-#[allow(missing_debug_implementations)]
-#[unstable(feature = "shared", reason = "needs an RFC to flesh out design",
- issue = "27730")]
-pub struct Shared<T: ?Sized> {
+#[stable(feature = "nonnull", since = "1.24.0")]
+pub struct NonNull<T: ?Sized> {
pointer: NonZero<*const T>,
}
-/// `Shared` pointers are not `Send` because the data they reference may be aliased.
+#[stable(feature = "nonnull", since = "1.24.0")]
+impl<T: ?Sized> fmt::Debug for NonNull<T> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ fmt::Pointer::fmt(&self.as_ptr(), f)
+ }
+}
+
+/// `NonNull` pointers are not `Send` because the data they reference may be aliased.
// NB: This impl is unnecessary, but should provide better error messages.
-#[unstable(feature = "shared", issue = "27730")]
-impl<T: ?Sized> !Send for Shared<T> { }
+#[stable(feature = "nonnull", since = "1.24.0")]
+impl<T: ?Sized> !Send for NonNull<T> { }
-/// `Shared` pointers are not `Sync` because the data they reference may be aliased.
+/// `NonNull` pointers are not `Sync` because the data they reference may be aliased.
// NB: This impl is unnecessary, but should provide better error messages.
-#[unstable(feature = "shared", issue = "27730")]
-impl<T: ?Sized> !Sync for Shared<T> { }
+#[stable(feature = "nonnull", since = "1.24.0")]
+impl<T: ?Sized> !Sync for NonNull<T> { }
-#[unstable(feature = "shared", issue = "27730")]
-impl<T: Sized> Shared<T> {
- /// Creates a new `Shared` that is dangling, but well-aligned.
+impl<T: Sized> NonNull<T> {
+ /// Creates a new `NonNull` that is dangling, but well-aligned.
///
/// This is useful for initializing types which lazily allocate, like
/// `Vec::new` does.
- pub fn empty() -> Self {
+ #[stable(feature = "nonnull", since = "1.24.0")]
+ pub fn dangling() -> Self {
unsafe {
let ptr = mem::align_of::<T>() as *mut T;
- Shared::new_unchecked(ptr)
+ NonNull::new_unchecked(ptr)
}
}
}
-#[unstable(feature = "shared", issue = "27730")]
-impl<T: ?Sized> Shared<T> {
- /// Creates a new `Shared`.
+impl<T: ?Sized> NonNull<T> {
+ /// Creates a new `NonNull`.
///
/// # Safety
///
/// `ptr` must be non-null.
- #[unstable(feature = "shared", issue = "27730")]
+ #[stable(feature = "nonnull", since = "1.24.0")]
pub const unsafe fn new_unchecked(ptr: *mut T) -> Self {
- Shared { pointer: NonZero::new_unchecked(ptr) }
+ NonNull { pointer: NonZero::new_unchecked(ptr) }
}
- /// Creates a new `Shared` if `ptr` is non-null.
+ /// Creates a new `NonNull` if `ptr` is non-null.
+ #[stable(feature = "nonnull", since = "1.24.0")]
pub fn new(ptr: *mut T) -> Option<Self> {
- NonZero::new(ptr as *const T).map(|nz| Shared { pointer: nz })
+ NonZero::new(ptr as *const T).map(|nz| NonNull { pointer: nz })
}
/// Acquires the underlying `*mut` pointer.
+ #[stable(feature = "nonnull", since = "1.24.0")]
pub fn as_ptr(self) -> *mut T {
self.pointer.get() as *mut T
}
///
/// The resulting lifetime is bound to self so this behaves "as if"
/// it were actually an instance of T that is getting borrowed. If a longer
- /// (unbound) lifetime is needed, use `&*my_ptr.ptr()`.
+ /// (unbound) lifetime is needed, use `&*my_ptr.as_ptr()`.
+ #[stable(feature = "nonnull", since = "1.24.0")]
pub unsafe fn as_ref(&self) -> &T {
&*self.as_ptr()
}
///
/// The resulting lifetime is bound to self so this behaves "as if"
/// it were actually an instance of T that is getting borrowed. If a longer
- /// (unbound) lifetime is needed, use `&mut *my_ptr.ptr_mut()`.
+ /// (unbound) lifetime is needed, use `&mut *my_ptr.as_ptr()`.
+ #[stable(feature = "nonnull", since = "1.24.0")]
pub unsafe fn as_mut(&mut self) -> &mut T {
&mut *self.as_ptr()
}
-
- /// Acquires the underlying pointer as a `*mut` pointer.
- #[rustc_deprecated(since = "1.19", reason = "renamed to `as_ptr` for ergonomics/consistency")]
- #[unstable(feature = "shared", issue = "27730")]
- pub unsafe fn as_mut_ptr(&self) -> *mut T {
- self.as_ptr()
- }
}
-#[unstable(feature = "shared", issue = "27730")]
-impl<T: ?Sized> Clone for Shared<T> {
+#[stable(feature = "nonnull", since = "1.24.0")]
+impl<T: ?Sized> Clone for NonNull<T> {
fn clone(&self) -> Self {
*self
}
}
-#[unstable(feature = "shared", issue = "27730")]
-impl<T: ?Sized> Copy for Shared<T> { }
+#[stable(feature = "nonnull", since = "1.24.0")]
+impl<T: ?Sized> Copy for NonNull<T> { }
-#[unstable(feature = "shared", issue = "27730")]
-impl<T: ?Sized, U: ?Sized> CoerceUnsized<Shared<U>> for Shared<T> where T: Unsize<U> { }
+#[stable(feature = "nonnull", since = "1.24.0")]
+impl<T: ?Sized, U: ?Sized> CoerceUnsized<NonNull<U>> for NonNull<T> where T: Unsize<U> { }
-#[unstable(feature = "shared", issue = "27730")]
-impl<T: ?Sized> fmt::Pointer for Shared<T> {
+#[stable(feature = "nonnull", since = "1.24.0")]
+impl<T: ?Sized> fmt::Pointer for NonNull<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Pointer::fmt(&self.as_ptr(), f)
}
}
-#[unstable(feature = "shared", issue = "27730")]
-impl<T: ?Sized> From<Unique<T>> for Shared<T> {
+#[stable(feature = "nonnull", since = "1.24.0")]
+impl<T: ?Sized> From<Unique<T>> for NonNull<T> {
fn from(unique: Unique<T>) -> Self {
- Shared { pointer: unique.pointer }
+ NonNull { pointer: unique.pointer }
}
}
-#[unstable(feature = "shared", issue = "27730")]
-impl<'a, T: ?Sized> From<&'a mut T> for Shared<T> {
+#[stable(feature = "nonnull", since = "1.24.0")]
+impl<'a, T: ?Sized> From<&'a mut T> for NonNull<T> {
fn from(reference: &'a mut T) -> Self {
- Shared { pointer: NonZero::from(reference) }
+ NonNull { pointer: NonZero::from(reference) }
}
}
-#[unstable(feature = "shared", issue = "27730")]
-impl<'a, T: ?Sized> From<&'a T> for Shared<T> {
+#[stable(feature = "nonnull", since = "1.24.0")]
+impl<'a, T: ?Sized> From<&'a T> for NonNull<T> {
fn from(reference: &'a T) -> Self {
- Shared { pointer: NonZero::from(reference) }
+ NonNull { pointer: NonZero::from(reference) }
}
}
// a lot of stuff defined here. Let's keep it clean.
//
// Since slices don't support inherent methods; all operations
-// on them are defined on traits, which are then reexported from
+// on them are defined on traits, which are then re-exported from
// the prelude for convenience. So there are a lot of traits here.
//
// The layout of this file is thus:
#[stable(feature = "core", since = "1.6.0")]
fn chunks(&self, size: usize) -> Chunks<Self::Item>;
+ #[unstable(feature = "exact_chunks", issue = "47115")]
+ fn exact_chunks(&self, size: usize) -> ExactChunks<Self::Item>;
+
#[stable(feature = "core", since = "1.6.0")]
fn get<I>(&self, index: I) -> Option<&I::Output>
where I: SliceIndex<Self>;
#[stable(feature = "core", since = "1.6.0")]
fn chunks_mut(&mut self, chunk_size: usize) -> ChunksMut<Self::Item>;
+ #[unstable(feature = "exact_chunks", issue = "47115")]
+ fn exact_chunks_mut(&mut self, size: usize) -> ExactChunksMut<Self::Item>;
+
#[stable(feature = "core", since = "1.6.0")]
fn swap(&mut self, a: usize, b: usize);
fn ends_with(&self, needle: &[Self::Item]) -> bool where Self::Item: PartialEq;
#[unstable(feature = "slice_rotate", issue = "41891")]
- fn rotate(&mut self, mid: usize);
+ fn rotate_left(&mut self, mid: usize);
+
+ #[unstable(feature = "slice_rotate", issue = "41891")]
+ fn rotate_right(&mut self, k: usize);
#[stable(feature = "clone_from_slice", since = "1.7.0")]
fn clone_from_slice(&mut self, src: &[Self::Item]) where Self::Item: Clone;
Chunks { v: self, chunk_size: chunk_size }
}
+ #[inline]
+ fn exact_chunks(&self, chunk_size: usize) -> ExactChunks<T> {
+ assert!(chunk_size != 0);
+ let rem = self.len() % chunk_size;
+ let len = self.len() - rem;
+ ExactChunks { v: &self[..len], chunk_size: chunk_size}
+ }
+
#[inline]
fn get<I>(&self, index: I) -> Option<&I::Output>
where I: SliceIndex<[T]>
ChunksMut { v: self, chunk_size: chunk_size }
}
+ #[inline]
+ fn exact_chunks_mut(&mut self, chunk_size: usize) -> ExactChunksMut<T> {
+ assert!(chunk_size != 0);
+ let rem = self.len() % chunk_size;
+ let len = self.len() - rem;
+ ExactChunksMut { v: &mut self[..len], chunk_size: chunk_size}
+ }
+
#[inline]
fn swap(&mut self, a: usize, b: usize) {
unsafe {
self.binary_search_by(|p| p.cmp(x))
}
- fn rotate(&mut self, mid: usize) {
+ fn rotate_left(&mut self, mid: usize) {
assert!(mid <= self.len());
let k = self.len() - mid;
}
}
+ fn rotate_right(&mut self, k: usize) {
+ assert!(k <= self.len());
+ let mid = self.len() - k;
+
+ unsafe {
+ let p = self.as_mut_ptr();
+ rotate::ptr_rotate(mid, p.offset(mid as isize), k);
+ }
+ }
+
#[inline]
fn clone_from_slice(&mut self, src: &[T]) where T: Clone {
assert!(self.len() == src.len(),
}
accum
}
+
+ #[inline]
+ #[rustc_inherit_overflow_checks]
+ fn position<P>(&mut self, mut predicate: P) -> Option<usize> where
+ Self: Sized,
+ P: FnMut(Self::Item) -> bool,
+ {
+ // The addition might panic on overflow
+ let n = self.len();
+ self.try_fold(0, move |i, x| {
+ if predicate(x) { Err(i) }
+ else { Ok(i + 1) }
+ }).err()
+ .map(|i| {
+ unsafe { assume(i < n) };
+ i
+ })
+ }
+
+ #[inline]
+ fn rposition<P>(&mut self, mut predicate: P) -> Option<usize> where
+ P: FnMut(Self::Item) -> bool,
+ Self: Sized + ExactSizeIterator + DoubleEndedIterator
+ {
+ // No need for an overflow check here, because `ExactSizeIterator`
+ // implies that the number of elements fits into a `usize`.
+ let n = self.len();
+ self.try_rfold(n, move |i, x| {
+ let i = i - 1;
+ if predicate(x) { Err(i) }
+ else { Ok(i) }
+ }).err()
+ .map(|i| {
+ unsafe { assume(i < n) };
+ i
+ })
+ }
}
#[stable(feature = "rust1", since = "1.0.0")]
#[unstable(feature = "fused", issue = "35602")]
impl<'a, T> FusedIterator for Windows<'a, T> {}
+#[doc(hidden)]
+unsafe impl<'a, T> TrustedRandomAccess for Windows<'a, T> {
+ unsafe fn get_unchecked(&mut self, i: usize) -> &'a [T] {
+ from_raw_parts(self.v.as_ptr().offset(i as isize), self.size)
+ }
+ fn may_have_side_effect() -> bool { false }
+}
+
/// An iterator over a slice in (non-overlapping) chunks (`chunk_size` elements at a
/// time).
///
#[unstable(feature = "fused", issue = "35602")]
impl<'a, T> FusedIterator for Chunks<'a, T> {}
+#[doc(hidden)]
+unsafe impl<'a, T> TrustedRandomAccess for Chunks<'a, T> {
+ unsafe fn get_unchecked(&mut self, i: usize) -> &'a [T] {
+ let start = i * self.chunk_size;
+ let end = match start.checked_add(self.chunk_size) {
+ None => self.v.len(),
+ Some(end) => cmp::min(end, self.v.len()),
+ };
+ from_raw_parts(self.v.as_ptr().offset(start as isize), end - start)
+ }
+ fn may_have_side_effect() -> bool { false }
+}
+
/// An iterator over a slice in (non-overlapping) mutable chunks (`chunk_size`
/// elements at a time). When the slice len is not evenly divided by the chunk
/// size, the last slice of the iteration will be the remainder.
#[unstable(feature = "fused", issue = "35602")]
impl<'a, T> FusedIterator for ChunksMut<'a, T> {}
+#[doc(hidden)]
+unsafe impl<'a, T> TrustedRandomAccess for ChunksMut<'a, T> {
+ unsafe fn get_unchecked(&mut self, i: usize) -> &'a mut [T] {
+ let start = i * self.chunk_size;
+ let end = match start.checked_add(self.chunk_size) {
+ None => self.v.len(),
+ Some(end) => cmp::min(end, self.v.len()),
+ };
+ from_raw_parts_mut(self.v.as_mut_ptr().offset(start as isize), end - start)
+ }
+ fn may_have_side_effect() -> bool { false }
+}
+
+/// An iterator over a slice in (non-overlapping) chunks (`chunk_size` elements at a
+/// time).
+///
+/// When the slice len is not evenly divided by the chunk size, the last
+/// up to `chunk_size-1` elements will be omitted.
+///
+/// This struct is created by the [`exact_chunks`] method on [slices].
+///
+/// [`exact_chunks`]: ../../std/primitive.slice.html#method.exact_chunks
+/// [slices]: ../../std/primitive.slice.html
+#[derive(Debug)]
+#[unstable(feature = "exact_chunks", issue = "47115")]
+pub struct ExactChunks<'a, T:'a> {
+ v: &'a [T],
+ chunk_size: usize
+}
+
+// FIXME(#26925) Remove in favor of `#[derive(Clone)]`
+#[unstable(feature = "exact_chunks", issue = "47115")]
+impl<'a, T> Clone for ExactChunks<'a, T> {
+ fn clone(&self) -> ExactChunks<'a, T> {
+ ExactChunks {
+ v: self.v,
+ chunk_size: self.chunk_size,
+ }
+ }
+}
+
+#[unstable(feature = "exact_chunks", issue = "47115")]
+impl<'a, T> Iterator for ExactChunks<'a, T> {
+ type Item = &'a [T];
+
+ #[inline]
+ fn next(&mut self) -> Option<&'a [T]> {
+ if self.v.len() < self.chunk_size {
+ None
+ } else {
+ let (fst, snd) = self.v.split_at(self.chunk_size);
+ self.v = snd;
+ Some(fst)
+ }
+ }
+
+ #[inline]
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ let n = self.v.len() / self.chunk_size;
+ (n, Some(n))
+ }
+
+ #[inline]
+ fn count(self) -> usize {
+ self.len()
+ }
+
+ #[inline]
+ fn nth(&mut self, n: usize) -> Option<Self::Item> {
+ let (start, overflow) = n.overflowing_mul(self.chunk_size);
+ if start >= self.v.len() || overflow {
+ self.v = &[];
+ None
+ } else {
+ let (_, snd) = self.v.split_at(start);
+ self.v = snd;
+ self.next()
+ }
+ }
+
+ #[inline]
+ fn last(mut self) -> Option<Self::Item> {
+ self.next_back()
+ }
+}
+
+#[unstable(feature = "exact_chunks", issue = "47115")]
+impl<'a, T> DoubleEndedIterator for ExactChunks<'a, T> {
+ #[inline]
+ fn next_back(&mut self) -> Option<&'a [T]> {
+ if self.v.len() < self.chunk_size {
+ None
+ } else {
+ let (fst, snd) = self.v.split_at(self.v.len() - self.chunk_size);
+ self.v = fst;
+ Some(snd)
+ }
+ }
+}
+
+#[unstable(feature = "exact_chunks", issue = "47115")]
+impl<'a, T> ExactSizeIterator for ExactChunks<'a, T> {
+ fn is_empty(&self) -> bool {
+ self.v.is_empty()
+ }
+}
+
+#[unstable(feature = "fused", issue = "35602")]
+impl<'a, T> FusedIterator for ExactChunks<'a, T> {}
+
+#[doc(hidden)]
+unsafe impl<'a, T> TrustedRandomAccess for ExactChunks<'a, T> {
+ unsafe fn get_unchecked(&mut self, i: usize) -> &'a [T] {
+ let start = i * self.chunk_size;
+ from_raw_parts(self.v.as_ptr().offset(start as isize), self.chunk_size)
+ }
+ fn may_have_side_effect() -> bool { false }
+}
+
+/// An iterator over a slice in (non-overlapping) mutable chunks (`chunk_size`
+/// elements at a time). When the slice len is not evenly divided by the chunk
+/// size, the last up to `chunk_size-1` elements will be omitted.
+///
+/// This struct is created by the [`exact_chunks_mut`] method on [slices].
+///
+/// [`exact_chunks_mut`]: ../../std/primitive.slice.html#method.exact_chunks_mut
+/// [slices]: ../../std/primitive.slice.html
+#[derive(Debug)]
+#[unstable(feature = "exact_chunks", issue = "47115")]
+pub struct ExactChunksMut<'a, T:'a> {
+ v: &'a mut [T],
+ chunk_size: usize
+}
+
+#[unstable(feature = "exact_chunks", issue = "47115")]
+impl<'a, T> Iterator for ExactChunksMut<'a, T> {
+ type Item = &'a mut [T];
+
+ #[inline]
+ fn next(&mut self) -> Option<&'a mut [T]> {
+ if self.v.len() < self.chunk_size {
+ None
+ } else {
+ let tmp = mem::replace(&mut self.v, &mut []);
+ let (head, tail) = tmp.split_at_mut(self.chunk_size);
+ self.v = tail;
+ Some(head)
+ }
+ }
+
+ #[inline]
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ let n = self.v.len() / self.chunk_size;
+ (n, Some(n))
+ }
+
+ #[inline]
+ fn count(self) -> usize {
+ self.len()
+ }
+
+ #[inline]
+ fn nth(&mut self, n: usize) -> Option<&'a mut [T]> {
+ let (start, overflow) = n.overflowing_mul(self.chunk_size);
+ if start >= self.v.len() || overflow {
+ self.v = &mut [];
+ None
+ } else {
+ let tmp = mem::replace(&mut self.v, &mut []);
+ let (_, snd) = tmp.split_at_mut(start);
+ self.v = snd;
+ self.next()
+ }
+ }
+
+ #[inline]
+ fn last(mut self) -> Option<Self::Item> {
+ self.next_back()
+ }
+}
+
+#[unstable(feature = "exact_chunks", issue = "47115")]
+impl<'a, T> DoubleEndedIterator for ExactChunksMut<'a, T> {
+ #[inline]
+ fn next_back(&mut self) -> Option<&'a mut [T]> {
+ if self.v.len() < self.chunk_size {
+ None
+ } else {
+ let tmp = mem::replace(&mut self.v, &mut []);
+ let tmp_len = tmp.len();
+ let (head, tail) = tmp.split_at_mut(tmp_len - self.chunk_size);
+ self.v = head;
+ Some(tail)
+ }
+ }
+}
+
+#[unstable(feature = "exact_chunks", issue = "47115")]
+impl<'a, T> ExactSizeIterator for ExactChunksMut<'a, T> {
+ fn is_empty(&self) -> bool {
+ self.v.is_empty()
+ }
+}
+
+#[unstable(feature = "fused", issue = "35602")]
+impl<'a, T> FusedIterator for ExactChunksMut<'a, T> {}
+
+#[doc(hidden)]
+unsafe impl<'a, T> TrustedRandomAccess for ExactChunksMut<'a, T> {
+ unsafe fn get_unchecked(&mut self, i: usize) -> &'a mut [T] {
+ let start = i * self.chunk_size;
+ from_raw_parts_mut(self.v.as_mut_ptr().offset(start as isize), self.chunk_size)
+ }
+ fn may_have_side_effect() -> bool { false }
+}
+
//
// Free functions
//
}
}
- #[stable(feature = "str_checked_slicing", since = "1.20.0")]
+ #[unstable(feature = "inclusive_range",
+ reason = "recently added, follows RFC",
+ issue = "28237")]
impl SliceIndex<str> for ops::RangeInclusive<usize> {
type Output = str;
#[inline]
- #[stable(feature = "str_checked_slicing", since = "1.20.0")]
+ #[unstable(feature = "inclusive_range",
+ reason = "recently added, follows RFC",
+ issue = "28237")]
impl SliceIndex<str> for ops::RangeToInclusive<usize> {
type Output = str;
#[inline]
#[inline]
fn next(&mut self) -> SearchStep {
let old_finger = self.finger;
- let slice = unsafe { self.haystack.get_unchecked(old_finger..self.haystack.len()) };
+ let slice = unsafe { self.haystack.get_unchecked(old_finger..self.finger_back) };
let mut iter = slice.chars();
let old_len = iter.iter.len();
if let Some(ch) = iter.next() {
fn next_match(&mut self) -> Option<(usize, usize)> {
loop {
// get the haystack after the last character found
- let bytes = if let Some(slice) = self.haystack.as_bytes().get(self.finger..) {
+ let bytes = if let Some(slice) = self.haystack.as_bytes()
+ .get(self.finger..self.finger_back) {
slice
} else {
return None;
}
} else {
// found nothing, exit
- self.finger = self.haystack.len();
+ self.finger = self.finger_back;
return None;
}
}
#[inline]
fn next_back(&mut self) -> SearchStep {
let old_finger = self.finger_back;
- let slice = unsafe { self.haystack.slice_unchecked(0, old_finger) };
+ let slice = unsafe { self.haystack.slice_unchecked(self.finger, old_finger) };
let mut iter = slice.chars();
let old_len = iter.iter.len();
if let Some(ch) = iter.next_back() {
let haystack = self.haystack.as_bytes();
loop {
// get the haystack up to but not including the last character searched
- let bytes = if let Some(slice) = haystack.get(..self.finger_back) {
+ let bytes = if let Some(slice) = haystack.get(self.finger..self.finger_back) {
slice
} else {
return None;
// the last byte of the utf8 encoded needle
let last_byte = unsafe { *self.utf8_encoded.get_unchecked(self.utf8_size - 1) };
if let Some(index) = memchr::memrchr(last_byte, bytes) {
+ // we searched a slice that was offset by self.finger,
+ // add self.finger to recoup the original index
+ let index = self.finger + index;
// memrchr will return the index of the byte we wish to
// find. In case of an ASCII character, this is indeed
// were we wish our new finger to be ("after" the found
// found the last byte when searching in reverse.
self.finger_back = index;
} else {
- self.finger_back = 0;
+ self.finger_back = self.finger;
// found nothing, exit
return None;
}
$stable_cxchg:meta,
$stable_debug:meta,
$stable_access:meta,
+ $stable_from:meta,
$s_int_type:expr, $int_ref:expr,
$int_type:ident $atomic_type:ident $atomic_init:ident) => {
/// An integer type which can be safely shared between threads.
}
}
- #[stable(feature = "atomic_from", since = "1.23.0")]
+ #[$stable_from]
impl From<$int_type> for $atomic_type {
#[inline]
fn from(v: $int_type) -> Self { Self::new(v) }
unstable(feature = "integer_atomics", issue = "32976"),
unstable(feature = "integer_atomics", issue = "32976"),
unstable(feature = "integer_atomics", issue = "32976"),
+ unstable(feature = "integer_atomics", issue = "32976"),
"i8", "../../../std/primitive.i8.html",
i8 AtomicI8 ATOMIC_I8_INIT
}
unstable(feature = "integer_atomics", issue = "32976"),
unstable(feature = "integer_atomics", issue = "32976"),
unstable(feature = "integer_atomics", issue = "32976"),
+ unstable(feature = "integer_atomics", issue = "32976"),
"u8", "../../../std/primitive.u8.html",
u8 AtomicU8 ATOMIC_U8_INIT
}
unstable(feature = "integer_atomics", issue = "32976"),
unstable(feature = "integer_atomics", issue = "32976"),
unstable(feature = "integer_atomics", issue = "32976"),
+ unstable(feature = "integer_atomics", issue = "32976"),
"i16", "../../../std/primitive.i16.html",
i16 AtomicI16 ATOMIC_I16_INIT
}
unstable(feature = "integer_atomics", issue = "32976"),
unstable(feature = "integer_atomics", issue = "32976"),
unstable(feature = "integer_atomics", issue = "32976"),
+ unstable(feature = "integer_atomics", issue = "32976"),
"u16", "../../../std/primitive.u16.html",
u16 AtomicU16 ATOMIC_U16_INIT
}
unstable(feature = "integer_atomics", issue = "32976"),
unstable(feature = "integer_atomics", issue = "32976"),
unstable(feature = "integer_atomics", issue = "32976"),
+ unstable(feature = "integer_atomics", issue = "32976"),
"i32", "../../../std/primitive.i32.html",
i32 AtomicI32 ATOMIC_I32_INIT
}
unstable(feature = "integer_atomics", issue = "32976"),
unstable(feature = "integer_atomics", issue = "32976"),
unstable(feature = "integer_atomics", issue = "32976"),
+ unstable(feature = "integer_atomics", issue = "32976"),
"u32", "../../../std/primitive.u32.html",
u32 AtomicU32 ATOMIC_U32_INIT
}
unstable(feature = "integer_atomics", issue = "32976"),
unstable(feature = "integer_atomics", issue = "32976"),
unstable(feature = "integer_atomics", issue = "32976"),
+ unstable(feature = "integer_atomics", issue = "32976"),
"i64", "../../../std/primitive.i64.html",
i64 AtomicI64 ATOMIC_I64_INIT
}
unstable(feature = "integer_atomics", issue = "32976"),
unstable(feature = "integer_atomics", issue = "32976"),
unstable(feature = "integer_atomics", issue = "32976"),
+ unstable(feature = "integer_atomics", issue = "32976"),
"u64", "../../../std/primitive.u64.html",
u64 AtomicU64 ATOMIC_U64_INIT
}
stable(feature = "extended_compare_and_swap", since = "1.10.0"),
stable(feature = "atomic_debug", since = "1.3.0"),
stable(feature = "atomic_access", since = "1.15.0"),
+ stable(feature = "atomic_from", since = "1.23.0"),
"isize", "../../../std/primitive.isize.html",
isize AtomicIsize ATOMIC_ISIZE_INIT
}
stable(feature = "extended_compare_and_swap", since = "1.10.0"),
stable(feature = "atomic_debug", since = "1.3.0"),
stable(feature = "atomic_access", since = "1.15.0"),
+ stable(feature = "atomic_from", since = "1.23.0"),
"usize", "../../../std/primitive.usize.html",
usize AtomicUsize ATOMIC_USIZE_INIT
}
assert_eq!((isize::MIN..isize::MAX).step_by(1).size_hint(), (usize::MAX, Some(usize::MAX)));
}
+#[test]
+fn test_range_last_max() {
+ assert_eq!((0..20).last(), Some(19));
+ assert_eq!((-20..0).last(), Some(-1));
+ assert_eq!((5..5).last(), None);
+
+ assert_eq!((0..20).max(), Some(19));
+ assert_eq!((-20..0).max(), Some(-1));
+ assert_eq!((5..5).max(), None);
+}
+
+#[test]
+fn test_range_inclusive_last_max() {
+ assert_eq!((0..=20).last(), Some(20));
+ assert_eq!((-20..=0).last(), Some(0));
+ assert_eq!((5..=5).last(), Some(5));
+ let mut r = 10..=10;
+ r.next();
+ assert_eq!(r.last(), None);
+
+ assert_eq!((0..=20).max(), Some(20));
+ assert_eq!((-20..=0).max(), Some(0));
+ assert_eq!((5..=5).max(), Some(5));
+ let mut r = 10..=10;
+ r.next();
+ assert_eq!(r.max(), None);
+}
+
+#[test]
+fn test_range_min() {
+ assert_eq!((0..20).min(), Some(0));
+ assert_eq!((-20..0).min(), Some(-20));
+ assert_eq!((5..5).min(), None);
+}
+
+#[test]
+fn test_range_inclusive_min() {
+ assert_eq!((0..=20).min(), Some(0));
+ assert_eq!((-20..=0).min(), Some(-20));
+ assert_eq!((5..=5).min(), Some(5));
+ let mut r = 10..=10;
+ r.next();
+ assert_eq!(r.min(), None);
+}
+
#[test]
fn test_repeat() {
let mut it = repeat(42);
#![feature(trusted_len)]
#![feature(try_from)]
#![feature(try_trait)]
-#![feature(unique)]
+#![feature(exact_chunks)]
extern crate core;
extern crate test;
test_impl_from! { test_u32f64, u32, f64 }
// Float -> Float
-#[cfg_attr(all(target_arch = "wasm32", target_os = "emscripten"), ignore)] // issue 42630
#[test]
fn test_f32f64() {
use core::f32;
[InRange(37, 40), Rejects(34, 37), InRange(10, 13), Rejects(8, 10), Done]
);
}
+
+#[test]
+fn double_ended_regression_test() {
+ // https://github.com/rust-lang/rust/issues/47175
+ // Ensures that double ended searching comes to a convergence
+ search_asserts!("abcdeabcdeabcde", 'a', "alternating double ended search",
+ [next_match, next_match_back, next_match, next_match_back],
+ [InRange(0, 1), InRange(10, 11), InRange(5, 6), Done]
+ );
+ search_asserts!("abcdeabcdeabcde", 'a', "triple double ended search for a",
+ [next_match, next_match_back, next_match_back, next_match_back],
+ [InRange(0, 1), InRange(10, 11), InRange(5, 6), Done]
+ );
+ search_asserts!("abcdeabcdeabcde", 'd', "triple double ended search for d",
+ [next_match, next_match_back, next_match_back, next_match_back],
+ [InRange(3, 4), InRange(13, 14), InRange(8, 9), Done]
+ );
+ search_asserts!(STRESS, 'Á', "Double ended search for two-byte Latin character",
+ [next_match, next_match_back, next_match, next_match_back],
+ [InRange(0, 2), InRange(32, 34), InRange(8, 10), Done]
+ );
+ search_asserts!(STRESS, '각', "Reverse double ended search for three-byte Hangul character",
+ [next_match_back, next_back, next_match, next, next_match_back, next_match],
+ [InRange(34, 37), Rejects(32, 34), InRange(19, 22), Rejects(22, 25), InRange(28, 31), Done]
+ );
+ search_asserts!(STRESS, 'ก', "Double ended search for three-byte Thai character",
+ [next_match, next_back, next, next_match_back, next_match],
+ [InRange(22, 25), Rejects(47, 48), Rejects(25, 28), InRange(40, 43), Done]
+ );
+ search_asserts!(STRESS, '😁', "Double ended search for four-byte emoji",
+ [next_match_back, next, next_match, next_back, next_match],
+ [InRange(43, 47), Rejects(0, 2), InRange(15, 19), Rejects(40, 43), Done]
+ );
+ search_asserts!(STRESS, 'ꁁ', "Double ended search for three-byte Yi character with repeated bytes",
+ [next_match, next, next_match_back, next_back, next_match],
+ [InRange(10, 13), Rejects(13, 14), InRange(37, 40), Rejects(34, 37), Done]
+ );
+}
}
#[test]
-fn test_unsized_unique() {
+fn test_unsized_nonnull() {
let xs: &[i32] = &[1, 2, 3];
- let ptr = unsafe { Unique::new_unchecked(xs as *const [i32] as *mut [i32]) };
+ let ptr = unsafe { NonNull::new_unchecked(xs as *const [i32] as *mut [i32]) };
let ys = unsafe { ptr.as_ref() };
let zs: &[i32] = &[1, 2, 3];
assert!(ys == zs);
use core::result::Result::{Ok, Err};
+
+#[test]
+fn test_position() {
+ let b = [1, 2, 3, 5, 5];
+ assert!(b.iter().position(|&v| v == 9) == None);
+ assert!(b.iter().position(|&v| v == 5) == Some(3));
+ assert!(b.iter().position(|&v| v == 3) == Some(2));
+ assert!(b.iter().position(|&v| v == 0) == None);
+}
+
+#[test]
+fn test_rposition() {
+ let b = [1, 2, 3, 5, 5];
+ assert!(b.iter().rposition(|&v| v == 9) == None);
+ assert!(b.iter().rposition(|&v| v == 5) == Some(4));
+ assert!(b.iter().rposition(|&v| v == 3) == Some(2));
+ assert!(b.iter().rposition(|&v| v == 0) == None);
+}
+
#[test]
fn test_binary_search() {
let b: [i32; 0] = [];
fn test_chunks_nth() {
let v: &[i32] = &[0, 1, 2, 3, 4, 5];
let mut c = v.chunks(2);
- assert_eq!(c.nth(1).unwrap()[1], 3);
- assert_eq!(c.next().unwrap()[0], 4);
+ assert_eq!(c.nth(1).unwrap(), &[2, 3]);
+ assert_eq!(c.next().unwrap(), &[4, 5]);
let v2: &[i32] = &[0, 1, 2, 3, 4];
let mut c2 = v2.chunks(3);
- assert_eq!(c2.nth(1).unwrap()[1], 4);
+ assert_eq!(c2.nth(1).unwrap(), &[3, 4]);
assert_eq!(c2.next(), None);
}
assert_eq!(c2.last().unwrap()[0], 4);
}
+#[test]
+fn test_chunks_zip() {
+ let v1: &[i32] = &[0, 1, 2, 3, 4];
+ let v2: &[i32] = &[6, 7, 8, 9, 10];
+
+ let res = v1.chunks(2)
+ .zip(v2.chunks(2))
+ .map(|(a, b)| a.iter().sum::<i32>() + b.iter().sum::<i32>())
+ .collect::<Vec<_>>();
+ assert_eq!(res, vec![14, 22, 14]);
+}
+
#[test]
fn test_chunks_mut_count() {
let v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5];
fn test_chunks_mut_nth() {
let v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5];
let mut c = v.chunks_mut(2);
- assert_eq!(c.nth(1).unwrap()[1], 3);
- assert_eq!(c.next().unwrap()[0], 4);
+ assert_eq!(c.nth(1).unwrap(), &[2, 3]);
+ assert_eq!(c.next().unwrap(), &[4, 5]);
let v2: &mut [i32] = &mut [0, 1, 2, 3, 4];
let mut c2 = v2.chunks_mut(3);
- assert_eq!(c2.nth(1).unwrap()[1], 4);
+ assert_eq!(c2.nth(1).unwrap(), &[3, 4]);
assert_eq!(c2.next(), None);
}
fn test_chunks_mut_last() {
let v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5];
let c = v.chunks_mut(2);
- assert_eq!(c.last().unwrap()[1], 5);
+ assert_eq!(c.last().unwrap(), &[4, 5]);
let v2: &mut [i32] = &mut [0, 1, 2, 3, 4];
let c2 = v2.chunks_mut(2);
- assert_eq!(c2.last().unwrap()[0], 4);
+ assert_eq!(c2.last().unwrap(), &[4]);
+}
+
+#[test]
+fn test_chunks_mut_zip() {
+ let v1: &mut [i32] = &mut [0, 1, 2, 3, 4];
+ let v2: &[i32] = &[6, 7, 8, 9, 10];
+
+ for (a, b) in v1.chunks_mut(2).zip(v2.chunks(2)) {
+ let sum = b.iter().sum::<i32>();
+ for v in a {
+ *v += sum;
+ }
+ }
+ assert_eq!(v1, [13, 14, 19, 20, 14]);
+}
+
+#[test]
+fn test_exact_chunks_count() {
+ let v: &[i32] = &[0, 1, 2, 3, 4, 5];
+ let c = v.exact_chunks(3);
+ assert_eq!(c.count(), 2);
+
+ let v2: &[i32] = &[0, 1, 2, 3, 4];
+ let c2 = v2.exact_chunks(2);
+ assert_eq!(c2.count(), 2);
+
+ let v3: &[i32] = &[];
+ let c3 = v3.exact_chunks(2);
+ assert_eq!(c3.count(), 0);
+}
+
+#[test]
+fn test_exact_chunks_nth() {
+ let v: &[i32] = &[0, 1, 2, 3, 4, 5];
+ let mut c = v.exact_chunks(2);
+ assert_eq!(c.nth(1).unwrap(), &[2, 3]);
+ assert_eq!(c.next().unwrap(), &[4, 5]);
+
+ let v2: &[i32] = &[0, 1, 2, 3, 4, 5, 6];
+ let mut c2 = v2.exact_chunks(3);
+ assert_eq!(c2.nth(1).unwrap(), &[3, 4, 5]);
+ assert_eq!(c2.next(), None);
+}
+
+#[test]
+fn test_exact_chunks_last() {
+ let v: &[i32] = &[0, 1, 2, 3, 4, 5];
+ let c = v.exact_chunks(2);
+ assert_eq!(c.last().unwrap(), &[4, 5]);
+
+ let v2: &[i32] = &[0, 1, 2, 3, 4];
+ let c2 = v2.exact_chunks(2);
+ assert_eq!(c2.last().unwrap(), &[2, 3]);
+}
+
+#[test]
+fn test_exact_chunks_zip() {
+ let v1: &[i32] = &[0, 1, 2, 3, 4];
+ let v2: &[i32] = &[6, 7, 8, 9, 10];
+
+ let res = v1.exact_chunks(2)
+ .zip(v2.exact_chunks(2))
+ .map(|(a, b)| a.iter().sum::<i32>() + b.iter().sum::<i32>())
+ .collect::<Vec<_>>();
+ assert_eq!(res, vec![14, 22]);
+}
+
+#[test]
+fn test_exact_chunks_mut_count() {
+ let v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5];
+ let c = v.exact_chunks_mut(3);
+ assert_eq!(c.count(), 2);
+
+ let v2: &mut [i32] = &mut [0, 1, 2, 3, 4];
+ let c2 = v2.exact_chunks_mut(2);
+ assert_eq!(c2.count(), 2);
+
+ let v3: &mut [i32] = &mut [];
+ let c3 = v3.exact_chunks_mut(2);
+ assert_eq!(c3.count(), 0);
+}
+
+#[test]
+fn test_exact_chunks_mut_nth() {
+ let v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5];
+ let mut c = v.exact_chunks_mut(2);
+ assert_eq!(c.nth(1).unwrap(), &[2, 3]);
+ assert_eq!(c.next().unwrap(), &[4, 5]);
+
+ let v2: &mut [i32] = &mut [0, 1, 2, 3, 4, 5, 6];
+ let mut c2 = v2.exact_chunks_mut(3);
+ assert_eq!(c2.nth(1).unwrap(), &[3, 4, 5]);
+ assert_eq!(c2.next(), None);
+}
+
+#[test]
+fn test_exact_chunks_mut_last() {
+ let v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5];
+ let c = v.exact_chunks_mut(2);
+ assert_eq!(c.last().unwrap(), &[4, 5]);
+
+ let v2: &mut [i32] = &mut [0, 1, 2, 3, 4];
+ let c2 = v2.exact_chunks_mut(2);
+ assert_eq!(c2.last().unwrap(), &[2, 3]);
+}
+
+#[test]
+fn test_exact_chunks_mut_zip() {
+ let v1: &mut [i32] = &mut [0, 1, 2, 3, 4];
+ let v2: &[i32] = &[6, 7, 8, 9, 10];
+
+ for (a, b) in v1.exact_chunks_mut(2).zip(v2.exact_chunks(2)) {
+ let sum = b.iter().sum::<i32>();
+ for v in a {
+ *v += sum;
+ }
+ }
+ assert_eq!(v1, [13, 14, 19, 20, 4]);
}
#[test]
assert_eq!(c2.last().unwrap()[0], 3);
}
+#[test]
+fn test_windows_zip() {
+ let v1: &[i32] = &[0, 1, 2, 3, 4];
+ let v2: &[i32] = &[6, 7, 8, 9, 10];
+
+ let res = v1.windows(2)
+ .zip(v2.windows(2))
+ .map(|(a, b)| a.iter().sum::<i32>() + b.iter().sum::<i32>())
+ .collect::<Vec<_>>();
+
+ assert_eq!(res, [14, 18, 22, 26]);
+}
+
#[test]
fn get_range() {
let v: &[i32] = &[0, 1, 2, 3, 4, 5];
}
#[test]
-fn test_rotate() {
+fn test_rotate_left() {
const N: usize = 600;
let a: &mut [_] = &mut [0; N];
for i in 0..N {
a[i] = i;
}
- a.rotate(42);
+ a.rotate_left(42);
let k = N - 42;
for i in 0..N {
- assert_eq!(a[(i+k)%N], i);
+ assert_eq!(a[(i + k) % N], i);
+ }
+}
+
+#[test]
+fn test_rotate_right() {
+ const N: usize = 600;
+ let a: &mut [_] = &mut [0; N];
+ for i in 0..N {
+ a[i] = i;
+ }
+
+ a.rotate_right(42);
+
+ for i in 0..N {
+ assert_eq!(a[(i + 42) % N], i);
}
}
-Subproject commit ef9eefb6df3f3a2cb989e8050519661faa7d7118
+Subproject commit 2b4cd1016bdba92becb4f982a4dcb18fe6653bc4
pub unsafe extern fn __rust_start_panic(_data: usize, _vtable: usize) -> u32 {
abort();
- #[cfg(unix)]
+ #[cfg(any(unix, target_os = "cloudabi"))]
unsafe fn abort() -> ! {
extern crate libc;
libc::abort();
// i686-pc-windows-gnu and all others
#[cfg(any(all(unix, not(target_os = "emscripten")),
+ target_os = "cloudabi",
target_os = "redox",
all(windows, target_arch = "x86", target_env = "gnu")))]
#[path = "gcc.rs"]
// notify the expansion info that it is unhygienic
let mark = Mark::fresh(mark);
mark.set_expn_info(expn_info);
- let span = call_site.with_ctxt(call_site.ctxt().apply_mark(mark));
+ let span = call_site.with_ctxt(SyntaxContext::empty().apply_mark(mark));
let stream = parse::parse_stream_from_source_str(name, src, sess, Some(span));
Ok(__internal::token_stream_wrap(stream))
})
}
}
+ /// The `Span` for the tokens in the previous macro expansion from which
+ /// `self` was generated from, if any.
+ #[unstable(feature = "proc_macro", issue = "38356")]
+ pub fn parent(&self) -> Option<Span> {
+ self.0.ctxt().outer().expn_info().map(|i| Span(i.call_site))
+ }
+
+ /// The span for the origin source code that `self` was generated from. If
+ /// this `Span` wasn't generated from other macro expansions then the return
+ /// value is the same as `*self`.
+ #[unstable(feature = "proc_macro", issue = "38356")]
+ pub fn source(&self) -> Span {
+ Span(self.0.source_callsite())
+ }
+
/// Get the starting line/column in the source file for this span.
#[unstable(feature = "proc_macro", issue = "38356")]
pub fn start(&self) -> LineColumn {
#[unstable(feature = "proc_macro", issue = "38356")]
pub fn join(&self, other: Span) -> Option<Span> {
let self_loc = __internal::lookup_char_pos(self.0.lo());
- let other_loc = __internal::lookup_char_pos(self.0.lo());
+ let other_loc = __internal::lookup_char_pos(other.0.lo());
if self_loc.file.name != other_loc.file.name { return None }
Some(Span(self.0.to(other.0)))
}
+ /// Creates a new span with the same line/column information as `self` but
+ /// that resolves symbols as though it were at `other`.
+ #[unstable(feature = "proc_macro", issue = "38356")]
+ pub fn resolved_at(&self, other: Span) -> Span {
+ Span(self.0.with_ctxt(other.0.ctxt()))
+ }
+
+ /// Creates a new span with the same name resolution behavior as `self` but
+ /// with the line/column information of `other`.
+ #[unstable(feature = "proc_macro", issue = "38356")]
+ pub fn located_at(&self, other: Span) -> Span {
+ other.resolved_at(*self)
+ }
+
diagnostic_method!(error, Level::Error);
diagnostic_method!(warning, Level::Warning);
diagnostic_method!(note, Level::Note);
fmt_macros = { path = "../libfmt_macros" }
graphviz = { path = "../libgraphviz" }
jobserver = "0.1"
-log = "0.3"
+log = "0.4"
rustc_apfloat = { path = "../librustc_apfloat" }
rustc_back = { path = "../librustc_back" }
rustc_const_math = { path = "../librustc_const_math" }
[] SuperPredicatesOfItem(DefId),
[] TraitDefOfItem(DefId),
[] AdtDefOfItem(DefId),
- [] IsAutoImpl(DefId),
[] ImplTraitRef(DefId),
[] ImplPolarity(DefId),
[] FnSignature(DefId),
[anon] NormalizeTy,
// We use this for most things when incr. comp. is turned off.
[] Null,
+
+ [] SubstituteNormalizeAndTestPredicates { key: (DefId, &'tcx Substs<'tcx>) },
+
+ [input] TargetFeaturesWhitelist,
+ [] TargetFeaturesEnabled(DefId),
+
);
trait DepNodeParams<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> : fmt::Debug {
DepGraphQuery::new(&nodes[..], &edges[..])
}
- pub fn in_ignore<'graph>(&'graph self) -> Option<raii::IgnoreTask<'graph>> {
- self.data.as_ref().map(|data| raii::IgnoreTask::new(&data.current))
+ pub fn assert_ignored(&self)
+ {
+ if let Some(ref data) = self.data {
+ match data.current.borrow().task_stack.last() {
+ Some(&OpenTask::Ignore) | None => {
+ // ignored
+ }
+ _ => panic!("expected an ignore context")
+ }
+ }
}
pub fn with_ignore<OP,R>(&self, op: OP) -> R
where OP: FnOnce() -> R
{
- let _task = self.in_ignore();
+ let _task = self.data.as_ref().map(|data| raii::IgnoreTask::new(&data.current));
op()
}
//! conflicts between multiple such attributes attached to the same
//! item.
-use session::Session;
+use ty::TyCtxt;
-use syntax::ast;
-use syntax::visit;
-use syntax::visit::Visitor;
+use hir;
+use hir::intravisit::{self, Visitor, NestedVisitorMap};
#[derive(Copy, Clone, PartialEq)]
enum Target {
}
impl Target {
- fn from_item(item: &ast::Item) -> Target {
+ fn from_item(item: &hir::Item) -> Target {
match item.node {
- ast::ItemKind::Fn(..) => Target::Fn,
- ast::ItemKind::Struct(..) => Target::Struct,
- ast::ItemKind::Union(..) => Target::Union,
- ast::ItemKind::Enum(..) => Target::Enum,
+ hir::ItemFn(..) => Target::Fn,
+ hir::ItemStruct(..) => Target::Struct,
+ hir::ItemUnion(..) => Target::Union,
+ hir::ItemEnum(..) => Target::Enum,
_ => Target::Other,
}
}
}
-struct CheckAttrVisitor<'a> {
- sess: &'a Session,
+struct CheckAttrVisitor<'a, 'tcx: 'a> {
+ tcx: TyCtxt<'a, 'tcx, 'tcx>,
}
-impl<'a> CheckAttrVisitor<'a> {
+impl<'a, 'tcx> CheckAttrVisitor<'a, 'tcx> {
/// Check any attribute.
- fn check_attributes(&self, item: &ast::Item, target: Target) {
+ fn check_attributes(&self, item: &hir::Item, target: Target) {
+ self.tcx.target_features_enabled(self.tcx.hir.local_def_id(item.id));
+
for attr in &item.attrs {
if let Some(name) = attr.name() {
if name == "inline" {
}
}
}
+
self.check_repr(item, target);
}
/// Check if an `#[inline]` is applied to a function.
- fn check_inline(&self, attr: &ast::Attribute, item: &ast::Item, target: Target) {
+ fn check_inline(&self, attr: &hir::Attribute, item: &hir::Item, target: Target) {
if target != Target::Fn {
- struct_span_err!(self.sess, attr.span, E0518, "attribute should be applied to function")
+ struct_span_err!(self.tcx.sess,
+ attr.span,
+ E0518,
+ "attribute should be applied to function")
.span_label(item.span, "not a function")
.emit();
}
}
/// Check if the `#[repr]` attributes on `item` are valid.
- fn check_repr(&self, item: &ast::Item, target: Target) {
+ fn check_repr(&self, item: &hir::Item, target: Target) {
// Extract the names of all repr hints, e.g., [foo, bar, align] for:
// ```
// #[repr(foo)]
}
_ => continue,
};
- struct_span_err!(self.sess, hint.span, E0517,
+ struct_span_err!(self.tcx.sess, hint.span, E0517,
"attribute should be applied to {}", allowed_targets)
.span_label(item.span, format!("not {} {}", article, allowed_targets))
.emit();
if (int_reprs > 1)
|| (is_simd && is_c)
|| (int_reprs == 1 && is_c && is_c_like_enum(item)) {
- // Just point at all repr hints. This is not ideal, but tracking precisely which ones
- // are at fault is a huge hassle.
+ // Just point at all repr hints. This is not ideal, but tracking
+ // precisely which ones are at fault is a huge hassle.
let spans: Vec<_> = hints.iter().map(|hint| hint.span).collect();
- span_warn!(self.sess, spans, E0566,
+ span_warn!(self.tcx.sess, spans, E0566,
"conflicting representation hints");
}
}
}
-impl<'a> Visitor<'a> for CheckAttrVisitor<'a> {
- fn visit_item(&mut self, item: &'a ast::Item) {
+impl<'a, 'tcx> Visitor<'tcx> for CheckAttrVisitor<'a, 'tcx> {
+ fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+ NestedVisitorMap::None
+ }
+
+ fn visit_item(&mut self, item: &'tcx hir::Item) {
let target = Target::from_item(item);
self.check_attributes(item, target);
- visit::walk_item(self, item);
+ intravisit::walk_item(self, item);
}
}
-pub fn check_crate(sess: &Session, krate: &ast::Crate) {
- visit::walk_crate(&mut CheckAttrVisitor { sess: sess }, krate);
+pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
+ let mut checker = CheckAttrVisitor { tcx };
+ tcx.hir.krate().visit_all_item_likes(&mut checker.as_deep_visitor());
}
-fn is_c_like_enum(item: &ast::Item) -> bool {
- if let ast::ItemKind::Enum(ref def, _) = item.node {
+fn is_c_like_enum(item: &hir::Item) -> bool {
+ if let hir::ItemEnum(ref def, _) = item.node {
for variant in &def.variants {
match variant.node.data {
- ast::VariantData::Unit(_) => { /* continue */ }
+ hir::VariantData::Unit(_) => { /* continue */ }
_ => { return false; }
}
}
/// particular definition. It should really be considered an interned
/// shorthand for a particular DefPath.
///
-/// At the moment we are allocating the numerical values of DefIndexes into two
-/// ranges: the "low" range (starting at zero) and the "high" range (starting at
-/// DEF_INDEX_HI_START). This allows us to allocate the DefIndexes of all
-/// item-likes (Items, TraitItems, and ImplItems) into one of these ranges and
+/// At the moment we are allocating the numerical values of DefIndexes from two
+/// address spaces: DefIndexAddressSpace::Low and DefIndexAddressSpace::High.
+/// This allows us to allocate the DefIndexes of all item-likes
+/// (Items, TraitItems, and ImplItems) into one of these spaces and
/// consequently use a simple array for lookup tables keyed by DefIndex and
/// known to be densely populated. This is especially important for the HIR map.
///
/// Since the DefIndex is mostly treated as an opaque ID, you probably
-/// don't have to care about these ranges.
-newtype_index!(DefIndex
- {
- ENCODABLE = custom
- DEBUG_FORMAT = custom,
+/// don't have to care about these address spaces.
- /// The start of the "high" range of DefIndexes.
- const DEF_INDEX_HI_START = 1 << 31,
+#[derive(Clone, Eq, Ord, PartialOrd, PartialEq, Hash, Copy)]
+pub struct DefIndex(u32);
+
+/// The crate root is always assigned index 0 by the AST Map code,
+/// thanks to `NodeCollector::new`.
+pub const CRATE_DEF_INDEX: DefIndex = DefIndex(0);
- /// The crate root is always assigned index 0 by the AST Map code,
- /// thanks to `NodeCollector::new`.
- const CRATE_DEF_INDEX = 0,
- });
impl fmt::Debug for DefIndex {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
impl DefIndex {
#[inline]
- pub fn from_u32(x: u32) -> DefIndex {
- DefIndex(x)
+ pub fn address_space(&self) -> DefIndexAddressSpace {
+ match self.0 & 1 {
+ 0 => DefIndexAddressSpace::Low,
+ 1 => DefIndexAddressSpace::High,
+ _ => unreachable!()
+ }
}
+ /// Converts this DefIndex into a zero-based array index.
+ /// This index is the offset within the given DefIndexAddressSpace.
#[inline]
- pub fn as_usize(&self) -> usize {
- self.0 as usize
+ pub fn as_array_index(&self) -> usize {
+ (self.0 >> 1) as usize
}
#[inline]
- pub fn as_u32(&self) -> u32 {
- self.0
+ pub fn from_array_index(i: usize, address_space: DefIndexAddressSpace) -> DefIndex {
+ DefIndex::from_raw_u32(((i << 1) | (address_space as usize)) as u32)
}
- #[inline]
- pub fn address_space(&self) -> DefIndexAddressSpace {
- if self.0 < DEF_INDEX_HI_START.0 {
- DefIndexAddressSpace::Low
- } else {
- DefIndexAddressSpace::High
- }
+ // Proc macros from a proc-macro crate have a kind of virtual DefIndex. This
+ // function maps the index of the macro within the crate (which is also the
+ // index of the macro in the CrateMetadata::proc_macros array) to the
+ // corresponding DefIndex.
+ pub fn from_proc_macro_index(proc_macro_index: usize) -> DefIndex {
+ let def_index = DefIndex::from_array_index(proc_macro_index,
+ DefIndexAddressSpace::High);
+ assert!(def_index != CRATE_DEF_INDEX);
+ def_index
}
- /// Converts this DefIndex into a zero-based array index.
- /// This index is the offset within the given "range" of the DefIndex,
- /// that is, if the DefIndex is part of the "high" range, the resulting
- /// index will be (DefIndex - DEF_INDEX_HI_START).
- #[inline]
- pub fn as_array_index(&self) -> usize {
- (self.0 & !DEF_INDEX_HI_START.0) as usize
+ // This function is the reverse of from_proc_macro_index() above.
+ pub fn to_proc_macro_index(self: DefIndex) -> usize {
+ self.as_array_index()
}
- pub fn from_array_index(i: usize, address_space: DefIndexAddressSpace) -> DefIndex {
- DefIndex::new(address_space.start() + i)
+ // Don't use this if you don't know about the DefIndex encoding.
+ pub fn from_raw_u32(x: u32) -> DefIndex {
+ DefIndex(x)
+ }
+
+ // Don't use this if you don't know about the DefIndex encoding.
+ pub fn as_raw_u32(&self) -> u32 {
+ self.0
}
}
pub fn index(&self) -> usize {
*self as usize
}
-
- #[inline]
- pub fn start(&self) -> usize {
- self.index() * DEF_INDEX_HI_START.as_usize()
- }
}
/// A DefId identifies a particular *definition*, by combining a crate
// visit_enum_def() takes care of visiting the Item's NodeId
visitor.visit_enum_def(enum_definition, type_parameters, item.id, item.span)
}
- ItemAutoImpl(_, ref trait_ref) => {
- visitor.visit_id(item.id);
- visitor.visit_trait_ref(trait_ref)
- }
ItemImpl(.., ref type_parameters, ref opt_trait_reference, ref typ, ref impl_item_refs) => {
visitor.visit_id(item.id);
visitor.visit_generics(type_parameters);
// We're constructing the HIR here; we don't care what we will
// read, since we haven't even constructed the *input* to
// incr. comp. yet.
- let _ignore = dep_graph.in_ignore();
+ dep_graph.assert_ignored();
LoweringContext {
crate_root: std_inject::injected_crate_name(),
);
let hir_bounds = self.lower_bounds(bounds, itctx);
+ // Set the name to `impl Bound1 + Bound2`
+ let name = Symbol::intern(&pprust::ty_to_string(t));
self.in_band_ty_params.push(hir::TyParam {
- // Set the name to `impl Bound1 + Bound2`
- name: Symbol::intern(&pprust::ty_to_string(t)),
+ name,
id: def_node_id,
bounds: hir_bounds,
default: None,
hir::TyPath(hir::QPath::Resolved(None, P(hir::Path {
span,
def: Def::TyParam(DefId::local(def_index)),
- segments: vec![].into(),
+ segments: hir_vec![hir::PathSegment::from_name(name)],
})))
},
ImplTraitContext::Disallowed => {
fn_def_id: Option<DefId>,
impl_trait_return_allow: bool)
-> P<hir::FnDecl> {
- // NOTE: The two last paramters here have to do with impl Trait. If fn_def_id is Some,
- // then impl Trait arguments are lowered into generic paramters on the given
+ // NOTE: The two last parameters here have to do with impl Trait. If fn_def_id is Some,
+ // then impl Trait arguments are lowered into generic parameters on the given
// fn_def_id, otherwise impl Trait is disallowed. (for now)
//
// Furthermore, if impl_trait_return_allow is true, then impl Trait may be used in
let vdata = self.lower_variant_data(vdata);
hir::ItemUnion(vdata, self.lower_generics(generics))
}
- ItemKind::AutoImpl(unsafety, ref trait_ref) => {
- let trait_ref = self.lower_trait_ref(trait_ref, ImplTraitContext::Disallowed);
-
- if let Def::Trait(def_id) = trait_ref.path.def {
- self.trait_auto_impl.insert(def_id, id);
- }
-
- hir::ItemAutoImpl(self.lower_unsafety(unsafety),
- trait_ref)
- }
ItemKind::Impl(unsafety,
polarity,
defaultness,
// Privatize the degenerate import base, used only to check
// the stability of `use a::{};`, to avoid it showing up as
- // a reexport by accident when `pub`, e.g. in documentation.
+ // a re-export by accident when `pub`, e.g. in documentation.
let path = P(self.lower_path(id, &prefix, ParamMode::Explicit, true));
*vis = hir::Inherited;
hir::ItemUse(path, hir::UseKind::ListStem)
// Pick the def data. This need not be unique, but the more
// information we encapsulate into
let def_data = match i.node {
- ItemKind::AutoImpl(..) | ItemKind::Impl(..) =>
- DefPathData::Impl,
+ ItemKind::Impl(..) => DefPathData::Impl,
ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..) |
ItemKind::Trait(..) | ItemKind::TraitAlias(..) |
ItemKind::ExternCrate(..) | ItemKind::ForeignMod(..) | ItemKind::Ty(..) =>
CRATE_DEF_INDEX};
use ich::Fingerprint;
use rustc_data_structures::fx::FxHashMap;
-use rustc_data_structures::indexed_vec::{IndexVec, Idx};
+use rustc_data_structures::indexed_vec::{IndexVec};
use rustc_data_structures::stable_hasher::StableHasher;
use serialize::{Encodable, Decodable, Encoder, Decoder};
use session::CrateDisambiguator;
-> DefIndex {
let index = {
let index_to_key = &mut self.index_to_key[address_space.index()];
- let index = DefIndex::new(index_to_key.len() + address_space.start());
+ let index = DefIndex::from_array_index(index_to_key.len(), address_space);
debug!("DefPathTable::insert() - {:?} <-> {:?}", key, index);
index_to_key.push(key);
index
pub fn add_def_path_hashes_to(&self,
cnum: CrateNum,
out: &mut FxHashMap<DefPathHash, DefId>) {
- for address_space in &[DefIndexAddressSpace::Low, DefIndexAddressSpace::High] {
- let start_index = address_space.start();
+ for &address_space in &[DefIndexAddressSpace::Low, DefIndexAddressSpace::High] {
out.extend(
(&self.def_path_hashes[address_space.index()])
.iter()
.map(|(index, &hash)| {
let def_id = DefId {
krate: cnum,
- index: DefIndex::new(index + start_index),
+ index: DefIndex::from_array_index(index, address_space),
};
(hash, def_id)
})
errors: vec![],
};
- hir_map.dep_graph.with_ignore(|| {
- hir_map.krate().visit_all_item_likes(&mut outer_visitor);
- if !outer_visitor.errors.is_empty() {
- let message = outer_visitor
- .errors
- .iter()
- .fold(String::new(), |s1, s2| s1 + "\n" + s2);
- bug!("{}", message);
- }
- });
+ hir_map.dep_graph.assert_ignored();
+
+ hir_map.krate().visit_all_item_likes(&mut outer_visitor);
+ if !outer_visitor.errors.is_empty() {
+ let message = outer_visitor
+ .errors
+ .iter()
+ .fold(String::new(), |s1, s2| s1 + "\n" + s2);
+ bug!("{}", message);
+ }
}
struct HirIdValidator<'a, 'hir: 'a> {
cmdline_args)
};
- if log_enabled!(::log::LogLevel::Debug) {
+ if log_enabled!(::log::Level::Debug) {
// This only makes sense for ordered stores; note the
// enumerate to count the number of entries.
let (entries_less_1, _) = map.iter().filter(|&x| {
ItemTrait(..) => "trait",
ItemTraitAlias(..) => "trait alias",
ItemImpl(..) => "impl",
- ItemAutoImpl(..) => "default impl",
};
format!("{} {}{}", item_str, path_str(), id_str)
}
}
/// A "Path" is essentially Rust's notion of a name; for instance:
-/// std::cmp::PartialEq . It's represented as a sequence of identifiers,
+/// `std::cmp::PartialEq`. It's represented as a sequence of identifiers,
/// along with a bunch of supporting information.
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash)]
pub struct Path {
/// Represents a Trait Alias Declaration
ItemTraitAlias(Generics, TyParamBounds),
- /// Auto trait implementations
- ///
- /// `impl Trait for .. {}`
- ItemAutoImpl(Unsafety, TraitRef),
/// An implementation, eg `impl<A> Trait for Foo { .. }`
ItemImpl(Unsafety,
ImplPolarity,
ItemUnion(..) => "union",
ItemTrait(..) => "trait",
ItemTraitAlias(..) => "trait alias",
- ItemImpl(..) |
- ItemAutoImpl(..) => "item",
+ ItemImpl(..) => "item",
}
}
self.head(&visibility_qualified(&item.vis, "union"))?;
self.print_struct(struct_def, generics, item.name, item.span, true)?;
}
- hir::ItemAutoImpl(unsafety, ref trait_ref) => {
- self.head("")?;
- self.print_visibility(&item.vis)?;
- self.print_unsafety(unsafety)?;
- self.word_nbsp("impl")?;
- self.print_trait_ref(trait_ref)?;
- self.s.space()?;
- self.word_space("for")?;
- self.word_space("..")?;
- self.bopen()?;
- self.bclose(item.span)?;
- }
hir::ItemImpl(unsafety,
polarity,
defaultness,
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use std::mem;
use rustc_data_structures::stable_hasher;
+use serialize;
+use serialize::opaque::{EncodeResult, Encoder, Decoder};
-#[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Clone, Copy, RustcEncodable, RustcDecodable)]
+#[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Clone, Copy)]
pub struct Fingerprint(u64, u64);
impl Fingerprint {
format!("{:x}{:x}", self.0, self.1)
}
+ pub fn encode_opaque(&self, encoder: &mut Encoder) -> EncodeResult {
+ let bytes: [u8; 16] = unsafe { mem::transmute([self.0.to_le(), self.1.to_le()]) };
+
+ encoder.emit_raw_bytes(&bytes)
+ }
+
+ pub fn decode_opaque<'a>(decoder: &mut Decoder<'a>) -> Result<Fingerprint, String> {
+ let mut bytes = [0; 16];
+
+ decoder.read_raw_bytes(&mut bytes)?;
+
+ let [l, r]: [u64; 2] = unsafe { mem::transmute(bytes) };
+
+ Ok(Fingerprint(u64::from_le(l), u64::from_le(r)))
+ }
}
impl ::std::fmt::Display for Fingerprint {
::std::hash::Hash::hash(self, hasher);
}
}
+
+impl serialize::UseSpecializedEncodable for Fingerprint { }
+
+impl serialize::UseSpecializedDecodable for Fingerprint { }
+
+impl<'a> serialize::SpecializedEncoder<Fingerprint> for serialize::opaque::Encoder<'a> {
+ fn specialized_encode(&mut self, f: &Fingerprint) -> Result<(), Self::Error> {
+ f.encode_opaque(self)
+ }
+}
+
+impl<'a> serialize::SpecializedDecoder<Fingerprint> for serialize::opaque::Decoder<'a> {
+ fn specialized_decode(&mut self) -> Result<Fingerprint, Self::Error> {
+ Fingerprint::decode_opaque(self)
+ }
+}
ItemUnion(variant_data, generics),
ItemTrait(is_auto, unsafety, generics, bounds, item_refs),
ItemTraitAlias(generics, bounds),
- ItemAutoImpl(unsafety, trait_ref),
ItemImpl(unsafety, impl_polarity, impl_defaultness, generics, trait_ref, ty, impl_item_refs)
});
Bool(value)
});
-impl_stable_hash_for!(enum ::syntax::ast::IntTy { Is, I8, I16, I32, I64, I128 });
-impl_stable_hash_for!(enum ::syntax::ast::UintTy { Us, U8, U16, U32, U64, U128 });
+impl_stable_hash_for!(enum ::syntax::ast::IntTy { Isize, I8, I16, I32, I64, I128 });
+impl_stable_hash_for!(enum ::syntax::ast::UintTy { Usize, U8, U16, U32, U64, U128 });
impl_stable_hash_for!(enum ::syntax::ast::FloatTy { F32, F64 });
impl_stable_hash_for!(enum ::syntax::ast::Unsafety { Unsafe, Normal });
impl_stable_hash_for!(enum ::syntax::ast::Constness { Const, NotConst });
.emit();
return Some(ErrorReported);
}
+
+ // This method returns whether the given Region is Named
+ pub(super) fn is_named_region(&self, region: ty::Region<'tcx>) -> bool {
+ match *region {
+ ty::ReStatic => true,
+ ty::ReFree(ref free_region) => match free_region.bound_region {
+ ty::BrNamed(..) => true,
+ _ => false,
+ },
+ ty::ReEarlyBound(_) => true,
+ _ => false,
+ }
+ }
}
}
false
}
-
- // This method returns whether the given Region is Named
- pub(super) fn is_named_region(&self, region: Region<'tcx>) -> bool {
- match *region {
- ty::ReFree(ref free_region) => match free_region.bound_region {
- ty::BrNamed(..) => true,
- _ => false,
- },
- ty::ReEarlyBound(_) => true,
- _ => false,
- }
- }
}
use graphviz as dot;
use hir::def_id::DefIndex;
-use rustc_data_structures::indexed_vec::Idx;
use ty;
use middle::free_region::RegionRelations;
use middle::region;
}
let requested_node = env::var("RUST_REGION_GRAPH_NODE")
- .ok().and_then(|s| s.parse().map(DefIndex::new).ok());
+ .ok().and_then(|s| s.parse().map(DefIndex::from_raw_u32).ok());
if requested_node.is_some() && requested_node != Some(context.index) {
return;
let mut new_str = String::new();
for c in output_template.chars() {
if c == '%' {
- new_str.push_str(&context.index.as_usize().to_string());
+ new_str.push_str(&context.index.as_raw_u32().to_string());
} else {
new_str.push(c);
}
#![feature(drain_filter)]
#![feature(dyn_trait)]
#![feature(from_ref)]
+#![feature(fs_read_write)]
#![feature(i128)]
#![feature(i128_type)]
#![feature(inclusive_range)]
// Build the diagnostics array at the end so that the metadata includes error use sites.
+#[cfg(not(stage0))] // remove after the next snapshot
__build_diagnostic_array! { librustc, DIAGNOSTICS }
declare_lint! {
pub PUB_USE_OF_PRIVATE_EXTERN_CRATE,
Deny,
- "detect public reexports of private extern crates"
+ "detect public re-exports of private extern crates"
}
declare_lint! {
// calculated the lint levels for all AST nodes.
for (_id, lints) in cx.buffered.map {
for early_lint in lints {
- span_bug!(early_lint.span, "failed to process bufferd lint here");
+ span_bug!(early_lint.span, "failed to process buffered lint here");
}
}
}
/// Declare a static `LintArray` and return it as an expression.
#[macro_export]
-macro_rules! lint_array { ($( $lint:expr ),*) => (
- {
- static ARRAY: LintArray = &[ $( &$lint ),* ];
- ARRAY
- }
-) }
+macro_rules! lint_array {
+ ($( $lint:expr ),*,) => { lint_array!( $( $lint ),* ) };
+ ($( $lint:expr ),*) => {{
+ static ARRAY: LintArray = &[ $( &$lint ),* ];
+ ARRAY
+ }}
+}
pub type LintArray = &'static [&'static &'static Lint];
tcx: TyCtxt<'a, 'tcx, 'tcx>,
tables: &'a ty::TypeckTables<'tcx>,
live_symbols: Box<FxHashSet<ast::NodeId>>,
- struct_has_extern_repr: bool,
+ repr_has_repr_c: bool,
in_pat: bool,
inherited_pub_visibility: bool,
ignore_variant_stack: Vec<DefId>,
fn handle_field_access(&mut self, lhs: &hir::Expr, name: ast::Name) {
match self.tables.expr_ty_adjusted(lhs).sty {
ty::TyAdt(def, _) => {
- self.insert_def_id(def.struct_variant().field_named(name).did);
+ self.insert_def_id(def.non_enum_variant().field_named(name).did);
}
_ => span_bug!(lhs.span, "named field access on non-ADT"),
}
fn handle_tup_field_access(&mut self, lhs: &hir::Expr, idx: usize) {
match self.tables.expr_ty_adjusted(lhs).sty {
ty::TyAdt(def, _) => {
- self.insert_def_id(def.struct_variant().fields[idx].did);
+ self.insert_def_id(def.non_enum_variant().fields[idx].did);
}
ty::TyTuple(..) => {}
_ => span_bug!(lhs.span, "numeric field access on non-ADT"),
}
fn visit_node(&mut self, node: &hir_map::Node<'tcx>) {
- let had_extern_repr = self.struct_has_extern_repr;
- self.struct_has_extern_repr = false;
+ let had_repr_c = self.repr_has_repr_c;
+ self.repr_has_repr_c = false;
let had_inherited_pub_visibility = self.inherited_pub_visibility;
self.inherited_pub_visibility = false;
match *node {
hir::ItemStruct(..) | hir::ItemUnion(..) => {
let def_id = self.tcx.hir.local_def_id(item.id);
let def = self.tcx.adt_def(def_id);
- self.struct_has_extern_repr = def.repr.c();
+ self.repr_has_repr_c = def.repr.c();
intravisit::walk_item(self, &item);
}
}
_ => ()
}
- self.struct_has_extern_repr = had_extern_repr;
+ self.repr_has_repr_c = had_repr_c;
self.inherited_pub_visibility = had_inherited_pub_visibility;
}
fn visit_variant_data(&mut self, def: &'tcx hir::VariantData, _: ast::Name,
_: &hir::Generics, _: ast::NodeId, _: syntax_pos::Span) {
- let has_extern_repr = self.struct_has_extern_repr;
+ let has_repr_c = self.repr_has_repr_c;
let inherited_pub_visibility = self.inherited_pub_visibility;
let live_fields = def.fields().iter().filter(|f| {
- has_extern_repr || inherited_pub_visibility || f.vis == hir::Public
+ has_repr_c || inherited_pub_visibility || f.vis == hir::Public
});
self.live_symbols.extend(live_fields.map(|f| f.id));
tcx,
tables: &ty::TypeckTables::empty(None),
live_symbols: box FxHashSet(),
- struct_has_extern_repr: false,
+ repr_has_repr_c: false,
in_pat: false,
inherited_pub_visibility: false,
ignore_variant_stack: vec![],
hir::ItemStruct(..) |
hir::ItemUnion(..) |
hir::ItemTrait(..) |
- hir::ItemAutoImpl(..) |
hir::ItemImpl(..) => self.tcx.sess.codemap().def_span(item.span),
_ => item.span,
};
match with_cmt.ty.sty {
ty::TyAdt(adt, substs) if adt.is_struct() => {
// Consume those fields of the with expression that are needed.
- for with_field in &adt.struct_variant().fields {
+ for with_field in &adt.non_enum_variant().fields {
if !contains_field_named(with_field, fields) {
let cmt_field = self.mc.cat_field(
&*with_expr,
Def::StructCtor(_, CtorKind::Fn) => {
match self.pat_ty(&pat)?.sty {
ty::TyAdt(adt_def, _) => {
- (cmt, adt_def.struct_variant().fields.len())
+ (cmt, adt_def.non_enum_variant().fields.len())
}
ref ty => {
span_bug!(pat.span, "tuple struct pattern unexpected type {:?}", ty);
// public, then type `T` is reachable. Its values can be obtained by other crates
// even if the type itself is not nameable.
Reachable,
- // Public items + items accessible to other crates with help of `pub use` reexports
+ // Public items + items accessible to other crates with help of `pub use` re-exports
Exported,
- // Items accessible to other crates directly, without help of reexports
+ // Items accessible to other crates directly, without help of re-exports
Public,
}
hir::ItemMod(..) | hir::ItemForeignMod(..) |
hir::ItemImpl(..) | hir::ItemTrait(..) | hir::ItemTraitAlias(..) |
hir::ItemStruct(..) | hir::ItemEnum(..) |
- hir::ItemUnion(..) | hir::ItemAutoImpl(..) |
- hir::ItemGlobalAsm(..) => {}
+ hir::ItemUnion(..) | hir::ItemGlobalAsm(..) => {}
}
}
hir_map::NodeTraitItem(trait_method) => {
intravisit::walk_item(this, item);
});
}
+
hir::ItemExternCrate(_)
| hir::ItemUse(..)
| hir::ItemMod(..)
- | hir::ItemAutoImpl(..)
| hir::ItemForeignMod(..)
| hir::ItemGlobalAsm(..) => {
// These sorts of items have no lifetime parameters at all.
}
-#[derive(Copy, Clone, Eq, Hash, Ord, PartialEq, PartialOrd, Debug)]
+#[derive(Copy, Clone, Default, Eq, Hash, Ord, PartialEq, PartialOrd, Debug)]
pub struct AllocId(pub u64);
impl fmt::Display for AllocId {
use syntax::symbol::InternedString;
use ty::Instance;
use util::nodemap::FxHashMap;
+use rustc_data_structures::base_n;
use rustc_data_structures::stable_hasher::{HashStable, StableHasherResult,
StableHasher};
use ich::{Fingerprint, StableHashingContext, NodeIdHashingMode};
+use std::hash::Hash;
#[derive(PartialEq, Eq, Clone, Copy, Debug, Hash)]
pub enum MonoItem<'tcx> {
{
&mut self.items
}
+
+ pub fn mangle_name(human_readable_name: &str) -> String {
+ // We generate a 80 bit hash from the name. This should be enough to
+ // avoid collisions and is still reasonably short for filenames.
+ let mut hasher = StableHasher::new();
+ human_readable_name.hash(&mut hasher);
+ let hash: u128 = hasher.finish();
+ let hash = hash & ((1u128 << 80) - 1);
+ base_n::encode(hash, base_n::CASE_INSENSITIVE)
+ }
}
impl<'tcx> HashStable<StableHashingContext<'tcx>> for CodegenUnit<'tcx> {
"gather borrowck statistics"),
no_landing_pads: bool = (false, parse_bool, [TRACKED],
"omit landing pads for unwinding"),
- debug_llvm: bool = (false, parse_bool, [UNTRACKED],
- "enable debug output from LLVM"),
+ fewer_names: bool = (false, parse_bool, [TRACKED],
+ "reduce memory use by retaining fewer names within compilation artifacts (LLVM-IR)"),
meta_stats: bool = (false, parse_bool, [UNTRACKED],
"gather metadata statistics"),
print_link_args: bool = (false, parse_bool, [UNTRACKED],
"emit noalias metadata for mutable references"),
dump_mir: Option<String> = (None, parse_opt_string, [UNTRACKED],
"dump MIR state at various points in translation"),
- dump_mir_dir: Option<String> = (None, parse_opt_string, [UNTRACKED],
+ dump_mir_dir: String = (String::from("mir_dump"), parse_string, [UNTRACKED],
"the directory the MIR is dumped into"),
dump_mir_graphviz: bool = (false, parse_bool, [UNTRACKED],
"in addition to `.mir` files, create graphviz `.dot` files"),
"rewrite operators on i128 and u128 into lang item calls (typically provided \
by compiler-builtins) so translation doesn't need to support them,
overriding the default for the current target"),
+ human_readable_cgu_names: bool = (false, parse_bool, [TRACKED],
+ "generate human-readable, predictable names for codegen units"),
+ dep_info_omit_d_target: bool = (false, parse_bool, [TRACKED],
+ "in dep-info output, omit targets for tracking dependencies of the dep-info files \
+ themselves"),
}
pub fn default_lib_output() -> CrateType {
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.debugging_opts.borrowck_stats = true;
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
- opts.debugging_opts.debug_llvm = true;
- assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.debugging_opts.meta_stats = true;
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.debugging_opts.print_link_args = true;
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.debugging_opts.dump_mir = Some(String::from("abc"));
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
- opts.debugging_opts.dump_mir_dir = Some(String::from("abc"));
+ opts.debugging_opts.dump_mir_dir = String::from("abc");
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.debugging_opts.dump_mir_graphviz = true;
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.debugging_opts.no_landing_pads = true;
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
+ opts = reference.clone();
+ opts.debugging_opts.fewer_names = true;
+ assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
+
opts = reference.clone();
opts.debugging_opts.no_trans = true;
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
pub use self::code_stats::{CodeStats, DataTypeKind, FieldInfo};
pub use self::code_stats::{SizeKind, TypeSizeInfo, VariantInfo};
-use hir::def_id::{CrateNum, DefIndex};
+use hir::def_id::CrateNum;
use ich::Fingerprint;
use lint;
use middle::allocator::AllocatorKind;
use middle::dependency_format;
use session::search_paths::PathKind;
-use session::config::{BorrowckMode, DebugInfoLevel};
+use session::config::{BorrowckMode, DebugInfoLevel, OutputType};
use ty::tls;
use util::nodemap::{FxHashMap, FxHashSet};
use util::common::{duration_to_secs_str, ErrorReported};
pub fn linker_flavor(&self) -> LinkerFlavor {
self.opts.debugging_opts.linker_flavor.unwrap_or(self.target.target.linker_flavor)
}
+
+ pub fn fewer_names(&self) -> bool {
+ let more_names = self.opts.output_types.contains_key(&OutputType::LlvmAssembly) ||
+ self.opts.output_types.contains_key(&OutputType::Bitcode);
+ self.opts.debugging_opts.fewer_names || !more_names
+ }
+
pub fn no_landing_pads(&self) -> bool {
self.opts.debugging_opts.no_landing_pads || self.panic_strategy() == PanicStrategy::Abort
}
/// Returns the symbol name for the registrar function,
/// given the crate Svh and the function DefIndex.
- pub fn generate_plugin_registrar_symbol(&self, disambiguator: CrateDisambiguator,
- index: DefIndex)
+ pub fn generate_plugin_registrar_symbol(&self,
+ disambiguator: CrateDisambiguator)
-> String {
- format!("__rustc_plugin_registrar__{}_{}", disambiguator.to_fingerprint().to_hex(),
- index.as_usize())
+ format!("__rustc_plugin_registrar_{}__", disambiguator.to_fingerprint().to_hex())
}
- pub fn generate_derive_registrar_symbol(&self, disambiguator: CrateDisambiguator,
- index: DefIndex)
+ pub fn generate_derive_registrar_symbol(&self,
+ disambiguator: CrateDisambiguator)
-> String {
- format!("__rustc_derive_registrar__{}_{}", disambiguator.to_fingerprint().to_hex(),
- index.as_usize())
+ format!("__rustc_derive_registrar_{}__", disambiguator.to_fingerprint().to_hex())
}
pub fn sysroot<'a>(&'a self) -> &'a Path {
IncrCompSession::Active { ref session_directory, .. } => {
session_directory.clone()
}
+ IncrCompSession::InvalidBecauseOfErrors { .. } => return,
_ => bug!("Trying to invalidate IncrCompSession `{:?}`",
*incr_comp_session),
};
}
ObligationCauseCode::ItemObligation(item_def_id) => {
let item_name = tcx.item_path_str(item_def_id);
- err.note(&format!("required by `{}`", item_name));
+ let msg = format!("required by `{}`", item_name);
+ if let Some(sp) = tcx.hir.span_if_local(item_def_id) {
+ let sp = tcx.sess.codemap().def_span(sp);
+ err.span_note(sp, &msg);
+ } else {
+ err.note(&msg);
+ }
}
ObligationCauseCode::ObjectCastObligation(object_ty) => {
err.note(&format!("required for the cast to the object type `{}`",
/// environment. If this returns false, then either normalize
/// encountered an error or one of the predicates did not hold. Used
/// when creating vtables to check for unsatisfiable methods.
-pub fn normalize_and_test_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
- predicates: Vec<ty::Predicate<'tcx>>)
- -> bool
+fn normalize_and_test_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+ predicates: Vec<ty::Predicate<'tcx>>)
+ -> bool
{
debug!("normalize_and_test_predicates(predicates={:?})",
predicates);
result
}
+fn substitute_normalize_and_test_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+ key: (DefId, &'tcx Substs<'tcx>))
+ -> bool
+{
+ use ty::subst::Subst;
+ debug!("substitute_normalize_and_test_predicates(key={:?})",
+ key);
+
+ let predicates = tcx.predicates_of(key.0).predicates.subst(tcx, key.1);
+ let result = normalize_and_test_predicates(tcx, predicates);
+
+ debug!("substitute_normalize_and_test_predicates(key={:?}) = {:?}",
+ key, result);
+ result
+}
+
/// Given a trait `trait_ref`, iterates the vtable entries
/// that come from `trait_ref`, including its supertraits.
#[inline] // FIXME(#35870) Avoid closures being unexported due to impl Trait.
specializes: specialize::specializes,
trans_fulfill_obligation: trans::trans_fulfill_obligation,
vtable_methods,
+ substitute_normalize_and_test_predicates,
..*providers
};
}
VtableBuiltinData { nested: obligations }
}
- /// This handles the case where a `impl Foo for ..` impl is being used.
+ /// This handles the case where a `auto trait Foo` impl is being used.
/// The idea is that the impl applies to `X : Foo` if the following conditions are met:
///
/// 1. For each constituent type `Y` in `X`, `Y : Foo` holds
/*!
* Creates a cause for obligations that are derived from
* `obligation` by a recursive search (e.g., for a builtin
- * bound, or eventually a `impl Foo for ..`). If `obligation`
+ * bound, or eventually a `auto trait Foo`). If `obligation`
* is itself a derived obligation, this is just a clone, but
* otherwise we create a "derived obligation" cause so as to
* keep track of the original root obligation for error
char: mk(TyChar),
never: mk(TyNever),
err: mk(TyError),
- isize: mk(TyInt(ast::IntTy::Is)),
+ isize: mk(TyInt(ast::IntTy::Isize)),
i8: mk(TyInt(ast::IntTy::I8)),
i16: mk(TyInt(ast::IntTy::I16)),
i32: mk(TyInt(ast::IntTy::I32)),
i64: mk(TyInt(ast::IntTy::I64)),
i128: mk(TyInt(ast::IntTy::I128)),
- usize: mk(TyUint(ast::UintTy::Us)),
+ usize: mk(TyUint(ast::UintTy::Usize)),
u8: mk(TyUint(ast::UintTy::U8)),
u16: mk(TyUint(ast::UintTy::U16)),
u32: mk(TyUint(ast::UintTy::U32)),
allocs: FxHashSet<&'tcx interpret::Allocation>,
/// Allows obtaining function instance handles via a unique identifier
- functions: FxHashMap<u64, Instance<'tcx>>,
+ functions: FxHashMap<interpret::AllocId, Instance<'tcx>>,
/// Inverse map of `interpret_functions`.
/// Used so we don't allocate a new pointer every time we need one
- function_cache: FxHashMap<Instance<'tcx>, u64>,
+ function_cache: FxHashMap<Instance<'tcx>, interpret::AllocId>,
/// Allows obtaining const allocs via a unique identifier
- alloc_by_id: FxHashMap<u64, &'tcx interpret::Allocation>,
+ alloc_by_id: FxHashMap<interpret::AllocId, &'tcx interpret::Allocation>,
/// The AllocId to assign to the next new regular allocation.
/// Always incremented, never gets smaller.
- next_id: u64,
+ next_id: interpret::AllocId,
/// Allows checking whether a constant already has an allocation
- ///
- /// The pointers are to the beginning of an `alloc_by_id` allocation
- alloc_cache: FxHashMap<interpret::GlobalId<'tcx>, interpret::Pointer>,
+ alloc_cache: FxHashMap<interpret::GlobalId<'tcx>, interpret::AllocId>,
/// A cache for basic byte allocations keyed by their contents. This is used to deduplicate
/// allocations for string and bytestring literals.
- literal_alloc_cache: FxHashMap<Vec<u8>, u64>,
+ literal_alloc_cache: FxHashMap<Vec<u8>, interpret::AllocId>,
}
impl<'tcx> InterpretInterner<'tcx> {
- pub fn create_fn_alloc(&mut self, instance: Instance<'tcx>) -> u64 {
+ pub fn create_fn_alloc(&mut self, instance: Instance<'tcx>) -> interpret::AllocId {
if let Some(&alloc_id) = self.function_cache.get(&instance) {
return alloc_id;
}
pub fn get_fn(
&self,
- id: u64,
+ id: interpret::AllocId,
) -> Option<Instance<'tcx>> {
self.functions.get(&id).cloned()
}
pub fn get_alloc(
&self,
- id: u64,
+ id: interpret::AllocId,
) -> Option<&'tcx interpret::Allocation> {
self.alloc_by_id.get(&id).cloned()
}
pub fn get_cached(
&self,
global_id: interpret::GlobalId<'tcx>,
- ) -> Option<interpret::Pointer> {
+ ) -> Option<interpret::AllocId> {
self.alloc_cache.get(&global_id).cloned()
}
pub fn cache(
&mut self,
global_id: interpret::GlobalId<'tcx>,
- ptr: interpret::Pointer,
+ ptr: interpret::AllocId,
) {
if let Some(old) = self.alloc_cache.insert(global_id, ptr) {
bug!("tried to cache {:?}, but was already existing as {:#?}", global_id, old);
pub fn intern_at_reserved(
&mut self,
- id: u64,
+ id: interpret::AllocId,
alloc: &'tcx interpret::Allocation,
) {
if let Some(old) = self.alloc_by_id.insert(id, alloc) {
/// yet have an allocation backing it.
pub fn reserve(
&mut self,
- ) -> u64 {
+ ) -> interpret::AllocId {
let next = self.next_id;
- self.next_id = self.next_id
+ self.next_id.0 = self.next_id.0
.checked_add(1)
.expect("You overflowed a u64 by incrementing by 1... \
You've just earned yourself a free drink if we ever meet. \
}
/// Allocates a byte or string literal for `mir::interpret`
- pub fn allocate_cached(self, bytes: &[u8]) -> u64 {
+ pub fn allocate_cached(self, bytes: &[u8]) -> interpret::AllocId {
// check whether we already allocated this literal or a constant with the same memory
if let Some(&alloc_id) = self.interpret_interner.borrow().literal_alloc_cache.get(bytes) {
return alloc_id;
pub fn mk_mach_int(self, tm: ast::IntTy) -> Ty<'tcx> {
match tm {
- ast::IntTy::Is => self.types.isize,
+ ast::IntTy::Isize => self.types.isize,
ast::IntTy::I8 => self.types.i8,
ast::IntTy::I16 => self.types.i16,
ast::IntTy::I32 => self.types.i32,
pub fn mk_mach_uint(self, tm: ast::UintTy) -> Ty<'tcx> {
match tm {
- ast::UintTy::Us => self.types.usize,
+ ast::UintTy::Usize => self.types.usize,
ast::UintTy::U8 => self.types.u8,
ast::UintTy::U16 => self.types.u16,
ast::UintTy::U32 => self.types.u32,
// Always use types for non-local impls, where types are always
// available, and filename/line-number is mostly uninteresting.
- let use_types = !self.is_auto_impl(impl_def_id) && (!impl_def_id.is_local() || {
+ let use_types = !impl_def_id.is_local() || {
// Otherwise, use filename/line-number if forced.
let force_no_types = FORCE_IMPL_FILENAME_LINE.with(|f| f.get());
!force_no_types
- });
+ };
if !use_types {
return self.push_impl_path_fallback(buffer, impl_def_id);
attr::SignedInt(IntTy::I32) | attr::UnsignedInt(UintTy::U32) => I32,
attr::SignedInt(IntTy::I64) | attr::UnsignedInt(UintTy::U64) => I64,
attr::SignedInt(IntTy::I128) | attr::UnsignedInt(UintTy::U128) => I128,
- attr::SignedInt(IntTy::Is) | attr::UnsignedInt(UintTy::Us) => {
+ attr::SignedInt(IntTy::Isize) | attr::UnsignedInt(UintTy::Usize) => {
dl.ptr_sized_integer()
}
}
}, niche_start))
};
+ // Locals variables which live across yields are stored
+ // in the generator type as fields. These may be uninitialized
+ // so we don't look for niches there.
+ if let ty::TyGenerator(..) = self.ty.sty {
+ return Ok(None);
+ }
+
match self.abi {
Abi::Scalar(ref scalar) => {
return Ok(scalar_component(scalar, Size::from_bytes(0)));
}
}
+impl<'tcx> QueryDescription<'tcx> for queries::substitute_normalize_and_test_predicates<'tcx> {
+ fn describe(tcx: TyCtxt, key: (DefId, &'tcx Substs<'tcx>)) -> String {
+ format!("testing substituted normalized predicates:`{}`", tcx.item_path_str(key.0))
+ }
+}
+
+impl<'tcx> QueryDescription<'tcx> for queries::target_features_whitelist<'tcx> {
+ fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
+ format!("looking up the whitelist of target features")
+ }
+}
+
macro_rules! impl_disk_cacheable_query(
($query_name:ident, |$key:tt| $cond:expr) => {
impl<'tcx> QueryDescription<'tcx> for queries::$query_name<'tcx> {
/// True if this is a foreign item (i.e., linked via `extern { ... }`).
[] fn is_foreign_item: IsForeignItem(DefId) -> bool,
- /// True if this is an auto impl (aka impl Foo for ..)
- [] fn is_auto_impl: IsAutoImpl(DefId) -> bool,
-
/// Get a map with the variance of every item; use `item_variance`
/// instead.
[] fn crate_variances: crate_variances(CrateNum) -> Rc<ty::CrateVariancesMap>,
// however, which uses this query as a kind of cache.
[] fn erase_regions_ty: erase_regions_ty(Ty<'tcx>) -> Ty<'tcx>,
[] fn fully_normalize_monormophic_ty: normalize_ty_node(Ty<'tcx>) -> Ty<'tcx>,
+
+ [] fn substitute_normalize_and_test_predicates:
+ substitute_normalize_and_test_predicates_node((DefId, &'tcx Substs<'tcx>)) -> bool,
+
+ [] fn target_features_whitelist:
+ target_features_whitelist_node(CrateNum) -> Rc<FxHashSet<String>>,
+ [] fn target_features_enabled: TargetFeaturesEnabled(DefId) -> Rc<Vec<String>>,
+
}
//////////////////////////////////////////////////////////////////////
fn normalize_ty_node<'tcx>(_: Ty<'tcx>) -> DepConstructor<'tcx> {
DepConstructor::NormalizeTy
}
+
+fn substitute_normalize_and_test_predicates_node<'tcx>(key: (DefId, &'tcx Substs<'tcx>))
+ -> DepConstructor<'tcx> {
+ DepConstructor::SubstituteNormalizeAndTestPredicates { key }
+}
+
+fn target_features_whitelist_node<'tcx>(_: CrateNum) -> DepConstructor<'tcx> {
+ DepConstructor::TargetFeaturesWhitelist
+}
use hir::def_id::{CrateNum, DefIndex, DefId, LocalDefId,
RESERVED_FOR_INCR_COMP_CACHE, LOCAL_CRATE};
use hir::map::definitions::DefPathHash;
-use ich::CachingCodemapView;
+use ich::{CachingCodemapView, Fingerprint};
use mir;
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::indexed_vec::{IndexVec, Idx};
where E: ty_codec::TyEncoder
{
// Serializing the DepGraph should not modify it:
- let _in_ignore = tcx.dep_graph.in_ignore();
-
- // Allocate FileMapIndices
- let (file_to_file_index, file_index_to_stable_id) = {
- let mut file_to_file_index = FxHashMap();
- let mut file_index_to_stable_id = FxHashMap();
-
- for (index, file) in tcx.sess.codemap().files().iter().enumerate() {
- let index = FileMapIndex(index as u32);
- let file_ptr: *const FileMap = &**file as *const _;
- file_to_file_index.insert(file_ptr, index);
- file_index_to_stable_id.insert(index, StableFilemapId::new(&file));
- }
-
- (file_to_file_index, file_index_to_stable_id)
- };
-
- let mut encoder = CacheEncoder {
- tcx,
- encoder,
- type_shorthands: FxHashMap(),
- predicate_shorthands: FxHashMap(),
- expn_info_shorthands: FxHashMap(),
- codemap: CachingCodemapView::new(tcx.sess.codemap()),
- file_to_file_index,
- };
-
- // Load everything into memory so we can write it out to the on-disk
- // cache. The vast majority of cacheable query results should already
- // be in memory, so this should be a cheap operation.
- tcx.dep_graph.exec_cache_promotions(tcx);
-
- // Encode query results
- let mut query_result_index = EncodedQueryResultIndex::new();
-
- {
- use ty::maps::queries::*;
- let enc = &mut encoder;
- let qri = &mut query_result_index;
-
- // Encode TypeckTables
- encode_query_results::<typeck_tables_of, _>(tcx, enc, qri)?;
- encode_query_results::<optimized_mir, _>(tcx, enc, qri)?;
- encode_query_results::<unsafety_check_result, _>(tcx, enc, qri)?;
- encode_query_results::<borrowck, _>(tcx, enc, qri)?;
- encode_query_results::<mir_borrowck, _>(tcx, enc, qri)?;
- encode_query_results::<mir_const_qualif, _>(tcx, enc, qri)?;
- encode_query_results::<def_symbol_name, _>(tcx, enc, qri)?;
- encode_query_results::<const_is_rvalue_promotable_to_static, _>(tcx, enc, qri)?;
- encode_query_results::<contains_extern_indicator, _>(tcx, enc, qri)?;
- encode_query_results::<symbol_name, _>(tcx, enc, qri)?;
- encode_query_results::<trans_fulfill_obligation, _>(tcx, enc, qri)?;
- encode_query_results::<check_match, _>(tcx, enc, qri)?;
- }
+ tcx.dep_graph.with_ignore(|| {
+ // Allocate FileMapIndices
+ let (file_to_file_index, file_index_to_stable_id) = {
+ let mut file_to_file_index = FxHashMap();
+ let mut file_index_to_stable_id = FxHashMap();
+
+ for (index, file) in tcx.sess.codemap().files().iter().enumerate() {
+ let index = FileMapIndex(index as u32);
+ let file_ptr: *const FileMap = &**file as *const _;
+ file_to_file_index.insert(file_ptr, index);
+ file_index_to_stable_id.insert(index, StableFilemapId::new(&file));
+ }
- // Encode diagnostics
- let diagnostics_index = {
- let mut diagnostics_index = EncodedDiagnosticsIndex::new();
-
- for (dep_node_index, diagnostics) in self.current_diagnostics
- .borrow()
- .iter() {
- let pos = AbsoluteBytePos::new(encoder.position());
- // Let's make sure we get the expected type here:
- let diagnostics: &EncodedDiagnostics = diagnostics;
- let dep_node_index =
- SerializedDepNodeIndex::new(dep_node_index.index());
- encoder.encode_tagged(dep_node_index, diagnostics)?;
- diagnostics_index.push((dep_node_index, pos));
+ (file_to_file_index, file_index_to_stable_id)
+ };
+
+ let mut encoder = CacheEncoder {
+ tcx,
+ encoder,
+ type_shorthands: FxHashMap(),
+ predicate_shorthands: FxHashMap(),
+ expn_info_shorthands: FxHashMap(),
+ codemap: CachingCodemapView::new(tcx.sess.codemap()),
+ file_to_file_index,
+ };
+
+ // Load everything into memory so we can write it out to the on-disk
+ // cache. The vast majority of cacheable query results should already
+ // be in memory, so this should be a cheap operation.
+ tcx.dep_graph.exec_cache_promotions(tcx);
+
+ // Encode query results
+ let mut query_result_index = EncodedQueryResultIndex::new();
+
+ {
+ use ty::maps::queries::*;
+ let enc = &mut encoder;
+ let qri = &mut query_result_index;
+
+ // Encode TypeckTables
+ encode_query_results::<typeck_tables_of, _>(tcx, enc, qri)?;
+ encode_query_results::<optimized_mir, _>(tcx, enc, qri)?;
+ encode_query_results::<unsafety_check_result, _>(tcx, enc, qri)?;
+ encode_query_results::<borrowck, _>(tcx, enc, qri)?;
+ encode_query_results::<mir_borrowck, _>(tcx, enc, qri)?;
+ encode_query_results::<mir_const_qualif, _>(tcx, enc, qri)?;
+ encode_query_results::<def_symbol_name, _>(tcx, enc, qri)?;
+ encode_query_results::<const_is_rvalue_promotable_to_static, _>(tcx, enc, qri)?;
+ encode_query_results::<contains_extern_indicator, _>(tcx, enc, qri)?;
+ encode_query_results::<symbol_name, _>(tcx, enc, qri)?;
+ encode_query_results::<trans_fulfill_obligation, _>(tcx, enc, qri)?;
+ encode_query_results::<check_match, _>(tcx, enc, qri)?;
}
- diagnostics_index
- };
+ // Encode diagnostics
+ let diagnostics_index = {
+ let mut diagnostics_index = EncodedDiagnosticsIndex::new();
+
+ for (dep_node_index, diagnostics) in self.current_diagnostics
+ .borrow()
+ .iter() {
+ let pos = AbsoluteBytePos::new(encoder.position());
+ // Let's make sure we get the expected type here:
+ let diagnostics: &EncodedDiagnostics = diagnostics;
+ let dep_node_index =
+ SerializedDepNodeIndex::new(dep_node_index.index());
+ encoder.encode_tagged(dep_node_index, diagnostics)?;
+ diagnostics_index.push((dep_node_index, pos));
+ }
- let sorted_cnums = sorted_cnums_including_local_crate(tcx);
- let prev_cnums: Vec<_> = sorted_cnums.iter().map(|&cnum| {
- let crate_name = tcx.original_crate_name(cnum).as_str().to_string();
- let crate_disambiguator = tcx.crate_disambiguator(cnum);
- (cnum.as_u32(), crate_name, crate_disambiguator)
- }).collect();
-
- // Encode the file footer
- let footer_pos = encoder.position() as u64;
- encoder.encode_tagged(TAG_FILE_FOOTER, &Footer {
- file_index_to_stable_id,
- prev_cnums,
- query_result_index,
- diagnostics_index,
- })?;
-
- // Encode the position of the footer as the last 8 bytes of the
- // file so we know where to look for it.
- IntEncodedWithFixedSize(footer_pos).encode(encoder.encoder)?;
-
- // DO NOT WRITE ANYTHING TO THE ENCODER AFTER THIS POINT! The address
- // of the footer must be the last thing in the data stream.
-
- return Ok(());
-
- fn sorted_cnums_including_local_crate(tcx: TyCtxt) -> Vec<CrateNum> {
- let mut cnums = vec![LOCAL_CRATE];
- cnums.extend_from_slice(&tcx.crates()[..]);
- cnums.sort_unstable();
- // Just to be sure...
- cnums.dedup();
- cnums
- }
+ diagnostics_index
+ };
+
+ let sorted_cnums = sorted_cnums_including_local_crate(tcx);
+ let prev_cnums: Vec<_> = sorted_cnums.iter().map(|&cnum| {
+ let crate_name = tcx.original_crate_name(cnum).as_str().to_string();
+ let crate_disambiguator = tcx.crate_disambiguator(cnum);
+ (cnum.as_u32(), crate_name, crate_disambiguator)
+ }).collect();
+
+ // Encode the file footer
+ let footer_pos = encoder.position() as u64;
+ encoder.encode_tagged(TAG_FILE_FOOTER, &Footer {
+ file_index_to_stable_id,
+ prev_cnums,
+ query_result_index,
+ diagnostics_index,
+ })?;
+
+ // Encode the position of the footer as the last 8 bytes of the
+ // file so we know where to look for it.
+ IntEncodedWithFixedSize(footer_pos).encode(encoder.encoder)?;
+
+ // DO NOT WRITE ANYTHING TO THE ENCODER AFTER THIS POINT! The address
+ // of the footer must be the last thing in the data stream.
+
+ return Ok(());
+
+ fn sorted_cnums_including_local_crate(tcx: TyCtxt) -> Vec<CrateNum> {
+ let mut cnums = vec![LOCAL_CRATE];
+ cnums.extend_from_slice(&tcx.crates()[..]);
+ cnums.sort_unstable();
+ // Just to be sure...
+ cnums.dedup();
+ cnums
+ }
+ })
}
/// Load a diagnostic emitted during the previous compilation session.
prev_cnums: &[(u32, String, CrateDisambiguator)])
-> IndexVec<CrateNum, Option<CrateNum>>
{
- let _in_ignore = tcx.dep_graph.in_ignore();
-
- let current_cnums = tcx.all_crate_nums(LOCAL_CRATE).iter().map(|&cnum| {
- let crate_name = tcx.original_crate_name(cnum)
- .as_str()
- .to_string();
- let crate_disambiguator = tcx.crate_disambiguator(cnum);
- ((crate_name, crate_disambiguator), cnum)
- }).collect::<FxHashMap<_,_>>();
-
- let map_size = prev_cnums.iter()
- .map(|&(cnum, ..)| cnum)
- .max()
- .unwrap_or(0) + 1;
- let mut map = IndexVec::new();
- map.resize(map_size as usize, None);
-
- for &(prev_cnum, ref crate_name, crate_disambiguator) in prev_cnums {
- let key = (crate_name.clone(), crate_disambiguator);
- map[CrateNum::from_u32(prev_cnum)] = current_cnums.get(&key).cloned();
- }
+ tcx.dep_graph.with_ignore(|| {
+ let current_cnums = tcx.all_crate_nums(LOCAL_CRATE).iter().map(|&cnum| {
+ let crate_name = tcx.original_crate_name(cnum)
+ .as_str()
+ .to_string();
+ let crate_disambiguator = tcx.crate_disambiguator(cnum);
+ ((crate_name, crate_disambiguator), cnum)
+ }).collect::<FxHashMap<_,_>>();
+
+ let map_size = prev_cnums.iter()
+ .map(|&(cnum, ..)| cnum)
+ .max()
+ .unwrap_or(0) + 1;
+ let mut map = IndexVec::new();
+ map.resize(map_size as usize, None);
+
+ for &(prev_cnum, ref crate_name, crate_disambiguator) in prev_cnums {
+ let key = (crate_name.clone(), crate_disambiguator);
+ map[CrateNum::from_u32(prev_cnum)] = current_cnums.get(&key).cloned();
+ }
- map[LOCAL_CRATE] = Some(LOCAL_CRATE);
- map
+ map[LOCAL_CRATE] = Some(LOCAL_CRATE);
+ map
+ })
}
}
}
}
+impl<'a, 'tcx, 'x> SpecializedDecoder<Fingerprint> for CacheDecoder<'a, 'tcx, 'x> {
+ fn specialized_decode(&mut self) -> Result<Fingerprint, Self::Error> {
+ Fingerprint::decode_opaque(&mut self.opaque)
+ }
+}
+
impl<'a, 'tcx, 'x, T: Decodable> SpecializedDecoder<mir::ClearCrossCrate<T>>
for CacheDecoder<'a, 'tcx, 'x> {
#[inline]
}
}
+impl<'enc, 'a, 'tcx> SpecializedEncoder<Fingerprint>
+for CacheEncoder<'enc, 'a, 'tcx, opaque::Encoder<'enc>>
+{
+ fn specialized_encode(&mut self, f: &Fingerprint) -> Result<(), Self::Error> {
+ f.encode_opaque(&mut self.encoder)
+ }
+}
+
impl<'enc, 'a, 'tcx, E, T> SpecializedEncoder<mir::ClearCrossCrate<T>>
for CacheEncoder<'enc, 'a, 'tcx, E>
where E: 'enc + ty_codec::TyEncoder,
DepKind::VtableMethods |
DepKind::EraseRegionsTy |
DepKind::NormalizeTy |
+ DepKind::SubstituteNormalizeAndTestPredicates |
// This one should never occur in this context
DepKind::Null => {
DepKind::SuperPredicatesOfItem => { force!(super_predicates_of, def_id!()); }
DepKind::TraitDefOfItem => { force!(trait_def, def_id!()); }
DepKind::AdtDefOfItem => { force!(adt_def, def_id!()); }
- DepKind::IsAutoImpl => { force!(is_auto_impl, def_id!()); }
DepKind::ImplTraitRef => { force!(impl_trait_ref, def_id!()); }
DepKind::ImplPolarity => { force!(impl_polarity, def_id!()); }
DepKind::FnSignature => { force!(fn_sig, def_id!()); }
}
DepKind::IsTranslatedFunction => { force!(is_translated_function, def_id!()); }
DepKind::OutputFilenames => { force!(output_filenames, LOCAL_CRATE); }
+
+ DepKind::TargetFeaturesWhitelist => { force!(target_features_whitelist, LOCAL_CRATE); }
+ DepKind::TargetFeaturesEnabled => { force!(target_features_enabled, def_id!()); }
}
true
for attr in tcx.get_attrs(did).iter() {
for r in attr::find_repr_attrs(tcx.sess.diagnostic(), attr) {
flags.insert(match r {
- attr::ReprExtern => ReprFlags::IS_C,
+ attr::ReprC => ReprFlags::IS_C,
attr::ReprPacked => ReprFlags::IS_PACKED,
attr::ReprSimd => ReprFlags::IS_SIMD,
attr::ReprInt(i) => {
}
}
- // FIXME(eddyb) This is deprecated and should be removed.
- if tcx.has_attr(did, "simd") {
- flags.insert(ReprFlags::IS_SIMD);
- }
-
// This is here instead of layout because the choice must make it into metadata.
if !tcx.consider_optimizing(|| format!("Reorder fields of {:?}", tcx.item_path_str(did))) {
flags.insert(ReprFlags::IS_LINEAR);
pub fn linear(&self) -> bool { self.flags.contains(ReprFlags::IS_LINEAR) }
pub fn discr_type(&self) -> attr::IntType {
- self.int.unwrap_or(attr::SignedInt(ast::IntTy::Is))
+ self.int.unwrap_or(attr::SignedInt(ast::IntTy::Isize))
}
/// Returns true if this `#[repr()]` should inhabit "smart enum
self.destructor(tcx).is_some()
}
- /// Asserts this is a struct and returns the struct's unique
- /// variant.
- pub fn struct_variant(&self) -> &VariantDef {
- assert!(!self.is_enum());
+ /// Asserts this is a struct or union and returns its unique variant.
+ pub fn non_enum_variant(&self) -> &VariantDef {
+ assert!(self.is_struct() || self.is_union());
&self.variants[0]
}
match def {
Def::Variant(vid) | Def::VariantCtor(vid, ..) => self.variant_with_id(vid),
Def::Struct(..) | Def::StructCtor(..) | Def::Union(..) |
- Def::TyAlias(..) | Def::AssociatedTy(..) | Def::SelfTy(..) => self.struct_variant(),
+ Def::TyAlias(..) | Def::AssociatedTy(..) | Def::SelfTy(..) => self.non_enum_variant(),
_ => bug!("unexpected def {:?} in variant_of_def", def)
}
}
self.adt_def(enum_did).variant_with_id(did)
}
Def::Struct(did) | Def::Union(did) => {
- self.adt_def(did).struct_variant()
+ self.adt_def(did).non_enum_variant()
}
Def::StructCtor(ctor_did, ..) => {
let did = self.parent_def_id(ctor_did).expect("struct ctor has no parent");
- self.adt_def(did).struct_variant()
+ self.adt_def(did).non_enum_variant()
}
_ => bug!("expect_variant_def used with unexpected def {:?}", def)
}
}
/// Returns true if this is an `auto trait`.
- ///
- /// NB. For a limited time, also returns true if `impl Trait for .. { }` is in the code-base.
pub fn trait_is_auto(self, trait_def_id: DefId) -> bool {
self.trait_def(trait_def_id).has_auto_impl
}
pub fn simd_type(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx> {
match self.sty {
TyAdt(def, substs) => {
- def.struct_variant().fields[0].ty(tcx, substs)
+ def.non_enum_variant().fields[0].ty(tcx, substs)
}
_ => bug!("simd_type called on invalid type")
}
pub fn simd_size(&self, _cx: TyCtxt) -> usize {
match self.sty {
- TyAdt(def, _) => def.struct_variant().fields.len(),
+ TyAdt(def, _) => def.non_enum_variant().fields.len(),
_ => bug!("simd_size called on invalid type")
}
}
}
}
- pub fn is_uint(&self) -> bool {
- match self.sty {
- TyInfer(IntVar(_)) | TyUint(ast::UintTy::Us) => true,
- _ => false
- }
- }
-
pub fn is_char(&self) -> bool {
match self.sty {
TyChar => true,
pub fn is_machine(&self) -> bool {
match self.sty {
- TyInt(ast::IntTy::Is) | TyUint(ast::UintTy::Us) => false,
+ TyInt(ast::IntTy::Isize) | TyUint(ast::UintTy::Usize) => false,
TyInt(..) | TyUint(..) | TyFloat(..) => true,
_ => false,
}
SignedInt(ast::IntTy::I32) => ConstInt::I32($lit),
SignedInt(ast::IntTy::I64) => ConstInt::I64($lit),
SignedInt(ast::IntTy::I128) => ConstInt::I128($lit),
- SignedInt(ast::IntTy::Is) => match $tcx.sess.target.isize_ty {
+ SignedInt(ast::IntTy::Isize) => match $tcx.sess.target.isize_ty {
ast::IntTy::I16 => ConstInt::Isize(ConstIsize::Is16($lit)),
ast::IntTy::I32 => ConstInt::Isize(ConstIsize::Is32($lit)),
ast::IntTy::I64 => ConstInt::Isize(ConstIsize::Is64($lit)),
UnsignedInt(ast::UintTy::U32) => ConstInt::U32($lit),
UnsignedInt(ast::UintTy::U64) => ConstInt::U64($lit),
UnsignedInt(ast::UintTy::U128) => ConstInt::U128($lit),
- UnsignedInt(ast::UintTy::Us) => match $tcx.sess.target.usize_ty {
+ UnsignedInt(ast::UintTy::Usize) => match $tcx.sess.target.usize_ty {
ast::UintTy::U16 => ConstInt::Usize(ConstUsize::Us16($lit)),
ast::UintTy::U32 => ConstInt::Usize(ConstUsize::Us32($lit)),
ast::UintTy::U64 => ConstInt::Usize(ConstUsize::Us64($lit)),
SignedInt(ast::IntTy::I32) => tcx.types.i32,
SignedInt(ast::IntTy::I64) => tcx.types.i64,
SignedInt(ast::IntTy::I128) => tcx.types.i128,
- SignedInt(ast::IntTy::Is) => tcx.types.isize,
+ SignedInt(ast::IntTy::Isize) => tcx.types.isize,
UnsignedInt(ast::UintTy::U8) => tcx.types.u8,
UnsignedInt(ast::UintTy::U16) => tcx.types.u16,
UnsignedInt(ast::UintTy::U32) => tcx.types.u32,
UnsignedInt(ast::UintTy::U64) => tcx.types.u64,
UnsignedInt(ast::UintTy::U128) => tcx.types.u128,
- UnsignedInt(ast::UintTy::Us) => tcx.types.usize,
+ UnsignedInt(ast::UintTy::Usize) => tcx.types.usize,
}
}
(SignedInt(ast::IntTy::I32), ConstInt::I32(_)) => {},
(SignedInt(ast::IntTy::I64), ConstInt::I64(_)) => {},
(SignedInt(ast::IntTy::I128), ConstInt::I128(_)) => {},
- (SignedInt(ast::IntTy::Is), ConstInt::Isize(_)) => {},
+ (SignedInt(ast::IntTy::Isize), ConstInt::Isize(_)) => {},
(UnsignedInt(ast::UintTy::U8), ConstInt::U8(_)) => {},
(UnsignedInt(ast::UintTy::U16), ConstInt::U16(_)) => {},
(UnsignedInt(ast::UintTy::U32), ConstInt::U32(_)) => {},
(UnsignedInt(ast::UintTy::U64), ConstInt::U64(_)) => {},
(UnsignedInt(ast::UintTy::U128), ConstInt::U128(_)) => {},
- (UnsignedInt(ast::UintTy::Us), ConstInt::Usize(_)) => {},
+ (UnsignedInt(ast::UintTy::Usize), ConstInt::Usize(_)) => {},
_ => bug!("disr type mismatch: {:?} vs {:?}", self, val),
}
}
adt.variant_with_id(vid).fields.get(i).map(|f| f.ty(self, substs))
}
(&TyAdt(adt, substs), None) => {
- // Don't use `struct_variant`, this may be a univariant enum.
+ // Don't use `non_enum_variant`, this may be a univariant enum.
adt.variants[0].fields.get(i).map(|f| f.ty(self, substs))
}
(&TyTuple(ref v, _), None) => v.get(i).cloned(),
adt.variant_with_id(vid).find_field_named(n).map(|f| f.ty(self, substs))
}
(&TyAdt(adt, substs), None) => {
- adt.struct_variant().find_field_named(n).map(|f| f.ty(self, substs))
+ adt.non_enum_variant().find_field_named(n).map(|f| f.ty(self, substs))
}
_ => return None
}
if !def.is_struct() {
break;
}
- match def.struct_variant().fields.last() {
+ match def.non_enum_variant().fields.last() {
Some(f) => ty = f.ty(self, substs),
None => break,
}
match (&a.sty, &b.sty) {
(&TyAdt(a_def, a_substs), &TyAdt(b_def, b_substs))
if a_def == b_def && a_def.is_struct() => {
- if let Some(f) = a_def.struct_variant().fields.last() {
+ if let Some(f) = a_def.non_enum_variant().fields.last() {
a = f.ty(self, a_substs);
b = f.ty(self, b_substs);
} else {
// Memory reporting
#[cfg(unix)]
fn get_resident() -> Option<usize> {
- use std::fs::File;
- use std::io::Read;
+ use std::fs;
let field = 1;
- let mut f = File::open("/proc/self/statm").ok()?;
- let mut contents = String::new();
- f.read_to_string(&mut contents).ok()?;
+ let contents = fs::read_string("/proc/self/statm").ok()?;
let s = contents.split_whitespace().nth(field)?;
let npages = s.parse::<usize>().ok()?;
Some(npages * 4096)
let max_change = S::MAX_EXP as i32 - (S::MIN_EXP as i32 - sig_bits) + 1;
// Clamp to one past the range ends to let normalize handle overflow.
- let exp_change = cmp::min(cmp::max(exp as i32, (-max_change - 1)), max_change);
+ let exp_change = cmp::min(cmp::max(exp as i32, -max_change - 1), max_change);
self.exp = self.exp.saturating_add(exp_change as ExpInt);
self = self.normalize(round, Loss::ExactlyZero).value;
if self.is_nan() {
[dependencies]
syntax = { path = "../libsyntax" }
serialize = { path = "../libserialize" }
-log = "0.3"
+log = "0.4"
rand = "0.3"
[features]
#![feature(box_syntax)]
#![feature(const_fn)]
+#![feature(fs_read_write)]
extern crate syntax;
extern crate rand;
linker_is_gnu: true,
pre_link_args: args,
position_independent_executables: true,
+ // As CloudABI only supports static linkage, there is no need
+ // for dynamic TLS. The C library therefore does not provide
+ // __tls_get_addr(), which is normally used to perform dynamic
+ // TLS lookups by programs that make use of dlopen(). Only the
+ // "local-exec" and "initial-exec" TLS models can be used.
+ //
+ // "local-exec" is more efficient than "initial-exec", as the
+ // latter has one more level of indirection: it accesses the GOT
+ // (Global Offset Table) to obtain the effective address of a
+ // thread-local variable. Using a GOT is useful only when doing
+ // dynamic linking.
+ tls_model: "local-exec".to_string(),
relro_level: RelroLevel::Full,
exe_allocation_crate: super::maybe_jemalloc(),
.. Default::default()
--- /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.
+
+use target::TargetResult;
+
+pub fn target() -> TargetResult {
+ let mut base = super::i686_unknown_linux_musl::target()?;
+ base.options.cpu = "pentium".to_string();
+ base.llvm_target = "i586-unknown-linux-musl".to_string();
+ Ok(base)
+}
use serialize::json::{Json, ToJson};
use std::collections::BTreeMap;
use std::default::Default;
-use std::io::prelude::*;
use syntax::abi::{Abi, lookup as lookup_abi};
use {LinkerFlavor, PanicStrategy, RelroLevel};
("powerpc64-unknown-linux-gnu", powerpc64_unknown_linux_gnu),
("powerpc64le-unknown-linux-gnu", powerpc64le_unknown_linux_gnu),
("s390x-unknown-linux-gnu", s390x_unknown_linux_gnu),
+ ("sparc64-unknown-linux-gnu", sparc64_unknown_linux_gnu),
("arm-unknown-linux-gnueabi", arm_unknown_linux_gnueabi),
("arm-unknown-linux-gnueabihf", arm_unknown_linux_gnueabihf),
("arm-unknown-linux-musleabi", arm_unknown_linux_musleabi),
("armv7-unknown-linux-gnueabihf", armv7_unknown_linux_gnueabihf),
("armv7-unknown-linux-musleabihf", armv7_unknown_linux_musleabihf),
("aarch64-unknown-linux-gnu", aarch64_unknown_linux_gnu),
+
("aarch64-unknown-linux-musl", aarch64_unknown_linux_musl),
("x86_64-unknown-linux-musl", x86_64_unknown_linux_musl),
("i686-unknown-linux-musl", i686_unknown_linux_musl),
+ ("i586-unknown-linux-musl", i586_unknown_linux_musl),
("mips-unknown-linux-musl", mips_unknown_linux_musl),
("mipsel-unknown-linux-musl", mipsel_unknown_linux_musl),
+
("mips-unknown-linux-uclibc", mips_unknown_linux_uclibc),
("mipsel-unknown-linux-uclibc", mipsel_unknown_linux_uclibc),
- ("sparc64-unknown-linux-gnu", sparc64_unknown_linux_gnu),
-
("i686-linux-android", i686_linux_android),
("x86_64-linux-android", x86_64_linux_android),
("arm-linux-androideabi", arm_linux_androideabi),
pub fn search(target: &str) -> Result<Target, String> {
use std::env;
use std::ffi::OsString;
- use std::fs::File;
+ use std::fs;
use std::path::{Path, PathBuf};
use serialize::json;
fn load_file(path: &Path) -> Result<Target, String> {
- let mut f = File::open(path).map_err(|e| e.to_string())?;
- let mut contents = Vec::new();
- f.read_to_end(&mut contents).map_err(|e| e.to_string())?;
+ let contents = fs::read(path).map_err(|e| e.to_string())?;
let obj = json::from_reader(&mut &contents[..])
.map_err(|e| e.to_string())?;
Target::from_json(obj)
"-lmingw32".to_string(),
"-lgcc".to_string(), // alas, mingw* libraries above depend on libgcc
"-lmsvcrt".to_string(),
+ // mingw's msvcrt is a weird hybrid import library and static library.
+ // And it seems that the linker fails to use import symbols from msvcrt
+ // that are required from functions in msvcrt in certain cases. For example
+ // `_fmode` that is used by an implementation of `__p__fmode` in x86_64.
+ // Listing the library twice seems to fix that, and seems to also be done
+ // by mingw's gcc (Though not sure if it's done on purpose, or by mistake).
+ //
+ // See https://github.com/rust-lang/rust/pull/47483
+ "-lmsvcrt".to_string(),
"-luser32".to_string(),
"-lkernel32".to_string(),
]);
test = false
[dependencies]
-log = "0.3"
+log = "0.4"
syntax = { path = "../libsyntax" }
syntax_pos = { path = "../libsyntax_pos" }
graphviz = { path = "../libgraphviz" }
ty::TyAdt(adt_def, _) if adt_def.is_union() => match result {
RestrictionResult::Safe => RestrictionResult::Safe,
RestrictionResult::SafeIf(base_lp, mut base_vec) => {
- for field in &adt_def.struct_variant().fields {
+ for field in &adt_def.non_enum_variant().fields {
let field = InteriorKind::InteriorField(mc::NamedField(field.name));
let field_ty = if field == interior {
cmt.ty
&move_data::Assignment) {
let mut err = self.cannot_reassign_immutable(span,
&self.loan_path_to_string(lp),
+ false,
Origin::Ast);
err.span_label(span, "cannot assign twice to immutable variable");
if span != assign.span {
err.span_label(assign.span, format!("first assignment to `{}`",
- self.loan_path_to_string(lp)));
+ self.loan_path_to_string(lp)));
}
err.emit();
}
if let mc::NoteClosureEnv(upvar_id) = err.cmt.note {
let node_id = self.tcx.hir.hir_to_node_id(upvar_id.var_id);
let sp = self.tcx.hir.span(node_id);
- match self.tcx.sess.codemap().span_to_snippet(sp) {
- Ok(snippet) => {
+ let fn_closure_msg = "`Fn` closures cannot capture their enclosing \
+ environment for modifications";
+ match (self.tcx.sess.codemap().span_to_snippet(sp), &err.cmt.cat) {
+ (_, &Categorization::Upvar(mc::Upvar {
+ kind: ty::ClosureKind::Fn, ..
+ })) => {
+ db.note(fn_closure_msg);
+ // we should point at the cause for this closure being
+ // identified as `Fn` (like in signature of method this
+ // closure was passed into)
+ }
+ (Ok(ref snippet), ref cat) => {
let msg = &format!("consider making `{}` mutable", snippet);
- db.span_suggestion(sp, msg, format!("mut {}", snippet));
+ let suggestion = format!("mut {}", snippet);
+
+ if let &Categorization::Deref(ref cmt, _) = cat {
+ if let Categorization::Upvar(mc::Upvar {
+ kind: ty::ClosureKind::Fn, ..
+ }) = cmt.cat {
+ db.note(fn_closure_msg);
+ } else {
+ db.span_suggestion(sp, msg, suggestion);
+ }
+ } else {
+ db.span_suggestion(sp, msg, suggestion);
+ }
}
_ => {
db.span_help(sp, "consider making this binding mutable");
if let (&ty::TyAdt(adt_def, _), LpInterior(opt_variant_id, interior))
= (&base_lp.ty.sty, lp_elem) {
if adt_def.is_union() {
- for field in &adt_def.struct_variant().fields {
+ for field in &adt_def.non_enum_variant().fields {
let field = InteriorKind::InteriorField(mc::NamedField(field.name));
if field != interior {
let sibling_lp_kind =
if let LpExtend(ref base_lp, mutbl, LpInterior(opt_variant_id, interior)) = lp.kind {
if let ty::TyAdt(adt_def, _) = base_lp.ty.sty {
if adt_def.is_union() {
- for field in &adt_def.struct_variant().fields {
+ for field in &adt_def.non_enum_variant().fields {
let field = InteriorKind::InteriorField(mc::NamedField(field.name));
let field_ty = if field == interior {
lp.ty
[dependencies]
arena = { path = "../libarena" }
-log = "0.3"
+log = "0.4"
rustc = { path = "../librustc" }
rustc_const_math = { path = "../librustc_const_math" }
rustc_data_structures = { path = "../librustc_data_structures" }
(&LitKind::Int(I128_OVERFLOW, Signed(IntTy::I128)), _) => {
Some(I128(i128::min_value()))
},
- (&LitKind::Int(n, _), &ty::TyInt(IntTy::Is)) |
- (&LitKind::Int(n, Signed(IntTy::Is)), _) => {
+ (&LitKind::Int(n, _), &ty::TyInt(IntTy::Isize)) |
+ (&LitKind::Int(n, Signed(IntTy::Isize)), _) => {
match tcx.sess.target.isize_ty {
IntTy::I16 => if n == I16_OVERFLOW {
Some(Isize(Is16(i16::min_value())))
ty::TyInt(ast::IntTy::I32) => Ok(Integral(I32(v as i128 as i32))),
ty::TyInt(ast::IntTy::I64) => Ok(Integral(I64(v as i128 as i64))),
ty::TyInt(ast::IntTy::I128) => Ok(Integral(I128(v as i128))),
- ty::TyInt(ast::IntTy::Is) => {
+ ty::TyInt(ast::IntTy::Isize) => {
Ok(Integral(Isize(ConstIsize::new_truncating(v as i128, tcx.sess.target.isize_ty))))
},
ty::TyUint(ast::UintTy::U8) => Ok(Integral(U8(v as u8))),
ty::TyUint(ast::UintTy::U32) => Ok(Integral(U32(v as u32))),
ty::TyUint(ast::UintTy::U64) => Ok(Integral(U64(v as u64))),
ty::TyUint(ast::UintTy::U128) => Ok(Integral(U128(v as u128))),
- ty::TyUint(ast::UintTy::Us) => {
+ ty::TyUint(ast::UintTy::Usize) => {
Ok(Integral(Usize(ConstUsize::new_truncating(v, tcx.sess.target.usize_ty))))
},
ty::TyFloat(fty) => {
}
// Build the diagnostics array at the end so that the metadata includes error use sites.
+#[cfg(not(stage0))] // remove after the next snapshot
__build_diagnostic_array! { librustc_const_eval, DIAGNOSTICS }
let mut pcx = PatternContext::new(tcx, param_env_and_substs, tables);
let result = pcx.lower_pattern(pat);
if !pcx.errors.is_empty() {
- span_bug!(pat.span, "encountered errors lowering pattern: {:?}", pcx.errors)
+ let msg = format!("encountered errors lowering pattern: {:?}", pcx.errors);
+ tcx.sess.delay_span_bug(pat.span, &msg);
}
debug!("Pattern::from_hir({:?}) = {:?}", pat, result);
result
ULitOutOfRange(ast::UintTy::U32) => "literal out of range for u32",
ULitOutOfRange(ast::UintTy::U64) => "literal out of range for u64",
ULitOutOfRange(ast::UintTy::U128) => "literal out of range for u128",
- ULitOutOfRange(ast::UintTy::Us) => "literal out of range for usize",
+ ULitOutOfRange(ast::UintTy::Usize) => "literal out of range for usize",
LitOutOfRange(ast::IntTy::I8) => "literal out of range for i8",
LitOutOfRange(ast::IntTy::I16) => "literal out of range for i16",
LitOutOfRange(ast::IntTy::I32) => "literal out of range for i32",
LitOutOfRange(ast::IntTy::I64) => "literal out of range for i64",
LitOutOfRange(ast::IntTy::I128) => "literal out of range for i128",
- LitOutOfRange(ast::IntTy::Is) => "literal out of range for isize",
+ LitOutOfRange(ast::IntTy::Isize) => "literal out of range for isize",
}
}
}
use syntax::attr::IntType;
use syntax::ast::{IntTy, UintTy};
-use super::is::*;
-use super::us::*;
+use super::isize::*;
+use super::usize::*;
use super::err::*;
#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable, Hash, Eq, PartialEq)]
UintTy::U16 if val <= ubounds::U16MAX => Some(U16(val as u16)),
UintTy::U32 if val <= ubounds::U32MAX => Some(U32(val as u32)),
UintTy::U64 if val <= ubounds::U64MAX => Some(U64(val as u64)),
- UintTy::Us if val <= ubounds::U64MAX => ConstUsize::new(val as u64, usize_ty).ok()
+ UintTy::Usize if val <= ubounds::U64MAX => ConstUsize::new(val as u64, usize_ty).ok()
.map(Usize),
UintTy::U128 => Some(U128(val)),
_ => None
IntTy::I16 if val <= ibounds::I16MAX => Some(I16(val as i16)),
IntTy::I32 if val <= ibounds::I32MAX => Some(I32(val as i32)),
IntTy::I64 if val <= ibounds::I64MAX => Some(I64(val as i64)),
- IntTy::Is if val <= ibounds::I64MAX => ConstIsize::new(val as i64, isize_ty).ok()
+ IntTy::Isize if val <= ibounds::I64MAX => ConstIsize::new(val as i64, isize_ty).ok()
.map(Isize),
IntTy::I128 => Some(I128(val)),
_ => None
UintTy::U16 => U16(val as u16),
UintTy::U32 => U32(val as u32),
UintTy::U64 => U64(val as u64),
- UintTy::Us => Usize(ConstUsize::new_truncating(val, usize_ty)),
+ UintTy::Usize => Usize(ConstUsize::new_truncating(val, usize_ty)),
UintTy::U128 => U128(val)
}
}
IntTy::I16 => I16(val as i16),
IntTy::I32 => I32(val as i32),
IntTy::I64 => I64(val as i64),
- IntTy::Is => Isize(ConstIsize::new_truncating(val, isize_ty)),
+ IntTy::Isize => Isize(ConstIsize::new_truncating(val, isize_ty)),
IntTy::I128 => I128(val)
}
}
ConstInt::I32(_) => IntType::SignedInt(IntTy::I32),
ConstInt::I64(_) => IntType::SignedInt(IntTy::I64),
ConstInt::I128(_) => IntType::SignedInt(IntTy::I128),
- ConstInt::Isize(_) => IntType::SignedInt(IntTy::Is),
+ ConstInt::Isize(_) => IntType::SignedInt(IntTy::Isize),
ConstInt::U8(_) => IntType::UnsignedInt(UintTy::U8),
ConstInt::U16(_) => IntType::UnsignedInt(UintTy::U16),
ConstInt::U32(_) => IntType::UnsignedInt(UintTy::U32),
ConstInt::U64(_) => IntType::UnsignedInt(UintTy::U64),
ConstInt::U128(_) => IntType::UnsignedInt(UintTy::U128),
- ConstInt::Usize(_) => IntType::UnsignedInt(UintTy::Us),
+ ConstInt::Usize(_) => IntType::UnsignedInt(UintTy::Usize),
}
}
}
+++ /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.
-
-use syntax::ast;
-use super::err::*;
-
-/// Depending on the target only one variant is ever used in a compilation.
-/// Anything else is an error. This invariant is checked at several locations
-#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable, Hash, Eq, PartialEq)]
-pub enum ConstIsize {
- Is16(i16),
- Is32(i32),
- Is64(i64),
-}
-pub use self::ConstIsize::*;
-
-impl ::std::fmt::Display for ConstIsize {
- fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
- write!(fmt, "{}", self.as_i64())
- }
-}
-
-impl ConstIsize {
- pub fn as_i64(self) -> i64 {
- match self {
- Is16(i) => i as i64,
- Is32(i) => i as i64,
- Is64(i) => i,
- }
- }
- pub fn new(i: i64, isize_ty: ast::IntTy) -> Result<Self, ConstMathErr> {
- match isize_ty {
- ast::IntTy::I16 if i as i16 as i64 == i => Ok(Is16(i as i16)),
- ast::IntTy::I16 => Err(LitOutOfRange(ast::IntTy::Is)),
- ast::IntTy::I32 if i as i32 as i64 == i => Ok(Is32(i as i32)),
- ast::IntTy::I32 => Err(LitOutOfRange(ast::IntTy::Is)),
- ast::IntTy::I64 => Ok(Is64(i)),
- _ => unreachable!(),
- }
- }
- pub fn new_truncating(i: i128, isize_ty: ast::IntTy) -> Self {
- match isize_ty {
- ast::IntTy::I16 => Is16(i as i16),
- ast::IntTy::I32 => Is32(i as i32),
- ast::IntTy::I64 => Is64(i as i64),
- _ => unreachable!(),
- }
- }
-}
--- /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.
+
+use syntax::ast;
+use super::err::*;
+
+/// Depending on the target only one variant is ever used in a compilation.
+/// Anything else is an error. This invariant is checked at several locations
+#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable, Hash, Eq, PartialEq)]
+pub enum ConstIsize {
+ Is16(i16),
+ Is32(i32),
+ Is64(i64),
+}
+pub use self::ConstIsize::*;
+
+impl ::std::fmt::Display for ConstIsize {
+ fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
+ write!(fmt, "{}", self.as_i64())
+ }
+}
+
+impl ConstIsize {
+ pub fn as_i64(self) -> i64 {
+ match self {
+ Is16(i) => i as i64,
+ Is32(i) => i as i64,
+ Is64(i) => i,
+ }
+ }
+ pub fn new(i: i64, isize_ty: ast::IntTy) -> Result<Self, ConstMathErr> {
+ match isize_ty {
+ ast::IntTy::I16 if i as i16 as i64 == i => Ok(Is16(i as i16)),
+ ast::IntTy::I16 => Err(LitOutOfRange(ast::IntTy::Isize)),
+ ast::IntTy::I32 if i as i32 as i64 == i => Ok(Is32(i as i32)),
+ ast::IntTy::I32 => Err(LitOutOfRange(ast::IntTy::Isize)),
+ ast::IntTy::I64 => Ok(Is64(i)),
+ _ => unreachable!(),
+ }
+ }
+ pub fn new_truncating(i: i128, isize_ty: ast::IntTy) -> Self {
+ match isize_ty {
+ ast::IntTy::I16 => Is16(i as i16),
+ ast::IntTy::I32 => Is32(i as i32),
+ ast::IntTy::I64 => Is64(i as i64),
+ _ => unreachable!(),
+ }
+ }
+}
mod float;
mod int;
-mod us;
-mod is;
+mod usize;
+mod isize;
mod err;
pub use float::*;
pub use int::*;
-pub use us::*;
-pub use is::*;
+pub use usize::*;
+pub use isize::*;
pub use err::{ConstMathErr, Op};
+++ /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.
-
-use syntax::ast;
-use super::err::*;
-
-/// Depending on the target only one variant is ever used in a compilation.
-/// Anything else is an error. This invariant is checked at several locations
-#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable, Hash, Eq, PartialEq)]
-pub enum ConstUsize {
- Us16(u16),
- Us32(u32),
- Us64(u64),
-}
-pub use self::ConstUsize::*;
-
-impl ::std::fmt::Display for ConstUsize {
- fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
- write!(fmt, "{}", self.as_u64())
- }
-}
-
-impl ConstUsize {
- pub fn as_u64(self) -> u64 {
- match self {
- Us16(i) => i as u64,
- Us32(i) => i as u64,
- Us64(i) => i,
- }
- }
- pub fn new(i: u64, usize_ty: ast::UintTy) -> Result<Self, ConstMathErr> {
- match usize_ty {
- ast::UintTy::U16 if i as u16 as u64 == i => Ok(Us16(i as u16)),
- ast::UintTy::U16 => Err(ULitOutOfRange(ast::UintTy::Us)),
- ast::UintTy::U32 if i as u32 as u64 == i => Ok(Us32(i as u32)),
- ast::UintTy::U32 => Err(ULitOutOfRange(ast::UintTy::Us)),
- ast::UintTy::U64 => Ok(Us64(i)),
- _ => unreachable!(),
- }
- }
- pub fn new_truncating(i: u128, usize_ty: ast::UintTy) -> Self {
- match usize_ty {
- ast::UintTy::U16 => Us16(i as u16),
- ast::UintTy::U32 => Us32(i as u32),
- ast::UintTy::U64 => Us64(i as u64),
- _ => unreachable!(),
- }
- }
-}
--- /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.
+
+use syntax::ast;
+use super::err::*;
+
+/// Depending on the target only one variant is ever used in a compilation.
+/// Anything else is an error. This invariant is checked at several locations
+#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable, Hash, Eq, PartialEq)]
+pub enum ConstUsize {
+ Us16(u16),
+ Us32(u32),
+ Us64(u64),
+}
+pub use self::ConstUsize::*;
+
+impl ::std::fmt::Display for ConstUsize {
+ fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
+ write!(fmt, "{}", self.as_u64())
+ }
+}
+
+impl ConstUsize {
+ pub fn as_u64(self) -> u64 {
+ match self {
+ Us16(i) => i as u64,
+ Us32(i) => i as u64,
+ Us64(i) => i,
+ }
+ }
+ pub fn new(i: u64, usize_ty: ast::UintTy) -> Result<Self, ConstMathErr> {
+ match usize_ty {
+ ast::UintTy::U16 if i as u16 as u64 == i => Ok(Us16(i as u16)),
+ ast::UintTy::U16 => Err(ULitOutOfRange(ast::UintTy::Usize)),
+ ast::UintTy::U32 if i as u32 as u64 == i => Ok(Us32(i as u32)),
+ ast::UintTy::U32 => Err(ULitOutOfRange(ast::UintTy::Usize)),
+ ast::UintTy::U64 => Ok(Us64(i)),
+ _ => unreachable!(),
+ }
+ }
+ pub fn new_truncating(i: u128, usize_ty: ast::UintTy) -> Self {
+ match usize_ty {
+ ast::UintTy::U16 => Us16(i as u16),
+ ast::UintTy::U32 => Us32(i as u32),
+ ast::UintTy::U64 => Us64(i as u64),
+ _ => unreachable!(),
+ }
+ }
+}
crate-type = ["dylib"]
[dependencies]
-log = "0.3"
+log = "0.4"
serialize = { path = "../libserialize" }
cfg-if = "0.1.2"
stable_deref_trait = "1.0.0"
[dependencies.parking_lot]
version = "0.5"
-features = ["nightly"]
\ No newline at end of file
+features = ["nightly"]
use std::marker::Unsize;
use std::iter::Extend;
-use std::ptr::{self, drop_in_place, Shared};
+use std::ptr::{self, drop_in_place, NonNull};
use std::ops::{Deref, DerefMut, Range};
use std::hash::{Hash, Hasher};
use std::slice;
tail_start: end,
tail_len: len - end,
iter: range_slice.iter(),
- array_vec: Shared::from(self),
+ array_vec: NonNull::from(self),
}
}
}
tail_start: usize,
tail_len: usize,
iter: slice::Iter<'a, ManuallyDrop<A::Element>>,
- array_vec: Shared<ArrayVec<A>>,
+ array_vec: NonNull<ArrayVec<A>>,
}
impl<'a, A: Array> Iterator for Drain<'a, A> {
use std::str;
-pub const MAX_BASE: u64 = 64;
-pub const ALPHANUMERIC_ONLY: u64 = 62;
+pub const MAX_BASE: usize = 64;
+pub const ALPHANUMERIC_ONLY: usize = 62;
+pub const CASE_INSENSITIVE: usize = 36;
const BASE_64: &'static [u8; MAX_BASE as usize] =
b"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ@$";
#[inline]
-pub fn push_str(mut n: u64, base: u64, output: &mut String) {
+pub fn push_str(mut n: u128, base: usize, output: &mut String) {
debug_assert!(base >= 2 && base <= MAX_BASE);
- let mut s = [0u8; 64];
+ let mut s = [0u8; 128];
let mut index = 0;
+ let base = base as u128;
+
loop {
s[index] = BASE_64[(n % base) as usize];
index += 1;
}
#[inline]
-pub fn encode(n: u64, base: u64) -> String {
- let mut s = String::with_capacity(13);
+pub fn encode(n: u128, base: usize) -> String {
+ let mut s = String::new();
push_str(n, base, &mut s);
s
}
#[test]
fn test_encode() {
- fn test(n: u64, base: u64) {
- assert_eq!(Ok(n), u64::from_str_radix(&encode(n, base), base as u32));
+ fn test(n: u128, base: usize) {
+ assert_eq!(Ok(n), u128::from_str_radix(&encode(n, base), base as u32));
}
for base in 2..37 {
test(35, base);
test(36, base);
test(37, base);
- test(u64::max_value(), base);
+ test(u64::max_value() as u128, base);
+ test(u128::max_value(), base);
for i in 0 .. 1_000 {
test(i * 983, base);
html_root_url = "https://doc.rust-lang.org/nightly/")]
#![deny(warnings)]
-#![feature(shared)]
#![feature(collections_range)]
#![feature(nonzero)]
#![feature(unboxed_closures)]
[dependencies]
arena = { path = "../libarena" }
graphviz = { path = "../libgraphviz" }
-log = { version = "0.3", features = ["release_max_level_info"] }
+log = { version = "0.4", features = ["release_max_level_info"] }
env_logger = { version = "0.4", default-features = false }
rustc = { path = "../librustc" }
rustc_allocator = { path = "../librustc_allocator" }
use rustc_privacy;
use rustc_plugin::registry::Registry;
use rustc_plugin as plugin;
-use rustc_passes::{self, ast_validation, no_asm, loops, consts, static_recursion, hir_stats};
+use rustc_passes::{self, ast_validation, loops, consts, static_recursion, hir_stats};
use rustc_const_eval::{self, check_match};
use super::Compilation;
use ::DefaultTransCrate;
|| hir_map::map_crate(sess, cstore, &mut hir_forest, &defs));
{
- let _ignore = hir_map.dep_graph.in_ignore();
+ hir_map.dep_graph.assert_ignored();
controller_entry_point!(after_hir_lowering,
sess,
CompileState::state_after_hir_lowering(input,
Ok(()));
}
- time(sess.time_passes(), "attribute checking", || {
- hir::check_attr::check_crate(sess, &expanded_crate);
- });
-
let opt_crate = if control.keep_ast {
Some(&expanded_crate)
} else {
|tcx, analysis, rx, result| {
{
// Eventually, we will want to track plugins.
- let _ignore = tcx.dep_graph.in_ignore();
-
- let mut state = CompileState::state_after_analysis(input,
- sess,
- outdir,
- output,
- opt_crate,
- tcx.hir.krate(),
- &analysis,
- tcx,
- &crate_name);
- (control.after_analysis.callback)(&mut state);
+ tcx.dep_graph.with_ignore(|| {
+ let mut state = CompileState::state_after_analysis(input,
+ sess,
+ outdir,
+ output,
+ opt_crate,
+ tcx.hir.krate(),
+ &analysis,
+ tcx,
+ &crate_name);
+ (control.after_analysis.callback)(&mut state);
+ });
if control.after_analysis.stop == Compilation::Stop {
return result.and_then(|_| Err(CompileIncomplete::Stopped));
result?;
- if log_enabled!(::log::LogLevel::Info) {
+ if log_enabled!(::log::Level::Info) {
println!("Pre-trans");
tcx.print_debug_stats();
}
let trans = phase_4_translate_to_llvm::<DefaultTransCrate>(tcx, rx);
- if log_enabled!(::log::LogLevel::Info) {
+ if log_enabled!(::log::Level::Info) {
println!("Post-trans");
tcx.print_debug_stats();
}
println!("{}", json::as_json(&krate));
}
- time(time_passes,
- "checking for inline asm in case the target doesn't support it",
- || no_asm::check_crate(sess, &krate));
-
time(time_passes,
"AST validation",
|| ast_validation::check_crate(sess, &krate));
let dep_graph = match future_dep_graph {
None => DepGraph::new_disabled(),
Some(future) => {
- let prev_graph = future
- .open()
- .expect("Could not join with background dep_graph thread")
- .open(sess);
+ let prev_graph = time(time_passes, "blocked while dep-graph loading finishes", || {
+ future.open()
+ .expect("Could not join with background dep_graph thread")
+ .open(sess)
+ });
DepGraph::new(prev_graph)
}
};
// tcx available.
rustc_incremental::dep_graph_tcx_init(tcx);
+ time(sess.time_passes(), "attribute checking", || {
+ hir::check_attr::check_crate(tcx)
+ });
+
time(time_passes,
"stability checking",
|| stability::check_unstable_api_usage(tcx));
out_filenames.push(p);
}
}
+ OutputType::DepInfo if sess.opts.debugging_opts.dep_info_omit_d_target => {
+ // Don't add the dep-info output when omitting it from dep-info targets
+ }
_ => {
out_filenames.push(file);
}
pub use rustc_trans_utils::trans_crate::TranslatedCrate as CrateTranslation;
pub fn init(_sess: &Session) {}
- pub fn enable_llvm_debug() {}
pub fn print_version() {}
pub fn print_passes() {}
pub fn print(_req: PrintRequest, _sess: &Session) {}
let (sopts, cfg) = config::build_session_options_and_crate_config(&matches);
- if sopts.debugging_opts.debug_llvm {
- rustc_trans::enable_llvm_debug();
- }
-
let descriptions = diagnostics_registry();
do_or_return!(callbacks.early_callback(&matches,
panic!();
}
+#[cfg(stage0)]
+pub fn diagnostics_registry() -> errors::registry::Registry {
+ use errors::registry::Registry;
+
+ Registry::new(&[])
+}
+
+#[cfg(not(stage0))]
pub fn diagnostics_registry() -> errors::registry::Registry {
use errors::registry::Registry;
tcx,
tables: Cell::new(&empty_tables)
};
- let _ignore = tcx.dep_graph.in_ignore();
- f(&annotation, hir_map.forest.krate())
+ tcx.dep_graph.with_ignore(|| {
+ f(&annotation, hir_map.forest.krate())
+ })
}),
sess)
}
hir::ItemUnion(..) |
hir::ItemTrait(..) |
hir::ItemTraitAlias(..) |
- hir::ItemImpl(..) |
- hir::ItemAutoImpl(..) => None,
+ hir::ItemImpl(..) => None,
hir::ItemMod(ref m) => search_mod(this, m, idx, names),
};
buffer.append(buffer_msg_line_offset,
&format!("{}:{}:{}",
loc.file.name,
- loc.line,
+ cm.doctest_offset_line(loc.line),
loc.col.0 + 1),
Style::LineAndColumn);
for _ in 0..max_line_num_len {
buffer.prepend(0,
&format!("{}:{}:{} - ",
loc.file.name,
- loc.line,
+ cm.doctest_offset_line(loc.line),
loc.col.0 + 1),
Style::LineAndColumn);
}
let sub_len = parts[0].snippet.trim().chars().fold(0, |acc, ch| {
acc + unicode_width::UnicodeWidthChar::width(ch).unwrap_or(0)
});
- let underline_start = span_start_pos.col.0 + start;
- let underline_end = span_start_pos.col.0 + start + sub_len;
+ let underline_start = span_start_pos.col_display + start;
+ let underline_end = span_start_pos.col_display + start + sub_len;
for p in underline_start..underline_end {
buffer.putc(row_num,
max_line_num_len + 3 + p,
fn merge_spans(&self, sp_lhs: Span, sp_rhs: Span) -> Option<Span>;
fn call_span_if_macro(&self, sp: Span) -> Span;
fn ensure_filemap_source_present(&self, file_map: Rc<FileMap>) -> bool;
+ fn doctest_offset_line(&self, line: usize) -> usize;
}
impl CodeSuggestion {
self.continue_after_error.set(continue_after_error);
}
- // NOTE: DO NOT call this function from rustc, as it relies on `err_count` being non-zero
- // if an error happened to avoid ICEs. This function should only be called from tools.
+ /// Resets the diagnostic error count as well as the cached emitted diagnostics.
+ ///
+ /// NOTE: DO NOT call this function from rustc. It is only meant to be called from external
+ /// tools that want to reuse a `Parser` cleaning the previously emitted diagnostics as well as
+ /// the overall count of emitted error diagnostics.
pub fn reset_err_count(&self) {
+ self.emitted_diagnostics.replace(FxHashSet());
self.err_count.store(0, SeqCst);
}
[dependencies]
graphviz = { path = "../libgraphviz" }
-log = "0.3"
+log = "0.4"
rand = "0.3"
rustc = { path = "../librustc" }
rustc_data_structures = { path = "../librustc_data_structures" }
use rustc::ich::{ATTR_IF_THIS_CHANGED, ATTR_THEN_THIS_WOULD_NEED};
use graphviz::IntoCow;
use std::env;
-use std::fs::File;
+use std::fs::{self, File};
use std::io::Write;
use syntax::ast;
use syntax_pos::Span;
pub fn assert_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
- let _ignore = tcx.dep_graph.in_ignore();
-
- if tcx.sess.opts.debugging_opts.dump_dep_graph {
- dump_graph(tcx);
- }
-
- // if the `rustc_attrs` feature is not enabled, then the
- // attributes we are interested in cannot be present anyway, so
- // skip the walk.
- if !tcx.sess.features.borrow().rustc_attrs {
- return;
- }
+ tcx.dep_graph.with_ignore(|| {
+ if tcx.sess.opts.debugging_opts.dump_dep_graph {
+ dump_graph(tcx);
+ }
- // Find annotations supplied by user (if any).
- let (if_this_changed, then_this_would_need) = {
- let mut visitor = IfThisChanged { tcx,
- if_this_changed: vec![],
- then_this_would_need: vec![] };
- visitor.process_attrs(ast::CRATE_NODE_ID, &tcx.hir.krate().attrs);
- tcx.hir.krate().visit_all_item_likes(&mut visitor.as_deep_visitor());
- (visitor.if_this_changed, visitor.then_this_would_need)
- };
+ // if the `rustc_attrs` feature is not enabled, then the
+ // attributes we are interested in cannot be present anyway, so
+ // skip the walk.
+ if !tcx.sess.features.borrow().rustc_attrs {
+ return;
+ }
- if !if_this_changed.is_empty() || !then_this_would_need.is_empty() {
- assert!(tcx.sess.opts.debugging_opts.query_dep_graph,
- "cannot use the `#[{}]` or `#[{}]` annotations \
- without supplying `-Z query-dep-graph`",
- ATTR_IF_THIS_CHANGED, ATTR_THEN_THIS_WOULD_NEED);
- }
+ // Find annotations supplied by user (if any).
+ let (if_this_changed, then_this_would_need) = {
+ let mut visitor = IfThisChanged { tcx,
+ if_this_changed: vec![],
+ then_this_would_need: vec![] };
+ visitor.process_attrs(ast::CRATE_NODE_ID, &tcx.hir.krate().attrs);
+ tcx.hir.krate().visit_all_item_likes(&mut visitor.as_deep_visitor());
+ (visitor.if_this_changed, visitor.then_this_would_need)
+ };
+
+ if !if_this_changed.is_empty() || !then_this_would_need.is_empty() {
+ assert!(tcx.sess.opts.debugging_opts.query_dep_graph,
+ "cannot use the `#[{}]` or `#[{}]` annotations \
+ without supplying `-Z query-dep-graph`",
+ ATTR_IF_THIS_CHANGED, ATTR_THEN_THIS_WOULD_NEED);
+ }
- // Check paths.
- check_paths(tcx, &if_this_changed, &then_this_would_need);
+ // Check paths.
+ check_paths(tcx, &if_this_changed, &then_this_would_need);
+ })
}
type Sources = Vec<(Span, DefId, DepNode)>;
let dot_path = format!("{}.dot", path);
let mut v = Vec::new();
dot::render(&GraphvizDepGraph(nodes, edges), &mut v).unwrap();
- File::create(&dot_path).and_then(|mut f| f.write_all(&v)).unwrap();
+ fs::write(dot_path, v).unwrap();
}
}
#![deny(warnings)]
#![feature(conservative_impl_trait)]
+#![feature(fs_read_write)]
#![feature(i128_type)]
#![feature(inclusive_range_syntax)]
#![feature(specialization)]
return;
}
- let _ignore = tcx.dep_graph.in_ignore();
- let krate = tcx.hir.krate();
- let mut dirty_clean_visitor = DirtyCleanVisitor {
- tcx,
- checked_attrs: FxHashSet(),
- };
- krate.visit_all_item_likes(&mut dirty_clean_visitor);
-
- let mut all_attrs = FindAllAttrs {
- tcx,
- attr_names: vec![ATTR_DIRTY, ATTR_CLEAN],
- found_attrs: vec![],
- };
- intravisit::walk_crate(&mut all_attrs, krate);
-
- // Note that we cannot use the existing "unused attribute"-infrastructure
- // here, since that is running before trans. This is also the reason why
- // all trans-specific attributes are `Whitelisted` in syntax::feature_gate.
- all_attrs.report_unchecked_attrs(&dirty_clean_visitor.checked_attrs);
+ tcx.dep_graph.with_ignore(|| {
+ let krate = tcx.hir.krate();
+ let mut dirty_clean_visitor = DirtyCleanVisitor {
+ tcx,
+ checked_attrs: FxHashSet(),
+ };
+ krate.visit_all_item_likes(&mut dirty_clean_visitor);
+
+ let mut all_attrs = FindAllAttrs {
+ tcx,
+ attr_names: vec![ATTR_DIRTY, ATTR_CLEAN],
+ found_attrs: vec![],
+ };
+ intravisit::walk_crate(&mut all_attrs, krate);
+
+ // Note that we cannot use the existing "unused attribute"-infrastructure
+ // here, since that is running before trans. This is also the reason why
+ // all trans-specific attributes are `Whitelisted` in syntax::feature_gate.
+ all_attrs.report_unchecked_attrs(&dirty_clean_visitor.checked_attrs);
+ })
}
pub struct DirtyCleanVisitor<'a, 'tcx:'a> {
//
//HirItem::ItemTrait(..) => ("ItemTrait", LABELS_TRAIT),
- // `impl Trait for .. {}`
- HirItem::ItemAutoImpl(..) => ("ItemAutoImpl", LABELS_IMPL),
-
// An implementation, eg `impl<A> Trait for Foo { .. }`
HirItem::ItemImpl(..) => ("ItemImpl", LABELS_IMPL),
use std::io::{self, Read};
use std::path::Path;
-use std::fs::File;
+use std::fs;
use std::env;
use rustc::session::config::nightly_options;
return Ok(None);
}
- let mut file = File::open(path)?;
- let file_size = file.metadata()?.len() as usize;
-
- let mut data = Vec::with_capacity(file_size);
- file.read_to_end(&mut data)?;
+ let data = fs::read(path)?;
let mut file = io::Cursor::new(data);
// or hexadecimal numbers (we want short file and directory names). Since these
// numbers will be used in file names, we choose an encoding that is not
// case-sensitive (as opposed to base64, for example).
-const INT_ENCODE_BASE: u64 = 36;
+const INT_ENCODE_BASE: usize = base_n::CASE_INSENSITIVE;
pub fn dep_graph_path(sess: &Session) -> PathBuf {
in_incr_comp_dir_sess(sess, DEP_GRAPH_FILENAME)
let mut new_sub_dir_name = String::from(&old_sub_dir_name[.. dash_indices[2] + 1]);
// Append the svh
- base_n::push_str(svh.as_u64(), INT_ENCODE_BASE, &mut new_sub_dir_name);
+ base_n::push_str(svh.as_u64() as u128, INT_ENCODE_BASE, &mut new_sub_dir_name);
// Create the full path
let new_path = incr_comp_session_dir.parent().unwrap().join(new_sub_dir_name);
let directory_name = format!("s-{}-{}-working",
timestamp,
- base_n::encode(random_number as u64,
+ base_n::encode(random_number as u128,
INT_ENCODE_BASE));
debug!("generate_session_dir_path: directory_name = {}", directory_name);
let directory_path = crate_dir.join(directory_name);
let duration = timestamp.duration_since(UNIX_EPOCH).unwrap();
let micros = duration.as_secs() * 1_000_000 +
(duration.subsec_nanos() as u64) / 1000;
- base_n::encode(micros, INT_ENCODE_BASE)
+ base_n::encode(micros as u128, INT_ENCODE_BASE)
}
fn string_to_timestamp(s: &str) -> Result<SystemTime, ()> {
// The full crate disambiguator is really long. 64 bits of it should be
// sufficient.
let crate_disambiguator = crate_disambiguator.to_fingerprint().to_smaller_hash();
- let crate_disambiguator = base_n::encode(crate_disambiguator, INT_ENCODE_BASE);
+ let crate_disambiguator = base_n::encode(crate_disambiguator as u128,
+ INT_ENCODE_BASE);
let crate_name = format!("{}-{}", crate_name, crate_disambiguator);
incr_dir.join(crate_name)
use rustc_data_structures::fx::FxHashMap;
use rustc_serialize::Encodable as RustcEncodable;
use rustc_serialize::opaque::Encoder;
-use std::io::{self, Cursor, Write};
-use std::fs::{self, File};
+use std::io::{self, Cursor};
+use std::fs;
use std::path::PathBuf;
use super::data::*;
pub fn save_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
debug!("save_dep_graph()");
- let _ignore = tcx.dep_graph.in_ignore();
- let sess = tcx.sess;
- if sess.opts.incremental.is_none() {
- return;
- }
-
- time(sess.time_passes(), "persist query result cache", || {
- save_in(sess,
- query_cache_path(sess),
- |e| encode_query_cache(tcx, e));
- });
+ tcx.dep_graph.with_ignore(|| {
+ let sess = tcx.sess;
+ if sess.opts.incremental.is_none() {
+ return;
+ }
- if tcx.sess.opts.debugging_opts.incremental_queries {
- time(sess.time_passes(), "persist dep-graph", || {
+ time(sess.time_passes(), "persist query result cache", || {
save_in(sess,
- dep_graph_path(sess),
- |e| encode_dep_graph(tcx, e));
+ query_cache_path(sess),
+ |e| encode_query_cache(tcx, e));
});
- }
- dirty_clean::check_dirty_clean_annotations(tcx);
+ if tcx.sess.opts.debugging_opts.incremental_queries {
+ time(sess.time_passes(), "persist dep-graph", || {
+ save_in(sess,
+ dep_graph_path(sess),
+ |e| encode_dep_graph(tcx, e));
+ });
+ }
+
+ dirty_clean::check_dirty_clean_annotations(tcx);
+ })
}
pub fn save_work_products(sess: &Session, dep_graph: &DepGraph) {
}
debug!("save_work_products()");
- let _ignore = dep_graph.in_ignore();
+ dep_graph.assert_ignored();
let path = work_products_path(sess);
save_in(sess, path, |e| encode_work_products(dep_graph, e));
// write the data out
let data = wr.into_inner();
- match File::create(&path_buf).and_then(|mut file| file.write_all(&data)) {
+ match fs::write(&path_buf, data) {
Ok(_) => {
debug!("save: data written to disk successfully");
}
let extension = match kind {
WorkProductFileKind::Object => "o",
WorkProductFileKind::Bytecode => "bc",
- WorkProductFileKind::BytecodeCompressed => "bc-compressed",
+ WorkProductFileKind::BytecodeCompressed => "bc.z",
};
- let file_name = format!("cgu-{}.{}", cgu_name, extension);
+ let file_name = format!("{}.{}", cgu_name, extension);
let path_in_incr_dir = in_incr_comp_dir_sess(sess, &file_name);
match link_or_copy(path, &path_in_incr_dir) {
Ok(_) => Some((kind, file_name)),
test = false
[dependencies]
-log = "0.3"
+log = "0.4"
rustc = { path = "../librustc" }
rustc_const_eval = { path = "../librustc_const_eval" }
syntax = { path = "../libsyntax" }
impl NonCamelCaseTypes {
fn check_case(&self, cx: &LateContext, sort: &str, name: ast::Name, span: Span) {
+ fn char_has_case(c: char) -> bool {
+ c.is_lowercase() || c.is_uppercase()
+ }
+
fn is_camel_case(name: ast::Name) -> bool {
let name = name.as_str();
if name.is_empty() {
// start with a non-lowercase letter rather than non-uppercase
// ones (some scripts don't have a concept of upper/lowercase)
- !name.is_empty() && !name.chars().next().unwrap().is_lowercase() && !name.contains('_')
+ !name.is_empty() && !name.chars().next().unwrap().is_lowercase() &&
+ !name.contains("__") && !name.chars().collect::<Vec<_>>().windows(2).any(|pair| {
+ // contains a capitalisable character followed by, or preceded by, an underscore
+ char_has_case(pair[0]) && pair[1] == '_' ||
+ char_has_case(pair[1]) && pair[0] == '_'
+ })
}
fn to_camel_case(s: &str) -> String {
- s.split('_')
- .flat_map(|word| {
+ s.trim_matches('_')
+ .split('_')
+ .map(|word| {
word.chars().enumerate().map(|(i, c)| if i == 0 {
c.to_uppercase().collect::<String>()
} else {
c.to_lowercase().collect()
})
+ .collect::<Vec<_>>()
+ .concat()
})
+ .filter(|x| !x.is_empty())
.collect::<Vec<_>>()
- .concat()
+ .iter().fold((String::new(), None), |(acc, prev): (String, Option<&String>), next| {
+ // separate two components with an underscore if their boundary cannot
+ // be distinguished using a uppercase/lowercase case distinction
+ let join = if let Some(prev) = prev {
+ let l = prev.chars().last().unwrap();
+ let f = next.chars().next().unwrap();
+ !char_has_case(l) && !char_has_case(f)
+ } else { false };
+ (acc + if join { "_" } else { "" } + next, Some(next))
+ }).0
}
if !is_camel_case(name) {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonCamelCaseTypes {
fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
- let extern_repr_count = it.attrs
+ let has_repr_c = it.attrs
.iter()
- .filter(|attr| {
+ .any(|attr| {
attr::find_repr_attrs(cx.tcx.sess.diagnostic(), attr)
.iter()
- .any(|r| r == &attr::ReprExtern)
- })
- .count();
- let has_extern_repr = extern_repr_count > 0;
+ .any(|r| r == &attr::ReprC)
+ });
- if has_extern_repr {
+ if has_repr_c {
return;
}
// hardwired lints from librustc
pub use lint::builtin::*;
-declare_lint! {
- pub AUTO_IMPL,
- Deny,
- "The form `impl Foo for .. {}` will be removed, please use `auto trait Foo {}`"
-}
-
-#[derive(Copy, Clone)]
-pub struct AutoImpl;
-
-impl LintPass for AutoImpl {
- fn get_lints(&self) -> LintArray {
- lint_array!(AUTO_IMPL)
- }
-}
-
-impl EarlyLintPass for AutoImpl {
- fn check_item(&mut self, cx: &EarlyContext, item: &ast::Item) {
- let msg = "The form `impl Foo for .. {}` will be removed, please use `auto trait Foo {}`";
- match item.node {
- ast::ItemKind::AutoImpl(..) => cx.span_lint(AUTO_IMPL, item.span, msg),
- _ => ()
- }
- }
-}
-
declare_lint! {
WHILE_TRUE,
Warn,
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());
- err.span_suggestion(insertion_span,
- "try making it public",
- "pub ".to_owned());
+ if it.vis == hir::Visibility::Inherited {
+ err.span_suggestion(insertion_span,
+ "try making it public",
+ "pub ".to_owned());
+ }
err.emit();
}
if generics.is_type_parameterized() {
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());
- err.span_suggestion(insertion_span,
- "try making it public",
- "pub ".to_owned());
+ if it.vis == hir::Visibility::Inherited {
+ err.span_suggestion(insertion_span,
+ "try making it public",
+ "pub ".to_owned());
+ }
err.emit();
}
}
// don't have anything to attach a symbol to
let msg = "const items should never be #[no_mangle]";
let mut err = cx.struct_span_lint(NO_MANGLE_CONST_ITEMS, it.span, msg);
+
+ // account for "pub const" (#45562)
+ let start = cx.tcx.sess.codemap().span_to_snippet(it.span)
+ .map(|snippet| snippet.find("const").unwrap_or(0))
+ .unwrap_or(0) as u32;
// `const` is 5 chars
- let const_span = it.span.with_hi(BytePos(it.span.lo().0 + 5));
+ let const_span = it.span.with_hi(BytePos(it.span.lo().0 + start + 5));
err.span_suggestion(const_span,
"try a static value",
"pub static".to_owned());
AnonymousParameters,
IllegalFloatLiteralPattern,
UnusedDocComment,
- AutoImpl,
);
add_early_builtin_with_new!(sess,
// - Eventually, remove lint
store.register_future_incompatible(sess,
vec![
- FutureIncompatibleInfo {
- id: LintId::of(AUTO_IMPL),
- reference: "issue #13231 <https://github.com/rust-lang/rust/issues/13231>",
- },
FutureIncompatibleInfo {
id: LintId::of(PRIVATE_IN_PUBLIC),
reference: "issue #34537 <https://github.com/rust-lang/rust/issues/34537>",
match lit.node {
ast::LitKind::Int(v, ast::LitIntType::Signed(_)) |
ast::LitKind::Int(v, ast::LitIntType::Unsuffixed) => {
- let int_type = if let ast::IntTy::Is = t {
+ let int_type = if let ast::IntTy::Isize = t {
cx.sess().target.isize_ty
} else {
t
};
}
ty::TyUint(t) => {
- let uint_type = if let ast::UintTy::Us = t {
+ let uint_type = if let ast::UintTy::Usize = t {
cx.sess().target.usize_ty
} else {
t
// warnings are consistent between 32- and 64-bit platforms
fn int_ty_range(int_ty: ast::IntTy) -> (i128, i128) {
match int_ty {
- ast::IntTy::Is => (i64::min_value() as i128, i64::max_value() as i128),
+ ast::IntTy::Isize => (i64::min_value() as i128, i64::max_value() as i128),
ast::IntTy::I8 => (i8::min_value() as i64 as i128, i8::max_value() as i128),
ast::IntTy::I16 => (i16::min_value() as i64 as i128, i16::max_value() as i128),
ast::IntTy::I32 => (i32::min_value() as i64 as i128, i32::max_value() as i128),
fn uint_ty_range(uint_ty: ast::UintTy) -> (u128, u128) {
match uint_ty {
- ast::UintTy::Us => (u64::min_value() as u128, u64::max_value() as u128),
+ ast::UintTy::Usize => (u64::min_value() as u128, u64::max_value() as u128),
ast::UintTy::U8 => (u8::min_value() as u128, u8::max_value() as u128),
ast::UintTy::U16 => (u16::min_value() as u128, u16::max_value() as u128),
ast::UintTy::U32 => (u32::min_value() as u128, u32::max_value() as u128),
fn int_ty_bits(int_ty: ast::IntTy, isize_ty: ast::IntTy) -> u64 {
match int_ty {
- ast::IntTy::Is => int_ty_bits(isize_ty, isize_ty),
+ ast::IntTy::Isize => int_ty_bits(isize_ty, isize_ty),
ast::IntTy::I8 => 8,
ast::IntTy::I16 => 16 as u64,
ast::IntTy::I32 => 32,
fn uint_ty_bits(uint_ty: ast::UintTy, usize_ty: ast::UintTy) -> u64 {
match uint_ty {
- ast::UintTy::Us => uint_ty_bits(usize_ty, usize_ty),
+ ast::UintTy::Usize => uint_ty_bits(usize_ty, usize_ty),
ast::UintTy::U8 => 8,
ast::UintTy::U16 => 16,
ast::UintTy::U32 => 32,
attr::SignedInt(ast::IntTy::I32) | attr::UnsignedInt(ast::UintTy::U32) |
attr::SignedInt(ast::IntTy::I64) | attr::UnsignedInt(ast::UintTy::U64) |
attr::SignedInt(ast::IntTy::I128) | attr::UnsignedInt(ast::UintTy::U128) => true,
- attr::SignedInt(ast::IntTy::Is) | attr::UnsignedInt(ast::UintTy::Us) => false
+ attr::SignedInt(ast::IntTy::Isize) | attr::UnsignedInt(ast::UintTy::Usize) => false
}
}
consider adding a #[repr(C)] attribute to the type");
}
- if def.struct_variant().fields.is_empty() {
+ if def.non_enum_variant().fields.is_empty() {
return FfiUnsafe("found zero-size struct in foreign module, consider \
adding a member to this struct");
}
// We can't completely trust repr(C) markings; make sure the
// fields are actually safe.
let mut all_phantom = true;
- for field in &def.struct_variant().fields {
+ for field in &def.non_enum_variant().fields {
let field_ty = cx.fully_normalize_associated_types_in(
&field.ty(cx, substs)
);
consider adding a #[repr(C)] attribute to the type");
}
- if def.struct_variant().fields.is_empty() {
+ if def.non_enum_variant().fields.is_empty() {
return FfiUnsafe("found zero-size union in foreign module, consider \
adding a member to this union");
}
let mut all_phantom = true;
- for field in &def.struct_variant().fields {
+ for field in &def.non_enum_variant().fields {
let field_ty = cx.fully_normalize_associated_types_in(
&field.ty(cx, substs)
);
Assign(_, ref value) => (value, "assigned value", false),
AssignOp(.., ref value) => (value, "assigned value", false),
InPlace(_, ref value) => (value, "emplacement value", false),
+ Call(_, ref args) => {
+ for arg in args {
+ self.check_unused_parens_core(cx, arg, "function argument", false)
+ }
+ return;
+ },
+ MethodCall(_, ref args) => {
+ for arg in &args[1..] { // first "argument" is self (which sometimes needs parens)
+ self.check_unused_parens_core(cx, arg, "method argument", false)
+ }
+ return;
+ }
_ => return,
};
self.check_unused_parens_core(cx, &value, msg, struct_lit_needs_parens);
#[link(name = "rustllvm", kind = "static")]
extern "C" {
// Create and destroy contexts.
- pub fn LLVMContextCreate() -> ContextRef;
+ pub fn LLVMRustContextCreate(shouldDiscardNames: bool) -> ContextRef;
pub fn LLVMContextDispose(C: ContextRef);
pub fn LLVMGetMDKindIDInContext(C: ContextRef, Name: *const c_char, SLen: c_uint) -> c_uint;
/// See llvm::LLVMTypeKind::getTypeID.
pub fn LLVMRustGetTypeKind(Ty: TypeRef) -> TypeKind;
- /// See llvm::Value::getContext
- pub fn LLVMRustGetValueContext(V: ValueRef) -> ContextRef;
-
// Operations on integer types
pub fn LLVMInt1TypeInContext(C: ContextRef) -> TypeRef;
pub fn LLVMInt8TypeInContext(C: ContextRef) -> TypeRef;
Bundle: OperandBundleDefRef,
Name: *const c_char)
-> ValueRef;
- pub fn LLVMRustBuildLandingPad(B: BuilderRef,
- Ty: TypeRef,
- PersFn: ValueRef,
- NumClauses: c_uint,
- Name: *const c_char,
- F: ValueRef)
- -> ValueRef;
+ pub fn LLVMBuildLandingPad(B: BuilderRef,
+ Ty: TypeRef,
+ PersFn: ValueRef,
+ NumClauses: c_uint,
+ Name: *const c_char)
+ -> ValueRef;
pub fn LLVMBuildResume(B: BuilderRef, Exn: ValueRef) -> ValueRef;
pub fn LLVMBuildUnreachable(B: BuilderRef) -> ValueRef;
ElementCount: c_uint,
Packed: Bool);
- /// Enables LLVM debug output.
- pub fn LLVMRustSetDebug(Enabled: c_int);
-
/// Prepares inline assembly.
pub fn LLVMRustInlineAsm(Ty: TypeRef,
AsmString: *const c_char,
pub fn LLVMRustSetNormalizedTarget(M: ModuleRef, triple: *const c_char);
pub fn LLVMRustAddAlwaysInlinePass(P: PassManagerBuilderRef, AddLifetimes: bool);
pub fn LLVMRustLinkInExternalBitcode(M: ModuleRef, bc: *const c_char, len: size_t) -> bool;
- pub fn LLVMRustLinkInParsedExternalBitcode(M: ModuleRef, M: ModuleRef) -> bool;
pub fn LLVMRustRunRestrictionPass(M: ModuleRef, syms: *const *const c_char, len: size_t);
pub fn LLVMRustMarkAllFunctionsNounwind(M: ModuleRef);
pub fn LLVMRustWriteDiagnosticInfoToString(DI: DiagnosticInfoRef, s: RustStringRef);
pub fn LLVMRustGetDiagInfoKind(DI: DiagnosticInfoRef) -> DiagnosticKind;
- pub fn LLVMRustWriteDebugLocToString(C: ContextRef, DL: DebugLocRef, s: RustStringRef);
-
pub fn LLVMRustSetInlineAsmDiagnosticHandler(C: ContextRef,
H: InlineAsmDiagHandler,
CX: *mut c_void);
pub fn LLVMRustArchiveMemberFree(Member: RustArchiveMemberRef);
pub fn LLVMRustSetDataLayoutFromTargetMachine(M: ModuleRef, TM: TargetMachineRef);
- pub fn LLVMRustGetModuleDataLayout(M: ModuleRef) -> TargetDataRef;
pub fn LLVMRustBuildOperandBundleDef(Name: *const c_char,
Inputs: *const ValueRef,
build_string(|s| LLVMRustWriteTwineToString(tr, s)).expect("got a non-UTF8 Twine from LLVM")
}
-pub unsafe fn debug_loc_to_string(c: ContextRef, tr: DebugLocRef) -> String {
- build_string(|s| LLVMRustWriteDebugLocToString(c, tr, s))
- .expect("got a non-UTF8 DebugLoc from LLVM")
-}
-
pub fn initialize_available_targets() {
macro_rules! init_target(
($cfg:meta, $($method:ident),*) => { {
[dependencies]
flate2 = "1.0"
-log = "0.3"
+log = "0.4"
proc_macro = { path = "../libproc_macro" }
rustc = { path = "../librustc" }
rustc_back = { path = "../librustc_back" }
use native_libs::relevant_lib;
use schema::CrateRoot;
-use rustc::hir::def_id::{CrateNum, DefIndex, CRATE_DEF_INDEX};
+use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX};
use rustc::hir::svh::Svh;
use rustc::middle::allocator::AllocatorKind;
use rustc::middle::cstore::DepKind;
Err(err) => self.sess.span_fatal(span, &err),
};
- let sym = self.sess.generate_derive_registrar_symbol(root.disambiguator,
- root.macro_derive_registrar.unwrap());
+ let sym = self.sess.generate_derive_registrar_symbol(root.disambiguator);
let registrar = unsafe {
let sym = match lib.symbol(&sym) {
Ok(f) => f,
pub fn find_plugin_registrar(&mut self,
span: Span,
name: &str)
- -> Option<(PathBuf, CrateDisambiguator, DefIndex)> {
+ -> Option<(PathBuf, CrateDisambiguator)> {
let name = Symbol::intern(name);
let ekrate = self.read_extension_crate(span, name, name);
}
let root = ekrate.metadata.get_root();
- match (ekrate.dylib.as_ref(), root.plugin_registrar_fn) {
- (Some(dylib), Some(reg)) => {
- Some((dylib.to_path_buf(), root.disambiguator, reg))
+ match ekrate.dylib.as_ref() {
+ Some(dylib) => {
+ Some((dylib.to_path_buf(), root.disambiguator))
}
- (None, Some(_)) => {
+ None => {
span_err!(self.sess, span, E0457,
"plugin `{}` only found in rlib format, but must be available \
in dylib format",
// empty dylib.
None
}
- _ => None,
}
}
self.inject_allocator_crate(krate);
self.inject_panic_runtime(krate);
- if log_enabled!(log::LogLevel::Info) {
+ if log_enabled!(log::Level::Info) {
dump_crates(&self.cstore);
}
}
inherent_impls => { Rc::new(cdata.get_inherent_implementations_for_type(def_id.index)) }
is_const_fn => { cdata.is_const_fn(def_id.index) }
is_foreign_item => { cdata.is_foreign_item(def_id.index) }
- is_auto_impl => { cdata.is_auto_impl(def_id.index) }
describe_def => { cdata.get_def(def_id.index) }
def_span => { cdata.get_span(def_id.index, &tcx.sess) }
lookup_stability => {
fn load_macro_untracked(&self, id: DefId, sess: &Session) -> LoadedMacro {
let data = self.get_crate_data(id.krate);
if let Some(ref proc_macros) = data.proc_macros {
- return LoadedMacro::ProcMacro(proc_macros[id.index.as_usize() - 1].1.clone());
+ return LoadedMacro::ProcMacro(proc_macros[id.index.to_proc_macro_index()].1.clone());
} else if data.name == "proc_macro" &&
self.get_crate_data(id.krate).item_name(id.index) == "quote" {
let ext = SyntaxExtension::ProcMacro(Box::new(::proc_macro::__internal::Quoter));
use rustc::middle::cstore::{LinkagePreference, ExternConstBody,
ExternBodyNestedBodies};
use rustc::hir::def::{self, Def, CtorKind};
-use rustc::hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE};
+use rustc::hir::def_id::{CrateNum, DefId, DefIndex,
+ CRATE_DEF_INDEX, LOCAL_CRATE};
use rustc::ich::Fingerprint;
use rustc::middle::lang_items;
use rustc::mir;
use std::u32;
use rustc_serialize::{Decodable, Decoder, SpecializedDecoder, opaque};
-use rustc_data_structures::indexed_vec::Idx;
use syntax::attr;
use syntax::ast::{self, Ident};
use syntax::codemap;
impl<'a, 'tcx> SpecializedDecoder<DefIndex> for DecodeContext<'a, 'tcx> {
#[inline]
fn specialized_decode(&mut self) -> Result<DefIndex, Self::Error> {
- Ok(DefIndex::from_u32(self.read_u32()?))
+ Ok(DefIndex::from_raw_u32(self.read_u32()?))
}
}
impl<'a, 'tcx> SpecializedDecoder<Span> for DecodeContext<'a, 'tcx> {
fn specialized_decode(&mut self) -> Result<Span, Self::Error> {
- let lo = BytePos::decode(self)?;
- let hi = BytePos::decode(self)?;
+ let tag = u8::decode(self)?;
- if lo == BytePos(0) && hi == BytePos(0) {
- // Don't try to rebase DUMMY_SP. Otherwise it will look like a valid
- // Span again.
+ if tag == TAG_INVALID_SPAN {
return Ok(DUMMY_SP)
}
- if hi < lo {
- // Consistently map invalid spans to DUMMY_SP.
- return Ok(DUMMY_SP)
- }
+ debug_assert_eq!(tag, TAG_VALID_SPAN);
+
+ let lo = BytePos::decode(self)?;
+ let len = BytePos::decode(self)?;
+ let hi = lo + len;
let sess = if let Some(sess) = self.sess {
sess
let last_filemap = &imported_filemaps[self.last_filemap_index];
if lo >= last_filemap.original_start_pos &&
- lo <= last_filemap.original_end_pos &&
- hi >= last_filemap.original_start_pos &&
- hi <= last_filemap.original_end_pos {
+ lo <= last_filemap.original_end_pos {
last_filemap
} else {
let mut a = 0;
debug_assert!(lo >= filemap.original_start_pos &&
lo <= filemap.original_end_pos);
- if hi < filemap.original_start_pos || hi > filemap.original_end_pos {
- // `hi` points to a different FileMap than `lo` which is invalid.
- // Again, map invalid Spans to DUMMY_SP.
- return Ok(DUMMY_SP)
- }
+ // Make sure we correctly filtered out invalid spans during encoding
+ debug_assert!(hi >= filemap.original_start_pos &&
+ hi <= filemap.original_end_pos);
let lo = (lo + filemap.translated_filemap.start_pos) - filemap.original_start_pos;
let hi = (hi + filemap.translated_filemap.start_pos) - filemap.original_start_pos;
}
}
+impl<'a, 'tcx> SpecializedDecoder<Fingerprint> for DecodeContext<'a, 'tcx> {
+ fn specialized_decode(&mut self) -> Result<Fingerprint, Self::Error> {
+ Fingerprint::decode_opaque(&mut self.opaque)
+ }
+}
+
impl<'a, 'tcx, T: Decodable> SpecializedDecoder<mir::ClearCrossCrate<T>>
for DecodeContext<'a, 'tcx> {
#[inline]
EntryKind::ForeignMod |
EntryKind::Impl(_) |
- EntryKind::AutoImpl(_) |
EntryKind::Field |
EntryKind::Generator(_) |
EntryKind::Closure(_) => return None,
if !self.is_proc_macro(index) {
self.entry(index).kind.to_def(self.local_def_id(index))
} else {
- let kind = self.proc_macros.as_ref().unwrap()[index.as_usize() - 1].1.kind();
+ let kind = self.proc_macros.as_ref().unwrap()[index.to_proc_macro_index()].1.kind();
Some(Def::Macro(self.local_def_id(index), kind))
}
}
let def = Def::Macro(
DefId {
krate: self.cnum,
- index: DefIndex::new(id + 1)
+ index: DefIndex::from_proc_macro_index(id),
},
ext.kind()
);
}
continue;
}
- EntryKind::Impl(_) |
- EntryKind::AutoImpl(_) => continue,
+ EntryKind::Impl(_) => continue,
_ => {}
}
let vis = self.get_visibility(child_index);
let is_import = false;
callback(def::Export { def, ident, vis, span, is_import });
- // For non-reexport structs and variants add their constructors to children.
- // Reexport lists automatically contain constructors when necessary.
+ // For non-re-export structs and variants add their constructors to children.
+ // Re-export lists automatically contain constructors when necessary.
match def {
Def::Struct(..) => {
if let Some(ctor_def_id) = self.get_struct_ctor_def_id(child_index) {
self.dllimport_foreign_items.contains(&id)
}
- pub fn is_auto_impl(&self, impl_id: DefIndex) -> bool {
- match self.entry(impl_id).kind {
- EntryKind::AutoImpl(_) => true,
- _ => false,
- }
- }
-
pub fn fn_sig(&self,
id: DefIndex,
tcx: TyCtxt<'a, 'tcx, 'tcx>)
use rustc::hir::def::CtorKind;
use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefIndex, DefId, LOCAL_CRATE};
use rustc::hir::map::definitions::DefPathTable;
+use rustc::ich::Fingerprint;
use rustc::middle::dependency_format::Linkage;
use rustc::middle::lang_items;
use rustc::mir;
use syntax::codemap::Spanned;
use syntax::attr;
use syntax::symbol::Symbol;
-use syntax_pos::{self, FileName};
+use syntax_pos::{self, FileName, FileMap, Span, DUMMY_SP};
use rustc::hir::{self, PatKind};
use rustc::hir::itemlikevisit::ItemLikeVisitor;
lazy_state: LazyState,
type_shorthands: FxHashMap<Ty<'tcx>, usize>,
predicate_shorthands: FxHashMap<ty::Predicate<'tcx>, usize>,
+
+ // This is used to speed up Span encoding.
+ filemap_cache: Rc<FileMap>,
}
macro_rules! encoder_methods {
impl<'a, 'tcx> SpecializedEncoder<DefIndex> for EncodeContext<'a, 'tcx> {
#[inline]
fn specialized_encode(&mut self, def_index: &DefIndex) -> Result<(), Self::Error> {
- self.emit_u32(def_index.as_u32())
+ self.emit_u32(def_index.as_raw_u32())
+ }
+}
+
+impl<'a, 'tcx> SpecializedEncoder<Span> for EncodeContext<'a, 'tcx> {
+ fn specialized_encode(&mut self, span: &Span) -> Result<(), Self::Error> {
+ if *span == DUMMY_SP {
+ return TAG_INVALID_SPAN.encode(self)
+ }
+
+ let span = span.data();
+
+ // The Span infrastructure should make sure that this invariant holds:
+ debug_assert!(span.lo <= span.hi);
+
+ if !self.filemap_cache.contains(span.lo) {
+ let codemap = self.tcx.sess.codemap();
+ let filemap_index = codemap.lookup_filemap_idx(span.lo);
+ self.filemap_cache = codemap.files()[filemap_index].clone();
+ }
+
+ if !self.filemap_cache.contains(span.hi) {
+ // Unfortunately, macro expansion still sometimes generates Spans
+ // that malformed in this way.
+ return TAG_INVALID_SPAN.encode(self)
+ }
+
+ TAG_VALID_SPAN.encode(self)?;
+ span.lo.encode(self)?;
+
+ // Encode length which is usually less than span.hi and profits more
+ // from the variable-length integer encoding that we use.
+ let len = span.hi - span.lo;
+ len.encode(self)
+
+ // Don't encode the expansion context.
}
}
}
}
+impl<'a, 'tcx> SpecializedEncoder<Fingerprint> for EncodeContext<'a, 'tcx> {
+ fn specialized_encode(&mut self, f: &Fingerprint) -> Result<(), Self::Error> {
+ f.encode_opaque(&mut self.opaque)
+ }
+}
+
impl<'a, 'tcx, T: Encodable> SpecializedEncoder<mir::ClearCrossCrate<T>>
for EncodeContext<'a, 'tcx> {
fn specialized_encode(&mut self,
debug!("IsolatedEncoder::encode_struct_ctor({:?})", def_id);
let tcx = self.tcx;
let adt_def = tcx.adt_def(adt_def_id);
- let variant = adt_def.struct_variant();
+ let variant = adt_def.non_enum_variant();
let data = VariantData {
ctor_kind: variant.ctor_kind,
fn encode_fn_arg_names_for_body(&mut self, body_id: hir::BodyId)
-> LazySeq<ast::Name> {
- let _ignore = self.tcx.dep_graph.in_ignore();
- let body = self.tcx.hir.body(body_id);
- self.lazy_seq(body.arguments.iter().map(|arg| {
- match arg.pat.node {
- PatKind::Binding(_, _, name, _) => name.node,
- _ => Symbol::intern("")
- }
- }))
+ self.tcx.dep_graph.with_ignore(|| {
+ let body = self.tcx.hir.body(body_id);
+ self.lazy_seq(body.arguments.iter().map(|arg| {
+ match arg.pat.node {
+ PatKind::Binding(_, _, name, _) => name.node,
+ _ => Symbol::intern("")
+ }
+ }))
+ })
}
fn encode_fn_arg_names(&mut self, names: &[Spanned<ast::Name>])
hir::ItemTy(..) => EntryKind::Type,
hir::ItemEnum(..) => EntryKind::Enum(get_repr_options(&tcx, def_id)),
hir::ItemStruct(ref struct_def, _) => {
- let variant = tcx.adt_def(def_id).struct_variant();
+ let variant = tcx.adt_def(def_id).non_enum_variant();
// Encode def_ids for each field and method
// for methods, write all the stuff get_trait_method
}), repr_options)
}
hir::ItemUnion(..) => {
- let variant = tcx.adt_def(def_id).struct_variant();
+ let variant = tcx.adt_def(def_id).non_enum_variant();
let repr_options = get_repr_options(&tcx, def_id);
EntryKind::Union(self.lazy(&VariantData {
ctor_sig: None,
}), repr_options)
}
- hir::ItemAutoImpl(..) => {
- let data = ImplData {
- polarity: hir::ImplPolarity::Positive,
- defaultness: hir::Defaultness::Final,
- parent_impl: None,
- coerce_unsized_info: None,
- trait_ref: tcx.impl_trait_ref(def_id).map(|trait_ref| self.lazy(&trait_ref)),
- };
-
- EntryKind::AutoImpl(self.lazy(&data))
- }
hir::ItemImpl(_, polarity, defaultness, ..) => {
let trait_ref = tcx.impl_trait_ref(def_id);
let parent = if let Some(trait_ref) = trait_ref {
hir::ItemStruct(..) |
hir::ItemUnion(..) => {
let def = self.tcx.adt_def(def_id);
- self.lazy_seq(def.struct_variant().fields.iter().map(|f| {
+ self.lazy_seq(def.non_enum_variant().fields.iter().map(|f| {
assert!(f.did.is_local());
f.did.index
}))
hir::ItemGlobalAsm(..) |
hir::ItemExternCrate(..) |
hir::ItemUse(..) |
- hir::ItemAutoImpl(..) |
hir::ItemTy(..) |
hir::ItemTraitAlias(..) => {
// no sub-item recording needed in these cases
lazy_state: LazyState::NoNode,
type_shorthands: Default::default(),
predicate_shorthands: Default::default(),
+ filemap_cache: tcx.sess.codemap().files()[0].clone(),
};
// Encode the rustc version string in a predictable location.
#[inline(never)]
pub fn lookup(&self, bytes: &[u8], def_index: DefIndex) -> Option<Lazy<Entry<'tcx>>> {
let words = &bytes_to_words(&bytes[self.position..])[..self.len];
- let index = def_index.as_usize();
debug!("Index::lookup: index={:?} words.len={:?}",
- index,
+ def_index,
words.len());
let positions = match def_index.address_space() {
where DATA: DepGraphRead
{
assert!(id.is_local());
- let tcx: TyCtxt<'b, 'tcx, 'tcx> = self.ecx.tcx;
// We don't track this since we are explicitly computing the incr. comp.
// hashes anyway. In theory we could do some tracking here and use it to
// avoid rehashing things (and instead cache the hashes) but it's
// unclear whether that would be a win since hashing is cheap enough.
- let _task = tcx.dep_graph.in_ignore();
+ self.ecx.tcx.dep_graph.with_ignore(move || {
+ let mut entry_builder = IsolatedEncoder::new(self.ecx);
+ let entry = op(&mut entry_builder, data);
+ let entry = entry_builder.lazy(&entry);
- let mut entry_builder = IsolatedEncoder::new(self.ecx);
- let entry = op(&mut entry_builder, data);
- let entry = entry_builder.lazy(&entry);
-
- self.items.record(id, entry);
+ self.items.record(id, entry);
+ })
}
pub fn into_items(self) -> Index {
#![feature(box_patterns)]
#![feature(conservative_impl_trait)]
+#![feature(fs_read_write)]
#![feature(i128_type)]
#![feature(libc)]
#![feature(proc_macro_internals)]
pub mod dynamic_lib;
pub mod locator;
+#[cfg(not(stage0))] // remove after the next snapshot
__build_diagnostic_array! { librustc_metadata, DIAGNOSTICS }
use std::cmp;
use std::fmt;
-use std::fs::{self, File};
+use std::fs;
use std::io::{self, Read};
use std::path::{Path, PathBuf};
use std::time::Instant;
}
}
CrateFlavor::Rmeta => {
- let mut file = File::open(filename).map_err(|_|
- format!("could not open file: '{}'", filename.display()))?;
- let mut buf = vec![];
- file.read_to_end(&mut buf).map_err(|_|
+ let buf = fs::read(filename).map_err(|_|
format!("failed to read rmeta metadata: '{}'", filename.display()))?;
OwningRef::new(buf).map_owner_box().erase_owner()
}
let cfg = items.iter().find(|k| {
k.check_name("cfg")
}).and_then(|a| a.meta_item_list());
- let cfg = cfg.map(|list| {
- list[0].meta_item().unwrap().clone()
- });
+ let cfg = if let Some(list) = cfg {
+ if list.is_empty() {
+ self.tcx.sess.span_err(m.span(), "`cfg()` must have an argument");
+ return;
+ } else if let cfg @ Some(..) = list[0].meta_item() {
+ cfg.cloned()
+ } else {
+ self.tcx.sess.span_err(list[0].span(), "invalid argument for `cfg(..)`");
+ return;
+ }
+ } else {
+ None
+ };
let foreign_items = fm.items.iter()
.map(|it| self.tcx.hir.local_def_id(it.id))
.collect();
Generator(Lazy<GeneratorData<'tcx>>),
Trait(Lazy<TraitData<'tcx>>),
Impl(Lazy<ImplData<'tcx>>),
- AutoImpl(Lazy<ImplData<'tcx>>),
Method(Lazy<MethodData<'tcx>>),
AssociatedType(AssociatedContainer),
AssociatedConst(AssociatedContainer, u8),
EntryKind::Trait(ref trait_data) => {
trait_data.hash_stable(hcx, hasher);
}
- EntryKind::AutoImpl(ref impl_data) |
EntryKind::Impl(ref impl_data) => {
impl_data.hash_stable(hcx, hasher);
}
pub layout: mir::GeneratorLayout<'tcx>,
}
impl_stable_hash_for!(struct GeneratorData<'tcx> { layout });
+
+// Tags used for encoding Spans:
+pub const TAG_VALID_SPAN: u8 = 0;
+pub const TAG_INVALID_SPAN: u8 = 1;
[dependencies]
bitflags = "1.0"
graphviz = { path = "../libgraphviz" }
-log = "0.3"
+log = "0.4"
log_settings = "0.1.1"
rustc = { path = "../librustc" }
rustc_back = { path = "../librustc_back" }
use syntax_pos::Span;
use rustc::middle::region::ScopeTree;
-use rustc::mir::{BorrowKind, Field, Local, Location, Operand};
+use rustc::mir::{BorrowKind, Field, Local, LocalKind, Location, Operand};
use rustc::mir::{Place, ProjectionElem, Rvalue, Statement, StatementKind};
use rustc::ty::{self, RegionKind};
use rustc_data_structures::indexed_vec::Idx;
(place, span): (&Place<'tcx>, Span),
assigned_span: Span,
) {
+ let is_arg = if let Place::Local(local) = place {
+ if let LocalKind::Arg = self.mir.local_kind(*local) {
+ true
+ } else {
+ false
+ }
+ } else {
+ false
+ };
+
let mut err = self.tcx.cannot_reassign_immutable(
span,
&self.describe_place(place).unwrap_or("_".to_owned()),
+ is_arg,
Origin::Mir,
);
- err.span_label(span, "cannot assign twice to immutable variable");
+ let msg = if is_arg {
+ "cannot assign to immutable argument"
+ } else {
+ "cannot assign twice to immutable variable"
+ };
if span != assigned_span {
- let value_msg = match self.describe_place(place) {
- Some(name) => format!("`{}`", name),
- None => "value".to_owned(),
- };
- err.span_label(assigned_span, format!("first assignment to {}", value_msg));
+ if is_arg {
+ err.span_label(assigned_span, "argument not declared as `mut`");
+ } else {
+ let value_msg = match self.describe_place(place) {
+ Some(name) => format!("`{}`", name),
+ None => "value".to_owned(),
+ };
+ err.span_label(assigned_span, format!("first assignment to {}", value_msg));
+ }
}
+ err.span_label(span, msg);
err.emit();
}
}
ty::TyAdt(def, _) => if def.is_enum() {
format!("{}", field.index())
} else {
- format!("{}", def.struct_variant().fields[field.index()].name)
+ format!("{}", def.non_enum_variant().fields[field.index()].name)
},
ty::TyTuple(_, _) => format!("{}", field.index()),
ty::TyRef(_, tnm) | ty::TyRawPtr(tnm) => {
// associated types here and possibly recursively process.
for ty in dtorck_types {
let ty = self.cx.normalize(&ty, location);
+ let ty = self.cx.infcx.resolve_type_and_region_vars_if_possible(&ty);
match ty.sty {
ty::TyParam(..) | ty::TyProjection(..) | ty::TyAnon(..) => {
let cause = Cause::DropVar(dropped_local, location);
ast::IntTy::I32 => ConstInt::I32(-1),
ast::IntTy::I64 => ConstInt::I64(-1),
ast::IntTy::I128 => ConstInt::I128(-1),
- ast::IntTy::Is => {
+ ast::IntTy::Isize => {
let int_ty = self.hir.tcx().sess.target.isize_ty;
let val = ConstIsize::new(-1, int_ty).unwrap();
ConstInt::Isize(val)
ast::IntTy::I32 => ConstInt::I32(i32::min_value()),
ast::IntTy::I64 => ConstInt::I64(i64::min_value()),
ast::IntTy::I128 => ConstInt::I128(i128::min_value()),
- ast::IntTy::Is => {
+ ast::IntTy::Isize => {
let int_ty = self.hir.tcx().sess.target.isize_ty;
let min = match int_ty {
ast::IntTy::I16 => std::i16::MIN as i64,
}
}
+ /// Convert a byte array or byte slice to a byte slice.
+ fn to_slice_operand(&mut self,
+ block: BasicBlock,
+ source_info: SourceInfo,
+ operand: Operand<'tcx>)
+ -> Operand<'tcx>
+ {
+ let tcx = self.hir.tcx();
+ let ty = operand.ty(&self.local_decls, tcx);
+ debug!("to_slice_operand({:?}, {:?}: {:?})", block, operand, ty);
+ match ty.sty {
+ ty::TyRef(region, mt) => match mt.ty.sty {
+ ty::TyArray(ety, _) => {
+ let ty = tcx.mk_imm_ref(region, tcx.mk_slice(ety));
+ let temp = self.temp(ty, source_info.span);
+ self.cfg.push_assign(block, source_info, &temp,
+ Rvalue::Cast(CastKind::Unsize, operand, ty));
+ Operand::Move(temp)
+ }
+ ty::TySlice(_) => operand,
+ _ => {
+ span_bug!(source_info.span,
+ "bad operand {:?}: {:?} to `to_slice_operand`", operand, ty)
+ }
+ }
+ _ => {
+ span_bug!(source_info.span,
+ "bad operand {:?}: {:?} to `to_slice_operand`", operand, ty)
+ }
+ }
+
+ }
+
/// Generates the code to perform a test.
pub fn perform_test(&mut self,
block: BasicBlock,
place: &Place<'tcx>,
test: &Test<'tcx>)
-> Vec<BasicBlock> {
+ debug!("perform_test({:?}, {:?}: {:?}, {:?})",
+ block,
+ place,
+ place.ty(&self.local_decls, self.hir.tcx()),
+ test);
let source_info = self.source_info(test.span);
match test.kind {
TestKind::Switch { adt_def, ref variants } => {
ret
}
- TestKind::Eq { value, mut ty } => {
+ TestKind::Eq { value, ty } => {
+ let tcx = self.hir.tcx();
let mut val = Operand::Copy(place.clone());
// If we're using b"..." as a pattern, we need to insert an
// unsizing coercion, as the byte string has the type &[u8; N].
- let expect = if let ConstVal::ByteStr(bytes) = value.val {
- let tcx = self.hir.tcx();
-
- // Unsize the place to &[u8], too, if necessary.
- if let ty::TyRef(region, mt) = ty.sty {
- if let ty::TyArray(_, _) = mt.ty.sty {
- ty = tcx.mk_imm_ref(region, tcx.mk_slice(tcx.types.u8));
- let val_slice = self.temp(ty, test.span);
- self.cfg.push_assign(block, source_info, &val_slice,
- Rvalue::Cast(CastKind::Unsize, val, ty));
- val = Operand::Move(val_slice);
- }
- }
-
- assert!(ty.is_slice());
-
+ //
+ // We want to do this even when the scrutinee is a reference to an
+ // array, so we can call `<[u8]>::eq` rather than having to find an
+ // `<[u8; N]>::eq`.
+ let (expect, val) = if let ConstVal::ByteStr(bytes) = value.val {
let array_ty = tcx.mk_array(tcx.types.u8, bytes.data.len() as u64);
let array_ref = tcx.mk_imm_ref(tcx.types.re_static, array_ty);
let array = self.literal_operand(test.span, array_ref, Literal::Value {
value
});
- let slice = self.temp(ty, test.span);
- self.cfg.push_assign(block, source_info, &slice,
- Rvalue::Cast(CastKind::Unsize, array, ty));
- Operand::Move(slice)
+ let val = self.to_slice_operand(block, source_info, val);
+ let slice = self.to_slice_operand(block, source_info, array);
+ (slice, val)
} else {
- self.literal_operand(test.span, ty, Literal::Value {
+ (self.literal_operand(test.span, ty, Literal::Value {
value
- })
+ }), val)
};
// Use PartialEq::eq for &str and &[u8] slices, instead of BinOp::Eq.
let fail = self.cfg.start_new_block();
+ let ty = expect.ty(&self.local_decls, tcx);
if let ty::TyRef(_, mt) = ty.sty {
assert!(ty.is_slice());
let eq_def_id = self.hir.tcx().lang_items().eq_trait().unwrap();
ast::UintTy::U32 => ConstInt::U32(0),
ast::UintTy::U64 => ConstInt::U64(0),
ast::UintTy::U128 => ConstInt::U128(0),
- ast::UintTy::Us => {
+ ast::UintTy::Usize => {
let uint_ty = self.hir.tcx().sess.target.usize_ty;
let val = ConstUsize::new(0, uint_ty).unwrap();
ConstInt::Usize(val)
ast::IntTy::I32 => ConstInt::I32(0),
ast::IntTy::I64 => ConstInt::I64(0),
ast::IntTy::I128 => ConstInt::I128(0),
- ast::IntTy::Is => {
+ ast::IntTy::Isize => {
let int_ty = self.hir.tcx().sess.target.isize_ty;
let val = ConstIsize::new(0, int_ty).unwrap();
ConstInt::Isize(val)
use dot;
use dot::IntoCow;
-use std::fs::File;
+use std::fs;
use std::io;
use std::io::prelude::*;
use std::marker::PhantomData;
dot::render(&g, &mut v)?;
debug!("print_borrowck_graph_to path: {} node_id: {}",
path.display(), mbcx.node_id);
- File::create(path).and_then(|mut f| f.write_all(&v))
+ fs::write(path, v)
}
pub type Node = BasicBlock;
}
impl ReserveOrActivateIndex {
- fn reserved(i: BorrowIndex) -> Self { ReserveOrActivateIndex::new((i.index() * 2)) }
+ fn reserved(i: BorrowIndex) -> Self { ReserveOrActivateIndex::new(i.index() * 2) }
fn active(i: BorrowIndex) -> Self { ReserveOrActivateIndex::new((i.index() * 2) + 1) }
pub(crate) fn is_reservation(self) -> bool { self.index() % 2 == 0 }
IntTy::I32 => v as i32 as u128,
IntTy::I64 => v as i64 as u128,
IntTy::I128 => v as u128,
- IntTy::Is => {
+ IntTy::Isize => {
let ty = self.tcx.sess.target.isize_ty;
self.int_to_int(v, ty)
}
UintTy::U32 => v as u32 as u128,
UintTy::U64 => v as u64 as u128,
UintTy::U128 => v,
- UintTy::Us => {
+ UintTy::Usize => {
let ty = self.tcx.sess.target.usize_ty;
self.int_to_uint(v, ty)
}
match ty.sty {
// Casting to a reference or fn pointer is not permitted by rustc, no need to support it here.
TyRawPtr(_) |
- TyInt(IntTy::Is) |
- TyUint(UintTy::Us) => Ok(PrimVal::Ptr(ptr)),
+ TyInt(IntTy::Isize) |
+ TyUint(UintTy::Usize) => Ok(PrimVal::Ptr(ptr)),
TyInt(_) | TyUint(_) => err!(ReadPointerAsBytes),
_ => err!(Unimplemented(format!("ptr to {:?} cast", ty))),
}
use syntax::ast::Mutability;
use syntax::codemap::Span;
-use rustc::mir::interpret::{EvalResult, EvalError, EvalErrorKind, GlobalId, Value, Pointer, PrimVal};
+use rustc::mir::interpret::{EvalResult, EvalError, EvalErrorKind, GlobalId, Value, MemoryPointer, Pointer, PrimVal};
use super::{Place, EvalContext, StackPopCleanup, ValTy};
use rustc_const_math::ConstInt;
layout.align,
None,
)?;
- tcx.interpret_interner.borrow_mut().cache(cid, ptr.into());
+ tcx.interpret_interner.borrow_mut().cache(cid, ptr.alloc_id);
let cleanup = StackPopCleanup::MarkStatic(Mutability::Immutable);
let name = ty::tls::with(|tcx| tcx.item_path_str(instance.def_id()));
trace!("const_eval: pushing stack frame for global: {}", name);
while ecx.step()? {}
}
- let value = tcx.interpret_interner.borrow().get_cached(cid).expect("global not cached");
- Ok((value, instance_ty))
+ let alloc = tcx.interpret_interner.borrow().get_cached(cid).expect("global not cached");
+ Ok((MemoryPointer::new(alloc, 0).into(), instance_ty))
}
pub fn eval_body_as_integer<'a, 'tcx>(
TyInt(IntTy::I32) => ConstInt::I32(prim as i128 as i32),
TyInt(IntTy::I64) => ConstInt::I64(prim as i128 as i64),
TyInt(IntTy::I128) => ConstInt::I128(prim as i128),
- TyInt(IntTy::Is) => ConstInt::Isize(
+ TyInt(IntTy::Isize) => ConstInt::Isize(
ConstIsize::new(prim as i128 as i64, tcx.sess.target.isize_ty)
.expect("miri should already have errored"),
),
TyUint(UintTy::U32) => ConstInt::U32(prim as u32),
TyUint(UintTy::U64) => ConstInt::U64(prim as u64),
TyUint(UintTy::U128) => ConstInt::U128(prim),
- TyUint(UintTy::Us) => ConstInt::Usize(
+ TyUint(UintTy::Usize) => ConstInt::Usize(
ConstUsize::new(prim as u64, tcx.sess.target.usize_ty)
.expect("miri should already have errored"),
),
miri_place = ecx.place_downcast(miri_place, variant).unwrap();
&def.variants[variant]
} else {
- def.struct_variant()
+ def.non_enum_variant()
};
let vec = match ctfe {
ConstVal::Aggregate(Struct(v)) => v,
}
}
- if log_enabled!(::log::LogLevel::Trace) {
+ if log_enabled!(::log::Level::Trace) {
self.dump_local(dest);
}
}
pub fn read_global_as_value(&self, gid: GlobalId, layout: TyLayout) -> Value {
- Value::ByRef(self.tcx.interpret_interner.borrow().get_cached(gid).expect("global not cached"),
- layout.align)
+ let alloc = self.tcx.interpret_interner.borrow().get_cached(gid).expect("global not cached");
+ Value::ByRef(MemoryPointer::new(alloc, 0).into(), layout.align)
}
pub fn force_allocation(&mut self, place: Place) -> EvalResult<'tcx, Place> {
I32 => 4,
I64 => 8,
I128 => 16,
- Is => self.memory.pointer_size(),
+ Isize => self.memory.pointer_size(),
};
PrimValKind::from_int_size(size)
}
U32 => 4,
U64 => 8,
U128 => 16,
- Us => self.memory.pointer_size(),
+ Usize => self.memory.pointer_size(),
};
PrimValKind::from_uint_size(size)
}
I32 => 4,
I64 => 8,
I128 => 16,
- Is => self.memory.pointer_size(),
+ Isize => self.memory.pointer_size(),
};
self.memory.read_primval(ptr, ptr_align, size, true)?
}
U32 => 4,
U64 => 8,
U128 => 16,
- Us => self.memory.pointer_size(),
+ Usize => self.memory.pointer_size(),
};
self.memory.read_primval(ptr, ptr_align, size, false)?
}
//! This separation exists to ensure that no fancy miri features like
//! interpreting common C functions leak into CTFE.
-use rustc::mir::interpret::{EvalResult, PrimVal, MemoryPointer, AccessKind};
+use rustc::mir::interpret::{AllocId, EvalResult, PrimVal, MemoryPointer, AccessKind};
use super::{EvalContext, Place, ValTy, Memory};
use rustc::mir;
fn add_lock<'a>(
_mem: &mut Memory<'a, 'tcx, Self>,
- _id: u64,
+ _id: AllocId,
) {}
fn free_lock<'a>(
_mem: &mut Memory<'a, 'tcx, Self>,
- _id: u64,
+ _id: AllocId,
_len: u64,
) -> EvalResult<'tcx> {
Ok(())
pub data: M::MemoryData,
/// Helps guarantee that stack allocations aren't deallocated via `rust_deallocate`
- alloc_kind: HashMap<u64, MemoryKind<M::MemoryKinds>>,
+ alloc_kind: HashMap<AllocId, MemoryKind<M::MemoryKinds>>,
/// Actual memory allocations (arbitrary bytes, may contain pointers into other allocations).
- alloc_map: HashMap<u64, Allocation>,
+ alloc_map: HashMap<AllocId, Allocation>,
/// Actual memory allocations (arbitrary bytes, may contain pointers into other allocations).
///
/// Stores statics while they are being processed, before they are interned and thus frozen
- uninitialized_statics: HashMap<u64, Allocation>,
+ uninitialized_statics: HashMap<AllocId, Allocation>,
/// Number of virtual bytes allocated.
memory_usage: u64,
pub fn allocations<'x>(
&'x self,
) -> impl Iterator<Item = (AllocId, &'x Allocation)> {
- self.alloc_map.iter().map(|(&id, alloc)| (AllocId(id), alloc))
+ self.alloc_map.iter().map(|(&id, alloc)| (id, alloc))
}
pub fn create_fn_alloc(&mut self, instance: Instance<'tcx>) -> MemoryPointer {
let id = self.tcx.interpret_interner.borrow_mut().create_fn_alloc(instance);
- MemoryPointer::new(AllocId(id), 0)
+ MemoryPointer::new(id, 0)
}
pub fn allocate_cached(&mut self, bytes: &[u8]) -> MemoryPointer {
let id = self.tcx.allocate_cached(bytes);
- MemoryPointer::new(AllocId(id), 0)
+ MemoryPointer::new(id, 0)
}
/// kind is `None` for statics
},
Some(MemoryKind::MutableStatic) => bug!("don't allocate mutable statics directly")
}
- Ok(MemoryPointer::new(AllocId(id), 0))
+ Ok(MemoryPointer::new(id, 0))
}
pub fn reallocate(
if ptr.offset != 0 {
return err!(ReallocateNonBasePtr);
}
- if self.alloc_map.contains_key(&ptr.alloc_id.0) {
- let alloc_kind = self.alloc_kind[&ptr.alloc_id.0];
+ if self.alloc_map.contains_key(&ptr.alloc_id) {
+ let alloc_kind = self.alloc_kind[&ptr.alloc_id];
if alloc_kind != kind {
return err!(ReallocatedWrongMemoryKind(
format!("{:?}", alloc_kind),
}
pub fn deallocate_local(&mut self, ptr: MemoryPointer) -> EvalResult<'tcx> {
- match self.alloc_kind.get(&ptr.alloc_id.0).cloned() {
+ match self.alloc_kind.get(&ptr.alloc_id).cloned() {
// for a constant like `const FOO: &i32 = &1;` the local containing
// the `1` is referred to by the global. We transitively marked everything
// the global refers to as static itself, so we don't free it here
return err!(DeallocateNonBasePtr);
}
- let alloc = match self.alloc_map.remove(&ptr.alloc_id.0) {
+ let alloc = match self.alloc_map.remove(&ptr.alloc_id) {
Some(alloc) => alloc,
- None => if self.uninitialized_statics.contains_key(&ptr.alloc_id.0) {
+ None => if self.uninitialized_statics.contains_key(&ptr.alloc_id) {
return err!(DeallocatedWrongMemoryKind(
"uninitializedstatic".to_string(),
format!("{:?}", kind),
))
- } else if self.tcx.interpret_interner.borrow().get_fn(ptr.alloc_id.0).is_some() {
+ } else if self.tcx.interpret_interner.borrow().get_fn(ptr.alloc_id).is_some() {
return err!(DeallocatedWrongMemoryKind(
"function".to_string(),
format!("{:?}", kind),
))
- } else if self.tcx.interpret_interner.borrow().get_alloc(ptr.alloc_id.0).is_some() {
+ } else if self.tcx.interpret_interner.borrow().get_alloc(ptr.alloc_id).is_some() {
return err!(DeallocatedWrongMemoryKind(
"static".to_string(),
format!("{:?}", kind),
},
};
- let alloc_kind = self.alloc_kind.remove(&ptr.alloc_id.0).expect("alloc_map out of sync with alloc_kind");
+ let alloc_kind = self.alloc_kind.remove(&ptr.alloc_id).expect("alloc_map out of sync with alloc_kind");
// It is okay for us to still holds locks on deallocation -- for example, we could store data we own
// in a local, and the local could be deallocated (from StorageDead) before the function returns.
// However, we should check *something*. For now, we make sure that there is no conflicting write
// lock by another frame. We *have* to permit deallocation if we hold a read lock.
// TODO: Figure out the exact rules here.
- M::free_lock(self, ptr.alloc_id.0, alloc.bytes.len() as u64)?;
+ M::free_lock(self, ptr.alloc_id, alloc.bytes.len() as u64)?;
if alloc_kind != kind {
return err!(DeallocatedWrongMemoryKind(
impl<'a, 'tcx, M: Machine<'tcx>> Memory<'a, 'tcx, M> {
pub fn get(&self, id: AllocId) -> EvalResult<'tcx, &Allocation> {
// normal alloc?
- match self.alloc_map.get(&id.0) {
+ match self.alloc_map.get(&id) {
Some(alloc) => Ok(alloc),
// uninitialized static alloc?
- None => match self.uninitialized_statics.get(&id.0) {
+ None => match self.uninitialized_statics.get(&id) {
Some(alloc) => Ok(alloc),
None => {
let int = self.tcx.interpret_interner.borrow();
// static alloc?
- int.get_alloc(id.0)
+ int.get_alloc(id)
// no alloc? produce an error
- .ok_or_else(|| if int.get_fn(id.0).is_some() {
+ .ok_or_else(|| if int.get_fn(id).is_some() {
EvalErrorKind::DerefFunctionPointer.into()
} else {
EvalErrorKind::DanglingPointerDeref.into()
id: AllocId,
) -> EvalResult<'tcx, &mut Allocation> {
// normal alloc?
- match self.alloc_map.get_mut(&id.0) {
+ match self.alloc_map.get_mut(&id) {
Some(alloc) => Ok(alloc),
// uninitialized static alloc?
- None => match self.uninitialized_statics.get_mut(&id.0) {
+ None => match self.uninitialized_statics.get_mut(&id) {
Some(alloc) => Ok(alloc),
None => {
let int = self.tcx.interpret_interner.borrow();
// no alloc or immutable alloc? produce an error
- if int.get_alloc(id.0).is_some() {
+ if int.get_alloc(id).is_some() {
err!(ModifiedConstantMemory)
- } else if int.get_fn(id.0).is_some() {
+ } else if int.get_fn(id).is_some() {
err!(DerefFunctionPointer)
} else {
err!(DanglingPointerDeref)
self.tcx
.interpret_interner
.borrow()
- .get_fn(ptr.alloc_id.0)
+ .get_fn(ptr.alloc_id)
.ok_or(EvalErrorKind::ExecuteMemory.into())
}
let (alloc, immutable) =
// normal alloc?
- match self.alloc_map.get(&id.0) {
- Some(a) => (a, match self.alloc_kind[&id.0] {
+ match self.alloc_map.get(&id) {
+ Some(a) => (a, match self.alloc_kind[&id] {
MemoryKind::Stack => " (stack)".to_owned(),
MemoryKind::Machine(m) => format!(" ({:?})", m),
MemoryKind::MutableStatic => " (static mut)".to_owned(),
}),
// uninitialized static alloc?
- None => match self.uninitialized_statics.get(&id.0) {
+ None => match self.uninitialized_statics.get(&id) {
Some(a) => (a, " (static in the process of initialization)".to_owned()),
None => {
let int = self.tcx.interpret_interner.borrow();
// static alloc?
- match int.get_alloc(id.0) {
+ match int.get_alloc(id) {
Some(a) => (a, "(immutable)".to_owned()),
- None => if let Some(func) = int.get_fn(id.0) {
+ None => if let Some(func) = int.get_fn(id) {
trace!("{} {}", msg, func);
continue;
} else {
let leaks: Vec<_> = self.alloc_map
.keys()
.filter_map(|key| if kinds[key] != MemoryKind::MutableStatic {
- Some(AllocId(*key))
+ Some(*key)
} else {
None
})
alloc: AllocId,
mutability: Mutability,
) -> EvalResult<'tcx> {
- match self.alloc_kind.get(&alloc.0) {
+ match self.alloc_kind.get(&alloc) {
// do not go into immutable statics
None |
// or mutable statics
mutability
);
if mutability == Mutability::Immutable {
- let alloc = self.alloc_map.remove(&alloc_id.0);
- let kind = self.alloc_kind.remove(&alloc_id.0);
+ let alloc = self.alloc_map.remove(&alloc_id);
+ let kind = self.alloc_kind.remove(&alloc_id);
assert_ne!(kind, Some(MemoryKind::MutableStatic));
- let uninit = self.uninitialized_statics.remove(&alloc_id.0);
+ let uninit = self.uninitialized_statics.remove(&alloc_id);
if let Some(alloc) = alloc.or(uninit) {
let alloc = self.tcx.intern_const_alloc(alloc);
- self.tcx.interpret_interner.borrow_mut().intern_at_reserved(alloc_id.0, alloc);
+ self.tcx.interpret_interner.borrow_mut().intern_at_reserved(alloc_id, alloc);
// recurse into inner allocations
for &alloc in alloc.relocations.values() {
self.mark_inner_allocation_initialized(alloc, mutability)?;
return Ok(());
}
// We are marking the static as initialized, so move it out of the uninit map
- if let Some(uninit) = self.uninitialized_statics.remove(&alloc_id.0) {
- self.alloc_map.insert(alloc_id.0, uninit);
+ if let Some(uninit) = self.uninitialized_statics.remove(&alloc_id) {
+ self.alloc_map.insert(alloc_id, uninit);
}
// do not use `self.get_mut(alloc_id)` here, because we might have already marked a
// sub-element or have circular pointers (e.g. `Rc`-cycles)
- let relocations = match self.alloc_map.get_mut(&alloc_id.0) {
+ let relocations = match self.alloc_map.get_mut(&alloc_id) {
Some(&mut Allocation {
ref mut relocations,
..
}) => {
- match self.alloc_kind.get(&alloc_id.0) {
+ match self.alloc_kind.get(&alloc_id) {
// const eval results can refer to "locals".
// E.g. `const Foo: &u32 = &1;` refers to the temp local that stores the `1`
None |
},
}
// overwrite or insert
- self.alloc_kind.insert(alloc_id.0, MemoryKind::MutableStatic);
+ self.alloc_kind.insert(alloc_id, MemoryKind::MutableStatic);
// take out the relocations vector to free the borrow on self, so we can call
// mark recursively
mem::replace(relocations, Default::default())
}
// put back the relocations
self.alloc_map
- .get_mut(&alloc_id.0)
+ .get_mut(&alloc_id)
.expect("checked above")
.relocations = relocations;
Ok(())
promoted: None,
};
let layout = self.layout_of(self.place_ty(mir_place))?;
+ let alloc = self.tcx.interpret_interner.borrow().get_cached(gid).expect("uncached global");
Place::Ptr {
- ptr: self.tcx.interpret_interner.borrow().get_cached(gid).expect("uncached global"),
+ ptr: MemoryPointer::new(alloc, 0).into(),
align: layout.align,
extra: PlaceExtra::None,
}
}
};
- if log_enabled!(::log::LogLevel::Trace) {
+ if log_enabled!(::log::Level::Trace) {
self.dump_local(place);
}
layout.align,
None,
)?;
- self.tcx.interpret_interner.borrow_mut().cache(cid, ptr.into());
+ self.tcx.interpret_interner.borrow_mut().cache(cid, ptr.alloc_id);
let internally_mutable = !layout.ty.is_freeze(self.tcx, self.param_env, span);
let mutability = if mutability == Mutability::Mutable || internally_mutable {
Mutability::Mutable
layout.align,
None,
)?;
- this.ecx.tcx.interpret_interner.borrow_mut().cache(cid, ptr.into());
+ this.ecx.tcx.interpret_interner.borrow_mut().cache(cid, ptr.alloc_id);
trace!("pushing stack frame for {:?}", index);
this.ecx.push_stack_frame(
this.instance,
#![feature(core_intrinsics)]
#![feature(decl_macro)]
#![feature(dyn_trait)]
+#![feature(fs_read_write)]
#![feature(i128_type)]
#![feature(inclusive_range_syntax)]
#![feature(inclusive_range)]
providers.const_eval = interpret::const_eval_provider;
}
+#[cfg(not(stage0))] // remove after the next snapshot
__build_diagnostic_array! { librustc_mir, DIAGNOSTICS }
CustomCoerceUnsized::Struct(i) => i
};
- let source_fields = &source_adt_def.struct_variant().fields;
- let target_fields = &target_adt_def.struct_variant().fields;
+ let source_fields = &source_adt_def.non_enum_variant().fields;
+ let target_fields = &target_adt_def.non_enum_variant().fields;
assert!(coerce_index < source_fields.len() &&
source_fields.len() == target_fields.len());
hir::ItemUse(..) |
hir::ItemForeignMod(..) |
hir::ItemTy(..) |
- hir::ItemAutoImpl(..) |
hir::ItemTrait(..) |
hir::ItemTraitAlias(..) |
hir::ItemMod(..) => {
use rustc::hir;
use rustc::hir::def_id::DefId;
use rustc::session::config::OptLevel;
-use rustc::traits;
use rustc::ty::{self, Ty, TyCtxt};
-use rustc::ty::subst::{Subst, Substs};
+use rustc::ty::subst::Substs;
use syntax::ast;
use syntax::attr::{self, InlineAttr};
use std::fmt::{self, Write};
MonoItem::GlobalAsm(..) => return true
};
- let predicates = tcx.predicates_of(def_id).predicates.subst(tcx, substs);
- traits::normalize_and_test_predicates(tcx, predicates)
+ tcx.substitute_normalize_and_test_predicates((def_id, &substs))
}
fn to_string(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> String {
ty::TyChar => output.push_str("char"),
ty::TyStr => output.push_str("str"),
ty::TyNever => output.push_str("!"),
- ty::TyInt(ast::IntTy::Is) => output.push_str("isize"),
+ ty::TyInt(ast::IntTy::Isize) => output.push_str("isize"),
ty::TyInt(ast::IntTy::I8) => output.push_str("i8"),
ty::TyInt(ast::IntTy::I16) => output.push_str("i16"),
ty::TyInt(ast::IntTy::I32) => output.push_str("i32"),
ty::TyInt(ast::IntTy::I64) => output.push_str("i64"),
ty::TyInt(ast::IntTy::I128) => output.push_str("i128"),
- ty::TyUint(ast::UintTy::Us) => output.push_str("usize"),
+ ty::TyUint(ast::UintTy::Usize) => output.push_str("usize"),
ty::TyUint(ast::UintTy::U8) => output.push_str("u8"),
ty::TyUint(ast::UintTy::U16) => output.push_str("u16"),
ty::TyUint(ast::UintTy::U32) => output.push_str("u32"),
}
// Anything we can't find a proper codegen unit for goes into this.
-const FALLBACK_CODEGEN_UNIT: &'static str = "__rustc_fallback_codegen_unit";
+fn fallback_cgu_name(tcx: TyCtxt) -> InternedString {
+ const FALLBACK_CODEGEN_UNIT: &'static str = "__rustc_fallback_codegen_unit";
+
+ if tcx.sess.opts.debugging_opts.human_readable_cgu_names {
+ Symbol::intern(FALLBACK_CODEGEN_UNIT).as_str()
+ } else {
+ Symbol::intern(&CodegenUnit::mangle_name(FALLBACK_CODEGEN_UNIT)).as_str()
+ }
+}
+
pub fn partition<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
trans_items: I,
let codegen_unit_name = match characteristic_def_id {
Some(def_id) => compute_codegen_unit_name(tcx, def_id, is_volatile),
- None => Symbol::intern(FALLBACK_CODEGEN_UNIT).as_str(),
+ None => fallback_cgu_name(tcx),
};
let make_codegen_unit = || {
// always ensure we have at least one CGU; otherwise, if we have a
// crate with just types (for example), we could wind up with no CGU
if codegen_units.is_empty() {
- let codegen_unit_name = Symbol::intern(FALLBACK_CODEGEN_UNIT).as_str();
+ let codegen_unit_name = fallback_cgu_name(tcx);
codegen_units.insert(codegen_unit_name.clone(),
CodegenUnit::new(codegen_unit_name.clone()));
}
// Unfortunately we cannot just use the `ty::item_path` infrastructure here
// because we need paths to modules and the DefIds of those are not
// available anymore for external items.
- let mut mod_path = String::with_capacity(64);
+ let mut cgu_name = String::with_capacity(64);
let def_path = tcx.def_path(def_id);
- mod_path.push_str(&tcx.crate_name(def_path.krate).as_str());
+ cgu_name.push_str(&tcx.crate_name(def_path.krate).as_str());
for part in tcx.def_path(def_id)
.data
_ => false,
}
}) {
- mod_path.push_str("-");
- mod_path.push_str(&part.data.as_interned_str());
+ cgu_name.push_str("-");
+ cgu_name.push_str(&part.data.as_interned_str());
}
if volatile {
- mod_path.push_str(".volatile");
+ cgu_name.push_str(".volatile");
}
- return Symbol::intern(&mod_path[..]).as_str();
+ let cgu_name = if tcx.sess.opts.debugging_opts.human_readable_cgu_names {
+ cgu_name
+ } else {
+ CodegenUnit::mangle_name(&cgu_name)
+ };
+
+ Symbol::intern(&cgu_name[..]).as_str()
}
fn numbered_codegen_unit_name(crate_name: &str, index: usize) -> InternedString {
use std::iter;
use transform::{add_moves_for_packed_drops, add_call_guards};
-use transform::{no_landing_pads, simplify};
+use transform::{remove_noop_landing_pads, no_landing_pads, simplify};
use util::elaborate_drops::{self, DropElaborator, DropStyle, DropFlagMode};
use util::patch::MirPatch;
add_moves_for_packed_drops::add_moves_for_packed_drops(
tcx, &mut result, instance.def_id());
no_landing_pads::no_landing_pads(tcx, &mut result);
+ remove_noop_landing_pads::remove_noop_landing_pads(tcx, &mut result);
simplify::simplify_cfg(&mut result);
add_call_guards::CriticalCallEdges.add_call_guards(&mut result);
debug!("make_shim({:?}) = {:?}", instance, result);
return_qualif: Option<Qualif>,
qualif: Qualif,
const_fn_arg_vars: BitVector,
- local_needs_drop: IndexVec<Local, Option<Span>>,
temp_promotion_state: IndexVec<Local, TempState>,
promotion_candidates: Vec<Candidate>
}
let mut rpo = traversal::reverse_postorder(mir);
let temps = promote_consts::collect_temps(mir, &mut rpo);
rpo.reset();
+
+ let param_env = tcx.param_env(def_id);
+
+ let mut temp_qualif = IndexVec::from_elem(None, &mir.local_decls);
+ for arg in mir.args_iter() {
+ let mut qualif = Qualif::NEEDS_DROP;
+ qualif.restrict(mir.local_decls[arg].ty, tcx, param_env);
+ temp_qualif[arg] = Some(qualif);
+ }
+
Qualifier {
mode,
span: mir.span,
mir,
rpo,
tcx,
- param_env: tcx.param_env(def_id),
- temp_qualif: IndexVec::from_elem(None, &mir.local_decls),
+ param_env,
+ temp_qualif,
return_qualif: None,
qualif: Qualif::empty(),
const_fn_arg_vars: BitVector::new(mir.local_decls.len()),
- local_needs_drop: IndexVec::from_elem(None, &mir.local_decls),
temp_promotion_state: temps,
promotion_candidates: vec![]
}
return;
}
- // When initializing a local, record whether the *value* being
- // stored in it needs dropping, which it may not, even if its
- // type does, e.g. `None::<String>`.
- if let Place::Local(local) = *dest {
- if qualif.intersects(Qualif::NEEDS_DROP) {
- self.local_needs_drop[local] = Some(self.span);
- }
- }
-
match *dest {
Place::Local(index) if self.mir.local_kind(index) == LocalKind::Temp => {
debug!("store to temp {:?}", index);
&local: &Local,
_: PlaceContext<'tcx>,
_: Location) {
- match self.mir.local_kind(local) {
+ let kind = self.mir.local_kind(local);
+ match kind {
LocalKind::ReturnPointer => {
self.not_const();
}
- LocalKind::Arg => {
- self.add(Qualif::FN_ARGUMENT);
- }
LocalKind::Var => {
self.add(Qualif::NOT_CONST);
}
+ LocalKind::Arg |
LocalKind::Temp => {
+ if let LocalKind::Arg = kind {
+ self.add(Qualif::FN_ARGUMENT);
+ }
+
if !self.temp_promotion_state[local].is_promotable() {
self.add(Qualif::NOT_PROMOTABLE);
}
fn visit_operand(&mut self, operand: &Operand<'tcx>, location: Location) {
match *operand {
- Operand::Copy(ref place) |
- Operand::Move(ref place) => {
+ Operand::Copy(_) |
+ Operand::Move(_) => {
self.nest(|this| {
this.super_operand(operand, location);
this.try_consume();
});
// Mark the consumed locals to indicate later drops are noops.
- if let Place::Local(local) = *place {
- self.local_needs_drop[local] = None;
+ if let Operand::Move(Place::Local(local)) = *operand {
+ self.temp_qualif[local] = self.temp_qualif[local].map(|q|
+ q - Qualif::NEEDS_DROP
+ );
}
}
Operand::Constant(ref constant) => {
// HACK(eddyb) Emulate a bit of dataflow analysis,
// conservatively, that drop elaboration will do.
let needs_drop = if let Place::Local(local) = *place {
- self.local_needs_drop[local]
+ if self.temp_qualif[local].map_or(true, |q| q.intersects(Qualif::NEEDS_DROP)) {
+ Some(self.mir.local_decls[local].source_info.span)
+ } else {
+ None
+ }
} else {
- None
+ Some(self.span)
};
if let Some(span) = needs_drop {
/// code for these.
pub struct RemoveNoopLandingPads;
+pub fn remove_noop_landing_pads<'a, 'tcx>(
+ tcx: TyCtxt<'a, 'tcx, 'tcx>,
+ mir: &mut Mir<'tcx>)
+{
+ if tcx.sess.no_landing_pads() {
+ return
+ }
+ debug!("remove_noop_landing_pads({:?})", mir);
+
+ RemoveNoopLandingPads.remove_nop_landing_pads(mir)
+}
+
impl MirPass for RemoveNoopLandingPads {
fn run_pass<'a, 'tcx>(&self,
tcx: TyCtxt<'a, 'tcx, 'tcx>,
_src: MirSource,
mir: &mut Mir<'tcx>) {
- if tcx.sess.no_landing_pads() {
- return
- }
-
- debug!("remove_noop_landing_pads({:?})", mir);
- self.remove_nop_landing_pads(mir);
+ remove_noop_landing_pads(tcx, mir);
}
}
self.cancel_if_wrong_origin(err, o)
}
- fn cannot_reassign_immutable(&self, span: Span, desc: &str, o: Origin)
+ fn cannot_reassign_immutable(&self, span: Span, desc: &str, is_arg: bool, o: Origin)
-> DiagnosticBuilder
{
+ let msg = if is_arg {
+ "to immutable argument"
+ } else {
+ "twice to immutable variable"
+ };
let err = struct_span_err!(self, span, E0384,
- "cannot assign twice to immutable variable `{}`{OGN}",
- desc, OGN=o);
+ "cannot assign {} `{}`{OGN}",
+ msg, desc, OGN=o);
self.cancel_if_wrong_origin(err, o)
}
result: &LivenessResult,
) {
let mut file_path = PathBuf::new();
- if let Some(ref file_dir) = tcx.sess.opts.debugging_opts.dump_mir_dir {
- let p = Path::new(file_dir);
- file_path.push(p);
- };
+ file_path.push(Path::new(&tcx.sess.opts.debugging_opts.dump_mir_dir));
let item_id = tcx.hir.as_local_node_id(source.def_id).unwrap();
let file_name = format!("rustc.node{}{}-liveness.mir", item_id, pass_name);
file_path.push(&file_name);
};
let mut file_path = PathBuf::new();
-
- if let Some(ref file_dir) = tcx.sess.opts.debugging_opts.dump_mir_dir {
- let p = Path::new(file_dir);
- file_path.push(p);
- };
+ file_path.push(Path::new(&tcx.sess.opts.debugging_opts.dump_mir_dir));
let item_name = tcx.hir
.def_path(source.def_id)
crate-type = ["dylib"]
[dependencies]
-log = "0.3"
+log = "0.4"
rustc = { path = "../librustc" }
rustc_const_eval = { path = "../librustc_const_eval" }
rustc_const_math = { path = "../librustc_const_math" }
ExprKind::Continue(Some(ident)) => {
self.check_label(ident.node, ident.span);
}
+ ExprKind::InlineAsm(..) if !self.session.target.target.options.allow_asm => {
+ span_err!(self.session, expr.span, E0472, "asm! is unsupported on this target");
+ }
_ => {}
}
fn visit_item(&mut self, item: &'a Item) {
match item.node {
- ItemKind::Impl(.., Some(..), _, ref impl_items) => {
+ ItemKind::Impl(unsafety, polarity, _, _, Some(..), ref ty, ref impl_items) => {
self.invalid_visibility(&item.vis, item.span, None);
+ if ty.node == TyKind::Err {
+ self.err_handler()
+ .struct_span_err(item.span, "`impl Trait for .. {}` is an obsolete syntax")
+ .help("use `auto trait Trait {}` instead").emit();
+ }
+ if unsafety == Unsafety::Unsafe && polarity == ImplPolarity::Negative {
+ span_err!(self.session, item.span, E0198, "negative impls cannot be unsafe");
+ }
for impl_item in impl_items {
self.invalid_visibility(&impl_item.vis, impl_item.span, None);
if let ImplItemKind::Method(ref sig, _) = impl_item.node {
}
}
}
- ItemKind::Impl(.., None, _, _) => {
+ ItemKind::Impl(unsafety, polarity, defaultness, _, None, _, _) => {
self.invalid_visibility(&item.vis,
item.span,
Some("place qualifiers on individual impl items instead"));
- }
- ItemKind::AutoImpl(..) => {
- self.invalid_visibility(&item.vis, item.span, None);
+ if unsafety == Unsafety::Unsafe {
+ span_err!(self.session, item.span, E0197, "inherent impls cannot be unsafe");
+ }
+ if polarity == ImplPolarity::Negative {
+ self.err_handler().span_err(item.span, "inherent impls cannot be negative");
+ }
+ if defaultness == Defaultness::Default {
+ self.err_handler().span_err(item.span, "inherent impls cannot be default");
+ }
}
ItemKind::ForeignMod(..) => {
self.invalid_visibility(&item.vis,
if is_auto == IsAuto::Yes {
// Auto traits cannot have generics, super traits nor contain items.
if generics.is_parameterized() {
- self.err_handler().span_err(item.span,
- "auto traits cannot have generics");
+ struct_span_err!(self.session, item.span, E0567,
+ "auto traits cannot have generic parameters").emit();
}
if !bounds.is_empty() {
- self.err_handler().span_err(item.span,
- "auto traits cannot have super traits");
+ struct_span_err!(self.session, item.span, E0568,
+ "auto traits cannot have super traits").emit();
}
if !trait_items.is_empty() {
- self.err_handler().span_err(item.span,
- "auto traits cannot contain items");
+ struct_span_err!(self.session, item.span, E0380,
+ "auto traits cannot have methods or associated items").emit();
}
}
self.no_questions_in_bounds(bounds, "supertraits", true);
```
"##,
+E0197: r##"
+Inherent implementations (one that do not implement a trait but provide
+methods associated with a type) are always safe because they are not
+implementing an unsafe trait. Removing the `unsafe` keyword from the inherent
+implementation will resolve this error.
+
+```compile_fail,E0197
+struct Foo;
+
+// this will cause this error
+unsafe impl Foo { }
+// converting it to this will fix it
+impl Foo { }
+```
+"##,
+
+E0198: r##"
+A negative implementation is one that excludes a type from implementing a
+particular trait. Not being able to use a trait is always a safe operation,
+so negative implementations are always safe and never need to be marked as
+unsafe.
+
+```compile_fail
+#![feature(optin_builtin_traits)]
+
+struct Foo;
+
+// unsafe is unnecessary
+unsafe impl !Clone for Foo { }
+```
+
+This will compile:
+
+```ignore (ignore auto_trait future compatibility warning)
+#![feature(optin_builtin_traits)]
+
+struct Foo;
+
+auto trait Enterprise {}
+
+impl !Enterprise for Foo { }
+```
+
+Please note that negative impls are only allowed for auto traits.
+"##,
+
E0265: r##"
This error indicates that a static or constant references itself.
All statics and constants need to resolve to a value in an acyclic manner.
[RFC 911]: https://github.com/rust-lang/rfcs/pull/911
"##,
+E0380: r##"
+Auto traits cannot have methods or associated items.
+For more information see the [opt-in builtin traits RFC][RFC 19].
+
+[RFC 19]: https://github.com/rust-lang/rfcs/blob/master/text/0019-opt-in-builtin-traits.md
+"##,
+
E0449: r##"
A visibility qualifier was used when it was unnecessary. Erroneous code
examples:
E0226, // only a single explicit lifetime bound is permitted
E0472, // asm! is unsupported on this target
E0561, // patterns aren't allowed in function pointer types
+ E0567, // auto traits can not have generic parameters
+ E0568, // auto traits can not have super traits
E0642, // patterns aren't allowed in methods without bodies
}
pub mod hir_stats;
pub mod loops;
mod mir_stats;
-pub mod no_asm;
pub mod static_recursion;
+#[cfg(not(stage0))] // remove after the next snapshot
__build_diagnostic_array! { librustc_passes, DIAGNOSTICS }
pub fn provide(providers: &mut Providers) {
+++ /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.
-
-/// Run over the whole crate and check for ExprInlineAsm.
-/// Inline asm isn't allowed on virtual ISA based targets, so we reject it
-/// here.
-
-use rustc::session::Session;
-
-use syntax::ast;
-use syntax::visit::Visitor;
-use syntax::visit;
-
-pub fn check_crate(sess: &Session, krate: &ast::Crate) {
- if sess.target.target.options.allow_asm {
- return;
- }
-
- visit::walk_crate(&mut CheckNoAsm { sess: sess }, krate);
-}
-
-#[derive(Copy, Clone)]
-struct CheckNoAsm<'a> {
- sess: &'a Session,
-}
-
-impl<'a> Visitor<'a> for CheckNoAsm<'a> {
- fn visit_expr(&mut self, e: &'a ast::Expr) {
- match e.node {
- ast::ExprKind::InlineAsm(_) => {
- span_err!(self.sess,
- e.span,
- E0472,
- "asm! is unsupported on this target")
- }
- _ => {}
- }
- visit::walk_expr(self, e)
- }
-}
pub mod load;
pub mod build;
+#[cfg(not(stage0))] // remove after the next snapshot
__build_diagnostic_array! { librustc_plugin, DIAGNOSTICS }
fn load_plugin(&mut self, span: Span, name: &str, args: Vec<ast::NestedMetaItem>) {
let registrar = self.reader.find_plugin_registrar(span, name);
- if let Some((lib, disambiguator, index)) = registrar {
- let symbol = self.sess.generate_plugin_registrar_symbol(disambiguator, index);
+ if let Some((lib, disambiguator)) = registrar {
+ let symbol = self.sess.generate_plugin_registrar_symbol(disambiguator);
let fun = self.dylink_registrar(span, lib, symbol);
self.plugins.push(PluginRegistrar {
fun,
let def_id = self.tcx.hir.local_def_id(item.id);
cmp::min(self.item_ty_level(def_id), self.impl_trait_level(def_id))
}
- hir::ItemAutoImpl(..) => {
- let def_id = self.tcx.hir.local_def_id(item.id);
- self.impl_trait_level(def_id)
- }
// Foreign mods inherit level from parents
hir::ItemForeignMod(..) => {
self.prev_level
}
hir::ItemUse(..) | hir::ItemStatic(..) | hir::ItemConst(..) |
hir::ItemGlobalAsm(..) | hir::ItemTy(..) | hir::ItemMod(..) | hir::ItemTraitAlias(..) |
- hir::ItemFn(..) | hir::ItemExternCrate(..) | hir::ItemAutoImpl(..) => {}
+ hir::ItemFn(..) | hir::ItemExternCrate(..) => {}
}
// Mark all items in interfaces of reachable items as reachable
hir::ItemExternCrate(..) => {}
// All nested items are checked by visit_item
hir::ItemMod(..) => {}
- // Reexports are handled in visit_mod
+ // Re-exports are handled in visit_mod
hir::ItemUse(..) => {}
// The interface is empty
- hir::ItemAutoImpl(..) => {}
- // The interface is empty
hir::ItemGlobalAsm(..) => {}
// Visit everything
hir::ItemConst(..) | hir::ItemStatic(..) |
fn visit_item(&mut self, item: &'tcx hir::Item) {
match item.node {
- // contents of a private mod can be reexported, so we need
+ // contents of a private mod can be re-exported, so we need
// to check internals.
hir::ItemMod(_) => {}
self.check(field.id, min(item_visibility, field_visibility)).ty();
}
}
- // The interface is empty
- hir::ItemAutoImpl(..) => {}
// An inherent impl is public when its type is public
// Subitems of inherent impls have their own publicity
hir::ItemImpl(.., None, _, ref impl_item_refs) => {
Rc::new(visitor.access_levels)
}
+#[cfg(not(stage0))] // remove after the next snapshot
__build_diagnostic_array! { librustc_privacy, DIAGNOSTICS }
test = false
[dependencies]
-log = "0.3"
+log = "0.4"
syntax = { path = "../libsyntax" }
rustc = { path = "../librustc" }
arena = { path = "../libarena" }
// Disallow `use $crate;`
if source.name == keywords::DollarCrate.name() && path.segments.len() == 1 {
- let crate_root = self.resolve_crate_root(source.ctxt);
+ let crate_root = self.resolve_crate_root(source.ctxt, true);
let crate_name = match crate_root.kind {
ModuleKind::Def(_, name) => name,
ModuleKind::Block(..) => unreachable!(),
self.insert_field_names(item_def_id, field_names);
}
- ItemKind::AutoImpl(..) | ItemKind::Impl(..) => {}
+ ItemKind::Impl(..) => {}
ItemKind::Trait(..) => {
let def_id = self.definitions.local_def_id(item.id);
let (def, vis) = (binding.def(), binding.vis);
self.macro_exports.push(Export { ident, def, vis, span, is_import: true });
} else {
- span_err!(self.session, span, E0470, "reexported macro not found");
+ span_err!(self.session, span, E0470, "re-exported macro not found");
}
}
used
}
} else if attr.check_name("macro_reexport") {
let bad_macro_reexport = |this: &mut Self, span| {
- span_err!(this.session, span, E0467, "bad macro reexport");
+ span_err!(this.session, span, E0467, "bad macro re-export");
};
if let Some(names) = attr.meta_item_list() {
for attr in names {
"##,
E0467: r##"
-Macro reexport declarations were empty or malformed.
+Macro re-export declarations were empty or malformed.
Erroneous code examples:
This is a syntax error at the level of attribute declarations.
Currently, `macro_reexport` requires at least one macro name to be listed.
-Unlike `macro_use`, listing no names does not reexport all macros from the
+Unlike `macro_use`, listing no names does not re-export all macros from the
given crate.
Decide which macros you would like to export and list them properly.
-These are proper reexport declarations:
+These are proper re-export declarations:
```ignore (cannot-doctest-multicrate-project)
#[macro_reexport(some_macro, another_macro)]
"##,
E0470: r##"
-A macro listed for reexport was not found.
+A macro listed for re-export was not found.
Erroneous code example:
This could be caused by a typo. Did you misspell the macro's name?
-Double-check the names of the macros listed for reexport, and that the crate
+Double-check the names of the macros listed for re-export, and that the crate
in question exports them.
A working version:
use rustc::util::nodemap::{NodeMap, NodeSet, FxHashMap, FxHashSet, DefIdMap};
use syntax::codemap::{dummy_spanned, respan};
-use syntax::ext::hygiene::{Mark, SyntaxContext};
+use syntax::ext::hygiene::{Mark, MarkKind, SyntaxContext};
use syntax::ast::{self, Name, NodeId, Ident, SpannedIdent, FloatTy, IntTy, UintTy};
use syntax::ext::base::SyntaxExtension;
use syntax::ext::base::Determinacy::{self, Determined, Undetermined};
unresolved_invocations: RefCell::new(FxHashSet()),
no_implicit_prelude: false,
glob_importers: RefCell::new(Vec::new()),
- globs: RefCell::new((Vec::new())),
+ globs: RefCell::new(Vec::new()),
traits: RefCell::new(None),
populated: Cell::new(normal_ancestor_id.is_local()),
span,
table.intern("char", TyChar);
table.intern("f32", TyFloat(FloatTy::F32));
table.intern("f64", TyFloat(FloatTy::F64));
- table.intern("isize", TyInt(IntTy::Is));
+ table.intern("isize", TyInt(IntTy::Isize));
table.intern("i8", TyInt(IntTy::I8));
table.intern("i16", TyInt(IntTy::I16));
table.intern("i32", TyInt(IntTy::I32));
table.intern("i64", TyInt(IntTy::I64));
table.intern("i128", TyInt(IntTy::I128));
table.intern("str", TyStr);
- table.intern("usize", TyUint(UintTy::Us));
+ table.intern("usize", TyUint(UintTy::Usize));
table.intern("u8", TyUint(UintTy::U8));
table.intern("u16", TyUint(UintTy::U16));
table.intern("u32", TyUint(UintTy::U32));
result
}
- fn resolve_crate_root(&mut self, mut ctxt: SyntaxContext) -> Module<'a> {
- let module = match ctxt.adjust(Mark::root()) {
+ fn resolve_crate_root(&mut self, mut ctxt: SyntaxContext, legacy: bool) -> Module<'a> {
+ let mark = if legacy {
+ // When resolving `$crate` from a `macro_rules!` invoked in a `macro`,
+ // we don't want to pretend that the `macro_rules!` definition is in the `macro`
+ // as described in `SyntaxContext::apply_mark`, so we ignore prepended modern marks.
+ ctxt.marks().into_iter().find(|&mark| mark.kind() != MarkKind::Modern)
+ } else {
+ ctxt = ctxt.modern();
+ ctxt.adjust(Mark::root())
+ };
+ let module = match mark {
Some(def) => self.macro_def_scope(def),
None => return self.graph_root,
};
|this| visit::walk_item(this, item));
}
- ItemKind::AutoImpl(_, ref trait_ref) => {
- self.with_optional_trait_ref(Some(trait_ref), |this, _| {
- // Resolve type arguments in trait path
- visit::walk_trait_ref(this, trait_ref);
- });
- }
ItemKind::Impl(.., ref generics, ref opt_trait_ref, ref self_type, ref impl_items) =>
self.resolve_implementation(generics,
opt_trait_ref,
let lint = lint::builtin::LEGACY_CONSTRUCTOR_VISIBILITY;
self.session.buffer_lint(lint, id, span,
"private struct constructors are not usable through \
- reexports in outer modules",
+ re-exports in outer modules",
);
res = Some(PathResolution::new(ctor_def));
}
let msg = "There are too many initial `super`s.".to_string();
return PathResult::Failed(ident.span, msg, false);
}
+ } else if i == 0 && ns == TypeNS && name == keywords::Extern.name() {
+ continue;
}
allow_super = false;
(i == 1 && name == keywords::Crate.name() &&
path[0].node.name == keywords::CrateRoot.name()) {
// `::a::b` or `::crate::a::b`
- module = Some(self.resolve_crate_root(ident.node.ctxt.modern()));
+ module = Some(self.resolve_crate_root(ident.node.ctxt, false));
continue
} else if i == 0 && name == keywords::DollarCrate.name() {
// `$crate::a::b`
- module = Some(self.resolve_crate_root(ident.node.ctxt));
- continue
- } else if i == 1 && self.session.features.borrow().extern_absolute_paths &&
- path[0].node.name == keywords::CrateRoot.name() &&
- !token::Ident(ident.node).is_path_segment_keyword() {
- // `::extern_crate::a::b`
- let crate_id = self.crate_loader.resolve_crate_from_path(name, ident.span);
- let crate_root =
- self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX });
- self.populate_module_if_necessary(crate_root);
- module = Some(crate_root);
+ module = Some(self.resolve_crate_root(ident.node.ctxt, true));
continue
+ } else if i == 1 && !token::Ident(ident.node).is_path_segment_keyword() {
+ let prev_name = path[0].node.name;
+ if prev_name == keywords::Extern.name() ||
+ prev_name == keywords::CrateRoot.name() &&
+ self.session.features.borrow().extern_absolute_paths {
+ // `::extern_crate::a::b`
+ let crate_id = self.crate_loader.resolve_crate_from_path(name, ident.span);
+ let crate_root =
+ self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX });
+ self.populate_module_if_necessary(crate_root);
+ module = Some(crate_root);
+ continue
+ }
}
}
name == keywords::SelfValue.name() && i != 0 ||
name == keywords::SelfType.name() && i != 0 ||
name == keywords::Super.name() && i != 0 ||
+ name == keywords::Extern.name() && i != 0 ||
name == keywords::Crate.name() && i != 1 &&
path[0].node.name != keywords::CrateRoot.name() {
let name_str = if name == keywords::CrateRoot.name() {
}
/// A somewhat inefficient routine to obtain the name of a module.
-fn module_to_string(module: Module) -> String {
+fn module_to_string(module: Module) -> Option<String> {
let mut names = Vec::new();
fn collect_mod(names: &mut Vec<Ident>, module: Module) {
collect_mod(&mut names, module);
if names.is_empty() {
- return "???".to_string();
+ return None;
}
- names_to_string(&names.into_iter()
+ Some(names_to_string(&names.into_iter()
.rev()
.map(|n| dummy_spanned(n))
- .collect::<Vec<_>>())
+ .collect::<Vec<_>>()))
}
fn err_path_resolution() -> PathResolution {
No,
}
+#[cfg(not(stage0))] // remove after the next snapshot
__build_diagnostic_array! { librustc_resolve, DIAGNOSTICS }
use Namespace::{self, MacroNS};
use build_reduced_graph::BuildReducedGraphVisitor;
use resolve_imports::ImportResolver;
-use rustc_data_structures::indexed_vec::Idx;
-use rustc::hir::def_id::{DefId, BUILTIN_MACROS_CRATE, CRATE_DEF_INDEX, DefIndex};
+use rustc::hir::def_id::{DefId, BUILTIN_MACROS_CRATE, CRATE_DEF_INDEX, DefIndex,
+ DefIndexAddressSpace};
use rustc::hir::def::{Def, Export};
use rustc::hir::map::{self, DefCollector};
use rustc::{ty, lint};
let ident = path.segments[0].identifier;
if ident.name == keywords::DollarCrate.name() {
path.segments[0].identifier.name = keywords::CrateRoot.name();
- let module = self.0.resolve_crate_root(ident.ctxt);
+ let module = self.0.resolve_crate_root(ident.ctxt, true);
if !module.is_local() {
let span = path.segments[0].span;
path.segments.insert(1, match module.kind {
fn add_builtin(&mut self, ident: ast::Ident, ext: Rc<SyntaxExtension>) {
let def_id = DefId {
krate: BUILTIN_MACROS_CRATE,
- index: DefIndex::new(self.macro_map.len()),
+ index: DefIndex::from_array_index(self.macro_map.len(),
+ DefIndexAddressSpace::Low),
};
let kind = ext.kind();
self.macro_map.insert(def_id, ext);
if let Some(suggestion) = suggestion {
if suggestion != name {
if let MacroKind::Bang = kind {
- err.span_suggestion(span, "you could try the macro",
- format!("{}!", suggestion));
+ err.span_suggestion(span, "you could try the macro", suggestion.to_string());
} else {
err.span_suggestion(span, "try", suggestion.to_string());
}
},
GlobImport {
is_prelude: bool,
- max_vis: Cell<ty::Visibility>, // The visibility of the greatest reexport.
- // n.b. `max_vis` is only used in `finalize_import` to check for reexport errors.
+ max_vis: Cell<ty::Visibility>, // The visibility of the greatest re-export.
+ // n.b. `max_vis` is only used in `finalize_import` to check for re-export errors.
},
ExternCrate(Option<Name>),
MacroUse,
fn resolve_import(&mut self, directive: &'b ImportDirective<'b>) -> bool {
debug!("(resolving import for module) resolving import `{}::...` in `{}`",
names_to_string(&directive.module_path[..]),
- module_to_string(self.current_module));
+ module_to_string(self.current_module).unwrap_or("???".to_string()));
self.current_module = directive.parent;
self.current_module = directive.parent;
let ImportDirective { ref module_path, span, .. } = *directive;
- // Extern crate mode for absolute paths needs some
- // special support for single-segment imports.
- let extern_absolute_paths = self.session.features.borrow().extern_absolute_paths;
- if module_path.len() == 1 && module_path[0].node.name == keywords::CrateRoot.name() {
+ // FIXME: Last path segment is treated specially in import resolution, so extern crate
+ // mode for absolute paths needs some special support for single-segment imports.
+ if module_path.len() == 1 && (module_path[0].node.name == keywords::CrateRoot.name() ||
+ module_path[0].node.name == keywords::Extern.name()) {
+ let is_extern = module_path[0].node.name == keywords::Extern.name() ||
+ self.session.features.borrow().extern_absolute_paths;
match directive.subclass {
- GlobImport { .. } if extern_absolute_paths => {
+ GlobImport { .. } if is_extern => {
return Some((directive.span,
"cannot glob-import all possible crates".to_string()));
}
SingleImport { source, target, .. } => {
- let crate_root = if source.name == keywords::Crate.name() {
+ let crate_root = if source.name == keywords::Crate.name() &&
+ module_path[0].node.name != keywords::Extern.name() {
if target.name == keywords::Crate.name() {
return Some((directive.span,
"crate root imports need to be explicitly named: \
`use crate as name;`".to_string()));
} else {
- Some(self.resolve_crate_root(source.ctxt.modern()))
+ Some(self.resolve_crate_root(source.ctxt.modern(), false))
}
- } else if extern_absolute_paths &&
- !token::Ident(source).is_path_segment_keyword() {
+ } else if is_extern && !token::Ident(source).is_path_segment_keyword() {
let crate_id =
self.crate_loader.resolve_crate_from_path(source.name, directive.span);
let crate_root =
None => "".to_owned(),
};
let module_str = module_to_string(module);
- let msg = if &module_str == "???" {
- format!("no `{}` in the root{}", ident, lev_suggestion)
- } else {
+ let msg = if let Some(module_str) = module_str {
format!("no `{}` in `{}`{}", ident, module_str, lev_suggestion)
+ } else {
+ format!("no `{}` in the root{}", ident, lev_suggestion)
};
Some((span, msg))
} else {
if !any_successful_reexport {
let (ns, binding) = reexport_error.unwrap();
if ns == TypeNS && binding.is_extern_crate() {
- let msg = format!("extern crate `{}` is private, and cannot be reexported \
- (error E0365), consider declaring with `pub`",
+ let msg = format!("extern crate `{}` is private, and cannot be \
+ re-exported (error E0365), consider declaring with \
+ `pub`",
ident);
self.session.buffer_lint(PUB_USE_OF_PRIVATE_EXTERN_CRATE,
directive.id,
&msg);
} else if ns == TypeNS {
struct_span_err!(self.session, directive.span, E0365,
- "`{}` is private, and cannot be reexported", ident)
- .span_label(directive.span, format!("reexport of private `{}`", ident))
+ "`{}` is private, and cannot be re-exported", ident)
+ .span_label(directive.span, format!("re-export of private `{}`", ident))
.note(&format!("consider declaring type or module `{}` with `pub`", ident))
.emit();
} else {
- let msg = format!("`{}` is private, and cannot be reexported", ident);
+ let msg = format!("`{}` is private, and cannot be re-exported", ident);
let note_msg =
format!("consider marking `{}` as `pub` in the imported module", ident);
struct_span_err!(self.session, directive.span, E0364, "{}", &msg)
self.record_def(directive.id, PathResolution::new(module.def().unwrap()));
}
- // Miscellaneous post-processing, including recording reexports,
+ // Miscellaneous post-processing, including recording re-exports,
// reporting conflicts, and reporting unresolved imports.
fn finalize_resolutions_in(&mut self, module: Module<'b>) {
// Since import resolution is finished, globs will not define any more names.
!orig_binding.vis.is_at_least(binding.vis, &*self) {
let msg = match directive.subclass {
ImportDirectiveSubclass::SingleImport { .. } => {
- format!("variant `{}` is private and cannot be reexported",
+ format!("variant `{}` is private and cannot be re-exported",
ident)
},
ImportDirectiveSubclass::GlobImport { .. } => {
let msg = "enum is private and its variants \
- cannot be reexported".to_owned();
+ cannot be re-exported".to_owned();
let error_id = (DiagnosticMessageId::ErrorId(0), // no code?!
Some(binding.span),
msg.clone());
crate-type = ["dylib"]
[dependencies]
-log = "0.3"
+log = "0.4"
rustc = { path = "../librustc" }
rustc_data_structures = { path = "../librustc_data_structures" }
rustc_typeck = { path = "../librustc_typeck" }
root_item: &'l ast::Item,
prefix: &ast::Path) {
let path = &use_tree.prefix;
- let access = access_from!(self.save_ctxt, root_item);
+
+ // The access is calculated using the current tree ID, but with the root tree's visibility
+ // (since nested trees don't have their own visibility).
+ let access = Access {
+ public: root_item.vis == ast::Visibility::Public,
+ reachable: self.save_ctxt.analysis.access_levels.is_reachable(id),
+ };
// The parent def id of a given use tree is always the enclosing item.
let parent = self.save_ctxt.tcx.hir.opt_local_def_id(id)
if !self.span.filter_generated(sub_span, ex.span) {
let span =
self.span_from_span(sub_span.expect("No span found for var ref"));
+ let ref_id =
+ ::id_from_def_id(def.non_enum_variant().fields[idx.node].did);
self.dumper.dump_ref(Ref {
kind: RefKind::Variable,
span,
- ref_id: ::id_from_def_id(def.struct_variant().fields[idx.node].did),
+ ref_id,
});
}
}
};
match self.tables.expr_ty_adjusted(&hir_node).sty {
ty::TyAdt(def, _) if !def.is_enum() => {
- let f = def.struct_variant().field_named(ident.node.name);
+ let f = def.non_enum_variant().field_named(ident.node.name);
let sub_span = self.span_utils.span_for_last_ident(expr.span);
filter!(self.span_utils, sub_span, expr.span, None);
let span = self.span_from_span(sub_span.unwrap());
config: Option<Config>,
mut handler: H,
) {
- let _ignore = tcx.dep_graph.in_ignore();
+ tcx.dep_graph.with_ignore(|| {
+ assert!(analysis.glob_map.is_some());
- assert!(analysis.glob_map.is_some());
+ info!("Dumping crate {}", cratename);
- info!("Dumping crate {}", cratename);
-
- let save_ctxt = SaveContext {
- tcx,
- tables: &ty::TypeckTables::empty(None),
- analysis,
- span_utils: SpanUtils::new(&tcx.sess),
- config: find_config(config),
- };
+ let save_ctxt = SaveContext {
+ tcx,
+ tables: &ty::TypeckTables::empty(None),
+ analysis,
+ span_utils: SpanUtils::new(&tcx.sess),
+ config: find_config(config),
+ };
- handler.save(save_ctxt, krate, cratename)
+ handler.save(save_ctxt, krate, cratename)
+ })
}
fn find_config(supplied: Option<Config>) -> Config {
fn id_from_def_id(id: DefId) -> rls_data::Id {
rls_data::Id {
krate: id.krate.as_u32(),
- index: id.index.as_u32(),
+ index: id.index.as_raw_u32(),
}
}
Ok(sig)
}
- ast::ItemKind::AutoImpl(unsafety, ref trait_ref) => {
- let mut text = String::new();
- if unsafety == ast::Unsafety::Unsafe {
- text.push_str("unsafe ");
- }
- text.push_str("impl ");
- let trait_sig = trait_ref.path.make(offset + text.len(), id, scx)?;
- text.push_str(&trait_sig.text);
- text.push_str(" for .. {}");
- Ok(replace_text(trait_sig, text))
- }
ast::ItemKind::Impl(
unsafety,
polarity,
bitflags = "1.0"
flate2 = "1.0"
jobserver = "0.1.5"
-log = "0.3"
+log = "0.4"
num_cpus = "1.0"
rustc = { path = "../librustc" }
rustc-demangle = "0.1.4"
use base;
use builder::Builder;
use common::{ty_fn_sig, C_usize};
-use context::CrateContext;
+use context::CodegenCx;
use cabi_x86;
use cabi_x86_64;
use cabi_x86_win64;
}
impl Reg {
- pub fn align(&self, ccx: &CrateContext) -> Align {
- let dl = ccx.data_layout();
+ pub fn align(&self, cx: &CodegenCx) -> Align {
+ let dl = cx.data_layout();
match self.kind {
RegKind::Integer => {
match self.size.bits() {
}
}
- pub fn llvm_type(&self, ccx: &CrateContext) -> Type {
+ pub fn llvm_type(&self, cx: &CodegenCx) -> Type {
match self.kind {
- RegKind::Integer => Type::ix(ccx, self.size.bits()),
+ RegKind::Integer => Type::ix(cx, self.size.bits()),
RegKind::Float => {
match self.size.bits() {
- 32 => Type::f32(ccx),
- 64 => Type::f64(ccx),
+ 32 => Type::f32(cx),
+ 64 => Type::f64(cx),
_ => bug!("unsupported float: {:?}", self)
}
}
RegKind::Vector => {
- Type::vector(&Type::i8(ccx), self.size.bytes())
+ Type::vector(&Type::i8(cx), self.size.bytes())
}
}
}
}
impl Uniform {
- pub fn align(&self, ccx: &CrateContext) -> Align {
- self.unit.align(ccx)
+ pub fn align(&self, cx: &CodegenCx) -> Align {
+ self.unit.align(cx)
}
- pub fn llvm_type(&self, ccx: &CrateContext) -> Type {
- let llunit = self.unit.llvm_type(ccx);
+ pub fn llvm_type(&self, cx: &CodegenCx) -> Type {
+ let llunit = self.unit.llvm_type(cx);
if self.total <= self.unit.size {
return llunit;
assert_eq!(self.unit.kind, RegKind::Integer);
let args: Vec<_> = (0..count).map(|_| llunit)
- .chain(iter::once(Type::ix(ccx, rem_bytes * 8)))
+ .chain(iter::once(Type::ix(cx, rem_bytes * 8)))
.collect();
- Type::struct_(ccx, &args, false)
+ Type::struct_(cx, &args, false)
}
}
pub trait LayoutExt<'tcx> {
fn is_aggregate(&self) -> bool;
- fn homogeneous_aggregate<'a>(&self, ccx: &CrateContext<'a, 'tcx>) -> Option<Reg>;
+ fn homogeneous_aggregate<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> Option<Reg>;
}
impl<'tcx> LayoutExt<'tcx> for TyLayout<'tcx> {
}
}
- fn homogeneous_aggregate<'a>(&self, ccx: &CrateContext<'a, 'tcx>) -> Option<Reg> {
+ fn homogeneous_aggregate<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> Option<Reg> {
match self.abi {
layout::Abi::Uninhabited => None,
let is_union = match self.fields {
layout::FieldPlacement::Array { count, .. } => {
if count > 0 {
- return self.field(ccx, 0).homogeneous_aggregate(ccx);
+ return self.field(cx, 0).homogeneous_aggregate(cx);
} else {
return None;
}
return None;
}
- let field = self.field(ccx, i);
- match (result, field.homogeneous_aggregate(ccx)) {
+ let field = self.field(cx, i);
+ match (result, field.homogeneous_aggregate(cx)) {
// The field itself must be a homogeneous aggregate.
(_, None) => return None,
// If this is the first field, record the unit.
}
impl CastTarget {
- pub fn size(&self, ccx: &CrateContext) -> Size {
+ pub fn size(&self, cx: &CodegenCx) -> Size {
match *self {
CastTarget::Uniform(u) => u.total,
CastTarget::Pair(a, b) => {
- (a.size.abi_align(a.align(ccx)) + b.size)
- .abi_align(self.align(ccx))
+ (a.size.abi_align(a.align(cx)) + b.size)
+ .abi_align(self.align(cx))
}
}
}
- pub fn align(&self, ccx: &CrateContext) -> Align {
+ pub fn align(&self, cx: &CodegenCx) -> Align {
match *self {
- CastTarget::Uniform(u) => u.align(ccx),
+ CastTarget::Uniform(u) => u.align(cx),
CastTarget::Pair(a, b) => {
- ccx.data_layout().aggregate_align
- .max(a.align(ccx))
- .max(b.align(ccx))
+ cx.data_layout().aggregate_align
+ .max(a.align(cx))
+ .max(b.align(cx))
}
}
}
- pub fn llvm_type(&self, ccx: &CrateContext) -> Type {
+ pub fn llvm_type(&self, cx: &CodegenCx) -> Type {
match *self {
- CastTarget::Uniform(u) => u.llvm_type(ccx),
+ CastTarget::Uniform(u) => u.llvm_type(cx),
CastTarget::Pair(a, b) => {
- Type::struct_(ccx, &[
- a.llvm_type(ccx),
- b.llvm_type(ccx)
+ Type::struct_(cx, &[
+ a.llvm_type(cx),
+ b.llvm_type(cx)
], false)
}
}
/// Get the LLVM type for an place of the original Rust type of
/// this argument/return, i.e. the result of `type_of::type_of`.
- pub fn memory_ty(&self, ccx: &CrateContext<'a, 'tcx>) -> Type {
- self.layout.llvm_type(ccx)
+ pub fn memory_ty(&self, cx: &CodegenCx<'a, 'tcx>) -> Type {
+ self.layout.llvm_type(cx)
}
/// Store a direct/indirect value described by this ArgType into a
/// place for the original Rust type of this argument/return.
/// Can be used for both storing formal arguments into Rust variables
/// or results of call/invoke instructions into their destinations.
- pub fn store(&self, bcx: &Builder<'a, 'tcx>, val: ValueRef, dst: PlaceRef<'tcx>) {
+ pub fn store(&self, bx: &Builder<'a, 'tcx>, val: ValueRef, dst: PlaceRef<'tcx>) {
if self.is_ignore() {
return;
}
- let ccx = bcx.ccx;
+ let cx = bx.cx;
if self.is_indirect() {
- OperandValue::Ref(val, self.layout.align).store(bcx, dst)
+ OperandValue::Ref(val, self.layout.align).store(bx, dst)
} else if let PassMode::Cast(cast) = self.mode {
// FIXME(eddyb): Figure out when the simpler Store is safe, clang
// uses it for i16 -> {i8, i8}, but not for i24 -> {i8, i8, i8}.
let can_store_through_cast_ptr = false;
if can_store_through_cast_ptr {
- let cast_dst = bcx.pointercast(dst.llval, cast.llvm_type(ccx).ptr_to());
- bcx.store(val, cast_dst, self.layout.align);
+ let cast_dst = bx.pointercast(dst.llval, cast.llvm_type(cx).ptr_to());
+ bx.store(val, cast_dst, self.layout.align);
} else {
// The actual return type is a struct, but the ABI
// adaptation code has cast it into some scalar type. The
// bitcasting to the struct type yields invalid cast errors.
// We instead thus allocate some scratch space...
- let scratch_size = cast.size(ccx);
- let scratch_align = cast.align(ccx);
- let llscratch = bcx.alloca(cast.llvm_type(ccx), "abi_cast", scratch_align);
- bcx.lifetime_start(llscratch, scratch_size);
+ let scratch_size = cast.size(cx);
+ let scratch_align = cast.align(cx);
+ let llscratch = bx.alloca(cast.llvm_type(cx), "abi_cast", scratch_align);
+ bx.lifetime_start(llscratch, scratch_size);
// ...where we first store the value...
- bcx.store(val, llscratch, scratch_align);
+ bx.store(val, llscratch, scratch_align);
// ...and then memcpy it to the intended destination.
- base::call_memcpy(bcx,
- bcx.pointercast(dst.llval, Type::i8p(ccx)),
- bcx.pointercast(llscratch, Type::i8p(ccx)),
- C_usize(ccx, self.layout.size.bytes()),
+ base::call_memcpy(bx,
+ bx.pointercast(dst.llval, Type::i8p(cx)),
+ bx.pointercast(llscratch, Type::i8p(cx)),
+ C_usize(cx, self.layout.size.bytes()),
self.layout.align.min(scratch_align));
- bcx.lifetime_end(llscratch, scratch_size);
+ bx.lifetime_end(llscratch, scratch_size);
}
} else {
- OperandValue::Immediate(val).store(bcx, dst);
+ OperandValue::Immediate(val).store(bx, dst);
}
}
- pub fn store_fn_arg(&self, bcx: &Builder<'a, 'tcx>, idx: &mut usize, dst: PlaceRef<'tcx>) {
- if self.pad.is_some() {
- *idx += 1;
- }
+ pub fn store_fn_arg(&self, bx: &Builder<'a, 'tcx>, idx: &mut usize, dst: PlaceRef<'tcx>) {
let mut next = || {
- let val = llvm::get_param(bcx.llfn(), *idx as c_uint);
+ let val = llvm::get_param(bx.llfn(), *idx as c_uint);
*idx += 1;
val
};
match self.mode {
PassMode::Ignore => {},
PassMode::Pair(..) => {
- OperandValue::Pair(next(), next()).store(bcx, dst);
+ OperandValue::Pair(next(), next()).store(bx, dst);
}
PassMode::Direct(_) | PassMode::Indirect(_) | PassMode::Cast(_) => {
- self.store(bcx, next(), dst);
+ self.store(bx, next(), dst);
}
}
}
}
impl<'a, 'tcx> FnType<'tcx> {
- pub fn of_instance(ccx: &CrateContext<'a, 'tcx>, instance: &ty::Instance<'tcx>)
+ pub fn of_instance(cx: &CodegenCx<'a, 'tcx>, instance: &ty::Instance<'tcx>)
-> Self {
- let fn_ty = instance.ty(ccx.tcx());
- let sig = ty_fn_sig(ccx, fn_ty);
- let sig = ccx.tcx().erase_late_bound_regions_and_normalize(&sig);
- FnType::new(ccx, sig, &[])
+ let fn_ty = instance.ty(cx.tcx);
+ let sig = ty_fn_sig(cx, fn_ty);
+ let sig = cx.tcx.erase_late_bound_regions_and_normalize(&sig);
+ FnType::new(cx, sig, &[])
}
- pub fn new(ccx: &CrateContext<'a, 'tcx>,
+ pub fn new(cx: &CodegenCx<'a, 'tcx>,
sig: ty::FnSig<'tcx>,
extra_args: &[Ty<'tcx>]) -> FnType<'tcx> {
- let mut fn_ty = FnType::unadjusted(ccx, sig, extra_args);
- fn_ty.adjust_for_abi(ccx, sig.abi);
+ let mut fn_ty = FnType::unadjusted(cx, sig, extra_args);
+ fn_ty.adjust_for_abi(cx, sig.abi);
fn_ty
}
- pub fn new_vtable(ccx: &CrateContext<'a, 'tcx>,
+ pub fn new_vtable(cx: &CodegenCx<'a, 'tcx>,
sig: ty::FnSig<'tcx>,
extra_args: &[Ty<'tcx>]) -> FnType<'tcx> {
- let mut fn_ty = FnType::unadjusted(ccx, sig, extra_args);
+ let mut fn_ty = FnType::unadjusted(cx, sig, extra_args);
// Don't pass the vtable, it's not an argument of the virtual fn.
{
let self_arg = &mut fn_ty.args[0];
.unwrap_or_else(|| {
bug!("FnType::new_vtable: non-pointer self {:?}", self_arg)
}).ty;
- let fat_ptr_ty = ccx.tcx().mk_mut_ptr(pointee);
- self_arg.layout = ccx.layout_of(fat_ptr_ty).field(ccx, 0);
+ let fat_ptr_ty = cx.tcx.mk_mut_ptr(pointee);
+ self_arg.layout = cx.layout_of(fat_ptr_ty).field(cx, 0);
}
- fn_ty.adjust_for_abi(ccx, sig.abi);
+ fn_ty.adjust_for_abi(cx, sig.abi);
fn_ty
}
- pub fn unadjusted(ccx: &CrateContext<'a, 'tcx>,
+ pub fn unadjusted(cx: &CodegenCx<'a, 'tcx>,
sig: ty::FnSig<'tcx>,
extra_args: &[Ty<'tcx>]) -> FnType<'tcx> {
debug!("FnType::unadjusted({:?}, {:?})", sig, extra_args);
use self::Abi::*;
- let cconv = match ccx.sess().target.target.adjust_abi(sig.abi) {
+ let cconv = match cx.sess().target.target.adjust_abi(sig.abi) {
RustIntrinsic | PlatformIntrinsic |
Rust | RustCall => llvm::CCallConv,
extra_args
};
- let target = &ccx.sess().target.target;
+ let target = &cx.sess().target.target;
let win_x64_gnu = target.target_os == "windows"
&& target.arch == "x86_64"
&& target.target_env == "gnu";
}
}
- if let Some(pointee) = layout.pointee_info_at(ccx, offset) {
+ if let Some(pointee) = layout.pointee_info_at(cx, offset) {
if let Some(kind) = pointee.safe {
attrs.pointee_size = pointee.size;
attrs.pointee_align = Some(pointee.align);
};
let arg_of = |ty: Ty<'tcx>, is_return: bool| {
- let mut arg = ArgType::new(ccx.layout_of(ty));
+ let mut arg = ArgType::new(cx.layout_of(ty));
if arg.layout.is_zst() {
// For some forsaken reason, x86_64-pc-windows-gnu
// doesn't ignore zero-sized struct arguments.
adjust_for_rust_scalar(&mut b_attrs,
b,
arg.layout,
- a.value.size(ccx).abi_align(b.value.align(ccx)),
+ a.value.size(cx).abi_align(b.value.align(cx)),
false);
arg.mode = PassMode::Pair(a_attrs, b_attrs);
return arg;
}
fn adjust_for_abi(&mut self,
- ccx: &CrateContext<'a, 'tcx>,
+ cx: &CodegenCx<'a, 'tcx>,
abi: Abi) {
if abi == Abi::Unadjusted { return }
}
let size = arg.layout.size;
- if size > layout::Pointer.size(ccx) {
+ if size > layout::Pointer.size(cx) {
arg.make_indirect();
} else {
// We want to pass small aggregates as immediates, but using
return;
}
- match &ccx.sess().target.target.arch[..] {
+ match &cx.sess().target.target.arch[..] {
"x86" => {
let flavor = if abi == Abi::Fastcall {
cabi_x86::Flavor::Fastcall
} else {
cabi_x86::Flavor::General
};
- cabi_x86::compute_abi_info(ccx, self, flavor);
+ cabi_x86::compute_abi_info(cx, self, flavor);
},
"x86_64" => if abi == Abi::SysV64 {
- cabi_x86_64::compute_abi_info(ccx, self);
- } else if abi == Abi::Win64 || ccx.sess().target.target.options.is_like_windows {
+ cabi_x86_64::compute_abi_info(cx, self);
+ } else if abi == Abi::Win64 || cx.sess().target.target.options.is_like_windows {
cabi_x86_win64::compute_abi_info(self);
} else {
- cabi_x86_64::compute_abi_info(ccx, self);
+ cabi_x86_64::compute_abi_info(cx, self);
},
- "aarch64" => cabi_aarch64::compute_abi_info(ccx, self),
- "arm" => cabi_arm::compute_abi_info(ccx, self),
- "mips" => cabi_mips::compute_abi_info(ccx, self),
- "mips64" => cabi_mips64::compute_abi_info(ccx, self),
- "powerpc" => cabi_powerpc::compute_abi_info(ccx, self),
- "powerpc64" => cabi_powerpc64::compute_abi_info(ccx, self),
- "s390x" => cabi_s390x::compute_abi_info(ccx, self),
- "asmjs" => cabi_asmjs::compute_abi_info(ccx, self),
- "wasm32" => cabi_asmjs::compute_abi_info(ccx, self),
+ "aarch64" => cabi_aarch64::compute_abi_info(cx, self),
+ "arm" => cabi_arm::compute_abi_info(cx, self),
+ "mips" => cabi_mips::compute_abi_info(cx, self),
+ "mips64" => cabi_mips64::compute_abi_info(cx, self),
+ "powerpc" => cabi_powerpc::compute_abi_info(cx, self),
+ "powerpc64" => cabi_powerpc64::compute_abi_info(cx, self),
+ "s390x" => cabi_s390x::compute_abi_info(cx, self),
+ "asmjs" => cabi_asmjs::compute_abi_info(cx, self),
+ "wasm32" => cabi_asmjs::compute_abi_info(cx, self),
"msp430" => cabi_msp430::compute_abi_info(self),
- "sparc" => cabi_sparc::compute_abi_info(ccx, self),
- "sparc64" => cabi_sparc64::compute_abi_info(ccx, self),
+ "sparc" => cabi_sparc::compute_abi_info(cx, self),
+ "sparc64" => cabi_sparc64::compute_abi_info(cx, self),
"nvptx" => cabi_nvptx::compute_abi_info(self),
"nvptx64" => cabi_nvptx64::compute_abi_info(self),
"hexagon" => cabi_hexagon::compute_abi_info(self),
- a => ccx.sess().fatal(&format!("unrecognized arch \"{}\" in target specification", a))
+ a => cx.sess().fatal(&format!("unrecognized arch \"{}\" in target specification", a))
}
if let PassMode::Indirect(ref mut attrs) = self.ret.mode {
}
}
- pub fn llvm_type(&self, ccx: &CrateContext<'a, 'tcx>) -> Type {
+ pub fn llvm_type(&self, cx: &CodegenCx<'a, 'tcx>) -> Type {
let mut llargument_tys = Vec::new();
let llreturn_ty = match self.ret.mode {
- PassMode::Ignore => Type::void(ccx),
+ PassMode::Ignore => Type::void(cx),
PassMode::Direct(_) | PassMode::Pair(..) => {
- self.ret.layout.immediate_llvm_type(ccx)
+ self.ret.layout.immediate_llvm_type(cx)
}
- PassMode::Cast(cast) => cast.llvm_type(ccx),
+ PassMode::Cast(cast) => cast.llvm_type(cx),
PassMode::Indirect(_) => {
- llargument_tys.push(self.ret.memory_ty(ccx).ptr_to());
- Type::void(ccx)
+ llargument_tys.push(self.ret.memory_ty(cx).ptr_to());
+ Type::void(cx)
}
};
for arg in &self.args {
// add padding
if let Some(ty) = arg.pad {
- llargument_tys.push(ty.llvm_type(ccx));
+ llargument_tys.push(ty.llvm_type(cx));
}
let llarg_ty = match arg.mode {
PassMode::Ignore => continue,
- PassMode::Direct(_) => arg.layout.immediate_llvm_type(ccx),
+ PassMode::Direct(_) => arg.layout.immediate_llvm_type(cx),
PassMode::Pair(..) => {
- llargument_tys.push(arg.layout.scalar_pair_element_llvm_type(ccx, 0));
- llargument_tys.push(arg.layout.scalar_pair_element_llvm_type(ccx, 1));
+ llargument_tys.push(arg.layout.scalar_pair_element_llvm_type(cx, 0));
+ llargument_tys.push(arg.layout.scalar_pair_element_llvm_type(cx, 1));
continue;
}
- PassMode::Cast(cast) => cast.llvm_type(ccx),
- PassMode::Indirect(_) => arg.memory_ty(ccx).ptr_to(),
+ PassMode::Cast(cast) => cast.llvm_type(cx),
+ PassMode::Indirect(_) => arg.memory_ty(cx).ptr_to(),
};
llargument_tys.push(llarg_ty);
}
// Take an inline assembly expression and splat it out via LLVM
pub fn trans_inline_asm<'a, 'tcx>(
- bcx: &Builder<'a, 'tcx>,
+ bx: &Builder<'a, 'tcx>,
ia: &hir::InlineAsm,
outputs: Vec<PlaceRef<'tcx>>,
mut inputs: Vec<ValueRef>
let mut indirect_outputs = vec![];
for (i, (out, place)) in ia.outputs.iter().zip(&outputs).enumerate() {
if out.is_rw {
- inputs.push(place.load(bcx).immediate());
+ inputs.push(place.load(bx).immediate());
ext_constraints.push(i.to_string());
}
if out.is_indirect {
- indirect_outputs.push(place.load(bcx).immediate());
+ indirect_outputs.push(place.load(bx).immediate());
} else {
- output_types.push(place.layout.llvm_type(bcx.ccx));
+ output_types.push(place.layout.llvm_type(bx.cx));
}
}
if !indirect_outputs.is_empty() {
// Default per-arch clobbers
// Basically what clang does
- let arch_clobbers = match &bcx.sess().target.target.arch[..] {
+ let arch_clobbers = match &bx.sess().target.target.arch[..] {
"x86" | "x86_64" => vec!["~{dirflag}", "~{fpsr}", "~{flags}"],
_ => Vec::new()
};
// Depending on how many outputs we have, the return type is different
let num_outputs = output_types.len();
let output_type = match num_outputs {
- 0 => Type::void(bcx.ccx),
+ 0 => Type::void(bx.cx),
1 => output_types[0],
- _ => Type::struct_(bcx.ccx, &output_types, false)
+ _ => Type::struct_(bx.cx, &output_types, false)
};
let dialect = match ia.dialect {
let asm = CString::new(ia.asm.as_str().as_bytes()).unwrap();
let constraint_cstr = CString::new(all_constraints).unwrap();
- let r = bcx.inline_asm_call(
+ let r = bx.inline_asm_call(
asm.as_ptr(),
constraint_cstr.as_ptr(),
&inputs,
// Again, based on how many outputs we have
let outputs = ia.outputs.iter().zip(&outputs).filter(|&(ref o, _)| !o.is_indirect);
for (i, (_, &place)) in outputs.enumerate() {
- let v = if num_outputs == 1 { r } else { bcx.extract_value(r, i as u64) };
- OperandValue::Immediate(v).store(bcx, place);
+ let v = if num_outputs == 1 { r } else { bx.extract_value(r, i as u64) };
+ OperandValue::Immediate(v).store(bx, place);
}
// Store mark in a metadata node so we can map LLVM errors
// back to source locations. See #17552.
unsafe {
let key = "srcloc";
- let kind = llvm::LLVMGetMDKindIDInContext(bcx.ccx.llcx(),
+ let kind = llvm::LLVMGetMDKindIDInContext(bx.cx.llcx,
key.as_ptr() as *const c_char, key.len() as c_uint);
- let val: llvm::ValueRef = C_i32(bcx.ccx, ia.ctxt.outer().as_u32() as i32);
+ let val: llvm::ValueRef = C_i32(bx.cx, ia.ctxt.outer().as_u32() as i32);
llvm::LLVMSetMetadata(r, kind,
- llvm::LLVMMDNodeInContext(bcx.ccx.llcx(), &val, 1));
+ llvm::LLVMMDNodeInContext(bx.cx.llcx, &val, 1));
}
}
-pub fn trans_global_asm<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
+pub fn trans_global_asm<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
ga: &hir::GlobalAsm) {
let asm = CString::new(ga.asm.as_str().as_bytes()).unwrap();
unsafe {
- llvm::LLVMRustAppendModuleInlineAsm(ccx.llmod(), asm.as_ptr());
+ llvm::LLVMRustAppendModuleInlineAsm(cx.llmod, asm.as_ptr());
}
}
//! perturb the reuse results.
use rustc::dep_graph::{DepNode, DepConstructor};
+use rustc::mir::mono::CodegenUnit;
use rustc::ty::TyCtxt;
use syntax::ast;
+use syntax_pos::symbol::Symbol;
use rustc::ich::{ATTR_PARTITION_REUSED, ATTR_PARTITION_TRANSLATED};
const MODULE: &'static str = "module";
enum Disposition { Reused, Translated }
pub(crate) fn assert_module_sources<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
- let _ignore = tcx.dep_graph.in_ignore();
-
- if tcx.sess.opts.incremental.is_none() {
- return;
- }
+ tcx.dep_graph.with_ignore(|| {
+ if tcx.sess.opts.incremental.is_none() {
+ return;
+ }
- let ams = AssertModuleSource { tcx };
- for attr in &tcx.hir.krate().attrs {
- ams.check_attr(attr);
- }
+ let ams = AssertModuleSource { tcx };
+ for attr in &tcx.hir.krate().attrs {
+ ams.check_attr(attr);
+ }
+ })
}
struct AssertModuleSource<'a, 'tcx: 'a> {
}
let mname = self.field(attr, MODULE);
+ let mangled_cgu_name = CodegenUnit::mangle_name(&mname.as_str());
+ let mangled_cgu_name = Symbol::intern(&mangled_cgu_name).as_str();
let dep_node = DepNode::new(self.tcx,
- DepConstructor::CompileCodegenUnit(mname.as_str()));
+ DepConstructor::CompileCodegenUnit(mangled_cgu_name));
if let Some(loaded_from_cache) = self.tcx.dep_graph.was_loaded_from_cache(&dep_node) {
match (disposition, loaded_from_cache) {
//! Set and unset common attributes on LLVM values.
use std::ffi::{CStr, CString};
+use std::rc::Rc;
+use rustc::hir::Unsafety;
+use rustc::hir::def_id::{DefId, LOCAL_CRATE};
use rustc::session::config::Sanitizer;
+use rustc::ty::TyCtxt;
+use rustc::ty::maps::Providers;
+use rustc_data_structures::fx::FxHashSet;
use llvm::{self, Attribute, ValueRef};
use llvm::AttributePlace::Function;
+use llvm_util;
pub use syntax::attr::{self, InlineAttr};
use syntax::ast;
-use context::CrateContext;
+use context::CodegenCx;
/// Mark LLVM function to use provided inline heuristic.
#[inline]
Attribute::Naked.toggle_llfn(Function, val, is_naked);
}
-pub fn set_frame_pointer_elimination(ccx: &CrateContext, llfn: ValueRef) {
+pub fn set_frame_pointer_elimination(cx: &CodegenCx, llfn: ValueRef) {
// FIXME: #11906: Omitting frame pointers breaks retrieving the value of a
// parameter.
- if ccx.sess().must_not_eliminate_frame_pointers() {
+ if cx.sess().must_not_eliminate_frame_pointers() {
llvm::AddFunctionAttrStringValue(
llfn, llvm::AttributePlace::Function,
cstr("no-frame-pointer-elim\0"), cstr("true\0"));
}
}
-pub fn set_probestack(ccx: &CrateContext, llfn: ValueRef) {
+pub fn set_probestack(cx: &CodegenCx, llfn: ValueRef) {
// Only use stack probes if the target specification indicates that we
// should be using stack probes
- if !ccx.sess().target.target.options.stack_probes {
+ if !cx.sess().target.target.options.stack_probes {
return
}
// Currently stack probes seem somewhat incompatible with the address
// sanitizer. With asan we're already protected from stack overflow anyway
// so we don't really need stack probes regardless.
- match ccx.sess().opts.debugging_opts.sanitizer {
+ match cx.sess().opts.debugging_opts.sanitizer {
Some(Sanitizer::Address) => return,
_ => {}
}
/// Composite function which sets LLVM attributes for function depending on its AST (#[attribute])
/// attributes.
-pub fn from_fn_attrs(ccx: &CrateContext, attrs: &[ast::Attribute], llfn: ValueRef) {
+pub fn from_fn_attrs(cx: &CodegenCx, llfn: ValueRef, id: DefId) {
use syntax::attr::*;
- inline(llfn, find_inline_attr(Some(ccx.sess().diagnostic()), attrs));
+ let attrs = cx.tcx.get_attrs(id);
+ inline(llfn, find_inline_attr(Some(cx.sess().diagnostic()), &attrs));
- set_frame_pointer_elimination(ccx, llfn);
- set_probestack(ccx, llfn);
- let mut target_features = vec![];
- for attr in attrs {
- if attr.check_name("target_feature") {
- if let Some(val) = attr.value_str() {
- for feat in val.as_str().split(",").map(|f| f.trim()) {
- if !feat.is_empty() && !feat.contains('\0') {
- target_features.push(feat.to_string());
- }
- }
- }
- } else if attr.check_name("cold") {
+ set_frame_pointer_elimination(cx, llfn);
+ set_probestack(cx, llfn);
+
+ for attr in attrs.iter() {
+ if attr.check_name("cold") {
Attribute::Cold.apply_llfn(Function, llfn);
} else if attr.check_name("naked") {
naked(llfn, true);
unwind(llfn, false);
}
}
+
+ let target_features = cx.tcx.target_features_enabled(id);
if !target_features.is_empty() {
let val = CString::new(target_features.join(",")).unwrap();
llvm::AddFunctionAttrStringValue(
fn cstr(s: &'static str) -> &CStr {
CStr::from_bytes_with_nul(s.as_bytes()).expect("null-terminated string")
}
+
+pub fn provide(providers: &mut Providers) {
+ providers.target_features_whitelist = |tcx, cnum| {
+ assert_eq!(cnum, LOCAL_CRATE);
+ Rc::new(llvm_util::target_feature_whitelist(tcx.sess)
+ .iter()
+ .map(|c| c.to_str().unwrap().to_string())
+ .collect())
+ };
+
+ providers.target_features_enabled = |tcx, id| {
+ let whitelist = tcx.target_features_whitelist(LOCAL_CRATE);
+ let mut target_features = Vec::new();
+ for attr in tcx.get_attrs(id).iter() {
+ if !attr.check_name("target_feature") {
+ continue
+ }
+ if let Some(val) = attr.value_str() {
+ for feat in val.as_str().split(",").map(|f| f.trim()) {
+ if !feat.is_empty() && !feat.contains('\0') {
+ target_features.push(feat.to_string());
+ }
+ }
+ let msg = "#[target_feature = \"..\"] is deprecated and will \
+ eventually be removed, use \
+ #[target_feature(enable = \"..\")] instead";
+ tcx.sess.span_warn(attr.span, &msg);
+ continue
+ }
+
+ if tcx.fn_sig(id).unsafety() == Unsafety::Normal {
+ let msg = "#[target_feature(..)] can only be applied to \
+ `unsafe` function";
+ tcx.sess.span_err(attr.span, msg);
+ }
+ from_target_feature(tcx, attr, &whitelist, &mut target_features);
+ }
+ Rc::new(target_features)
+ };
+}
+
+fn from_target_feature(
+ tcx: TyCtxt,
+ attr: &ast::Attribute,
+ whitelist: &FxHashSet<String>,
+ target_features: &mut Vec<String>,
+) {
+ let list = match attr.meta_item_list() {
+ Some(list) => list,
+ None => {
+ let msg = "#[target_feature] attribute must be of the form \
+ #[target_feature(..)]";
+ tcx.sess.span_err(attr.span, &msg);
+ return
+ }
+ };
+
+ for item in list {
+ if !item.check_name("enable") {
+ let msg = "#[target_feature(..)] only accepts sub-keys of `enable` \
+ currently";
+ tcx.sess.span_err(item.span, &msg);
+ continue
+ }
+ let value = match item.value_str() {
+ Some(list) => list,
+ None => {
+ let msg = "#[target_feature] attribute must be of the form \
+ #[target_feature(enable = \"..\")]";
+ tcx.sess.span_err(item.span, &msg);
+ continue
+ }
+ };
+ let value = value.as_str();
+ for feature in value.split(',') {
+ if whitelist.contains(feature) {
+ target_features.push(format!("+{}", feature));
+ continue
+ }
+
+ let msg = format!("the feature named `{}` is not valid for \
+ this target", feature);
+ let mut err = tcx.sess.struct_span_err(item.span, &msg);
+
+ if feature.starts_with("+") {
+ let valid = whitelist.contains(&feature[1..]);
+ if valid {
+ err.help("consider removing the leading `+` in the feature name");
+ }
+ }
+ err.emit();
+ }
+ }
+}
// The version number this compiler will write to bytecode objects in rlibs
pub const RLIB_BYTECODE_OBJECT_VERSION: u8 = 2;
-pub const RLIB_BYTECODE_EXTENSION: &str = "bytecode.encoded";
+pub const RLIB_BYTECODE_EXTENSION: &str = "bc.z";
pub fn encode(identifier: &str, bytecode: &[u8]) -> Vec<u8> {
let mut encoded = Vec::new();
// was tagged as #42791) and some more info can be found on #44443 for
// emscripten itself.
let cmd = |linker: &Path| {
- if cfg!(windows) && linker.ends_with(".bat") {
- let mut cmd = Command::new("cmd");
- cmd.arg("/c").arg(linker);
- cmd
- } else {
- Command::new(linker)
+ if let Some(linker) = linker.to_str() {
+ if cfg!(windows) && linker.ends_with(".bat") {
+ let mut cmd = Command::new("cmd");
+ cmd.arg("/c").arg(linker);
+ return cmd
+ }
}
+ Command::new(linker)
};
if let Some(ref linker) = sess.opts.cg.linker {
fn emit_metadata<'a>(sess: &'a Session, trans: &CrateTranslation, tmpdir: &TempDir)
-> PathBuf {
let out_filename = tmpdir.path().join(METADATA_FILENAME);
- let result = fs::File::create(&out_filename).and_then(|mut f| {
- f.write_all(&trans.metadata.raw_data)
- });
+ let result = fs::write(&out_filename, &trans.metadata.raw_data);
if let Err(e) = result {
sess.fatal(&format!("failed to write {}: {}", out_filename.display(), e));
// into that context. One day, however, we may do this for upstream
// crates but for locally translated modules we may be able to reuse
// that LLVM Context and Module.
- let llcx = llvm::LLVMContextCreate();
+ let llcx = llvm::LLVMRustContextCreate(cgcx.fewer_names);
let llmod = llvm::LLVMRustParseBitcodeForThinLTO(
llcx,
self.data().as_ptr(),
if let Some(id) = tcx.sess.derive_registrar_fn.get() {
let def_id = tcx.hir.local_def_id(id);
- let idx = def_id.index;
let disambiguator = tcx.sess.local_crate_disambiguator();
- let registrar = tcx.sess.generate_derive_registrar_symbol(disambiguator, idx);
+ let registrar = tcx.sess.generate_derive_registrar_symbol(disambiguator);
local_crate.push((registrar, Some(def_id), SymbolExportLevel::C));
}
if let Some(id) = node_id {
if tcx.sess.plugin_registrar_fn.get() == Some(id) {
- let idx = def_id.index;
let disambiguator = tcx.sess.local_crate_disambiguator();
- return tcx.sess.generate_plugin_registrar_symbol(disambiguator, idx);
+ return tcx.sess.generate_plugin_registrar_symbol(disambiguator);
}
if tcx.sess.derive_registrar_fn.get() == Some(id) {
- let idx = def_id.index;
let disambiguator = tcx.sess.local_crate_disambiguator();
- return tcx.sess.generate_derive_registrar_symbol(disambiguator, idx);
+ return tcx.sess.generate_derive_registrar_symbol(disambiguator);
}
}
use std::any::Any;
use std::ffi::{CString, CStr};
-use std::fs::{self, File};
-use std::io;
-use std::io::{Read, Write};
+use std::fs;
+use std::io::{self, Write};
use std::mem;
use std::path::{Path, PathBuf};
use std::str;
pub thinlto: bool,
pub no_landing_pads: bool,
pub save_temps: bool,
+ pub fewer_names: bool,
pub exported_symbols: Arc<ExportedSymbols>,
pub opts: Arc<config::Options>,
pub crate_types: Vec<config::CrateType>,
timeline.record("make-bc");
if write_bc {
- if let Err(e) = File::create(&bc_out).and_then(|mut f| f.write_all(data)) {
+ if let Err(e) = fs::write(&bc_out, data) {
diag_handler.err(&format!("failed to write bytecode: {}", e));
}
timeline.record("write-bc");
if config.emit_bc_compressed {
let dst = bc_out.with_extension(RLIB_BYTECODE_EXTENSION);
let data = bytecode::encode(&mtrans.llmod_id, data);
- if let Err(e) = File::create(&dst).and_then(|mut f| f.write_all(&data)) {
+ if let Err(e) = fs::write(&dst, data) {
diag_handler.err(&format!("failed to write bytecode: {}", e));
}
timeline.record("compress-bc");
object: &Path) {
use rustc_binaryen::{Module, ModuleOptions};
- let input = File::open(&assembly).and_then(|mut f| {
- let mut contents = Vec::new();
- f.read_to_end(&mut contents)?;
+ let input = fs::read(&assembly).and_then(|contents| {
Ok(CString::new(contents)?)
});
let mut options = ModuleOptions::new();
.map_err(|e| io::Error::new(io::ErrorKind::Other, e))
});
let err = assembled.and_then(|binary| {
- File::create(&object).and_then(|mut f| f.write_all(binary.data()))
+ fs::write(&object, binary.data())
});
if let Err(e) = err {
handler.err(&format!("failed to run binaryen assembler: {}", e));
let sess = tcx.sess;
// First up, convert our jobserver into a helper thread so we can use normal
- // mpsc channels to manage our messages and such. Once we've got the helper
- // thread then request `n-1` tokens because all of our work items are ready
- // to go.
- //
- // Note that the `n-1` is here because we ourselves have a token (our
- // process) and we'll use that token to execute at least one unit of work.
- //
- // After we've requested all these tokens then we'll, when we can, get
- // tokens on `rx` above which will get managed in the main loop below.
+ // mpsc channels to manage our messages and such.
+ // After we've requested tokens then we'll, when we can,
+ // get tokens on `coordinator_receive` which will
+ // get managed in the main loop below.
let coordinator_send2 = coordinator_send.clone();
let helper = jobserver.into_helper_thread(move |token| {
drop(coordinator_send2.send(Box::new(Message::Token(token))));
unsafe { llvm::LLVMRustThinLTOAvailable() },
no_landing_pads: sess.no_landing_pads(),
+ fewer_names: sess.fewer_names(),
save_temps: sess.opts.cg.save_temps,
opts: Arc::new(sess.opts.clone()),
time_passes: sess.time_passes(),
use callee;
use common::{C_bool, C_bytes_in_context, C_i32, C_usize};
use rustc_mir::monomorphize::collector::{self, MonoItemCollectionMode};
-use common::{self, C_struct_in_context, C_array, CrateContext, val_ty};
+use common::{self, C_struct_in_context, C_array, val_ty};
use consts;
-use context::{self, LocalCrateContext, SharedCrateContext};
+use context::{self, CodegenCx};
use debuginfo;
use declare;
use meth;
pub use rustc_mir::monomorphize::item::linkage_by_name;
pub struct StatRecorder<'a, 'tcx: 'a> {
- ccx: &'a CrateContext<'a, 'tcx>,
+ cx: &'a CodegenCx<'a, 'tcx>,
name: Option<String>,
istart: usize,
}
impl<'a, 'tcx> StatRecorder<'a, 'tcx> {
- pub fn new(ccx: &'a CrateContext<'a, 'tcx>, name: String) -> StatRecorder<'a, 'tcx> {
- let istart = ccx.stats().borrow().n_llvm_insns;
+ pub fn new(cx: &'a CodegenCx<'a, 'tcx>, name: String) -> StatRecorder<'a, 'tcx> {
+ let istart = cx.stats.borrow().n_llvm_insns;
StatRecorder {
- ccx,
+ cx,
name: Some(name),
istart,
}
impl<'a, 'tcx> Drop for StatRecorder<'a, 'tcx> {
fn drop(&mut self) {
- if self.ccx.sess().trans_stats() {
- let mut stats = self.ccx.stats().borrow_mut();
+ if self.cx.sess().trans_stats() {
+ let mut stats = self.cx.stats.borrow_mut();
let iend = stats.n_llvm_insns;
stats.fn_stats.push((self.name.take().unwrap(), iend - self.istart));
stats.n_fns += 1;
}
pub fn compare_simd_types<'a, 'tcx>(
- bcx: &Builder<'a, 'tcx>,
+ bx: &Builder<'a, 'tcx>,
lhs: ValueRef,
rhs: ValueRef,
t: Ty<'tcx>,
let signed = match t.sty {
ty::TyFloat(_) => {
let cmp = bin_op_to_fcmp_predicate(op);
- return bcx.sext(bcx.fcmp(cmp, lhs, rhs), ret_ty);
+ return bx.sext(bx.fcmp(cmp, lhs, rhs), ret_ty);
},
ty::TyUint(_) => false,
ty::TyInt(_) => true,
// to get the correctly sized type. This will compile to a single instruction
// once the IR is converted to assembly if the SIMD instruction is supported
// by the target architecture.
- bcx.sext(bcx.icmp(cmp, lhs, rhs), ret_ty)
+ bx.sext(bx.icmp(cmp, lhs, rhs), ret_ty)
}
/// Retrieve the information we are losing (making dynamic) in an unsizing
/// The `old_info` argument is a bit funny. It is intended for use
/// in an upcast, where the new vtable for an object will be derived
/// from the old one.
-pub fn unsized_info<'ccx, 'tcx>(ccx: &CrateContext<'ccx, 'tcx>,
+pub fn unsized_info<'cx, 'tcx>(cx: &CodegenCx<'cx, 'tcx>,
source: Ty<'tcx>,
target: Ty<'tcx>,
old_info: Option<ValueRef>)
-> ValueRef {
- let (source, target) = ccx.tcx().struct_lockstep_tails(source, target);
+ let (source, target) = cx.tcx.struct_lockstep_tails(source, target);
match (&source.sty, &target.sty) {
(&ty::TyArray(_, len), &ty::TySlice(_)) => {
- C_usize(ccx, len.val.to_const_int().unwrap().to_u64().unwrap())
+ C_usize(cx, len.val.to_const_int().unwrap().to_u64().unwrap())
}
(&ty::TyDynamic(..), &ty::TyDynamic(..)) => {
// For now, upcasts are limited to changes in marker
old_info.expect("unsized_info: missing old info for trait upcast")
}
(_, &ty::TyDynamic(ref data, ..)) => {
- let vtable_ptr = ccx.layout_of(ccx.tcx().mk_mut_ptr(target))
- .field(ccx, abi::FAT_PTR_EXTRA);
- consts::ptrcast(meth::get_vtable(ccx, source, data.principal()),
- vtable_ptr.llvm_type(ccx))
+ let vtable_ptr = cx.layout_of(cx.tcx.mk_mut_ptr(target))
+ .field(cx, abi::FAT_PTR_EXTRA);
+ consts::ptrcast(meth::get_vtable(cx, source, data.principal()),
+ vtable_ptr.llvm_type(cx))
}
_ => bug!("unsized_info: invalid unsizing {:?} -> {:?}",
source,
/// Coerce `src` to `dst_ty`. `src_ty` must be a thin pointer.
pub fn unsize_thin_ptr<'a, 'tcx>(
- bcx: &Builder<'a, 'tcx>,
+ bx: &Builder<'a, 'tcx>,
src: ValueRef,
src_ty: Ty<'tcx>,
dst_ty: Ty<'tcx>
&ty::TyRawPtr(ty::TypeAndMut { ty: b, .. })) |
(&ty::TyRawPtr(ty::TypeAndMut { ty: a, .. }),
&ty::TyRawPtr(ty::TypeAndMut { ty: b, .. })) => {
- assert!(bcx.ccx.shared().type_is_sized(a));
- let ptr_ty = bcx.ccx.layout_of(b).llvm_type(bcx.ccx).ptr_to();
- (bcx.pointercast(src, ptr_ty), unsized_info(bcx.ccx, a, b, None))
+ assert!(bx.cx.type_is_sized(a));
+ let ptr_ty = bx.cx.layout_of(b).llvm_type(bx.cx).ptr_to();
+ (bx.pointercast(src, ptr_ty), unsized_info(bx.cx, a, b, None))
}
(&ty::TyAdt(def_a, _), &ty::TyAdt(def_b, _)) if def_a.is_box() && def_b.is_box() => {
let (a, b) = (src_ty.boxed_ty(), dst_ty.boxed_ty());
- assert!(bcx.ccx.shared().type_is_sized(a));
- let ptr_ty = bcx.ccx.layout_of(b).llvm_type(bcx.ccx).ptr_to();
- (bcx.pointercast(src, ptr_ty), unsized_info(bcx.ccx, a, b, None))
+ assert!(bx.cx.type_is_sized(a));
+ let ptr_ty = bx.cx.layout_of(b).llvm_type(bx.cx).ptr_to();
+ (bx.pointercast(src, ptr_ty), unsized_info(bx.cx, a, b, None))
}
(&ty::TyAdt(def_a, _), &ty::TyAdt(def_b, _)) => {
assert_eq!(def_a, def_b);
- let src_layout = bcx.ccx.layout_of(src_ty);
- let dst_layout = bcx.ccx.layout_of(dst_ty);
+ let src_layout = bx.cx.layout_of(src_ty);
+ let dst_layout = bx.cx.layout_of(dst_ty);
let mut result = None;
for i in 0..src_layout.fields.count() {
- let src_f = src_layout.field(bcx.ccx, i);
+ let src_f = src_layout.field(bx.cx, i);
assert_eq!(src_layout.fields.offset(i).bytes(), 0);
assert_eq!(dst_layout.fields.offset(i).bytes(), 0);
if src_f.is_zst() {
}
assert_eq!(src_layout.size, src_f.size);
- let dst_f = dst_layout.field(bcx.ccx, i);
+ let dst_f = dst_layout.field(bx.cx, i);
assert_ne!(src_f.ty, dst_f.ty);
assert_eq!(result, None);
- result = Some(unsize_thin_ptr(bcx, src, src_f.ty, dst_f.ty));
+ result = Some(unsize_thin_ptr(bx, src, src_f.ty, dst_f.ty));
}
let (lldata, llextra) = result.unwrap();
// HACK(eddyb) have to bitcast pointers until LLVM removes pointee types.
- (bcx.bitcast(lldata, dst_layout.scalar_pair_element_llvm_type(bcx.ccx, 0)),
- bcx.bitcast(llextra, dst_layout.scalar_pair_element_llvm_type(bcx.ccx, 1)))
+ (bx.bitcast(lldata, dst_layout.scalar_pair_element_llvm_type(bx.cx, 0)),
+ bx.bitcast(llextra, dst_layout.scalar_pair_element_llvm_type(bx.cx, 1)))
}
_ => bug!("unsize_thin_ptr: called on bad types"),
}
/// Coerce `src`, which is a reference to a value of type `src_ty`,
/// to a value of type `dst_ty` and store the result in `dst`
-pub fn coerce_unsized_into<'a, 'tcx>(bcx: &Builder<'a, 'tcx>,
+pub fn coerce_unsized_into<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
src: PlaceRef<'tcx>,
dst: PlaceRef<'tcx>) {
let src_ty = src.layout.ty;
let dst_ty = dst.layout.ty;
let coerce_ptr = || {
- let (base, info) = match src.load(bcx).val {
+ let (base, info) = match src.load(bx).val {
OperandValue::Pair(base, info) => {
// fat-ptr to fat-ptr unsize preserves the vtable
// i.e. &'a fmt::Debug+Send => &'a fmt::Debug
// So we need to pointercast the base to ensure
// the types match up.
- let thin_ptr = dst.layout.field(bcx.ccx, abi::FAT_PTR_ADDR);
- (bcx.pointercast(base, thin_ptr.llvm_type(bcx.ccx)), info)
+ let thin_ptr = dst.layout.field(bx.cx, abi::FAT_PTR_ADDR);
+ (bx.pointercast(base, thin_ptr.llvm_type(bx.cx)), info)
}
OperandValue::Immediate(base) => {
- unsize_thin_ptr(bcx, base, src_ty, dst_ty)
+ unsize_thin_ptr(bx, base, src_ty, dst_ty)
}
OperandValue::Ref(..) => bug!()
};
- OperandValue::Pair(base, info).store(bcx, dst);
+ OperandValue::Pair(base, info).store(bx, dst);
};
match (&src_ty.sty, &dst_ty.sty) {
(&ty::TyRef(..), &ty::TyRef(..)) |
assert_eq!(def_a, def_b);
for i in 0..def_a.variants[0].fields.len() {
- let src_f = src.project_field(bcx, i);
- let dst_f = dst.project_field(bcx, i);
+ let src_f = src.project_field(bx, i);
+ let dst_f = dst.project_field(bx, i);
if dst_f.layout.is_zst() {
continue;
}
if src_f.layout.ty == dst_f.layout.ty {
- memcpy_ty(bcx, dst_f.llval, src_f.llval, src_f.layout,
+ memcpy_ty(bx, dst_f.llval, src_f.llval, src_f.layout,
src_f.align.min(dst_f.align));
} else {
- coerce_unsized_into(bcx, src_f, dst_f);
+ coerce_unsized_into(bx, src_f, dst_f);
}
}
}
sess.target.target.options.is_like_msvc
}
-pub fn call_assume<'a, 'tcx>(b: &Builder<'a, 'tcx>, val: ValueRef) {
- let assume_intrinsic = b.ccx.get_intrinsic("llvm.assume");
- b.call(assume_intrinsic, &[val], None);
+pub fn call_assume<'a, 'tcx>(bx: &Builder<'a, 'tcx>, val: ValueRef) {
+ let assume_intrinsic = bx.cx.get_intrinsic("llvm.assume");
+ bx.call(assume_intrinsic, &[val], None);
}
-pub fn from_immediate(bcx: &Builder, val: ValueRef) -> ValueRef {
- if val_ty(val) == Type::i1(bcx.ccx) {
- bcx.zext(val, Type::i8(bcx.ccx))
+pub fn from_immediate(bx: &Builder, val: ValueRef) -> ValueRef {
+ if val_ty(val) == Type::i1(bx.cx) {
+ bx.zext(val, Type::i8(bx.cx))
} else {
val
}
}
-pub fn to_immediate(bcx: &Builder, val: ValueRef, layout: layout::TyLayout) -> ValueRef {
+pub fn to_immediate(bx: &Builder, val: ValueRef, layout: layout::TyLayout) -> ValueRef {
if let layout::Abi::Scalar(ref scalar) = layout.abi {
if scalar.is_bool() {
- return bcx.trunc(val, Type::i1(bcx.ccx));
+ return bx.trunc(val, Type::i1(bx.cx));
}
}
val
}
-pub fn call_memcpy(b: &Builder,
+pub fn call_memcpy(bx: &Builder,
dst: ValueRef,
src: ValueRef,
n_bytes: ValueRef,
align: Align) {
- let ccx = b.ccx;
- let ptr_width = &ccx.sess().target.target.target_pointer_width;
+ let cx = bx.cx;
+ let ptr_width = &cx.sess().target.target.target_pointer_width;
let key = format!("llvm.memcpy.p0i8.p0i8.i{}", ptr_width);
- let memcpy = ccx.get_intrinsic(&key);
- let src_ptr = b.pointercast(src, Type::i8p(ccx));
- let dst_ptr = b.pointercast(dst, Type::i8p(ccx));
- let size = b.intcast(n_bytes, ccx.isize_ty(), false);
- let align = C_i32(ccx, align.abi() as i32);
- let volatile = C_bool(ccx, false);
- b.call(memcpy, &[dst_ptr, src_ptr, size, align, volatile], None);
+ let memcpy = cx.get_intrinsic(&key);
+ let src_ptr = bx.pointercast(src, Type::i8p(cx));
+ let dst_ptr = bx.pointercast(dst, Type::i8p(cx));
+ let size = bx.intcast(n_bytes, cx.isize_ty, false);
+ let align = C_i32(cx, align.abi() as i32);
+ let volatile = C_bool(cx, false);
+ bx.call(memcpy, &[dst_ptr, src_ptr, size, align, volatile], None);
}
pub fn memcpy_ty<'a, 'tcx>(
- bcx: &Builder<'a, 'tcx>,
+ bx: &Builder<'a, 'tcx>,
dst: ValueRef,
src: ValueRef,
layout: TyLayout<'tcx>,
return;
}
- call_memcpy(bcx, dst, src, C_usize(bcx.ccx, size), align);
+ call_memcpy(bx, dst, src, C_usize(bx.cx, size), align);
}
-pub fn call_memset<'a, 'tcx>(b: &Builder<'a, 'tcx>,
+pub fn call_memset<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
ptr: ValueRef,
fill_byte: ValueRef,
size: ValueRef,
align: ValueRef,
volatile: bool) -> ValueRef {
- let ptr_width = &b.ccx.sess().target.target.target_pointer_width;
+ let ptr_width = &bx.cx.sess().target.target.target_pointer_width;
let intrinsic_key = format!("llvm.memset.p0i8.i{}", ptr_width);
- let llintrinsicfn = b.ccx.get_intrinsic(&intrinsic_key);
- let volatile = C_bool(b.ccx, volatile);
- b.call(llintrinsicfn, &[ptr, fill_byte, size, align, volatile], None)
+ let llintrinsicfn = bx.cx.get_intrinsic(&intrinsic_key);
+ let volatile = C_bool(bx.cx, volatile);
+ bx.call(llintrinsicfn, &[ptr, fill_byte, size, align, volatile], None)
}
-pub fn trans_instance<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, instance: Instance<'tcx>) {
- let _s = if ccx.sess().trans_stats() {
+pub fn trans_instance<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, instance: Instance<'tcx>) {
+ let _s = if cx.sess().trans_stats() {
let mut instance_name = String::new();
- DefPathBasedNames::new(ccx.tcx(), true, true)
+ DefPathBasedNames::new(cx.tcx, true, true)
.push_def_path(instance.def_id(), &mut instance_name);
- Some(StatRecorder::new(ccx, instance_name))
+ Some(StatRecorder::new(cx, instance_name))
} else {
None
};
// release builds.
info!("trans_instance({})", instance);
- let fn_ty = instance.ty(ccx.tcx());
- let sig = common::ty_fn_sig(ccx, fn_ty);
- let sig = ccx.tcx().erase_late_bound_regions_and_normalize(&sig);
+ let fn_ty = instance.ty(cx.tcx);
+ let sig = common::ty_fn_sig(cx, fn_ty);
+ let sig = cx.tcx.erase_late_bound_regions_and_normalize(&sig);
- let lldecl = match ccx.instances().borrow().get(&instance) {
+ let lldecl = match cx.instances.borrow().get(&instance) {
Some(&val) => val,
None => bug!("Instance `{:?}` not already declared", instance)
};
- ccx.stats().borrow_mut().n_closures += 1;
+ cx.stats.borrow_mut().n_closures += 1;
// The `uwtable` attribute according to LLVM is:
//
//
// You can also find more info on why Windows is whitelisted here in:
// https://bugzilla.mozilla.org/show_bug.cgi?id=1302078
- if !ccx.sess().no_landing_pads() ||
- ccx.sess().target.target.options.is_like_windows {
+ if !cx.sess().no_landing_pads() ||
+ cx.sess().target.target.options.is_like_windows {
attributes::emit_uwtable(lldecl, true);
}
- let mir = ccx.tcx().instance_mir(instance.def);
- mir::trans_mir(ccx, lldecl, &mir, instance, sig);
+ let mir = cx.tcx.instance_mir(instance.def);
+ mir::trans_mir(cx, lldecl, &mir, instance, sig);
}
-pub fn set_link_section(ccx: &CrateContext,
+pub fn set_link_section(cx: &CodegenCx,
llval: ValueRef,
attrs: &[ast::Attribute]) {
if let Some(sect) = attr::first_attr_value_str_by_name(attrs, "link_section") {
if contains_null(§.as_str()) {
- ccx.sess().fatal(&format!("Illegal null byte in link_section value: `{}`", §));
+ cx.sess().fatal(&format!("Illegal null byte in link_section value: `{}`", §));
}
unsafe {
let buf = CString::new(sect.as_str().as_bytes()).unwrap();
/// Create the `main` function which will initialize the rust runtime and call
/// users main function.
-fn maybe_create_entry_wrapper(ccx: &CrateContext) {
- let (main_def_id, span) = match *ccx.sess().entry_fn.borrow() {
+fn maybe_create_entry_wrapper(cx: &CodegenCx) {
+ let (main_def_id, span) = match *cx.sess().entry_fn.borrow() {
Some((id, span)) => {
- (ccx.tcx().hir.local_def_id(id), span)
+ (cx.tcx.hir.local_def_id(id), span)
}
None => return,
};
- let instance = Instance::mono(ccx.tcx(), main_def_id);
+ let instance = Instance::mono(cx.tcx, main_def_id);
- if !ccx.codegen_unit().contains_item(&MonoItem::Fn(instance)) {
+ if !cx.codegen_unit.contains_item(&MonoItem::Fn(instance)) {
// We want to create the wrapper in the same codegen unit as Rust's main
// function.
return;
}
- let main_llfn = callee::get_fn(ccx, instance);
+ let main_llfn = callee::get_fn(cx, instance);
- let et = ccx.sess().entry_type.get().unwrap();
+ let et = cx.sess().entry_type.get().unwrap();
match et {
- config::EntryMain => create_entry_fn(ccx, span, main_llfn, main_def_id, true),
- config::EntryStart => create_entry_fn(ccx, span, main_llfn, main_def_id, false),
+ config::EntryMain => create_entry_fn(cx, span, main_llfn, main_def_id, true),
+ config::EntryStart => create_entry_fn(cx, span, main_llfn, main_def_id, false),
config::EntryNone => {} // Do nothing.
}
- fn create_entry_fn<'ccx>(ccx: &'ccx CrateContext,
+ fn create_entry_fn<'cx>(cx: &'cx CodegenCx,
sp: Span,
rust_main: ValueRef,
rust_main_def_id: DefId,
use_start_lang_item: bool) {
- let llfty = Type::func(&[Type::c_int(ccx), Type::i8p(ccx).ptr_to()], &Type::c_int(ccx));
+ let llfty = Type::func(&[Type::c_int(cx), Type::i8p(cx).ptr_to()], &Type::c_int(cx));
- let main_ret_ty = ccx.tcx().fn_sig(rust_main_def_id).output();
+ let main_ret_ty = cx.tcx.fn_sig(rust_main_def_id).output();
// Given that `main()` has no arguments,
// then its return type cannot have
// late-bound regions, since late-bound
// listing.
let main_ret_ty = main_ret_ty.no_late_bound_regions().unwrap();
- if declare::get_defined_value(ccx, "main").is_some() {
+ if declare::get_defined_value(cx, "main").is_some() {
// FIXME: We should be smart and show a better diagnostic here.
- ccx.sess().struct_span_err(sp, "entry symbol `main` defined multiple times")
+ cx.sess().struct_span_err(sp, "entry symbol `main` defined multiple times")
.help("did you use #[no_mangle] on `fn main`? Use #[start] instead")
.emit();
- ccx.sess().abort_if_errors();
+ cx.sess().abort_if_errors();
bug!();
}
- let llfn = declare::declare_cfn(ccx, "main", llfty);
+ let llfn = declare::declare_cfn(cx, "main", llfty);
// `main` should respect same config for frame pointer elimination as rest of code
- attributes::set_frame_pointer_elimination(ccx, llfn);
+ attributes::set_frame_pointer_elimination(cx, llfn);
- let bld = Builder::new_block(ccx, llfn, "top");
+ let bx = Builder::new_block(cx, llfn, "top");
- debuginfo::gdb::insert_reference_to_gdb_debug_scripts_section_global(ccx, &bld);
+ debuginfo::gdb::insert_reference_to_gdb_debug_scripts_section_global(&bx);
// Params from native main() used as args for rust start function
let param_argc = get_param(llfn, 0);
let param_argv = get_param(llfn, 1);
- let arg_argc = bld.intcast(param_argc, ccx.isize_ty(), true);
+ let arg_argc = bx.intcast(param_argc, cx.isize_ty, true);
let arg_argv = param_argv;
let (start_fn, args) = if use_start_lang_item {
- let start_def_id = ccx.tcx().require_lang_item(StartFnLangItem);
- let start_fn = callee::resolve_and_get_fn(ccx, start_def_id, ccx.tcx().mk_substs(
+ let start_def_id = cx.tcx.require_lang_item(StartFnLangItem);
+ let start_fn = callee::resolve_and_get_fn(cx, start_def_id, cx.tcx.mk_substs(
iter::once(Kind::from(main_ret_ty))));
- (start_fn, vec![bld.pointercast(rust_main, Type::i8p(ccx).ptr_to()),
+ (start_fn, vec![bx.pointercast(rust_main, Type::i8p(cx).ptr_to()),
arg_argc, arg_argv])
} else {
debug!("using user-defined start fn");
(rust_main, vec![arg_argc, arg_argv])
};
- let result = bld.call(start_fn, &args, None);
- bld.ret(bld.intcast(result, Type::c_int(ccx), true));
+ let result = bx.call(start_fn, &args, None);
+ bx.ret(bx.intcast(result, Type::c_int(cx), true));
}
}
let link_meta = link::build_link_meta(crate_hash);
let exported_symbol_node_ids = find_exported_symbols(tcx);
- let shared_ccx = SharedCrateContext::new(tcx);
// Translate the metadata.
let llmod_id = "metadata";
let (metadata_llcx, metadata_llmod, metadata) =
// Run the translation item collector and partition the collected items into
// codegen units.
let codegen_units =
- shared_ccx.tcx().collect_and_partition_translation_items(LOCAL_CRATE).1;
+ tcx.collect_and_partition_translation_items(LOCAL_CRATE).1;
let codegen_units = (*codegen_units).clone();
// Force all codegen_unit queries so they are already either red or green
symbol_names_test::report_symbol_names(tcx);
- if shared_ccx.sess().trans_stats() {
+ if tcx.sess.trans_stats() {
println!("--- trans stats ---");
println!("n_glues_created: {}", all_stats.n_glues_created);
println!("n_null_glues: {}", all_stats.n_null_glues);
}
}
- if shared_ccx.sess().count_llvm_insns() {
+ if tcx.sess.count_llvm_insns() {
for (k, v) in all_stats.llvm_insns.iter() {
println!("{:7} {}", *v, *k);
}
.to_fingerprint().to_hex());
// Instantiate translation items without filling out definitions yet...
- let scx = SharedCrateContext::new(tcx);
- let lcx = LocalCrateContext::new(&scx, cgu, &llmod_id);
+ let cx = CodegenCx::new(tcx, cgu, &llmod_id);
let module = {
- let ccx = CrateContext::new(&scx, &lcx);
- let trans_items = ccx.codegen_unit()
- .items_in_deterministic_order(ccx.tcx());
+ let trans_items = cx.codegen_unit
+ .items_in_deterministic_order(cx.tcx);
for &(trans_item, (linkage, visibility)) in &trans_items {
- trans_item.predefine(&ccx, linkage, visibility);
+ trans_item.predefine(&cx, linkage, visibility);
}
// ... and now that we have everything pre-defined, fill out those definitions.
for &(trans_item, _) in &trans_items {
- trans_item.define(&ccx);
+ trans_item.define(&cx);
}
// If this codegen unit contains the main function, also create the
// wrapper here
- maybe_create_entry_wrapper(&ccx);
+ maybe_create_entry_wrapper(&cx);
// Run replace-all-uses-with for statics that need it
- for &(old_g, new_g) in ccx.statics_to_rauw().borrow().iter() {
+ for &(old_g, new_g) in cx.statics_to_rauw.borrow().iter() {
unsafe {
let bitcast = llvm::LLVMConstPointerCast(new_g, llvm::LLVMTypeOf(old_g));
llvm::LLVMReplaceAllUsesWith(old_g, bitcast);
// Create the llvm.used variable
// This variable has type [N x i8*] and is stored in the llvm.metadata section
- if !ccx.used_statics().borrow().is_empty() {
+ if !cx.used_statics.borrow().is_empty() {
let name = CString::new("llvm.used").unwrap();
let section = CString::new("llvm.metadata").unwrap();
- let array = C_array(Type::i8(&ccx).ptr_to(), &*ccx.used_statics().borrow());
+ let array = C_array(Type::i8(&cx).ptr_to(), &*cx.used_statics.borrow());
unsafe {
- let g = llvm::LLVMAddGlobal(ccx.llmod(),
+ let g = llvm::LLVMAddGlobal(cx.llmod,
val_ty(array).to_ref(),
name.as_ptr());
llvm::LLVMSetInitializer(g, array);
}
// Finalize debuginfo
- if ccx.sess().opts.debuginfo != NoDebugInfo {
- debuginfo::finalize(&ccx);
+ if cx.sess().opts.debuginfo != NoDebugInfo {
+ debuginfo::finalize(&cx);
}
let llvm_module = ModuleLlvm {
- llcx: ccx.llcx(),
- llmod: ccx.llmod(),
- tm: create_target_machine(ccx.sess()),
+ llcx: cx.llcx,
+ llmod: cx.llmod,
+ tm: create_target_machine(cx.sess()),
};
ModuleTranslation {
}
};
- (lcx.into_stats(), module)
+ (cx.into_stats(), module)
}
}
#[must_use]
pub struct Builder<'a, 'tcx: 'a> {
pub llbuilder: BuilderRef,
- pub ccx: &'a CrateContext<'a, 'tcx>,
+ pub cx: &'a CodegenCx<'a, 'tcx>,
}
impl<'a, 'tcx> Drop for Builder<'a, 'tcx> {
}
impl<'a, 'tcx> Builder<'a, 'tcx> {
- pub fn new_block<'b>(ccx: &'a CrateContext<'a, 'tcx>, llfn: ValueRef, name: &'b str) -> Self {
- let builder = Builder::with_ccx(ccx);
+ pub fn new_block<'b>(cx: &'a CodegenCx<'a, 'tcx>, llfn: ValueRef, name: &'b str) -> Self {
+ let bx = Builder::with_cx(cx);
let llbb = unsafe {
let name = CString::new(name).unwrap();
llvm::LLVMAppendBasicBlockInContext(
- ccx.llcx(),
+ cx.llcx,
llfn,
name.as_ptr()
)
};
- builder.position_at_end(llbb);
- builder
+ bx.position_at_end(llbb);
+ bx
}
- pub fn with_ccx(ccx: &'a CrateContext<'a, 'tcx>) -> Self {
+ pub fn with_cx(cx: &'a CodegenCx<'a, 'tcx>) -> Self {
// Create a fresh builder from the crate context.
let llbuilder = unsafe {
- llvm::LLVMCreateBuilderInContext(ccx.llcx())
+ llvm::LLVMCreateBuilderInContext(cx.llcx)
};
Builder {
llbuilder,
- ccx,
+ cx,
}
}
pub fn build_sibling_block<'b>(&self, name: &'b str) -> Builder<'a, 'tcx> {
- Builder::new_block(self.ccx, self.llfn(), name)
+ Builder::new_block(self.cx, self.llfn(), name)
}
pub fn sess(&self) -> &Session {
- self.ccx.sess()
+ self.cx.sess()
}
pub fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx> {
- self.ccx.tcx()
+ self.cx.tcx
}
pub fn llfn(&self) -> ValueRef {
}
fn count_insn(&self, category: &str) {
- if self.ccx.sess().trans_stats() {
- self.ccx.stats().borrow_mut().n_llvm_insns += 1;
+ if self.cx.sess().trans_stats() {
+ self.cx.stats.borrow_mut().n_llvm_insns += 1;
}
- if self.ccx.sess().count_llvm_insns() {
- *self.ccx.stats()
+ if self.cx.sess().count_llvm_insns() {
+ *self.cx.stats
.borrow_mut()
.llvm_insns
.entry(category.to_string())
}
pub fn alloca(&self, ty: Type, name: &str, align: Align) -> ValueRef {
- let builder = Builder::with_ccx(self.ccx);
- builder.position_at_start(unsafe {
+ let bx = Builder::with_cx(self.cx);
+ bx.position_at_start(unsafe {
llvm::LLVMGetFirstBasicBlock(self.llfn())
});
- builder.dynamic_alloca(ty, name, align)
+ bx.dynamic_alloca(ty, name, align)
}
pub fn dynamic_alloca(&self, ty: Type, name: &str, align: Align) -> ValueRef {
];
llvm::LLVMSetMetadata(load, llvm::MD_range as c_uint,
- llvm::LLVMMDNodeInContext(self.ccx.llcx(),
+ llvm::LLVMMDNodeInContext(self.cx.llcx,
v.as_ptr(),
v.len() as c_uint));
}
pub fn nonnull_metadata(&self, load: ValueRef) {
unsafe {
llvm::LLVMSetMetadata(load, llvm::MD_nonnull as c_uint,
- llvm::LLVMMDNodeInContext(self.ccx.llcx(), ptr::null(), 0));
+ llvm::LLVMMDNodeInContext(self.cx.llcx, ptr::null(), 0));
}
}
// point to a metadata value of the integer 1. Who knew?
//
// [1]: http://llvm.org/docs/LangRef.html#store-instruction
- let one = C_i32(self.ccx, 1);
- let node = llvm::LLVMMDNodeInContext(self.ccx.llcx(),
+ let one = C_i32(self.cx, 1);
+ let node = llvm::LLVMMDNodeInContext(self.cx.llcx,
&one,
1);
llvm::LLVMSetMetadata(insn,
}
pub fn add_span_comment(&self, sp: Span, text: &str) {
- if self.ccx.sess().asm_comments() {
+ if self.cx.sess().asm_comments() {
let s = format!("{} ({})",
text,
- self.ccx.sess().codemap().span_to_string(sp));
+ self.cx.sess().codemap().span_to_string(sp));
debug!("{}", s);
self.add_comment(&s);
}
}
pub fn add_comment(&self, text: &str) {
- if self.ccx.sess().asm_comments() {
+ if self.cx.sess().asm_comments() {
let sanitized = text.replace("$", "");
let comment_text = format!("{} {}", "#",
sanitized.replace("\n", "\n\t# "));
self.count_insn("inlineasm");
let comment_text = CString::new(comment_text).unwrap();
let asm = unsafe {
- llvm::LLVMConstInlineAsm(Type::func(&[], &Type::void(self.ccx)).to_ref(),
+ llvm::LLVMConstInlineAsm(Type::func(&[], &Type::void(self.cx)).to_ref(),
comment_text.as_ptr(), noname(), False,
False)
};
unsafe {
let elt_ty = val_ty(elt);
let undef = llvm::LLVMGetUndef(Type::vector(&elt_ty, num_elts as u64).to_ref());
- let vec = self.insert_element(undef, elt, C_i32(self.ccx, 0));
- let vec_i32_ty = Type::vector(&Type::i32(self.ccx), num_elts as u64);
+ let vec = self.insert_element(undef, elt, C_i32(self.cx, 0));
+ let vec_i32_ty = Type::vector(&Type::i32(self.cx), num_elts as u64);
self.shuffle_vector(vec, undef, C_null(vec_i32_ty))
}
}
}
pub fn landing_pad(&self, ty: Type, pers_fn: ValueRef,
- num_clauses: usize,
- llfn: ValueRef) -> ValueRef {
+ num_clauses: usize) -> ValueRef {
self.count_insn("landingpad");
unsafe {
- llvm::LLVMRustBuildLandingPad(self.llbuilder, ty.to_ref(), pers_fn,
- num_clauses as c_uint, noname(), llfn)
+ llvm::LLVMBuildLandingPad(self.llbuilder, ty.to_ref(), pers_fn,
+ num_clauses as c_uint, noname())
}
}
pub fn set_invariant_load(&self, load: ValueRef) {
unsafe {
llvm::LLVMSetMetadata(load, llvm::MD_invariant_load as c_uint,
- llvm::LLVMMDNodeInContext(self.ccx.llcx(), ptr::null(), 0));
+ llvm::LLVMMDNodeInContext(self.cx.llcx, ptr::null(), 0));
}
}
/// If LLVM lifetime intrinsic support is disabled (i.e. optimizations
/// off) or `ptr` is zero-sized, then no-op (does not call `emit`).
fn call_lifetime_intrinsic(&self, intrinsic: &str, ptr: ValueRef, size: Size) {
- if self.ccx.sess().opts.optimize == config::OptLevel::No {
+ if self.cx.sess().opts.optimize == config::OptLevel::No {
return;
}
return;
}
- let lifetime_intrinsic = self.ccx.get_intrinsic(intrinsic);
+ let lifetime_intrinsic = self.cx.get_intrinsic(intrinsic);
- let ptr = self.pointercast(ptr, Type::i8p(self.ccx));
- self.call(lifetime_intrinsic, &[C_u64(self.ccx, size), ptr], None);
+ let ptr = self.pointercast(ptr, Type::i8p(self.cx));
+ self.call(lifetime_intrinsic, &[C_u64(self.cx, size), ptr], None);
}
}
// except according to those terms.
use abi::{FnType, ArgType, LayoutExt, Reg, RegKind, Uniform};
-use context::CrateContext;
+use context::CodegenCx;
-fn is_homogeneous_aggregate<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, arg: &mut ArgType<'tcx>)
+fn is_homogeneous_aggregate<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, arg: &mut ArgType<'tcx>)
-> Option<Uniform> {
- arg.layout.homogeneous_aggregate(ccx).and_then(|unit| {
+ arg.layout.homogeneous_aggregate(cx).and_then(|unit| {
let size = arg.layout.size;
// Ensure we have at most four uniquely addressable members.
- if size > unit.size.checked_mul(4, ccx).unwrap() {
+ if size > unit.size.checked_mul(4, cx).unwrap() {
return None;
}
})
}
-fn classify_ret_ty<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ret: &mut ArgType<'tcx>) {
+fn classify_ret_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, ret: &mut ArgType<'tcx>) {
if !ret.layout.is_aggregate() {
ret.extend_integer_width_to(32);
return;
}
- if let Some(uniform) = is_homogeneous_aggregate(ccx, ret) {
+ if let Some(uniform) = is_homogeneous_aggregate(cx, ret) {
ret.cast_to(uniform);
return;
}
ret.make_indirect();
}
-fn classify_arg_ty<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, arg: &mut ArgType<'tcx>) {
+fn classify_arg_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, arg: &mut ArgType<'tcx>) {
if !arg.layout.is_aggregate() {
arg.extend_integer_width_to(32);
return;
}
- if let Some(uniform) = is_homogeneous_aggregate(ccx, arg) {
+ if let Some(uniform) = is_homogeneous_aggregate(cx, arg) {
arg.cast_to(uniform);
return;
}
arg.make_indirect();
}
-pub fn compute_abi_info<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fty: &mut FnType<'tcx>) {
+pub fn compute_abi_info<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, fty: &mut FnType<'tcx>) {
if !fty.ret.is_ignore() {
- classify_ret_ty(ccx, &mut fty.ret);
+ classify_ret_ty(cx, &mut fty.ret);
}
for arg in &mut fty.args {
if arg.is_ignore() { continue; }
- classify_arg_ty(ccx, arg);
+ classify_arg_ty(cx, arg);
}
}
// except according to those terms.
use abi::{FnType, ArgType, LayoutExt, Reg, RegKind, Uniform};
-use context::CrateContext;
+use context::CodegenCx;
use llvm::CallConv;
-fn is_homogeneous_aggregate<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, arg: &mut ArgType<'tcx>)
+fn is_homogeneous_aggregate<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, arg: &mut ArgType<'tcx>)
-> Option<Uniform> {
- arg.layout.homogeneous_aggregate(ccx).and_then(|unit| {
+ arg.layout.homogeneous_aggregate(cx).and_then(|unit| {
let size = arg.layout.size;
// Ensure we have at most four uniquely addressable members.
- if size > unit.size.checked_mul(4, ccx).unwrap() {
+ if size > unit.size.checked_mul(4, cx).unwrap() {
return None;
}
})
}
-fn classify_ret_ty<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ret: &mut ArgType<'tcx>, vfp: bool) {
+fn classify_ret_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, ret: &mut ArgType<'tcx>, vfp: bool) {
if !ret.layout.is_aggregate() {
ret.extend_integer_width_to(32);
return;
}
if vfp {
- if let Some(uniform) = is_homogeneous_aggregate(ccx, ret) {
+ if let Some(uniform) = is_homogeneous_aggregate(cx, ret) {
ret.cast_to(uniform);
return;
}
ret.make_indirect();
}
-fn classify_arg_ty<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, arg: &mut ArgType<'tcx>, vfp: bool) {
+fn classify_arg_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, arg: &mut ArgType<'tcx>, vfp: bool) {
if !arg.layout.is_aggregate() {
arg.extend_integer_width_to(32);
return;
}
if vfp {
- if let Some(uniform) = is_homogeneous_aggregate(ccx, arg) {
+ if let Some(uniform) = is_homogeneous_aggregate(cx, arg) {
arg.cast_to(uniform);
return;
}
});
}
-pub fn compute_abi_info<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fty: &mut FnType<'tcx>) {
+pub fn compute_abi_info<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, fty: &mut FnType<'tcx>) {
// If this is a target with a hard-float ABI, and the function is not explicitly
// `extern "aapcs"`, then we must use the VFP registers for homogeneous aggregates.
- let vfp = ccx.sess().target.target.llvm_target.ends_with("hf")
+ let vfp = cx.sess().target.target.llvm_target.ends_with("hf")
&& fty.cconv != CallConv::ArmAapcsCallConv
&& !fty.variadic;
if !fty.ret.is_ignore() {
- classify_ret_ty(ccx, &mut fty.ret, vfp);
+ classify_ret_ty(cx, &mut fty.ret, vfp);
}
for arg in &mut fty.args {
if arg.is_ignore() { continue; }
- classify_arg_ty(ccx, arg, vfp);
+ classify_arg_ty(cx, arg, vfp);
}
}
// except according to those terms.
use abi::{FnType, ArgType, LayoutExt, Uniform};
-use context::CrateContext;
+use context::CodegenCx;
// Data layout: e-p:32:32-i64:64-v128:32:128-n32-S128
// See the https://github.com/kripken/emscripten-fastcomp-clang repository.
// The class `EmscriptenABIInfo` in `/lib/CodeGen/TargetInfo.cpp` contains the ABI definitions.
-fn classify_ret_ty<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ret: &mut ArgType<'tcx>) {
+fn classify_ret_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, ret: &mut ArgType<'tcx>) {
if ret.layout.is_aggregate() {
- if let Some(unit) = ret.layout.homogeneous_aggregate(ccx) {
+ if let Some(unit) = ret.layout.homogeneous_aggregate(cx) {
let size = ret.layout.size;
if unit.size == size {
ret.cast_to(Uniform {
}
}
-pub fn compute_abi_info<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fty: &mut FnType<'tcx>) {
+pub fn compute_abi_info<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, fty: &mut FnType<'tcx>) {
if !fty.ret.is_ignore() {
- classify_ret_ty(ccx, &mut fty.ret);
+ classify_ret_ty(cx, &mut fty.ret);
}
for arg in &mut fty.args {
// except according to those terms.
use abi::{ArgType, FnType, LayoutExt, Reg, Uniform};
-use context::CrateContext;
+use context::CodegenCx;
use rustc::ty::layout::Size;
-fn classify_ret_ty<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
+fn classify_ret_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
ret: &mut ArgType<'tcx>,
offset: &mut Size) {
if !ret.layout.is_aggregate() {
ret.extend_integer_width_to(32);
} else {
ret.make_indirect();
- *offset += ccx.tcx().data_layout.pointer_size;
+ *offset += cx.tcx.data_layout.pointer_size;
}
}
-fn classify_arg_ty(ccx: &CrateContext, arg: &mut ArgType, offset: &mut Size) {
- let dl = &ccx.tcx().data_layout;
+fn classify_arg_ty(cx: &CodegenCx, arg: &mut ArgType, offset: &mut Size) {
+ let dl = &cx.tcx.data_layout;
let size = arg.layout.size;
let align = arg.layout.align.max(dl.i32_align).min(dl.i64_align);
*offset = offset.abi_align(align) + size.abi_align(align);
}
-pub fn compute_abi_info<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fty: &mut FnType<'tcx>) {
+pub fn compute_abi_info<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, fty: &mut FnType<'tcx>) {
let mut offset = Size::from_bytes(0);
if !fty.ret.is_ignore() {
- classify_ret_ty(ccx, &mut fty.ret, &mut offset);
+ classify_ret_ty(cx, &mut fty.ret, &mut offset);
}
for arg in &mut fty.args {
if arg.is_ignore() { continue; }
- classify_arg_ty(ccx, arg, &mut offset);
+ classify_arg_ty(cx, arg, &mut offset);
}
}
// except according to those terms.
use abi::{ArgType, FnType, LayoutExt, Reg, Uniform};
-use context::CrateContext;
+use context::CodegenCx;
use rustc::ty::layout::Size;
-fn classify_ret_ty<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
+fn classify_ret_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
ret: &mut ArgType<'tcx>,
offset: &mut Size) {
if !ret.layout.is_aggregate() {
ret.extend_integer_width_to(64);
} else {
ret.make_indirect();
- *offset += ccx.tcx().data_layout.pointer_size;
+ *offset += cx.tcx.data_layout.pointer_size;
}
}
-fn classify_arg_ty(ccx: &CrateContext, arg: &mut ArgType, offset: &mut Size) {
- let dl = &ccx.tcx().data_layout;
+fn classify_arg_ty(cx: &CodegenCx, arg: &mut ArgType, offset: &mut Size) {
+ let dl = &cx.tcx.data_layout;
let size = arg.layout.size;
let align = arg.layout.align.max(dl.i32_align).min(dl.i64_align);
*offset = offset.abi_align(align) + size.abi_align(align);
}
-pub fn compute_abi_info<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fty: &mut FnType<'tcx>) {
+pub fn compute_abi_info<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, fty: &mut FnType<'tcx>) {
let mut offset = Size::from_bytes(0);
if !fty.ret.is_ignore() {
- classify_ret_ty(ccx, &mut fty.ret, &mut offset);
+ classify_ret_ty(cx, &mut fty.ret, &mut offset);
}
for arg in &mut fty.args {
if arg.is_ignore() { continue; }
- classify_arg_ty(ccx, arg, &mut offset);
+ classify_arg_ty(cx, arg, &mut offset);
}
}
// except according to those terms.
use abi::{ArgType, FnType, LayoutExt, Reg, Uniform};
-use context::CrateContext;
+use context::CodegenCx;
use rustc::ty::layout::Size;
-fn classify_ret_ty<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
+fn classify_ret_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
ret: &mut ArgType<'tcx>,
offset: &mut Size) {
if !ret.layout.is_aggregate() {
ret.extend_integer_width_to(32);
} else {
ret.make_indirect();
- *offset += ccx.tcx().data_layout.pointer_size;
+ *offset += cx.tcx.data_layout.pointer_size;
}
}
-fn classify_arg_ty(ccx: &CrateContext, arg: &mut ArgType, offset: &mut Size) {
- let dl = &ccx.tcx().data_layout;
+fn classify_arg_ty(cx: &CodegenCx, arg: &mut ArgType, offset: &mut Size) {
+ let dl = &cx.tcx.data_layout;
let size = arg.layout.size;
let align = arg.layout.align.max(dl.i32_align).min(dl.i64_align);
*offset = offset.abi_align(align) + size.abi_align(align);
}
-pub fn compute_abi_info<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fty: &mut FnType<'tcx>) {
+pub fn compute_abi_info<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, fty: &mut FnType<'tcx>) {
let mut offset = Size::from_bytes(0);
if !fty.ret.is_ignore() {
- classify_ret_ty(ccx, &mut fty.ret, &mut offset);
+ classify_ret_ty(cx, &mut fty.ret, &mut offset);
}
for arg in &mut fty.args {
if arg.is_ignore() { continue; }
- classify_arg_ty(ccx, arg, &mut offset);
+ classify_arg_ty(cx, arg, &mut offset);
}
}
// need to be fixed when PowerPC vector support is added.
use abi::{FnType, ArgType, LayoutExt, Reg, RegKind, Uniform};
-use context::CrateContext;
+use context::CodegenCx;
use rustc::ty::layout;
#[derive(Debug, Clone, Copy, PartialEq)]
}
use self::ABI::*;
-fn is_homogeneous_aggregate<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
+fn is_homogeneous_aggregate<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
arg: &mut ArgType<'tcx>,
abi: ABI)
-> Option<Uniform> {
- arg.layout.homogeneous_aggregate(ccx).and_then(|unit| {
+ arg.layout.homogeneous_aggregate(cx).and_then(|unit| {
// ELFv1 only passes one-member aggregates transparently.
// ELFv2 passes up to eight uniquely addressable members.
if (abi == ELFv1 && arg.layout.size > unit.size)
- || arg.layout.size > unit.size.checked_mul(8, ccx).unwrap() {
+ || arg.layout.size > unit.size.checked_mul(8, cx).unwrap() {
return None;
}
})
}
-fn classify_ret_ty<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ret: &mut ArgType<'tcx>, abi: ABI) {
+fn classify_ret_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, ret: &mut ArgType<'tcx>, abi: ABI) {
if !ret.layout.is_aggregate() {
ret.extend_integer_width_to(64);
return;
return;
}
- if let Some(uniform) = is_homogeneous_aggregate(ccx, ret, abi) {
+ if let Some(uniform) = is_homogeneous_aggregate(cx, ret, abi) {
ret.cast_to(uniform);
return;
}
ret.make_indirect();
}
-fn classify_arg_ty<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, arg: &mut ArgType<'tcx>, abi: ABI) {
+fn classify_arg_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, arg: &mut ArgType<'tcx>, abi: ABI) {
if !arg.layout.is_aggregate() {
arg.extend_integer_width_to(64);
return;
}
- if let Some(uniform) = is_homogeneous_aggregate(ccx, arg, abi) {
+ if let Some(uniform) = is_homogeneous_aggregate(cx, arg, abi) {
arg.cast_to(uniform);
return;
}
});
}
-pub fn compute_abi_info<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fty: &mut FnType<'tcx>) {
- let abi = match ccx.sess().target.target.target_endian.as_str() {
+pub fn compute_abi_info<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, fty: &mut FnType<'tcx>) {
+ let abi = match cx.sess().target.target.target_endian.as_str() {
"big" => ELFv1,
"little" => ELFv2,
_ => unimplemented!(),
};
if !fty.ret.is_ignore() {
- classify_ret_ty(ccx, &mut fty.ret, abi);
+ classify_ret_ty(cx, &mut fty.ret, abi);
}
for arg in &mut fty.args {
if arg.is_ignore() { continue; }
- classify_arg_ty(ccx, arg, abi);
+ classify_arg_ty(cx, arg, abi);
}
}
// for a pre-z13 machine or using -mno-vx.
use abi::{FnType, ArgType, LayoutExt, Reg};
-use context::CrateContext;
+use context::CodegenCx;
use rustc::ty::layout::{self, TyLayout};
}
}
-fn is_single_fp_element<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
+fn is_single_fp_element<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
layout: TyLayout<'tcx>) -> bool {
match layout.abi {
layout::Abi::Scalar(ref scalar) => {
}
layout::Abi::Aggregate { .. } => {
if layout.fields.count() == 1 && layout.fields.offset(0).bytes() == 0 {
- is_single_fp_element(ccx, layout.field(ccx, 0))
+ is_single_fp_element(cx, layout.field(cx, 0))
} else {
false
}
}
}
-fn classify_arg_ty<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, arg: &mut ArgType<'tcx>) {
+fn classify_arg_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, arg: &mut ArgType<'tcx>) {
if !arg.layout.is_aggregate() && arg.layout.size.bits() <= 64 {
arg.extend_integer_width_to(64);
return;
}
- if is_single_fp_element(ccx, arg.layout) {
+ if is_single_fp_element(cx, arg.layout) {
match arg.layout.size.bytes() {
4 => arg.cast_to(Reg::f32()),
8 => arg.cast_to(Reg::f64()),
}
}
-pub fn compute_abi_info<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fty: &mut FnType<'tcx>) {
+pub fn compute_abi_info<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, fty: &mut FnType<'tcx>) {
if !fty.ret.is_ignore() {
classify_ret_ty(&mut fty.ret);
}
for arg in &mut fty.args {
if arg.is_ignore() { continue; }
- classify_arg_ty(ccx, arg);
+ classify_arg_ty(cx, arg);
}
}
// except according to those terms.
use abi::{ArgType, FnType, LayoutExt, Reg, Uniform};
-use context::CrateContext;
+use context::CodegenCx;
use rustc::ty::layout::Size;
-fn classify_ret_ty<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
+fn classify_ret_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
ret: &mut ArgType<'tcx>,
offset: &mut Size) {
if !ret.layout.is_aggregate() {
ret.extend_integer_width_to(32);
} else {
ret.make_indirect();
- *offset += ccx.tcx().data_layout.pointer_size;
+ *offset += cx.tcx.data_layout.pointer_size;
}
}
-fn classify_arg_ty(ccx: &CrateContext, arg: &mut ArgType, offset: &mut Size) {
- let dl = &ccx.tcx().data_layout;
+fn classify_arg_ty(cx: &CodegenCx, arg: &mut ArgType, offset: &mut Size) {
+ let dl = &cx.tcx.data_layout;
let size = arg.layout.size;
let align = arg.layout.align.max(dl.i32_align).min(dl.i64_align);
*offset = offset.abi_align(align) + size.abi_align(align);
}
-pub fn compute_abi_info<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fty: &mut FnType<'tcx>) {
+pub fn compute_abi_info<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, fty: &mut FnType<'tcx>) {
let mut offset = Size::from_bytes(0);
if !fty.ret.is_ignore() {
- classify_ret_ty(ccx, &mut fty.ret, &mut offset);
+ classify_ret_ty(cx, &mut fty.ret, &mut offset);
}
for arg in &mut fty.args {
if arg.is_ignore() { continue; }
- classify_arg_ty(ccx, arg, &mut offset);
+ classify_arg_ty(cx, arg, &mut offset);
}
}
// FIXME: This needs an audit for correctness and completeness.
use abi::{FnType, ArgType, LayoutExt, Reg, RegKind, Uniform};
-use context::CrateContext;
+use context::CodegenCx;
-fn is_homogeneous_aggregate<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, arg: &mut ArgType<'tcx>)
+fn is_homogeneous_aggregate<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, arg: &mut ArgType<'tcx>)
-> Option<Uniform> {
- arg.layout.homogeneous_aggregate(ccx).and_then(|unit| {
+ arg.layout.homogeneous_aggregate(cx).and_then(|unit| {
// Ensure we have at most eight uniquely addressable members.
- if arg.layout.size > unit.size.checked_mul(8, ccx).unwrap() {
+ if arg.layout.size > unit.size.checked_mul(8, cx).unwrap() {
return None;
}
})
}
-fn classify_ret_ty<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ret: &mut ArgType<'tcx>) {
+fn classify_ret_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, ret: &mut ArgType<'tcx>) {
if !ret.layout.is_aggregate() {
ret.extend_integer_width_to(64);
return;
}
- if let Some(uniform) = is_homogeneous_aggregate(ccx, ret) {
+ if let Some(uniform) = is_homogeneous_aggregate(cx, ret) {
ret.cast_to(uniform);
return;
}
ret.make_indirect();
}
-fn classify_arg_ty<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, arg: &mut ArgType<'tcx>) {
+fn classify_arg_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, arg: &mut ArgType<'tcx>) {
if !arg.layout.is_aggregate() {
arg.extend_integer_width_to(64);
return;
}
- if let Some(uniform) = is_homogeneous_aggregate(ccx, arg) {
+ if let Some(uniform) = is_homogeneous_aggregate(cx, arg) {
arg.cast_to(uniform);
return;
}
});
}
-pub fn compute_abi_info<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fty: &mut FnType<'tcx>) {
+pub fn compute_abi_info<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, fty: &mut FnType<'tcx>) {
if !fty.ret.is_ignore() {
- classify_ret_ty(ccx, &mut fty.ret);
+ classify_ret_ty(cx, &mut fty.ret);
}
for arg in &mut fty.args {
if arg.is_ignore() { continue; }
- classify_arg_ty(ccx, arg);
+ classify_arg_ty(cx, arg);
}
}
// except according to those terms.
use abi::{ArgAttribute, FnType, LayoutExt, PassMode, Reg, RegKind};
-use common::CrateContext;
+use common::CodegenCx;
use rustc::ty::layout::{self, TyLayout};
Fastcall
}
-fn is_single_fp_element<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
+fn is_single_fp_element<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
layout: TyLayout<'tcx>) -> bool {
match layout.abi {
layout::Abi::Scalar(ref scalar) => {
}
layout::Abi::Aggregate { .. } => {
if layout.fields.count() == 1 && layout.fields.offset(0).bytes() == 0 {
- is_single_fp_element(ccx, layout.field(ccx, 0))
+ is_single_fp_element(cx, layout.field(cx, 0))
} else {
false
}
}
}
-pub fn compute_abi_info<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
+pub fn compute_abi_info<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
fty: &mut FnType<'tcx>,
flavor: Flavor) {
if !fty.ret.is_ignore() {
// Some links:
// http://www.angelcode.com/dev/callconv/callconv.html
// Clang's ABI handling is in lib/CodeGen/TargetInfo.cpp
- let t = &ccx.sess().target.target;
+ let t = &cx.sess().target.target;
if t.options.is_like_osx || t.options.is_like_windows
|| t.options.is_like_openbsd {
// According to Clang, everyone but MSVC returns single-element
// float aggregates directly in a floating-point register.
- if !t.options.is_like_msvc && is_single_fp_element(ccx, fty.ret.layout) {
+ if !t.options.is_like_msvc && is_single_fp_element(cx, fty.ret.layout) {
match fty.ret.layout.size.bytes() {
4 => fty.ret.cast_to(Reg::f32()),
8 => fty.ret.cast_to(Reg::f64()),
};
// At this point we know this must be a primitive of sorts.
- let unit = arg.layout.homogeneous_aggregate(ccx).unwrap();
+ let unit = arg.layout.homogeneous_aggregate(cx).unwrap();
assert_eq!(unit.size, arg.layout.size);
if unit.kind == RegKind::Float {
continue;
// https://github.com/jckarter/clay/blob/master/compiler/src/externals.cpp
use abi::{ArgType, CastTarget, FnType, LayoutExt, Reg, RegKind};
-use context::CrateContext;
+use context::CodegenCx;
use rustc::ty::layout::{self, TyLayout, Size};
const LARGEST_VECTOR_SIZE: usize = 512;
const MAX_EIGHTBYTES: usize = LARGEST_VECTOR_SIZE / 64;
-fn classify_arg<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, arg: &ArgType<'tcx>)
+fn classify_arg<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, arg: &ArgType<'tcx>)
-> Result<[Class; MAX_EIGHTBYTES], Memory> {
fn unify(cls: &mut [Class],
off: Size,
cls[i] = to_write;
}
- fn classify<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
+ fn classify<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
layout: TyLayout<'tcx>,
cls: &mut [Class],
off: Size)
// everything after the first one is the upper
// half of a register.
- let stride = element.value.size(ccx);
+ let stride = element.value.size(cx);
for i in 1..count {
let field_off = off + stride * i;
unify(cls, field_off, Class::SseUp);
layout::Variants::Single { .. } => {
for i in 0..layout.fields.count() {
let field_off = off + layout.fields.offset(i);
- classify(ccx, layout.field(ccx, i), cls, field_off)?;
+ classify(cx, layout.field(cx, i), cls, field_off)?;
}
}
layout::Variants::Tagged { .. } |
}
let mut cls = [Class::None; MAX_EIGHTBYTES];
- classify(ccx, arg.layout, &mut cls, Size::from_bytes(0))?;
+ classify(cx, arg.layout, &mut cls, Size::from_bytes(0))?;
if n > 2 {
if cls[0] != Class::Sse {
return Err(Memory);
target
}
-pub fn compute_abi_info<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fty: &mut FnType<'tcx>) {
+pub fn compute_abi_info<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, fty: &mut FnType<'tcx>) {
let mut int_regs = 6; // RDI, RSI, RDX, RCX, R8, R9
let mut sse_regs = 8; // XMM0-7
let mut x86_64_ty = |arg: &mut ArgType<'tcx>, is_arg: bool| {
- let cls = classify_arg(ccx, arg);
+ let cls = classify_arg(cx, arg);
let mut needed_int = 0;
let mut needed_sse = 0;
//! closure.
use attributes;
-use common::{self, CrateContext};
+use common::{self, CodegenCx};
use consts;
use declare;
use llvm::{self, ValueRef};
///
/// # Parameters
///
-/// - `ccx`: the crate context
+/// - `cx`: the crate context
/// - `instance`: the instance to be instantiated
-pub fn get_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
+pub fn get_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
instance: Instance<'tcx>)
-> ValueRef
{
- let tcx = ccx.tcx();
+ let tcx = cx.tcx;
debug!("get_fn(instance={:?})", instance);
assert!(!instance.substs.has_escaping_regions());
assert!(!instance.substs.has_param_types());
- let fn_ty = instance.ty(ccx.tcx());
- if let Some(&llfn) = ccx.instances().borrow().get(&instance) {
+ let fn_ty = instance.ty(cx.tcx);
+ if let Some(&llfn) = cx.instances.borrow().get(&instance) {
return llfn;
}
debug!("get_fn({:?}: {:?}) => {}", instance, fn_ty, sym);
// Create a fn pointer with the substituted signature.
- let fn_ptr_ty = tcx.mk_fn_ptr(common::ty_fn_sig(ccx, fn_ty));
- let llptrty = ccx.layout_of(fn_ptr_ty).llvm_type(ccx);
+ let fn_ptr_ty = tcx.mk_fn_ptr(common::ty_fn_sig(cx, fn_ty));
+ let llptrty = cx.layout_of(fn_ptr_ty).llvm_type(cx);
- let llfn = if let Some(llfn) = declare::get_declared_value(ccx, &sym) {
+ let llfn = if let Some(llfn) = declare::get_declared_value(cx, &sym) {
// This is subtle and surprising, but sometimes we have to bitcast
// the resulting fn pointer. The reason has to do with external
// functions. If you have two crates that both bind the same C
llfn
}
} else {
- let llfn = declare::declare_fn(ccx, &sym, fn_ty);
+ let llfn = declare::declare_fn(cx, &sym, fn_ty);
assert_eq!(common::val_ty(llfn), llptrty);
debug!("get_fn: not casting pointer!");
if instance.def.is_inline(tcx) {
attributes::inline(llfn, attributes::InlineAttr::Hint);
}
- let attrs = instance.def.attrs(ccx.tcx());
- attributes::from_fn_attrs(ccx, &attrs, llfn);
+ attributes::from_fn_attrs(cx, llfn, instance.def.def_id());
let instance_def_id = instance.def_id();
unsafe {
llvm::LLVMRustSetLinkage(llfn, llvm::Linkage::ExternalLinkage);
- if ccx.tcx().is_translated_function(instance_def_id) {
+ if cx.tcx.is_translated_function(instance_def_id) {
if instance_def_id.is_local() {
- if !ccx.tcx().is_exported_symbol(instance_def_id) {
+ if !cx.tcx.is_exported_symbol(instance_def_id) {
llvm::LLVMRustSetVisibility(llfn, llvm::Visibility::Hidden);
}
} else {
}
}
- if ccx.use_dll_storage_attrs() &&
+ if cx.use_dll_storage_attrs &&
tcx.is_dllimport_foreign_item(instance_def_id)
{
unsafe {
llfn
};
- ccx.instances().borrow_mut().insert(instance, llfn);
+ cx.instances.borrow_mut().insert(instance, llfn);
llfn
}
-pub fn resolve_and_get_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
+pub fn resolve_and_get_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
def_id: DefId,
substs: &'tcx Substs<'tcx>)
-> ValueRef
{
get_fn(
- ccx,
+ cx,
ty::Instance::resolve(
- ccx.tcx(),
+ cx.tcx,
ty::ParamEnv::empty(traits::Reveal::All),
def_id,
substs
use syntax::symbol::InternedString;
use syntax_pos::{Span, DUMMY_SP};
-pub use context::{CrateContext, SharedCrateContext};
+pub use context::CodegenCx;
pub fn type_needs_drop<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty: Ty<'tcx>) -> bool {
ty.needs_drop(tcx, ty::ParamEnv::empty(traits::Reveal::All))
}
}
-pub fn C_bool(ccx: &CrateContext, val: bool) -> ValueRef {
- C_uint(Type::i1(ccx), val as u64)
+pub fn C_bool(cx: &CodegenCx, val: bool) -> ValueRef {
+ C_uint(Type::i1(cx), val as u64)
}
-pub fn C_i32(ccx: &CrateContext, i: i32) -> ValueRef {
- C_int(Type::i32(ccx), i as i64)
+pub fn C_i32(cx: &CodegenCx, i: i32) -> ValueRef {
+ C_int(Type::i32(cx), i as i64)
}
-pub fn C_u32(ccx: &CrateContext, i: u32) -> ValueRef {
- C_uint(Type::i32(ccx), i as u64)
+pub fn C_u32(cx: &CodegenCx, i: u32) -> ValueRef {
+ C_uint(Type::i32(cx), i as u64)
}
-pub fn C_u64(ccx: &CrateContext, i: u64) -> ValueRef {
- C_uint(Type::i64(ccx), i)
+pub fn C_u64(cx: &CodegenCx, i: u64) -> ValueRef {
+ C_uint(Type::i64(cx), i)
}
-pub fn C_usize(ccx: &CrateContext, i: u64) -> ValueRef {
- let bit_size = ccx.data_layout().pointer_size.bits();
+pub fn C_usize(cx: &CodegenCx, i: u64) -> ValueRef {
+ let bit_size = cx.data_layout().pointer_size.bits();
if bit_size < 64 {
// make sure it doesn't overflow
assert!(i < (1<<bit_size));
}
- C_uint(ccx.isize_ty(), i)
+ C_uint(cx.isize_ty, i)
}
-pub fn C_u8(ccx: &CrateContext, i: u8) -> ValueRef {
- C_uint(Type::i8(ccx), i as u64)
+pub fn C_u8(cx: &CodegenCx, i: u8) -> ValueRef {
+ C_uint(Type::i8(cx), i as u64)
}
// This is a 'c-like' raw string, which differs from
// our boxed-and-length-annotated strings.
-pub fn C_cstr(cx: &CrateContext, s: InternedString, null_terminated: bool) -> ValueRef {
+pub fn C_cstr(cx: &CodegenCx, s: InternedString, null_terminated: bool) -> ValueRef {
unsafe {
- if let Some(&llval) = cx.const_cstr_cache().borrow().get(&s) {
+ if let Some(&llval) = cx.const_cstr_cache.borrow().get(&s) {
return llval;
}
- let sc = llvm::LLVMConstStringInContext(cx.llcx(),
+ let sc = llvm::LLVMConstStringInContext(cx.llcx,
s.as_ptr() as *const c_char,
s.len() as c_uint,
!null_terminated as Bool);
llvm::LLVMSetGlobalConstant(g, True);
llvm::LLVMRustSetLinkage(g, llvm::Linkage::InternalLinkage);
- cx.const_cstr_cache().borrow_mut().insert(s, g);
+ cx.const_cstr_cache.borrow_mut().insert(s, g);
g
}
}
// NB: Do not use `do_spill_noroot` to make this into a constant string, or
// you will be kicked off fast isel. See issue #4352 for an example of this.
-pub fn C_str_slice(cx: &CrateContext, s: InternedString) -> ValueRef {
+pub fn C_str_slice(cx: &CodegenCx, s: InternedString) -> ValueRef {
let len = s.len();
let cs = consts::ptrcast(C_cstr(cx, s, false),
- cx.layout_of(cx.tcx().mk_str()).llvm_type(cx).ptr_to());
+ cx.layout_of(cx.tcx.mk_str()).llvm_type(cx).ptr_to());
C_fat_ptr(cx, cs, C_usize(cx, len as u64))
}
-pub fn C_fat_ptr(cx: &CrateContext, ptr: ValueRef, meta: ValueRef) -> ValueRef {
+pub fn C_fat_ptr(cx: &CodegenCx, ptr: ValueRef, meta: ValueRef) -> ValueRef {
assert_eq!(abi::FAT_PTR_ADDR, 0);
assert_eq!(abi::FAT_PTR_EXTRA, 1);
C_struct(cx, &[ptr, meta], false)
}
-pub fn C_struct(cx: &CrateContext, elts: &[ValueRef], packed: bool) -> ValueRef {
- C_struct_in_context(cx.llcx(), elts, packed)
+pub fn C_struct(cx: &CodegenCx, elts: &[ValueRef], packed: bool) -> ValueRef {
+ C_struct_in_context(cx.llcx, elts, packed)
}
pub fn C_struct_in_context(llcx: ContextRef, elts: &[ValueRef], packed: bool) -> ValueRef {
}
}
-pub fn C_bytes(cx: &CrateContext, bytes: &[u8]) -> ValueRef {
- C_bytes_in_context(cx.llcx(), bytes)
+pub fn C_bytes(cx: &CodegenCx, bytes: &[u8]) -> ValueRef {
+ C_bytes_in_context(cx.llcx, bytes)
}
pub fn C_bytes_in_context(llcx: ContextRef, bytes: &[u8]) -> ValueRef {
// of Java. (See related discussion on #1877 and #10183.)
pub fn build_unchecked_lshift<'a, 'tcx>(
- bcx: &Builder<'a, 'tcx>,
+ bx: &Builder<'a, 'tcx>,
lhs: ValueRef,
rhs: ValueRef
) -> ValueRef {
- let rhs = base::cast_shift_expr_rhs(bcx, hir::BinOp_::BiShl, lhs, rhs);
+ let rhs = base::cast_shift_expr_rhs(bx, hir::BinOp_::BiShl, lhs, rhs);
// #1877, #10183: Ensure that input is always valid
- let rhs = shift_mask_rhs(bcx, rhs);
- bcx.shl(lhs, rhs)
+ let rhs = shift_mask_rhs(bx, rhs);
+ bx.shl(lhs, rhs)
}
pub fn build_unchecked_rshift<'a, 'tcx>(
- bcx: &Builder<'a, 'tcx>, lhs_t: Ty<'tcx>, lhs: ValueRef, rhs: ValueRef
+ bx: &Builder<'a, 'tcx>, lhs_t: Ty<'tcx>, lhs: ValueRef, rhs: ValueRef
) -> ValueRef {
- let rhs = base::cast_shift_expr_rhs(bcx, hir::BinOp_::BiShr, lhs, rhs);
+ let rhs = base::cast_shift_expr_rhs(bx, hir::BinOp_::BiShr, lhs, rhs);
// #1877, #10183: Ensure that input is always valid
- let rhs = shift_mask_rhs(bcx, rhs);
+ let rhs = shift_mask_rhs(bx, rhs);
let is_signed = lhs_t.is_signed();
if is_signed {
- bcx.ashr(lhs, rhs)
+ bx.ashr(lhs, rhs)
} else {
- bcx.lshr(lhs, rhs)
+ bx.lshr(lhs, rhs)
}
}
-fn shift_mask_rhs<'a, 'tcx>(bcx: &Builder<'a, 'tcx>, rhs: ValueRef) -> ValueRef {
+fn shift_mask_rhs<'a, 'tcx>(bx: &Builder<'a, 'tcx>, rhs: ValueRef) -> ValueRef {
let rhs_llty = val_ty(rhs);
- bcx.and(rhs, shift_mask_val(bcx, rhs_llty, rhs_llty, false))
+ bx.and(rhs, shift_mask_val(bx, rhs_llty, rhs_llty, false))
}
pub fn shift_mask_val<'a, 'tcx>(
- bcx: &Builder<'a, 'tcx>,
+ bx: &Builder<'a, 'tcx>,
llty: Type,
mask_llty: Type,
invert: bool
}
},
TypeKind::Vector => {
- let mask = shift_mask_val(bcx, llty.element_type(), mask_llty.element_type(), invert);
- bcx.vector_splat(mask_llty.vector_length(), mask)
+ let mask = shift_mask_val(bx, llty.element_type(), mask_llty.element_type(), invert);
+ bx.vector_splat(mask_llty.vector_length(), mask)
},
_ => bug!("shift_mask_val: expected Integer or Vector, found {:?}", kind),
}
}
-pub fn ty_fn_sig<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
+pub fn ty_fn_sig<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
ty: Ty<'tcx>)
-> ty::PolyFnSig<'tcx>
{
match ty.sty {
ty::TyFnDef(..) |
// Shims currently have type TyFnPtr. Not sure this should remain.
- ty::TyFnPtr(_) => ty.fn_sig(ccx.tcx()),
+ ty::TyFnPtr(_) => ty.fn_sig(cx.tcx),
ty::TyClosure(def_id, substs) => {
- let tcx = ccx.tcx();
+ let tcx = cx.tcx;
let sig = substs.closure_sig(def_id, tcx);
let env_ty = tcx.closure_env_ty(def_id, substs).unwrap();
))
}
ty::TyGenerator(def_id, substs, _) => {
- let tcx = ccx.tcx();
- let sig = substs.generator_poly_sig(def_id, ccx.tcx());
+ let tcx = cx.tcx;
+ let sig = substs.generator_poly_sig(def_id, cx.tcx);
let env_region = ty::ReLateBound(ty::DebruijnIndex::new(1), ty::BrEnv);
let env_ty = tcx.mk_mut_ref(tcx.mk_region(env_region), ty);
use debuginfo;
use base;
use monomorphize::{MonoItem, MonoItemExt};
-use common::{CrateContext, val_ty};
+use common::{CodegenCx, val_ty};
use declare;
use monomorphize::Instance;
use type_::Type;
}
}
-fn set_global_alignment(ccx: &CrateContext,
+fn set_global_alignment(cx: &CodegenCx,
gv: ValueRef,
mut align: Align) {
// The target may require greater alignment for globals than the type does.
// Note: GCC and Clang also allow `__attribute__((aligned))` on variables,
// which can force it to be smaller. Rust doesn't support this yet.
- if let Some(min) = ccx.sess().target.target.options.min_global_align {
+ if let Some(min) = cx.sess().target.target.options.min_global_align {
match ty::layout::Align::from_bits(min, min) {
Ok(min) => align = align.max(min),
Err(err) => {
- ccx.sess().err(&format!("invalid minimum global alignment: {}", err));
+ cx.sess().err(&format!("invalid minimum global alignment: {}", err));
}
}
}
}
}
-pub fn addr_of_mut(ccx: &CrateContext,
+pub fn addr_of_mut(cx: &CodegenCx,
cv: ValueRef,
align: Align,
kind: &str)
-> ValueRef {
unsafe {
- let name = ccx.generate_local_symbol_name(kind);
- let gv = declare::define_global(ccx, &name[..], val_ty(cv)).unwrap_or_else(||{
+ let name = cx.generate_local_symbol_name(kind);
+ let gv = declare::define_global(cx, &name[..], val_ty(cv)).unwrap_or_else(||{
bug!("symbol `{}` is already defined", name);
});
llvm::LLVMSetInitializer(gv, cv);
- set_global_alignment(ccx, gv, align);
+ set_global_alignment(cx, gv, align);
llvm::LLVMRustSetLinkage(gv, llvm::Linkage::PrivateLinkage);
SetUnnamedAddr(gv, true);
gv
}
}
-pub fn addr_of(ccx: &CrateContext,
+pub fn addr_of(cx: &CodegenCx,
cv: ValueRef,
align: Align,
kind: &str)
-> ValueRef {
- if let Some(&gv) = ccx.const_globals().borrow().get(&cv) {
+ if let Some(&gv) = cx.const_globals.borrow().get(&cv) {
unsafe {
// Upgrade the alignment in cases where the same constant is used with different
// alignment requirements
}
return gv;
}
- let gv = addr_of_mut(ccx, cv, align, kind);
+ let gv = addr_of_mut(cx, cv, align, kind);
unsafe {
llvm::LLVMSetGlobalConstant(gv, True);
}
- ccx.const_globals().borrow_mut().insert(cv, gv);
+ cx.const_globals.borrow_mut().insert(cv, gv);
gv
}
-pub fn get_static(ccx: &CrateContext, def_id: DefId) -> ValueRef {
- let instance = Instance::mono(ccx.tcx(), def_id);
- if let Some(&g) = ccx.instances().borrow().get(&instance) {
+pub fn get_static(cx: &CodegenCx, def_id: DefId) -> ValueRef {
+ let instance = Instance::mono(cx.tcx, def_id);
+ if let Some(&g) = cx.instances.borrow().get(&instance) {
return g;
}
- let ty = instance.ty(ccx.tcx());
- let g = if let Some(id) = ccx.tcx().hir.as_local_node_id(def_id) {
+ let ty = instance.ty(cx.tcx);
+ let g = if let Some(id) = cx.tcx.hir.as_local_node_id(def_id) {
- let llty = ccx.layout_of(ty).llvm_type(ccx);
- let (g, attrs) = match ccx.tcx().hir.get(id) {
+ let llty = cx.layout_of(ty).llvm_type(cx);
+ let (g, attrs) = match cx.tcx.hir.get(id) {
hir_map::NodeItem(&hir::Item {
ref attrs, span, node: hir::ItemStatic(..), ..
}) => {
- let sym = MonoItem::Static(id).symbol_name(ccx.tcx());
+ let sym = MonoItem::Static(id).symbol_name(cx.tcx);
- let defined_in_current_codegen_unit = ccx.codegen_unit()
+ let defined_in_current_codegen_unit = cx.codegen_unit
.items()
.contains_key(&MonoItem::Static(id));
assert!(!defined_in_current_codegen_unit);
- if declare::get_declared_value(ccx, &sym[..]).is_some() {
+ if declare::get_declared_value(cx, &sym[..]).is_some() {
span_bug!(span, "trans: Conflicting symbol names for static?");
}
- let g = declare::define_global(ccx, &sym[..], llty).unwrap();
+ let g = declare::define_global(cx, &sym[..], llty).unwrap();
- if !ccx.tcx().is_exported_symbol(def_id) {
+ if !cx.tcx.is_exported_symbol(def_id) {
unsafe {
llvm::LLVMRustSetVisibility(g, llvm::Visibility::Hidden);
}
hir_map::NodeForeignItem(&hir::ForeignItem {
ref attrs, span, node: hir::ForeignItemStatic(..), ..
}) => {
- let sym = ccx.tcx().symbol_name(instance);
+ let sym = cx.tcx.symbol_name(instance);
let g = if let Some(name) =
attr::first_attr_value_str_by_name(&attrs, "linkage") {
// If this is a static with a linkage specified, then we need to handle
let linkage = match base::linkage_by_name(&name.as_str()) {
Some(linkage) => linkage,
None => {
- ccx.sess().span_fatal(span, "invalid linkage specified");
+ cx.sess().span_fatal(span, "invalid linkage specified");
}
};
let llty2 = match ty.sty {
- ty::TyRawPtr(ref mt) => ccx.layout_of(mt.ty).llvm_type(ccx),
+ ty::TyRawPtr(ref mt) => cx.layout_of(mt.ty).llvm_type(cx),
_ => {
- ccx.sess().span_fatal(span, "must have type `*const T` or `*mut T`");
+ cx.sess().span_fatal(span, "must have type `*const T` or `*mut T`");
}
};
unsafe {
// Declare a symbol `foo` with the desired linkage.
- let g1 = declare::declare_global(ccx, &sym, llty2);
+ let g1 = declare::declare_global(cx, &sym, llty2);
llvm::LLVMRustSetLinkage(g1, base::linkage_to_llvm(linkage));
// Declare an internal global `extern_with_linkage_foo` which
// zero.
let mut real_name = "_rust_extern_with_linkage_".to_string();
real_name.push_str(&sym);
- let g2 = declare::define_global(ccx, &real_name, llty).unwrap_or_else(||{
- ccx.sess().span_fatal(span,
+ let g2 = declare::define_global(cx, &real_name, llty).unwrap_or_else(||{
+ cx.sess().span_fatal(span,
&format!("symbol `{}` is already defined", &sym))
});
llvm::LLVMRustSetLinkage(g2, llvm::Linkage::InternalLinkage);
}
} else {
// Generate an external declaration.
- declare::declare_global(ccx, &sym, llty)
+ declare::declare_global(cx, &sym, llty)
};
(g, attrs)
for attr in attrs {
if attr.check_name("thread_local") {
- llvm::set_thread_local_mode(g, ccx.tls_model());
+ llvm::set_thread_local_mode(g, cx.tls_model);
}
}
g
} else {
- let sym = ccx.tcx().symbol_name(instance);
+ let sym = cx.tcx.symbol_name(instance);
// FIXME(nagisa): perhaps the map of externs could be offloaded to llvm somehow?
// FIXME(nagisa): investigate whether it can be changed into define_global
- let g = declare::declare_global(ccx, &sym, ccx.layout_of(ty).llvm_type(ccx));
+ let g = declare::declare_global(cx, &sym, cx.layout_of(ty).llvm_type(cx));
// Thread-local statics in some other crate need to *always* be linked
// against in a thread-local fashion, so we need to be sure to apply the
// thread-local attribute locally if it was present remotely. If we
// don't do this then linker errors can be generated where the linker
// complains that one object files has a thread local version of the
// symbol and another one doesn't.
- for attr in ccx.tcx().get_attrs(def_id).iter() {
+ for attr in cx.tcx.get_attrs(def_id).iter() {
if attr.check_name("thread_local") {
- llvm::set_thread_local_mode(g, ccx.tls_model());
+ llvm::set_thread_local_mode(g, cx.tls_model);
}
}
- if ccx.use_dll_storage_attrs() && !ccx.tcx().is_foreign_item(def_id) {
+ if cx.use_dll_storage_attrs && !cx.tcx.is_foreign_item(def_id) {
// This item is external but not foreign, i.e. it originates from an external Rust
// crate. Since we don't know whether this crate will be linked dynamically or
// statically in the final application, we always mark such symbols as 'dllimport'.
g
};
- if ccx.use_dll_storage_attrs() && ccx.tcx().is_dllimport_foreign_item(def_id) {
+ if cx.use_dll_storage_attrs && cx.tcx.is_dllimport_foreign_item(def_id) {
// For foreign (native) libs we know the exact storage type to use.
unsafe {
llvm::LLVMSetDLLStorageClass(g, llvm::DLLStorageClass::DllImport);
}
}
- ccx.instances().borrow_mut().insert(instance, g);
- ccx.statics().borrow_mut().insert(g, def_id);
+ cx.instances.borrow_mut().insert(instance, g);
+ cx.statics.borrow_mut().insert(g, def_id);
g
}
-pub fn trans_static<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
+pub fn trans_static<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
m: hir::Mutability,
id: ast::NodeId,
attrs: &[ast::Attribute])
-> Result<ValueRef, ConstEvalErr<'tcx>> {
unsafe {
- let def_id = ccx.tcx().hir.local_def_id(id);
- let g = get_static(ccx, def_id);
+ let def_id = cx.tcx.hir.local_def_id(id);
+ let g = get_static(cx, def_id);
- let v = ::mir::trans_static_initializer(ccx, def_id)?;
+ let v = ::mir::trans_static_initializer(cx, def_id)?;
// boolean SSA values are i1, but they have to be stored in i8 slots,
// otherwise some LLVM optimization passes don't work as expected
let mut val_llty = val_ty(v);
- let v = if val_llty == Type::i1(ccx) {
- val_llty = Type::i8(ccx);
+ let v = if val_llty == Type::i1(cx) {
+ val_llty = Type::i8(cx);
llvm::LLVMConstZExt(v, val_llty.to_ref())
} else {
v
};
- let instance = Instance::mono(ccx.tcx(), def_id);
- let ty = instance.ty(ccx.tcx());
- let llty = ccx.layout_of(ty).llvm_type(ccx);
+ let instance = Instance::mono(cx.tcx, def_id);
+ let ty = instance.ty(cx.tcx);
+ let llty = cx.layout_of(ty).llvm_type(cx);
let g = if val_llty == llty {
g
} else {
let visibility = llvm::LLVMRustGetVisibility(g);
let new_g = llvm::LLVMRustGetOrInsertGlobal(
- ccx.llmod(), name_string.as_ptr(), val_llty.to_ref());
+ cx.llmod, name_string.as_ptr(), val_llty.to_ref());
llvm::LLVMRustSetLinkage(new_g, linkage);
llvm::LLVMRustSetVisibility(new_g, visibility);
// To avoid breaking any invariants, we leave around the old
// global for the moment; we'll replace all references to it
// with the new global later. (See base::trans_crate.)
- ccx.statics_to_rauw().borrow_mut().push((g, new_g));
+ cx.statics_to_rauw.borrow_mut().push((g, new_g));
new_g
};
- set_global_alignment(ccx, g, ccx.align_of(ty));
+ set_global_alignment(cx, g, cx.align_of(ty));
llvm::LLVMSetInitializer(g, v);
// As an optimization, all shared statics which do not have interior
// mutability are placed into read-only memory.
if m != hir::MutMutable {
- if ccx.shared().type_is_freeze(ty) {
+ if cx.type_is_freeze(ty) {
llvm::LLVMSetGlobalConstant(g, llvm::True);
}
}
- debuginfo::create_global_var_metadata(ccx, id, g);
+ debuginfo::create_global_var_metadata(cx, id, g);
if attr::contains_name(attrs, "thread_local") {
- llvm::set_thread_local_mode(g, ccx.tls_model());
+ llvm::set_thread_local_mode(g, cx.tls_model);
}
- base::set_link_section(ccx, g, attrs);
+ base::set_link_section(cx, g, attrs);
if attr::contains_name(attrs, "used") {
// This static will be stored in the llvm.used variable which is an array of i8*
- let cast = llvm::LLVMConstPointerCast(g, Type::i8p(ccx).to_ref());
- ccx.used_statics().borrow_mut().push(cast);
+ let cast = llvm::LLVMConstPointerCast(g, Type::i8p(cx).to_ref());
+ cx.used_statics.borrow_mut().push(cast);
}
Ok(g)
use common;
use llvm;
use llvm::{ContextRef, ModuleRef, ValueRef};
-use rustc::dep_graph::{DepGraph, DepGraphSafe};
+use rustc::dep_graph::DepGraphSafe;
use rustc::hir;
use rustc::hir::def_id::DefId;
-use rustc::ich::StableHashingContext;
use rustc::traits;
use debuginfo;
use callee;
use rustc_data_structures::base_n;
use rustc::mir::mono::Stats;
-use rustc_data_structures::stable_hasher::StableHashingContextProvider;
use rustc::session::config::{self, NoDebugInfo};
use rustc::session::Session;
use rustc::ty::layout::{LayoutError, LayoutOf, Size, TyLayout};
use std::iter;
use std::str;
use std::sync::Arc;
-use std::marker::PhantomData;
use syntax::symbol::InternedString;
use abi::Abi;
-/// The shared portion of a `CrateContext`. There is one `SharedCrateContext`
-/// per crate. The data here is shared between all compilation units of the
-/// crate, so it must not contain references to any LLVM data structures
-/// (aside from metadata-related ones).
-pub struct SharedCrateContext<'a, 'tcx: 'a> {
- tcx: TyCtxt<'a, 'tcx, 'tcx>,
- check_overflow: bool,
- use_dll_storage_attrs: bool,
- tls_model: llvm::ThreadLocalMode,
-}
+/// There is one `CodegenCx` per compilation unit. Each one has its own LLVM
+/// `ContextRef` so that several compilation units may be optimized in parallel.
+/// All other LLVM data structures in the `CodegenCx` are tied to that `ContextRef`.
+pub struct CodegenCx<'a, 'tcx: 'a> {
+ pub tcx: TyCtxt<'a, 'tcx, 'tcx>,
+ pub check_overflow: bool,
+ pub use_dll_storage_attrs: bool,
+ pub tls_model: llvm::ThreadLocalMode,
-/// The local portion of a `CrateContext`. There is one `LocalCrateContext`
-/// per compilation unit. Each one has its own LLVM `ContextRef` so that
-/// several compilation units may be optimized in parallel. All other LLVM
-/// data structures in the `LocalCrateContext` are tied to that `ContextRef`.
-pub struct LocalCrateContext<'a, 'tcx: 'a> {
- llmod: ModuleRef,
- llcx: ContextRef,
- stats: RefCell<Stats>,
- codegen_unit: Arc<CodegenUnit<'tcx>>,
+ pub llmod: ModuleRef,
+ pub llcx: ContextRef,
+ pub stats: RefCell<Stats>,
+ pub codegen_unit: Arc<CodegenUnit<'tcx>>,
/// Cache instances of monomorphic and polymorphic items
- instances: RefCell<FxHashMap<Instance<'tcx>, ValueRef>>,
+ pub instances: RefCell<FxHashMap<Instance<'tcx>, ValueRef>>,
/// Cache generated vtables
- vtables: RefCell<FxHashMap<(Ty<'tcx>,
+ pub vtables: RefCell<FxHashMap<(Ty<'tcx>,
Option<ty::PolyExistentialTraitRef<'tcx>>), ValueRef>>,
/// Cache of constant strings,
- const_cstr_cache: RefCell<FxHashMap<InternedString, ValueRef>>,
+ pub const_cstr_cache: RefCell<FxHashMap<InternedString, ValueRef>>,
/// Reverse-direction for const ptrs cast from globals.
/// Key is a ValueRef holding a *T,
/// when we ptrcast, and we have to ptrcast during translation
/// of a [T] const because we form a slice, a (*T,usize) pair, not
/// a pointer to an LLVM array type. Similar for trait objects.
- const_unsized: RefCell<FxHashMap<ValueRef, ValueRef>>,
+ pub const_unsized: RefCell<FxHashMap<ValueRef, ValueRef>>,
/// Cache of emitted const globals (value -> global)
- const_globals: RefCell<FxHashMap<ValueRef, ValueRef>>,
+ pub const_globals: RefCell<FxHashMap<ValueRef, ValueRef>>,
/// Mapping from static definitions to their DefId's.
- statics: RefCell<FxHashMap<ValueRef, DefId>>,
+ pub statics: RefCell<FxHashMap<ValueRef, DefId>>,
/// List of globals for static variables which need to be passed to the
/// LLVM function ReplaceAllUsesWith (RAUW) when translation is complete.
/// (We have to make sure we don't invalidate any ValueRefs referring
/// to constants.)
- statics_to_rauw: RefCell<Vec<(ValueRef, ValueRef)>>,
+ pub statics_to_rauw: RefCell<Vec<(ValueRef, ValueRef)>>,
/// Statics that will be placed in the llvm.used variable
/// See http://llvm.org/docs/LangRef.html#the-llvm-used-global-variable for details
- used_statics: RefCell<Vec<ValueRef>>,
+ pub used_statics: RefCell<Vec<ValueRef>>,
- lltypes: RefCell<FxHashMap<(Ty<'tcx>, Option<usize>), Type>>,
- scalar_lltypes: RefCell<FxHashMap<Ty<'tcx>, Type>>,
- pointee_infos: RefCell<FxHashMap<(Ty<'tcx>, Size), Option<PointeeInfo>>>,
- isize_ty: Type,
+ pub lltypes: RefCell<FxHashMap<(Ty<'tcx>, Option<usize>), Type>>,
+ pub scalar_lltypes: RefCell<FxHashMap<Ty<'tcx>, Type>>,
+ pub pointee_infos: RefCell<FxHashMap<(Ty<'tcx>, Size), Option<PointeeInfo>>>,
+ pub isize_ty: Type,
- dbg_cx: Option<debuginfo::CrateDebugContext<'tcx>>,
+ pub dbg_cx: Option<debuginfo::CrateDebugContext<'tcx>>,
eh_personality: Cell<Option<ValueRef>>,
eh_unwind_resume: Cell<Option<ValueRef>>,
- rust_try_fn: Cell<Option<ValueRef>>,
+ pub rust_try_fn: Cell<Option<ValueRef>>,
intrinsics: RefCell<FxHashMap<&'static str, ValueRef>>,
/// A counter that is used for generating local symbol names
local_gen_sym_counter: Cell<usize>,
-
- /// A placeholder so we can add lifetimes
- placeholder: PhantomData<&'a ()>,
-}
-
-/// A CrateContext value binds together one LocalCrateContext with the
-/// SharedCrateContext. It exists as a convenience wrapper, so we don't have to
-/// pass around (SharedCrateContext, LocalCrateContext) tuples all over trans.
-pub struct CrateContext<'a, 'tcx: 'a> {
- shared: &'a SharedCrateContext<'a, 'tcx>,
- local_ccx: &'a LocalCrateContext<'a, 'tcx>,
-}
-
-impl<'a, 'tcx> CrateContext<'a, 'tcx> {
- pub fn new(shared: &'a SharedCrateContext<'a, 'tcx>,
- local_ccx: &'a LocalCrateContext<'a, 'tcx>)
- -> Self {
- CrateContext { shared, local_ccx }
- }
-}
-
-impl<'a, 'tcx> DepGraphSafe for CrateContext<'a, 'tcx> {
-}
-
-impl<'a, 'tcx> DepGraphSafe for SharedCrateContext<'a, 'tcx> {
}
-impl<'a, 'tcx> StableHashingContextProvider for SharedCrateContext<'a, 'tcx> {
- type ContextType = StableHashingContext<'tcx>;
-
- fn create_stable_hashing_context(&self) -> Self::ContextType {
- self.tcx.create_stable_hashing_context()
- }
+impl<'a, 'tcx> DepGraphSafe for CodegenCx<'a, 'tcx> {
}
pub fn get_reloc_model(sess: &Session) -> llvm::RelocMode {
}
pub unsafe fn create_context_and_module(sess: &Session, mod_name: &str) -> (ContextRef, ModuleRef) {
- let llcx = llvm::LLVMContextCreate();
+ let llcx = llvm::LLVMRustContextCreate(sess.fewer_names());
let mod_name = CString::new(mod_name).unwrap();
let llmod = llvm::LLVMModuleCreateWithNameInContext(mod_name.as_ptr(), llcx);
(llcx, llmod)
}
-impl<'b, 'tcx> SharedCrateContext<'b, 'tcx> {
- pub fn new(tcx: TyCtxt<'b, 'tcx, 'tcx>) -> SharedCrateContext<'b, 'tcx> {
+impl<'a, 'tcx> CodegenCx<'a, 'tcx> {
+ pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+ codegen_unit: Arc<CodegenUnit<'tcx>>,
+ llmod_id: &str)
+ -> CodegenCx<'a, 'tcx> {
// An interesting part of Windows which MSVC forces our hand on (and
// apparently MinGW didn't) is the usage of `dllimport` and `dllexport`
// attributes in LLVM IR as well as native dependencies (in C these
let tls_model = get_tls_model(&tcx.sess);
- SharedCrateContext {
- tcx,
- check_overflow,
- use_dll_storage_attrs,
- tls_model,
- }
- }
-
- pub fn type_needs_drop(&self, ty: Ty<'tcx>) -> bool {
- common::type_needs_drop(self.tcx, ty)
- }
-
- pub fn type_is_sized(&self, ty: Ty<'tcx>) -> bool {
- common::type_is_sized(self.tcx, ty)
- }
-
- pub fn type_is_freeze(&self, ty: Ty<'tcx>) -> bool {
- common::type_is_freeze(self.tcx, ty)
- }
-
- pub fn type_has_metadata(&self, ty: Ty<'tcx>) -> bool {
- use syntax_pos::DUMMY_SP;
- if ty.is_sized(self.tcx, ty::ParamEnv::empty(traits::Reveal::All), DUMMY_SP) {
- return false;
- }
-
- let tail = self.tcx.struct_tail(ty);
- match tail.sty {
- ty::TyForeign(..) => false,
- ty::TyStr | ty::TySlice(..) | ty::TyDynamic(..) => true,
- _ => bug!("unexpected unsized tail: {:?}", tail.sty),
- }
- }
-
- pub fn tcx(&self) -> TyCtxt<'b, 'tcx, 'tcx> {
- self.tcx
- }
-
- pub fn sess<'a>(&'a self) -> &'a Session {
- &self.tcx.sess
- }
-
- pub fn dep_graph<'a>(&'a self) -> &'a DepGraph {
- &self.tcx.dep_graph
- }
-
- pub fn use_dll_storage_attrs(&self) -> bool {
- self.use_dll_storage_attrs
- }
-}
-
-impl<'a, 'tcx> LocalCrateContext<'a, 'tcx> {
- pub fn new(shared: &SharedCrateContext<'a, 'tcx>,
- codegen_unit: Arc<CodegenUnit<'tcx>>,
- llmod_id: &str)
- -> LocalCrateContext<'a, 'tcx> {
unsafe {
- let (llcx, llmod) = create_context_and_module(&shared.tcx.sess,
+ let (llcx, llmod) = create_context_and_module(&tcx.sess,
&llmod_id[..]);
- let dbg_cx = if shared.tcx.sess.opts.debuginfo != NoDebugInfo {
+ let dbg_cx = if tcx.sess.opts.debuginfo != NoDebugInfo {
let dctx = debuginfo::CrateDebugContext::new(llmod);
- debuginfo::metadata::compile_unit_metadata(shared,
+ debuginfo::metadata::compile_unit_metadata(tcx,
codegen_unit.name(),
- &dctx,
- shared.tcx.sess);
+ &dctx);
Some(dctx)
} else {
None
};
- let local_ccx = LocalCrateContext {
+ let mut cx = CodegenCx {
+ tcx,
+ check_overflow,
+ use_dll_storage_attrs,
+ tls_model,
llmod,
llcx,
stats: RefCell::new(Stats::default()),
rust_try_fn: Cell::new(None),
intrinsics: RefCell::new(FxHashMap()),
local_gen_sym_counter: Cell::new(0),
- placeholder: PhantomData,
};
-
- let (isize_ty, mut local_ccx) = {
- // Do a little dance to create a dummy CrateContext, so we can
- // create some things in the LLVM module of this codegen unit
- let mut local_ccxs = vec![local_ccx];
- let isize_ty = {
- let dummy_ccx = LocalCrateContext::dummy_ccx(shared,
- local_ccxs.as_mut_slice());
- Type::isize(&dummy_ccx)
- };
- (isize_ty, local_ccxs.pop().unwrap())
- };
-
- local_ccx.isize_ty = isize_ty;
-
- local_ccx
- }
- }
-
- /// Create a dummy `CrateContext` from `self` and the provided
- /// `SharedCrateContext`. This is somewhat dangerous because `self` may
- /// not be fully initialized.
- ///
- /// This is used in the `LocalCrateContext` constructor to allow calling
- /// functions that expect a complete `CrateContext`, even before the local
- /// portion is fully initialized and attached to the `SharedCrateContext`.
- fn dummy_ccx(shared: &'a SharedCrateContext<'a, 'tcx>,
- local_ccxs: &'a [LocalCrateContext<'a, 'tcx>])
- -> CrateContext<'a, 'tcx> {
- assert!(local_ccxs.len() == 1);
- CrateContext {
- shared,
- local_ccx: &local_ccxs[0]
+ cx.isize_ty = Type::isize(&cx);
+ cx
}
}
}
}
-impl<'b, 'tcx> CrateContext<'b, 'tcx> {
- pub fn shared(&self) -> &'b SharedCrateContext<'b, 'tcx> {
- self.shared
- }
-
- fn local(&self) -> &'b LocalCrateContext<'b, 'tcx> {
- self.local_ccx
- }
-
- pub fn tcx(&self) -> TyCtxt<'b, 'tcx, 'tcx> {
- self.shared.tcx
- }
-
+impl<'b, 'tcx> CodegenCx<'b, 'tcx> {
pub fn sess<'a>(&'a self) -> &'a Session {
- &self.shared.tcx.sess
+ &self.tcx.sess
}
pub fn get_intrinsic(&self, key: &str) -> ValueRef {
- if let Some(v) = self.intrinsics().borrow().get(key).cloned() {
+ if let Some(v) = self.intrinsics.borrow().get(key).cloned() {
return v;
}
match declare_intrinsic(self, key) {
}
}
- pub fn llmod(&self) -> ModuleRef {
- self.local().llmod
- }
-
- pub fn llcx(&self) -> ContextRef {
- self.local().llcx
- }
-
- pub fn codegen_unit(&self) -> &CodegenUnit<'tcx> {
- &self.local().codegen_unit
- }
-
- pub fn td(&self) -> llvm::TargetDataRef {
- unsafe { llvm::LLVMRustGetModuleDataLayout(self.llmod()) }
- }
-
- pub fn instances<'a>(&'a self) -> &'a RefCell<FxHashMap<Instance<'tcx>, ValueRef>> {
- &self.local().instances
- }
-
- pub fn vtables<'a>(&'a self)
- -> &'a RefCell<FxHashMap<(Ty<'tcx>,
- Option<ty::PolyExistentialTraitRef<'tcx>>), ValueRef>> {
- &self.local().vtables
- }
-
- pub fn const_cstr_cache<'a>(&'a self) -> &'a RefCell<FxHashMap<InternedString, ValueRef>> {
- &self.local().const_cstr_cache
- }
-
- pub fn const_unsized<'a>(&'a self) -> &'a RefCell<FxHashMap<ValueRef, ValueRef>> {
- &self.local().const_unsized
- }
-
- pub fn const_globals<'a>(&'a self) -> &'a RefCell<FxHashMap<ValueRef, ValueRef>> {
- &self.local().const_globals
- }
-
- pub fn statics<'a>(&'a self) -> &'a RefCell<FxHashMap<ValueRef, DefId>> {
- &self.local().statics
- }
-
- pub fn statics_to_rauw<'a>(&'a self) -> &'a RefCell<Vec<(ValueRef, ValueRef)>> {
- &self.local().statics_to_rauw
- }
-
- pub fn used_statics<'a>(&'a self) -> &'a RefCell<Vec<ValueRef>> {
- &self.local().used_statics
- }
-
- pub fn lltypes<'a>(&'a self) -> &'a RefCell<FxHashMap<(Ty<'tcx>, Option<usize>), Type>> {
- &self.local().lltypes
- }
-
- pub fn scalar_lltypes<'a>(&'a self) -> &'a RefCell<FxHashMap<Ty<'tcx>, Type>> {
- &self.local().scalar_lltypes
- }
-
- pub fn pointee_infos<'a>(&'a self)
- -> &'a RefCell<FxHashMap<(Ty<'tcx>, Size), Option<PointeeInfo>>> {
- &self.local().pointee_infos
- }
-
- pub fn stats<'a>(&'a self) -> &'a RefCell<Stats> {
- &self.local().stats
- }
-
- pub fn isize_ty(&self) -> Type {
- self.local().isize_ty
- }
-
- pub fn dbg_cx<'a>(&'a self) -> &'a Option<debuginfo::CrateDebugContext<'tcx>> {
- &self.local().dbg_cx
- }
-
- pub fn rust_try_fn<'a>(&'a self) -> &'a Cell<Option<ValueRef>> {
- &self.local().rust_try_fn
- }
-
- fn intrinsics<'a>(&'a self) -> &'a RefCell<FxHashMap<&'static str, ValueRef>> {
- &self.local().intrinsics
- }
-
- pub fn check_overflow(&self) -> bool {
- self.shared.check_overflow
- }
-
- pub fn use_dll_storage_attrs(&self) -> bool {
- self.shared.use_dll_storage_attrs()
- }
-
- pub fn tls_model(&self) -> llvm::ThreadLocalMode {
- self.shared.tls_model
- }
-
/// Generate a new symbol name with the given prefix. This symbol name must
/// only be used for definitions with `internal` or `private` linkage.
pub fn generate_local_symbol_name(&self, prefix: &str) -> String {
- let idx = self.local().local_gen_sym_counter.get();
- self.local().local_gen_sym_counter.set(idx + 1);
+ let idx = self.local_gen_sym_counter.get();
+ self.local_gen_sym_counter.set(idx + 1);
// Include a '.' character, so there can be no accidental conflicts with
// user defined names
let mut name = String::with_capacity(prefix.len() + 6);
name.push_str(prefix);
name.push_str(".");
- base_n::push_str(idx as u64, base_n::ALPHANUMERIC_ONLY, &mut name);
+ base_n::push_str(idx as u128, base_n::ALPHANUMERIC_ONLY, &mut name);
name
}
// `rust_eh_personality` function, but rather we wired it up to the
// CRT's custom personality function, which forces LLVM to consider
// landing pads as "landing pads for SEH".
- if let Some(llpersonality) = self.local().eh_personality.get() {
+ if let Some(llpersonality) = self.eh_personality.get() {
return llpersonality
}
- let tcx = self.tcx();
+ let tcx = self.tcx;
let llfn = match tcx.lang_items().eh_personality() {
Some(def_id) if !base::wants_msvc_seh(self.sess()) => {
callee::resolve_and_get_fn(self, def_id, tcx.intern_substs(&[]))
declare::declare_cfn(self, name, fty)
}
};
- self.local().eh_personality.set(Some(llfn));
+ self.eh_personality.set(Some(llfn));
llfn
}
// otherwise declares it as an external function.
pub fn eh_unwind_resume(&self) -> ValueRef {
use attributes;
- let unwresume = &self.local().eh_unwind_resume;
+ let unwresume = &self.eh_unwind_resume;
if let Some(llfn) = unwresume.get() {
return llfn;
}
- let tcx = self.tcx();
+ let tcx = self.tcx;
assert!(self.sess().target.target.options.custom_unwind_resume);
if let Some(def_id) = tcx.lang_items().eh_unwind_resume() {
let llfn = callee::resolve_and_get_fn(self, def_id, tcx.intern_substs(&[]));
unwresume.set(Some(llfn));
llfn
}
-}
-impl<'a, 'tcx> ty::layout::HasDataLayout for &'a SharedCrateContext<'a, 'tcx> {
- fn data_layout(&self) -> &ty::layout::TargetDataLayout {
- &self.tcx.data_layout
+ pub fn type_needs_drop(&self, ty: Ty<'tcx>) -> bool {
+ common::type_needs_drop(self.tcx, ty)
}
-}
-impl<'a, 'tcx> ty::layout::HasTyCtxt<'tcx> for &'a SharedCrateContext<'a, 'tcx> {
- fn tcx<'b>(&'b self) -> TyCtxt<'b, 'tcx, 'tcx> {
- self.tcx
+ pub fn type_is_sized(&self, ty: Ty<'tcx>) -> bool {
+ common::type_is_sized(self.tcx, ty)
+ }
+
+ pub fn type_is_freeze(&self, ty: Ty<'tcx>) -> bool {
+ common::type_is_freeze(self.tcx, ty)
+ }
+
+ pub fn type_has_metadata(&self, ty: Ty<'tcx>) -> bool {
+ use syntax_pos::DUMMY_SP;
+ if ty.is_sized(self.tcx, ty::ParamEnv::empty(traits::Reveal::All), DUMMY_SP) {
+ return false;
+ }
+
+ let tail = self.tcx.struct_tail(ty);
+ match tail.sty {
+ ty::TyForeign(..) => false,
+ ty::TyStr | ty::TySlice(..) | ty::TyDynamic(..) => true,
+ _ => bug!("unexpected unsized tail: {:?}", tail.sty),
+ }
}
}
-impl<'a, 'tcx> ty::layout::HasDataLayout for &'a CrateContext<'a, 'tcx> {
+impl<'a, 'tcx> ty::layout::HasDataLayout for &'a CodegenCx<'a, 'tcx> {
fn data_layout(&self) -> &ty::layout::TargetDataLayout {
- &self.shared.tcx.data_layout
+ &self.tcx.data_layout
}
}
-impl<'a, 'tcx> ty::layout::HasTyCtxt<'tcx> for &'a CrateContext<'a, 'tcx> {
+impl<'a, 'tcx> ty::layout::HasTyCtxt<'tcx> for &'a CodegenCx<'a, 'tcx> {
fn tcx<'b>(&'b self) -> TyCtxt<'b, 'tcx, 'tcx> {
- self.shared.tcx
+ self.tcx
}
}
-impl<'a, 'tcx> LayoutOf<Ty<'tcx>> for &'a SharedCrateContext<'a, 'tcx> {
+impl<'a, 'tcx> LayoutOf<Ty<'tcx>> for &'a CodegenCx<'a, 'tcx> {
type TyLayout = TyLayout<'tcx>;
fn layout_of(self, ty: Ty<'tcx>) -> Self::TyLayout {
}
}
-impl<'a, 'tcx> LayoutOf<Ty<'tcx>> for &'a CrateContext<'a, 'tcx> {
- type TyLayout = TyLayout<'tcx>;
-
-
- fn layout_of(self, ty: Ty<'tcx>) -> Self::TyLayout {
- self.shared.layout_of(ty)
- }
-}
-
/// Declare any llvm intrinsics that you might need
-fn declare_intrinsic(ccx: &CrateContext, key: &str) -> Option<ValueRef> {
+fn declare_intrinsic(cx: &CodegenCx, key: &str) -> Option<ValueRef> {
macro_rules! ifn {
($name:expr, fn() -> $ret:expr) => (
if key == $name {
- let f = declare::declare_cfn(ccx, $name, Type::func(&[], &$ret));
+ let f = declare::declare_cfn(cx, $name, Type::func(&[], &$ret));
llvm::SetUnnamedAddr(f, false);
- ccx.intrinsics().borrow_mut().insert($name, f.clone());
+ cx.intrinsics.borrow_mut().insert($name, f.clone());
return Some(f);
}
);
($name:expr, fn(...) -> $ret:expr) => (
if key == $name {
- let f = declare::declare_cfn(ccx, $name, Type::variadic_func(&[], &$ret));
+ let f = declare::declare_cfn(cx, $name, Type::variadic_func(&[], &$ret));
llvm::SetUnnamedAddr(f, false);
- ccx.intrinsics().borrow_mut().insert($name, f.clone());
+ cx.intrinsics.borrow_mut().insert($name, f.clone());
return Some(f);
}
);
($name:expr, fn($($arg:expr),*) -> $ret:expr) => (
if key == $name {
- let f = declare::declare_cfn(ccx, $name, Type::func(&[$($arg),*], &$ret));
+ let f = declare::declare_cfn(cx, $name, Type::func(&[$($arg),*], &$ret));
llvm::SetUnnamedAddr(f, false);
- ccx.intrinsics().borrow_mut().insert($name, f.clone());
+ cx.intrinsics.borrow_mut().insert($name, f.clone());
return Some(f);
}
);
}
macro_rules! mk_struct {
- ($($field_ty:expr),*) => (Type::struct_(ccx, &[$($field_ty),*], false))
+ ($($field_ty:expr),*) => (Type::struct_(cx, &[$($field_ty),*], false))
}
- let i8p = Type::i8p(ccx);
- let void = Type::void(ccx);
- let i1 = Type::i1(ccx);
- let t_i8 = Type::i8(ccx);
- let t_i16 = Type::i16(ccx);
- let t_i32 = Type::i32(ccx);
- let t_i64 = Type::i64(ccx);
- let t_i128 = Type::i128(ccx);
- let t_f32 = Type::f32(ccx);
- let t_f64 = Type::f64(ccx);
+ let i8p = Type::i8p(cx);
+ let void = Type::void(cx);
+ let i1 = Type::i1(cx);
+ let t_i8 = Type::i8(cx);
+ let t_i16 = Type::i16(cx);
+ let t_i32 = Type::i32(cx);
+ let t_i64 = Type::i64(cx);
+ let t_i128 = Type::i128(cx);
+ let t_f32 = Type::f32(cx);
+ let t_f64 = Type::f64(cx);
ifn!("llvm.memcpy.p0i8.p0i8.i16", fn(i8p, i8p, t_i16, t_i32, i1) -> void);
ifn!("llvm.memcpy.p0i8.p0i8.i32", fn(i8p, i8p, t_i32, t_i32, i1) -> void);
ifn!("llvm.assume", fn(i1) -> void);
ifn!("llvm.prefetch", fn(i8p, t_i32, t_i32, t_i32) -> void);
- if ccx.sess().opts.debuginfo != NoDebugInfo {
- ifn!("llvm.dbg.declare", fn(Type::metadata(ccx), Type::metadata(ccx)) -> void);
- ifn!("llvm.dbg.value", fn(Type::metadata(ccx), t_i64, Type::metadata(ccx)) -> void);
+ if cx.sess().opts.debuginfo != NoDebugInfo {
+ ifn!("llvm.dbg.declare", fn(Type::metadata(cx), Type::metadata(cx)) -> void);
+ ifn!("llvm.dbg.value", fn(Type::metadata(cx), t_i64, Type::metadata(cx)) -> void);
}
return None;
}
use llvm;
use llvm::debuginfo::DIScope;
-use common::CrateContext;
+use common::CodegenCx;
use rustc::mir::{Mir, VisibilityScope};
use libc::c_uint;
/// Produce DIScope DIEs for each MIR Scope which has variables defined in it.
/// If debuginfo is disabled, the returned vector is empty.
-pub fn create_mir_scopes(ccx: &CrateContext, mir: &Mir, debug_context: &FunctionDebugContext)
+pub fn create_mir_scopes(cx: &CodegenCx, mir: &Mir, debug_context: &FunctionDebugContext)
-> IndexVec<VisibilityScope, MirDebugScope> {
let null_scope = MirDebugScope {
scope_metadata: ptr::null_mut(),
// Instantiate all scopes.
for idx in 0..mir.visibility_scopes.len() {
let scope = VisibilityScope::new(idx);
- make_mir_scope(ccx, &mir, &has_variables, debug_context, scope, &mut scopes);
+ make_mir_scope(cx, &mir, &has_variables, debug_context, scope, &mut scopes);
}
scopes
}
-fn make_mir_scope(ccx: &CrateContext,
+fn make_mir_scope(cx: &CodegenCx,
mir: &Mir,
has_variables: &BitVector,
debug_context: &FunctionDebugContextData,
let scope_data = &mir.visibility_scopes[scope];
let parent_scope = if let Some(parent) = scope_data.parent_scope {
- make_mir_scope(ccx, mir, has_variables, debug_context, parent, scopes);
+ make_mir_scope(cx, mir, has_variables, debug_context, parent, scopes);
scopes[parent]
} else {
// The root is the function itself.
- let loc = span_start(ccx, mir.span);
+ let loc = span_start(cx, mir.span);
scopes[scope] = MirDebugScope {
scope_metadata: debug_context.fn_metadata,
file_start_pos: loc.file.start_pos,
}
}
- let loc = span_start(ccx, scope_data.span);
- let file_metadata = file_metadata(ccx,
+ let loc = span_start(cx, scope_data.span);
+ let file_metadata = file_metadata(cx,
&loc.file.name,
debug_context.defining_crate);
let scope_metadata = unsafe {
llvm::LLVMRustDIBuilderCreateLexicalBlock(
- DIB(ccx),
+ DIB(cx),
parent_scope.scope_metadata,
file_metadata,
loc.line as c_uint,
//! The public API of the module is a set of functions that will insert the
//! correct metadata into the LLVM IR when called with the right parameters.
//! The module is thus driven from an outside client with functions like
-//! `debuginfo::create_local_var_metadata(bcx: block, local: &ast::local)`.
+//! `debuginfo::create_local_var_metadata(bx: block, local: &ast::local)`.
//!
//! Internally the module will try to reuse already created metadata by
//! utilizing a cache. The way to get a shared metadata node when needed is
//! that exact file path.
//!
//! All private state used by the module is stored within either the
-//! CrateDebugContext struct (owned by the CrateContext) or the
-//! FunctionDebugContext (owned by the MirContext).
+//! CrateDebugContext struct (owned by the CodegenCx) or the
+//! FunctionDebugContext (owned by the FunctionCx).
//!
//! This file consists of three conceptual sections:
//! 1. The public interface of the module
use llvm;
-use common::{C_bytes, CrateContext, C_i32};
+use common::{C_bytes, CodegenCx, C_i32};
use builder::Builder;
use declare;
use type_::Type;
/// Inserts a side-effect free instruction sequence that makes sure that the
/// .debug_gdb_scripts global is referenced, so it isn't removed by the linker.
-pub fn insert_reference_to_gdb_debug_scripts_section_global(ccx: &CrateContext, builder: &Builder) {
- if needs_gdb_debug_scripts_section(ccx) {
- let gdb_debug_scripts_section_global = get_or_insert_gdb_debug_scripts_section_global(ccx);
+pub fn insert_reference_to_gdb_debug_scripts_section_global(bx: &Builder) {
+ if needs_gdb_debug_scripts_section(bx.cx) {
+ let gdb_debug_scripts_section = get_or_insert_gdb_debug_scripts_section_global(bx.cx);
// Load just the first byte as that's all that's necessary to force
// LLVM to keep around the reference to the global.
- let indices = [C_i32(ccx, 0), C_i32(ccx, 0)];
- let element = builder.inbounds_gep(gdb_debug_scripts_section_global, &indices);
- let volative_load_instruction = builder.volatile_load(element);
+ let indices = [C_i32(bx.cx, 0), C_i32(bx.cx, 0)];
+ let element = bx.inbounds_gep(gdb_debug_scripts_section, &indices);
+ let volative_load_instruction = bx.volatile_load(element);
unsafe {
llvm::LLVMSetAlignment(volative_load_instruction, 1);
}
/// Allocates the global variable responsible for the .debug_gdb_scripts binary
/// section.
-pub fn get_or_insert_gdb_debug_scripts_section_global(ccx: &CrateContext)
+pub fn get_or_insert_gdb_debug_scripts_section_global(cx: &CodegenCx)
-> llvm::ValueRef {
let c_section_var_name = "__rustc_debug_gdb_scripts_section__\0";
let section_var_name = &c_section_var_name[..c_section_var_name.len()-1];
let section_var = unsafe {
- llvm::LLVMGetNamedGlobal(ccx.llmod(),
+ llvm::LLVMGetNamedGlobal(cx.llmod,
c_section_var_name.as_ptr() as *const _)
};
let section_contents = b"\x01gdb_load_rust_pretty_printers.py\0";
unsafe {
- let llvm_type = Type::array(&Type::i8(ccx),
+ let llvm_type = Type::array(&Type::i8(cx),
section_contents.len() as u64);
- let section_var = declare::define_global(ccx, section_var_name,
+ let section_var = declare::define_global(cx, section_var_name,
llvm_type).unwrap_or_else(||{
bug!("symbol `{}` is already defined", section_var_name)
});
llvm::LLVMSetSection(section_var, section_name.as_ptr() as *const _);
- llvm::LLVMSetInitializer(section_var, C_bytes(ccx, section_contents));
+ llvm::LLVMSetInitializer(section_var, C_bytes(cx, section_contents));
llvm::LLVMSetGlobalConstant(section_var, llvm::True);
llvm::LLVMSetUnnamedAddr(section_var, llvm::True);
llvm::LLVMRustSetLinkage(section_var, llvm::Linkage::LinkOnceODRLinkage);
}
}
-pub fn needs_gdb_debug_scripts_section(ccx: &CrateContext) -> bool {
+pub fn needs_gdb_debug_scripts_section(cx: &CodegenCx) -> bool {
let omit_gdb_pretty_printer_section =
- attr::contains_name(&ccx.tcx().hir.krate_attrs(),
+ attr::contains_name(&cx.tcx.hir.krate_attrs(),
"omit_gdb_pretty_printer_section");
!omit_gdb_pretty_printer_section &&
- !ccx.sess().target.target.options.is_like_osx &&
- !ccx.sess().target.target.options.is_like_windows &&
- ccx.sess().opts.debuginfo != NoDebugInfo
+ !cx.sess().target.target.options.is_like_osx &&
+ !cx.sess().target.target.options.is_like_windows &&
+ cx.sess().opts.debuginfo != NoDebugInfo
}
use super::type_names::compute_debuginfo_type_name;
use super::{CrateDebugContext};
use abi;
-use context::SharedCrateContext;
use llvm::{self, ValueRef};
use llvm::debuginfo::{DIType, DIFile, DIScope, DIDescriptor,
use rustc::ty::util::TypeIdHasher;
use rustc::ich::Fingerprint;
use rustc::ty::Instance;
-use common::CrateContext;
-use rustc::ty::{self, AdtKind, Ty};
+use common::CodegenCx;
+use rustc::ty::{self, AdtKind, Ty, TyCtxt};
use rustc::ty::layout::{self, Align, LayoutOf, Size, TyLayout};
-use rustc::session::{Session, config};
+use rustc::session::config;
use rustc::util::nodemap::FxHashMap;
use rustc::util::common::path2cstr;
// Get the UniqueTypeId for the given type. If the UniqueTypeId for the given
// type has been requested before, this is just a table lookup. Otherwise an
// ID will be generated and stored for later lookup.
- fn get_unique_type_id_of_type<'a>(&mut self, cx: &CrateContext<'a, 'tcx>,
+ fn get_unique_type_id_of_type<'a>(&mut self, cx: &CodegenCx<'a, 'tcx>,
type_: Ty<'tcx>) -> UniqueTypeId {
// Let's see if we already have something in the cache
match self.type_to_unique_id.get(&type_).cloned() {
// The hasher we are using to generate the UniqueTypeId. We want
// something that provides more than the 64 bits of the DefaultHasher.
- let mut type_id_hasher = TypeIdHasher::<Fingerprint>::new(cx.tcx());
+ let mut type_id_hasher = TypeIdHasher::<Fingerprint>::new(cx.tcx);
type_id_hasher.visit_ty(type_);
let unique_type_id = type_id_hasher.finish().to_hex();
// types of their own, so they need special handling. We still need a
// UniqueTypeId for them, since to debuginfo they *are* real types.
fn get_unique_type_id_of_enum_variant<'a>(&mut self,
- cx: &CrateContext<'a, 'tcx>,
+ cx: &CodegenCx<'a, 'tcx>,
enum_type: Ty<'tcx>,
variant_name: &str)
-> UniqueTypeId {
}
fn create_and_register_recursive_type_forward_declaration<'a, 'tcx>(
- cx: &CrateContext<'a, 'tcx>,
+ cx: &CodegenCx<'a, 'tcx>,
unfinished_type: Ty<'tcx>,
unique_type_id: UniqueTypeId,
metadata_stub: DICompositeType,
// Finishes up the description of the type in question (mostly by providing
// descriptions of the fields of the given type) and returns the final type
// metadata.
- fn finalize<'a>(&self, cx: &CrateContext<'a, 'tcx>) -> MetadataCreationResult {
+ fn finalize<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> MetadataCreationResult {
match *self {
FinalMetadata(metadata) => MetadataCreationResult::new(metadata, false),
UnfinishedMetadata {
)
}
-fn fixed_vec_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
+fn fixed_vec_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
unique_type_id: UniqueTypeId,
array_or_slice_type: Ty<'tcx>,
element_type: Ty<'tcx>,
return MetadataCreationResult::new(metadata, false);
}
-fn vec_slice_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
+fn vec_slice_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
slice_ptr_type: Ty<'tcx>,
element_type: Ty<'tcx>,
unique_type_id: UniqueTypeId,
span: Span)
-> MetadataCreationResult {
- let data_ptr_type = cx.tcx().mk_imm_ptr(element_type);
+ let data_ptr_type = cx.tcx.mk_imm_ptr(element_type);
let data_ptr_metadata = type_metadata(cx, data_ptr_type, span);
let slice_type_name = compute_debuginfo_type_name(cx, slice_ptr_type, true);
let (pointer_size, pointer_align) = cx.size_and_align_of(data_ptr_type);
- let (usize_size, usize_align) = cx.size_and_align_of(cx.tcx().types.usize);
+ let (usize_size, usize_align) = cx.size_and_align_of(cx.tcx.types.usize);
let member_descriptions = [
MemberDescription {
},
MemberDescription {
name: "length".to_string(),
- type_metadata: type_metadata(cx, cx.tcx().types.usize, span),
+ type_metadata: type_metadata(cx, cx.tcx.types.usize, span),
offset: pointer_size,
size: usize_size,
align: usize_align,
MetadataCreationResult::new(metadata, false)
}
-fn subroutine_type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
+fn subroutine_type_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
unique_type_id: UniqueTypeId,
signature: ty::PolyFnSig<'tcx>,
span: Span)
-> MetadataCreationResult
{
- let signature = cx.tcx().erase_late_bound_regions_and_normalize(&signature);
+ let signature = cx.tcx.erase_late_bound_regions_and_normalize(&signature);
let mut signature_metadata: Vec<DIType> = Vec::with_capacity(signature.inputs().len() + 1);
// trait_type should be the actual trait (e.g., Trait). Where the trait is part
// of a DST struct, there is no trait_object_type and the results of this
// function will be a little bit weird.
-fn trait_pointer_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
+fn trait_pointer_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
trait_type: Ty<'tcx>,
trait_object_type: Option<Ty<'tcx>>,
unique_type_id: UniqueTypeId)
let file_metadata = unknown_file_metadata(cx);
- let layout = cx.layout_of(cx.tcx().mk_mut_ptr(trait_type));
+ let layout = cx.layout_of(cx.tcx.mk_mut_ptr(trait_type));
assert_eq!(abi::FAT_PTR_ADDR, 0);
assert_eq!(abi::FAT_PTR_EXTRA, 1);
MemberDescription {
name: "pointer".to_string(),
type_metadata: type_metadata(cx,
- cx.tcx().mk_mut_ptr(cx.tcx().types.u8),
+ cx.tcx.mk_mut_ptr(cx.tcx.types.u8),
syntax_pos::DUMMY_SP),
offset: layout.fields.offset(0),
size: data_ptr_field.size,
syntax_pos::DUMMY_SP)
}
-pub fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
+pub fn type_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
t: Ty<'tcx>,
usage_site_span: Span)
-> DIType {
Ok(vec_slice_metadata(cx, t, typ, unique_type_id, usage_site_span))
}
ty::TyStr => {
- Ok(vec_slice_metadata(cx, t, cx.tcx().types.u8, unique_type_id, usage_site_span))
+ Ok(vec_slice_metadata(cx, t, cx.tcx.types.u8, unique_type_id, usage_site_span))
}
ty::TyDynamic(..) => {
Ok(MetadataCreationResult::new(
fixed_vec_metadata(cx, unique_type_id, t, typ, usage_site_span)
}
ty::TyStr => {
- fixed_vec_metadata(cx, unique_type_id, t, cx.tcx().types.i8, usage_site_span)
+ fixed_vec_metadata(cx, unique_type_id, t, cx.tcx.types.i8, usage_site_span)
}
ty::TyDynamic(..) => {
MetadataCreationResult::new(
ty::TyFnDef(..) | ty::TyFnPtr(_) => {
let fn_metadata = subroutine_type_metadata(cx,
unique_type_id,
- t.fn_sig(cx.tcx()),
+ t.fn_sig(cx.tcx),
usage_site_span).metadata;
match debug_context(cx).type_map
.borrow()
}
ty::TyClosure(def_id, substs) => {
- let upvar_tys : Vec<_> = substs.upvar_tys(def_id, cx.tcx()).collect();
+ let upvar_tys : Vec<_> = substs.upvar_tys(def_id, cx.tcx).collect();
prepare_tuple_metadata(cx,
t,
&upvar_tys,
usage_site_span).finalize(cx)
}
ty::TyGenerator(def_id, substs, _) => {
- let upvar_tys : Vec<_> = substs.field_tys(def_id, cx.tcx()).map(|t| {
- cx.tcx().fully_normalize_associated_types_in(&t)
+ let upvar_tys : Vec<_> = substs.field_tys(def_id, cx.tcx).map(|t| {
+ cx.tcx.fully_normalize_associated_types_in(&t)
}).collect();
prepare_tuple_metadata(cx,
t,
metadata
}
-pub fn file_metadata(cx: &CrateContext,
+pub fn file_metadata(cx: &CodegenCx,
file_name: &FileName,
defining_crate: CrateNum) -> DIFile {
debug!("file_metadata: file_name: {}, defining_crate: {}",
file_metadata_raw(cx, &file_name.to_string(), &directory.to_string_lossy())
}
-pub fn unknown_file_metadata(cx: &CrateContext) -> DIFile {
+pub fn unknown_file_metadata(cx: &CodegenCx) -> DIFile {
file_metadata_raw(cx, "<unknown>", "")
}
-fn file_metadata_raw(cx: &CrateContext,
+fn file_metadata_raw(cx: &CodegenCx,
file_name: &str,
directory: &str)
-> DIFile {
file_metadata
}
-fn basic_type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
+fn basic_type_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
t: Ty<'tcx>) -> DIType {
debug!("basic_type_metadata: {:?}", t);
return ty_metadata;
}
-fn foreign_type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
+fn foreign_type_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
t: Ty<'tcx>,
unique_type_id: UniqueTypeId) -> DIType {
debug!("foreign_type_metadata: {:?}", t);
create_struct_stub(cx, t, &name, unique_type_id, NO_SCOPE_METADATA)
}
-fn pointer_type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
+fn pointer_type_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
pointer_type: Ty<'tcx>,
pointee_type_metadata: DIType)
-> DIType {
}
}
-pub fn compile_unit_metadata(scc: &SharedCrateContext,
+pub fn compile_unit_metadata(tcx: TyCtxt,
codegen_unit_name: &str,
- debug_context: &CrateDebugContext,
- sess: &Session)
+ debug_context: &CrateDebugContext)
-> DIDescriptor {
- let mut name_in_debuginfo = match sess.local_crate_source_file {
+ let mut name_in_debuginfo = match tcx.sess.local_crate_source_file {
Some(ref path) => path.clone(),
- None => PathBuf::from(&*scc.tcx().crate_name(LOCAL_CRATE).as_str()),
+ None => PathBuf::from(&*tcx.crate_name(LOCAL_CRATE).as_str()),
};
// The OSX linker has an idiosyncrasy where it will ignore some debuginfo
// if multiple object files with the same DW_AT_name are linked together.
// As a workaround we generate unique names for each object file. Those do
// not correspond to an actual source file but that should be harmless.
- if scc.sess().target.target.options.is_like_osx {
+ if tcx.sess.target.target.options.is_like_osx {
name_in_debuginfo.push("@");
name_in_debuginfo.push(codegen_unit_name);
}
let name_in_debuginfo = name_in_debuginfo.to_string_lossy().into_owned();
let name_in_debuginfo = CString::new(name_in_debuginfo).unwrap();
- let work_dir = CString::new(&sess.working_dir.0.to_string_lossy()[..]).unwrap();
+ let work_dir = CString::new(&tcx.sess.working_dir.0.to_string_lossy()[..]).unwrap();
let producer = CString::new(producer).unwrap();
let flags = "\0";
let split_name = "\0";
DW_LANG_RUST,
file_metadata,
producer.as_ptr(),
- sess.opts.optimize != config::OptLevel::No,
+ tcx.sess.opts.optimize != config::OptLevel::No,
flags.as_ptr() as *const _,
0,
split_name.as_ptr() as *const _);
- if sess.opts.debugging_opts.profile {
+ if tcx.sess.opts.debugging_opts.profile {
let cu_desc_metadata = llvm::LLVMRustMetadataAsValue(debug_context.llcontext,
unit_metadata);
let gcov_cu_info = [
path_to_mdstring(debug_context.llcontext,
- &scc.tcx().output_filenames(LOCAL_CRATE).with_extension("gcno")),
+ &tcx.output_filenames(LOCAL_CRATE).with_extension("gcno")),
path_to_mdstring(debug_context.llcontext,
- &scc.tcx().output_filenames(LOCAL_CRATE).with_extension("gcda")),
+ &tcx.output_filenames(LOCAL_CRATE).with_extension("gcda")),
cu_desc_metadata,
];
let gcov_metadata = llvm::LLVMMDNodeInContext(debug_context.llcontext,
}
impl<'tcx> MemberDescriptionFactory<'tcx> {
- fn create_member_descriptions<'a>(&self, cx: &CrateContext<'a, 'tcx>)
+ fn create_member_descriptions<'a>(&self, cx: &CodegenCx<'a, 'tcx>)
-> Vec<MemberDescription> {
match *self {
StructMDF(ref this) => {
}
impl<'tcx> StructMemberDescriptionFactory<'tcx> {
- fn create_member_descriptions<'a>(&self, cx: &CrateContext<'a, 'tcx>)
+ fn create_member_descriptions<'a>(&self, cx: &CodegenCx<'a, 'tcx>)
-> Vec<MemberDescription> {
let layout = cx.layout_of(self.ty);
self.variant.fields.iter().enumerate().map(|(i, f)| {
}
-fn prepare_struct_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
+fn prepare_struct_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
struct_type: Ty<'tcx>,
unique_type_id: UniqueTypeId,
span: Span)
let struct_name = compute_debuginfo_type_name(cx, struct_type, false);
let (struct_def_id, variant) = match struct_type.sty {
- ty::TyAdt(def, _) => (def.did, def.struct_variant()),
+ ty::TyAdt(def, _) => (def.did, def.non_enum_variant()),
_ => bug!("prepare_struct_metadata on a non-ADT")
};
}
impl<'tcx> TupleMemberDescriptionFactory<'tcx> {
- fn create_member_descriptions<'a>(&self, cx: &CrateContext<'a, 'tcx>)
+ fn create_member_descriptions<'a>(&self, cx: &CodegenCx<'a, 'tcx>)
-> Vec<MemberDescription> {
let layout = cx.layout_of(self.ty);
self.component_types.iter().enumerate().map(|(i, &component_type)| {
}
}
-fn prepare_tuple_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
+fn prepare_tuple_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
tuple_type: Ty<'tcx>,
component_types: &[Ty<'tcx>],
unique_type_id: UniqueTypeId,
}
impl<'tcx> UnionMemberDescriptionFactory<'tcx> {
- fn create_member_descriptions<'a>(&self, cx: &CrateContext<'a, 'tcx>)
+ fn create_member_descriptions<'a>(&self, cx: &CodegenCx<'a, 'tcx>)
-> Vec<MemberDescription> {
self.variant.fields.iter().enumerate().map(|(i, f)| {
let field = self.layout.field(cx, i);
}
}
-fn prepare_union_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
+fn prepare_union_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
union_type: Ty<'tcx>,
unique_type_id: UniqueTypeId,
span: Span)
let union_name = compute_debuginfo_type_name(cx, union_type, false);
let (union_def_id, variant) = match union_type.sty {
- ty::TyAdt(def, _) => (def.did, def.struct_variant()),
+ ty::TyAdt(def, _) => (def.did, def.non_enum_variant()),
_ => bug!("prepare_union_metadata on a non-ADT")
};
}
impl<'tcx> EnumMemberDescriptionFactory<'tcx> {
- fn create_member_descriptions<'a>(&self, cx: &CrateContext<'a, 'tcx>)
+ fn create_member_descriptions<'a>(&self, cx: &CodegenCx<'a, 'tcx>)
-> Vec<MemberDescription> {
let adt = &self.enum_type.ty_adt_def().unwrap();
match self.layout.variants {
// of discriminant instead of us having to recover its path.
// Right now it's not even going to work for `niche_start > 0`,
// and for multiple niche variants it only supports the first.
- fn compute_field_path<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
+ fn compute_field_path<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
name: &mut String,
layout: TyLayout<'tcx>,
offset: Size,
continue;
}
let inner_offset = offset - field_offset;
- let field = layout.field(ccx, i);
+ let field = layout.field(cx, i);
if inner_offset + size <= field.size {
write!(name, "{}$", i).unwrap();
- compute_field_path(ccx, name, field, inner_offset, size);
+ compute_field_path(cx, name, field, inner_offset, size);
}
}
}
}
impl<'tcx> VariantMemberDescriptionFactory<'tcx> {
- fn create_member_descriptions<'a>(&self, cx: &CrateContext<'a, 'tcx>)
+ fn create_member_descriptions<'a>(&self, cx: &CodegenCx<'a, 'tcx>)
-> Vec<MemberDescription> {
self.args.iter().enumerate().map(|(i, &(ref name, ty))| {
let (size, align) = cx.size_and_align_of(ty);
// of the variant, and (3) a MemberDescriptionFactory for producing the
// descriptions of the fields of the variant. This is a rudimentary version of a
// full RecursiveTypeDescription.
-fn describe_enum_variant<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
+fn describe_enum_variant<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
layout: layout::TyLayout<'tcx>,
variant: &'tcx ty::VariantDef,
discriminant_info: EnumDiscriminantInfo,
(metadata_stub, member_description_factory)
}
-fn prepare_enum_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
+fn prepare_enum_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
enum_type: Ty<'tcx>,
enum_def_id: DefId,
unique_type_id: UniqueTypeId,
let file_metadata = unknown_file_metadata(cx);
let def = enum_type.ty_adt_def().unwrap();
- let enumerators_metadata: Vec<DIDescriptor> = def.discriminants(cx.tcx())
+ let enumerators_metadata: Vec<DIDescriptor> = def.discriminants(cx.tcx)
.zip(&def.variants)
.map(|(discr, v)| {
let token = v.name.as_str();
let (discriminant_size, discriminant_align) =
(discr.size(cx), discr.align(cx));
let discriminant_base_type_metadata =
- type_metadata(cx, discr.to_ty(cx.tcx()), syntax_pos::DUMMY_SP);
+ type_metadata(cx, discr.to_ty(cx.tcx), syntax_pos::DUMMY_SP);
let discriminant_name = get_enum_discriminant_name(cx, enum_def_id);
let name = CString::new(discriminant_name.as_bytes()).unwrap();
}),
);
- fn get_enum_discriminant_name(cx: &CrateContext,
+ fn get_enum_discriminant_name(cx: &CodegenCx,
def_id: DefId)
-> InternedString {
- cx.tcx().item_name(def_id)
+ cx.tcx.item_name(def_id)
}
}
/// results in a LLVM struct.
///
/// Examples of Rust types to use this are: structs, tuples, boxes, vecs, and enums.
-fn composite_type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
+fn composite_type_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
composite_type: Ty<'tcx>,
composite_type_name: &str,
composite_type_unique_id: UniqueTypeId,
return composite_type_metadata;
}
-fn set_members_of_composite_type(cx: &CrateContext,
+fn set_members_of_composite_type(cx: &CodegenCx,
composite_type_metadata: DICompositeType,
member_descriptions: &[MemberDescription]) {
// In some rare cases LLVM metadata uniquing would lead to an existing type
// A convenience wrapper around LLVMRustDIBuilderCreateStructType(). Does not do
// any caching, does not add any fields to the struct. This can be done later
// with set_members_of_composite_type().
-fn create_struct_stub<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
+fn create_struct_stub<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
struct_type: Ty<'tcx>,
struct_type_name: &str,
unique_type_id: UniqueTypeId,
return metadata_stub;
}
-fn create_union_stub<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
+fn create_union_stub<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
union_type: Ty<'tcx>,
union_type_name: &str,
unique_type_id: UniqueTypeId,
/// Creates debug information for the given global variable.
///
/// Adds the created metadata nodes directly to the crate's IR.
-pub fn create_global_var_metadata(cx: &CrateContext,
+pub fn create_global_var_metadata(cx: &CodegenCx,
node_id: ast::NodeId,
global: ValueRef) {
- if cx.dbg_cx().is_none() {
+ if cx.dbg_cx.is_none() {
return;
}
- let tcx = cx.tcx();
+ let tcx = cx.tcx;
let node_def_id = tcx.hir.local_def_id(node_id);
let no_mangle = attr::contains_name(&tcx.get_attrs(node_def_id), "no_mangle");
// We may want to remove the namespace scope if we're in an extern block, see:
// https://github.com/rust-lang/rust/pull/46457#issuecomment-351750952
let var_scope = get_namespace_for_item(cx, node_def_id);
- let span = cx.tcx().def_span(node_def_id);
+ let span = cx.tcx.def_span(node_def_id);
let (file_metadata, line_number) = if span != syntax_pos::DUMMY_SP {
let loc = span_start(cx, span);
};
let is_local_to_unit = is_node_local_to_unit(cx, node_id);
- let variable_type = Instance::mono(cx.tcx(), node_def_id).ty(cx.tcx());
+ let variable_type = Instance::mono(cx.tcx, node_def_id).ty(cx.tcx);
let type_metadata = type_metadata(cx, variable_type, span);
let var_name = tcx.item_name(node_def_id).to_string();
let var_name = CString::new(var_name).unwrap();
}
// Creates an "extension" of an existing DIScope into another file.
-pub fn extend_scope_to_file(ccx: &CrateContext,
+pub fn extend_scope_to_file(cx: &CodegenCx,
scope_metadata: DIScope,
file: &syntax_pos::FileMap,
defining_crate: CrateNum)
-> DILexicalBlock {
- let file_metadata = file_metadata(ccx, &file.name, defining_crate);
+ let file_metadata = file_metadata(cx, &file.name, defining_crate);
unsafe {
llvm::LLVMRustDIBuilderCreateLexicalBlockFile(
- DIB(ccx),
+ DIB(cx),
scope_metadata,
file_metadata)
}
/// given type.
///
/// Adds the created metadata nodes directly to the crate's IR.
-pub fn create_vtable_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
+pub fn create_vtable_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
ty: ty::Ty<'tcx>,
vtable: ValueRef) {
- if cx.dbg_cx().is_none() {
+ if cx.dbg_cx.is_none() {
return;
}
unknown_file_metadata(cx),
UNKNOWN_LINE_NUMBER,
Size::from_bytes(0).bits(),
- cx.tcx().data_layout.pointer_align.abi_bits() as u32,
+ cx.tcx.data_layout.pointer_align.abi_bits() as u32,
DIFlags::FlagArtificial,
ptr::null_mut(),
empty_array,
use rustc::ty::subst::Substs;
use abi::Abi;
-use common::CrateContext;
+use common::CodegenCx;
use builder::Builder;
use monomorphize::Instance;
use rustc::ty::{self, Ty};
}
/// Create any deferred debug metadata nodes
-pub fn finalize(cx: &CrateContext) {
- if cx.dbg_cx().is_none() {
+pub fn finalize(cx: &CodegenCx) {
+ if cx.dbg_cx.is_none() {
return;
}
// Android has the same issue (#22398)
if cx.sess().target.target.options.is_like_osx ||
cx.sess().target.target.options.is_like_android {
- llvm::LLVMRustAddModuleFlag(cx.llmod(),
+ llvm::LLVMRustAddModuleFlag(cx.llmod,
"Dwarf Version\0".as_ptr() as *const _,
2)
}
// Indicate that we want CodeView debug information on MSVC
if cx.sess().target.target.options.is_like_msvc {
- llvm::LLVMRustAddModuleFlag(cx.llmod(),
+ llvm::LLVMRustAddModuleFlag(cx.llmod,
"CodeView\0".as_ptr() as *const _,
1)
}
// Prevent bitcode readers from deleting the debug info.
let ptr = "Debug Info Version\0".as_ptr();
- llvm::LLVMRustAddModuleFlag(cx.llmod(), ptr as *const _,
+ llvm::LLVMRustAddModuleFlag(cx.llmod, ptr as *const _,
llvm::LLVMRustDebugMetadataVersion());
};
}
/// for debug info creation. The function may also return another variant of the
/// FunctionDebugContext enum which indicates why no debuginfo should be created
/// for the function.
-pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
+pub fn create_function_debug_context<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
instance: Instance<'tcx>,
sig: ty::FnSig<'tcx>,
llfn: ValueRef,
return FunctionDebugContext::DebugInfoDisabled;
}
- for attr in instance.def.attrs(cx.tcx()).iter() {
+ for attr in instance.def.attrs(cx.tcx).iter() {
if attr.check_name("no_debug") {
return FunctionDebugContext::FunctionWithoutDebugInfo;
}
};
// Find the enclosing function, in case this is a closure.
- let def_key = cx.tcx().def_key(def_id);
+ let def_key = cx.tcx.def_key(def_id);
let mut name = def_key.disambiguated_data.data.to_string();
- let enclosing_fn_def_id = cx.tcx().closure_base_def_id(def_id);
+ let enclosing_fn_def_id = cx.tcx.closure_base_def_id(def_id);
// Get_template_parameters() will append a `<...>` clause to the function
// name if necessary.
- let generics = cx.tcx().generics_of(enclosing_fn_def_id);
- let substs = instance.substs.truncate_to(cx.tcx(), generics);
+ let generics = cx.tcx.generics_of(enclosing_fn_def_id);
+ let substs = instance.substs.truncate_to(cx.tcx, generics);
let template_parameters = get_template_parameters(cx,
&generics,
substs,
let scope_line = span_start(cx, span).line;
- let local_id = cx.tcx().hir.as_local_node_id(instance.def_id());
+ let local_id = cx.tcx.hir.as_local_node_id(instance.def_id());
let is_local_to_unit = local_id.map_or(false, |id| is_node_local_to_unit(cx, id));
let function_name = CString::new(name).unwrap();
return FunctionDebugContext::RegularContext(fn_debug_context);
- fn get_function_signature<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
+ fn get_function_signature<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
sig: ty::FnSig<'tcx>) -> DIArray {
if cx.sess().opts.debuginfo == LimitedDebugInfo {
return create_DIArray(DIB(cx), &[]);
signature.extend(inputs.iter().map(|&t| {
let t = match t.sty {
ty::TyArray(ct, _)
- if (ct == cx.tcx().types.u8) || cx.layout_of(ct).is_zst() => {
- cx.tcx().mk_imm_ptr(ct)
+ if (ct == cx.tcx.types.u8) || cx.layout_of(ct).is_zst() => {
+ cx.tcx.mk_imm_ptr(ct)
}
_ => t
};
return create_DIArray(DIB(cx), &signature[..]);
}
- fn get_template_parameters<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
+ fn get_template_parameters<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
generics: &ty::Generics,
substs: &Substs<'tcx>,
file_metadata: DIFile,
name_to_append_suffix_to.push_str(",");
}
- let actual_type = cx.tcx().fully_normalize_associated_types_in(&actual_type);
+ let actual_type = cx.tcx.fully_normalize_associated_types_in(&actual_type);
// Add actual type name to <...> clause of function name
let actual_type_name = compute_debuginfo_type_name(cx,
actual_type,
let template_params: Vec<_> = if cx.sess().opts.debuginfo == FullDebugInfo {
let names = get_type_parameter_names(cx, generics);
substs.types().zip(names).map(|(ty, name)| {
- let actual_type = cx.tcx().fully_normalize_associated_types_in(&ty);
+ let actual_type = cx.tcx.fully_normalize_associated_types_in(&ty);
let actual_type_metadata = type_metadata(cx, actual_type, syntax_pos::DUMMY_SP);
let name = CString::new(name.as_str().as_bytes()).unwrap();
unsafe {
return create_DIArray(DIB(cx), &template_params[..]);
}
- fn get_type_parameter_names(cx: &CrateContext, generics: &ty::Generics) -> Vec<ast::Name> {
+ fn get_type_parameter_names(cx: &CodegenCx, generics: &ty::Generics) -> Vec<ast::Name> {
let mut names = generics.parent.map_or(vec![], |def_id| {
- get_type_parameter_names(cx, cx.tcx().generics_of(def_id))
+ get_type_parameter_names(cx, cx.tcx.generics_of(def_id))
});
names.extend(generics.types.iter().map(|param| param.name));
names
}
- fn get_containing_scope<'ccx, 'tcx>(cx: &CrateContext<'ccx, 'tcx>,
+ fn get_containing_scope<'cx, 'tcx>(cx: &CodegenCx<'cx, 'tcx>,
instance: Instance<'tcx>)
-> DIScope {
// First, let's see if this is a method within an inherent impl. Because
// if yes, we want to make the result subroutine DIE a child of the
// subroutine's self-type.
- let self_type = cx.tcx().impl_of_method(instance.def_id()).and_then(|impl_def_id| {
+ let self_type = cx.tcx.impl_of_method(instance.def_id()).and_then(|impl_def_id| {
// If the method does *not* belong to a trait, proceed
- if cx.tcx().trait_id_of_impl(impl_def_id).is_none() {
- let impl_self_ty = cx.tcx().trans_impl_self_ty(impl_def_id, instance.substs);
+ if cx.tcx.trait_id_of_impl(impl_def_id).is_none() {
+ let impl_self_ty = cx.tcx.trans_impl_self_ty(impl_def_id, instance.substs);
// Only "class" methods are generally understood by LLVM,
// so avoid methods on other types (e.g. `<*mut T>::null`).
self_type.unwrap_or_else(|| {
namespace::item_namespace(cx, DefId {
krate: instance.def_id().krate,
- index: cx.tcx()
+ index: cx.tcx
.def_key(instance.def_id())
.parent
.expect("get_containing_scope: missing parent?")
}
}
-pub fn declare_local<'a, 'tcx>(bcx: &Builder<'a, 'tcx>,
+pub fn declare_local<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
dbg_context: &FunctionDebugContext,
variable_name: ast::Name,
variable_type: Ty<'tcx>,
variable_access: VariableAccess,
variable_kind: VariableKind,
span: Span) {
- let cx = bcx.ccx;
+ let cx = bx.cx;
let file = span_start(cx, span).file;
let file_metadata = file_metadata(cx,
align.abi() as u32,
)
};
- source_loc::set_debug_location(bcx,
+ source_loc::set_debug_location(bx,
InternalDebugLocation::new(scope_metadata, loc.line, loc.col.to_usize()));
unsafe {
- let debug_loc = llvm::LLVMGetCurrentDebugLocation(bcx.llbuilder);
+ let debug_loc = llvm::LLVMGetCurrentDebugLocation(bx.llbuilder);
let instr = llvm::LLVMRustDIBuilderInsertDeclareAtEnd(
DIB(cx),
alloca,
address_operations.as_ptr(),
address_operations.len() as c_uint,
debug_loc,
- bcx.llbb());
+ bx.llbb());
- llvm::LLVMSetInstDebugLocation(bcx.llbuilder, instr);
+ llvm::LLVMSetInstDebugLocation(bx.llbuilder, instr);
}
}
}
match variable_kind {
ArgumentVariable(_) | CapturedVariable => {
assert!(!dbg_context.get_ref(span).source_locations_enabled.get());
- source_loc::set_debug_location(bcx, UnknownLocation);
+ source_loc::set_debug_location(bx, UnknownLocation);
}
_ => { /* nothing to do */ }
}
use llvm::debuginfo::DIScope;
use rustc::hir::def_id::DefId;
use rustc::hir::map::DefPathData;
-use common::CrateContext;
+use common::CodegenCx;
use std::ffi::CString;
use std::ptr;
pub fn mangled_name_of_instance<'a, 'tcx>(
- ccx: &CrateContext<'a, 'tcx>,
+ cx: &CodegenCx<'a, 'tcx>,
instance: Instance<'tcx>,
) -> ty::SymbolName {
- let tcx = ccx.tcx();
+ let tcx = cx.tcx;
tcx.symbol_name(instance)
}
pub fn mangled_name_of_item<'a, 'tcx>(
- ccx: &CrateContext<'a, 'tcx>,
+ cx: &CodegenCx<'a, 'tcx>,
node_id: ast::NodeId,
) -> ty::SymbolName {
- let tcx = ccx.tcx();
+ let tcx = cx.tcx;
let node_def_id = tcx.hir.local_def_id(node_id);
let instance = Instance::mono(tcx, node_def_id);
tcx.symbol_name(instance)
}
-pub fn item_namespace(ccx: &CrateContext, def_id: DefId) -> DIScope {
- if let Some(&scope) = debug_context(ccx).namespace_map.borrow().get(&def_id) {
+pub fn item_namespace(cx: &CodegenCx, def_id: DefId) -> DIScope {
+ if let Some(&scope) = debug_context(cx).namespace_map.borrow().get(&def_id) {
return scope;
}
- let def_key = ccx.tcx().def_key(def_id);
+ let def_key = cx.tcx.def_key(def_id);
let parent_scope = def_key.parent.map_or(ptr::null_mut(), |parent| {
- item_namespace(ccx, DefId {
+ item_namespace(cx, DefId {
krate: def_id.krate,
index: parent
})
});
let namespace_name = match def_key.disambiguated_data.data {
- DefPathData::CrateRoot => ccx.tcx().crate_name(def_id.krate).as_str(),
+ DefPathData::CrateRoot => cx.tcx.crate_name(def_id.krate).as_str(),
data => data.as_interned_str()
};
let scope = unsafe {
llvm::LLVMRustDIBuilderCreateNameSpace(
- DIB(ccx),
+ DIB(cx),
parent_scope,
namespace_name.as_ptr(),
- unknown_file_metadata(ccx),
+ unknown_file_metadata(cx),
UNKNOWN_LINE_NUMBER)
};
- debug_context(ccx).namespace_map.borrow_mut().insert(def_id, scope);
+ debug_context(cx).namespace_map.borrow_mut().insert(def_id, scope);
scope
}
///
/// Maps to a call to llvm::LLVMSetCurrentDebugLocation(...).
pub fn set_source_location(
- debug_context: &FunctionDebugContext, builder: &Builder, scope: DIScope, span: Span
+ debug_context: &FunctionDebugContext, bx: &Builder, scope: DIScope, span: Span
) {
let function_debug_context = match *debug_context {
FunctionDebugContext::DebugInfoDisabled => return,
FunctionDebugContext::FunctionWithoutDebugInfo => {
- set_debug_location(builder, UnknownLocation);
+ set_debug_location(bx, UnknownLocation);
return;
}
FunctionDebugContext::RegularContext(ref data) => data
};
let dbg_loc = if function_debug_context.source_locations_enabled.get() {
- debug!("set_source_location: {}", builder.sess().codemap().span_to_string(span));
- let loc = span_start(builder.ccx, span);
+ debug!("set_source_location: {}", bx.sess().codemap().span_to_string(span));
+ let loc = span_start(bx.cx, span);
InternalDebugLocation::new(scope, loc.line, loc.col.to_usize())
} else {
UnknownLocation
};
- set_debug_location(builder, dbg_loc);
+ set_debug_location(bx, dbg_loc);
}
/// Enables emitting source locations for the given functions.
}
}
-pub fn set_debug_location(builder: &Builder, debug_location: InternalDebugLocation) {
+pub fn set_debug_location(bx: &Builder, debug_location: InternalDebugLocation) {
let metadata_node = match debug_location {
KnownLocation { scope, line, .. } => {
// Always set the column to zero like Clang and GCC
unsafe {
llvm::LLVMRustDIBuilderCreateDebugLocation(
- debug_context(builder.ccx).llcontext,
+ debug_context(bx.cx).llcontext,
line as c_uint,
col as c_uint,
scope,
};
unsafe {
- llvm::LLVMSetCurrentDebugLocation(builder.llbuilder, metadata_node);
+ llvm::LLVMSetCurrentDebugLocation(bx.llbuilder, metadata_node);
}
}
// Type Names for Debug Info.
-use common::CrateContext;
+use common::CodegenCx;
use rustc::hir::def_id::DefId;
use rustc::ty::subst::Substs;
use rustc::ty::{self, Ty};
// any caching, i.e. calling the function twice with the same type will also do
// the work twice. The `qualified` parameter only affects the first level of the
// type name, further levels (i.e. type parameters) are always fully qualified.
-pub fn compute_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
+pub fn compute_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
t: Ty<'tcx>,
qualified: bool)
-> String {
// Pushes the name of the type as it should be stored in debuginfo on the
// `output` String. See also compute_debuginfo_type_name().
-pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
+pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
t: Ty<'tcx>,
qualified: bool,
output: &mut String) {
},
ty::TyDynamic(ref trait_data, ..) => {
if let Some(principal) = trait_data.principal() {
- let principal = cx.tcx().erase_late_bound_regions_and_normalize(
+ let principal = cx.tcx.erase_late_bound_regions_and_normalize(
&principal);
push_item_name(cx, principal.def_id, false, output);
push_type_params(cx, principal.substs, output);
}
},
ty::TyFnDef(..) | ty::TyFnPtr(_) => {
- let sig = t.fn_sig(cx.tcx());
+ let sig = t.fn_sig(cx.tcx);
if sig.unsafety() == hir::Unsafety::Unsafe {
output.push_str("unsafe ");
}
output.push_str("fn(");
- let sig = cx.tcx().erase_late_bound_regions_and_normalize(&sig);
+ let sig = cx.tcx.erase_late_bound_regions_and_normalize(&sig);
if !sig.inputs().is_empty() {
for ¶meter_type in sig.inputs() {
push_debuginfo_type_name(cx, parameter_type, true, output);
}
}
- fn push_item_name(cx: &CrateContext,
+ fn push_item_name(cx: &CodegenCx,
def_id: DefId,
qualified: bool,
output: &mut String) {
if qualified {
- output.push_str(&cx.tcx().crate_name(def_id.krate).as_str());
- for path_element in cx.tcx().def_path(def_id).data {
+ output.push_str(&cx.tcx.crate_name(def_id.krate).as_str());
+ for path_element in cx.tcx.def_path(def_id).data {
output.push_str("::");
output.push_str(&path_element.data.as_interned_str());
}
} else {
- output.push_str(&cx.tcx().item_name(def_id));
+ output.push_str(&cx.tcx.item_name(def_id));
}
}
// reconstructed for items from non-local crates. For local crates, this
// would be possible but with inlining and LTO we have to use the least
// common denominator - otherwise we would run into conflicts.
- fn push_type_params<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
+ fn push_type_params<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
substs: &Substs<'tcx>,
output: &mut String) {
if substs.types().next().is_none() {
use llvm;
use llvm::debuginfo::{DIScope, DIBuilderRef, DIDescriptor, DIArray};
-use common::{CrateContext};
+use common::{CodegenCx};
use syntax_pos::{self, Span};
use syntax::ast;
-pub fn is_node_local_to_unit(cx: &CrateContext, node_id: ast::NodeId) -> bool
+pub fn is_node_local_to_unit(cx: &CodegenCx, node_id: ast::NodeId) -> bool
{
// The is_local_to_unit flag indicates whether a function is local to the
// current compilation unit (i.e. if it is *static* in the C-sense). The
// visible). It might better to use the `exported_items` set from
// `driver::CrateAnalysis` in the future, but (atm) this set is not
// available in the translation pass.
- let def_id = cx.tcx().hir.local_def_id(node_id);
- !cx.tcx().is_exported_symbol(def_id)
+ let def_id = cx.tcx.hir.local_def_id(node_id);
+ !cx.tcx.is_exported_symbol(def_id)
}
#[allow(non_snake_case)]
}
/// Return syntax_pos::Loc corresponding to the beginning of the span
-pub fn span_start(cx: &CrateContext, span: Span) -> syntax_pos::Loc {
+pub fn span_start(cx: &CodegenCx, span: Span) -> syntax_pos::Loc {
cx.sess().codemap().lookup_char_pos(span.lo())
}
#[inline]
-pub fn debug_context<'a, 'tcx>(cx: &'a CrateContext<'a, 'tcx>)
+pub fn debug_context<'a, 'tcx>(cx: &'a CodegenCx<'a, 'tcx>)
-> &'a CrateDebugContext<'tcx> {
- cx.dbg_cx().as_ref().unwrap()
+ cx.dbg_cx.as_ref().unwrap()
}
#[inline]
#[allow(non_snake_case)]
-pub fn DIB(cx: &CrateContext) -> DIBuilderRef {
- cx.dbg_cx().as_ref().unwrap().builder
+pub fn DIB(cx: &CodegenCx) -> DIBuilderRef {
+ cx.dbg_cx.as_ref().unwrap().builder
}
-pub fn get_namespace_for_item(cx: &CrateContext, def_id: DefId) -> DIScope {
- item_namespace(cx, cx.tcx().parent(def_id)
+pub fn get_namespace_for_item(cx: &CodegenCx, def_id: DefId) -> DIScope {
+ item_namespace(cx, cx.tcx.parent(def_id)
.expect("get_namespace_for_item: missing parent?"))
}
use rustc_back::PanicStrategy;
use abi::{Abi, FnType};
use attributes;
-use context::CrateContext;
+use context::CodegenCx;
use common;
use type_::Type;
use value::Value;
///
/// If there’s a value with the same name already declared, the function will
/// return its ValueRef instead.
-pub fn declare_global(ccx: &CrateContext, name: &str, ty: Type) -> llvm::ValueRef {
+pub fn declare_global(cx: &CodegenCx, name: &str, ty: Type) -> llvm::ValueRef {
debug!("declare_global(name={:?})", name);
let namebuf = CString::new(name).unwrap_or_else(|_|{
bug!("name {:?} contains an interior null byte", name)
});
unsafe {
- llvm::LLVMRustGetOrInsertGlobal(ccx.llmod(), namebuf.as_ptr(), ty.to_ref())
+ llvm::LLVMRustGetOrInsertGlobal(cx.llmod, namebuf.as_ptr(), ty.to_ref())
}
}
///
/// If there’s a value with the same name already declared, the function will
/// update the declaration and return existing ValueRef instead.
-fn declare_raw_fn(ccx: &CrateContext, name: &str, callconv: llvm::CallConv, ty: Type) -> ValueRef {
+fn declare_raw_fn(cx: &CodegenCx, name: &str, callconv: llvm::CallConv, ty: Type) -> ValueRef {
debug!("declare_raw_fn(name={:?}, ty={:?})", name, ty);
let namebuf = CString::new(name).unwrap_or_else(|_|{
bug!("name {:?} contains an interior null byte", name)
});
let llfn = unsafe {
- llvm::LLVMRustGetOrInsertFunction(ccx.llmod(), namebuf.as_ptr(), ty.to_ref())
+ llvm::LLVMRustGetOrInsertFunction(cx.llmod, namebuf.as_ptr(), ty.to_ref())
};
llvm::SetFunctionCallConv(llfn, callconv);
// be merged.
llvm::SetUnnamedAddr(llfn, true);
- if ccx.tcx().sess.opts.cg.no_redzone
- .unwrap_or(ccx.tcx().sess.target.target.options.disable_redzone) {
+ if cx.tcx.sess.opts.cg.no_redzone
+ .unwrap_or(cx.tcx.sess.target.target.options.disable_redzone) {
llvm::Attribute::NoRedZone.apply_llfn(Function, llfn);
}
- if let Some(ref sanitizer) = ccx.tcx().sess.opts.debugging_opts.sanitizer {
+ if let Some(ref sanitizer) = cx.tcx.sess.opts.debugging_opts.sanitizer {
match *sanitizer {
Sanitizer::Address => {
llvm::Attribute::SanitizeAddress.apply_llfn(Function, llfn);
}
}
- match ccx.tcx().sess.opts.cg.opt_level.as_ref().map(String::as_ref) {
+ match cx.tcx.sess.opts.cg.opt_level.as_ref().map(String::as_ref) {
Some("s") => {
llvm::Attribute::OptimizeForSize.apply_llfn(Function, llfn);
},
_ => {},
}
- if ccx.tcx().sess.panic_strategy() != PanicStrategy::Unwind {
+ if cx.tcx.sess.panic_strategy() != PanicStrategy::Unwind {
attributes::unwind(llfn, false);
}
///
/// If there’s a value with the same name already declared, the function will
/// update the declaration and return existing ValueRef instead.
-pub fn declare_cfn(ccx: &CrateContext, name: &str, fn_type: Type) -> ValueRef {
- declare_raw_fn(ccx, name, llvm::CCallConv, fn_type)
+pub fn declare_cfn(cx: &CodegenCx, name: &str, fn_type: Type) -> ValueRef {
+ declare_raw_fn(cx, name, llvm::CCallConv, fn_type)
}
///
/// If there’s a value with the same name already declared, the function will
/// update the declaration and return existing ValueRef instead.
-pub fn declare_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, name: &str,
+pub fn declare_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, name: &str,
fn_type: Ty<'tcx>) -> ValueRef {
debug!("declare_rust_fn(name={:?}, fn_type={:?})", name, fn_type);
- let sig = common::ty_fn_sig(ccx, fn_type);
- let sig = ccx.tcx().erase_late_bound_regions_and_normalize(&sig);
+ let sig = common::ty_fn_sig(cx, fn_type);
+ let sig = cx.tcx.erase_late_bound_regions_and_normalize(&sig);
debug!("declare_rust_fn (after region erasure) sig={:?}", sig);
- let fty = FnType::new(ccx, sig, &[]);
- let llfn = declare_raw_fn(ccx, name, fty.cconv, fty.llvm_type(ccx));
+ let fty = FnType::new(cx, sig, &[]);
+ let llfn = declare_raw_fn(cx, name, fty.cconv, fty.llvm_type(cx));
// FIXME(canndrew): This is_never should really be an is_uninhabited
if sig.output().is_never() {
/// return None if the name already has a definition associated with it. In that
/// case an error should be reported to the user, because it usually happens due
/// to user’s fault (e.g. misuse of #[no_mangle] or #[export_name] attributes).
-pub fn define_global(ccx: &CrateContext, name: &str, ty: Type) -> Option<ValueRef> {
- if get_defined_value(ccx, name).is_some() {
+pub fn define_global(cx: &CodegenCx, name: &str, ty: Type) -> Option<ValueRef> {
+ if get_defined_value(cx, name).is_some() {
None
} else {
- Some(declare_global(ccx, name, ty))
+ Some(declare_global(cx, name, ty))
}
}
/// Use this function when you intend to define a function. This function will
/// return panic if the name already has a definition associated with it. This
/// can happen with #[no_mangle] or #[export_name], for example.
-pub fn define_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
+pub fn define_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
name: &str,
fn_type: Ty<'tcx>) -> ValueRef {
- if get_defined_value(ccx, name).is_some() {
- ccx.sess().fatal(&format!("symbol `{}` already defined", name))
+ if get_defined_value(cx, name).is_some() {
+ cx.sess().fatal(&format!("symbol `{}` already defined", name))
} else {
- declare_fn(ccx, name, fn_type)
+ declare_fn(cx, name, fn_type)
}
}
/// Use this function when you intend to define a function. This function will
/// return panic if the name already has a definition associated with it. This
/// can happen with #[no_mangle] or #[export_name], for example.
-pub fn define_internal_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
+pub fn define_internal_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
name: &str,
fn_type: Ty<'tcx>) -> ValueRef {
- let llfn = define_fn(ccx, name, fn_type);
+ let llfn = define_fn(cx, name, fn_type);
unsafe { llvm::LLVMRustSetLinkage(llfn, llvm::Linkage::InternalLinkage) };
llfn
}
/// Get declared value by name.
-pub fn get_declared_value(ccx: &CrateContext, name: &str) -> Option<ValueRef> {
+pub fn get_declared_value(cx: &CodegenCx, name: &str) -> Option<ValueRef> {
debug!("get_declared_value(name={:?})", name);
let namebuf = CString::new(name).unwrap_or_else(|_|{
bug!("name {:?} contains an interior null byte", name)
});
- let val = unsafe { llvm::LLVMRustGetNamedValue(ccx.llmod(), namebuf.as_ptr()) };
+ let val = unsafe { llvm::LLVMRustGetNamedValue(cx.llmod, namebuf.as_ptr()) };
if val.is_null() {
debug!("get_declared_value: {:?} value is null", name);
None
/// Get defined or externally defined (AvailableExternally linkage) value by
/// name.
-pub fn get_defined_value(ccx: &CrateContext, name: &str) -> Option<ValueRef> {
- get_declared_value(ccx, name).and_then(|val|{
+pub fn get_defined_value(cx: &CodegenCx, name: &str) -> Option<ValueRef> {
+ get_declared_value(cx, name).and_then(|val|{
let declaration = unsafe {
llvm::LLVMIsDeclaration(val) != 0
};
use rustc::ty::{self, Ty};
use value::Value;
-pub fn size_and_align_of_dst<'a, 'tcx>(bcx: &Builder<'a, 'tcx>, t: Ty<'tcx>, info: ValueRef)
+pub fn size_and_align_of_dst<'a, 'tcx>(bx: &Builder<'a, 'tcx>, t: Ty<'tcx>, info: ValueRef)
-> (ValueRef, ValueRef) {
debug!("calculate size of DST: {}; with lost info: {:?}",
t, Value(info));
- if bcx.ccx.shared().type_is_sized(t) {
- let (size, align) = bcx.ccx.size_and_align_of(t);
+ if bx.cx.type_is_sized(t) {
+ let (size, align) = bx.cx.size_and_align_of(t);
debug!("size_and_align_of_dst t={} info={:?} size: {:?} align: {:?}",
t, Value(info), size, align);
- let size = C_usize(bcx.ccx, size.bytes());
- let align = C_usize(bcx.ccx, align.abi());
+ let size = C_usize(bx.cx, size.bytes());
+ let align = C_usize(bx.cx, align.abi());
return (size, align);
}
assert!(!info.is_null());
match t.sty {
ty::TyDynamic(..) => {
// load size/align from vtable
- (meth::SIZE.get_usize(bcx, info), meth::ALIGN.get_usize(bcx, info))
+ (meth::SIZE.get_usize(bx, info), meth::ALIGN.get_usize(bx, info))
}
ty::TySlice(_) | ty::TyStr => {
- let unit = t.sequence_element_type(bcx.tcx());
+ let unit = t.sequence_element_type(bx.tcx());
// The info in this case is the length of the str, so the size is that
// times the unit size.
- let (size, align) = bcx.ccx.size_and_align_of(unit);
- (bcx.mul(info, C_usize(bcx.ccx, size.bytes())),
- C_usize(bcx.ccx, align.abi()))
+ let (size, align) = bx.cx.size_and_align_of(unit);
+ (bx.mul(info, C_usize(bx.cx, size.bytes())),
+ C_usize(bx.cx, align.abi()))
}
_ => {
- let ccx = bcx.ccx;
+ let cx = bx.cx;
// First get the size of all statically known fields.
// Don't use size_of because it also rounds up to alignment, which we
// want to avoid, as the unsized field's alignment could be smaller.
assert!(!t.is_simd());
- let layout = ccx.layout_of(t);
+ let layout = cx.layout_of(t);
debug!("DST {} layout: {:?}", t, layout);
let i = layout.fields.count() - 1;
let sized_align = layout.align.abi();
debug!("DST {} statically sized prefix size: {} align: {}",
t, sized_size, sized_align);
- let sized_size = C_usize(ccx, sized_size);
- let sized_align = C_usize(ccx, sized_align);
+ let sized_size = C_usize(cx, sized_size);
+ let sized_align = C_usize(cx, sized_align);
// Recurse to get the size of the dynamically sized field (must be
// the last field).
- let field_ty = layout.field(ccx, i).ty;
- let (unsized_size, mut unsized_align) = size_and_align_of_dst(bcx, field_ty, info);
+ let field_ty = layout.field(cx, i).ty;
+ let (unsized_size, mut unsized_align) = size_and_align_of_dst(bx, field_ty, info);
// FIXME (#26403, #27023): We should be adding padding
// to `sized_size` (to accommodate the `unsized_align`
// here. But this is where the add would go.)
// Return the sum of sizes and max of aligns.
- let size = bcx.add(sized_size, unsized_size);
+ let size = bx.add(sized_size, unsized_size);
// Packed types ignore the alignment of their fields.
if let ty::TyAdt(def, _) = t.sty {
(Some(sized_align), Some(unsized_align)) => {
// If both alignments are constant, (the sized_align should always be), then
// pick the correct alignment statically.
- C_usize(ccx, std::cmp::max(sized_align, unsized_align) as u64)
+ C_usize(cx, std::cmp::max(sized_align, unsized_align) as u64)
}
- _ => bcx.select(bcx.icmp(llvm::IntUGT, sized_align, unsized_align),
+ _ => bx.select(bx.icmp(llvm::IntUGT, sized_align, unsized_align),
sized_align,
unsized_align)
};
//
// `(size + (align-1)) & -align`
- let addend = bcx.sub(align, C_usize(bcx.ccx, 1));
- let size = bcx.and(bcx.add(size, addend), bcx.neg(align));
+ let addend = bx.sub(align, C_usize(bx.cx, 1));
+ let size = bx.and(bx.add(size, addend), bx.neg(align));
(size, align)
}
use std::cmp::Ordering;
use std::iter;
-fn get_simple_intrinsic(ccx: &CrateContext, name: &str) -> Option<ValueRef> {
+fn get_simple_intrinsic(cx: &CodegenCx, name: &str) -> Option<ValueRef> {
let llvm_name = match name {
"sqrtf32" => "llvm.sqrt.f32",
"sqrtf64" => "llvm.sqrt.f64",
"abort" => "llvm.trap",
_ => return None
};
- Some(ccx.get_intrinsic(&llvm_name))
+ Some(cx.get_intrinsic(&llvm_name))
}
/// Remember to add all intrinsics here, in librustc_typeck/check/mod.rs,
/// and in libcore/intrinsics.rs; if you need access to any llvm intrinsics,
/// add them to librustc_trans/trans/context.rs
-pub fn trans_intrinsic_call<'a, 'tcx>(bcx: &Builder<'a, 'tcx>,
+pub fn trans_intrinsic_call<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
callee_ty: Ty<'tcx>,
fn_ty: &FnType<'tcx>,
args: &[OperandRef<'tcx>],
llresult: ValueRef,
span: Span) {
- let ccx = bcx.ccx;
- let tcx = ccx.tcx();
+ let cx = bx.cx;
+ let tcx = cx.tcx;
let (def_id, substs) = match callee_ty.sty {
ty::TyFnDef(def_id, substs) => (def_id, substs),
let ret_ty = sig.output();
let name = &*tcx.item_name(def_id);
- let llret_ty = ccx.layout_of(ret_ty).llvm_type(ccx);
+ let llret_ty = cx.layout_of(ret_ty).llvm_type(cx);
let result = PlaceRef::new_sized(llresult, fn_ty.ret.layout, fn_ty.ret.layout.align);
- let simple = get_simple_intrinsic(ccx, name);
+ let simple = get_simple_intrinsic(cx, name);
let llval = match name {
_ if simple.is_some() => {
- bcx.call(simple.unwrap(),
+ bx.call(simple.unwrap(),
&args.iter().map(|arg| arg.immediate()).collect::<Vec<_>>(),
None)
}
return;
},
"likely" => {
- let expect = ccx.get_intrinsic(&("llvm.expect.i1"));
- bcx.call(expect, &[args[0].immediate(), C_bool(ccx, true)], None)
+ let expect = cx.get_intrinsic(&("llvm.expect.i1"));
+ bx.call(expect, &[args[0].immediate(), C_bool(cx, true)], None)
}
"unlikely" => {
- let expect = ccx.get_intrinsic(&("llvm.expect.i1"));
- bcx.call(expect, &[args[0].immediate(), C_bool(ccx, false)], None)
+ let expect = cx.get_intrinsic(&("llvm.expect.i1"));
+ bx.call(expect, &[args[0].immediate(), C_bool(cx, false)], None)
}
"try" => {
- try_intrinsic(bcx, ccx,
+ try_intrinsic(bx, cx,
args[0].immediate(),
args[1].immediate(),
args[2].immediate(),
return;
}
"breakpoint" => {
- let llfn = ccx.get_intrinsic(&("llvm.debugtrap"));
- bcx.call(llfn, &[], None)
+ let llfn = cx.get_intrinsic(&("llvm.debugtrap"));
+ bx.call(llfn, &[], None)
}
"size_of" => {
let tp_ty = substs.type_at(0);
- C_usize(ccx, ccx.size_of(tp_ty).bytes())
+ C_usize(cx, cx.size_of(tp_ty).bytes())
}
"size_of_val" => {
let tp_ty = substs.type_at(0);
if let OperandValue::Pair(_, meta) = args[0].val {
let (llsize, _) =
- glue::size_and_align_of_dst(bcx, tp_ty, meta);
+ glue::size_and_align_of_dst(bx, tp_ty, meta);
llsize
} else {
- C_usize(ccx, ccx.size_of(tp_ty).bytes())
+ C_usize(cx, cx.size_of(tp_ty).bytes())
}
}
"min_align_of" => {
let tp_ty = substs.type_at(0);
- C_usize(ccx, ccx.align_of(tp_ty).abi())
+ C_usize(cx, cx.align_of(tp_ty).abi())
}
"min_align_of_val" => {
let tp_ty = substs.type_at(0);
if let OperandValue::Pair(_, meta) = args[0].val {
let (_, llalign) =
- glue::size_and_align_of_dst(bcx, tp_ty, meta);
+ glue::size_and_align_of_dst(bx, tp_ty, meta);
llalign
} else {
- C_usize(ccx, ccx.align_of(tp_ty).abi())
+ C_usize(cx, cx.align_of(tp_ty).abi())
}
}
"pref_align_of" => {
let tp_ty = substs.type_at(0);
- C_usize(ccx, ccx.align_of(tp_ty).pref())
+ C_usize(cx, cx.align_of(tp_ty).pref())
}
"type_name" => {
let tp_ty = substs.type_at(0);
let ty_name = Symbol::intern(&tp_ty.to_string()).as_str();
- C_str_slice(ccx, ty_name)
+ C_str_slice(cx, ty_name)
}
"type_id" => {
- C_u64(ccx, ccx.tcx().type_id_hash(substs.type_at(0)))
+ C_u64(cx, cx.tcx.type_id_hash(substs.type_at(0)))
}
"init" => {
let ty = substs.type_at(0);
- if !ccx.layout_of(ty).is_zst() {
+ if !cx.layout_of(ty).is_zst() {
// Just zero out the stack slot.
// If we store a zero constant, LLVM will drown in vreg allocation for large data
// structures, and the generated code will be awful. (A telltale sign of this is
// large quantities of `mov [byte ptr foo],0` in the generated code.)
- memset_intrinsic(bcx, false, ty, llresult, C_u8(ccx, 0), C_usize(ccx, 1));
+ memset_intrinsic(bx, false, ty, llresult, C_u8(cx, 0), C_usize(cx, 1));
}
return;
}
"needs_drop" => {
let tp_ty = substs.type_at(0);
- C_bool(ccx, bcx.ccx.shared().type_needs_drop(tp_ty))
+ C_bool(cx, bx.cx.type_needs_drop(tp_ty))
}
"offset" => {
let ptr = args[0].immediate();
let offset = args[1].immediate();
- bcx.inbounds_gep(ptr, &[offset])
+ bx.inbounds_gep(ptr, &[offset])
}
"arith_offset" => {
let ptr = args[0].immediate();
let offset = args[1].immediate();
- bcx.gep(ptr, &[offset])
+ bx.gep(ptr, &[offset])
}
"copy_nonoverlapping" => {
- copy_intrinsic(bcx, false, false, substs.type_at(0),
+ copy_intrinsic(bx, false, false, substs.type_at(0),
args[1].immediate(), args[0].immediate(), args[2].immediate())
}
"copy" => {
- copy_intrinsic(bcx, true, false, substs.type_at(0),
+ copy_intrinsic(bx, true, false, substs.type_at(0),
args[1].immediate(), args[0].immediate(), args[2].immediate())
}
"write_bytes" => {
- memset_intrinsic(bcx, false, substs.type_at(0),
+ memset_intrinsic(bx, false, substs.type_at(0),
args[0].immediate(), args[1].immediate(), args[2].immediate())
}
"volatile_copy_nonoverlapping_memory" => {
- copy_intrinsic(bcx, false, true, substs.type_at(0),
+ copy_intrinsic(bx, false, true, substs.type_at(0),
args[0].immediate(), args[1].immediate(), args[2].immediate())
}
"volatile_copy_memory" => {
- copy_intrinsic(bcx, true, true, substs.type_at(0),
+ copy_intrinsic(bx, true, true, substs.type_at(0),
args[0].immediate(), args[1].immediate(), args[2].immediate())
}
"volatile_set_memory" => {
- memset_intrinsic(bcx, true, substs.type_at(0),
+ memset_intrinsic(bx, true, substs.type_at(0),
args[0].immediate(), args[1].immediate(), args[2].immediate())
}
"volatile_load" => {
let tp_ty = substs.type_at(0);
let mut ptr = args[0].immediate();
if let PassMode::Cast(ty) = fn_ty.ret.mode {
- ptr = bcx.pointercast(ptr, ty.llvm_type(ccx).ptr_to());
+ ptr = bx.pointercast(ptr, ty.llvm_type(cx).ptr_to());
}
- let load = bcx.volatile_load(ptr);
+ let load = bx.volatile_load(ptr);
unsafe {
- llvm::LLVMSetAlignment(load, ccx.align_of(tp_ty).abi() as u32);
+ llvm::LLVMSetAlignment(load, cx.align_of(tp_ty).abi() as u32);
}
- to_immediate(bcx, load, ccx.layout_of(tp_ty))
+ to_immediate(bx, load, cx.layout_of(tp_ty))
},
"volatile_store" => {
let tp_ty = substs.type_at(0);
- let dst = args[0].deref(bcx.ccx);
+ let dst = args[0].deref(bx.cx);
if let OperandValue::Pair(a, b) = args[1].val {
- bcx.volatile_store(a, dst.project_field(bcx, 0).llval);
- bcx.volatile_store(b, dst.project_field(bcx, 1).llval);
+ bx.volatile_store(a, dst.project_field(bx, 0).llval);
+ bx.volatile_store(b, dst.project_field(bx, 1).llval);
} else {
let val = if let OperandValue::Ref(ptr, align) = args[1].val {
- bcx.load(ptr, align)
+ bx.load(ptr, align)
} else {
if dst.layout.is_zst() {
return;
}
- from_immediate(bcx, args[1].immediate())
+ from_immediate(bx, args[1].immediate())
};
- let ptr = bcx.pointercast(dst.llval, val_ty(val).ptr_to());
- let store = bcx.volatile_store(val, ptr);
+ let ptr = bx.pointercast(dst.llval, val_ty(val).ptr_to());
+ let store = bx.volatile_store(val, ptr);
unsafe {
- llvm::LLVMSetAlignment(store, ccx.align_of(tp_ty).abi() as u32);
+ llvm::LLVMSetAlignment(store, cx.align_of(tp_ty).abi() as u32);
}
}
return;
},
"prefetch_read_data" | "prefetch_write_data" |
"prefetch_read_instruction" | "prefetch_write_instruction" => {
- let expect = ccx.get_intrinsic(&("llvm.prefetch"));
+ let expect = cx.get_intrinsic(&("llvm.prefetch"));
let (rw, cache_type) = match name {
"prefetch_read_data" => (0, 1),
"prefetch_write_data" => (1, 1),
"prefetch_write_instruction" => (1, 0),
_ => bug!()
};
- bcx.call(expect, &[
+ bx.call(expect, &[
args[0].immediate(),
- C_i32(ccx, rw),
+ C_i32(cx, rw),
args[1].immediate(),
- C_i32(ccx, cache_type)
+ C_i32(cx, cache_type)
], None)
},
"ctlz" | "ctlz_nonzero" | "cttz" | "cttz_nonzero" | "ctpop" | "bswap" |
"overflowing_add" | "overflowing_sub" | "overflowing_mul" |
"unchecked_div" | "unchecked_rem" | "unchecked_shl" | "unchecked_shr" => {
let ty = arg_tys[0];
- match int_type_width_signed(ty, ccx) {
+ match int_type_width_signed(ty, cx) {
Some((width, signed)) =>
match name {
"ctlz" | "cttz" => {
- let y = C_bool(bcx.ccx, false);
- let llfn = ccx.get_intrinsic(&format!("llvm.{}.i{}", name, width));
- bcx.call(llfn, &[args[0].immediate(), y], None)
+ let y = C_bool(bx.cx, false);
+ let llfn = cx.get_intrinsic(&format!("llvm.{}.i{}", name, width));
+ bx.call(llfn, &[args[0].immediate(), y], None)
}
"ctlz_nonzero" | "cttz_nonzero" => {
- let y = C_bool(bcx.ccx, true);
+ let y = C_bool(bx.cx, true);
let llvm_name = &format!("llvm.{}.i{}", &name[..4], width);
- let llfn = ccx.get_intrinsic(llvm_name);
- bcx.call(llfn, &[args[0].immediate(), y], None)
+ let llfn = cx.get_intrinsic(llvm_name);
+ bx.call(llfn, &[args[0].immediate(), y], None)
}
- "ctpop" => bcx.call(ccx.get_intrinsic(&format!("llvm.ctpop.i{}", width)),
+ "ctpop" => bx.call(cx.get_intrinsic(&format!("llvm.ctpop.i{}", width)),
&[args[0].immediate()], None),
"bswap" => {
if width == 8 {
args[0].immediate() // byte swap a u8/i8 is just a no-op
} else {
- bcx.call(ccx.get_intrinsic(&format!("llvm.bswap.i{}", width)),
+ bx.call(cx.get_intrinsic(&format!("llvm.bswap.i{}", width)),
&[args[0].immediate()], None)
}
}
let intrinsic = format!("llvm.{}{}.with.overflow.i{}",
if signed { 's' } else { 'u' },
&name[..3], width);
- let llfn = bcx.ccx.get_intrinsic(&intrinsic);
+ let llfn = bx.cx.get_intrinsic(&intrinsic);
// Convert `i1` to a `bool`, and write it to the out parameter
- let pair = bcx.call(llfn, &[
+ let pair = bx.call(llfn, &[
args[0].immediate(),
args[1].immediate()
], None);
- let val = bcx.extract_value(pair, 0);
- let overflow = bcx.zext(bcx.extract_value(pair, 1), Type::bool(ccx));
+ let val = bx.extract_value(pair, 0);
+ let overflow = bx.zext(bx.extract_value(pair, 1), Type::bool(cx));
- let dest = result.project_field(bcx, 0);
- bcx.store(val, dest.llval, dest.align);
- let dest = result.project_field(bcx, 1);
- bcx.store(overflow, dest.llval, dest.align);
+ let dest = result.project_field(bx, 0);
+ bx.store(val, dest.llval, dest.align);
+ let dest = result.project_field(bx, 1);
+ bx.store(overflow, dest.llval, dest.align);
return;
},
- "overflowing_add" => bcx.add(args[0].immediate(), args[1].immediate()),
- "overflowing_sub" => bcx.sub(args[0].immediate(), args[1].immediate()),
- "overflowing_mul" => bcx.mul(args[0].immediate(), args[1].immediate()),
+ "overflowing_add" => bx.add(args[0].immediate(), args[1].immediate()),
+ "overflowing_sub" => bx.sub(args[0].immediate(), args[1].immediate()),
+ "overflowing_mul" => bx.mul(args[0].immediate(), args[1].immediate()),
"unchecked_div" =>
if signed {
- bcx.sdiv(args[0].immediate(), args[1].immediate())
+ bx.sdiv(args[0].immediate(), args[1].immediate())
} else {
- bcx.udiv(args[0].immediate(), args[1].immediate())
+ bx.udiv(args[0].immediate(), args[1].immediate())
},
"unchecked_rem" =>
if signed {
- bcx.srem(args[0].immediate(), args[1].immediate())
+ bx.srem(args[0].immediate(), args[1].immediate())
} else {
- bcx.urem(args[0].immediate(), args[1].immediate())
+ bx.urem(args[0].immediate(), args[1].immediate())
},
- "unchecked_shl" => bcx.shl(args[0].immediate(), args[1].immediate()),
+ "unchecked_shl" => bx.shl(args[0].immediate(), args[1].immediate()),
"unchecked_shr" =>
if signed {
- bcx.ashr(args[0].immediate(), args[1].immediate())
+ bx.ashr(args[0].immediate(), args[1].immediate())
} else {
- bcx.lshr(args[0].immediate(), args[1].immediate())
+ bx.lshr(args[0].immediate(), args[1].immediate())
},
_ => bug!(),
},
match float_type_width(sty) {
Some(_width) =>
match name {
- "fadd_fast" => bcx.fadd_fast(args[0].immediate(), args[1].immediate()),
- "fsub_fast" => bcx.fsub_fast(args[0].immediate(), args[1].immediate()),
- "fmul_fast" => bcx.fmul_fast(args[0].immediate(), args[1].immediate()),
- "fdiv_fast" => bcx.fdiv_fast(args[0].immediate(), args[1].immediate()),
- "frem_fast" => bcx.frem_fast(args[0].immediate(), args[1].immediate()),
+ "fadd_fast" => bx.fadd_fast(args[0].immediate(), args[1].immediate()),
+ "fsub_fast" => bx.fsub_fast(args[0].immediate(), args[1].immediate()),
+ "fmul_fast" => bx.fmul_fast(args[0].immediate(), args[1].immediate()),
+ "fdiv_fast" => bx.fdiv_fast(args[0].immediate(), args[1].immediate()),
+ "frem_fast" => bx.frem_fast(args[0].immediate(), args[1].immediate()),
_ => bug!(),
},
None => {
},
"discriminant_value" => {
- args[0].deref(bcx.ccx).trans_get_discr(bcx, ret_ty)
+ args[0].deref(bx.cx).trans_get_discr(bx, ret_ty)
}
"align_offset" => {
// `ptr as usize`
- let ptr_val = bcx.ptrtoint(args[0].immediate(), bcx.ccx.isize_ty());
+ let ptr_val = bx.ptrtoint(args[0].immediate(), bx.cx.isize_ty);
// `ptr_val % align`
let align = args[1].immediate();
- let offset = bcx.urem(ptr_val, align);
- let zero = C_null(bcx.ccx.isize_ty());
+ let offset = bx.urem(ptr_val, align);
+ let zero = C_null(bx.cx.isize_ty);
// `offset == 0`
- let is_zero = bcx.icmp(llvm::IntPredicate::IntEQ, offset, zero);
+ let is_zero = bx.icmp(llvm::IntPredicate::IntEQ, offset, zero);
// `if offset == 0 { 0 } else { align - offset }`
- bcx.select(is_zero, zero, bcx.sub(align, offset))
+ bx.select(is_zero, zero, bx.sub(align, offset))
}
name if name.starts_with("simd_") => {
- match generic_simd_intrinsic(bcx, name,
+ match generic_simd_intrinsic(bx, name,
callee_ty,
args,
ret_ty, llret_ty,
(SequentiallyConsistent, Monotonic),
"failacq" if is_cxchg =>
(SequentiallyConsistent, Acquire),
- _ => ccx.sess().fatal("unknown ordering in atomic intrinsic")
+ _ => cx.sess().fatal("unknown ordering in atomic intrinsic")
},
4 => match (split[2], split[3]) {
("acq", "failrelaxed") if is_cxchg =>
(Acquire, Monotonic),
("acqrel", "failrelaxed") if is_cxchg =>
(AcquireRelease, Monotonic),
- _ => ccx.sess().fatal("unknown ordering in atomic intrinsic")
+ _ => cx.sess().fatal("unknown ordering in atomic intrinsic")
},
- _ => ccx.sess().fatal("Atomic intrinsic not in correct format"),
+ _ => cx.sess().fatal("Atomic intrinsic not in correct format"),
};
let invalid_monomorphization = |ty| {
match split[1] {
"cxchg" | "cxchgweak" => {
let ty = substs.type_at(0);
- if int_type_width_signed(ty, ccx).is_some() {
+ if int_type_width_signed(ty, cx).is_some() {
let weak = if split[1] == "cxchgweak" { llvm::True } else { llvm::False };
- let pair = bcx.atomic_cmpxchg(
+ let pair = bx.atomic_cmpxchg(
args[0].immediate(),
args[1].immediate(),
args[2].immediate(),
order,
failorder,
weak);
- let val = bcx.extract_value(pair, 0);
- let success = bcx.zext(bcx.extract_value(pair, 1), Type::bool(bcx.ccx));
+ let val = bx.extract_value(pair, 0);
+ let success = bx.zext(bx.extract_value(pair, 1), Type::bool(bx.cx));
- let dest = result.project_field(bcx, 0);
- bcx.store(val, dest.llval, dest.align);
- let dest = result.project_field(bcx, 1);
- bcx.store(success, dest.llval, dest.align);
+ let dest = result.project_field(bx, 0);
+ bx.store(val, dest.llval, dest.align);
+ let dest = result.project_field(bx, 1);
+ bx.store(success, dest.llval, dest.align);
return;
} else {
return invalid_monomorphization(ty);
"load" => {
let ty = substs.type_at(0);
- if int_type_width_signed(ty, ccx).is_some() {
- let align = ccx.align_of(ty);
- bcx.atomic_load(args[0].immediate(), order, align)
+ if int_type_width_signed(ty, cx).is_some() {
+ let align = cx.align_of(ty);
+ bx.atomic_load(args[0].immediate(), order, align)
} else {
return invalid_monomorphization(ty);
}
"store" => {
let ty = substs.type_at(0);
- if int_type_width_signed(ty, ccx).is_some() {
- let align = ccx.align_of(ty);
- bcx.atomic_store(args[1].immediate(), args[0].immediate(), order, align);
+ if int_type_width_signed(ty, cx).is_some() {
+ let align = cx.align_of(ty);
+ bx.atomic_store(args[1].immediate(), args[0].immediate(), order, align);
return;
} else {
return invalid_monomorphization(ty);
}
"fence" => {
- bcx.atomic_fence(order, llvm::SynchronizationScope::CrossThread);
+ bx.atomic_fence(order, llvm::SynchronizationScope::CrossThread);
return;
}
"singlethreadfence" => {
- bcx.atomic_fence(order, llvm::SynchronizationScope::SingleThread);
+ bx.atomic_fence(order, llvm::SynchronizationScope::SingleThread);
return;
}
"min" => llvm::AtomicMin,
"umax" => llvm::AtomicUMax,
"umin" => llvm::AtomicUMin,
- _ => ccx.sess().fatal("unknown atomic operation")
+ _ => cx.sess().fatal("unknown atomic operation")
};
let ty = substs.type_at(0);
- if int_type_width_signed(ty, ccx).is_some() {
- bcx.atomic_rmw(atom_op, args[0].immediate(), args[1].immediate(), order)
+ if int_type_width_signed(ty, cx).is_some() {
+ bx.atomic_rmw(atom_op, args[0].immediate(), args[1].immediate(), order)
} else {
return invalid_monomorphization(ty);
}
"nontemporal_store" => {
let tp_ty = substs.type_at(0);
- let dst = args[0].deref(bcx.ccx);
+ let dst = args[0].deref(bx.cx);
let val = if let OperandValue::Ref(ptr, align) = args[1].val {
- bcx.load(ptr, align)
+ bx.load(ptr, align)
} else {
- from_immediate(bcx, args[1].immediate())
+ from_immediate(bx, args[1].immediate())
};
- let ptr = bcx.pointercast(dst.llval, val_ty(val).ptr_to());
- let store = bcx.nontemporal_store(val, ptr);
+ let ptr = bx.pointercast(dst.llval, val_ty(val).ptr_to());
+ let store = bx.nontemporal_store(val, ptr);
unsafe {
- llvm::LLVMSetAlignment(store, ccx.align_of(tp_ty).abi() as u32);
+ llvm::LLVMSetAlignment(store, cx.align_of(tp_ty).abi() as u32);
}
return
}
assert_eq!(x.len(), 1);
x.into_iter().next().unwrap()
}
- fn ty_to_type(ccx: &CrateContext, t: &intrinsics::Type) -> Vec<Type> {
+ fn ty_to_type(cx: &CodegenCx, t: &intrinsics::Type) -> Vec<Type> {
use intrinsics::Type::*;
match *t {
- Void => vec![Type::void(ccx)],
+ Void => vec![Type::void(cx)],
Integer(_signed, _width, llvm_width) => {
- vec![Type::ix(ccx, llvm_width as u64)]
+ vec![Type::ix(cx, llvm_width as u64)]
}
Float(x) => {
match x {
- 32 => vec![Type::f32(ccx)],
- 64 => vec![Type::f64(ccx)],
+ 32 => vec![Type::f32(cx)],
+ 64 => vec![Type::f64(cx)],
_ => bug!()
}
}
Pointer(ref t, ref llvm_elem, _const) => {
let t = llvm_elem.as_ref().unwrap_or(t);
- let elem = one(ty_to_type(ccx, t));
+ let elem = one(ty_to_type(cx, t));
vec![elem.ptr_to()]
}
Vector(ref t, ref llvm_elem, length) => {
let t = llvm_elem.as_ref().unwrap_or(t);
- let elem = one(ty_to_type(ccx, t));
+ let elem = one(ty_to_type(cx, t));
vec![Type::vector(&elem, length as u64)]
}
Aggregate(false, ref contents) => {
let elems = contents.iter()
- .map(|t| one(ty_to_type(ccx, t)))
+ .map(|t| one(ty_to_type(cx, t)))
.collect::<Vec<_>>();
- vec![Type::struct_(ccx, &elems, false)]
+ vec![Type::struct_(cx, &elems, false)]
}
Aggregate(true, ref contents) => {
contents.iter()
- .flat_map(|t| ty_to_type(ccx, t))
+ .flat_map(|t| ty_to_type(cx, t))
.collect()
}
}
// qux` to be converted into `foo, bar, baz, qux`, integer
// arguments to be truncated as needed and pointers to be
// cast.
- fn modify_as_needed<'a, 'tcx>(bcx: &Builder<'a, 'tcx>,
+ fn modify_as_needed<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
t: &intrinsics::Type,
arg: &OperandRef<'tcx>)
-> Vec<ValueRef>
// This assumes the type is "simple", i.e. no
// destructors, and the contents are SIMD
// etc.
- assert!(!bcx.ccx.shared().type_needs_drop(arg.layout.ty));
+ assert!(!bx.cx.type_needs_drop(arg.layout.ty));
let (ptr, align) = match arg.val {
OperandValue::Ref(ptr, align) => (ptr, align),
_ => bug!()
};
let arg = PlaceRef::new_sized(ptr, arg.layout, align);
(0..contents.len()).map(|i| {
- arg.project_field(bcx, i).load(bcx).immediate()
+ arg.project_field(bx, i).load(bx).immediate()
}).collect()
}
intrinsics::Type::Pointer(_, Some(ref llvm_elem), _) => {
- let llvm_elem = one(ty_to_type(bcx.ccx, llvm_elem));
- vec![bcx.pointercast(arg.immediate(), llvm_elem.ptr_to())]
+ let llvm_elem = one(ty_to_type(bx.cx, llvm_elem));
+ vec![bx.pointercast(arg.immediate(), llvm_elem.ptr_to())]
}
intrinsics::Type::Vector(_, Some(ref llvm_elem), length) => {
- let llvm_elem = one(ty_to_type(bcx.ccx, llvm_elem));
- vec![bcx.bitcast(arg.immediate(), Type::vector(&llvm_elem, length as u64))]
+ let llvm_elem = one(ty_to_type(bx.cx, llvm_elem));
+ vec![bx.bitcast(arg.immediate(), Type::vector(&llvm_elem, length as u64))]
}
intrinsics::Type::Integer(_, width, llvm_width) if width != llvm_width => {
// the LLVM intrinsic uses a smaller integer
// size than the C intrinsic's signature, so
// we have to trim it down here.
- vec![bcx.trunc(arg.immediate(), Type::ix(bcx.ccx, llvm_width as u64))]
+ vec![bx.trunc(arg.immediate(), Type::ix(bx.cx, llvm_width as u64))]
}
_ => vec![arg.immediate()],
}
let inputs = intr.inputs.iter()
- .flat_map(|t| ty_to_type(ccx, t))
+ .flat_map(|t| ty_to_type(cx, t))
.collect::<Vec<_>>();
- let outputs = one(ty_to_type(ccx, &intr.output));
+ let outputs = one(ty_to_type(cx, &intr.output));
let llargs: Vec<_> = intr.inputs.iter().zip(args).flat_map(|(t, arg)| {
- modify_as_needed(bcx, t, arg)
+ modify_as_needed(bx, t, arg)
}).collect();
assert_eq!(inputs.len(), llargs.len());
let val = match intr.definition {
intrinsics::IntrinsicDef::Named(name) => {
- let f = declare::declare_cfn(ccx,
+ let f = declare::declare_cfn(cx,
name,
Type::func(&inputs, &outputs));
- bcx.call(f, &llargs, None)
+ bx.call(f, &llargs, None)
}
};
assert!(!flatten);
for i in 0..elems.len() {
- let dest = result.project_field(bcx, i);
- let val = bcx.extract_value(val, i as u64);
- bcx.store(val, dest.llval, dest.align);
+ let dest = result.project_field(bx, i);
+ let val = bx.extract_value(val, i as u64);
+ bx.store(val, dest.llval, dest.align);
}
return;
}
if !fn_ty.ret.is_ignore() {
if let PassMode::Cast(ty) = fn_ty.ret.mode {
- let ptr = bcx.pointercast(result.llval, ty.llvm_type(ccx).ptr_to());
- bcx.store(llval, ptr, result.align);
+ let ptr = bx.pointercast(result.llval, ty.llvm_type(cx).ptr_to());
+ bx.store(llval, ptr, result.align);
} else {
- OperandRef::from_immediate_or_packed_pair(bcx, llval, result.layout)
- .val.store(bcx, result);
+ OperandRef::from_immediate_or_packed_pair(bx, llval, result.layout)
+ .val.store(bx, result);
}
}
}
-fn copy_intrinsic<'a, 'tcx>(bcx: &Builder<'a, 'tcx>,
+fn copy_intrinsic<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
allow_overlap: bool,
volatile: bool,
ty: Ty<'tcx>,
src: ValueRef,
count: ValueRef)
-> ValueRef {
- let ccx = bcx.ccx;
- let (size, align) = ccx.size_and_align_of(ty);
- let size = C_usize(ccx, size.bytes());
- let align = C_i32(ccx, align.abi() as i32);
+ let cx = bx.cx;
+ let (size, align) = cx.size_and_align_of(ty);
+ let size = C_usize(cx, size.bytes());
+ let align = C_i32(cx, align.abi() as i32);
let operation = if allow_overlap {
"memmove"
};
let name = format!("llvm.{}.p0i8.p0i8.i{}", operation,
- ccx.data_layout().pointer_size.bits());
+ cx.data_layout().pointer_size.bits());
- let dst_ptr = bcx.pointercast(dst, Type::i8p(ccx));
- let src_ptr = bcx.pointercast(src, Type::i8p(ccx));
- let llfn = ccx.get_intrinsic(&name);
+ let dst_ptr = bx.pointercast(dst, Type::i8p(cx));
+ let src_ptr = bx.pointercast(src, Type::i8p(cx));
+ let llfn = cx.get_intrinsic(&name);
- bcx.call(llfn,
+ bx.call(llfn,
&[dst_ptr,
src_ptr,
- bcx.mul(size, count),
+ bx.mul(size, count),
align,
- C_bool(ccx, volatile)],
+ C_bool(cx, volatile)],
None)
}
fn memset_intrinsic<'a, 'tcx>(
- bcx: &Builder<'a, 'tcx>,
+ bx: &Builder<'a, 'tcx>,
volatile: bool,
ty: Ty<'tcx>,
dst: ValueRef,
val: ValueRef,
count: ValueRef
) -> ValueRef {
- let ccx = bcx.ccx;
- let (size, align) = ccx.size_and_align_of(ty);
- let size = C_usize(ccx, size.bytes());
- let align = C_i32(ccx, align.abi() as i32);
- let dst = bcx.pointercast(dst, Type::i8p(ccx));
- call_memset(bcx, dst, val, bcx.mul(size, count), align, volatile)
+ let cx = bx.cx;
+ let (size, align) = cx.size_and_align_of(ty);
+ let size = C_usize(cx, size.bytes());
+ let align = C_i32(cx, align.abi() as i32);
+ let dst = bx.pointercast(dst, Type::i8p(cx));
+ call_memset(bx, dst, val, bx.mul(size, count), align, volatile)
}
fn try_intrinsic<'a, 'tcx>(
- bcx: &Builder<'a, 'tcx>,
- ccx: &CrateContext,
+ bx: &Builder<'a, 'tcx>,
+ cx: &CodegenCx,
func: ValueRef,
data: ValueRef,
local_ptr: ValueRef,
dest: ValueRef,
) {
- if bcx.sess().no_landing_pads() {
- bcx.call(func, &[data], None);
- let ptr_align = bcx.tcx().data_layout.pointer_align;
- bcx.store(C_null(Type::i8p(&bcx.ccx)), dest, ptr_align);
- } else if wants_msvc_seh(bcx.sess()) {
- trans_msvc_try(bcx, ccx, func, data, local_ptr, dest);
+ if bx.sess().no_landing_pads() {
+ bx.call(func, &[data], None);
+ let ptr_align = bx.tcx().data_layout.pointer_align;
+ bx.store(C_null(Type::i8p(&bx.cx)), dest, ptr_align);
+ } else if wants_msvc_seh(bx.sess()) {
+ trans_msvc_try(bx, cx, func, data, local_ptr, dest);
} else {
- trans_gnu_try(bcx, ccx, func, data, local_ptr, dest);
+ trans_gnu_try(bx, cx, func, data, local_ptr, dest);
}
}
// instructions are meant to work for all targets, as of the time of this
// writing, however, LLVM does not recommend the usage of these new instructions
// as the old ones are still more optimized.
-fn trans_msvc_try<'a, 'tcx>(bcx: &Builder<'a, 'tcx>,
- ccx: &CrateContext,
+fn trans_msvc_try<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
+ cx: &CodegenCx,
func: ValueRef,
data: ValueRef,
local_ptr: ValueRef,
dest: ValueRef) {
- let llfn = get_rust_try_fn(ccx, &mut |bcx| {
- let ccx = bcx.ccx;
+ let llfn = get_rust_try_fn(cx, &mut |bx| {
+ let cx = bx.cx;
- bcx.set_personality_fn(bcx.ccx.eh_personality());
+ bx.set_personality_fn(bx.cx.eh_personality());
- let normal = bcx.build_sibling_block("normal");
- let catchswitch = bcx.build_sibling_block("catchswitch");
- let catchpad = bcx.build_sibling_block("catchpad");
- let caught = bcx.build_sibling_block("caught");
+ let normal = bx.build_sibling_block("normal");
+ let catchswitch = bx.build_sibling_block("catchswitch");
+ let catchpad = bx.build_sibling_block("catchpad");
+ let caught = bx.build_sibling_block("caught");
- let func = llvm::get_param(bcx.llfn(), 0);
- let data = llvm::get_param(bcx.llfn(), 1);
- let local_ptr = llvm::get_param(bcx.llfn(), 2);
+ let func = llvm::get_param(bx.llfn(), 0);
+ let data = llvm::get_param(bx.llfn(), 1);
+ let local_ptr = llvm::get_param(bx.llfn(), 2);
// We're generating an IR snippet that looks like:
//
// }
//
// More information can be found in libstd's seh.rs implementation.
- let i64p = Type::i64(ccx).ptr_to();
- let ptr_align = bcx.tcx().data_layout.pointer_align;
- let slot = bcx.alloca(i64p, "slot", ptr_align);
- bcx.invoke(func, &[data], normal.llbb(), catchswitch.llbb(),
+ let i64p = Type::i64(cx).ptr_to();
+ let ptr_align = bx.tcx().data_layout.pointer_align;
+ let slot = bx.alloca(i64p, "slot", ptr_align);
+ bx.invoke(func, &[data], normal.llbb(), catchswitch.llbb(),
None);
- normal.ret(C_i32(ccx, 0));
+ normal.ret(C_i32(cx, 0));
let cs = catchswitch.catch_switch(None, None, 1);
catchswitch.add_handler(cs, catchpad.llbb());
- let tcx = ccx.tcx();
+ let tcx = cx.tcx;
let tydesc = match tcx.lang_items().msvc_try_filter() {
- Some(did) => ::consts::get_static(ccx, did),
+ Some(did) => ::consts::get_static(cx, did),
None => bug!("msvc_try_filter not defined"),
};
- let tok = catchpad.catch_pad(cs, &[tydesc, C_i32(ccx, 0), slot]);
+ let tok = catchpad.catch_pad(cs, &[tydesc, C_i32(cx, 0), slot]);
let addr = catchpad.load(slot, ptr_align);
- let i64_align = bcx.tcx().data_layout.i64_align;
+ let i64_align = bx.tcx().data_layout.i64_align;
let arg1 = catchpad.load(addr, i64_align);
- let val1 = C_i32(ccx, 1);
+ let val1 = C_i32(cx, 1);
let arg2 = catchpad.load(catchpad.inbounds_gep(addr, &[val1]), i64_align);
let local_ptr = catchpad.bitcast(local_ptr, i64p);
catchpad.store(arg1, local_ptr, i64_align);
catchpad.store(arg2, catchpad.inbounds_gep(local_ptr, &[val1]), i64_align);
catchpad.catch_ret(tok, caught.llbb());
- caught.ret(C_i32(ccx, 1));
+ caught.ret(C_i32(cx, 1));
});
// Note that no invoke is used here because by definition this function
// can't panic (that's what it's catching).
- let ret = bcx.call(llfn, &[func, data, local_ptr], None);
- let i32_align = bcx.tcx().data_layout.i32_align;
- bcx.store(ret, dest, i32_align);
+ let ret = bx.call(llfn, &[func, data, local_ptr], None);
+ let i32_align = bx.tcx().data_layout.i32_align;
+ bx.store(ret, dest, i32_align);
}
// Definition of the standard "try" function for Rust using the GNU-like model
// function calling it, and that function may already have other personality
// functions in play. By calling a shim we're guaranteed that our shim will have
// the right personality function.
-fn trans_gnu_try<'a, 'tcx>(bcx: &Builder<'a, 'tcx>,
- ccx: &CrateContext,
+fn trans_gnu_try<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
+ cx: &CodegenCx,
func: ValueRef,
data: ValueRef,
local_ptr: ValueRef,
dest: ValueRef) {
- let llfn = get_rust_try_fn(ccx, &mut |bcx| {
- let ccx = bcx.ccx;
+ let llfn = get_rust_try_fn(cx, &mut |bx| {
+ let cx = bx.cx;
// Translates the shims described above:
//
- // bcx:
+ // bx:
// invoke %func(%args...) normal %normal unwind %catch
//
// normal:
// expected to be `*mut *mut u8` for this to actually work, but that's
// managed by the standard library.
- let then = bcx.build_sibling_block("then");
- let catch = bcx.build_sibling_block("catch");
+ let then = bx.build_sibling_block("then");
+ let catch = bx.build_sibling_block("catch");
- let func = llvm::get_param(bcx.llfn(), 0);
- let data = llvm::get_param(bcx.llfn(), 1);
- let local_ptr = llvm::get_param(bcx.llfn(), 2);
- bcx.invoke(func, &[data], then.llbb(), catch.llbb(), None);
- then.ret(C_i32(ccx, 0));
+ let func = llvm::get_param(bx.llfn(), 0);
+ let data = llvm::get_param(bx.llfn(), 1);
+ let local_ptr = llvm::get_param(bx.llfn(), 2);
+ bx.invoke(func, &[data], then.llbb(), catch.llbb(), None);
+ then.ret(C_i32(cx, 0));
// Type indicator for the exception being thrown.
//
// being thrown. The second value is a "selector" indicating which of
// the landing pad clauses the exception's type had been matched to.
// rust_try ignores the selector.
- let lpad_ty = Type::struct_(ccx, &[Type::i8p(ccx), Type::i32(ccx)],
+ let lpad_ty = Type::struct_(cx, &[Type::i8p(cx), Type::i32(cx)],
false);
- let vals = catch.landing_pad(lpad_ty, bcx.ccx.eh_personality(), 1, catch.llfn());
- catch.add_clause(vals, C_null(Type::i8p(ccx)));
+ let vals = catch.landing_pad(lpad_ty, bx.cx.eh_personality(), 1);
+ catch.add_clause(vals, C_null(Type::i8p(cx)));
let ptr = catch.extract_value(vals, 0);
- let ptr_align = bcx.tcx().data_layout.pointer_align;
- catch.store(ptr, catch.bitcast(local_ptr, Type::i8p(ccx).ptr_to()), ptr_align);
- catch.ret(C_i32(ccx, 1));
+ let ptr_align = bx.tcx().data_layout.pointer_align;
+ catch.store(ptr, catch.bitcast(local_ptr, Type::i8p(cx).ptr_to()), ptr_align);
+ catch.ret(C_i32(cx, 1));
});
// Note that no invoke is used here because by definition this function
// can't panic (that's what it's catching).
- let ret = bcx.call(llfn, &[func, data, local_ptr], None);
- let i32_align = bcx.tcx().data_layout.i32_align;
- bcx.store(ret, dest, i32_align);
+ let ret = bx.call(llfn, &[func, data, local_ptr], None);
+ let i32_align = bx.tcx().data_layout.i32_align;
+ bx.store(ret, dest, i32_align);
}
// Helper function to give a Block to a closure to translate a shim function.
// This is currently primarily used for the `try` intrinsic functions above.
-fn gen_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
+fn gen_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
name: &str,
inputs: Vec<Ty<'tcx>>,
output: Ty<'tcx>,
trans: &mut for<'b> FnMut(Builder<'b, 'tcx>))
-> ValueRef {
- let rust_fn_ty = ccx.tcx().mk_fn_ptr(ty::Binder(ccx.tcx().mk_fn_sig(
+ let rust_fn_ty = cx.tcx.mk_fn_ptr(ty::Binder(cx.tcx.mk_fn_sig(
inputs.into_iter(),
output,
false,
hir::Unsafety::Unsafe,
Abi::Rust
)));
- let llfn = declare::define_internal_fn(ccx, name, rust_fn_ty);
- let bcx = Builder::new_block(ccx, llfn, "entry-block");
- trans(bcx);
+ let llfn = declare::define_internal_fn(cx, name, rust_fn_ty);
+ let bx = Builder::new_block(cx, llfn, "entry-block");
+ trans(bx);
llfn
}
// catch exceptions.
//
// This function is only generated once and is then cached.
-fn get_rust_try_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
+fn get_rust_try_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
trans: &mut for<'b> FnMut(Builder<'b, 'tcx>))
-> ValueRef {
- if let Some(llfn) = ccx.rust_try_fn().get() {
+ if let Some(llfn) = cx.rust_try_fn.get() {
return llfn;
}
// Define the type up front for the signature of the rust_try function.
- let tcx = ccx.tcx();
+ let tcx = cx.tcx;
let i8p = tcx.mk_mut_ptr(tcx.types.i8);
let fn_ty = tcx.mk_fn_ptr(ty::Binder(tcx.mk_fn_sig(
iter::once(i8p),
Abi::Rust
)));
let output = tcx.types.i32;
- let rust_try = gen_fn(ccx, "__rust_try", vec![fn_ty, i8p, i8p], output, trans);
- ccx.rust_try_fn().set(Some(rust_try));
+ let rust_try = gen_fn(cx, "__rust_try", vec![fn_ty, i8p, i8p], output, trans);
+ cx.rust_try_fn.set(Some(rust_try));
return rust_try
}
}
fn generic_simd_intrinsic<'a, 'tcx>(
- bcx: &Builder<'a, 'tcx>,
+ bx: &Builder<'a, 'tcx>,
name: &str,
callee_ty: Ty<'tcx>,
args: &[OperandRef<'tcx>],
};
($msg: tt, $($fmt: tt)*) => {
span_invalid_monomorphization_error(
- bcx.sess(), span,
+ bx.sess(), span,
&format!(concat!("invalid monomorphization of `{}` intrinsic: ",
$msg),
name, $($fmt)*));
- let tcx = bcx.tcx();
+ let tcx = bx.tcx();
let sig = tcx.erase_late_bound_regions_and_normalize(&callee_ty.fn_sig(tcx));
let arg_tys = sig.inputs();
ret_ty,
ret_ty.simd_type(tcx));
- return Ok(compare_simd_types(bcx,
+ return Ok(compare_simd_types(bx,
args[0].immediate(),
args[1].immediate(),
in_elem,
arg_idx, total_len);
None
}
- Some(idx) => Some(C_i32(bcx.ccx, idx as i32)),
+ Some(idx) => Some(C_i32(bx.cx, idx as i32)),
}
})
.collect();
None => return Ok(C_null(llret_ty))
};
- return Ok(bcx.shuffle_vector(args[0].immediate(),
+ return Ok(bx.shuffle_vector(args[0].immediate(),
args[1].immediate(),
C_vector(&indices)))
}
require!(in_elem == arg_tys[2],
"expected inserted type `{}` (element of input `{}`), found `{}`",
in_elem, in_ty, arg_tys[2]);
- return Ok(bcx.insert_element(args[0].immediate(),
+ return Ok(bx.insert_element(args[0].immediate(),
args[2].immediate(),
args[1].immediate()))
}
require!(ret_ty == in_elem,
"expected return type `{}` (element of input `{}`), found `{}`",
in_elem, in_ty, ret_ty);
- return Ok(bcx.extract_element(args[0].immediate(), args[1].immediate()))
+ return Ok(bx.extract_element(args[0].immediate(), args[1].immediate()))
}
if name == "simd_cast" {
match (in_style, out_style) {
(Style::Int(in_is_signed), Style::Int(_)) => {
return Ok(match in_width.cmp(&out_width) {
- Ordering::Greater => bcx.trunc(args[0].immediate(), llret_ty),
+ Ordering::Greater => bx.trunc(args[0].immediate(), llret_ty),
Ordering::Equal => args[0].immediate(),
Ordering::Less => if in_is_signed {
- bcx.sext(args[0].immediate(), llret_ty)
+ bx.sext(args[0].immediate(), llret_ty)
} else {
- bcx.zext(args[0].immediate(), llret_ty)
+ bx.zext(args[0].immediate(), llret_ty)
}
})
}
(Style::Int(in_is_signed), Style::Float) => {
return Ok(if in_is_signed {
- bcx.sitofp(args[0].immediate(), llret_ty)
+ bx.sitofp(args[0].immediate(), llret_ty)
} else {
- bcx.uitofp(args[0].immediate(), llret_ty)
+ bx.uitofp(args[0].immediate(), llret_ty)
})
}
(Style::Float, Style::Int(out_is_signed)) => {
return Ok(if out_is_signed {
- bcx.fptosi(args[0].immediate(), llret_ty)
+ bx.fptosi(args[0].immediate(), llret_ty)
} else {
- bcx.fptoui(args[0].immediate(), llret_ty)
+ bx.fptoui(args[0].immediate(), llret_ty)
})
}
(Style::Float, Style::Float) => {
return Ok(match in_width.cmp(&out_width) {
- Ordering::Greater => bcx.fptrunc(args[0].immediate(), llret_ty),
+ Ordering::Greater => bx.fptrunc(args[0].immediate(), llret_ty),
Ordering::Equal => args[0].immediate(),
- Ordering::Less => bcx.fpext(args[0].immediate(), llret_ty)
+ Ordering::Less => bx.fpext(args[0].immediate(), llret_ty)
})
}
_ => {/* Unsupported. Fallthrough. */}
$(if name == stringify!($name) {
match in_elem.sty {
$($(ty::$p(_))|* => {
- return Ok(bcx.$call(args[0].immediate(), args[1].immediate()))
+ return Ok(bx.$call(args[0].immediate(), args[1].immediate()))
})*
_ => {},
}
// Returns None if the type is not an integer
// FIXME: there’s multiple of this functions, investigate using some of the already existing
// stuffs.
-fn int_type_width_signed(ty: Ty, ccx: &CrateContext) -> Option<(u64, bool)> {
+fn int_type_width_signed(ty: Ty, cx: &CodegenCx) -> Option<(u64, bool)> {
match ty.sty {
ty::TyInt(t) => Some((match t {
- ast::IntTy::Is => {
- match &ccx.tcx().sess.target.target.target_pointer_width[..] {
+ ast::IntTy::Isize => {
+ match &cx.tcx.sess.target.target.target_pointer_width[..] {
"16" => 16,
"32" => 32,
"64" => 64,
ast::IntTy::I128 => 128,
}, true)),
ty::TyUint(t) => Some((match t {
- ast::UintTy::Us => {
- match &ccx.tcx().sess.target.target.target_pointer_width[..] {
+ ast::UintTy::Usize => {
+ match &cx.tcx.sess.target.target.target_pointer_width[..] {
"16" => 16,
"32" => 32,
"64" => 64,
#![feature(box_patterns)]
#![feature(box_syntax)]
#![feature(custom_attribute)]
+#![feature(fs_read_write)]
#![allow(unused_attributes)]
#![feature(i128_type)]
#![feature(i128)]
use back::bytecode::RLIB_BYTECODE_EXTENSION;
pub use metadata::LlvmMetadataLoader;
-pub use llvm_util::{init, target_features, print_version, print_passes, print, enable_llvm_debug};
+pub use llvm_util::{init, target_features, print_version, print_passes, print};
use std::any::Any;
use std::path::PathBuf;
back::symbol_names::provide(providers);
back::symbol_export::provide(providers);
base::provide(providers);
+ attributes::provide(providers);
}
fn provide_extern(providers: &mut ty::maps::Providers) {
used_crates_dynamic: Vec<(CrateNum, LibSource)>,
}
+#[cfg(not(stage0))] // remove after the next snapshot
__build_diagnostic_array! { librustc_trans, DIAGNOSTICS }
use llvm;
use rustc::session::Session;
use rustc::session::config::PrintRequest;
-use libc::{c_int, c_char};
-use std::ffi::CString;
+use libc::c_int;
+use std::ffi::{CStr, CString};
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Once;
"avx512dq\0", "avx512er\0",
"avx512f\0", "avx512ifma\0",
"avx512pf\0", "avx512vbmi\0",
- "avx512vl\0", "avx512vpopcntdq\0", "mmx\0"];
+ "avx512vl\0", "avx512vpopcntdq\0",
+ "mmx\0", "fxsr\0"];
const HEXAGON_WHITELIST: &'static [&'static str] = &["hvx\0", "hvx-double\0"];
const MIPS_WHITELIST: &'static [&'static str] = &["msa\0"];
pub fn target_features(sess: &Session) -> Vec<Symbol> {
+ let whitelist = target_feature_whitelist(sess);
let target_machine = create_target_machine(sess);
+ let mut features = Vec::new();
+ for feat in whitelist {
+ if unsafe { llvm::LLVMRustHasFeature(target_machine, feat.as_ptr()) } {
+ features.push(Symbol::intern(feat.to_str().unwrap()));
+ }
+ }
+ features
+}
+pub fn target_feature_whitelist(sess: &Session) -> Vec<&CStr> {
let whitelist = match &*sess.target.target.arch {
"arm" => ARM_WHITELIST,
"aarch64" => AARCH64_WHITELIST,
"powerpc" | "powerpc64" => POWERPC_WHITELIST,
_ => &[],
};
-
- let mut features = Vec::new();
- for feat in whitelist {
- assert_eq!(feat.chars().last(), Some('\0'));
- if unsafe { llvm::LLVMRustHasFeature(target_machine, feat.as_ptr() as *const c_char) } {
- features.push(Symbol::intern(&feat[..feat.len() - 1]));
- }
- }
- features
+ whitelist.iter().map(|m| {
+ CStr::from_bytes_with_nul(m.as_bytes()).unwrap()
+ }).collect()
}
pub fn print_version() {
}
}
}
-
-pub fn enable_llvm_debug() {
- unsafe { llvm::LLVMRustSetDebug(1); }
-}
VirtualIndex(index as u64 + 3)
}
- pub fn get_fn(self, bcx: &Builder<'a, 'tcx>,
+ pub fn get_fn(self, bx: &Builder<'a, 'tcx>,
llvtable: ValueRef,
fn_ty: &FnType<'tcx>) -> ValueRef {
// Load the data pointer from the object.
debug!("get_fn({:?}, {:?})", Value(llvtable), self);
- let llvtable = bcx.pointercast(llvtable, fn_ty.llvm_type(bcx.ccx).ptr_to().ptr_to());
- let ptr_align = bcx.tcx().data_layout.pointer_align;
- let ptr = bcx.load(bcx.inbounds_gep(llvtable, &[C_usize(bcx.ccx, self.0)]), ptr_align);
- bcx.nonnull_metadata(ptr);
+ let llvtable = bx.pointercast(llvtable, fn_ty.llvm_type(bx.cx).ptr_to().ptr_to());
+ let ptr_align = bx.tcx().data_layout.pointer_align;
+ let ptr = bx.load(bx.inbounds_gep(llvtable, &[C_usize(bx.cx, self.0)]), ptr_align);
+ bx.nonnull_metadata(ptr);
// Vtable loads are invariant
- bcx.set_invariant_load(ptr);
+ bx.set_invariant_load(ptr);
ptr
}
- pub fn get_usize(self, bcx: &Builder<'a, 'tcx>, llvtable: ValueRef) -> ValueRef {
+ pub fn get_usize(self, bx: &Builder<'a, 'tcx>, llvtable: ValueRef) -> ValueRef {
// Load the data pointer from the object.
debug!("get_int({:?}, {:?})", Value(llvtable), self);
- let llvtable = bcx.pointercast(llvtable, Type::isize(bcx.ccx).ptr_to());
- let usize_align = bcx.tcx().data_layout.pointer_align;
- let ptr = bcx.load(bcx.inbounds_gep(llvtable, &[C_usize(bcx.ccx, self.0)]), usize_align);
+ let llvtable = bx.pointercast(llvtable, Type::isize(bx.cx).ptr_to());
+ let usize_align = bx.tcx().data_layout.pointer_align;
+ let ptr = bx.load(bx.inbounds_gep(llvtable, &[C_usize(bx.cx, self.0)]), usize_align);
// Vtable loads are invariant
- bcx.set_invariant_load(ptr);
+ bx.set_invariant_load(ptr);
ptr
}
}
/// The `trait_ref` encodes the erased self type. Hence if we are
/// making an object `Foo<Trait>` from a value of type `Foo<T>`, then
/// `trait_ref` would map `T:Trait`.
-pub fn get_vtable<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
+pub fn get_vtable<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
ty: Ty<'tcx>,
trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>)
-> ValueRef
{
- let tcx = ccx.tcx();
+ let tcx = cx.tcx;
debug!("get_vtable(ty={:?}, trait_ref={:?})", ty, trait_ref);
// Check the cache.
- if let Some(&val) = ccx.vtables().borrow().get(&(ty, trait_ref)) {
+ if let Some(&val) = cx.vtables.borrow().get(&(ty, trait_ref)) {
return val;
}
// Not in the cache. Build it.
- let nullptr = C_null(Type::i8p(ccx));
+ let nullptr = C_null(Type::i8p(cx));
- let (size, align) = ccx.size_and_align_of(ty);
+ let (size, align) = cx.size_and_align_of(ty);
let mut components: Vec<_> = [
- callee::get_fn(ccx, monomorphize::resolve_drop_in_place(ccx.tcx(), ty)),
- C_usize(ccx, size.bytes()),
- C_usize(ccx, align.abi())
+ callee::get_fn(cx, monomorphize::resolve_drop_in_place(cx.tcx, ty)),
+ C_usize(cx, size.bytes()),
+ C_usize(cx, align.abi())
].iter().cloned().collect();
if let Some(trait_ref) = trait_ref {
let methods = tcx.vtable_methods(trait_ref);
let methods = methods.iter().cloned().map(|opt_mth| {
opt_mth.map_or(nullptr, |(def_id, substs)| {
- callee::resolve_and_get_fn(ccx, def_id, substs)
+ callee::resolve_and_get_fn(cx, def_id, substs)
})
});
components.extend(methods);
}
- let vtable_const = C_struct(ccx, &components, false);
- let align = ccx.data_layout().pointer_align;
- let vtable = consts::addr_of(ccx, vtable_const, align, "vtable");
+ let vtable_const = C_struct(cx, &components, false);
+ let align = cx.data_layout().pointer_align;
+ let vtable = consts::addr_of(cx, vtable_const, align, "vtable");
- debuginfo::create_vtable_metadata(ccx, ty, vtable);
+ debuginfo::create_vtable_metadata(cx, ty, vtable);
- ccx.vtables().borrow_mut().insert((ty, trait_ref), vtable);
+ cx.vtables.borrow_mut().insert((ty, trait_ref), vtable);
vtable
}
use rustc::ty;
use rustc::ty::layout::LayoutOf;
use type_of::LayoutLlvmExt;
-use super::MirContext;
+use super::FunctionCx;
-pub fn memory_locals<'a, 'tcx>(mircx: &MirContext<'a, 'tcx>) -> BitVector {
- let mir = mircx.mir;
- let mut analyzer = LocalAnalyzer::new(mircx);
+pub fn memory_locals<'a, 'tcx>(fx: &FunctionCx<'a, 'tcx>) -> BitVector {
+ let mir = fx.mir;
+ let mut analyzer = LocalAnalyzer::new(fx);
analyzer.visit_mir(mir);
for (index, ty) in mir.local_decls.iter().map(|l| l.ty).enumerate() {
- let ty = mircx.monomorphize(&ty);
+ let ty = fx.monomorphize(&ty);
debug!("local {} has type {:?}", index, ty);
- let layout = mircx.ccx.layout_of(ty);
+ let layout = fx.cx.layout_of(ty);
if layout.is_llvm_immediate() {
// These sorts of types are immediates that we can store
// in an ValueRef without an alloca.
}
struct LocalAnalyzer<'mir, 'a: 'mir, 'tcx: 'a> {
- cx: &'mir MirContext<'a, 'tcx>,
+ fx: &'mir FunctionCx<'a, 'tcx>,
memory_locals: BitVector,
seen_assigned: BitVector
}
impl<'mir, 'a, 'tcx> LocalAnalyzer<'mir, 'a, 'tcx> {
- fn new(mircx: &'mir MirContext<'a, 'tcx>) -> LocalAnalyzer<'mir, 'a, 'tcx> {
+ fn new(fx: &'mir FunctionCx<'a, 'tcx>) -> LocalAnalyzer<'mir, 'a, 'tcx> {
let mut analyzer = LocalAnalyzer {
- cx: mircx,
- memory_locals: BitVector::new(mircx.mir.local_decls.len()),
- seen_assigned: BitVector::new(mircx.mir.local_decls.len())
+ fx,
+ memory_locals: BitVector::new(fx.mir.local_decls.len()),
+ seen_assigned: BitVector::new(fx.mir.local_decls.len())
};
// Arguments get assigned to by means of the function being called
- for idx in 0..mircx.mir.arg_count {
+ for idx in 0..fx.mir.arg_count {
analyzer.seen_assigned.insert(idx + 1);
}
if let mir::Place::Local(index) = *place {
self.mark_assigned(index);
- if !self.cx.rvalue_creates_operand(rvalue) {
+ if !self.fx.rvalue_creates_operand(rvalue) {
self.mark_as_memory(index);
}
} else {
}, ..
}),
ref args, ..
- } if Some(def_id) == self.cx.ccx.tcx().lang_items().box_free_fn() => {
+ } if Some(def_id) == self.fx.cx.tcx.lang_items().box_free_fn() => {
// box_free(x) shares with `drop x` the property that it
// is not guaranteed to be statically dominated by the
// definition of x, so x must always be in an alloca.
context: PlaceContext<'tcx>,
location: Location) {
debug!("visit_place(place={:?}, context={:?})", place, context);
- let ccx = self.cx.ccx;
+ let cx = self.fx.cx;
if let mir::Place::Projection(ref proj) = *place {
// Allow uses of projections that are ZSTs or from scalar fields.
_ => false
};
if is_consume {
- let base_ty = proj.base.ty(self.cx.mir, ccx.tcx());
- let base_ty = self.cx.monomorphize(&base_ty);
+ let base_ty = proj.base.ty(self.fx.mir, cx.tcx);
+ let base_ty = self.fx.monomorphize(&base_ty);
// ZSTs don't require any actual memory access.
- let elem_ty = base_ty.projection_ty(ccx.tcx(), &proj.elem).to_ty(ccx.tcx());
- let elem_ty = self.cx.monomorphize(&elem_ty);
- if ccx.layout_of(elem_ty).is_zst() {
+ let elem_ty = base_ty.projection_ty(cx.tcx, &proj.elem).to_ty(cx.tcx);
+ let elem_ty = self.fx.monomorphize(&elem_ty);
+ if cx.layout_of(elem_ty).is_zst() {
return;
}
if let mir::ProjectionElem::Field(..) = proj.elem {
- let layout = ccx.layout_of(base_ty.to_ty(ccx.tcx()));
+ let layout = cx.layout_of(base_ty.to_ty(cx.tcx));
if layout.is_llvm_immediate() || layout.is_llvm_scalar_pair() {
// Recurse with the same context, instead of `Projection`,
// potentially stopping at non-operand projections,
}
PlaceContext::Drop => {
- let ty = mir::Place::Local(index).ty(self.cx.mir, self.cx.ccx.tcx());
- let ty = self.cx.monomorphize(&ty.to_ty(self.cx.ccx.tcx()));
+ let ty = mir::Place::Local(index).ty(self.fx.mir, self.fx.cx.tcx);
+ let ty = self.fx.monomorphize(&ty.to_ty(self.fx.cx.tcx));
// Only need the place if we're actually dropping it.
- if self.cx.ccx.shared().type_needs_drop(ty) {
+ if self.fx.cx.type_needs_drop(ty) {
self.mark_as_memory(index);
}
}
use syntax::symbol::Symbol;
use syntax_pos::Pos;
-use super::{MirContext, LocalRef};
+use super::{FunctionCx, LocalRef};
use super::constant::Const;
use super::place::PlaceRef;
use super::operand::OperandRef;
use super::operand::OperandValue::{Pair, Ref, Immediate};
-impl<'a, 'tcx> MirContext<'a, 'tcx> {
+impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
pub fn trans_block(&mut self, bb: mir::BasicBlock) {
- let mut bcx = self.get_builder(bb);
+ let mut bx = self.build_block(bb);
let data = &self.mir[bb];
debug!("trans_block({:?}={:?})", bb, data);
for statement in &data.statements {
- bcx = self.trans_statement(bcx, statement);
+ bx = self.trans_statement(bx, statement);
}
- self.trans_terminator(bcx, bb, data.terminator());
+ self.trans_terminator(bx, bb, data.terminator());
}
fn trans_terminator(&mut self,
- mut bcx: Builder<'a, 'tcx>,
+ mut bx: Builder<'a, 'tcx>,
bb: mir::BasicBlock,
terminator: &mir::Terminator<'tcx>)
{
debug!("trans_terminator: {:?}", terminator);
// Create the cleanup bundle, if needed.
- let tcx = bcx.tcx();
+ let tcx = bx.tcx();
let span = terminator.source_info.span;
let funclet_bb = self.cleanup_kinds[bb].funclet_bb(bb);
let funclet = funclet_bb.and_then(|funclet_bb| self.funclets[funclet_bb].as_ref());
}
};
- let funclet_br = |this: &mut Self, bcx: Builder, target: mir::BasicBlock| {
+ let funclet_br = |this: &mut Self, bx: Builder, target: mir::BasicBlock| {
let (lltarget, is_cleanupret) = lltarget(this, target);
if is_cleanupret {
// micro-optimization: generate a `ret` rather than a jump
// to a trampoline.
- bcx.cleanup_ret(cleanup_pad.unwrap(), Some(lltarget));
+ bx.cleanup_ret(cleanup_pad.unwrap(), Some(lltarget));
} else {
- bcx.br(lltarget);
+ bx.br(lltarget);
}
};
let do_call = |
this: &mut Self,
- bcx: Builder<'a, 'tcx>,
+ bx: Builder<'a, 'tcx>,
fn_ty: FnType<'tcx>,
fn_ptr: ValueRef,
llargs: &[ValueRef],
cleanup: Option<mir::BasicBlock>
| {
if let Some(cleanup) = cleanup {
- let ret_bcx = if let Some((_, target)) = destination {
+ let ret_bx = if let Some((_, target)) = destination {
this.blocks[target]
} else {
this.unreachable_block()
};
- let invokeret = bcx.invoke(fn_ptr,
+ let invokeret = bx.invoke(fn_ptr,
&llargs,
- ret_bcx,
+ ret_bx,
llblock(this, cleanup),
cleanup_bundle);
fn_ty.apply_attrs_callsite(invokeret);
if let Some((ret_dest, target)) = destination {
- let ret_bcx = this.get_builder(target);
- this.set_debug_loc(&ret_bcx, terminator.source_info);
- this.store_return(&ret_bcx, ret_dest, &fn_ty.ret, invokeret);
+ let ret_bx = this.build_block(target);
+ this.set_debug_loc(&ret_bx, terminator.source_info);
+ this.store_return(&ret_bx, ret_dest, &fn_ty.ret, invokeret);
}
} else {
- let llret = bcx.call(fn_ptr, &llargs, cleanup_bundle);
+ let llret = bx.call(fn_ptr, &llargs, cleanup_bundle);
fn_ty.apply_attrs_callsite(llret);
if this.mir[bb].is_cleanup {
// Cleanup is always the cold path. Don't inline
}
if let Some((ret_dest, target)) = destination {
- this.store_return(&bcx, ret_dest, &fn_ty.ret, llret);
- funclet_br(this, bcx, target);
+ this.store_return(&bx, ret_dest, &fn_ty.ret, llret);
+ funclet_br(this, bx, target);
} else {
- bcx.unreachable();
+ bx.unreachable();
}
}
};
- self.set_debug_loc(&bcx, terminator.source_info);
+ self.set_debug_loc(&bx, terminator.source_info);
match terminator.kind {
mir::TerminatorKind::Resume => {
if let Some(cleanup_pad) = cleanup_pad {
- bcx.cleanup_ret(cleanup_pad, None);
+ bx.cleanup_ret(cleanup_pad, None);
} else {
- let slot = self.get_personality_slot(&bcx);
- let lp0 = slot.project_field(&bcx, 0).load(&bcx).immediate();
- let lp1 = slot.project_field(&bcx, 1).load(&bcx).immediate();
- slot.storage_dead(&bcx);
+ let slot = self.get_personality_slot(&bx);
+ let lp0 = slot.project_field(&bx, 0).load(&bx).immediate();
+ let lp1 = slot.project_field(&bx, 1).load(&bx).immediate();
+ slot.storage_dead(&bx);
- if !bcx.sess().target.target.options.custom_unwind_resume {
+ if !bx.sess().target.target.options.custom_unwind_resume {
let mut lp = C_undef(self.landing_pad_type());
- lp = bcx.insert_value(lp, lp0, 0);
- lp = bcx.insert_value(lp, lp1, 1);
- bcx.resume(lp);
+ lp = bx.insert_value(lp, lp0, 0);
+ lp = bx.insert_value(lp, lp1, 1);
+ bx.resume(lp);
} else {
- bcx.call(bcx.ccx.eh_unwind_resume(), &[lp0], cleanup_bundle);
- bcx.unreachable();
+ bx.call(bx.cx.eh_unwind_resume(), &[lp0], cleanup_bundle);
+ bx.unreachable();
}
}
}
mir::TerminatorKind::Abort => {
// Call core::intrinsics::abort()
- let fnname = bcx.ccx.get_intrinsic(&("llvm.trap"));
- bcx.call(fnname, &[], None);
- bcx.unreachable();
+ let fnname = bx.cx.get_intrinsic(&("llvm.trap"));
+ bx.call(fnname, &[], None);
+ bx.unreachable();
}
mir::TerminatorKind::Goto { target } => {
- funclet_br(self, bcx, target);
+ funclet_br(self, bx, target);
}
mir::TerminatorKind::SwitchInt { ref discr, switch_ty, ref values, ref targets } => {
- let discr = self.trans_operand(&bcx, discr);
- if switch_ty == bcx.tcx().types.bool {
+ let discr = self.trans_operand(&bx, discr);
+ if switch_ty == bx.tcx().types.bool {
let lltrue = llblock(self, targets[0]);
let llfalse = llblock(self, targets[1]);
if let [ConstInt::U8(0)] = values[..] {
- bcx.cond_br(discr.immediate(), llfalse, lltrue);
+ bx.cond_br(discr.immediate(), llfalse, lltrue);
} else {
- bcx.cond_br(discr.immediate(), lltrue, llfalse);
+ bx.cond_br(discr.immediate(), lltrue, llfalse);
}
} else {
let (otherwise, targets) = targets.split_last().unwrap();
- let switch = bcx.switch(discr.immediate(),
+ let switch = bx.switch(discr.immediate(),
llblock(self, *otherwise), values.len());
for (value, target) in values.iter().zip(targets) {
- let val = Const::from_constint(bcx.ccx, value);
+ let val = Const::from_constint(bx.cx, value);
let llbb = llblock(self, *target);
- bcx.add_case(switch, val.llval, llbb)
+ bx.add_case(switch, val.llval, llbb)
}
}
}
mir::TerminatorKind::Return => {
let llval = match self.fn_ty.ret.mode {
PassMode::Ignore | PassMode::Indirect(_) => {
- bcx.ret_void();
+ bx.ret_void();
return;
}
PassMode::Direct(_) | PassMode::Pair(..) => {
- let op = self.trans_consume(&bcx, &mir::Place::Local(mir::RETURN_PLACE));
+ let op = self.trans_consume(&bx, &mir::Place::Local(mir::RETURN_PLACE));
if let Ref(llval, align) = op.val {
- bcx.load(llval, align)
+ bx.load(llval, align)
} else {
- op.immediate_or_packed_pair(&bcx)
+ op.immediate_or_packed_pair(&bx)
}
}
};
let llslot = match op.val {
Immediate(_) | Pair(..) => {
- let scratch = PlaceRef::alloca(&bcx, self.fn_ty.ret.layout, "ret");
- op.val.store(&bcx, scratch);
+ let scratch = PlaceRef::alloca(&bx, self.fn_ty.ret.layout, "ret");
+ op.val.store(&bx, scratch);
scratch.llval
}
Ref(llval, align) => {
llval
}
};
- bcx.load(
- bcx.pointercast(llslot, cast_ty.llvm_type(bcx.ccx).ptr_to()),
+ bx.load(
+ bx.pointercast(llslot, cast_ty.llvm_type(bx.cx).ptr_to()),
self.fn_ty.ret.layout.align)
}
};
- bcx.ret(llval);
+ bx.ret(llval);
}
mir::TerminatorKind::Unreachable => {
- bcx.unreachable();
+ bx.unreachable();
}
mir::TerminatorKind::Drop { ref location, target, unwind } => {
- let ty = location.ty(self.mir, bcx.tcx()).to_ty(bcx.tcx());
+ let ty = location.ty(self.mir, bx.tcx()).to_ty(bx.tcx());
let ty = self.monomorphize(&ty);
- let drop_fn = monomorphize::resolve_drop_in_place(bcx.ccx.tcx(), ty);
+ let drop_fn = monomorphize::resolve_drop_in_place(bx.cx.tcx, ty);
if let ty::InstanceDef::DropGlue(_, None) = drop_fn.def {
// we don't actually need to drop anything.
- funclet_br(self, bcx, target);
+ funclet_br(self, bx, target);
return
}
- let place = self.trans_place(&bcx, location);
+ let place = self.trans_place(&bx, location);
let mut args: &[_] = &[place.llval, place.llextra];
args = &args[..1 + place.has_extra() as usize];
let (drop_fn, fn_ty) = match ty.sty {
ty::TyDynamic(..) => {
- let fn_ty = drop_fn.ty(bcx.ccx.tcx());
- let sig = common::ty_fn_sig(bcx.ccx, fn_ty);
- let sig = bcx.tcx().erase_late_bound_regions_and_normalize(&sig);
- let fn_ty = FnType::new_vtable(bcx.ccx, sig, &[]);
+ let fn_ty = drop_fn.ty(bx.cx.tcx);
+ let sig = common::ty_fn_sig(bx.cx, fn_ty);
+ let sig = bx.tcx().erase_late_bound_regions_and_normalize(&sig);
+ let fn_ty = FnType::new_vtable(bx.cx, sig, &[]);
args = &args[..1];
- (meth::DESTRUCTOR.get_fn(&bcx, place.llextra, &fn_ty), fn_ty)
+ (meth::DESTRUCTOR.get_fn(&bx, place.llextra, &fn_ty), fn_ty)
}
_ => {
- (callee::get_fn(bcx.ccx, drop_fn),
- FnType::of_instance(bcx.ccx, &drop_fn))
+ (callee::get_fn(bx.cx, drop_fn),
+ FnType::of_instance(bx.cx, &drop_fn))
}
};
- do_call(self, bcx, fn_ty, drop_fn, args,
+ do_call(self, bx, fn_ty, drop_fn, args,
Some((ReturnDest::Nothing, target)),
unwind);
}
mir::TerminatorKind::Assert { ref cond, expected, ref msg, target, cleanup } => {
- let cond = self.trans_operand(&bcx, cond).immediate();
+ let cond = self.trans_operand(&bx, cond).immediate();
let mut const_cond = common::const_to_opt_u128(cond, false).map(|c| c == 1);
// This case can currently arise only from functions marked
// NOTE: Unlike binops, negation doesn't have its own
// checked operation, just a comparison with the minimum
// value, so we have to check for the assert message.
- if !bcx.ccx.check_overflow() {
+ if !bx.cx.check_overflow {
use rustc_const_math::ConstMathErr::Overflow;
use rustc_const_math::Op::Neg;
// Don't translate the panic block if success if known.
if const_cond == Some(expected) {
- funclet_br(self, bcx, target);
+ funclet_br(self, bx, target);
return;
}
// Pass the condition through llvm.expect for branch hinting.
- let expect = bcx.ccx.get_intrinsic(&"llvm.expect.i1");
- let cond = bcx.call(expect, &[cond, C_bool(bcx.ccx, expected)], None);
+ let expect = bx.cx.get_intrinsic(&"llvm.expect.i1");
+ let cond = bx.call(expect, &[cond, C_bool(bx.cx, expected)], None);
// Create the failure block and the conditional branch to it.
let lltarget = llblock(self, target);
let panic_block = self.new_block("panic");
if expected {
- bcx.cond_br(cond, lltarget, panic_block.llbb());
+ bx.cond_br(cond, lltarget, panic_block.llbb());
} else {
- bcx.cond_br(cond, panic_block.llbb(), lltarget);
+ bx.cond_br(cond, panic_block.llbb(), lltarget);
}
- // After this point, bcx is the block for the call to panic.
- bcx = panic_block;
- self.set_debug_loc(&bcx, terminator.source_info);
+ // After this point, bx is the block for the call to panic.
+ bx = panic_block;
+ self.set_debug_loc(&bx, terminator.source_info);
// Get the location information.
- let loc = bcx.sess().codemap().lookup_char_pos(span.lo());
+ let loc = bx.sess().codemap().lookup_char_pos(span.lo());
let filename = Symbol::intern(&loc.file.name.to_string()).as_str();
- let filename = C_str_slice(bcx.ccx, filename);
- let line = C_u32(bcx.ccx, loc.line as u32);
- let col = C_u32(bcx.ccx, loc.col.to_usize() as u32 + 1);
+ let filename = C_str_slice(bx.cx, filename);
+ let line = C_u32(bx.cx, loc.line as u32);
+ let col = C_u32(bx.cx, loc.col.to_usize() as u32 + 1);
let align = tcx.data_layout.aggregate_align
.max(tcx.data_layout.i32_align)
.max(tcx.data_layout.pointer_align);
// Put together the arguments to the panic entry point.
let (lang_item, args, const_err) = match *msg {
mir::AssertMessage::BoundsCheck { ref len, ref index } => {
- let len = self.trans_operand(&mut bcx, len).immediate();
- let index = self.trans_operand(&mut bcx, index).immediate();
+ let len = self.trans_operand(&mut bx, len).immediate();
+ let index = self.trans_operand(&mut bx, index).immediate();
let const_err = common::const_to_opt_u128(len, false)
.and_then(|len| common::const_to_opt_u128(index, false)
index: index as u64
}));
- let file_line_col = C_struct(bcx.ccx, &[filename, line, col], false);
- let file_line_col = consts::addr_of(bcx.ccx,
+ let file_line_col = C_struct(bx.cx, &[filename, line, col], false);
+ let file_line_col = consts::addr_of(bx.cx,
file_line_col,
align,
"panic_bounds_check_loc");
}
mir::AssertMessage::Math(ref err) => {
let msg_str = Symbol::intern(err.description()).as_str();
- let msg_str = C_str_slice(bcx.ccx, msg_str);
- let msg_file_line_col = C_struct(bcx.ccx,
+ let msg_str = C_str_slice(bx.cx, msg_str);
+ let msg_file_line_col = C_struct(bx.cx,
&[msg_str, filename, line, col],
false);
- let msg_file_line_col = consts::addr_of(bcx.ccx,
+ let msg_file_line_col = consts::addr_of(bx.cx,
msg_file_line_col,
align,
"panic_loc");
"generator resumed after panicking"
};
let msg_str = Symbol::intern(str).as_str();
- let msg_str = C_str_slice(bcx.ccx, msg_str);
- let msg_file_line_col = C_struct(bcx.ccx,
+ let msg_str = C_str_slice(bx.cx, msg_str);
+ let msg_file_line_col = C_struct(bx.cx,
&[msg_str, filename, line, col],
false);
- let msg_file_line_col = consts::addr_of(bcx.ccx,
+ let msg_file_line_col = consts::addr_of(bx.cx,
msg_file_line_col,
align,
"panic_loc");
if const_cond == Some(!expected) {
if let Some(err) = const_err {
let err = ConstEvalErr{ span: span, kind: err };
- let mut diag = bcx.tcx().sess.struct_span_warn(
+ let mut diag = bx.tcx().sess.struct_span_warn(
span, "this expression will panic at run-time");
- err.note(bcx.tcx(), span, "expression", &mut diag);
+ err.note(bx.tcx(), span, "expression", &mut diag);
diag.emit();
}
}
// Obtain the panic entry point.
- let def_id = common::langcall(bcx.tcx(), Some(span), "", lang_item);
- let instance = ty::Instance::mono(bcx.tcx(), def_id);
- let fn_ty = FnType::of_instance(bcx.ccx, &instance);
- let llfn = callee::get_fn(bcx.ccx, instance);
+ let def_id = common::langcall(bx.tcx(), Some(span), "", lang_item);
+ let instance = ty::Instance::mono(bx.tcx(), def_id);
+ let fn_ty = FnType::of_instance(bx.cx, &instance);
+ let llfn = callee::get_fn(bx.cx, instance);
// Translate the actual panic invoke/call.
- do_call(self, bcx, fn_ty, llfn, &args, None, cleanup);
+ do_call(self, bx, fn_ty, llfn, &args, None, cleanup);
}
mir::TerminatorKind::DropAndReplace { .. } => {
mir::TerminatorKind::Call { ref func, ref args, ref destination, cleanup } => {
// Create the callee. This is a fn ptr or zero-sized and hence a kind of scalar.
- let callee = self.trans_operand(&bcx, func);
+ let callee = self.trans_operand(&bx, func);
let (instance, mut llfn) = match callee.layout.ty.sty {
ty::TyFnDef(def_id, substs) => {
- (Some(ty::Instance::resolve(bcx.ccx.tcx(),
+ (Some(ty::Instance::resolve(bx.cx.tcx,
ty::ParamEnv::empty(traits::Reveal::All),
def_id,
substs).unwrap()),
_ => bug!("{} is not callable", callee.layout.ty)
};
let def = instance.map(|i| i.def);
- let sig = callee.layout.ty.fn_sig(bcx.tcx());
- let sig = bcx.tcx().erase_late_bound_regions_and_normalize(&sig);
+ let sig = callee.layout.ty.fn_sig(bx.tcx());
+ let sig = bx.tcx().erase_late_bound_regions_and_normalize(&sig);
let abi = sig.abi;
// Handle intrinsics old trans wants Expr's for, ourselves.
let intrinsic = match def {
Some(ty::InstanceDef::Intrinsic(def_id))
- => Some(bcx.tcx().item_name(def_id)),
+ => Some(bx.tcx().item_name(def_id)),
_ => None
};
let intrinsic = intrinsic.as_ref().map(|s| &s[..]);
if intrinsic == Some("transmute") {
let &(ref dest, target) = destination.as_ref().unwrap();
- self.trans_transmute(&bcx, &args[0], dest);
- funclet_br(self, bcx, target);
+ self.trans_transmute(&bx, &args[0], dest);
+ funclet_br(self, bx, target);
return;
}
let extra_args = &args[sig.inputs().len()..];
let extra_args = extra_args.iter().map(|op_arg| {
- let op_ty = op_arg.ty(self.mir, bcx.tcx());
+ let op_ty = op_arg.ty(self.mir, bx.tcx());
self.monomorphize(&op_ty)
}).collect::<Vec<_>>();
let fn_ty = match def {
Some(ty::InstanceDef::Virtual(..)) => {
- FnType::new_vtable(bcx.ccx, sig, &extra_args)
+ FnType::new_vtable(bx.cx, sig, &extra_args)
}
Some(ty::InstanceDef::DropGlue(_, None)) => {
// empty drop glue - a nop.
let &(_, target) = destination.as_ref().unwrap();
- funclet_br(self, bcx, target);
+ funclet_br(self, bx, target);
return;
}
- _ => FnType::new(bcx.ccx, sig, &extra_args)
+ _ => FnType::new(bx.cx, sig, &extra_args)
};
// The arguments we'll be passing. Plus one to account for outptr, if used.
// Prepare the return value destination
let ret_dest = if let Some((ref dest, _)) = *destination {
let is_intrinsic = intrinsic.is_some();
- self.make_return_dest(&bcx, dest, &fn_ty.ret, &mut llargs,
+ self.make_return_dest(&bx, dest, &fn_ty.ret, &mut llargs,
is_intrinsic)
} else {
ReturnDest::Nothing
let dest = match ret_dest {
_ if fn_ty.ret.is_indirect() => llargs[0],
ReturnDest::Nothing => {
- C_undef(fn_ty.ret.memory_ty(bcx.ccx).ptr_to())
+ C_undef(fn_ty.ret.memory_ty(bx.cx).ptr_to())
}
ReturnDest::IndirectOperand(dst, _) |
ReturnDest::Store(dst) => dst.llval,
span_bug!(span, "shuffle indices must be constant");
}
mir::Operand::Constant(ref constant) => {
- let val = self.trans_constant(&bcx, constant);
+ let val = self.trans_constant(&bx, constant);
return OperandRef {
val: Immediate(val.llval),
- layout: bcx.ccx.layout_of(val.ty)
+ layout: bx.cx.layout_of(val.ty)
};
}
}
}
- self.trans_operand(&bcx, arg)
+ self.trans_operand(&bx, arg)
}).collect();
- let callee_ty = instance.as_ref().unwrap().ty(bcx.ccx.tcx());
- trans_intrinsic_call(&bcx, callee_ty, &fn_ty, &args, dest,
+ let callee_ty = instance.as_ref().unwrap().ty(bx.cx.tcx);
+ trans_intrinsic_call(&bx, callee_ty, &fn_ty, &args, dest,
terminator.source_info.span);
if let ReturnDest::IndirectOperand(dst, _) = ret_dest {
- self.store_return(&bcx, ret_dest, &fn_ty.ret, dst.llval);
+ self.store_return(&bx, ret_dest, &fn_ty.ret, dst.llval);
}
if let Some((_, target)) = *destination {
- funclet_br(self, bcx, target);
+ funclet_br(self, bx, target);
} else {
- bcx.unreachable();
+ bx.unreachable();
}
return;
};
for (i, arg) in first_args.iter().enumerate() {
- let mut op = self.trans_operand(&bcx, arg);
+ let mut op = self.trans_operand(&bx, arg);
if let (0, Some(ty::InstanceDef::Virtual(_, idx))) = (i, def) {
if let Pair(data_ptr, meta) = op.val {
llfn = Some(meth::VirtualIndex::from_index(idx)
- .get_fn(&bcx, meta, &fn_ty));
+ .get_fn(&bx, meta, &fn_ty));
llargs.push(data_ptr);
continue;
}
match (arg, op.val) {
(&mir::Operand::Copy(_), Ref(..)) |
(&mir::Operand::Constant(_), Ref(..)) => {
- let tmp = PlaceRef::alloca(&bcx, op.layout, "const");
- op.val.store(&bcx, tmp);
+ let tmp = PlaceRef::alloca(&bx, op.layout, "const");
+ op.val.store(&bx, tmp);
op.val = Ref(tmp.llval, tmp.align);
}
_ => {}
}
- self.trans_argument(&bcx, op, &mut llargs, &fn_ty.args[i]);
+ self.trans_argument(&bx, op, &mut llargs, &fn_ty.args[i]);
}
if let Some(tup) = untuple {
- self.trans_arguments_untupled(&bcx, tup, &mut llargs,
+ self.trans_arguments_untupled(&bx, tup, &mut llargs,
&fn_ty.args[first_args.len()..])
}
let fn_ptr = match (llfn, instance) {
(Some(llfn), _) => llfn,
- (None, Some(instance)) => callee::get_fn(bcx.ccx, instance),
+ (None, Some(instance)) => callee::get_fn(bx.cx, instance),
_ => span_bug!(span, "no llfn for call"),
};
- do_call(self, bcx, fn_ty, fn_ptr, &llargs,
+ do_call(self, bx, fn_ty, fn_ptr, &llargs,
destination.as_ref().map(|&(_, target)| (ret_dest, target)),
cleanup);
}
}
fn trans_argument(&mut self,
- bcx: &Builder<'a, 'tcx>,
+ bx: &Builder<'a, 'tcx>,
op: OperandRef<'tcx>,
llargs: &mut Vec<ValueRef>,
arg: &ArgType<'tcx>) {
// Fill padding with undef value, where applicable.
if let Some(ty) = arg.pad {
- llargs.push(C_undef(ty.llvm_type(bcx.ccx)));
+ llargs.push(C_undef(ty.llvm_type(bx.cx)));
}
if arg.is_ignore() {
Immediate(_) | Pair(..) => {
match arg.mode {
PassMode::Indirect(_) | PassMode::Cast(_) => {
- let scratch = PlaceRef::alloca(bcx, arg.layout, "arg");
- op.val.store(bcx, scratch);
+ let scratch = PlaceRef::alloca(bx, arg.layout, "arg");
+ op.val.store(bx, scratch);
(scratch.llval, scratch.align, true)
}
_ => {
- (op.immediate_or_packed_pair(bcx), arg.layout.align, false)
+ (op.immediate_or_packed_pair(bx), arg.layout.align, false)
}
}
}
// think that ATM (Rust 1.16) we only pass temporaries, but we shouldn't
// have scary latent bugs around.
- let scratch = PlaceRef::alloca(bcx, arg.layout, "arg");
- base::memcpy_ty(bcx, scratch.llval, llval, op.layout, align);
+ let scratch = PlaceRef::alloca(bx, arg.layout, "arg");
+ base::memcpy_ty(bx, scratch.llval, llval, op.layout, align);
(scratch.llval, scratch.align, true)
} else {
(llval, align, true)
if by_ref && !arg.is_indirect() {
// Have to load the argument, maybe while casting it.
if let PassMode::Cast(ty) = arg.mode {
- llval = bcx.load(bcx.pointercast(llval, ty.llvm_type(bcx.ccx).ptr_to()),
+ llval = bx.load(bx.pointercast(llval, ty.llvm_type(bx.cx).ptr_to()),
align.min(arg.layout.align));
} else {
// We can't use `PlaceRef::load` here because the argument
// used for this call is passing it by-value. In that case,
// the load would just produce `OperandValue::Ref` instead
// of the `OperandValue::Immediate` we need for the call.
- llval = bcx.load(llval, align);
+ llval = bx.load(llval, align);
if let layout::Abi::Scalar(ref scalar) = arg.layout.abi {
if scalar.is_bool() {
- bcx.range_metadata(llval, 0..2);
+ bx.range_metadata(llval, 0..2);
}
}
// We store bools as i8 so we need to truncate to i1.
- llval = base::to_immediate(bcx, llval, arg.layout);
+ llval = base::to_immediate(bx, llval, arg.layout);
}
}
}
fn trans_arguments_untupled(&mut self,
- bcx: &Builder<'a, 'tcx>,
+ bx: &Builder<'a, 'tcx>,
operand: &mir::Operand<'tcx>,
llargs: &mut Vec<ValueRef>,
args: &[ArgType<'tcx>]) {
- let tuple = self.trans_operand(bcx, operand);
+ let tuple = self.trans_operand(bx, operand);
// Handle both by-ref and immediate tuples.
if let Ref(llval, align) = tuple.val {
let tuple_ptr = PlaceRef::new_sized(llval, tuple.layout, align);
for i in 0..tuple.layout.fields.count() {
- let field_ptr = tuple_ptr.project_field(bcx, i);
- self.trans_argument(bcx, field_ptr.load(bcx), llargs, &args[i]);
+ let field_ptr = tuple_ptr.project_field(bx, i);
+ self.trans_argument(bx, field_ptr.load(bx), llargs, &args[i]);
}
} else {
// If the tuple is immediate, the elements are as well.
for i in 0..tuple.layout.fields.count() {
- let op = tuple.extract_field(bcx, i);
- self.trans_argument(bcx, op, llargs, &args[i]);
+ let op = tuple.extract_field(bx, i);
+ self.trans_argument(bx, op, llargs, &args[i]);
}
}
}
- fn get_personality_slot(&mut self, bcx: &Builder<'a, 'tcx>) -> PlaceRef<'tcx> {
- let ccx = bcx.ccx;
+ fn get_personality_slot(&mut self, bx: &Builder<'a, 'tcx>) -> PlaceRef<'tcx> {
+ let cx = bx.cx;
if let Some(slot) = self.personality_slot {
slot
} else {
- let layout = ccx.layout_of(ccx.tcx().intern_tup(&[
- ccx.tcx().mk_mut_ptr(ccx.tcx().types.u8),
- ccx.tcx().types.i32
+ let layout = cx.layout_of(cx.tcx.intern_tup(&[
+ cx.tcx.mk_mut_ptr(cx.tcx.types.u8),
+ cx.tcx.types.i32
], false));
- let slot = PlaceRef::alloca(bcx, layout, "personalityslot");
+ let slot = PlaceRef::alloca(bx, layout, "personalityslot");
self.personality_slot = Some(slot);
slot
}
}
fn landing_pad_uncached(&mut self, target_bb: BasicBlockRef) -> BasicBlockRef {
- if base::wants_msvc_seh(self.ccx.sess()) {
+ if base::wants_msvc_seh(self.cx.sess()) {
span_bug!(self.mir.span, "landing pad was not inserted?")
}
- let bcx = self.new_block("cleanup");
+ let bx = self.new_block("cleanup");
- let llpersonality = self.ccx.eh_personality();
+ let llpersonality = self.cx.eh_personality();
let llretty = self.landing_pad_type();
- let lp = bcx.landing_pad(llretty, llpersonality, 1, self.llfn);
- bcx.set_cleanup(lp);
+ let lp = bx.landing_pad(llretty, llpersonality, 1);
+ bx.set_cleanup(lp);
- let slot = self.get_personality_slot(&bcx);
- slot.storage_live(&bcx);
- Pair(bcx.extract_value(lp, 0), bcx.extract_value(lp, 1)).store(&bcx, slot);
+ let slot = self.get_personality_slot(&bx);
+ slot.storage_live(&bx);
+ Pair(bx.extract_value(lp, 0), bx.extract_value(lp, 1)).store(&bx, slot);
- bcx.br(target_bb);
- bcx.llbb()
+ bx.br(target_bb);
+ bx.llbb()
}
fn landing_pad_type(&self) -> Type {
- let ccx = self.ccx;
- Type::struct_(ccx, &[Type::i8p(ccx), Type::i32(ccx)], false)
+ let cx = self.cx;
+ Type::struct_(cx, &[Type::i8p(cx), Type::i32(cx)], false)
}
fn unreachable_block(&mut self) -> BasicBlockRef {
}
pub fn new_block(&self, name: &str) -> Builder<'a, 'tcx> {
- Builder::new_block(self.ccx, self.llfn, name)
+ Builder::new_block(self.cx, self.llfn, name)
}
- pub fn get_builder(&self, bb: mir::BasicBlock) -> Builder<'a, 'tcx> {
- let builder = Builder::with_ccx(self.ccx);
- builder.position_at_end(self.blocks[bb]);
- builder
+ pub fn build_block(&self, bb: mir::BasicBlock) -> Builder<'a, 'tcx> {
+ let bx = Builder::with_cx(self.cx);
+ bx.position_at_end(self.blocks[bb]);
+ bx
}
- fn make_return_dest(&mut self, bcx: &Builder<'a, 'tcx>,
+ fn make_return_dest(&mut self, bx: &Builder<'a, 'tcx>,
dest: &mir::Place<'tcx>, fn_ret: &ArgType<'tcx>,
llargs: &mut Vec<ValueRef>, is_intrinsic: bool)
-> ReturnDest<'tcx> {
return if fn_ret.is_indirect() {
// Odd, but possible, case, we have an operand temporary,
// but the calling convention has an indirect return.
- let tmp = PlaceRef::alloca(bcx, fn_ret.layout, "tmp_ret");
- tmp.storage_live(bcx);
+ let tmp = PlaceRef::alloca(bx, fn_ret.layout, "tmp_ret");
+ tmp.storage_live(bx);
llargs.push(tmp.llval);
ReturnDest::IndirectOperand(tmp, index)
} else if is_intrinsic {
// Currently, intrinsics always need a location to store
// the result. so we create a temporary alloca for the
// result
- let tmp = PlaceRef::alloca(bcx, fn_ret.layout, "tmp_ret");
- tmp.storage_live(bcx);
+ let tmp = PlaceRef::alloca(bx, fn_ret.layout, "tmp_ret");
+ tmp.storage_live(bx);
ReturnDest::IndirectOperand(tmp, index)
} else {
ReturnDest::DirectOperand(index)
}
}
} else {
- self.trans_place(bcx, dest)
+ self.trans_place(bx, dest)
};
if fn_ret.is_indirect() {
if dest.align.abi() < dest.layout.align.abi() {
}
}
- fn trans_transmute(&mut self, bcx: &Builder<'a, 'tcx>,
+ fn trans_transmute(&mut self, bx: &Builder<'a, 'tcx>,
src: &mir::Operand<'tcx>,
dst: &mir::Place<'tcx>) {
if let mir::Place::Local(index) = *dst {
match self.locals[index] {
- LocalRef::Place(place) => self.trans_transmute_into(bcx, src, place),
+ LocalRef::Place(place) => self.trans_transmute_into(bx, src, place),
LocalRef::Operand(None) => {
- let dst_layout = bcx.ccx.layout_of(self.monomorphized_place_ty(dst));
+ let dst_layout = bx.cx.layout_of(self.monomorphized_place_ty(dst));
assert!(!dst_layout.ty.has_erasable_regions());
- let place = PlaceRef::alloca(bcx, dst_layout, "transmute_temp");
- place.storage_live(bcx);
- self.trans_transmute_into(bcx, src, place);
- let op = place.load(bcx);
- place.storage_dead(bcx);
+ let place = PlaceRef::alloca(bx, dst_layout, "transmute_temp");
+ place.storage_live(bx);
+ self.trans_transmute_into(bx, src, place);
+ let op = place.load(bx);
+ place.storage_dead(bx);
self.locals[index] = LocalRef::Operand(Some(op));
}
LocalRef::Operand(Some(op)) => {
}
}
} else {
- let dst = self.trans_place(bcx, dst);
- self.trans_transmute_into(bcx, src, dst);
+ let dst = self.trans_place(bx, dst);
+ self.trans_transmute_into(bx, src, dst);
}
}
- fn trans_transmute_into(&mut self, bcx: &Builder<'a, 'tcx>,
+ fn trans_transmute_into(&mut self, bx: &Builder<'a, 'tcx>,
src: &mir::Operand<'tcx>,
dst: PlaceRef<'tcx>) {
- let src = self.trans_operand(bcx, src);
- let llty = src.layout.llvm_type(bcx.ccx);
- let cast_ptr = bcx.pointercast(dst.llval, llty.ptr_to());
+ let src = self.trans_operand(bx, src);
+ let llty = src.layout.llvm_type(bx.cx);
+ let cast_ptr = bx.pointercast(dst.llval, llty.ptr_to());
let align = src.layout.align.min(dst.layout.align);
- src.val.store(bcx, PlaceRef::new_sized(cast_ptr, src.layout, align));
+ src.val.store(bx, PlaceRef::new_sized(cast_ptr, src.layout, align));
}
// Stores the return value of a function call into it's final location.
fn store_return(&mut self,
- bcx: &Builder<'a, 'tcx>,
+ bx: &Builder<'a, 'tcx>,
dest: ReturnDest<'tcx>,
ret_ty: &ArgType<'tcx>,
llval: ValueRef) {
match dest {
Nothing => (),
- Store(dst) => ret_ty.store(bcx, llval, dst),
+ Store(dst) => ret_ty.store(bx, llval, dst),
IndirectOperand(tmp, index) => {
- let op = tmp.load(bcx);
- tmp.storage_dead(bcx);
+ let op = tmp.load(bx);
+ tmp.storage_dead(bx);
self.locals[index] = LocalRef::Operand(Some(op));
}
DirectOperand(index) => {
// If there is a cast, we have to store and reload.
let op = if let PassMode::Cast(_) = ret_ty.mode {
- let tmp = PlaceRef::alloca(bcx, ret_ty.layout, "tmp_ret");
- tmp.storage_live(bcx);
- ret_ty.store(bcx, llval, tmp);
- let op = tmp.load(bcx);
- tmp.storage_dead(bcx);
+ let tmp = PlaceRef::alloca(bx, ret_ty.layout, "tmp_ret");
+ tmp.storage_live(bx);
+ ret_ty.store(bx, llval, tmp);
+ let op = tmp.load(bx);
+ tmp.storage_dead(bx);
op
} else {
- OperandRef::from_immediate_or_packed_pair(bcx, llval, ret_ty.layout)
+ OperandRef::from_immediate_or_packed_pair(bx, llval, ret_ty.layout)
};
self.locals[index] = LocalRef::Operand(Some(op));
}
use abi::{self, Abi};
use callee;
use builder::Builder;
-use common::{self, CrateContext, const_get_elt, val_ty};
+use common::{self, CodegenCx, const_get_elt, val_ty};
use common::{C_array, C_bool, C_bytes, C_int, C_uint, C_uint_big, C_u32, C_u64};
use common::{C_null, C_struct, C_str_slice, C_undef, C_usize, C_vector, C_fat_ptr};
use common::const_to_opt_u128;
use std::ptr;
use super::operand::{OperandRef, OperandValue};
-use super::MirContext;
+use super::FunctionCx;
/// A sized constant rvalue.
/// The LLVM type might not be the same for a single Rust type,
}
}
- pub fn from_constint(ccx: &CrateContext<'a, 'tcx>, ci: &ConstInt) -> Const<'tcx> {
- let tcx = ccx.tcx();
+ pub fn from_constint(cx: &CodegenCx<'a, 'tcx>, ci: &ConstInt) -> Const<'tcx> {
+ let tcx = cx.tcx;
let (llval, ty) = match *ci {
- I8(v) => (C_int(Type::i8(ccx), v as i64), tcx.types.i8),
- I16(v) => (C_int(Type::i16(ccx), v as i64), tcx.types.i16),
- I32(v) => (C_int(Type::i32(ccx), v as i64), tcx.types.i32),
- I64(v) => (C_int(Type::i64(ccx), v as i64), tcx.types.i64),
- I128(v) => (C_uint_big(Type::i128(ccx), v as u128), tcx.types.i128),
- Isize(v) => (C_int(Type::isize(ccx), v.as_i64()), tcx.types.isize),
- U8(v) => (C_uint(Type::i8(ccx), v as u64), tcx.types.u8),
- U16(v) => (C_uint(Type::i16(ccx), v as u64), tcx.types.u16),
- U32(v) => (C_uint(Type::i32(ccx), v as u64), tcx.types.u32),
- U64(v) => (C_uint(Type::i64(ccx), v), tcx.types.u64),
- U128(v) => (C_uint_big(Type::i128(ccx), v), tcx.types.u128),
- Usize(v) => (C_uint(Type::isize(ccx), v.as_u64()), tcx.types.usize),
+ I8(v) => (C_int(Type::i8(cx), v as i64), tcx.types.i8),
+ I16(v) => (C_int(Type::i16(cx), v as i64), tcx.types.i16),
+ I32(v) => (C_int(Type::i32(cx), v as i64), tcx.types.i32),
+ I64(v) => (C_int(Type::i64(cx), v as i64), tcx.types.i64),
+ I128(v) => (C_uint_big(Type::i128(cx), v as u128), tcx.types.i128),
+ Isize(v) => (C_int(Type::isize(cx), v.as_i64()), tcx.types.isize),
+ U8(v) => (C_uint(Type::i8(cx), v as u64), tcx.types.u8),
+ U16(v) => (C_uint(Type::i16(cx), v as u64), tcx.types.u16),
+ U32(v) => (C_uint(Type::i32(cx), v as u64), tcx.types.u32),
+ U64(v) => (C_uint(Type::i64(cx), v), tcx.types.u64),
+ U128(v) => (C_uint_big(Type::i128(cx), v), tcx.types.u128),
+ Usize(v) => (C_uint(Type::isize(cx), v.as_u64()), tcx.types.usize),
};
Const { llval: llval, ty: ty }
}
/// Translate ConstVal into a LLVM constant value.
- pub fn from_constval(ccx: &CrateContext<'a, 'tcx>,
+ pub fn from_constval(cx: &CodegenCx<'a, 'tcx>,
cv: &ConstVal,
ty: Ty<'tcx>)
-> Const<'tcx> {
- let llty = ccx.layout_of(ty).llvm_type(ccx);
+ let llty = cx.layout_of(ty).llvm_type(cx);
let val = match *cv {
ConstVal::Float(v) => {
let bits = match v.ty {
- ast::FloatTy::F32 => C_u32(ccx, v.bits as u32),
- ast::FloatTy::F64 => C_u64(ccx, v.bits as u64)
+ ast::FloatTy::F32 => C_u32(cx, v.bits as u32),
+ ast::FloatTy::F64 => C_u64(cx, v.bits as u64)
};
consts::bitcast(bits, llty)
}
- ConstVal::Bool(v) => C_bool(ccx, v),
- ConstVal::Integral(ref i) => return Const::from_constint(ccx, i),
- ConstVal::Str(ref v) => C_str_slice(ccx, v.clone()),
+ ConstVal::Bool(v) => C_bool(cx, v),
+ ConstVal::Integral(ref i) => return Const::from_constint(cx, i),
+ ConstVal::Str(ref v) => C_str_slice(cx, v.clone()),
ConstVal::ByteStr(v) => {
- consts::addr_of(ccx, C_bytes(ccx, v.data), ccx.align_of(ty), "byte_str")
+ consts::addr_of(cx, C_bytes(cx, v.data), cx.align_of(ty), "byte_str")
}
- ConstVal::Char(c) => C_uint(Type::char(ccx), c as u64),
+ ConstVal::Char(c) => C_uint(Type::char(cx), c as u64),
ConstVal::Function(..) => C_undef(llty),
ConstVal::Variant(_) |
ConstVal::Aggregate(..) |
Const::new(val, ty)
}
- fn get_field(&self, ccx: &CrateContext<'a, 'tcx>, i: usize) -> ValueRef {
- let layout = ccx.layout_of(self.ty);
- let field = layout.field(ccx, i);
+ fn get_field(&self, cx: &CodegenCx<'a, 'tcx>, i: usize) -> ValueRef {
+ let layout = cx.layout_of(self.ty);
+ let field = layout.field(cx, i);
if field.is_zst() {
- return C_undef(field.immediate_llvm_type(ccx));
+ return C_undef(field.immediate_llvm_type(cx));
}
let offset = layout.fields.offset(i);
match layout.abi {
layout::Abi::ScalarPair(ref a, ref b) => {
if offset.bytes() == 0 {
- assert_eq!(field.size, a.value.size(ccx));
+ assert_eq!(field.size, a.value.size(cx));
const_get_elt(self.llval, 0)
} else {
- assert_eq!(offset, a.value.size(ccx)
- .abi_align(b.value.align(ccx)));
- assert_eq!(field.size, b.value.size(ccx));
+ assert_eq!(offset, a.value.size(cx)
+ .abi_align(b.value.align(cx)));
+ assert_eq!(field.size, b.value.size(cx));
const_get_elt(self.llval, 1)
}
}
}
}
- fn get_pair(&self, ccx: &CrateContext<'a, 'tcx>) -> (ValueRef, ValueRef) {
- (self.get_field(ccx, 0), self.get_field(ccx, 1))
+ fn get_pair(&self, cx: &CodegenCx<'a, 'tcx>) -> (ValueRef, ValueRef) {
+ (self.get_field(cx, 0), self.get_field(cx, 1))
}
- fn get_fat_ptr(&self, ccx: &CrateContext<'a, 'tcx>) -> (ValueRef, ValueRef) {
+ fn get_fat_ptr(&self, cx: &CodegenCx<'a, 'tcx>) -> (ValueRef, ValueRef) {
assert_eq!(abi::FAT_PTR_ADDR, 0);
assert_eq!(abi::FAT_PTR_EXTRA, 1);
- self.get_pair(ccx)
+ self.get_pair(cx)
}
fn as_place(&self) -> ConstPlace<'tcx> {
}
}
- pub fn to_operand(&self, ccx: &CrateContext<'a, 'tcx>) -> OperandRef<'tcx> {
- let layout = ccx.layout_of(self.ty);
- let llty = layout.immediate_llvm_type(ccx);
+ pub fn to_operand(&self, cx: &CodegenCx<'a, 'tcx>) -> OperandRef<'tcx> {
+ let layout = cx.layout_of(self.ty);
+ let llty = layout.immediate_llvm_type(cx);
let llvalty = val_ty(self.llval);
let val = if llty == llvalty && layout.is_llvm_scalar_pair() {
} else {
// Otherwise, or if the value is not immediate, we create
// a constant LLVM global and cast its address if necessary.
- let align = ccx.align_of(self.ty);
- let ptr = consts::addr_of(ccx, self.llval, align, "const");
- OperandValue::Ref(consts::ptrcast(ptr, layout.llvm_type(ccx).ptr_to()),
+ let align = cx.align_of(self.ty);
+ let ptr = consts::addr_of(cx, self.llval, align, "const");
+ OperandValue::Ref(consts::ptrcast(ptr, layout.llvm_type(cx).ptr_to()),
layout.align)
};
}
}
- pub fn len<'a>(&self, ccx: &CrateContext<'a, 'tcx>) -> ValueRef {
+ pub fn len<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> ValueRef {
match self.ty.sty {
ty::TyArray(_, n) => {
- C_usize(ccx, n.val.to_const_int().unwrap().to_u64().unwrap())
+ C_usize(cx, n.val.to_const_int().unwrap().to_u64().unwrap())
}
ty::TySlice(_) | ty::TyStr => {
assert!(self.llextra != ptr::null_mut());
/// Machinery for translating a constant's MIR to LLVM values.
/// FIXME(eddyb) use miri and lower its allocations to LLVM.
struct MirConstContext<'a, 'tcx: 'a> {
- ccx: &'a CrateContext<'a, 'tcx>,
+ cx: &'a CodegenCx<'a, 'tcx>,
mir: &'a mir::Mir<'tcx>,
/// Type parameters for const fn and associated constants.
}
impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
- fn new(ccx: &'a CrateContext<'a, 'tcx>,
+ fn new(cx: &'a CodegenCx<'a, 'tcx>,
mir: &'a mir::Mir<'tcx>,
substs: &'tcx Substs<'tcx>,
args: IndexVec<mir::Local, Result<Const<'tcx>, ConstEvalErr<'tcx>>>)
-> MirConstContext<'a, 'tcx> {
let mut context = MirConstContext {
- ccx,
+ cx,
mir,
substs,
locals: (0..mir.local_decls.len()).map(|_| None).collect(),
context
}
- fn trans_def(ccx: &'a CrateContext<'a, 'tcx>,
+ fn trans_def(cx: &'a CodegenCx<'a, 'tcx>,
def_id: DefId,
substs: &'tcx Substs<'tcx>,
args: IndexVec<mir::Local, Result<Const<'tcx>, ConstEvalErr<'tcx>>>)
-> Result<Const<'tcx>, ConstEvalErr<'tcx>> {
- let instance = ty::Instance::resolve(ccx.tcx(),
+ let instance = ty::Instance::resolve(cx.tcx,
ty::ParamEnv::empty(traits::Reveal::All),
def_id,
substs).unwrap();
- let mir = ccx.tcx().instance_mir(instance.def);
- MirConstContext::new(ccx, &mir, instance.substs, args).trans()
+ let mir = cx.tcx.instance_mir(instance.def);
+ MirConstContext::new(cx, &mir, instance.substs, args).trans()
}
fn monomorphize<T>(&self, value: &T) -> T
where T: TransNormalize<'tcx>
{
- self.ccx.tcx().trans_apply_param_substs(self.substs, value)
+ self.cx.tcx.trans_apply_param_substs(self.substs, value)
}
fn trans(&mut self) -> Result<Const<'tcx>, ConstEvalErr<'tcx>> {
- let tcx = self.ccx.tcx();
+ let tcx = self.cx.tcx;
let mut bb = mir::START_BLOCK;
// Make sure to evaluate all statemenets to
let result = if fn_ty.fn_sig(tcx).abi() == Abi::RustIntrinsic {
match &tcx.item_name(def_id)[..] {
"size_of" => {
- let llval = C_usize(self.ccx,
- self.ccx.size_of(substs.type_at(0)).bytes());
+ let llval = C_usize(self.cx,
+ self.cx.size_of(substs.type_at(0)).bytes());
Ok(Const::new(llval, tcx.types.usize))
}
"min_align_of" => {
- let llval = C_usize(self.ccx,
- self.ccx.align_of(substs.type_at(0)).abi());
+ let llval = C_usize(self.cx,
+ self.cx.align_of(substs.type_at(0)).abi());
Ok(Const::new(llval, tcx.types.usize))
}
_ => span_bug!(span, "{:?} in constant", terminator.kind)
match const_scalar_checked_binop(tcx, op, lhs, rhs, ty) {
Some((llval, of)) => {
Ok(trans_const_adt(
- self.ccx,
+ self.cx,
binop_ty,
&mir::AggregateKind::Tuple,
&[
Const::new(llval, val_ty),
- Const::new(C_bool(self.ccx, of), tcx.types.bool)
+ Const::new(C_bool(self.cx, of), tcx.types.bool)
]))
}
None => {
}
})()
} else {
- MirConstContext::trans_def(self.ccx, def_id, substs, arg_vals)
+ MirConstContext::trans_def(self.cx, def_id, substs, arg_vals)
};
add_err(&mut failure, &result);
self.store(dest, result, span);
}
fn is_binop_lang_item(&mut self, def_id: DefId) -> Option<(mir::BinOp, bool)> {
- let tcx = self.ccx.tcx();
+ let tcx = self.cx.tcx;
let items = tcx.lang_items();
let def_id = Some(def_id);
if items.i128_add_fn() == def_id { Some((mir::BinOp::Add, false)) }
fn const_place(&self, place: &mir::Place<'tcx>, span: Span)
-> Result<ConstPlace<'tcx>, ConstEvalErr<'tcx>> {
- let tcx = self.ccx.tcx();
+ let tcx = self.cx.tcx;
if let mir::Place::Local(index) = *place {
return self.locals[index].clone().unwrap_or_else(|| {
mir::Place::Local(_) => bug!(), // handled above
mir::Place::Static(box mir::Static { def_id, ty }) => {
ConstPlace {
- base: Base::Static(consts::get_static(self.ccx, def_id)),
+ base: Base::Static(consts::get_static(self.cx, def_id)),
llextra: ptr::null_mut(),
ty: self.monomorphize(&ty),
}
.projection_ty(tcx, &projection.elem);
let base = tr_base.to_const(span);
let projected_ty = self.monomorphize(&projected_ty).to_ty(tcx);
- let has_metadata = self.ccx.shared().type_has_metadata(projected_ty);
+ let has_metadata = self.cx.type_has_metadata(projected_ty);
let (projected, llextra) = match projection.elem {
mir::ProjectionElem::Deref => {
let (base, extra) = if !has_metadata {
(base.llval, ptr::null_mut())
} else {
- base.get_fat_ptr(self.ccx)
+ base.get_fat_ptr(self.cx)
};
- if self.ccx.statics().borrow().contains_key(&base) {
+ if self.cx.statics.borrow().contains_key(&base) {
(Base::Static(base), extra)
} else if let ty::TyStr = projected_ty.sty {
(Base::Str(base), extra)
} else {
let v = base;
- let v = self.ccx.const_unsized().borrow().get(&v).map_or(v, |&v| v);
+ let v = self.cx.const_unsized.borrow().get(&v).map_or(v, |&v| v);
let mut val = unsafe { llvm::LLVMGetInitializer(v) };
if val.is_null() {
span_bug!(span, "dereference of non-constant pointer `{:?}`",
Value(base));
}
- let layout = self.ccx.layout_of(projected_ty);
+ let layout = self.cx.layout_of(projected_ty);
if let layout::Abi::Scalar(ref scalar) = layout.abi {
- let i1_type = Type::i1(self.ccx);
+ let i1_type = Type::i1(self.cx);
if scalar.is_bool() && val_ty(val) != i1_type {
unsafe {
val = llvm::LLVMConstTrunc(val, i1_type.to_ref());
}
}
mir::ProjectionElem::Field(ref field, _) => {
- let llprojected = base.get_field(self.ccx, field.index());
+ let llprojected = base.get_field(self.cx, field.index());
let llextra = if !has_metadata {
ptr::null_mut()
} else {
};
// Produce an undef instead of a LLVM assertion on OOB.
- let len = common::const_to_uint(tr_base.len(self.ccx));
+ let len = common::const_to_uint(tr_base.len(self.cx));
let llelem = if iv < len as u128 {
const_get_elt(base.llval, iv as u64)
} else {
- C_undef(self.ccx.layout_of(projected_ty).llvm_type(self.ccx))
+ C_undef(self.cx.layout_of(projected_ty).llvm_type(self.cx))
};
(Base::Value(llelem), ptr::null_mut())
match constant.literal.clone() {
mir::Literal::Promoted { index } => {
let mir = &self.mir.promoted[index];
- MirConstContext::new(self.ccx, mir, self.substs, IndexVec::new()).trans()
+ MirConstContext::new(self.cx, mir, self.substs, IndexVec::new()).trans()
}
mir::Literal::Value { value } => {
if let ConstVal::Unevaluated(def_id, substs) = value.val {
let substs = self.monomorphize(&substs);
- MirConstContext::trans_def(self.ccx, def_id, substs, IndexVec::new())
+ MirConstContext::trans_def(self.cx, def_id, substs, IndexVec::new())
} else {
- Ok(Const::from_constval(self.ccx, &value.val, ty))
+ Ok(Const::from_constval(self.cx, &value.val, ty))
}
}
}
let elem_ty = array_ty.builtin_index().unwrap_or_else(|| {
bug!("bad array type {:?}", array_ty)
});
- let llunitty = self.ccx.layout_of(elem_ty).llvm_type(self.ccx);
+ let llunitty = self.cx.layout_of(elem_ty).llvm_type(self.cx);
// If the array contains enums, an LLVM array won't work.
let val = if fields.iter().all(|&f| val_ty(f) == llunitty) {
C_array(llunitty, fields)
} else {
- C_struct(self.ccx, fields, false)
+ C_struct(self.cx, fields, false)
};
Const::new(val, array_ty)
}
fn const_rvalue(&self, rvalue: &mir::Rvalue<'tcx>,
dest_ty: Ty<'tcx>, span: Span)
-> Result<Const<'tcx>, ConstEvalErr<'tcx>> {
- let tcx = self.ccx.tcx();
+ let tcx = self.cx.tcx;
debug!("const_rvalue({:?}: {:?} @ {:?})", rvalue, dest_ty, span);
let val = match *rvalue {
mir::Rvalue::Use(ref operand) => self.const_operand(operand, span)?,
}
failure?;
- trans_const_adt(self.ccx, dest_ty, kind, &fields)
+ trans_const_adt(self.cx, dest_ty, kind, &fields)
}
mir::Rvalue::Cast(ref kind, ref source, cast_ty) => {
mir::CastKind::ReifyFnPointer => {
match operand.ty.sty {
ty::TyFnDef(def_id, substs) => {
- callee::resolve_and_get_fn(self.ccx, def_id, substs)
+ callee::resolve_and_get_fn(self.cx, def_id, substs)
}
_ => {
span_bug!(span, "{} cannot be reified to a fn ptr",
let input = tcx.erase_late_bound_regions_and_normalize(&input);
let substs = tcx.mk_substs([operand.ty, input]
.iter().cloned().map(Kind::from));
- callee::resolve_and_get_fn(self.ccx, call_once, substs)
+ callee::resolve_and_get_fn(self.cx, call_once, substs)
}
_ => {
bug!("{} cannot be cast to a fn ptr", operand.ty)
mir::CastKind::Unsize => {
let pointee_ty = operand.ty.builtin_deref(true, ty::NoPreference)
.expect("consts: unsizing got non-pointer type").ty;
- let (base, old_info) = if !self.ccx.shared().type_is_sized(pointee_ty) {
+ let (base, old_info) = if !self.cx.type_is_sized(pointee_ty) {
// Normally, the source is a thin pointer and we are
// adding extra info to make a fat pointer. The exception
// is when we are upcasting an existing object fat pointer
// to use a different vtable. In that case, we want to
// load out the original data pointer so we can repackage
// it.
- let (base, extra) = operand.get_fat_ptr(self.ccx);
+ let (base, extra) = operand.get_fat_ptr(self.cx);
(base, Some(extra))
} else {
(operand.llval, None)
let unsized_ty = cast_ty.builtin_deref(true, ty::NoPreference)
.expect("consts: unsizing got non-pointer target type").ty;
- let ptr_ty = self.ccx.layout_of(unsized_ty).llvm_type(self.ccx).ptr_to();
+ let ptr_ty = self.cx.layout_of(unsized_ty).llvm_type(self.cx).ptr_to();
let base = consts::ptrcast(base, ptr_ty);
- let info = base::unsized_info(self.ccx, pointee_ty,
+ let info = base::unsized_info(self.cx, pointee_ty,
unsized_ty, old_info);
if old_info.is_none() {
- let prev_const = self.ccx.const_unsized().borrow_mut()
+ let prev_const = self.cx.const_unsized.borrow_mut()
.insert(base, operand.llval);
assert!(prev_const.is_none() || prev_const == Some(operand.llval));
}
- C_fat_ptr(self.ccx, base, info)
+ C_fat_ptr(self.cx, base, info)
}
- mir::CastKind::Misc if self.ccx.layout_of(operand.ty).is_llvm_immediate() => {
+ mir::CastKind::Misc if self.cx.layout_of(operand.ty).is_llvm_immediate() => {
let r_t_in = CastTy::from_ty(operand.ty).expect("bad input type for cast");
let r_t_out = CastTy::from_ty(cast_ty).expect("bad output type for cast");
- let cast_layout = self.ccx.layout_of(cast_ty);
+ let cast_layout = self.cx.layout_of(cast_ty);
assert!(cast_layout.is_llvm_immediate());
- let ll_t_out = cast_layout.immediate_llvm_type(self.ccx);
+ let ll_t_out = cast_layout.immediate_llvm_type(self.cx);
let llval = operand.llval;
let mut signed = false;
- let l = self.ccx.layout_of(operand.ty);
+ let l = self.cx.layout_of(operand.ty);
if let layout::Abi::Scalar(ref scalar) = l.abi {
if let layout::Int(_, true) = scalar.value {
signed = true;
llvm::LLVMConstIntCast(llval, ll_t_out.to_ref(), s)
}
(CastTy::Int(_), CastTy::Float) => {
- cast_const_int_to_float(self.ccx, llval, signed, ll_t_out)
+ cast_const_int_to_float(self.cx, llval, signed, ll_t_out)
}
(CastTy::Float, CastTy::Float) => {
llvm::LLVMConstFPCast(llval, ll_t_out.to_ref())
}
(CastTy::Float, CastTy::Int(IntTy::I)) => {
- cast_const_float_to_int(self.ccx, &operand,
+ cast_const_float_to_int(self.cx, &operand,
true, ll_t_out, span)
}
(CastTy::Float, CastTy::Int(_)) => {
- cast_const_float_to_int(self.ccx, &operand,
+ cast_const_float_to_int(self.cx, &operand,
false, ll_t_out, span)
}
(CastTy::Ptr(_), CastTy::Ptr(_)) |
(CastTy::Int(_), CastTy::Ptr(_)) => {
let s = signed as llvm::Bool;
let usize_llval = llvm::LLVMConstIntCast(llval,
- self.ccx.isize_ty().to_ref(), s);
+ self.cx.isize_ty.to_ref(), s);
llvm::LLVMConstIntToPtr(usize_llval, ll_t_out.to_ref())
}
(CastTy::Ptr(_), CastTy::Int(_)) |
}
}
mir::CastKind::Misc => { // Casts from a fat-ptr.
- let l = self.ccx.layout_of(operand.ty);
- let cast = self.ccx.layout_of(cast_ty);
+ let l = self.cx.layout_of(operand.ty);
+ let cast = self.cx.layout_of(cast_ty);
if l.is_llvm_scalar_pair() {
- let (data_ptr, meta) = operand.get_fat_ptr(self.ccx);
+ let (data_ptr, meta) = operand.get_fat_ptr(self.cx);
if cast.is_llvm_scalar_pair() {
let data_cast = consts::ptrcast(data_ptr,
- cast.scalar_pair_element_llvm_type(self.ccx, 0));
- C_fat_ptr(self.ccx, data_cast, meta)
+ cast.scalar_pair_element_llvm_type(self.cx, 0));
+ C_fat_ptr(self.cx, data_cast, meta)
} else { // cast to thin-ptr
// Cast of fat-ptr to thin-ptr is an extraction of data-ptr and
// pointer-cast of that pointer to desired pointer type.
- let llcast_ty = cast.immediate_llvm_type(self.ccx);
+ let llcast_ty = cast.immediate_llvm_type(self.cx);
consts::ptrcast(data_ptr, llcast_ty)
}
} else {
let base = match tr_place.base {
Base::Value(llval) => {
// FIXME: may be wrong for &*(&simd_vec as &fmt::Debug)
- let align = if self.ccx.shared().type_is_sized(ty) {
- self.ccx.align_of(ty)
+ let align = if self.cx.type_is_sized(ty) {
+ self.cx.align_of(ty)
} else {
- self.ccx.tcx().data_layout.pointer_align
+ self.cx.tcx.data_layout.pointer_align
};
if bk == mir::BorrowKind::Mut {
- consts::addr_of_mut(self.ccx, llval, align, "ref_mut")
+ consts::addr_of_mut(self.cx, llval, align, "ref_mut")
} else {
- consts::addr_of(self.ccx, llval, align, "ref")
+ consts::addr_of(self.cx, llval, align, "ref")
}
}
Base::Str(llval) |
Base::Static(llval) => llval
};
- let ptr = if self.ccx.shared().type_is_sized(ty) {
+ let ptr = if self.cx.type_is_sized(ty) {
base
} else {
- C_fat_ptr(self.ccx, base, tr_place.llextra)
+ C_fat_ptr(self.cx, base, tr_place.llextra)
};
Const::new(ptr, ref_ty)
}
mir::Rvalue::Len(ref place) => {
let tr_place = self.const_place(place, span)?;
- Const::new(tr_place.len(self.ccx), tcx.types.usize)
+ Const::new(tr_place.len(self.cx), tcx.types.usize)
}
mir::Rvalue::BinaryOp(op, ref lhs, ref rhs) => {
match const_scalar_checked_binop(tcx, op, lhs, rhs, ty) {
Some((llval, of)) => {
- trans_const_adt(self.ccx, binop_ty, &mir::AggregateKind::Tuple, &[
+ trans_const_adt(self.cx, binop_ty, &mir::AggregateKind::Tuple, &[
Const::new(llval, val_ty),
- Const::new(C_bool(self.ccx, of), tcx.types.bool)
+ Const::new(C_bool(self.cx, of), tcx.types.bool)
])
}
None => {
}
mir::Rvalue::NullaryOp(mir::NullOp::SizeOf, ty) => {
- assert!(self.ccx.shared().type_is_sized(ty));
- let llval = C_usize(self.ccx, self.ccx.size_of(ty).bytes());
+ assert!(self.cx.type_is_sized(ty));
+ let llval = C_usize(self.cx, self.cx.size_of(ty).bytes());
Const::new(llval, tcx.types.usize)
}
}
}
-unsafe fn cast_const_float_to_int(ccx: &CrateContext,
+unsafe fn cast_const_float_to_int(cx: &CodegenCx,
operand: &Const,
signed: bool,
int_ty: Type,
// One way that might happen would be if addresses could be turned into integers in constant
// expressions, but that doesn't appear to be possible?
// In any case, an ICE is better than producing undef.
- let llval_bits = consts::bitcast(llval, Type::ix(ccx, float_bits as u64));
+ let llval_bits = consts::bitcast(llval, Type::ix(cx, float_bits as u64));
let bits = const_to_opt_u128(llval_bits, false).unwrap_or_else(|| {
panic!("could not get bits of constant float {:?}",
Value(llval));
};
if cast_result.status.contains(Status::INVALID_OP) {
let err = ConstEvalErr { span: span, kind: ErrKind::CannotCast };
- err.report(ccx.tcx(), span, "expression");
+ err.report(cx.tcx, span, "expression");
}
C_uint_big(int_ty, cast_result.value)
}
-unsafe fn cast_const_int_to_float(ccx: &CrateContext,
+unsafe fn cast_const_int_to_float(cx: &CodegenCx,
llval: ValueRef,
signed: bool,
float_ty: Type) -> ValueRef {
llvm::LLVMConstSIToFP(llval, float_ty.to_ref())
} else if float_ty.float_width() == 32 && value >= MAX_F32_PLUS_HALF_ULP {
// We're casting to f32 and the value is > f32::MAX + 0.5 ULP -> round up to infinity.
- let infinity_bits = C_u32(ccx, ieee::Single::INFINITY.to_bits() as u32);
+ let infinity_bits = C_u32(cx, ieee::Single::INFINITY.to_bits() as u32);
consts::bitcast(infinity_bits, float_ty)
} else {
llvm::LLVMConstUIToFP(llval, float_ty.to_ref())
}
}
-impl<'a, 'tcx> MirContext<'a, 'tcx> {
+impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
pub fn trans_constant(&mut self,
- bcx: &Builder<'a, 'tcx>,
+ bx: &Builder<'a, 'tcx>,
constant: &mir::Constant<'tcx>)
-> Const<'tcx>
{
let result = match constant.literal.clone() {
mir::Literal::Promoted { index } => {
let mir = &self.mir.promoted[index];
- MirConstContext::new(bcx.ccx, mir, self.param_substs, IndexVec::new()).trans()
+ MirConstContext::new(bx.cx, mir, self.param_substs, IndexVec::new()).trans()
}
mir::Literal::Value { value } => {
if let ConstVal::Unevaluated(def_id, substs) = value.val {
let substs = self.monomorphize(&substs);
- MirConstContext::trans_def(bcx.ccx, def_id, substs, IndexVec::new())
+ MirConstContext::trans_def(bx.cx, def_id, substs, IndexVec::new())
} else {
- Ok(Const::from_constval(bcx.ccx, &value.val, ty))
+ Ok(Const::from_constval(bx.cx, &value.val, ty))
}
}
};
let result = result.unwrap_or_else(|_| {
// We've errored, so we don't have to produce working code.
- let llty = bcx.ccx.layout_of(ty).llvm_type(bcx.ccx);
+ let llty = bx.cx.layout_of(ty).llvm_type(bx.cx);
Const::new(C_undef(llty), ty)
});
pub fn trans_static_initializer<'a, 'tcx>(
- ccx: &CrateContext<'a, 'tcx>,
+ cx: &CodegenCx<'a, 'tcx>,
def_id: DefId)
-> Result<ValueRef, ConstEvalErr<'tcx>>
{
- MirConstContext::trans_def(ccx, def_id, Substs::empty(), IndexVec::new())
+ MirConstContext::trans_def(cx, def_id, Substs::empty(), IndexVec::new())
.map(|c| c.llval)
}
/// this could be changed in the future to avoid allocating unnecessary
/// space after values of shorter-than-maximum cases.
fn trans_const_adt<'a, 'tcx>(
- ccx: &CrateContext<'a, 'tcx>,
+ cx: &CodegenCx<'a, 'tcx>,
t: Ty<'tcx>,
kind: &mir::AggregateKind,
vals: &[Const<'tcx>]
) -> Const<'tcx> {
- let l = ccx.layout_of(t);
+ let l = cx.layout_of(t);
let variant_index = match *kind {
mir::AggregateKind::Adt(_, index, _, _) => index,
_ => 0,
};
if let layout::Abi::Uninhabited = l.abi {
- return Const::new(C_undef(l.llvm_type(ccx)), t);
+ return Const::new(C_undef(l.llvm_type(cx)), t);
}
match l.variants {
if let layout::FieldPlacement::Union(_) = l.fields {
assert_eq!(variant_index, 0);
assert_eq!(vals.len(), 1);
- let (field_size, field_align) = ccx.size_and_align_of(vals[0].ty);
+ let (field_size, field_align) = cx.size_and_align_of(vals[0].ty);
let contents = [
vals[0].llval,
- padding(ccx, l.size - field_size)
+ padding(cx, l.size - field_size)
];
let packed = l.align.abi() < field_align.abi();
- Const::new(C_struct(ccx, &contents, packed), t)
+ Const::new(C_struct(cx, &contents, packed), t)
} else {
if let layout::Abi::Vector { .. } = l.abi {
if let layout::FieldPlacement::Array { .. } = l.fields {
.collect::<Vec<_>>()), t);
}
}
- build_const_struct(ccx, l, vals, None)
+ build_const_struct(cx, l, vals, None)
}
}
layout::Variants::Tagged { .. } => {
let discr = match *kind {
mir::AggregateKind::Adt(adt_def, _, _, _) => {
- adt_def.discriminant_for_variant(ccx.tcx(), variant_index)
+ adt_def.discriminant_for_variant(cx.tcx, variant_index)
.to_u128_unchecked() as u64
},
_ => 0,
};
- let discr_field = l.field(ccx, 0);
- let discr = C_int(discr_field.llvm_type(ccx), discr as i64);
+ let discr_field = l.field(cx, 0);
+ let discr = C_int(discr_field.llvm_type(cx), discr as i64);
if let layout::Abi::Scalar(_) = l.abi {
Const::new(discr, t)
} else {
let discr = Const::new(discr, discr_field.ty);
- build_const_struct(ccx, l.for_variant(ccx, variant_index), vals, Some(discr))
+ build_const_struct(cx, l.for_variant(cx, variant_index), vals, Some(discr))
}
}
layout::Variants::NicheFilling {
..
} => {
if variant_index == dataful_variant {
- build_const_struct(ccx, l.for_variant(ccx, dataful_variant), vals, None)
+ build_const_struct(cx, l.for_variant(cx, dataful_variant), vals, None)
} else {
- let niche = l.field(ccx, 0);
- let niche_llty = niche.llvm_type(ccx);
+ let niche = l.field(cx, 0);
+ let niche_llty = niche.llvm_type(cx);
let niche_value = ((variant_index - niche_variants.start) as u128)
.wrapping_add(niche_start);
// FIXME(eddyb) Check the actual primitive type here.
} else {
C_uint_big(niche_llty, niche_value)
};
- build_const_struct(ccx, l, &[Const::new(niche_llval, niche.ty)], None)
+ build_const_struct(cx, l, &[Const::new(niche_llval, niche.ty)], None)
}
}
}
/// initializer is 4-byte aligned then simply translating the tuple as
/// a two-element struct will locate it at offset 4, and accesses to it
/// will read the wrong memory.
-fn build_const_struct<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
+fn build_const_struct<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
layout: layout::TyLayout<'tcx>,
vals: &[Const<'tcx>],
discr: Option<Const<'tcx>>)
layout::Abi::Vector { .. } if discr.is_none() => {
let mut non_zst_fields = vals.iter().enumerate().map(|(i, f)| {
(f, layout.fields.offset(i))
- }).filter(|&(f, _)| !ccx.layout_of(f.ty).is_zst());
+ }).filter(|&(f, _)| !cx.layout_of(f.ty).is_zst());
match (non_zst_fields.next(), non_zst_fields.next()) {
(Some((x, offset)), None) if offset.bytes() == 0 => {
return Const::new(x.llval, layout.ty);
}
(Some((a, a_offset)), Some((b, _))) if a_offset.bytes() == 0 => {
- return Const::new(C_struct(ccx, &[a.llval, b.llval], false), layout.ty);
+ return Const::new(C_struct(cx, &[a.llval, b.llval], false), layout.ty);
}
(Some((a, _)), Some((b, b_offset))) if b_offset.bytes() == 0 => {
- return Const::new(C_struct(ccx, &[b.llval, a.llval], false), layout.ty);
+ return Const::new(C_struct(cx, &[b.llval, a.llval], false), layout.ty);
}
_ => {}
}
cfields.reserve(discr.is_some() as usize + 1 + layout.fields.count() * 2);
if let Some(discr) = discr {
- let (field_size, field_align) = ccx.size_and_align_of(discr.ty);
+ let (field_size, field_align) = cx.size_and_align_of(discr.ty);
packed |= layout.align.abi() < field_align.abi();
cfields.push(discr.llval);
offset = field_size;
(vals[i], layout.fields.offset(i))
});
for (val, target_offset) in parts {
- let (field_size, field_align) = ccx.size_and_align_of(val.ty);
+ let (field_size, field_align) = cx.size_and_align_of(val.ty);
packed |= layout.align.abi() < field_align.abi();
- cfields.push(padding(ccx, target_offset - offset));
+ cfields.push(padding(cx, target_offset - offset));
cfields.push(val.llval);
offset = target_offset + field_size;
}
// Pad to the size of the whole type, not e.g. the variant.
- cfields.push(padding(ccx, ccx.size_of(layout.ty) - offset));
+ cfields.push(padding(cx, cx.size_of(layout.ty) - offset));
- Const::new(C_struct(ccx, &cfields, packed), layout.ty)
+ Const::new(C_struct(cx, &cfields, packed), layout.ty)
}
-fn padding(ccx: &CrateContext, size: Size) -> ValueRef {
- C_undef(Type::array(&Type::i8(ccx), size.bytes()))
+fn padding(cx: &CodegenCx, size: Size) -> ValueRef {
+ C_undef(Type::array(&Type::i8(cx), size.bytes()))
}
use rustc::session::config::FullDebugInfo;
use base;
use builder::Builder;
-use common::{CrateContext, Funclet};
+use common::{CodegenCx, Funclet};
use debuginfo::{self, declare_local, VariableAccess, VariableKind, FunctionDebugContext};
use monomorphize::Instance;
use abi::{ArgAttribute, FnType, PassMode};
use self::operand::{OperandRef, OperandValue};
/// Master context for translating MIR.
-pub struct MirContext<'a, 'tcx:'a> {
+pub struct FunctionCx<'a, 'tcx:'a> {
mir: &'a mir::Mir<'tcx>,
debug_context: debuginfo::FunctionDebugContext,
llfn: ValueRef,
- ccx: &'a CrateContext<'a, 'tcx>,
+ cx: &'a CodegenCx<'a, 'tcx>,
fn_ty: FnType<'tcx>,
param_substs: &'tcx Substs<'tcx>,
}
-impl<'a, 'tcx> MirContext<'a, 'tcx> {
+impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
pub fn monomorphize<T>(&self, value: &T) -> T
where T: TransNormalize<'tcx>
{
- self.ccx.tcx().trans_apply_param_substs(self.param_substs, value)
+ self.cx.tcx.trans_apply_param_substs(self.param_substs, value)
}
- pub fn set_debug_loc(&mut self, bcx: &Builder, source_info: mir::SourceInfo) {
+ pub fn set_debug_loc(&mut self, bx: &Builder, source_info: mir::SourceInfo) {
let (scope, span) = self.debug_loc(source_info);
- debuginfo::set_source_location(&self.debug_context, bcx, scope, span);
+ debuginfo::set_source_location(&self.debug_context, bx, scope, span);
}
pub fn debug_loc(&mut self, source_info: mir::SourceInfo) -> (DIScope, Span) {
// locations of macro expansions with that of the outermost expansion site
// (unless the crate is being compiled with `-Z debug-macros`).
if source_info.span.ctxt() == NO_EXPANSION ||
- self.ccx.sess().opts.debugging_opts.debug_macros {
+ self.cx.sess().opts.debugging_opts.debug_macros {
let scope = self.scope_metadata_for_loc(source_info.scope, source_info.span.lo());
(scope, source_info.span)
} else {
let scope_metadata = self.scopes[scope_id].scope_metadata;
if pos < self.scopes[scope_id].file_start_pos ||
pos >= self.scopes[scope_id].file_end_pos {
- let cm = self.ccx.sess().codemap();
+ let cm = self.cx.sess().codemap();
let defining_crate = self.debug_context.get_ref(DUMMY_SP).defining_crate;
- debuginfo::extend_scope_to_file(self.ccx,
+ debuginfo::extend_scope_to_file(self.cx,
scope_metadata,
&cm.lookup_char_pos(pos).file,
defining_crate)
}
impl<'a, 'tcx> LocalRef<'tcx> {
- fn new_operand(ccx: &CrateContext<'a, 'tcx>, layout: TyLayout<'tcx>) -> LocalRef<'tcx> {
+ fn new_operand(cx: &CodegenCx<'a, 'tcx>, layout: TyLayout<'tcx>) -> LocalRef<'tcx> {
if layout.is_zst() {
// Zero-size temporaries aren't always initialized, which
// doesn't matter because they don't contain data, but
// we need something in the operand.
- LocalRef::Operand(Some(OperandRef::new_zst(ccx, layout)))
+ LocalRef::Operand(Some(OperandRef::new_zst(cx, layout)))
} else {
LocalRef::Operand(None)
}
///////////////////////////////////////////////////////////////////////////
pub fn trans_mir<'a, 'tcx: 'a>(
- ccx: &'a CrateContext<'a, 'tcx>,
+ cx: &'a CodegenCx<'a, 'tcx>,
llfn: ValueRef,
mir: &'a Mir<'tcx>,
instance: Instance<'tcx>,
sig: ty::FnSig<'tcx>,
) {
- let fn_ty = FnType::new(ccx, sig, &[]);
+ let fn_ty = FnType::new(cx, sig, &[]);
debug!("fn_ty: {:?}", fn_ty);
let debug_context =
- debuginfo::create_function_debug_context(ccx, instance, sig, llfn, mir);
- let bcx = Builder::new_block(ccx, llfn, "start");
+ debuginfo::create_function_debug_context(cx, instance, sig, llfn, mir);
+ let bx = Builder::new_block(cx, llfn, "start");
if mir.basic_blocks().iter().any(|bb| bb.is_cleanup) {
- bcx.set_personality_fn(ccx.eh_personality());
+ bx.set_personality_fn(cx.eh_personality());
}
let cleanup_kinds = analyze::cleanup_kinds(&mir);
// Allocate a `Block` for every basic block, except
// the start block, if nothing loops back to it.
let reentrant_start_block = !mir.predecessors_for(mir::START_BLOCK).is_empty();
- let block_bcxs: IndexVec<mir::BasicBlock, BasicBlockRef> =
+ let block_bxs: IndexVec<mir::BasicBlock, BasicBlockRef> =
mir.basic_blocks().indices().map(|bb| {
if bb == mir::START_BLOCK && !reentrant_start_block {
- bcx.llbb()
+ bx.llbb()
} else {
- bcx.build_sibling_block(&format!("{:?}", bb)).llbb()
+ bx.build_sibling_block(&format!("{:?}", bb)).llbb()
}
}).collect();
// Compute debuginfo scopes from MIR scopes.
- let scopes = debuginfo::create_mir_scopes(ccx, mir, &debug_context);
- let (landing_pads, funclets) = create_funclets(&bcx, &cleanup_kinds, &block_bcxs);
+ let scopes = debuginfo::create_mir_scopes(cx, mir, &debug_context);
+ let (landing_pads, funclets) = create_funclets(&bx, &cleanup_kinds, &block_bxs);
- let mut mircx = MirContext {
+ let mut fx = FunctionCx {
mir,
llfn,
fn_ty,
- ccx,
+ cx,
personality_slot: None,
- blocks: block_bcxs,
+ blocks: block_bxs,
unreachable_block: None,
cleanup_kinds,
landing_pads,
},
};
- let memory_locals = analyze::memory_locals(&mircx);
+ let memory_locals = analyze::memory_locals(&fx);
// Allocate variable and temp allocas
- mircx.locals = {
- let args = arg_local_refs(&bcx, &mircx, &mircx.scopes, &memory_locals);
+ fx.locals = {
+ let args = arg_local_refs(&bx, &fx, &fx.scopes, &memory_locals);
let mut allocate_local = |local| {
let decl = &mir.local_decls[local];
- let layout = bcx.ccx.layout_of(mircx.monomorphize(&decl.ty));
+ let layout = bx.cx.layout_of(fx.monomorphize(&decl.ty));
assert!(!layout.ty.has_erasable_regions());
if let Some(name) = decl.name {
// User variable
- let debug_scope = mircx.scopes[decl.source_info.scope];
- let dbg = debug_scope.is_valid() && bcx.sess().opts.debuginfo == FullDebugInfo;
+ let debug_scope = fx.scopes[decl.source_info.scope];
+ let dbg = debug_scope.is_valid() && bx.sess().opts.debuginfo == FullDebugInfo;
if !memory_locals.contains(local.index()) && !dbg {
debug!("alloc: {:?} ({}) -> operand", local, name);
- return LocalRef::new_operand(bcx.ccx, layout);
+ return LocalRef::new_operand(bx.cx, layout);
}
debug!("alloc: {:?} ({}) -> place", local, name);
- let place = PlaceRef::alloca(&bcx, layout, &name.as_str());
+ let place = PlaceRef::alloca(&bx, layout, &name.as_str());
if dbg {
- let (scope, span) = mircx.debug_loc(decl.source_info);
- declare_local(&bcx, &mircx.debug_context, name, layout.ty, scope,
+ let (scope, span) = fx.debug_loc(decl.source_info);
+ declare_local(&bx, &fx.debug_context, name, layout.ty, scope,
VariableAccess::DirectVariable { alloca: place.llval },
VariableKind::LocalVariable, span);
}
LocalRef::Place(place)
} else {
// Temporary or return place
- if local == mir::RETURN_PLACE && mircx.fn_ty.ret.is_indirect() {
+ if local == mir::RETURN_PLACE && fx.fn_ty.ret.is_indirect() {
debug!("alloc: {:?} (return place) -> place", local);
let llretptr = llvm::get_param(llfn, 0);
LocalRef::Place(PlaceRef::new_sized(llretptr, layout, layout.align))
} else if memory_locals.contains(local.index()) {
debug!("alloc: {:?} -> place", local);
- LocalRef::Place(PlaceRef::alloca(&bcx, layout, &format!("{:?}", local)))
+ LocalRef::Place(PlaceRef::alloca(&bx, layout, &format!("{:?}", local)))
} else {
// If this is an immediate local, we do not create an
// alloca in advance. Instead we wait until we see the
// definition and update the operand there.
debug!("alloc: {:?} -> operand", local);
- LocalRef::new_operand(bcx.ccx, layout)
+ LocalRef::new_operand(bx.cx, layout)
}
}
};
// Branch to the START block, if it's not the entry block.
if reentrant_start_block {
- bcx.br(mircx.blocks[mir::START_BLOCK]);
+ bx.br(fx.blocks[mir::START_BLOCK]);
}
// Up until here, IR instructions for this function have explicitly not been annotated with
// source code location, so we don't step into call setup code. From here on, source location
// emitting should be enabled.
- debuginfo::start_emitting_source_locations(&mircx.debug_context);
+ debuginfo::start_emitting_source_locations(&fx.debug_context);
let rpo = traversal::reverse_postorder(&mir);
let mut visited = BitVector::new(mir.basic_blocks().len());
// Translate the body of each block using reverse postorder
for (bb, _) in rpo {
visited.insert(bb.index());
- mircx.trans_block(bb);
+ fx.trans_block(bb);
}
// Remove blocks that haven't been visited, or have no
if !visited.contains(bb.index()) {
debug!("trans_mir: block {:?} was not visited", bb);
unsafe {
- llvm::LLVMDeleteBasicBlock(mircx.blocks[bb]);
+ llvm::LLVMDeleteBasicBlock(fx.blocks[bb]);
}
}
}
}
fn create_funclets<'a, 'tcx>(
- bcx: &Builder<'a, 'tcx>,
+ bx: &Builder<'a, 'tcx>,
cleanup_kinds: &IndexVec<mir::BasicBlock, CleanupKind>,
- block_bcxs: &IndexVec<mir::BasicBlock, BasicBlockRef>)
+ block_bxs: &IndexVec<mir::BasicBlock, BasicBlockRef>)
-> (IndexVec<mir::BasicBlock, Option<BasicBlockRef>>,
IndexVec<mir::BasicBlock, Option<Funclet>>)
{
- block_bcxs.iter_enumerated().zip(cleanup_kinds).map(|((bb, &llbb), cleanup_kind)| {
+ block_bxs.iter_enumerated().zip(cleanup_kinds).map(|((bb, &llbb), cleanup_kind)| {
match *cleanup_kind {
- CleanupKind::Funclet if base::wants_msvc_seh(bcx.sess()) => {
- let cleanup_bcx = bcx.build_sibling_block(&format!("funclet_{:?}", bb));
- let cleanup = cleanup_bcx.cleanup_pad(None, &[]);
- cleanup_bcx.br(llbb);
- (Some(cleanup_bcx.llbb()), Some(Funclet::new(cleanup)))
+ CleanupKind::Funclet if base::wants_msvc_seh(bx.sess()) => {
+ let cleanup_bx = bx.build_sibling_block(&format!("funclet_{:?}", bb));
+ let cleanup = cleanup_bx.cleanup_pad(None, &[]);
+ cleanup_bx.br(llbb);
+ (Some(cleanup_bx.llbb()), Some(Funclet::new(cleanup)))
}
_ => (None, None)
}
/// Produce, for each argument, a `ValueRef` pointing at the
/// argument's value. As arguments are places, these are always
/// indirect.
-fn arg_local_refs<'a, 'tcx>(bcx: &Builder<'a, 'tcx>,
- mircx: &MirContext<'a, 'tcx>,
+fn arg_local_refs<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
+ fx: &FunctionCx<'a, 'tcx>,
scopes: &IndexVec<mir::VisibilityScope, debuginfo::MirDebugScope>,
memory_locals: &BitVector)
-> Vec<LocalRef<'tcx>> {
- let mir = mircx.mir;
- let tcx = bcx.tcx();
+ let mir = fx.mir;
+ let tcx = bx.tcx();
let mut idx = 0;
- let mut llarg_idx = mircx.fn_ty.ret.is_indirect() as usize;
+ let mut llarg_idx = fx.fn_ty.ret.is_indirect() as usize;
// Get the argument scope, if it exists and if we need it.
let arg_scope = scopes[mir::ARGUMENT_VISIBILITY_SCOPE];
- let arg_scope = if arg_scope.is_valid() && bcx.sess().opts.debuginfo == FullDebugInfo {
+ let arg_scope = if arg_scope.is_valid() && bx.sess().opts.debuginfo == FullDebugInfo {
Some(arg_scope.scope_metadata)
} else {
None
// to reconstruct it into a tuple local variable, from multiple
// individual LLVM function arguments.
- let arg_ty = mircx.monomorphize(&arg_decl.ty);
+ let arg_ty = fx.monomorphize(&arg_decl.ty);
let tupled_arg_tys = match arg_ty.sty {
ty::TyTuple(ref tys, _) => tys,
_ => bug!("spread argument isn't a tuple?!")
};
- let place = PlaceRef::alloca(bcx, bcx.ccx.layout_of(arg_ty), &name);
+ let place = PlaceRef::alloca(bx, bx.cx.layout_of(arg_ty), &name);
for i in 0..tupled_arg_tys.len() {
- let arg = &mircx.fn_ty.args[idx];
+ let arg = &fx.fn_ty.args[idx];
idx += 1;
- arg.store_fn_arg(bcx, &mut llarg_idx, place.project_field(bcx, i));
+ if arg.pad.is_some() {
+ llarg_idx += 1;
+ }
+ arg.store_fn_arg(bx, &mut llarg_idx, place.project_field(bx, i));
}
// Now that we have one alloca that contains the aggregate value,
alloca: place.llval
};
declare_local(
- bcx,
- &mircx.debug_context,
+ bx,
+ &fx.debug_context,
arg_decl.name.unwrap_or(keywords::Invalid.name()),
arg_ty, scope,
variable_access,
return LocalRef::Place(place);
}
- let arg = &mircx.fn_ty.args[idx];
+ let arg = &fx.fn_ty.args[idx];
idx += 1;
if arg.pad.is_some() {
llarg_idx += 1;
let local = |op| LocalRef::Operand(Some(op));
match arg.mode {
PassMode::Ignore => {
- return local(OperandRef::new_zst(bcx.ccx, arg.layout));
+ return local(OperandRef::new_zst(bx.cx, arg.layout));
}
PassMode::Direct(_) => {
- let llarg = llvm::get_param(bcx.llfn(), llarg_idx as c_uint);
- bcx.set_value_name(llarg, &name);
+ let llarg = llvm::get_param(bx.llfn(), llarg_idx as c_uint);
+ bx.set_value_name(llarg, &name);
llarg_idx += 1;
return local(
- OperandRef::from_immediate_or_packed_pair(bcx, llarg, arg.layout));
+ OperandRef::from_immediate_or_packed_pair(bx, llarg, arg.layout));
}
PassMode::Pair(..) => {
- let a = llvm::get_param(bcx.llfn(), llarg_idx as c_uint);
- bcx.set_value_name(a, &(name.clone() + ".0"));
+ let a = llvm::get_param(bx.llfn(), llarg_idx as c_uint);
+ bx.set_value_name(a, &(name.clone() + ".0"));
llarg_idx += 1;
- let b = llvm::get_param(bcx.llfn(), llarg_idx as c_uint);
- bcx.set_value_name(b, &(name + ".1"));
+ let b = llvm::get_param(bx.llfn(), llarg_idx as c_uint);
+ bx.set_value_name(b, &(name + ".1"));
llarg_idx += 1;
return local(OperandRef {
// Don't copy an indirect argument to an alloca, the caller
// already put it in a temporary alloca and gave it up.
// FIXME: lifetimes
- let llarg = llvm::get_param(bcx.llfn(), llarg_idx as c_uint);
- bcx.set_value_name(llarg, &name);
+ let llarg = llvm::get_param(bx.llfn(), llarg_idx as c_uint);
+ bx.set_value_name(llarg, &name);
llarg_idx += 1;
PlaceRef::new_sized(llarg, arg.layout, arg.layout.align)
} else {
- let tmp = PlaceRef::alloca(bcx, arg.layout, &name);
- arg.store_fn_arg(bcx, &mut llarg_idx, tmp);
+ let tmp = PlaceRef::alloca(bx, arg.layout, &name);
+ arg.store_fn_arg(bx, &mut llarg_idx, tmp);
tmp
};
arg_scope.map(|scope| {
}
declare_local(
- bcx,
- &mircx.debug_context,
+ bx,
+ &fx.debug_context,
arg_decl.name.unwrap_or(keywords::Invalid.name()),
arg.layout.ty,
scope,
// Or is it the closure environment?
let (closure_layout, env_ref) = match arg.layout.ty.sty {
- ty::TyRef(_, mt) | ty::TyRawPtr(mt) => (bcx.ccx.layout_of(mt.ty), true),
+ ty::TyRef(_, mt) | ty::TyRawPtr(mt) => (bx.cx.layout_of(mt.ty), true),
_ => (arg.layout, false)
};
// doesn't actually strip the offset when splitting the closure
// environment into its components so it ends up out of bounds.
let env_ptr = if !env_ref {
- let scratch = PlaceRef::alloca(bcx,
- bcx.ccx.layout_of(tcx.mk_mut_ptr(arg.layout.ty)),
+ let scratch = PlaceRef::alloca(bx,
+ bx.cx.layout_of(tcx.mk_mut_ptr(arg.layout.ty)),
"__debuginfo_env_ptr");
- bcx.store(place.llval, scratch.llval, scratch.align);
+ bx.store(place.llval, scratch.llval, scratch.align);
scratch.llval
} else {
place.llval
address_operations: &ops
};
declare_local(
- bcx,
- &mircx.debug_context,
+ bx,
+ &fx.debug_context,
decl.debug_name,
ty,
scope,
use rustc_data_structures::indexed_vec::Idx;
use base;
-use common::{self, CrateContext, C_undef, C_usize};
+use common::{self, CodegenCx, C_undef, C_usize};
use builder::Builder;
use value::Value;
use type_of::LayoutLlvmExt;
use std::fmt;
use std::ptr;
-use super::{MirContext, LocalRef};
+use super::{FunctionCx, LocalRef};
use super::place::PlaceRef;
/// The representation of a Rust value. The enum variant is in fact
}
impl<'a, 'tcx> OperandRef<'tcx> {
- pub fn new_zst(ccx: &CrateContext<'a, 'tcx>,
+ pub fn new_zst(cx: &CodegenCx<'a, 'tcx>,
layout: TyLayout<'tcx>) -> OperandRef<'tcx> {
assert!(layout.is_zst());
OperandRef {
- val: OperandValue::Immediate(C_undef(layout.immediate_llvm_type(ccx))),
+ val: OperandValue::Immediate(C_undef(layout.immediate_llvm_type(cx))),
layout
}
}
}
}
- pub fn deref(self, ccx: &CrateContext<'a, 'tcx>) -> PlaceRef<'tcx> {
+ pub fn deref(self, cx: &CodegenCx<'a, 'tcx>) -> PlaceRef<'tcx> {
let projected_ty = self.layout.ty.builtin_deref(true, ty::NoPreference)
.unwrap_or_else(|| bug!("deref of non-pointer {:?}", self)).ty;
let (llptr, llextra) = match self.val {
OperandValue::Pair(llptr, llextra) => (llptr, llextra),
OperandValue::Ref(..) => bug!("Deref of by-Ref operand {:?}", self)
};
- let layout = ccx.layout_of(projected_ty);
+ let layout = cx.layout_of(projected_ty);
PlaceRef {
llval: llptr,
llextra,
/// If this operand is a `Pair`, we return an aggregate with the two values.
/// For other cases, see `immediate`.
- pub fn immediate_or_packed_pair(self, bcx: &Builder<'a, 'tcx>) -> ValueRef {
+ pub fn immediate_or_packed_pair(self, bx: &Builder<'a, 'tcx>) -> ValueRef {
if let OperandValue::Pair(a, b) = self.val {
- let llty = self.layout.llvm_type(bcx.ccx);
+ let llty = self.layout.llvm_type(bx.cx);
debug!("Operand::immediate_or_packed_pair: packing {:?} into {:?}",
self, llty);
// Reconstruct the immediate aggregate.
let mut llpair = C_undef(llty);
- llpair = bcx.insert_value(llpair, a, 0);
- llpair = bcx.insert_value(llpair, b, 1);
+ llpair = bx.insert_value(llpair, a, 0);
+ llpair = bx.insert_value(llpair, b, 1);
llpair
} else {
self.immediate()
}
/// If the type is a pair, we return a `Pair`, otherwise, an `Immediate`.
- pub fn from_immediate_or_packed_pair(bcx: &Builder<'a, 'tcx>,
+ pub fn from_immediate_or_packed_pair(bx: &Builder<'a, 'tcx>,
llval: ValueRef,
layout: TyLayout<'tcx>)
-> OperandRef<'tcx> {
llval, layout);
// Deconstruct the immediate aggregate.
- OperandValue::Pair(bcx.extract_value(llval, 0),
- bcx.extract_value(llval, 1))
+ OperandValue::Pair(bx.extract_value(llval, 0),
+ bx.extract_value(llval, 1))
} else {
OperandValue::Immediate(llval)
};
OperandRef { val, layout }
}
- pub fn extract_field(&self, bcx: &Builder<'a, 'tcx>, i: usize) -> OperandRef<'tcx> {
- let field = self.layout.field(bcx.ccx, i);
+ pub fn extract_field(&self, bx: &Builder<'a, 'tcx>, i: usize) -> OperandRef<'tcx> {
+ let field = self.layout.field(bx.cx, i);
let offset = self.layout.fields.offset(i);
let mut val = match (self.val, &self.layout.abi) {
// If we're uninhabited, or the field is ZST, it has no data.
_ if self.layout.abi == layout::Abi::Uninhabited || field.is_zst() => {
return OperandRef {
- val: OperandValue::Immediate(C_undef(field.immediate_llvm_type(bcx.ccx))),
+ val: OperandValue::Immediate(C_undef(field.immediate_llvm_type(bx.cx))),
layout: field
};
}
// Extract a scalar component from a pair.
(OperandValue::Pair(a_llval, b_llval), &layout::Abi::ScalarPair(ref a, ref b)) => {
if offset.bytes() == 0 {
- assert_eq!(field.size, a.value.size(bcx.ccx));
+ assert_eq!(field.size, a.value.size(bx.cx));
OperandValue::Immediate(a_llval)
} else {
- assert_eq!(offset, a.value.size(bcx.ccx)
- .abi_align(b.value.align(bcx.ccx)));
- assert_eq!(field.size, b.value.size(bcx.ccx));
+ assert_eq!(offset, a.value.size(bx.cx)
+ .abi_align(b.value.align(bx.cx)));
+ assert_eq!(field.size, b.value.size(bx.cx));
OperandValue::Immediate(b_llval)
}
}
// `#[repr(simd)]` types are also immediate.
(OperandValue::Immediate(llval), &layout::Abi::Vector { .. }) => {
OperandValue::Immediate(
- bcx.extract_element(llval, C_usize(bcx.ccx, i as u64)))
+ bx.extract_element(llval, C_usize(bx.cx, i as u64)))
}
_ => bug!("OperandRef::extract_field({:?}): not applicable", self)
// HACK(eddyb) have to bitcast pointers until LLVM removes pointee types.
match val {
OperandValue::Immediate(ref mut llval) => {
- *llval = bcx.bitcast(*llval, field.immediate_llvm_type(bcx.ccx));
+ *llval = bx.bitcast(*llval, field.immediate_llvm_type(bx.cx));
}
OperandValue::Pair(ref mut a, ref mut b) => {
- *a = bcx.bitcast(*a, field.scalar_pair_element_llvm_type(bcx.ccx, 0));
- *b = bcx.bitcast(*b, field.scalar_pair_element_llvm_type(bcx.ccx, 1));
+ *a = bx.bitcast(*a, field.scalar_pair_element_llvm_type(bx.cx, 0));
+ *b = bx.bitcast(*b, field.scalar_pair_element_llvm_type(bx.cx, 1));
}
OperandValue::Ref(..) => bug!()
}
}
impl<'a, 'tcx> OperandValue {
- pub fn store(self, bcx: &Builder<'a, 'tcx>, dest: PlaceRef<'tcx>) {
+ pub fn store(self, bx: &Builder<'a, 'tcx>, dest: PlaceRef<'tcx>) {
debug!("OperandRef::store: operand={:?}, dest={:?}", self, dest);
// Avoid generating stores of zero-sized values, because the only way to have a zero-sized
// value is through `undef`, and store itself is useless.
}
match self {
OperandValue::Ref(r, source_align) =>
- base::memcpy_ty(bcx, dest.llval, r, dest.layout,
+ base::memcpy_ty(bx, dest.llval, r, dest.layout,
source_align.min(dest.align)),
OperandValue::Immediate(s) => {
- bcx.store(base::from_immediate(bcx, s), dest.llval, dest.align);
+ bx.store(base::from_immediate(bx, s), dest.llval, dest.align);
}
OperandValue::Pair(a, b) => {
for (i, &x) in [a, b].iter().enumerate() {
- let mut llptr = bcx.struct_gep(dest.llval, i as u64);
+ let mut llptr = bx.struct_gep(dest.llval, i as u64);
// Make sure to always store i1 as i8.
- if common::val_ty(x) == Type::i1(bcx.ccx) {
- llptr = bcx.pointercast(llptr, Type::i8p(bcx.ccx));
+ if common::val_ty(x) == Type::i1(bx.cx) {
+ llptr = bx.pointercast(llptr, Type::i8p(bx.cx));
}
- bcx.store(base::from_immediate(bcx, x), llptr, dest.align);
+ bx.store(base::from_immediate(bx, x), llptr, dest.align);
}
}
}
}
}
-impl<'a, 'tcx> MirContext<'a, 'tcx> {
+impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
fn maybe_trans_consume_direct(&mut self,
- bcx: &Builder<'a, 'tcx>,
+ bx: &Builder<'a, 'tcx>,
place: &mir::Place<'tcx>)
-> Option<OperandRef<'tcx>>
{
// Moves out of scalar and scalar pair fields are trivial.
if let &mir::Place::Projection(ref proj) = place {
- if let Some(o) = self.maybe_trans_consume_direct(bcx, &proj.base) {
+ if let Some(o) = self.maybe_trans_consume_direct(bx, &proj.base) {
match proj.elem {
mir::ProjectionElem::Field(ref f, _) => {
- return Some(o.extract_field(bcx, f.index()));
+ return Some(o.extract_field(bx, f.index()));
}
mir::ProjectionElem::Index(_) |
mir::ProjectionElem::ConstantIndex { .. } => {
// ZSTs don't require any actual memory access.
// FIXME(eddyb) deduplicate this with the identical
// checks in `trans_consume` and `extract_field`.
- let elem = o.layout.field(bcx.ccx, 0);
+ let elem = o.layout.field(bx.cx, 0);
if elem.is_zst() {
- return Some(OperandRef::new_zst(bcx.ccx, elem));
+ return Some(OperandRef::new_zst(bx.cx, elem));
}
}
_ => {}
}
pub fn trans_consume(&mut self,
- bcx: &Builder<'a, 'tcx>,
+ bx: &Builder<'a, 'tcx>,
place: &mir::Place<'tcx>)
-> OperandRef<'tcx>
{
debug!("trans_consume(place={:?})", place);
let ty = self.monomorphized_place_ty(place);
- let layout = bcx.ccx.layout_of(ty);
+ let layout = bx.cx.layout_of(ty);
// ZSTs don't require any actual memory access.
if layout.is_zst() {
- return OperandRef::new_zst(bcx.ccx, layout);
+ return OperandRef::new_zst(bx.cx, layout);
}
- if let Some(o) = self.maybe_trans_consume_direct(bcx, place) {
+ if let Some(o) = self.maybe_trans_consume_direct(bx, place) {
return o;
}
// for most places, to consume them we just load them
// out from their home
- self.trans_place(bcx, place).load(bcx)
+ self.trans_place(bx, place).load(bx)
}
pub fn trans_operand(&mut self,
- bcx: &Builder<'a, 'tcx>,
+ bx: &Builder<'a, 'tcx>,
operand: &mir::Operand<'tcx>)
-> OperandRef<'tcx>
{
match *operand {
mir::Operand::Copy(ref place) |
mir::Operand::Move(ref place) => {
- self.trans_consume(bcx, place)
+ self.trans_consume(bx, place)
}
mir::Operand::Constant(ref constant) => {
- let val = self.trans_constant(&bcx, constant);
- let operand = val.to_operand(bcx.ccx);
+ let val = self.trans_constant(&bx, constant);
+ let operand = val.to_operand(bx.cx);
if let OperandValue::Ref(ptr, align) = operand.val {
// If this is a OperandValue::Ref to an immediate constant, load it.
- PlaceRef::new_sized(ptr, operand.layout, align).load(bcx)
+ PlaceRef::new_sized(ptr, operand.layout, align).load(bx)
} else {
operand
}
use rustc_data_structures::indexed_vec::Idx;
use base;
use builder::Builder;
-use common::{CrateContext, C_usize, C_u8, C_u32, C_uint, C_int, C_null, C_uint_big};
+use common::{CodegenCx, C_usize, C_u8, C_u32, C_uint, C_int, C_null, C_uint_big};
use consts;
use type_of::LayoutLlvmExt;
use type_::Type;
use std::ptr;
-use super::{MirContext, LocalRef};
+use super::{FunctionCx, LocalRef};
use super::operand::{OperandRef, OperandValue};
#[derive(Copy, Clone, Debug)]
}
}
- pub fn alloca(bcx: &Builder<'a, 'tcx>, layout: TyLayout<'tcx>, name: &str)
+ pub fn alloca(bx: &Builder<'a, 'tcx>, layout: TyLayout<'tcx>, name: &str)
-> PlaceRef<'tcx> {
debug!("alloca({:?}: {:?})", name, layout);
- let tmp = bcx.alloca(layout.llvm_type(bcx.ccx), name, layout.align);
+ let tmp = bx.alloca(layout.llvm_type(bx.cx), name, layout.align);
Self::new_sized(tmp, layout, layout.align)
}
- pub fn len(&self, ccx: &CrateContext<'a, 'tcx>) -> ValueRef {
+ pub fn len(&self, cx: &CodegenCx<'a, 'tcx>) -> ValueRef {
if let layout::FieldPlacement::Array { count, .. } = self.layout.fields {
if self.layout.is_unsized() {
assert!(self.has_extra());
assert_eq!(count, 0);
self.llextra
} else {
- C_usize(ccx, count)
+ C_usize(cx, count)
}
} else {
bug!("unexpected layout `{:#?}` in PlaceRef::len", self.layout)
!self.llextra.is_null()
}
- pub fn load(&self, bcx: &Builder<'a, 'tcx>) -> OperandRef<'tcx> {
+ pub fn load(&self, bx: &Builder<'a, 'tcx>) -> OperandRef<'tcx> {
debug!("PlaceRef::load: {:?}", self);
assert!(!self.has_extra());
if self.layout.is_zst() {
- return OperandRef::new_zst(bcx.ccx, self.layout);
+ return OperandRef::new_zst(bx.cx, self.layout);
}
let scalar_load_metadata = |load, scalar: &layout::Scalar| {
let (min, max) = (scalar.valid_range.start, scalar.valid_range.end);
let max_next = max.wrapping_add(1);
- let bits = scalar.value.size(bcx.ccx).bits();
+ let bits = scalar.value.size(bx.cx).bits();
assert!(bits <= 128);
let mask = !0u128 >> (128 - bits);
// For a (max) value of -1, max will be `-1 as usize`, which overflows.
layout::Int(..) if max_next & mask != min & mask => {
// llvm::ConstantRange can deal with ranges that wrap around,
// so an overflow on (max + 1) is fine.
- bcx.range_metadata(load, min..max_next);
+ bx.range_metadata(load, min..max_next);
}
layout::Pointer if 0 < min && min < max => {
- bcx.nonnull_metadata(load);
+ bx.nonnull_metadata(load);
}
_ => {}
}
let llval = if !const_llval.is_null() {
const_llval
} else {
- let load = bcx.load(self.llval, self.align);
+ let load = bx.load(self.llval, self.align);
if let layout::Abi::Scalar(ref scalar) = self.layout.abi {
scalar_load_metadata(load, scalar);
}
load
};
- OperandValue::Immediate(base::to_immediate(bcx, llval, self.layout))
+ OperandValue::Immediate(base::to_immediate(bx, llval, self.layout))
} else if let layout::Abi::ScalarPair(ref a, ref b) = self.layout.abi {
let load = |i, scalar: &layout::Scalar| {
- let mut llptr = bcx.struct_gep(self.llval, i as u64);
+ let mut llptr = bx.struct_gep(self.llval, i as u64);
// Make sure to always load i1 as i8.
if scalar.is_bool() {
- llptr = bcx.pointercast(llptr, Type::i8p(bcx.ccx));
+ llptr = bx.pointercast(llptr, Type::i8p(bx.cx));
}
- let load = bcx.load(llptr, self.align);
+ let load = bx.load(llptr, self.align);
scalar_load_metadata(load, scalar);
if scalar.is_bool() {
- bcx.trunc(load, Type::i1(bcx.ccx))
+ bx.trunc(load, Type::i1(bx.cx))
} else {
load
}
}
/// Access a field, at a point when the value's case is known.
- pub fn project_field(self, bcx: &Builder<'a, 'tcx>, ix: usize) -> PlaceRef<'tcx> {
- let ccx = bcx.ccx;
- let field = self.layout.field(ccx, ix);
+ pub fn project_field(self, bx: &Builder<'a, 'tcx>, ix: usize) -> PlaceRef<'tcx> {
+ let cx = bx.cx;
+ let field = self.layout.field(cx, ix);
let offset = self.layout.fields.offset(ix);
let align = self.align.min(self.layout.align).min(field.align);
self.llval
} else if let layout::Abi::ScalarPair(ref a, ref b) = self.layout.abi {
// Offsets have to match either first or second field.
- assert_eq!(offset, a.value.size(ccx).abi_align(b.value.align(ccx)));
- bcx.struct_gep(self.llval, 1)
+ assert_eq!(offset, a.value.size(cx).abi_align(b.value.align(cx)));
+ bx.struct_gep(self.llval, 1)
} else {
- bcx.struct_gep(self.llval, self.layout.llvm_field_index(ix))
+ bx.struct_gep(self.llval, self.layout.llvm_field_index(ix))
};
PlaceRef {
// HACK(eddyb) have to bitcast pointers until LLVM removes pointee types.
- llval: bcx.pointercast(llval, field.llvm_type(ccx).ptr_to()),
- llextra: if ccx.shared().type_has_metadata(field.ty) {
+ llval: bx.pointercast(llval, field.llvm_type(cx).ptr_to()),
+ llextra: if cx.type_has_metadata(field.ty) {
self.llextra
} else {
ptr::null_mut()
let meta = self.llextra;
- let unaligned_offset = C_usize(ccx, offset.bytes());
+ let unaligned_offset = C_usize(cx, offset.bytes());
// Get the alignment of the field
- let (_, unsized_align) = glue::size_and_align_of_dst(bcx, field.ty, meta);
+ let (_, unsized_align) = glue::size_and_align_of_dst(bx, field.ty, meta);
// Bump the unaligned offset up to the appropriate alignment using the
// following expression:
// (unaligned offset + (align - 1)) & -align
// Calculate offset
- let align_sub_1 = bcx.sub(unsized_align, C_usize(ccx, 1u64));
- let offset = bcx.and(bcx.add(unaligned_offset, align_sub_1),
- bcx.neg(unsized_align));
+ let align_sub_1 = bx.sub(unsized_align, C_usize(cx, 1u64));
+ let offset = bx.and(bx.add(unaligned_offset, align_sub_1),
+ bx.neg(unsized_align));
debug!("struct_field_ptr: DST field offset: {:?}", Value(offset));
// Cast and adjust pointer
- let byte_ptr = bcx.pointercast(self.llval, Type::i8p(ccx));
- let byte_ptr = bcx.gep(byte_ptr, &[offset]);
+ let byte_ptr = bx.pointercast(self.llval, Type::i8p(cx));
+ let byte_ptr = bx.gep(byte_ptr, &[offset]);
// Finally, cast back to the type expected
- let ll_fty = field.llvm_type(ccx);
+ let ll_fty = field.llvm_type(cx);
debug!("struct_field_ptr: Field type is {:?}", ll_fty);
PlaceRef {
- llval: bcx.pointercast(byte_ptr, ll_fty.ptr_to()),
+ llval: bx.pointercast(byte_ptr, ll_fty.ptr_to()),
llextra: self.llextra,
layout: field,
align,
}
/// Obtain the actual discriminant of a value.
- pub fn trans_get_discr(self, bcx: &Builder<'a, 'tcx>, cast_to: Ty<'tcx>) -> ValueRef {
- let cast_to = bcx.ccx.layout_of(cast_to).immediate_llvm_type(bcx.ccx);
+ pub fn trans_get_discr(self, bx: &Builder<'a, 'tcx>, cast_to: Ty<'tcx>) -> ValueRef {
+ let cast_to = bx.cx.layout_of(cast_to).immediate_llvm_type(bx.cx);
match self.layout.variants {
layout::Variants::Single { index } => {
return C_uint(cast_to, index as u64);
layout::Variants::NicheFilling { .. } => {},
}
- let discr = self.project_field(bcx, 0);
- let lldiscr = discr.load(bcx).immediate();
+ let discr = self.project_field(bx, 0);
+ let lldiscr = discr.load(bx).immediate();
match self.layout.variants {
layout::Variants::Single { .. } => bug!(),
layout::Variants::Tagged { ref discr, .. } => {
layout::Int(_, signed) => signed,
_ => false
};
- bcx.intcast(lldiscr, cast_to, signed)
+ bx.intcast(lldiscr, cast_to, signed)
}
layout::Variants::NicheFilling {
dataful_variant,
niche_start,
..
} => {
- let niche_llty = discr.layout.immediate_llvm_type(bcx.ccx);
+ let niche_llty = discr.layout.immediate_llvm_type(bx.cx);
if niche_variants.start == niche_variants.end {
// FIXME(eddyb) Check the actual primitive type here.
let niche_llval = if niche_start == 0 {
} else {
C_uint_big(niche_llty, niche_start)
};
- bcx.select(bcx.icmp(llvm::IntEQ, lldiscr, niche_llval),
+ bx.select(bx.icmp(llvm::IntEQ, lldiscr, niche_llval),
C_uint(cast_to, niche_variants.start as u64),
C_uint(cast_to, dataful_variant as u64))
} else {
// Rebase from niche values to discriminant values.
let delta = niche_start.wrapping_sub(niche_variants.start as u128);
- let lldiscr = bcx.sub(lldiscr, C_uint_big(niche_llty, delta));
+ let lldiscr = bx.sub(lldiscr, C_uint_big(niche_llty, delta));
let lldiscr_max = C_uint(niche_llty, niche_variants.end as u64);
- bcx.select(bcx.icmp(llvm::IntULE, lldiscr, lldiscr_max),
- bcx.intcast(lldiscr, cast_to, false),
+ bx.select(bx.icmp(llvm::IntULE, lldiscr, lldiscr_max),
+ bx.intcast(lldiscr, cast_to, false),
C_uint(cast_to, dataful_variant as u64))
}
}
/// Set the discriminant for a new value of the given case of the given
/// representation.
- pub fn trans_set_discr(&self, bcx: &Builder<'a, 'tcx>, variant_index: usize) {
- if self.layout.for_variant(bcx.ccx, variant_index).abi == layout::Abi::Uninhabited {
+ pub fn trans_set_discr(&self, bx: &Builder<'a, 'tcx>, variant_index: usize) {
+ if self.layout.for_variant(bx.cx, variant_index).abi == layout::Abi::Uninhabited {
return;
}
match self.layout.variants {
assert_eq!(index, variant_index);
}
layout::Variants::Tagged { .. } => {
- let ptr = self.project_field(bcx, 0);
+ let ptr = self.project_field(bx, 0);
let to = self.layout.ty.ty_adt_def().unwrap()
- .discriminant_for_variant(bcx.tcx(), variant_index)
+ .discriminant_for_variant(bx.tcx(), variant_index)
.to_u128_unchecked() as u64;
- bcx.store(C_int(ptr.layout.llvm_type(bcx.ccx), to as i64),
+ bx.store(C_int(ptr.layout.llvm_type(bx.cx), to as i64),
ptr.llval, ptr.align);
}
layout::Variants::NicheFilling {
..
} => {
if variant_index != dataful_variant {
- if bcx.sess().target.target.arch == "arm" ||
- bcx.sess().target.target.arch == "aarch64" {
+ if bx.sess().target.target.arch == "arm" ||
+ bx.sess().target.target.arch == "aarch64" {
// Issue #34427: As workaround for LLVM bug on ARM,
// use memset of 0 before assigning niche value.
- let llptr = bcx.pointercast(self.llval, Type::i8(bcx.ccx).ptr_to());
- let fill_byte = C_u8(bcx.ccx, 0);
+ let llptr = bx.pointercast(self.llval, Type::i8(bx.cx).ptr_to());
+ let fill_byte = C_u8(bx.cx, 0);
let (size, align) = self.layout.size_and_align();
- let size = C_usize(bcx.ccx, size.bytes());
- let align = C_u32(bcx.ccx, align.abi() as u32);
- base::call_memset(bcx, llptr, fill_byte, size, align, false);
+ let size = C_usize(bx.cx, size.bytes());
+ let align = C_u32(bx.cx, align.abi() as u32);
+ base::call_memset(bx, llptr, fill_byte, size, align, false);
}
- let niche = self.project_field(bcx, 0);
- let niche_llty = niche.layout.immediate_llvm_type(bcx.ccx);
+ let niche = self.project_field(bx, 0);
+ let niche_llty = niche.layout.immediate_llvm_type(bx.cx);
let niche_value = ((variant_index - niche_variants.start) as u128)
.wrapping_add(niche_start);
// FIXME(eddyb) Check the actual primitive type here.
} else {
C_uint_big(niche_llty, niche_value)
};
- OperandValue::Immediate(niche_llval).store(bcx, niche);
+ OperandValue::Immediate(niche_llval).store(bx, niche);
}
}
}
}
- pub fn project_index(&self, bcx: &Builder<'a, 'tcx>, llindex: ValueRef)
+ pub fn project_index(&self, bx: &Builder<'a, 'tcx>, llindex: ValueRef)
-> PlaceRef<'tcx> {
PlaceRef {
- llval: bcx.inbounds_gep(self.llval, &[C_usize(bcx.ccx, 0), llindex]),
+ llval: bx.inbounds_gep(self.llval, &[C_usize(bx.cx, 0), llindex]),
llextra: ptr::null_mut(),
- layout: self.layout.field(bcx.ccx, 0),
+ layout: self.layout.field(bx.cx, 0),
align: self.align
}
}
- pub fn project_downcast(&self, bcx: &Builder<'a, 'tcx>, variant_index: usize)
+ pub fn project_downcast(&self, bx: &Builder<'a, 'tcx>, variant_index: usize)
-> PlaceRef<'tcx> {
let mut downcast = *self;
- downcast.layout = self.layout.for_variant(bcx.ccx, variant_index);
+ downcast.layout = self.layout.for_variant(bx.cx, variant_index);
// Cast to the appropriate variant struct type.
- let variant_ty = downcast.layout.llvm_type(bcx.ccx);
- downcast.llval = bcx.pointercast(downcast.llval, variant_ty.ptr_to());
+ let variant_ty = downcast.layout.llvm_type(bx.cx);
+ downcast.llval = bx.pointercast(downcast.llval, variant_ty.ptr_to());
downcast
}
- pub fn storage_live(&self, bcx: &Builder<'a, 'tcx>) {
- bcx.lifetime_start(self.llval, self.layout.size);
+ pub fn storage_live(&self, bx: &Builder<'a, 'tcx>) {
+ bx.lifetime_start(self.llval, self.layout.size);
}
- pub fn storage_dead(&self, bcx: &Builder<'a, 'tcx>) {
- bcx.lifetime_end(self.llval, self.layout.size);
+ pub fn storage_dead(&self, bx: &Builder<'a, 'tcx>) {
+ bx.lifetime_end(self.llval, self.layout.size);
}
}
-impl<'a, 'tcx> MirContext<'a, 'tcx> {
+impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
pub fn trans_place(&mut self,
- bcx: &Builder<'a, 'tcx>,
+ bx: &Builder<'a, 'tcx>,
place: &mir::Place<'tcx>)
-> PlaceRef<'tcx> {
debug!("trans_place(place={:?})", place);
- let ccx = bcx.ccx;
- let tcx = ccx.tcx();
+ let cx = bx.cx;
+ let tcx = cx.tcx;
if let mir::Place::Local(index) = *place {
match self.locals[index] {
let result = match *place {
mir::Place::Local(_) => bug!(), // handled above
mir::Place::Static(box mir::Static { def_id, ty }) => {
- let layout = ccx.layout_of(self.monomorphize(&ty));
- PlaceRef::new_sized(consts::get_static(ccx, def_id), layout, layout.align)
+ let layout = cx.layout_of(self.monomorphize(&ty));
+ PlaceRef::new_sized(consts::get_static(cx, def_id), layout, layout.align)
},
mir::Place::Projection(box mir::Projection {
ref base,
elem: mir::ProjectionElem::Deref
}) => {
// Load the pointer from its location.
- self.trans_consume(bcx, base).deref(bcx.ccx)
+ self.trans_consume(bx, base).deref(bx.cx)
}
mir::Place::Projection(ref projection) => {
- let tr_base = self.trans_place(bcx, &projection.base);
+ let tr_base = self.trans_place(bx, &projection.base);
match projection.elem {
mir::ProjectionElem::Deref => bug!(),
mir::ProjectionElem::Field(ref field, _) => {
- tr_base.project_field(bcx, field.index())
+ tr_base.project_field(bx, field.index())
}
mir::ProjectionElem::Index(index) => {
let index = &mir::Operand::Copy(mir::Place::Local(index));
- let index = self.trans_operand(bcx, index);
+ let index = self.trans_operand(bx, index);
let llindex = index.immediate();
- tr_base.project_index(bcx, llindex)
+ tr_base.project_index(bx, llindex)
}
mir::ProjectionElem::ConstantIndex { offset,
from_end: false,
min_length: _ } => {
- let lloffset = C_usize(bcx.ccx, offset as u64);
- tr_base.project_index(bcx, lloffset)
+ let lloffset = C_usize(bx.cx, offset as u64);
+ tr_base.project_index(bx, lloffset)
}
mir::ProjectionElem::ConstantIndex { offset,
from_end: true,
min_length: _ } => {
- let lloffset = C_usize(bcx.ccx, offset as u64);
- let lllen = tr_base.len(bcx.ccx);
- let llindex = bcx.sub(lllen, lloffset);
- tr_base.project_index(bcx, llindex)
+ let lloffset = C_usize(bx.cx, offset as u64);
+ let lllen = tr_base.len(bx.cx);
+ let llindex = bx.sub(lllen, lloffset);
+ tr_base.project_index(bx, llindex)
}
mir::ProjectionElem::Subslice { from, to } => {
- let mut subslice = tr_base.project_index(bcx,
- C_usize(bcx.ccx, from as u64));
+ let mut subslice = tr_base.project_index(bx,
+ C_usize(bx.cx, from as u64));
let projected_ty = PlaceTy::Ty { ty: tr_base.layout.ty }
- .projection_ty(tcx, &projection.elem).to_ty(bcx.tcx());
- subslice.layout = bcx.ccx.layout_of(self.monomorphize(&projected_ty));
+ .projection_ty(tcx, &projection.elem).to_ty(bx.tcx());
+ subslice.layout = bx.cx.layout_of(self.monomorphize(&projected_ty));
if subslice.layout.is_unsized() {
assert!(tr_base.has_extra());
- subslice.llextra = bcx.sub(tr_base.llextra,
- C_usize(bcx.ccx, (from as u64) + (to as u64)));
+ subslice.llextra = bx.sub(tr_base.llextra,
+ C_usize(bx.cx, (from as u64) + (to as u64)));
}
// Cast the place pointer type to the new
// array or slice type (*[%_; new_len]).
- subslice.llval = bcx.pointercast(subslice.llval,
- subslice.layout.llvm_type(bcx.ccx).ptr_to());
+ subslice.llval = bx.pointercast(subslice.llval,
+ subslice.layout.llvm_type(bx.cx).ptr_to());
subslice
}
mir::ProjectionElem::Downcast(_, v) => {
- tr_base.project_downcast(bcx, v)
+ tr_base.project_downcast(bx, v)
}
}
}
}
pub fn monomorphized_place_ty(&self, place: &mir::Place<'tcx>) -> Ty<'tcx> {
- let tcx = self.ccx.tcx();
+ let tcx = self.cx.tcx;
let place_ty = place.ty(self.mir, tcx);
self.monomorphize(&place_ty.to_ty(tcx))
}
use type_of::LayoutLlvmExt;
use value::Value;
-use super::{MirContext, LocalRef};
+use super::{FunctionCx, LocalRef};
use super::constant::const_scalar_checked_binop;
use super::operand::{OperandRef, OperandValue};
use super::place::PlaceRef;
-impl<'a, 'tcx> MirContext<'a, 'tcx> {
+impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
pub fn trans_rvalue(&mut self,
- bcx: Builder<'a, 'tcx>,
+ bx: Builder<'a, 'tcx>,
dest: PlaceRef<'tcx>,
rvalue: &mir::Rvalue<'tcx>)
-> Builder<'a, 'tcx>
match *rvalue {
mir::Rvalue::Use(ref operand) => {
- let tr_operand = self.trans_operand(&bcx, operand);
+ let tr_operand = self.trans_operand(&bx, operand);
// FIXME: consider not copying constants through stack. (fixable by translating
// constants into OperandValue::Ref, why don’t we do that yet if we don’t?)
- tr_operand.val.store(&bcx, dest);
- bcx
+ tr_operand.val.store(&bx, dest);
+ bx
}
mir::Rvalue::Cast(mir::CastKind::Unsize, ref source, _) => {
if dest.layout.is_llvm_scalar_pair() {
// into-coerce of a thin pointer to a fat pointer - just
// use the operand path.
- let (bcx, temp) = self.trans_rvalue_operand(bcx, rvalue);
- temp.val.store(&bcx, dest);
- return bcx;
+ let (bx, temp) = self.trans_rvalue_operand(bx, rvalue);
+ temp.val.store(&bx, dest);
+ return bx;
}
// Unsize of a nontrivial struct. I would prefer for
// this to be eliminated by MIR translation, but
// `CoerceUnsized` can be passed by a where-clause,
// so the (generic) MIR may not be able to expand it.
- let operand = self.trans_operand(&bcx, source);
+ let operand = self.trans_operand(&bx, source);
match operand.val {
OperandValue::Pair(..) |
OperandValue::Immediate(_) => {
// index into the struct, and this case isn't
// important enough for it.
debug!("trans_rvalue: creating ugly alloca");
- let scratch = PlaceRef::alloca(&bcx, operand.layout, "__unsize_temp");
- scratch.storage_live(&bcx);
- operand.val.store(&bcx, scratch);
- base::coerce_unsized_into(&bcx, scratch, dest);
- scratch.storage_dead(&bcx);
+ let scratch = PlaceRef::alloca(&bx, operand.layout, "__unsize_temp");
+ scratch.storage_live(&bx);
+ operand.val.store(&bx, scratch);
+ base::coerce_unsized_into(&bx, scratch, dest);
+ scratch.storage_dead(&bx);
}
OperandValue::Ref(llref, align) => {
let source = PlaceRef::new_sized(llref, operand.layout, align);
- base::coerce_unsized_into(&bcx, source, dest);
+ base::coerce_unsized_into(&bx, source, dest);
}
}
- bcx
+ bx
}
mir::Rvalue::Repeat(ref elem, count) => {
- let tr_elem = self.trans_operand(&bcx, elem);
+ let tr_elem = self.trans_operand(&bx, elem);
// Do not generate the loop for zero-sized elements or empty arrays.
if dest.layout.is_zst() {
- return bcx;
+ return bx;
}
- let start = dest.project_index(&bcx, C_usize(bcx.ccx, 0)).llval;
+ let start = dest.project_index(&bx, C_usize(bx.cx, 0)).llval;
if let OperandValue::Immediate(v) = tr_elem.val {
- let align = C_i32(bcx.ccx, dest.align.abi() as i32);
- let size = C_usize(bcx.ccx, dest.layout.size.bytes());
+ let align = C_i32(bx.cx, dest.align.abi() as i32);
+ let size = C_usize(bx.cx, dest.layout.size.bytes());
// Use llvm.memset.p0i8.* to initialize all zero arrays
if common::is_const_integral(v) && common::const_to_uint(v) == 0 {
- let fill = C_u8(bcx.ccx, 0);
- base::call_memset(&bcx, start, fill, size, align, false);
- return bcx;
+ let fill = C_u8(bx.cx, 0);
+ base::call_memset(&bx, start, fill, size, align, false);
+ return bx;
}
// Use llvm.memset.p0i8.* to initialize byte arrays
- let v = base::from_immediate(&bcx, v);
- if common::val_ty(v) == Type::i8(bcx.ccx) {
- base::call_memset(&bcx, start, v, size, align, false);
- return bcx;
+ let v = base::from_immediate(&bx, v);
+ if common::val_ty(v) == Type::i8(bx.cx) {
+ base::call_memset(&bx, start, v, size, align, false);
+ return bx;
}
}
let count = count.as_u64();
- let count = C_usize(bcx.ccx, count);
- let end = dest.project_index(&bcx, count).llval;
+ let count = C_usize(bx.cx, count);
+ let end = dest.project_index(&bx, count).llval;
- let header_bcx = bcx.build_sibling_block("repeat_loop_header");
- let body_bcx = bcx.build_sibling_block("repeat_loop_body");
- let next_bcx = bcx.build_sibling_block("repeat_loop_next");
+ let header_bx = bx.build_sibling_block("repeat_loop_header");
+ let body_bx = bx.build_sibling_block("repeat_loop_body");
+ let next_bx = bx.build_sibling_block("repeat_loop_next");
- bcx.br(header_bcx.llbb());
- let current = header_bcx.phi(common::val_ty(start), &[start], &[bcx.llbb()]);
+ bx.br(header_bx.llbb());
+ let current = header_bx.phi(common::val_ty(start), &[start], &[bx.llbb()]);
- let keep_going = header_bcx.icmp(llvm::IntNE, current, end);
- header_bcx.cond_br(keep_going, body_bcx.llbb(), next_bcx.llbb());
+ let keep_going = header_bx.icmp(llvm::IntNE, current, end);
+ header_bx.cond_br(keep_going, body_bx.llbb(), next_bx.llbb());
- tr_elem.val.store(&body_bcx,
+ tr_elem.val.store(&body_bx,
PlaceRef::new_sized(current, tr_elem.layout, dest.align));
- let next = body_bcx.inbounds_gep(current, &[C_usize(bcx.ccx, 1)]);
- body_bcx.br(header_bcx.llbb());
- header_bcx.add_incoming_to_phi(current, next, body_bcx.llbb());
+ let next = body_bx.inbounds_gep(current, &[C_usize(bx.cx, 1)]);
+ body_bx.br(header_bx.llbb());
+ header_bx.add_incoming_to_phi(current, next, body_bx.llbb());
- next_bcx
+ next_bx
}
mir::Rvalue::Aggregate(ref kind, ref operands) => {
let (dest, active_field_index) = match **kind {
mir::AggregateKind::Adt(adt_def, variant_index, _, active_field_index) => {
- dest.trans_set_discr(&bcx, variant_index);
+ dest.trans_set_discr(&bx, variant_index);
if adt_def.is_enum() {
- (dest.project_downcast(&bcx, variant_index), active_field_index)
+ (dest.project_downcast(&bx, variant_index), active_field_index)
} else {
(dest, active_field_index)
}
_ => (dest, None)
};
for (i, operand) in operands.iter().enumerate() {
- let op = self.trans_operand(&bcx, operand);
+ let op = self.trans_operand(&bx, operand);
// Do not generate stores and GEPis for zero-sized fields.
if !op.layout.is_zst() {
let field_index = active_field_index.unwrap_or(i);
- op.val.store(&bcx, dest.project_field(&bcx, field_index));
+ op.val.store(&bx, dest.project_field(&bx, field_index));
}
}
- bcx
+ bx
}
_ => {
assert!(self.rvalue_creates_operand(rvalue));
- let (bcx, temp) = self.trans_rvalue_operand(bcx, rvalue);
- temp.val.store(&bcx, dest);
- bcx
+ let (bx, temp) = self.trans_rvalue_operand(bx, rvalue);
+ temp.val.store(&bx, dest);
+ bx
}
}
}
pub fn trans_rvalue_operand(&mut self,
- bcx: Builder<'a, 'tcx>,
+ bx: Builder<'a, 'tcx>,
rvalue: &mir::Rvalue<'tcx>)
-> (Builder<'a, 'tcx>, OperandRef<'tcx>)
{
match *rvalue {
mir::Rvalue::Cast(ref kind, ref source, mir_cast_ty) => {
- let operand = self.trans_operand(&bcx, source);
+ let operand = self.trans_operand(&bx, source);
debug!("cast operand is {:?}", operand);
- let cast = bcx.ccx.layout_of(self.monomorphize(&mir_cast_ty));
+ let cast = bx.cx.layout_of(self.monomorphize(&mir_cast_ty));
let val = match *kind {
mir::CastKind::ReifyFnPointer => {
match operand.layout.ty.sty {
ty::TyFnDef(def_id, substs) => {
OperandValue::Immediate(
- callee::resolve_and_get_fn(bcx.ccx, def_id, substs))
+ callee::resolve_and_get_fn(bx.cx, def_id, substs))
}
_ => {
bug!("{} cannot be reified to a fn ptr", operand.layout.ty)
match operand.layout.ty.sty {
ty::TyClosure(def_id, substs) => {
let instance = monomorphize::resolve_closure(
- bcx.ccx.tcx(), def_id, substs, ty::ClosureKind::FnOnce);
- OperandValue::Immediate(callee::get_fn(bcx.ccx, instance))
+ bx.cx.tcx, def_id, substs, ty::ClosureKind::FnOnce);
+ OperandValue::Immediate(callee::get_fn(bx.cx, instance))
}
_ => {
bug!("{} cannot be cast to a fn ptr", operand.layout.ty)
// HACK(eddyb) have to bitcast pointers
// until LLVM removes pointee types.
- let lldata = bcx.pointercast(lldata,
- cast.scalar_pair_element_llvm_type(bcx.ccx, 0));
+ let lldata = bx.pointercast(lldata,
+ cast.scalar_pair_element_llvm_type(bx.cx, 0));
OperandValue::Pair(lldata, llextra)
}
OperandValue::Immediate(lldata) => {
// "standard" unsize
- let (lldata, llextra) = base::unsize_thin_ptr(&bcx, lldata,
+ let (lldata, llextra) = base::unsize_thin_ptr(&bx, lldata,
operand.layout.ty, cast.ty);
OperandValue::Pair(lldata, llextra)
}
mir::CastKind::Misc if operand.layout.is_llvm_scalar_pair() => {
if let OperandValue::Pair(data_ptr, meta) = operand.val {
if cast.is_llvm_scalar_pair() {
- let data_cast = bcx.pointercast(data_ptr,
- cast.scalar_pair_element_llvm_type(bcx.ccx, 0));
+ let data_cast = bx.pointercast(data_ptr,
+ cast.scalar_pair_element_llvm_type(bx.cx, 0));
OperandValue::Pair(data_cast, meta)
} else { // cast to thin-ptr
// Cast of fat-ptr to thin-ptr is an extraction of data-ptr and
// pointer-cast of that pointer to desired pointer type.
- let llcast_ty = cast.immediate_llvm_type(bcx.ccx);
- let llval = bcx.pointercast(data_ptr, llcast_ty);
+ let llcast_ty = cast.immediate_llvm_type(bx.cx);
+ let llval = bx.pointercast(data_ptr, llcast_ty);
OperandValue::Immediate(llval)
}
} else {
let r_t_in = CastTy::from_ty(operand.layout.ty)
.expect("bad input type for cast");
let r_t_out = CastTy::from_ty(cast.ty).expect("bad output type for cast");
- let ll_t_in = operand.layout.immediate_llvm_type(bcx.ccx);
- let ll_t_out = cast.immediate_llvm_type(bcx.ccx);
+ let ll_t_in = operand.layout.immediate_llvm_type(bx.cx);
+ let ll_t_out = cast.immediate_llvm_type(bx.cx);
let llval = operand.immediate();
let mut signed = false;
// have bound checks, and this is the most
// convenient place to put the `assume`.
- base::call_assume(&bcx, bcx.icmp(
+ base::call_assume(&bx, bx.icmp(
llvm::IntULE,
llval,
C_uint_big(ll_t_in, scalar.valid_range.end)
let newval = match (r_t_in, r_t_out) {
(CastTy::Int(_), CastTy::Int(_)) => {
- bcx.intcast(llval, ll_t_out, signed)
+ bx.intcast(llval, ll_t_out, signed)
}
(CastTy::Float, CastTy::Float) => {
let srcsz = ll_t_in.float_width();
let dstsz = ll_t_out.float_width();
if dstsz > srcsz {
- bcx.fpext(llval, ll_t_out)
+ bx.fpext(llval, ll_t_out)
} else if srcsz > dstsz {
- bcx.fptrunc(llval, ll_t_out)
+ bx.fptrunc(llval, ll_t_out)
} else {
llval
}
(CastTy::Ptr(_), CastTy::Ptr(_)) |
(CastTy::FnPtr, CastTy::Ptr(_)) |
(CastTy::RPtr(_), CastTy::Ptr(_)) =>
- bcx.pointercast(llval, ll_t_out),
+ bx.pointercast(llval, ll_t_out),
(CastTy::Ptr(_), CastTy::Int(_)) |
(CastTy::FnPtr, CastTy::Int(_)) =>
- bcx.ptrtoint(llval, ll_t_out),
+ bx.ptrtoint(llval, ll_t_out),
(CastTy::Int(_), CastTy::Ptr(_)) => {
- let usize_llval = bcx.intcast(llval, bcx.ccx.isize_ty(), signed);
- bcx.inttoptr(usize_llval, ll_t_out)
+ let usize_llval = bx.intcast(llval, bx.cx.isize_ty, signed);
+ bx.inttoptr(usize_llval, ll_t_out)
}
(CastTy::Int(_), CastTy::Float) =>
- cast_int_to_float(&bcx, signed, llval, ll_t_in, ll_t_out),
+ cast_int_to_float(&bx, signed, llval, ll_t_in, ll_t_out),
(CastTy::Float, CastTy::Int(IntTy::I)) =>
- cast_float_to_int(&bcx, true, llval, ll_t_in, ll_t_out),
+ cast_float_to_int(&bx, true, llval, ll_t_in, ll_t_out),
(CastTy::Float, CastTy::Int(_)) =>
- cast_float_to_int(&bcx, false, llval, ll_t_in, ll_t_out),
+ cast_float_to_int(&bx, false, llval, ll_t_in, ll_t_out),
_ => bug!("unsupported cast: {:?} to {:?}", operand.layout.ty, cast.ty)
};
OperandValue::Immediate(newval)
}
};
- (bcx, OperandRef {
+ (bx, OperandRef {
val,
layout: cast
})
}
mir::Rvalue::Ref(_, bk, ref place) => {
- let tr_place = self.trans_place(&bcx, place);
+ let tr_place = self.trans_place(&bx, place);
let ty = tr_place.layout.ty;
// Note: places are indirect, so storing the `llval` into the
// destination effectively creates a reference.
- let val = if !bcx.ccx.shared().type_has_metadata(ty) {
+ let val = if !bx.cx.type_has_metadata(ty) {
OperandValue::Immediate(tr_place.llval)
} else {
OperandValue::Pair(tr_place.llval, tr_place.llextra)
};
- (bcx, OperandRef {
+ (bx, OperandRef {
val,
- layout: self.ccx.layout_of(self.ccx.tcx().mk_ref(
- self.ccx.tcx().types.re_erased,
+ layout: self.cx.layout_of(self.cx.tcx.mk_ref(
+ self.cx.tcx.types.re_erased,
ty::TypeAndMut { ty, mutbl: bk.to_mutbl_lossy() }
)),
})
}
mir::Rvalue::Len(ref place) => {
- let size = self.evaluate_array_len(&bcx, place);
+ let size = self.evaluate_array_len(&bx, place);
let operand = OperandRef {
val: OperandValue::Immediate(size),
- layout: bcx.ccx.layout_of(bcx.tcx().types.usize),
+ layout: bx.cx.layout_of(bx.tcx().types.usize),
};
- (bcx, operand)
+ (bx, operand)
}
mir::Rvalue::BinaryOp(op, ref lhs, ref rhs) => {
- let lhs = self.trans_operand(&bcx, lhs);
- let rhs = self.trans_operand(&bcx, rhs);
+ let lhs = self.trans_operand(&bx, lhs);
+ let rhs = self.trans_operand(&bx, rhs);
let llresult = match (lhs.val, rhs.val) {
(OperandValue::Pair(lhs_addr, lhs_extra),
OperandValue::Pair(rhs_addr, rhs_extra)) => {
- self.trans_fat_ptr_binop(&bcx, op,
+ self.trans_fat_ptr_binop(&bx, op,
lhs_addr, lhs_extra,
rhs_addr, rhs_extra,
lhs.layout.ty)
(OperandValue::Immediate(lhs_val),
OperandValue::Immediate(rhs_val)) => {
- self.trans_scalar_binop(&bcx, op, lhs_val, rhs_val, lhs.layout.ty)
+ self.trans_scalar_binop(&bx, op, lhs_val, rhs_val, lhs.layout.ty)
}
_ => bug!()
};
let operand = OperandRef {
val: OperandValue::Immediate(llresult),
- layout: bcx.ccx.layout_of(
- op.ty(bcx.tcx(), lhs.layout.ty, rhs.layout.ty)),
+ layout: bx.cx.layout_of(
+ op.ty(bx.tcx(), lhs.layout.ty, rhs.layout.ty)),
};
- (bcx, operand)
+ (bx, operand)
}
mir::Rvalue::CheckedBinaryOp(op, ref lhs, ref rhs) => {
- let lhs = self.trans_operand(&bcx, lhs);
- let rhs = self.trans_operand(&bcx, rhs);
- let result = self.trans_scalar_checked_binop(&bcx, op,
+ let lhs = self.trans_operand(&bx, lhs);
+ let rhs = self.trans_operand(&bx, rhs);
+ let result = self.trans_scalar_checked_binop(&bx, op,
lhs.immediate(), rhs.immediate(),
lhs.layout.ty);
- let val_ty = op.ty(bcx.tcx(), lhs.layout.ty, rhs.layout.ty);
- let operand_ty = bcx.tcx().intern_tup(&[val_ty, bcx.tcx().types.bool], false);
+ let val_ty = op.ty(bx.tcx(), lhs.layout.ty, rhs.layout.ty);
+ let operand_ty = bx.tcx().intern_tup(&[val_ty, bx.tcx().types.bool], false);
let operand = OperandRef {
val: result,
- layout: bcx.ccx.layout_of(operand_ty)
+ layout: bx.cx.layout_of(operand_ty)
};
- (bcx, operand)
+ (bx, operand)
}
mir::Rvalue::UnaryOp(op, ref operand) => {
- let operand = self.trans_operand(&bcx, operand);
+ let operand = self.trans_operand(&bx, operand);
let lloperand = operand.immediate();
let is_float = operand.layout.ty.is_fp();
let llval = match op {
- mir::UnOp::Not => bcx.not(lloperand),
+ mir::UnOp::Not => bx.not(lloperand),
mir::UnOp::Neg => if is_float {
- bcx.fneg(lloperand)
+ bx.fneg(lloperand)
} else {
- bcx.neg(lloperand)
+ bx.neg(lloperand)
}
};
- (bcx, OperandRef {
+ (bx, OperandRef {
val: OperandValue::Immediate(llval),
layout: operand.layout,
})
}
mir::Rvalue::Discriminant(ref place) => {
- let discr_ty = rvalue.ty(&*self.mir, bcx.tcx());
- let discr = self.trans_place(&bcx, place)
- .trans_get_discr(&bcx, discr_ty);
- (bcx, OperandRef {
+ let discr_ty = rvalue.ty(&*self.mir, bx.tcx());
+ let discr = self.trans_place(&bx, place)
+ .trans_get_discr(&bx, discr_ty);
+ (bx, OperandRef {
val: OperandValue::Immediate(discr),
- layout: self.ccx.layout_of(discr_ty)
+ layout: self.cx.layout_of(discr_ty)
})
}
mir::Rvalue::NullaryOp(mir::NullOp::SizeOf, ty) => {
- assert!(bcx.ccx.shared().type_is_sized(ty));
- let val = C_usize(bcx.ccx, bcx.ccx.size_of(ty).bytes());
- let tcx = bcx.tcx();
- (bcx, OperandRef {
+ assert!(bx.cx.type_is_sized(ty));
+ let val = C_usize(bx.cx, bx.cx.size_of(ty).bytes());
+ let tcx = bx.tcx();
+ (bx, OperandRef {
val: OperandValue::Immediate(val),
- layout: self.ccx.layout_of(tcx.types.usize),
+ layout: self.cx.layout_of(tcx.types.usize),
})
}
mir::Rvalue::NullaryOp(mir::NullOp::Box, content_ty) => {
let content_ty: Ty<'tcx> = self.monomorphize(&content_ty);
- let (size, align) = bcx.ccx.size_and_align_of(content_ty);
- let llsize = C_usize(bcx.ccx, size.bytes());
- let llalign = C_usize(bcx.ccx, align.abi());
- let box_layout = bcx.ccx.layout_of(bcx.tcx().mk_box(content_ty));
- let llty_ptr = box_layout.llvm_type(bcx.ccx);
+ let (size, align) = bx.cx.size_and_align_of(content_ty);
+ let llsize = C_usize(bx.cx, size.bytes());
+ let llalign = C_usize(bx.cx, align.abi());
+ let box_layout = bx.cx.layout_of(bx.tcx().mk_box(content_ty));
+ let llty_ptr = box_layout.llvm_type(bx.cx);
// Allocate space:
- let def_id = match bcx.tcx().lang_items().require(ExchangeMallocFnLangItem) {
+ let def_id = match bx.tcx().lang_items().require(ExchangeMallocFnLangItem) {
Ok(id) => id,
Err(s) => {
- bcx.sess().fatal(&format!("allocation of `{}` {}", box_layout.ty, s));
+ bx.sess().fatal(&format!("allocation of `{}` {}", box_layout.ty, s));
}
};
- let instance = ty::Instance::mono(bcx.tcx(), def_id);
- let r = callee::get_fn(bcx.ccx, instance);
- let val = bcx.pointercast(bcx.call(r, &[llsize, llalign], None), llty_ptr);
+ let instance = ty::Instance::mono(bx.tcx(), def_id);
+ let r = callee::get_fn(bx.cx, instance);
+ let val = bx.pointercast(bx.call(r, &[llsize, llalign], None), llty_ptr);
let operand = OperandRef {
val: OperandValue::Immediate(val),
layout: box_layout,
};
- (bcx, operand)
+ (bx, operand)
}
mir::Rvalue::Use(ref operand) => {
- let operand = self.trans_operand(&bcx, operand);
- (bcx, operand)
+ let operand = self.trans_operand(&bx, operand);
+ (bx, operand)
}
mir::Rvalue::Repeat(..) |
mir::Rvalue::Aggregate(..) => {
// According to `rvalue_creates_operand`, only ZST
// aggregate rvalues are allowed to be operands.
- let ty = rvalue.ty(self.mir, self.ccx.tcx());
- (bcx, OperandRef::new_zst(self.ccx,
- self.ccx.layout_of(self.monomorphize(&ty))))
+ let ty = rvalue.ty(self.mir, self.cx.tcx);
+ (bx, OperandRef::new_zst(self.cx,
+ self.cx.layout_of(self.monomorphize(&ty))))
}
}
}
fn evaluate_array_len(&mut self,
- bcx: &Builder<'a, 'tcx>,
+ bx: &Builder<'a, 'tcx>,
place: &mir::Place<'tcx>) -> ValueRef
{
// ZST are passed as operands and require special handling
if let LocalRef::Operand(Some(op)) = self.locals[index] {
if let ty::TyArray(_, n) = op.layout.ty.sty {
let n = n.val.to_const_int().unwrap().to_u64().unwrap();
- return common::C_usize(bcx.ccx, n);
+ return common::C_usize(bx.cx, n);
}
}
}
// use common size calculation for non zero-sized types
- let tr_value = self.trans_place(&bcx, place);
- return tr_value.len(bcx.ccx);
+ let tr_value = self.trans_place(&bx, place);
+ return tr_value.len(bx.cx);
}
pub fn trans_scalar_binop(&mut self,
- bcx: &Builder<'a, 'tcx>,
+ bx: &Builder<'a, 'tcx>,
op: mir::BinOp,
lhs: ValueRef,
rhs: ValueRef,
let is_bool = input_ty.is_bool();
match op {
mir::BinOp::Add => if is_float {
- bcx.fadd(lhs, rhs)
+ bx.fadd(lhs, rhs)
} else {
- bcx.add(lhs, rhs)
+ bx.add(lhs, rhs)
},
mir::BinOp::Sub => if is_float {
- bcx.fsub(lhs, rhs)
+ bx.fsub(lhs, rhs)
} else {
- bcx.sub(lhs, rhs)
+ bx.sub(lhs, rhs)
},
mir::BinOp::Mul => if is_float {
- bcx.fmul(lhs, rhs)
+ bx.fmul(lhs, rhs)
} else {
- bcx.mul(lhs, rhs)
+ bx.mul(lhs, rhs)
},
mir::BinOp::Div => if is_float {
- bcx.fdiv(lhs, rhs)
+ bx.fdiv(lhs, rhs)
} else if is_signed {
- bcx.sdiv(lhs, rhs)
+ bx.sdiv(lhs, rhs)
} else {
- bcx.udiv(lhs, rhs)
+ bx.udiv(lhs, rhs)
},
mir::BinOp::Rem => if is_float {
- bcx.frem(lhs, rhs)
+ bx.frem(lhs, rhs)
} else if is_signed {
- bcx.srem(lhs, rhs)
+ bx.srem(lhs, rhs)
} else {
- bcx.urem(lhs, rhs)
+ bx.urem(lhs, rhs)
},
- mir::BinOp::BitOr => bcx.or(lhs, rhs),
- mir::BinOp::BitAnd => bcx.and(lhs, rhs),
- mir::BinOp::BitXor => bcx.xor(lhs, rhs),
- mir::BinOp::Offset => bcx.inbounds_gep(lhs, &[rhs]),
- mir::BinOp::Shl => common::build_unchecked_lshift(bcx, lhs, rhs),
- mir::BinOp::Shr => common::build_unchecked_rshift(bcx, input_ty, lhs, rhs),
+ mir::BinOp::BitOr => bx.or(lhs, rhs),
+ mir::BinOp::BitAnd => bx.and(lhs, rhs),
+ mir::BinOp::BitXor => bx.xor(lhs, rhs),
+ mir::BinOp::Offset => bx.inbounds_gep(lhs, &[rhs]),
+ mir::BinOp::Shl => common::build_unchecked_lshift(bx, lhs, rhs),
+ mir::BinOp::Shr => common::build_unchecked_rshift(bx, input_ty, lhs, rhs),
mir::BinOp::Ne | mir::BinOp::Lt | mir::BinOp::Gt |
mir::BinOp::Eq | mir::BinOp::Le | mir::BinOp::Ge => if is_nil {
- C_bool(bcx.ccx, match op {
+ C_bool(bx.cx, match op {
mir::BinOp::Ne | mir::BinOp::Lt | mir::BinOp::Gt => false,
mir::BinOp::Eq | mir::BinOp::Le | mir::BinOp::Ge => true,
_ => unreachable!()
})
} else if is_float {
- bcx.fcmp(
+ bx.fcmp(
base::bin_op_to_fcmp_predicate(op.to_hir_binop()),
lhs, rhs
)
let (lhs, rhs) = if is_bool {
// FIXME(#36856) -- extend the bools into `i8` because
// LLVM's i1 comparisons are broken.
- (bcx.zext(lhs, Type::i8(bcx.ccx)),
- bcx.zext(rhs, Type::i8(bcx.ccx)))
+ (bx.zext(lhs, Type::i8(bx.cx)),
+ bx.zext(rhs, Type::i8(bx.cx)))
} else {
(lhs, rhs)
};
- bcx.icmp(
+ bx.icmp(
base::bin_op_to_icmp_predicate(op.to_hir_binop(), is_signed),
lhs, rhs
)
}
pub fn trans_fat_ptr_binop(&mut self,
- bcx: &Builder<'a, 'tcx>,
+ bx: &Builder<'a, 'tcx>,
op: mir::BinOp,
lhs_addr: ValueRef,
lhs_extra: ValueRef,
-> ValueRef {
match op {
mir::BinOp::Eq => {
- bcx.and(
- bcx.icmp(llvm::IntEQ, lhs_addr, rhs_addr),
- bcx.icmp(llvm::IntEQ, lhs_extra, rhs_extra)
+ bx.and(
+ bx.icmp(llvm::IntEQ, lhs_addr, rhs_addr),
+ bx.icmp(llvm::IntEQ, lhs_extra, rhs_extra)
)
}
mir::BinOp::Ne => {
- bcx.or(
- bcx.icmp(llvm::IntNE, lhs_addr, rhs_addr),
- bcx.icmp(llvm::IntNE, lhs_extra, rhs_extra)
+ bx.or(
+ bx.icmp(llvm::IntNE, lhs_addr, rhs_addr),
+ bx.icmp(llvm::IntNE, lhs_extra, rhs_extra)
)
}
mir::BinOp::Le | mir::BinOp::Lt |
_ => bug!(),
};
- bcx.or(
- bcx.icmp(strict_op, lhs_addr, rhs_addr),
- bcx.and(
- bcx.icmp(llvm::IntEQ, lhs_addr, rhs_addr),
- bcx.icmp(op, lhs_extra, rhs_extra)
+ bx.or(
+ bx.icmp(strict_op, lhs_addr, rhs_addr),
+ bx.and(
+ bx.icmp(llvm::IntEQ, lhs_addr, rhs_addr),
+ bx.icmp(op, lhs_extra, rhs_extra)
)
)
}
}
pub fn trans_scalar_checked_binop(&mut self,
- bcx: &Builder<'a, 'tcx>,
+ bx: &Builder<'a, 'tcx>,
op: mir::BinOp,
lhs: ValueRef,
rhs: ValueRef,
// with #[rustc_inherit_overflow_checks] and inlined from
// another crate (mostly core::num generic/#[inline] fns),
// while the current crate doesn't use overflow checks.
- if !bcx.ccx.check_overflow() {
- let val = self.trans_scalar_binop(bcx, op, lhs, rhs, input_ty);
- return OperandValue::Pair(val, C_bool(bcx.ccx, false));
+ if !bx.cx.check_overflow {
+ let val = self.trans_scalar_binop(bx, op, lhs, rhs, input_ty);
+ return OperandValue::Pair(val, C_bool(bx.cx, false));
}
// First try performing the operation on constants, which
// will only succeed if both operands are constant.
// This is necessary to determine when an overflow Assert
// will always panic at runtime, and produce a warning.
- if let Some((val, of)) = const_scalar_checked_binop(bcx.tcx(), op, lhs, rhs, input_ty) {
- return OperandValue::Pair(val, C_bool(bcx.ccx, of));
+ if let Some((val, of)) = const_scalar_checked_binop(bx.tcx(), op, lhs, rhs, input_ty) {
+ return OperandValue::Pair(val, C_bool(bx.cx, of));
}
let (val, of) = match op {
mir::BinOp::Mul => OverflowOp::Mul,
_ => unreachable!()
};
- let intrinsic = get_overflow_intrinsic(oop, bcx, input_ty);
- let res = bcx.call(intrinsic, &[lhs, rhs], None);
+ let intrinsic = get_overflow_intrinsic(oop, bx, input_ty);
+ let res = bx.call(intrinsic, &[lhs, rhs], None);
- (bcx.extract_value(res, 0),
- bcx.extract_value(res, 1))
+ (bx.extract_value(res, 0),
+ bx.extract_value(res, 1))
}
mir::BinOp::Shl | mir::BinOp::Shr => {
let lhs_llty = val_ty(lhs);
let rhs_llty = val_ty(rhs);
- let invert_mask = common::shift_mask_val(&bcx, lhs_llty, rhs_llty, true);
- let outer_bits = bcx.and(rhs, invert_mask);
+ let invert_mask = common::shift_mask_val(&bx, lhs_llty, rhs_llty, true);
+ let outer_bits = bx.and(rhs, invert_mask);
- let of = bcx.icmp(llvm::IntNE, outer_bits, C_null(rhs_llty));
- let val = self.trans_scalar_binop(bcx, op, lhs, rhs, input_ty);
+ let of = bx.icmp(llvm::IntNE, outer_bits, C_null(rhs_llty));
+ let val = self.trans_scalar_binop(bx, op, lhs, rhs, input_ty);
(val, of)
}
true,
mir::Rvalue::Repeat(..) |
mir::Rvalue::Aggregate(..) => {
- let ty = rvalue.ty(self.mir, self.ccx.tcx());
+ let ty = rvalue.ty(self.mir, self.cx.tcx);
let ty = self.monomorphize(&ty);
- self.ccx.layout_of(ty).is_zst()
+ self.cx.layout_of(ty).is_zst()
}
}
Add, Sub, Mul
}
-fn get_overflow_intrinsic(oop: OverflowOp, bcx: &Builder, ty: Ty) -> ValueRef {
+fn get_overflow_intrinsic(oop: OverflowOp, bx: &Builder, ty: Ty) -> ValueRef {
use syntax::ast::IntTy::*;
use syntax::ast::UintTy::*;
use rustc::ty::{TyInt, TyUint};
- let tcx = bcx.tcx();
+ let tcx = bx.tcx();
let new_sty = match ty.sty {
- TyInt(Is) => match &tcx.sess.target.target.target_pointer_width[..] {
+ TyInt(Isize) => match &tcx.sess.target.target.target_pointer_width[..] {
"16" => TyInt(I16),
"32" => TyInt(I32),
"64" => TyInt(I64),
_ => panic!("unsupported target word size")
},
- TyUint(Us) => match &tcx.sess.target.target.target_pointer_width[..] {
+ TyUint(Usize) => match &tcx.sess.target.target.target_pointer_width[..] {
"16" => TyUint(U16),
"32" => TyUint(U32),
"64" => TyUint(U64),
},
};
- bcx.ccx.get_intrinsic(&name)
+ bx.cx.get_intrinsic(&name)
}
-fn cast_int_to_float(bcx: &Builder,
+fn cast_int_to_float(bx: &Builder,
signed: bool,
x: ValueRef,
int_ty: Type,
// All inputs greater or equal to (f32::MAX + 0.5 ULP) are rounded to infinity,
// and for everything else LLVM's uitofp works just fine.
let max = C_uint_big(int_ty, MAX_F32_PLUS_HALF_ULP);
- let overflow = bcx.icmp(llvm::IntUGE, x, max);
- let infinity_bits = C_u32(bcx.ccx, ieee::Single::INFINITY.to_bits() as u32);
+ let overflow = bx.icmp(llvm::IntUGE, x, max);
+ let infinity_bits = C_u32(bx.cx, ieee::Single::INFINITY.to_bits() as u32);
let infinity = consts::bitcast(infinity_bits, float_ty);
- bcx.select(overflow, infinity, bcx.uitofp(x, float_ty))
+ bx.select(overflow, infinity, bx.uitofp(x, float_ty))
} else {
if signed {
- bcx.sitofp(x, float_ty)
+ bx.sitofp(x, float_ty)
} else {
- bcx.uitofp(x, float_ty)
+ bx.uitofp(x, float_ty)
}
}
}
-fn cast_float_to_int(bcx: &Builder,
+fn cast_float_to_int(bx: &Builder,
signed: bool,
x: ValueRef,
float_ty: Type,
int_ty: Type) -> ValueRef {
let fptosui_result = if signed {
- bcx.fptosi(x, int_ty)
+ bx.fptosi(x, int_ty)
} else {
- bcx.fptoui(x, int_ty)
+ bx.fptoui(x, int_ty)
};
- if !bcx.sess().opts.debugging_opts.saturating_float_casts {
+ if !bx.sess().opts.debugging_opts.saturating_float_casts {
return fptosui_result;
}
// LLVM's fpto[su]i returns undef when the input x is infinite, NaN, or does not fit into the
}
let float_bits_to_llval = |bits| {
let bits_llval = match float_ty.float_width() {
- 32 => C_u32(bcx.ccx, bits as u32),
- 64 => C_u64(bcx.ccx, bits as u64),
+ 32 => C_u32(bx.cx, bits as u32),
+ 64 => C_u64(bx.cx, bits as u64),
n => bug!("unsupported float width {}", n),
};
consts::bitcast(bits_llval, float_ty)
// negation, and the negation can be merged into the select. Therefore, it not necessarily any
// more expensive than a ordered ("normal") comparison. Whether these optimizations will be
// performed is ultimately up to the backend, but at least x86 does perform them.
- let less_or_nan = bcx.fcmp(llvm::RealULT, x, f_min);
- let greater = bcx.fcmp(llvm::RealOGT, x, f_max);
+ let less_or_nan = bx.fcmp(llvm::RealULT, x, f_min);
+ let greater = bx.fcmp(llvm::RealOGT, x, f_max);
let int_max = C_uint_big(int_ty, int_max(signed, int_ty));
let int_min = C_uint_big(int_ty, int_min(signed, int_ty) as u128);
- let s0 = bcx.select(less_or_nan, int_min, fptosui_result);
- let s1 = bcx.select(greater, int_max, s0);
+ let s0 = bx.select(less_or_nan, int_min, fptosui_result);
+ let s1 = bx.select(greater, int_max, s0);
// Step 3: NaN replacement.
// For unsigned types, the above step already yielded int_ty::MIN == 0 if x is NaN.
// Therefore we only need to execute this step for signed integer types.
if signed {
// LLVM has no isNaN predicate, so we use (x == x) instead
- bcx.select(bcx.fcmp(llvm::RealOEQ, x, x), s1, C_uint(int_ty, 0))
+ bx.select(bx.fcmp(llvm::RealOEQ, x, x), s1, C_uint(int_ty, 0))
} else {
s1
}
use asm;
use builder::Builder;
-use super::MirContext;
+use super::FunctionCx;
use super::LocalRef;
-impl<'a, 'tcx> MirContext<'a, 'tcx> {
+impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
pub fn trans_statement(&mut self,
- bcx: Builder<'a, 'tcx>,
+ bx: Builder<'a, 'tcx>,
statement: &mir::Statement<'tcx>)
-> Builder<'a, 'tcx> {
debug!("trans_statement(statement={:?})", statement);
- self.set_debug_loc(&bcx, statement.source_info);
+ self.set_debug_loc(&bx, statement.source_info);
match statement.kind {
mir::StatementKind::Assign(ref place, ref rvalue) => {
if let mir::Place::Local(index) = *place {
match self.locals[index] {
LocalRef::Place(tr_dest) => {
- self.trans_rvalue(bcx, tr_dest, rvalue)
+ self.trans_rvalue(bx, tr_dest, rvalue)
}
LocalRef::Operand(None) => {
- let (bcx, operand) = self.trans_rvalue_operand(bcx, rvalue);
+ let (bx, operand) = self.trans_rvalue_operand(bx, rvalue);
self.locals[index] = LocalRef::Operand(Some(operand));
- bcx
+ bx
}
LocalRef::Operand(Some(op)) => {
if !op.layout.is_zst() {
// If the type is zero-sized, it's already been set here,
// but we still need to make sure we translate the operand
- self.trans_rvalue_operand(bcx, rvalue).0
+ self.trans_rvalue_operand(bx, rvalue).0
}
}
} else {
- let tr_dest = self.trans_place(&bcx, place);
- self.trans_rvalue(bcx, tr_dest, rvalue)
+ let tr_dest = self.trans_place(&bx, place);
+ self.trans_rvalue(bx, tr_dest, rvalue)
}
}
mir::StatementKind::SetDiscriminant{ref place, variant_index} => {
- self.trans_place(&bcx, place)
- .trans_set_discr(&bcx, variant_index);
- bcx
+ self.trans_place(&bx, place)
+ .trans_set_discr(&bx, variant_index);
+ bx
}
mir::StatementKind::StorageLive(local) => {
if let LocalRef::Place(tr_place) = self.locals[local] {
- tr_place.storage_live(&bcx);
+ tr_place.storage_live(&bx);
}
- bcx
+ bx
}
mir::StatementKind::StorageDead(local) => {
if let LocalRef::Place(tr_place) = self.locals[local] {
- tr_place.storage_dead(&bcx);
+ tr_place.storage_dead(&bx);
}
- bcx
+ bx
}
mir::StatementKind::InlineAsm { ref asm, ref outputs, ref inputs } => {
let outputs = outputs.iter().map(|output| {
- self.trans_place(&bcx, output)
+ self.trans_place(&bx, output)
}).collect();
let input_vals = inputs.iter().map(|input| {
- self.trans_operand(&bcx, input).immediate()
+ self.trans_operand(&bx, input).immediate()
}).collect();
- asm::trans_inline_asm(&bcx, asm, outputs, input_vals);
- bcx
+ asm::trans_inline_asm(&bx, asm, outputs, input_vals);
+ bx
}
mir::StatementKind::EndRegion(_) |
mir::StatementKind::Validate(..) |
- mir::StatementKind::Nop => bcx,
+ mir::StatementKind::Nop => bx,
}
}
}
return;
}
- let _ignore = tcx.dep_graph.in_ignore();
- let mut visitor = SymbolNamesTest { tcx: tcx };
- // FIXME(#37712) could use ItemLikeVisitor if trait items were item-like
- tcx.hir.krate().visit_all_item_likes(&mut visitor.as_deep_visitor());
+ tcx.dep_graph.with_ignore(|| {
+ let mut visitor = SymbolNamesTest { tcx: tcx };
+ // FIXME(#37712) could use ItemLikeVisitor if trait items were item-like
+ tcx.hir.krate().visit_all_item_likes(&mut visitor.as_deep_visitor());
+ })
}
struct SymbolNamesTest<'a, 'tcx:'a> {
use attributes;
use base;
use consts;
-use context::CrateContext;
+use context::CodegenCx;
use declare;
use llvm;
use monomorphize::Instance;
pub use rustc_mir::monomorphize::item::MonoItemExt as BaseMonoItemExt;
pub trait MonoItemExt<'a, 'tcx>: fmt::Debug + BaseMonoItemExt<'a, 'tcx> {
- fn define(&self, ccx: &CrateContext<'a, 'tcx>) {
+ fn define(&self, cx: &CodegenCx<'a, 'tcx>) {
debug!("BEGIN IMPLEMENTING '{} ({})' in cgu {}",
- self.to_string(ccx.tcx()),
+ self.to_string(cx.tcx),
self.to_raw_string(),
- ccx.codegen_unit().name());
+ cx.codegen_unit.name());
match *self.as_mono_item() {
MonoItem::Static(node_id) => {
- let tcx = ccx.tcx();
+ let tcx = cx.tcx;
let item = tcx.hir.expect_item(node_id);
if let hir::ItemStatic(_, m, _) = item.node {
- match consts::trans_static(&ccx, m, item.id, &item.attrs) {
+ match consts::trans_static(&cx, m, item.id, &item.attrs) {
Ok(_) => { /* Cool, everything's alright. */ },
Err(err) => {
err.report(tcx, item.span, "static");
}
}
MonoItem::GlobalAsm(node_id) => {
- let item = ccx.tcx().hir.expect_item(node_id);
+ let item = cx.tcx.hir.expect_item(node_id);
if let hir::ItemGlobalAsm(ref ga) = item.node {
- asm::trans_global_asm(ccx, ga);
+ asm::trans_global_asm(cx, ga);
} else {
span_bug!(item.span, "Mismatch between hir::Item type and TransItem type")
}
}
MonoItem::Fn(instance) => {
- base::trans_instance(&ccx, instance);
+ base::trans_instance(&cx, instance);
}
}
debug!("END IMPLEMENTING '{} ({})' in cgu {}",
- self.to_string(ccx.tcx()),
+ self.to_string(cx.tcx),
self.to_raw_string(),
- ccx.codegen_unit().name());
+ cx.codegen_unit.name());
}
fn predefine(&self,
- ccx: &CrateContext<'a, 'tcx>,
+ cx: &CodegenCx<'a, 'tcx>,
linkage: Linkage,
visibility: Visibility) {
debug!("BEGIN PREDEFINING '{} ({})' in cgu {}",
- self.to_string(ccx.tcx()),
+ self.to_string(cx.tcx),
self.to_raw_string(),
- ccx.codegen_unit().name());
+ cx.codegen_unit.name());
- let symbol_name = self.symbol_name(ccx.tcx());
+ let symbol_name = self.symbol_name(cx.tcx);
debug!("symbol {}", &symbol_name);
match *self.as_mono_item() {
MonoItem::Static(node_id) => {
- predefine_static(ccx, node_id, linkage, visibility, &symbol_name);
+ predefine_static(cx, node_id, linkage, visibility, &symbol_name);
}
MonoItem::Fn(instance) => {
- predefine_fn(ccx, instance, linkage, visibility, &symbol_name);
+ predefine_fn(cx, instance, linkage, visibility, &symbol_name);
}
MonoItem::GlobalAsm(..) => {}
}
debug!("END PREDEFINING '{} ({})' in cgu {}",
- self.to_string(ccx.tcx()),
+ self.to_string(cx.tcx),
self.to_raw_string(),
- ccx.codegen_unit().name());
+ cx.codegen_unit.name());
}
fn local_span(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Option<Span> {
impl<'a, 'tcx> MonoItemExt<'a, 'tcx> for MonoItem<'tcx> {}
-fn predefine_static<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
+fn predefine_static<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
node_id: ast::NodeId,
linkage: Linkage,
visibility: Visibility,
symbol_name: &str) {
- let def_id = ccx.tcx().hir.local_def_id(node_id);
- let instance = Instance::mono(ccx.tcx(), def_id);
- let ty = instance.ty(ccx.tcx());
- let llty = ccx.layout_of(ty).llvm_type(ccx);
+ let def_id = cx.tcx.hir.local_def_id(node_id);
+ let instance = Instance::mono(cx.tcx, def_id);
+ let ty = instance.ty(cx.tcx);
+ let llty = cx.layout_of(ty).llvm_type(cx);
- let g = declare::define_global(ccx, symbol_name, llty).unwrap_or_else(|| {
- ccx.sess().span_fatal(ccx.tcx().hir.span(node_id),
+ let g = declare::define_global(cx, symbol_name, llty).unwrap_or_else(|| {
+ cx.sess().span_fatal(cx.tcx.hir.span(node_id),
&format!("symbol `{}` is already defined", symbol_name))
});
llvm::LLVMRustSetVisibility(g, base::visibility_to_llvm(visibility));
}
- ccx.instances().borrow_mut().insert(instance, g);
- ccx.statics().borrow_mut().insert(g, def_id);
+ cx.instances.borrow_mut().insert(instance, g);
+ cx.statics.borrow_mut().insert(g, def_id);
}
-fn predefine_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
+fn predefine_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
instance: Instance<'tcx>,
linkage: Linkage,
visibility: Visibility,
assert!(!instance.substs.needs_infer() &&
!instance.substs.has_param_types());
- let mono_ty = instance.ty(ccx.tcx());
- let attrs = instance.def.attrs(ccx.tcx());
- let lldecl = declare::declare_fn(ccx, symbol_name, mono_ty);
+ let mono_ty = instance.ty(cx.tcx);
+ let attrs = instance.def.attrs(cx.tcx);
+ let lldecl = declare::declare_fn(cx, symbol_name, mono_ty);
unsafe { llvm::LLVMRustSetLinkage(lldecl, base::linkage_to_llvm(linkage)) };
- base::set_link_section(ccx, lldecl, &attrs);
+ base::set_link_section(cx, lldecl, &attrs);
if linkage == Linkage::LinkOnceODR ||
linkage == Linkage::WeakODR {
- llvm::SetUniqueComdat(ccx.llmod(), lldecl);
+ llvm::SetUniqueComdat(cx.llmod, lldecl);
}
// If we're compiling the compiler-builtins crate, e.g. the equivalent of
// visibility as we're going to link this object all over the place but
// don't want the symbols to get exported.
if linkage != Linkage::Internal && linkage != Linkage::Private &&
- attr::contains_name(ccx.tcx().hir.krate_attrs(), "compiler_builtins") {
+ attr::contains_name(cx.tcx.hir.krate_attrs(), "compiler_builtins") {
unsafe {
llvm::LLVMRustSetVisibility(lldecl, llvm::Visibility::Hidden);
}
}
debug!("predefine_fn: mono_ty = {:?} instance = {:?}", mono_ty, instance);
- if instance.def.is_inline(ccx.tcx()) {
+ if instance.def.is_inline(cx.tcx) {
attributes::inline(lldecl, attributes::InlineAttr::Hint);
}
- attributes::from_fn_attrs(ccx, &attrs, lldecl);
+ attributes::from_fn_attrs(cx, lldecl, instance.def.def_id());
- ccx.instances().borrow_mut().insert(instance, lldecl);
+ cx.instances.borrow_mut().insert(instance, lldecl);
}
use llvm::{ContextRef, TypeRef, Bool, False, True, TypeKind};
use llvm::{Float, Double, X86_FP80, PPC_FP128, FP128};
-use context::CrateContext;
+use context::CodegenCx;
use syntax::ast;
use rustc::ty::layout::{self, Align, Size};
unsafe { mem::transmute(slice) }
}
- pub fn void(ccx: &CrateContext) -> Type {
- ty!(llvm::LLVMVoidTypeInContext(ccx.llcx()))
+ pub fn void(cx: &CodegenCx) -> Type {
+ ty!(llvm::LLVMVoidTypeInContext(cx.llcx))
}
- pub fn metadata(ccx: &CrateContext) -> Type {
- ty!(llvm::LLVMRustMetadataTypeInContext(ccx.llcx()))
+ pub fn metadata(cx: &CodegenCx) -> Type {
+ ty!(llvm::LLVMRustMetadataTypeInContext(cx.llcx))
}
- pub fn i1(ccx: &CrateContext) -> Type {
- ty!(llvm::LLVMInt1TypeInContext(ccx.llcx()))
+ pub fn i1(cx: &CodegenCx) -> Type {
+ ty!(llvm::LLVMInt1TypeInContext(cx.llcx))
}
- pub fn i8(ccx: &CrateContext) -> Type {
- ty!(llvm::LLVMInt8TypeInContext(ccx.llcx()))
+ pub fn i8(cx: &CodegenCx) -> Type {
+ ty!(llvm::LLVMInt8TypeInContext(cx.llcx))
}
pub fn i8_llcx(llcx: ContextRef) -> Type {
ty!(llvm::LLVMInt8TypeInContext(llcx))
}
- pub fn i16(ccx: &CrateContext) -> Type {
- ty!(llvm::LLVMInt16TypeInContext(ccx.llcx()))
+ pub fn i16(cx: &CodegenCx) -> Type {
+ ty!(llvm::LLVMInt16TypeInContext(cx.llcx))
}
- pub fn i32(ccx: &CrateContext) -> Type {
- ty!(llvm::LLVMInt32TypeInContext(ccx.llcx()))
+ pub fn i32(cx: &CodegenCx) -> Type {
+ ty!(llvm::LLVMInt32TypeInContext(cx.llcx))
}
- pub fn i64(ccx: &CrateContext) -> Type {
- ty!(llvm::LLVMInt64TypeInContext(ccx.llcx()))
+ pub fn i64(cx: &CodegenCx) -> Type {
+ ty!(llvm::LLVMInt64TypeInContext(cx.llcx))
}
- pub fn i128(ccx: &CrateContext) -> Type {
- ty!(llvm::LLVMIntTypeInContext(ccx.llcx(), 128))
+ pub fn i128(cx: &CodegenCx) -> Type {
+ ty!(llvm::LLVMIntTypeInContext(cx.llcx, 128))
}
// Creates an integer type with the given number of bits, e.g. i24
- pub fn ix(ccx: &CrateContext, num_bits: u64) -> Type {
- ty!(llvm::LLVMIntTypeInContext(ccx.llcx(), num_bits as c_uint))
+ pub fn ix(cx: &CodegenCx, num_bits: u64) -> Type {
+ ty!(llvm::LLVMIntTypeInContext(cx.llcx, num_bits as c_uint))
}
- pub fn f32(ccx: &CrateContext) -> Type {
- ty!(llvm::LLVMFloatTypeInContext(ccx.llcx()))
+ pub fn f32(cx: &CodegenCx) -> Type {
+ ty!(llvm::LLVMFloatTypeInContext(cx.llcx))
}
- pub fn f64(ccx: &CrateContext) -> Type {
- ty!(llvm::LLVMDoubleTypeInContext(ccx.llcx()))
+ pub fn f64(cx: &CodegenCx) -> Type {
+ ty!(llvm::LLVMDoubleTypeInContext(cx.llcx))
}
- pub fn bool(ccx: &CrateContext) -> Type {
- Type::i8(ccx)
+ pub fn bool(cx: &CodegenCx) -> Type {
+ Type::i8(cx)
}
- pub fn char(ccx: &CrateContext) -> Type {
- Type::i32(ccx)
+ pub fn char(cx: &CodegenCx) -> Type {
+ Type::i32(cx)
}
- pub fn i8p(ccx: &CrateContext) -> Type {
- Type::i8(ccx).ptr_to()
+ pub fn i8p(cx: &CodegenCx) -> Type {
+ Type::i8(cx).ptr_to()
}
pub fn i8p_llcx(llcx: ContextRef) -> Type {
Type::i8_llcx(llcx).ptr_to()
}
- pub fn isize(ccx: &CrateContext) -> Type {
- match &ccx.tcx().sess.target.target.target_pointer_width[..] {
- "16" => Type::i16(ccx),
- "32" => Type::i32(ccx),
- "64" => Type::i64(ccx),
+ pub fn isize(cx: &CodegenCx) -> Type {
+ match &cx.tcx.sess.target.target.target_pointer_width[..] {
+ "16" => Type::i16(cx),
+ "32" => Type::i32(cx),
+ "64" => Type::i64(cx),
tws => bug!("Unsupported target word size for int: {}", tws),
}
}
- pub fn c_int(ccx: &CrateContext) -> Type {
- match &ccx.tcx().sess.target.target.target_c_int_width[..] {
- "16" => Type::i16(ccx),
- "32" => Type::i32(ccx),
- "64" => Type::i64(ccx),
+ pub fn c_int(cx: &CodegenCx) -> Type {
+ match &cx.tcx.sess.target.target.target_c_int_width[..] {
+ "16" => Type::i16(cx),
+ "32" => Type::i32(cx),
+ "64" => Type::i64(cx),
width => bug!("Unsupported target_c_int_width: {}", width),
}
}
- pub fn int_from_ty(ccx: &CrateContext, t: ast::IntTy) -> Type {
+ pub fn int_from_ty(cx: &CodegenCx, t: ast::IntTy) -> Type {
match t {
- ast::IntTy::Is => ccx.isize_ty(),
- ast::IntTy::I8 => Type::i8(ccx),
- ast::IntTy::I16 => Type::i16(ccx),
- ast::IntTy::I32 => Type::i32(ccx),
- ast::IntTy::I64 => Type::i64(ccx),
- ast::IntTy::I128 => Type::i128(ccx),
+ ast::IntTy::Isize => cx.isize_ty,
+ ast::IntTy::I8 => Type::i8(cx),
+ ast::IntTy::I16 => Type::i16(cx),
+ ast::IntTy::I32 => Type::i32(cx),
+ ast::IntTy::I64 => Type::i64(cx),
+ ast::IntTy::I128 => Type::i128(cx),
}
}
- pub fn uint_from_ty(ccx: &CrateContext, t: ast::UintTy) -> Type {
+ pub fn uint_from_ty(cx: &CodegenCx, t: ast::UintTy) -> Type {
match t {
- ast::UintTy::Us => ccx.isize_ty(),
- ast::UintTy::U8 => Type::i8(ccx),
- ast::UintTy::U16 => Type::i16(ccx),
- ast::UintTy::U32 => Type::i32(ccx),
- ast::UintTy::U64 => Type::i64(ccx),
- ast::UintTy::U128 => Type::i128(ccx),
+ ast::UintTy::Usize => cx.isize_ty,
+ ast::UintTy::U8 => Type::i8(cx),
+ ast::UintTy::U16 => Type::i16(cx),
+ ast::UintTy::U32 => Type::i32(cx),
+ ast::UintTy::U64 => Type::i64(cx),
+ ast::UintTy::U128 => Type::i128(cx),
}
}
- pub fn float_from_ty(ccx: &CrateContext, t: ast::FloatTy) -> Type {
+ pub fn float_from_ty(cx: &CodegenCx, t: ast::FloatTy) -> Type {
match t {
- ast::FloatTy::F32 => Type::f32(ccx),
- ast::FloatTy::F64 => Type::f64(ccx),
+ ast::FloatTy::F32 => Type::f32(cx),
+ ast::FloatTy::F64 => Type::f64(cx),
}
}
args.len() as c_uint, True))
}
- pub fn struct_(ccx: &CrateContext, els: &[Type], packed: bool) -> Type {
+ pub fn struct_(cx: &CodegenCx, els: &[Type], packed: bool) -> Type {
let els: &[TypeRef] = Type::to_ref_slice(els);
- ty!(llvm::LLVMStructTypeInContext(ccx.llcx(), els.as_ptr(),
+ ty!(llvm::LLVMStructTypeInContext(cx.llcx, els.as_ptr(),
els.len() as c_uint,
packed as Bool))
}
- pub fn named_struct(ccx: &CrateContext, name: &str) -> Type {
+ pub fn named_struct(cx: &CodegenCx, name: &str) -> Type {
let name = CString::new(name).unwrap();
- ty!(llvm::LLVMStructCreateNamed(ccx.llcx(), name.as_ptr()))
+ ty!(llvm::LLVMStructCreateNamed(cx.llcx, name.as_ptr()))
}
}
}
- pub fn from_integer(cx: &CrateContext, i: layout::Integer) -> Type {
+ pub fn from_integer(cx: &CodegenCx, i: layout::Integer) -> Type {
use rustc::ty::layout::Integer::*;
match i {
I8 => Type::i8(cx),
/// Return a LLVM type that has at most the required alignment,
/// as a conservative approximation for unknown pointee types.
- pub fn pointee_for_abi_align(ccx: &CrateContext, align: Align) -> Type {
+ pub fn pointee_for_abi_align(cx: &CodegenCx, align: Align) -> Type {
// FIXME(eddyb) We could find a better approximation if ity.align < align.
- let ity = layout::Integer::approximate_abi_align(ccx, align);
- Type::from_integer(ccx, ity)
+ let ity = layout::Integer::approximate_abi_align(cx, align);
+ Type::from_integer(cx, ity)
}
/// Return a LLVM type that has at most the required alignment,
/// and exactly the required size, as a best-effort padding array.
- pub fn padding_filler(ccx: &CrateContext, size: Size, align: Align) -> Type {
- let unit = layout::Integer::approximate_abi_align(ccx, align);
+ pub fn padding_filler(cx: &CodegenCx, size: Size, align: Align) -> Type {
+ let unit = layout::Integer::approximate_abi_align(cx, align);
let size = size.bytes();
let unit_size = unit.size().bytes();
assert_eq!(size % unit_size, 0);
- Type::array(&Type::from_integer(ccx, unit), size / unit_size)
+ Type::array(&Type::from_integer(cx, unit), size / unit_size)
}
- pub fn x86_mmx(ccx: &CrateContext) -> Type {
- ty!(llvm::LLVMX86MMXTypeInContext(ccx.llcx()))
+ pub fn x86_mmx(cx: &CodegenCx) -> Type {
+ ty!(llvm::LLVMX86MMXTypeInContext(cx.llcx))
}
}
use std::fmt::Write;
-fn uncached_llvm_type<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
+fn uncached_llvm_type<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
layout: TyLayout<'tcx>,
defer: &mut Option<(Type, TyLayout<'tcx>)>)
-> Type {
// one-element SIMD vectors, so it's assumed this won't clash with
// much else.
let use_x86_mmx = count == 1 && layout.size.bits() == 64 &&
- (ccx.sess().target.target.arch == "x86" ||
- ccx.sess().target.target.arch == "x86_64");
+ (cx.sess().target.target.arch == "x86" ||
+ cx.sess().target.target.arch == "x86_64");
if use_x86_mmx {
- return Type::x86_mmx(ccx)
+ return Type::x86_mmx(cx)
} else {
- let element = layout.scalar_llvm_type_at(ccx, element, Size::from_bytes(0));
+ let element = layout.scalar_llvm_type_at(cx, element, Size::from_bytes(0));
return Type::vector(&element, count);
}
}
layout::Abi::ScalarPair(..) => {
- return Type::struct_(ccx, &[
- layout.scalar_pair_element_llvm_type(ccx, 0),
- layout.scalar_pair_element_llvm_type(ccx, 1),
+ return Type::struct_(cx, &[
+ layout.scalar_pair_element_llvm_type(cx, 0),
+ layout.scalar_pair_element_llvm_type(cx, 1),
], false);
}
layout::Abi::Uninhabited |
ty::TyForeign(..) |
ty::TyStr => {
let mut name = String::with_capacity(32);
- let printer = DefPathBasedNames::new(ccx.tcx(), true, true);
+ let printer = DefPathBasedNames::new(cx.tcx, true, true);
printer.push_type_name(layout.ty, &mut name);
match (&layout.ty.sty, &layout.variants) {
(&ty::TyAdt(def, _), &layout::Variants::Single { index }) => {
match layout.fields {
layout::FieldPlacement::Union(_) => {
- let fill = Type::padding_filler(ccx, layout.size, layout.align);
+ let fill = Type::padding_filler(cx, layout.size, layout.align);
let packed = false;
match name {
None => {
- Type::struct_(ccx, &[fill], packed)
+ Type::struct_(cx, &[fill], packed)
}
Some(ref name) => {
- let mut llty = Type::named_struct(ccx, name);
+ let mut llty = Type::named_struct(cx, name);
llty.set_struct_body(&[fill], packed);
llty
}
}
}
layout::FieldPlacement::Array { count, .. } => {
- Type::array(&layout.field(ccx, 0).llvm_type(ccx), count)
+ Type::array(&layout.field(cx, 0).llvm_type(cx), count)
}
layout::FieldPlacement::Arbitrary { .. } => {
match name {
None => {
- let (llfields, packed) = struct_llfields(ccx, layout);
- Type::struct_(ccx, &llfields, packed)
+ let (llfields, packed) = struct_llfields(cx, layout);
+ Type::struct_(cx, &llfields, packed)
}
Some(ref name) => {
- let llty = Type::named_struct(ccx, name);
+ let llty = Type::named_struct(cx, name);
*defer = Some((llty, layout));
llty
}
}
}
-fn struct_llfields<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
+fn struct_llfields<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
layout: TyLayout<'tcx>)
-> (Vec<Type>, bool) {
debug!("struct_llfields: {:#?}", layout);
let mut prev_align = layout.align;
let mut result: Vec<Type> = Vec::with_capacity(1 + field_count * 2);
for i in layout.fields.index_by_increasing_offset() {
- let field = layout.field(ccx, i);
+ let field = layout.field(cx, i);
packed |= layout.align.abi() < field.align.abi();
let target_offset = layout.fields.offset(i as usize);
let padding = target_offset - offset;
let padding_align = layout.align.min(prev_align).min(field.align);
assert_eq!(offset.abi_align(padding_align) + padding, target_offset);
- result.push(Type::padding_filler(ccx, padding, padding_align));
+ result.push(Type::padding_filler(cx, padding, padding_align));
debug!(" padding before: {:?}", padding);
- result.push(field.llvm_type(ccx));
+ result.push(field.llvm_type(cx));
offset = target_offset + field.size;
prev_align = field.align;
}
assert_eq!(offset.abi_align(padding_align) + padding, layout.size);
debug!("struct_llfields: pad_bytes: {:?} offset: {:?} stride: {:?}",
padding, offset, layout.size);
- result.push(Type::padding_filler(ccx, padding, padding_align));
+ result.push(Type::padding_filler(cx, padding, padding_align));
assert!(result.len() == 1 + field_count * 2);
} else {
debug!("struct_llfields: offset: {:?} stride: {:?}",
(result, packed)
}
-impl<'a, 'tcx> CrateContext<'a, 'tcx> {
+impl<'a, 'tcx> CodegenCx<'a, 'tcx> {
pub fn align_of(&self, ty: Ty<'tcx>) -> Align {
self.layout_of(ty).align
}
pub trait LayoutLlvmExt<'tcx> {
fn is_llvm_immediate(&self) -> bool;
fn is_llvm_scalar_pair<'a>(&self) -> bool;
- fn llvm_type<'a>(&self, ccx: &CrateContext<'a, 'tcx>) -> Type;
- fn immediate_llvm_type<'a>(&self, ccx: &CrateContext<'a, 'tcx>) -> Type;
- fn scalar_llvm_type_at<'a>(&self, ccx: &CrateContext<'a, 'tcx>,
+ fn llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> Type;
+ fn immediate_llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> Type;
+ fn scalar_llvm_type_at<'a>(&self, cx: &CodegenCx<'a, 'tcx>,
scalar: &layout::Scalar, offset: Size) -> Type;
- fn scalar_pair_element_llvm_type<'a>(&self, ccx: &CrateContext<'a, 'tcx>,
+ fn scalar_pair_element_llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>,
index: usize) -> Type;
fn llvm_field_index(&self, index: usize) -> u64;
- fn pointee_info_at<'a>(&self, ccx: &CrateContext<'a, 'tcx>, offset: Size)
+ fn pointee_info_at<'a>(&self, cx: &CodegenCx<'a, 'tcx>, offset: Size)
-> Option<PointeeInfo>;
}
/// with the inner-most trailing unsized field using the "minimal unit"
/// of that field's type - this is useful for taking the address of
/// that field and ensuring the struct has the right alignment.
- fn llvm_type<'a>(&self, ccx: &CrateContext<'a, 'tcx>) -> Type {
+ fn llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> Type {
if let layout::Abi::Scalar(ref scalar) = self.abi {
// Use a different cache for scalars because pointers to DSTs
// can be either fat or thin (data pointers of fat pointers).
- if let Some(&llty) = ccx.scalar_lltypes().borrow().get(&self.ty) {
+ if let Some(&llty) = cx.scalar_lltypes.borrow().get(&self.ty) {
return llty;
}
let llty = match self.ty.sty {
ty::TyRef(_, ty::TypeAndMut { ty, .. }) |
ty::TyRawPtr(ty::TypeAndMut { ty, .. }) => {
- ccx.layout_of(ty).llvm_type(ccx).ptr_to()
+ cx.layout_of(ty).llvm_type(cx).ptr_to()
}
ty::TyAdt(def, _) if def.is_box() => {
- ccx.layout_of(self.ty.boxed_ty()).llvm_type(ccx).ptr_to()
+ cx.layout_of(self.ty.boxed_ty()).llvm_type(cx).ptr_to()
}
ty::TyFnPtr(sig) => {
- let sig = ccx.tcx().erase_late_bound_regions_and_normalize(&sig);
- FnType::new(ccx, sig, &[]).llvm_type(ccx).ptr_to()
+ let sig = cx.tcx.erase_late_bound_regions_and_normalize(&sig);
+ FnType::new(cx, sig, &[]).llvm_type(cx).ptr_to()
}
- _ => self.scalar_llvm_type_at(ccx, scalar, Size::from_bytes(0))
+ _ => self.scalar_llvm_type_at(cx, scalar, Size::from_bytes(0))
};
- ccx.scalar_lltypes().borrow_mut().insert(self.ty, llty);
+ cx.scalar_lltypes.borrow_mut().insert(self.ty, llty);
return llty;
}
layout::Variants::Single { index } => Some(index),
_ => None
};
- if let Some(&llty) = ccx.lltypes().borrow().get(&(self.ty, variant_index)) {
+ if let Some(&llty) = cx.lltypes.borrow().get(&(self.ty, variant_index)) {
return llty;
}
// Make sure lifetimes are erased, to avoid generating distinct LLVM
// types for Rust types that only differ in the choice of lifetimes.
- let normal_ty = ccx.tcx().erase_regions(&self.ty);
+ let normal_ty = cx.tcx.erase_regions(&self.ty);
let mut defer = None;
let llty = if self.ty != normal_ty {
- let mut layout = ccx.layout_of(normal_ty);
+ let mut layout = cx.layout_of(normal_ty);
if let Some(v) = variant_index {
- layout = layout.for_variant(ccx, v);
+ layout = layout.for_variant(cx, v);
}
- layout.llvm_type(ccx)
+ layout.llvm_type(cx)
} else {
- uncached_llvm_type(ccx, *self, &mut defer)
+ uncached_llvm_type(cx, *self, &mut defer)
};
debug!("--> mapped {:#?} to llty={:?}", self, llty);
- ccx.lltypes().borrow_mut().insert((self.ty, variant_index), llty);
+ cx.lltypes.borrow_mut().insert((self.ty, variant_index), llty);
if let Some((mut llty, layout)) = defer {
- let (llfields, packed) = struct_llfields(ccx, layout);
+ let (llfields, packed) = struct_llfields(cx, layout);
llty.set_struct_body(&llfields, packed)
}
llty
}
- fn immediate_llvm_type<'a>(&self, ccx: &CrateContext<'a, 'tcx>) -> Type {
+ fn immediate_llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> Type {
if let layout::Abi::Scalar(ref scalar) = self.abi {
if scalar.is_bool() {
- return Type::i1(ccx);
+ return Type::i1(cx);
}
}
- self.llvm_type(ccx)
+ self.llvm_type(cx)
}
- fn scalar_llvm_type_at<'a>(&self, ccx: &CrateContext<'a, 'tcx>,
+ fn scalar_llvm_type_at<'a>(&self, cx: &CodegenCx<'a, 'tcx>,
scalar: &layout::Scalar, offset: Size) -> Type {
match scalar.value {
- layout::Int(i, _) => Type::from_integer(ccx, i),
- layout::F32 => Type::f32(ccx),
- layout::F64 => Type::f64(ccx),
+ layout::Int(i, _) => Type::from_integer(cx, i),
+ layout::F32 => Type::f32(cx),
+ layout::F64 => Type::f64(cx),
layout::Pointer => {
// If we know the alignment, pick something better than i8.
- let pointee = if let Some(pointee) = self.pointee_info_at(ccx, offset) {
- Type::pointee_for_abi_align(ccx, pointee.align)
+ let pointee = if let Some(pointee) = self.pointee_info_at(cx, offset) {
+ Type::pointee_for_abi_align(cx, pointee.align)
} else {
- Type::i8(ccx)
+ Type::i8(cx)
};
pointee.ptr_to()
}
}
}
- fn scalar_pair_element_llvm_type<'a>(&self, ccx: &CrateContext<'a, 'tcx>,
+ fn scalar_pair_element_llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>,
index: usize) -> Type {
// HACK(eddyb) special-case fat pointers until LLVM removes
// pointee types, to avoid bitcasting every `OperandRef::deref`.
match self.ty.sty {
ty::TyRef(..) |
ty::TyRawPtr(_) => {
- return self.field(ccx, index).llvm_type(ccx);
+ return self.field(cx, index).llvm_type(cx);
}
ty::TyAdt(def, _) if def.is_box() => {
- let ptr_ty = ccx.tcx().mk_mut_ptr(self.ty.boxed_ty());
- return ccx.layout_of(ptr_ty).scalar_pair_element_llvm_type(ccx, index);
+ let ptr_ty = cx.tcx.mk_mut_ptr(self.ty.boxed_ty());
+ return cx.layout_of(ptr_ty).scalar_pair_element_llvm_type(cx, index);
}
_ => {}
}
// load/store `bool` as `i8` to avoid crippling LLVM optimizations,
// `i1` in a LLVM aggregate is valid and mostly equivalent to `i8`.
if scalar.is_bool() {
- return Type::i1(ccx);
+ return Type::i1(cx);
}
let offset = if index == 0 {
Size::from_bytes(0)
} else {
- a.value.size(ccx).abi_align(b.value.align(ccx))
+ a.value.size(cx).abi_align(b.value.align(cx))
};
- self.scalar_llvm_type_at(ccx, scalar, offset)
+ self.scalar_llvm_type_at(cx, scalar, offset)
}
fn llvm_field_index(&self, index: usize) -> u64 {
}
}
- fn pointee_info_at<'a>(&self, ccx: &CrateContext<'a, 'tcx>, offset: Size)
+ fn pointee_info_at<'a>(&self, cx: &CodegenCx<'a, 'tcx>, offset: Size)
-> Option<PointeeInfo> {
- if let Some(&pointee) = ccx.pointee_infos().borrow().get(&(self.ty, offset)) {
+ if let Some(&pointee) = cx.pointee_infos.borrow().get(&(self.ty, offset)) {
return pointee;
}
let mut result = None;
match self.ty.sty {
ty::TyRawPtr(mt) if offset.bytes() == 0 => {
- let (size, align) = ccx.size_and_align_of(mt.ty);
+ let (size, align) = cx.size_and_align_of(mt.ty);
result = Some(PointeeInfo {
size,
align,
}
ty::TyRef(_, mt) if offset.bytes() == 0 => {
- let (size, align) = ccx.size_and_align_of(mt.ty);
+ let (size, align) = cx.size_and_align_of(mt.ty);
let kind = match mt.mutbl {
- hir::MutImmutable => if ccx.shared().type_is_freeze(mt.ty) {
+ hir::MutImmutable => if cx.type_is_freeze(mt.ty) {
PointerKind::Frozen
} else {
PointerKind::Shared
},
hir::MutMutable => {
- if ccx.shared().tcx().sess.opts.debugging_opts.mutable_noalias ||
- ccx.shared().tcx().sess.panic_strategy() == PanicStrategy::Abort {
+ if cx.tcx.sess.opts.debugging_opts.mutable_noalias ||
+ cx.tcx.sess.panic_strategy() == PanicStrategy::Abort {
PointerKind::UniqueBorrowed
} else {
PointerKind::Shared
// niches than just null (e.g. the first page
// of the address space, or unaligned pointers).
if self.fields.offset(0) == offset {
- Some(self.for_variant(ccx, dataful_variant))
+ Some(self.for_variant(cx, dataful_variant))
} else {
None
}
}
if let Some(variant) = data_variant {
- let ptr_end = offset + layout::Pointer.size(ccx);
+ let ptr_end = offset + layout::Pointer.size(cx);
for i in 0..variant.fields.count() {
let field_start = variant.fields.offset(i);
if field_start <= offset {
- let field = variant.field(ccx, i);
+ let field = variant.field(cx, i);
if ptr_end <= field_start + field.size {
// We found the right field, look inside it.
- result = field.pointee_info_at(ccx, offset - field_start);
+ result = field.pointee_info_at(cx, offset - field_start);
break;
}
}
}
}
- ccx.pointee_infos().borrow_mut().insert((self.ty, offset), result);
+ cx.pointee_infos.borrow_mut().insert((self.ty, offset), result);
result
}
}
[dependencies]
ar = "0.3.0"
flate2 = "1.0"
-log = "0.3"
+log = "0.4"
syntax = { path = "../libsyntax" }
syntax_pos = { path = "../libsyntax_pos" }
test = false
[dependencies]
-log = "0.3"
+log = "0.4"
syntax = { path = "../libsyntax" }
arena = { path = "../libarena" }
fmt_macros = { path = "../libfmt_macros" }
use super::method::MethodCallee;
use rustc::infer::InferOk;
+use rustc::session::DiagnosticMessageId;
use rustc::traits;
use rustc::ty::{self, Ty, TraitRef};
use rustc::ty::{ToPredicate, TypeFoldable};
return Some((self.cur_ty, 0));
}
- if self.steps.len() == tcx.sess.recursion_limit.get() {
+ if self.steps.len() >= tcx.sess.recursion_limit.get() {
// We've reached the recursion limit, error gracefully.
let suggested_limit = tcx.sess.recursion_limit.get() * 2;
- struct_span_err!(tcx.sess,
- self.span,
- E0055,
- "reached the recursion limit while auto-dereferencing {:?}",
- self.cur_ty)
- .span_label(self.span, "deref recursion limit reached")
- .help(&format!(
- "consider adding a `#[recursion_limit=\"{}\"]` attribute to your crate",
+ let msg = format!("reached the recursion limit while auto-dereferencing {:?}",
+ self.cur_ty);
+ let error_id = (DiagnosticMessageId::ErrorId(55), Some(self.span), msg.clone());
+ let fresh = tcx.sess.one_time_diagnostics.borrow_mut().insert(error_id);
+ if fresh {
+ struct_span_err!(tcx.sess,
+ self.span,
+ E0055,
+ "reached the recursion limit while auto-dereferencing {:?}",
+ self.cur_ty)
+ .span_label(self.span, "deref recursion limit reached")
+ .help(&format!(
+ "consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate",
suggested_limit))
- .emit();
+ .emit();
+ }
return None;
}
ty::TyDynamic(ref tty, ..) =>
Some(PointerKind::Vtable(tty.principal().map(|p| p.def_id()))),
ty::TyAdt(def, substs) if def.is_struct() => {
- match def.struct_variant().fields.last() {
+ match def.non_enum_variant().fields.last() {
None => Some(PointerKind::Thin),
Some(f) => {
let field_ty = self.field_ty(span, f, substs);
CastError::NeedViaPtr => {
let mut err = make_invalid_casting_error(fcx.tcx.sess, self.span, self.expr_ty,
self.cast_ty, fcx);
- if self.cast_ty.is_uint() {
+ if self.cast_ty.is_integral() {
err.help(&format!("cast through {} first",
match e {
CastError::NeedViaPtr => "a raw pointer",
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use std::iter;
use check::FnCtxt;
use rustc::infer::InferOk;
if let Some((msg, suggestion)) = self.check_ref(expr, checked_ty, expected) {
err.span_suggestion(expr.span, msg, suggestion);
} else {
- let mode = probe::Mode::MethodCall;
- let suggestions = self.probe_for_return_type(syntax_pos::DUMMY_SP,
- mode,
- expected,
- checked_ty,
- ast::DUMMY_NODE_ID);
- if suggestions.len() > 0 {
- err.help(&format!("here are some functions which \
- might fulfill your needs:\n{}",
- self.get_best_match(&suggestions).join("\n")));
+ let methods = self.get_conversion_methods(expected, checked_ty);
+ if let Ok(expr_text) = self.tcx.sess.codemap().span_to_snippet(expr.span) {
+ let suggestions = iter::repeat(expr_text).zip(methods.iter())
+ .map(|(receiver, method)| format!("{}.{}()", receiver, method.name))
+ .collect::<Vec<_>>();
+ if !suggestions.is_empty() {
+ err.span_suggestions(expr.span,
+ "try using a conversion method",
+ suggestions);
+ }
}
}
(expected, Some(err))
}
- fn format_method_suggestion(&self, method: &AssociatedItem) -> String {
- format!("- .{}({})",
- method.name,
- if self.has_no_input_arg(method) {
- ""
- } else {
- "..."
- })
- }
-
- fn display_suggested_methods(&self, methods: &[AssociatedItem]) -> Vec<String> {
- methods.iter()
- .take(5)
- .map(|method| self.format_method_suggestion(&*method))
- .collect::<Vec<String>>()
- }
+ fn get_conversion_methods(&self, expected: Ty<'tcx>, checked_ty: Ty<'tcx>)
+ -> Vec<AssociatedItem> {
+ let mut methods = self.probe_for_return_type(syntax_pos::DUMMY_SP,
+ probe::Mode::MethodCall,
+ expected,
+ checked_ty,
+ ast::DUMMY_NODE_ID);
+ methods.retain(|m| {
+ self.has_no_input_arg(m) &&
+ self.tcx.get_attrs(m.def_id).iter()
+ // This special internal attribute is used to whitelist
+ // "identity-like" conversion methods to be suggested here.
+ //
+ // FIXME (#46459 and #46460): ideally
+ // `std::convert::Into::into` and `std::borrow:ToOwned` would
+ // also be `#[rustc_conversion_suggestion]`, if not for
+ // method-probing false-positives and -negatives (respectively).
+ //
+ // FIXME? Other potential candidate methods: `as_ref` and
+ // `as_mut`?
+ .find(|a| a.check_name("rustc_conversion_suggestion")).is_some()
+ });
- fn get_best_match(&self, methods: &[AssociatedItem]) -> Vec<String> {
- let no_argument_methods: Vec<_> =
- methods.iter()
- .filter(|ref x| self.has_no_input_arg(&*x))
- .map(|x| x.clone())
- .collect();
- if no_argument_methods.len() > 0 {
- self.display_suggested_methods(&no_argument_methods)
- } else {
- self.display_suggested_methods(&methods)
- }
+ methods
}
// This function checks if the method isn't static and takes other arguments than `self`.
scope_expr_id);
let method_names =
self.probe_op(span, mode, None, Some(return_type), IsSuggestion(true),
- self_ty, scope_expr_id, ProbeScope::TraitsInScope,
+ self_ty, scope_expr_id, ProbeScope::AllTraits,
|probe_cx| Ok(probe_cx.candidate_method_names()))
.unwrap_or(vec![]);
method_names
self.probe_op(
span, mode, Some(method_name), Some(return_type),
IsSuggestion(true), self_ty, scope_expr_id,
- ProbeScope::TraitsInScope, |probe_cx| probe_cx.pick()
+ ProbeScope::AllTraits, |probe_cx| probe_cx.pick()
).ok().map(|pick| pick.item)
})
.collect()
let lang_def_id = lang_items.i128_impl();
self.assemble_inherent_impl_for_primitive(lang_def_id);
}
- ty::TyInt(ast::IntTy::Is) => {
+ ty::TyInt(ast::IntTy::Isize) => {
let lang_def_id = lang_items.isize_impl();
self.assemble_inherent_impl_for_primitive(lang_def_id);
}
let lang_def_id = lang_items.u128_impl();
self.assemble_inherent_impl_for_primitive(lang_def_id);
}
- ty::TyUint(ast::UintTy::Us) => {
+ ty::TyUint(ast::UintTy::Usize) => {
let lang_def_id = lang_items.usize_impl();
self.assemble_inherent_impl_for_primitive(lang_def_id);
}
}
};
let mut err = if !actual.references_error() {
- struct_span_err!(
- tcx.sess,
- span,
- E0599,
- "no {} named `{}` found for type `{}` in the current scope",
- type_str,
- item_name,
- ty_string
- )
+ // Suggest clamping down the type if the method that is being attempted to
+ // be used exists at all, and the type is an ambiuous numeric type
+ // ({integer}/{float}).
+ let mut candidates = all_traits(self.tcx)
+ .filter(|info| {
+ self.associated_item(info.def_id, item_name, Namespace::Value).is_some()
+ });
+ if let (true, false, Some(expr), Some(_)) = (actual.is_numeric(),
+ actual.has_concrete_skeleton(),
+ rcvr_expr,
+ candidates.next()) {
+ let mut err = struct_span_err!(
+ tcx.sess,
+ span,
+ E0689,
+ "can't call {} `{}` on ambiguous numeric type `{}`",
+ type_str,
+ item_name,
+ ty_string
+ );
+ let concrete_type = if actual.is_integral() {
+ "i32"
+ } else {
+ "f32"
+ };
+ match expr.node {
+ hir::ExprLit(_) => { // numeric literal
+ let snippet = tcx.sess.codemap().span_to_snippet(expr.span)
+ .unwrap_or("<numeric literal>".to_string());
+ // FIXME: use the literal for missing snippet
+
+ err.span_suggestion(expr.span,
+ &format!("you must specify a concrete type for \
+ this numeric value, like `{}`",
+ concrete_type),
+ format!("{}_{}",
+ snippet,
+ concrete_type));
+ }
+ hir::ExprPath(ref qpath) => { // local binding
+ if let &hir::QPath::Resolved(_, ref path) = &qpath {
+ if let hir::def::Def::Local(node_id) = path.def {
+ let span = tcx.hir.span(node_id);
+ let snippet = tcx.sess.codemap().span_to_snippet(span)
+ .unwrap();
+ err.span_suggestion(span,
+ &format!("you must specify a type for \
+ this binding, like `{}`",
+ concrete_type),
+ format!("{}: {}",
+ snippet,
+ concrete_type));
+ }
+ }
+ }
+ _ => {}
+ }
+ err.emit();
+ return;
+ } else {
+ struct_span_err!(
+ tcx.sess,
+ span,
+ E0599,
+ "no {} named `{}` found for type `{}` in the current scope",
+ type_str,
+ item_name,
+ ty_string
+ )
+ }
} else {
tcx.sess.diagnostic().struct_dummy()
};
for (ty, _) in self.autoderef(span, rcvr_ty) {
match ty.sty {
ty::TyAdt(def, substs) if !def.is_enum() => {
- if let Some(field) = def.struct_variant()
+ if let Some(field) = def.non_enum_variant()
.find_field_named(item_name) {
let snippet = tcx.sess.codemap().span_to_snippet(expr.span);
let expr_string = match snippet {
bound_list));
}
- self.suggest_traits_to_import(&mut err,
- span,
- rcvr_ty,
- item_name,
- rcvr_expr,
- out_of_scope_traits);
+ if actual.is_numeric() && actual.is_fresh() {
+
+ } else {
+ self.suggest_traits_to_import(&mut err,
+ span,
+ rcvr_ty,
+ item_name,
+ rcvr_expr,
+ out_of_scope_traits);
+ }
if let Some(lev_candidate) = lev_candidate {
err.help(&format!("did you mean `{}`?", lev_candidate.name));
let t = tcx.type_of(def_id);
match t.sty {
ty::TyAdt(def, substs) if def.is_struct() => {
- let fields = &def.struct_variant().fields;
+ let fields = &def.non_enum_variant().fields;
if fields.is_empty() {
span_err!(tcx.sess, sp, E0075, "SIMD vector cannot be empty");
return;
}
// push struct def_id before checking fields
stack.push(def_id);
- for field in &def.struct_variant().fields {
+ for field in &def.non_enum_variant().fields {
let f = field.ty(tcx, substs);
match f.sty {
ty::TyAdt(def, _) => {
adjusted_ty,
index_ty);
- // First, try built-in indexing.
- match (adjusted_ty.builtin_index(), &index_ty.sty) {
- (Some(ty), &ty::TyUint(ast::UintTy::Us)) | (Some(ty), &ty::TyInfer(ty::IntVar(_))) => {
- debug!("try_index_step: success, using built-in indexing");
- let adjustments = autoderef.adjust_steps(lvalue_pref);
- self.apply_adjustments(base_expr, adjustments);
- return Some((self.tcx.types.usize, ty));
- }
- _ => {}
- }
-
for &unsize in &[false, true] {
let mut self_ty = adjusted_ty;
if unsize {
debug!("struct named {:?}", base_t);
let (ident, def_scope) =
self.tcx.adjust(field.node, base_def.did, self.body_id);
- let fields = &base_def.struct_variant().fields;
+ let fields = &base_def.non_enum_variant().fields;
if let Some(field) = fields.iter().find(|f| f.name.to_ident() == ident) {
let field_ty = self.field_ty(expr.span, field, substs);
if field.vis.is_accessible_from(def_scope, self.tcx) {
match expr_t.sty {
ty::TyAdt(def, _) if !def.is_enum() => {
if let Some(suggested_field_name) =
- Self::suggest_field_name(def.struct_variant(), field, vec![]) {
+ Self::suggest_field_name(def.non_enum_variant(), field, vec![]) {
err.span_label(field.span,
format!("did you mean `{}`?", suggested_field_name));
} else {
err.span_label(field.span, "unknown field");
- let struct_variant_def = def.struct_variant();
+ let struct_variant_def = def.non_enum_variant();
let field_names = self.available_field_names(struct_variant_def);
if !field_names.is_empty() {
err.note(&format!("available fields are: {}",
while let Some((base_t, _)) = autoderef.next() {
let field = match base_t.sty {
ty::TyAdt(base_def, substs) if base_def.is_struct() => {
- tuple_like = base_def.struct_variant().ctor_kind == CtorKind::Fn;
+ tuple_like = base_def.non_enum_variant().ctor_kind == CtorKind::Fn;
if !tuple_like { continue }
debug!("tuple struct named {:?}", base_t);
};
let (ident, def_scope) =
self.tcx.adjust_ident(ident, base_def.did, self.body_id);
- let fields = &base_def.struct_variant().fields;
+ let fields = &base_def.non_enum_variant().fields;
if let Some(field) = fields.iter().find(|f| f.name.to_ident() == ident) {
let field_ty = self.field_ty(expr.span, field, substs);
if field.vis.is_accessible_from(def_scope, self.tcx) {
Def::AssociatedTy(..) | Def::SelfTy(..) => {
match ty.sty {
ty::TyAdt(adt, substs) if !adt.is_enum() => {
- Some((adt.struct_variant(), adt.did, substs))
+ Some((adt.non_enum_variant(), adt.did, substs))
}
_ => None,
}
self.check_expr_has_type_or_error(base_expr, struct_ty);
match struct_ty.sty {
ty::TyAdt(adt, substs) if adt.is_struct() => {
- let fru_field_types = adt.struct_variant().fields.iter().map(|f| {
+ let fru_field_types = adt.non_enum_variant().fields.iter().map(|f| {
self.normalize_associated_types_in(expr.span, &f.ty(self.tcx, substs))
}).collect();
//
// won't be allowed unless there's an *explicit* implementation of `Send`
// for `T`
- hir::ItemImpl(_, hir::ImplPolarity::Positive, _, _,
- ref trait_ref, ref self_ty, _) => {
- self.check_impl(item, self_ty, trait_ref);
- }
- hir::ItemImpl(_, hir::ImplPolarity::Negative, _, _, Some(_), ..) => {
- // FIXME(#27579) what amount of WF checking do we need for neg impls?
-
- let trait_ref = tcx.impl_trait_ref(tcx.hir.local_def_id(item.id)).unwrap();
- if !tcx.trait_is_auto(trait_ref.def_id) {
- error_192(tcx, item.span);
+ hir::ItemImpl(_, polarity, defaultness, _, ref trait_ref, ref self_ty, _) => {
+ let is_auto = tcx.impl_trait_ref(tcx.hir.local_def_id(item.id))
+ .map_or(false, |trait_ref| tcx.trait_is_auto(trait_ref.def_id));
+ if let (hir::Defaultness::Default { .. }, true) = (defaultness, is_auto) {
+ tcx.sess.span_err(item.span, "impls of auto traits cannot be default");
+ }
+ if polarity == hir::ImplPolarity::Positive {
+ self.check_impl(item, self_ty, trait_ref);
+ } else {
+ // FIXME(#27579) what amount of WF checking do we need for neg impls?
+ if trait_ref.is_some() && !is_auto {
+ span_err!(tcx.sess, item.span, E0192,
+ "negative impls are only allowed for \
+ auto traits (e.g., `Send` and `Sync`)")
+ }
}
}
hir::ItemFn(..) => {
}
hir::ItemStruct(ref struct_def, ref ast_generics) => {
self.check_type_defn(item, false, |fcx| {
- vec![fcx.struct_variant(struct_def)]
+ vec![fcx.non_enum_variant(struct_def)]
});
self.check_variances_for_type_defn(item, ast_generics);
}
hir::ItemUnion(ref struct_def, ref ast_generics) => {
self.check_type_defn(item, true, |fcx| {
- vec![fcx.struct_variant(struct_def)]
+ vec![fcx.non_enum_variant(struct_def)]
});
self.check_variances_for_type_defn(item, ast_generics);
});
}
- fn check_auto_trait(&mut self, trait_def_id: DefId, span: Span) {
- // We want to ensure:
- //
- // 1) that there are no items contained within
- // the trait definition
- //
- // 2) that the definition doesn't violate the no-super trait rule
- // for auto traits.
- //
- // 3) that the trait definition does not have any type parameters
-
- let predicates = self.tcx.predicates_of(trait_def_id);
-
- // We must exclude the Self : Trait predicate contained by all
- // traits.
- let has_predicates =
- predicates.predicates.iter().any(|predicate| {
- match predicate {
- &ty::Predicate::Trait(ref poly_trait_ref) => {
- let self_ty = poly_trait_ref.0.self_ty();
- !(self_ty.is_self() && poly_trait_ref.def_id() == trait_def_id)
- },
- _ => true,
- }
- });
-
- let has_ty_params = self.tcx.generics_of(trait_def_id).types.len() > 1;
-
- // We use an if-else here, since the generics will also trigger
- // an extraneous error message when we find predicates like
- // `T : Sized` for a trait like: `trait Magic<T>`.
- //
- // We also put the check on the number of items here,
- // as it seems confusing to report an error about
- // extraneous predicates created by things like
- // an associated type inside the trait.
- let mut err = None;
- if !self.tcx.associated_item_def_ids(trait_def_id).is_empty() {
- error_380(self.tcx, span);
- } else if has_ty_params {
- err = Some(struct_span_err!(self.tcx.sess, span, E0567,
- "traits with auto impls (`e.g. impl \
- Trait for ..`) can not have type parameters"));
- } else if has_predicates {
- err = Some(struct_span_err!(self.tcx.sess, span, E0568,
- "traits with auto impls (`e.g. impl \
- Trait for ..`) cannot have predicates"));
- }
-
- // Finally if either of the above conditions apply we should add a note
- // indicating that this error is the result of a recent soundness fix.
- match err {
- None => {},
- Some(mut e) => {
- e.note("the new auto trait rules are the result of a \
- recent soundness fix; see #29859 for more details");
- e.emit();
- }
- }
- }
-
fn check_trait(&mut self, item: &hir::Item) {
let trait_def_id = self.tcx.hir.local_def_id(item.id);
-
- if self.tcx.trait_is_auto(trait_def_id) {
- self.check_auto_trait(trait_def_id, item.span);
- }
-
self.for_item(item).with_fcx(|fcx, this| {
let predicates = fcx.tcx.predicates_of(trait_def_id).instantiate_identity(fcx.tcx);
let predicates = fcx.normalize_associated_types_in(item.span, &predicates);
}
impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
- fn struct_variant(&self, struct_def: &hir::VariantData) -> AdtVariant<'tcx> {
+ fn non_enum_variant(&self, struct_def: &hir::VariantData) -> AdtVariant<'tcx> {
let fields =
struct_def.fields().iter()
.map(|field| {
fn enum_variants(&self, enum_def: &hir::EnumDef) -> Vec<AdtVariant<'tcx>> {
enum_def.variants.iter()
- .map(|variant| self.struct_variant(&variant.node.data))
+ .map(|variant| self.non_enum_variant(&variant.node.data))
.collect()
}
}
}
-fn error_192(tcx: TyCtxt, span: Span) {
- span_err!(tcx.sess, span, E0192,
- "negative impls are only allowed for traits with \
- default impls (e.g., `Send` and `Sync`)")
-}
-
-fn error_380(tcx: TyCtxt, span: Span) {
- span_err!(tcx.sess, span, E0380,
- "traits with default impls (`e.g. impl \
- Trait for ..`) must have no methods or associated items")
-}
-
fn error_392<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, span: Span, param_name: ast::Name)
-> DiagnosticBuilder<'tcx> {
let mut err = struct_span_err!(tcx.sess, span, E0392,
use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor};
use rustc::infer::InferCtxt;
use rustc::ty::{self, Ty, TyCtxt};
+use rustc::ty::adjustment::{Adjust, Adjustment};
use rustc::ty::fold::{TypeFoldable, TypeFolder};
use rustc::util::nodemap::DefIdSet;
use syntax::ast;
_ => {}
}
}
+
+ // Similar to operators, indexing is always assumed to be overloaded
+ // Here, correct cases where an indexing expression can be simplified
+ // to use builtin indexing because the index type is known to be
+ // usize-ish
+ fn fix_index_builtin_expr(&mut self, e: &hir::Expr) {
+ if let hir::ExprIndex(ref base, ref index) = e.node {
+ let mut tables = self.fcx.tables.borrow_mut();
+
+ match tables.expr_ty_adjusted(&base).sty {
+ // All valid indexing looks like this
+ ty::TyRef(_, ty::TypeAndMut { ty: ref base_ty, .. }) => {
+ let index_ty = tables.expr_ty_adjusted(&index);
+ let index_ty = self.fcx.resolve_type_vars_if_possible(&index_ty);
+
+ if base_ty.builtin_index().is_some()
+ && index_ty == self.fcx.tcx.types.usize {
+ // Remove the method call record
+ tables.type_dependent_defs_mut().remove(e.hir_id);
+ tables.node_substs_mut().remove(e.hir_id);
+
+ tables.adjustments_mut().get_mut(base.hir_id).map(|a| {
+ // Discard the need for a mutable borrow
+ match a.pop() {
+ // Extra adjustment made when indexing causes a drop
+ // of size information - we need to get rid of it
+ // Since this is "after" the other adjustment to be
+ // discarded, we do an extra `pop()`
+ Some(Adjustment { kind: Adjust::Unsize, .. }) => {
+ // So the borrow discard actually happens here
+ a.pop();
+ },
+ _ => {}
+ }
+ });
+ }
+ },
+ // Might encounter non-valid indexes at this point, so there
+ // has to be a fall-through
+ _ => {},
+ }
+ }
+ }
}
+
///////////////////////////////////////////////////////////////////////////
// Impl of Visitor for Resolver
//
fn visit_expr(&mut self, e: &'gcx hir::Expr) {
self.fix_scalar_builtin_expr(e);
+ self.fix_index_builtin_expr(e);
self.visit_node_id(e.span, e.hir_id);
// conversion). This will work out because `U:
// Unsize<V>`, and we have a builtin rule that `*mut
// U` can be coerced to `*mut V` if `U: Unsize<V>`.
- let fields = &def_a.struct_variant().fields;
+ let fields = &def_a.non_enum_variant().fields;
let diff_fields = fields.iter()
.enumerate()
.filter_map(|(i, f)| {
impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for InherentCollect<'a, 'tcx> {
fn visit_item(&mut self, item: &hir::Item) {
- let (unsafety, ty) = match item.node {
- hir::ItemImpl(unsafety, .., None, ref ty, _) => (unsafety, ty),
+ let ty = match item.node {
+ hir::ItemImpl(.., None, ref ty, _) => ty,
_ => return
};
- match unsafety {
- hir::Unsafety::Normal => {
- // OK
- }
- hir::Unsafety::Unsafe => {
- span_err!(self.tcx.sess,
- item.span,
- E0197,
- "inherent impls cannot be declared as unsafe");
- }
- }
-
let def_id = self.tcx.hir.local_def_id(item.id);
let self_ty = self.tcx.type_of(def_id);
let lang_items = self.tcx.lang_items();
"i128",
item.span);
}
- ty::TyInt(ast::IntTy::Is) => {
+ ty::TyInt(ast::IntTy::Isize) => {
self.check_primitive_impl(def_id,
lang_items.isize_impl(),
"isize",
"u128",
item.span);
}
- ty::TyUint(ast::UintTy::Us) => {
+ ty::TyUint(ast::UintTy::Usize) => {
self.check_primitive_impl(def_id,
lang_items.usize_impl(),
"usize",
// mappings. That mapping code resides here.
use hir::def_id::{DefId, LOCAL_CRATE};
+use rustc::traits;
use rustc::ty::{self, TyCtxt, TypeFoldable};
use rustc::ty::maps::Providers;
mod inherent_impls;
mod inherent_impls_overlap;
mod orphan;
-mod overlap;
mod unsafety;
fn check_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, node_id: ast::NodeId) {
check_impl(tcx, impl_id);
}
for &impl_id in impls {
- overlap::check_impl(tcx, impl_id);
+ check_impl_overlap(tcx, impl_id);
}
builtin::check_trait(tcx, def_id);
}
unsafety::check(tcx);
orphan::check(tcx);
- overlap::check_auto_impls(tcx);
// these queries are executed for side-effects (error reporting):
ty::maps::queries::crate_inherent_impls::ensure(tcx, LOCAL_CRATE);
ty::maps::queries::crate_inherent_impls_overlap_check::ensure(tcx, LOCAL_CRATE);
}
+
+/// Overlap: No two impls for the same trait are implemented for the
+/// same type. Likewise, no two inherent impls for a given type
+/// constructor provide a method with the same name.
+fn check_impl_overlap<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, node_id: ast::NodeId) {
+ let impl_def_id = tcx.hir.local_def_id(node_id);
+ let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap();
+ let trait_def_id = trait_ref.def_id;
+
+ if trait_ref.references_error() {
+ debug!("coherence: skipping impl {:?} with error {:?}",
+ impl_def_id, trait_ref);
+ return
+ }
+
+ // Trigger building the specialization graph for the trait of this impl.
+ // This will detect any overlap errors.
+ tcx.specialization_graph_of(trait_def_id);
+
+ // check for overlap with the automatic `impl Trait for Trait`
+ if let ty::TyDynamic(ref data, ..) = trait_ref.self_ty().sty {
+ // This is something like impl Trait1 for Trait2. Illegal
+ // if Trait1 is a supertrait of Trait2 or Trait2 is not object safe.
+
+ if data.principal().map_or(true, |p| !tcx.is_object_safe(p.def_id())) {
+ // This is an error, but it will be reported by wfcheck. Ignore it here.
+ // This is tested by `coherence-impl-trait-for-trait-object-safe.rs`.
+ } else {
+ let mut supertrait_def_ids =
+ traits::supertrait_def_ids(tcx,
+ data.principal().unwrap().def_id());
+ if supertrait_def_ids.any(|d| d == trait_def_id) {
+ span_err!(tcx.sess,
+ tcx.span_of_impl(impl_def_id).unwrap(),
+ E0371,
+ "the object type `{}` automatically \
+ implements the trait `{}`",
+ trait_ref.self_ty(),
+ tcx.item_path_str(trait_def_id));
+ }
+ }
+ }
+}
}
}
- // In addition to the above rules, we restrict impls of defaulted traits
+ // In addition to the above rules, we restrict impls of auto traits
// so that they can only be implemented on nominal types, such as structs,
// enums or foreign types. To see why this restriction exists, consider the
- // following example (#22978). Imagine that crate A defines a defaulted trait
+ // following example (#22978). Imagine that crate A defines an auto trait
// `Foo` and a fn that operates on pairs of types:
//
// ```
// // Crate A
- // trait Foo { }
- // impl Foo for .. { }
+ // auto trait Foo { }
// fn two_foos<A:Foo,B:Foo>(..) {
// one_foo::<(A,B)>(..)
// }
}
}
}
- hir::ItemAutoImpl(_, ref item_trait_ref) => {
- // "Trait" impl
- debug!("coherence2::orphan check: default trait impl {}",
- self.tcx.hir.node_to_string(item.id));
- let trait_ref = self.tcx.impl_trait_ref(def_id).unwrap();
- if !trait_ref.def_id.is_local() {
- struct_span_err!(self.tcx.sess,
- item_trait_ref.path.span,
- E0318,
- "cannot create default implementations for traits outside \
- the crate they're defined in; define a new trait instead")
- .span_label(item_trait_ref.path.span,
- format!("`{}` trait not defined in this crate",
- self.tcx.hir.node_to_pretty_string(item_trait_ref.ref_id)))
- .emit();
- return;
- }
- }
_ => {
// Not an impl
}
+++ /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.
-
-//! Overlap: No two impls for the same trait are implemented for the
-//! same type. Likewise, no two inherent impls for a given type
-//! constructor provide a method with the same name.
-
-use rustc::traits;
-use rustc::ty::{self, TyCtxt, TypeFoldable};
-use syntax::ast;
-use rustc::hir;
-use rustc::hir::itemlikevisit::ItemLikeVisitor;
-
-pub fn check_auto_impls<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
- let mut overlap = OverlapChecker { tcx };
-
- // this secondary walk specifically checks for some other cases,
- // like defaulted traits, for which additional overlap rules exist
- tcx.hir.krate().visit_all_item_likes(&mut overlap);
-}
-
-pub fn check_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, node_id: ast::NodeId) {
- let impl_def_id = tcx.hir.local_def_id(node_id);
- let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap();
- let trait_def_id = trait_ref.def_id;
-
- if trait_ref.references_error() {
- debug!("coherence: skipping impl {:?} with error {:?}",
- impl_def_id, trait_ref);
- return
- }
-
- // Trigger building the specialization graph for the trait of this impl.
- // This will detect any overlap errors.
- tcx.specialization_graph_of(trait_def_id);
-
-
- // check for overlap with the automatic `impl Trait for Trait`
- if let ty::TyDynamic(ref data, ..) = trait_ref.self_ty().sty {
- // This is something like impl Trait1 for Trait2. Illegal
- // if Trait1 is a supertrait of Trait2 or Trait2 is not object safe.
-
- if data.principal().map_or(true, |p| !tcx.is_object_safe(p.def_id())) {
- // This is an error, but it will be reported by wfcheck. Ignore it here.
- // This is tested by `coherence-impl-trait-for-trait-object-safe.rs`.
- } else {
- let mut supertrait_def_ids =
- traits::supertrait_def_ids(tcx,
- data.principal().unwrap().def_id());
- if supertrait_def_ids.any(|d| d == trait_def_id) {
- span_err!(tcx.sess,
- tcx.span_of_impl(impl_def_id).unwrap(),
- E0371,
- "the object type `{}` automatically \
- implements the trait `{}`",
- trait_ref.self_ty(),
- tcx.item_path_str(trait_def_id));
- }
- }
- }
-}
-
-struct OverlapChecker<'cx, 'tcx: 'cx> {
- tcx: TyCtxt<'cx, 'tcx, 'tcx>,
-}
-
-impl<'cx, 'tcx, 'v> ItemLikeVisitor<'v> for OverlapChecker<'cx, 'tcx> {
- fn visit_item(&mut self, item: &'v hir::Item) {
- match item.node {
- hir::ItemAutoImpl(..) => {
- // look for another auto impl; note that due to the
- // general orphan/coherence rules, it must always be
- // in this crate.
- let impl_def_id = self.tcx.hir.local_def_id(item.id);
- let trait_ref = self.tcx.impl_trait_ref(impl_def_id).unwrap();
-
- let prev_id = self.tcx.hir.trait_auto_impl(trait_ref.def_id).unwrap();
- if prev_id != item.id {
- let mut err = struct_span_err!(self.tcx.sess,
- self.tcx.span_of_impl(impl_def_id).unwrap(),
- E0521,
- "redundant auto implementations of trait \
- `{}`:",
- trait_ref);
- err.span_note(self.tcx
- .span_of_impl(self.tcx.hir.local_def_id(prev_id))
- .unwrap(),
- "redundant implementation is here:");
- err.emit();
- }
- }
- hir::ItemImpl(.., Some(_), _, _) => {
- }
- _ => {}
- }
- }
-
- fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) {
- }
-
- fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
- }
-}
let trait_def = self.tcx.trait_def(trait_ref.def_id);
let unsafe_attr = impl_generics.and_then(|g| g.carries_unsafe_attr());
match (trait_def.unsafety, unsafe_attr, unsafety, polarity) {
- (_, _, Unsafety::Unsafe, hir::ImplPolarity::Negative) => {
- span_err!(self.tcx.sess,
- item.span,
- E0198,
- "negative implementations are not unsafe");
- }
-
- (Unsafety::Normal, None, Unsafety::Unsafe, _) => {
+ (Unsafety::Normal, None, Unsafety::Unsafe, hir::ImplPolarity::Positive) => {
span_err!(self.tcx.sess,
item.span,
E0199,
g.attr_name());
}
+ (_, _, Unsafety::Unsafe, hir::ImplPolarity::Negative) => {
+ // Reported in AST validation
+ self.tcx.sess.delay_span_bug(item.span, "unsafe negative impl");
+ }
(_, _, Unsafety::Normal, hir::ImplPolarity::Negative) |
(Unsafety::Unsafe, _, Unsafety::Unsafe, hir::ImplPolarity::Positive) |
(Unsafety::Normal, Some(_), Unsafety::Unsafe, hir::ImplPolarity::Positive) |
impl<'cx, 'tcx, 'v> ItemLikeVisitor<'v> for UnsafetyChecker<'cx, 'tcx> {
fn visit_item(&mut self, item: &'v hir::Item) {
match item.node {
- hir::ItemAutoImpl(unsafety, _) => {
- self.check_unsafety_coherence(item, None, unsafety, hir::ImplPolarity::Positive);
- }
hir::ItemImpl(unsafety, polarity, _, ref generics, ..) => {
self.check_unsafety_coherence(item, Some(generics), unsafety, polarity);
}
impl_trait_ref,
impl_polarity,
is_foreign_item,
- is_auto_impl,
..*providers
};
}
tcx.predicates_of(def_id);
convert_enum_variant_types(tcx, def_id, &enum_definition.variants);
},
- hir::ItemAutoImpl(..) => {
- tcx.impl_trait_ref(def_id);
- }
hir::ItemImpl(..) => {
tcx.generics_of(def_id);
tcx.type_of(def_id);
let node_id = tcx.hir.as_local_node_id(def_id).unwrap();
let item = tcx.hir.expect_item(node_id);
- let unsafety = match item.node {
- hir::ItemTrait(_, unsafety, ..) => unsafety,
- hir::ItemTraitAlias(..) => hir::Unsafety::Normal,
+ let (is_auto, unsafety) = match item.node {
+ hir::ItemTrait(is_auto, unsafety, ..) => (is_auto == hir::IsAuto::Yes, unsafety),
+ hir::ItemTraitAlias(..) => (false, hir::Unsafety::Normal),
_ => span_bug!(item.span, "trait_def_of_item invoked on non-trait"),
};
}
let def_path_hash = tcx.def_path_hash(def_id);
- let is_auto = match item.node {
- hir::ItemTrait(hir::IsAuto::Yes, ..) => true,
- _ => tcx.hir.trait_is_auto(def_id),
- };
let def = ty::TraitDef::new(def_id,
unsafety,
paren_sugar,
let substs = Substs::identity_for_item(tcx, def_id);
tcx.mk_adt(def, substs)
}
- ItemAutoImpl(..) |
ItemTrait(..) | ItemTraitAlias(..) |
ItemMod(..) |
ItemForeignMod(..) |
let node_id = tcx.hir.as_local_node_id(def_id).unwrap();
match tcx.hir.expect_item(node_id).node {
- hir::ItemAutoImpl(_, ref ast_trait_ref) => {
- Some(AstConv::instantiate_mono_trait_ref(&icx,
- ast_trait_ref,
- tcx.mk_self_type()))
- }
hir::ItemImpl(.., ref opt_trait_ref, _, _) => {
opt_trait_ref.as_ref().map(|ast_trait_ref| {
let selfty = tcx.type_of(def_id);
_ => bug!("is_foreign_item applied to non-local def-id {:?}", def_id)
}
}
-
-fn is_auto_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
- def_id: DefId)
- -> bool {
- match tcx.hir.get_if_local(def_id) {
- Some(hir_map::NodeItem(&hir::Item { node: hir::ItemAutoImpl(..), .. }))
- => true,
- Some(_) => false,
- _ => bug!("is_auto_impl applied to non-local def-id {:?}", def_id)
- }
-}
"##,
E0192: r##"
-Negative impls are only allowed for traits with default impls. For more
+Negative impls are only allowed for auto traits. For more
information see the [opt-in builtin traits RFC][RFC 19].
[RFC 19]: https://github.com/rust-lang/rfcs/blob/master/text/0019-opt-in-builtin-traits.md
```
"##,
-E0197: r##"
-Inherent implementations (one that do not implement a trait but provide
-methods associated with a type) are always safe because they are not
-implementing an unsafe trait. Removing the `unsafe` keyword from the inherent
-implementation will resolve this error.
-
-```compile_fail,E0197
-struct Foo;
-
-// this will cause this error
-unsafe impl Foo { }
-// converting it to this will fix it
-impl Foo { }
-```
-"##,
-
-E0198: r##"
-A negative implementation is one that excludes a type from implementing a
-particular trait. Not being able to use a trait is always a safe operation,
-so negative implementations are always safe and never need to be marked as
-unsafe.
-
-```compile_fail
-#![feature(optin_builtin_traits)]
-
-struct Foo;
-
-// unsafe is unnecessary
-unsafe impl !Clone for Foo { }
-```
-
-This will compile:
-
-```ignore (ignore auto_trait future compatibility warning)
-#![feature(optin_builtin_traits)]
-
-struct Foo;
-
-trait Enterprise {}
-
-impl Enterprise for .. { }
-
-impl !Enterprise for Foo { }
-```
-
-Please note that negative impls are only allowed for traits with default impls.
-"##,
-
E0199: r##"
Safe traits should not have unsafe implementations, therefore marking an
implementation for a safe trait unsafe will cause a compiler error. Removing
```
"##,
-E0318: r##"
-Default impls for a trait must be located in the same crate where the trait was
-defined. For more information see the [opt-in builtin traits RFC][RFC 19].
-
-[RFC 19]: https://github.com/rust-lang/rfcs/blob/master/text/0019-opt-in-builtin-traits.md
-"##,
-
E0321: r##"
A cross-crate opt-out trait was implemented on something which wasn't a struct
or enum type. Erroneous code example:
struct.
"##,
-E0380: r##"
-Default impls are only allowed for traits with no methods or associated items.
-For more information see the [opt-in builtin traits RFC][RFC 19].
-
-[RFC 19]: https://github.com/rust-lang/rfcs/blob/master/text/0019-opt-in-builtin-traits.md
-"##,
-
E0390: r##"
You tried to implement methods for a primitive type. Erroneous code example:
```
"##,
+E0689: r##"
+This error indicates that the numeric value for the method being passed exists
+but the type of the numeric value or binding could not be identified.
+
+The error happens on numeric literals:
+
+```compile_fail,E0689
+2.0.powi(2);
+```
+
+and on numeric bindings without an identified concrete type:
+
+```compile_fail,E0689
+let x = 2.0;
+x.powi(2); // same error as above
+```
+
+Because of this, you must give the numeric literal or binding a type:
+
+```
+let _ = 2.0_f32.powi(2);
+let x: f32 = 2.0;
+let _ = x.powi(2);
+let _ = (2.0 as f32).powi(2);
+```
+"##,
}
register_diagnostics! {
// E0372, // coherence not object safe
E0377, // the trait `CoerceUnsized` may only be implemented for a coercion
// between structures with the same definition
- E0521, // redundant auto implementations of trait
E0533, // `{}` does not name a unit variant, unit struct or a constant
// E0563, // cannot determine a type for this `impl Trait`: {} // removed in 6383de15
E0564, // only named lifetimes are allowed in `impl Trait`,
// but `{}` was found in the type `{}`
- E0567, // auto traits can not have type parameters
- E0568, // auto-traits can not have predicates,
E0587, // struct has conflicting packed and align representation hints
E0588, // packed struct cannot transitively contain a `[repr(align)]` struct
E0592, // duplicate definitions with name `{}`
(principal, projections)
}
+#[cfg(not(stage0))] // remove after the next snapshot
__build_diagnostic_array! { librustc_typeck, DIAGNOSTICS }
[dependencies]
pulldown-cmark = { version = "0.1.0", default-features = false }
-html-diff = "0.0.5"
+html-diff = "0.0.6"
tempdir = "0.3"
[build-dependencies]
ret.extend(build_impls(cx, did));
clean::ForeignTypeItem
}
- // Never inline enum variants but leave them shown as reexports.
+ // Never inline enum variants but leave them shown as re-exports.
Def::Variant(..) => return None,
- // Assume that enum variants and struct types are reexported next to
+ // Assume that enum variants and struct types are re-exported next to
// their constructors.
Def::VariantCtor(..) |
Def::StructCtor(..) => return Some(Vec::new()),
fn build_struct(cx: &DocContext, did: DefId) -> clean::Struct {
let predicates = cx.tcx.predicates_of(did);
- let variant = cx.tcx.adt_def(did).struct_variant();
+ let variant = cx.tcx.adt_def(did).non_enum_variant();
clean::Struct {
struct_type: match variant.ctor_kind {
fn build_union(cx: &DocContext, did: DefId) -> clean::Union {
let predicates = cx.tcx.predicates_of(did);
- let variant = cx.tcx.adt_def(did).struct_variant();
+ let variant = cx.tcx.adt_def(did).non_enum_variant();
clean::Union {
struct_type: doctree::Plain,
}
}
- // If this is an auto impl, then bail out early here
- if tcx.is_auto_impl(did) {
- return ret.push(clean::Item {
- inner: clean::AutoImplItem(clean::AutoImpl {
- // FIXME: this should be decoded
- unsafety: hir::Unsafety::Normal,
- trait_: match associated_trait.as_ref().unwrap().clean(cx) {
- clean::TraitBound(polyt, _) => polyt.trait_,
- clean::RegionBound(..) => unreachable!(),
- },
- }),
- source: tcx.def_span(did).clean(cx),
- name: None,
- attrs,
- visibility: Some(clean::Inherited),
- stability: tcx.lookup_stability(did).clean(cx),
- deprecation: tcx.lookup_deprecation(did).clean(cx),
- def_id: did,
- });
- }
-
let for_ = tcx.type_of(did).clean(cx);
// Only inline impl if the implementing type is
if trait_.def_id() == tcx.lang_items().deref_trait() {
super::build_deref_target_impls(cx, &trait_items, ret);
}
+ if let Some(trait_did) = trait_.def_id() {
+ record_extern_trait(cx, trait_did);
+ }
let provided = trait_.def_id().map(|did| {
tcx.provided_trait_methods(did)
};
fn fill_in(cx: &DocContext, did: DefId, items: &mut Vec<clean::Item>) {
- // If we're reexporting a reexport it may actually reexport something in
+ // If we're re-exporting a re-export it may actually re-export something in
// two namespaces, so the target may be listed twice. Make sure we only
// visit each node at most once.
let mut visited = FxHashSet();
});
(g, ty_bounds)
}
+
+pub fn record_extern_trait(cx: &DocContext, did: DefId) {
+ cx.external_traits.borrow_mut().entry(did).or_insert_with(|| {
+ build_external_trait(cx, did)
+ });
+}
PrimitiveItem(PrimitiveType),
AssociatedConstItem(Type, Option<String>),
AssociatedTypeItem(Vec<TyParamBound>, Option<Type>),
- AutoImplItem(AutoImpl),
/// An item that has been stripped by a rustdoc pass
StrippedItem(Box<ItemEnum>),
}
items.extend(self.traits.iter().map(|x| x.clean(cx)));
items.extend(self.impls.iter().flat_map(|x| x.clean(cx)));
items.extend(self.macros.iter().map(|x| x.clean(cx)));
- items.extend(self.def_traits.iter().map(|x| x.clean(cx)));
// determine if we should display the inner contents or
// the outer `mod` item for the source code.
impl From<ast::IntTy> for PrimitiveType {
fn from(int_ty: ast::IntTy) -> PrimitiveType {
match int_ty {
- ast::IntTy::Is => PrimitiveType::Isize,
+ ast::IntTy::Isize => PrimitiveType::Isize,
ast::IntTy::I8 => PrimitiveType::I8,
ast::IntTy::I16 => PrimitiveType::I16,
ast::IntTy::I32 => PrimitiveType::I32,
impl From<ast::UintTy> for PrimitiveType {
fn from(uint_ty: ast::UintTy) -> PrimitiveType {
match uint_ty {
- ast::UintTy::Us => PrimitiveType::Usize,
+ ast::UintTy::Usize => PrimitiveType::Usize,
ast::UintTy::U8 => PrimitiveType::U8,
ast::UintTy::U16 => PrimitiveType::U16,
ast::UintTy::U32 => PrimitiveType::U32,
}
}
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
-pub struct AutoImpl {
- pub unsafety: hir::Unsafety,
- pub trait_: Type,
-}
-
-impl Clean<Item> for doctree::AutoImpl {
- fn clean(&self, cx: &DocContext) -> Item {
- Item {
- name: None,
- attrs: self.attrs.clean(cx),
- source: self.whence.clean(cx),
- def_id: cx.tcx.hir.local_def_id(self.id),
- visibility: Some(Public),
- stability: None,
- deprecation: None,
- inner: AutoImplItem(AutoImpl {
- unsafety: self.unsafety,
- trait_: self.trait_.clean(cx),
- }),
- }
- }
-}
-
impl Clean<Item> for doctree::ExternCrate {
fn clean(&self, cx: &DocContext) -> Item {
Item {
if did.is_local() { return did }
inline::record_extern_fqn(cx, did, kind);
if let TypeKind::Trait = kind {
- let t = inline::build_external_trait(cx, did);
- cx.external_traits.borrow_mut().insert(did, t);
+ inline::record_extern_trait(cx, did);
}
did
}
pub stab: Option<attr::Stability>,
pub depr: Option<attr::Deprecation>,
pub impls: Vec<Impl>,
- pub def_traits: Vec<AutoImpl>,
pub foreigns: Vec<hir::ForeignMod>,
pub macros: Vec<Macro>,
pub is_crate: bool,
constants : Vec::new(),
traits : Vec::new(),
impls : Vec::new(),
- def_traits : Vec::new(),
foreigns : Vec::new(),
macros : Vec::new(),
is_crate : false,
pub id: ast::NodeId,
}
-pub struct AutoImpl {
- pub unsafety: hir::Unsafety,
- pub trait_: hir::TraitRef,
- pub id: ast::NodeId,
- pub attrs: hir::HirVec<ast::Attribute>,
- pub whence: Span,
-}
-
// For Macro we store the DefId instead of the NodeId, since we also create
// these imported macro_rules (which only have a DUMMY_NODE_ID).
pub struct Macro {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use std::fs::File;
-use std::io::prelude::*;
+use std::fs;
use std::path::Path;
use std::str;
use html::markdown::{Markdown, RenderType};
pub fn load_string<P: AsRef<Path>>(file_path: P) -> Result<String, LoadStringError> {
let file_path = file_path.as_ref();
- let mut contents = vec![];
- let result = File::open(file_path)
- .and_then(|mut f| f.read_to_end(&mut contents));
- if let Err(e) = result {
- eprintln!("error reading `{}`: {}", file_path.display(), e);
- return Err(LoadStringError::ReadFail);
- }
+ let contents = match fs::read(file_path) {
+ Ok(bytes) => bytes,
+ Err(e) => {
+ eprintln!("error reading `{}`: {}", file_path.display(), e);
+ return Err(LoadStringError::ReadFail);
+ }
+ };
match str::from_utf8(&contents) {
Ok(s) => Ok(s.to_string()),
Err(_) => {
clean::PrimitiveItem(..) => ItemType::Primitive,
clean::AssociatedConstItem(..) => ItemType::AssociatedConst,
clean::AssociatedTypeItem(..) => ItemType::AssociatedType,
- clean::AutoImplItem(..) => ItemType::Impl,
clean::ForeignTypeItem => ItemType::ForeignType,
clean::StrippedItem(..) => unreachable!(),
}
<h2>Keyboard Shortcuts</h2>
<dl>
- <dt>?</dt>
+ <dt><kbd>?</kbd></dt>
<dd>Show this help dialog</dd>
- <dt>S</dt>
+ <dt><kbd>S</kbd></dt>
<dd>Focus the search field</dd>
- <dt>↑</dt>
+ <dt><kbd>↑</kbd></dt>
<dd>Move up in search results</dd>
- <dt>↓</dt>
+ <dt><kbd>↓</kbd></dt>
<dd>Move down in search results</dd>
- <dt>↹</dt>
+ <dt><kbd>↹</kbd></dt>
<dd>Switch tab</dd>
- <dt>⏎</dt>
+ <dt><kbd>⏎</kbd></dt>
<dd>Go to active search result</dd>
- <dt style="width:31px;">+ / -</dt>
- <dd>Collapse/expand all sections</dd>
+ <dt><kbd>+</kbd></dt>
+ <dd>Expand all sections</dd>
+ <dt><kbd>-</kbd></dt>
+ <dd>Collapse all sections</dd>
</dl>
</div>
.map(|l| map_line(l).for_code())
.collect::<Vec<&str>>().join("\n");
let krate = krate.as_ref().map(|s| &**s);
- let test = test::make_test(&test, krate, false,
+ let (test, _) = test::make_test(&test, krate, false,
&Default::default());
let channel = if test.contains("#![feature(") {
"&version=nightly"
.map(|l| map_line(l).for_code())
.collect::<Vec<&str>>().join("\n");
let krate = krate.as_ref().map(|s| &**s);
- let test = test::make_test(&test, krate, false,
+ let (test, _) = test::make_test(&test, krate, false,
&Default::default());
let channel = if test.contains("#![feature(") {
"&version=nightly"
Unknown,
}
-/// Metadata about an implementor of a trait.
-pub struct Implementor {
- pub def_id: DefId,
- pub stability: Option<clean::Stability>,
- pub impl_: clean::Impl,
-}
-
-/// Metadata about implementations for a type.
+/// Metadata about implementations for a type or trait.
#[derive(Clone)]
pub struct Impl {
pub impl_item: clean::Item,
/// When rendering traits, it's often useful to be able to list all
/// implementors of the trait, and this mapping is exactly, that: a mapping
/// of trait ids to the list of known implementors of the trait
- pub implementors: FxHashMap<DefId, Vec<Implementor>>,
+ pub implementors: FxHashMap<DefId, Vec<Impl>>,
/// Cache of where external crate documentation can be found.
pub extern_locations: FxHashMap<CrateNum, (String, PathBuf, ExternalLocation)>,
write(cx.dst.join("main.css"),
include_bytes!("static/styles/main.css"))?;
if let Some(ref css) = cx.shared.css_file_extension {
- let mut content = String::new();
- let css = css.as_path();
- let mut f = try_err!(File::open(css), css);
-
- try_err!(f.read_to_string(&mut content), css);
- let css = cx.dst.join("theme.css");
- let css = css.as_path();
- let mut f = try_err!(File::create(css), css);
- try_err!(write!(f, "{}", &content), css);
+ let out = cx.dst.join("theme.css");
+ try_err!(fs::copy(css, out), css);
}
write(cx.dst.join("normalize.css"),
include_bytes!("static/normalize.css"))?;
// there's no need to emit information about it (there's inlining
// going on). If they're in different crates then the crate defining
// the trait will be interested in our implementation.
- if imp.def_id.krate == did.krate { continue }
+ if imp.impl_item.def_id.krate == did.krate { continue }
// If the implementation is from another crate then that crate
// should add it.
- if !imp.def_id.is_local() { continue }
+ if !imp.impl_item.def_id.is_local() { continue }
have_impls = true;
- write!(implementors, "{},", as_json(&imp.impl_.to_string())).unwrap();
+ write!(implementors, "{},", as_json(&imp.inner_impl().to_string())).unwrap();
}
implementors.push_str("];");
/// Writes the entire contents of a string to a destination, not attempting to
/// catch any errors.
fn write(dst: PathBuf, contents: &[u8]) -> Result<(), Error> {
- Ok(try_err!(try_err!(File::create(&dst), &dst).write_all(contents), &dst))
+ Ok(try_err!(fs::write(&dst, contents), &dst))
}
/// Takes a path to a source file and cleans the path to it. This canonicalizes
return Ok(());
}
- let mut contents = Vec::new();
- File::open(&p).and_then(|mut f| f.read_to_end(&mut contents))?;
-
- let contents = str::from_utf8(&contents).unwrap();
+ let contents = fs::read_string(&p)?;
// Remove the utf-8 BOM if any
let contents = if contents.starts_with("\u{feff}") {
&contents[3..]
} else {
- contents
+ &contents[..]
};
// Create the intermediate directories
if !self.masked_crates.contains(&item.def_id.krate) {
if let Some(did) = i.trait_.def_id() {
if i.for_.def_id().map_or(true, |d| !self.masked_crates.contains(&d.krate)) {
- self.implementors.entry(did).or_insert(vec![]).push(Implementor {
- def_id: item.def_id,
- stability: item.stability.clone(),
- impl_: i.clone(),
+ self.implementors.entry(did).or_insert(vec![]).push(Impl {
+ impl_item: item.clone(),
});
}
}
clean::ConstantItem(..) | clean::StaticItem(..) |
clean::UnionItem(..) | clean::ForeignTypeItem
if !self.stripped_mod => {
- // Reexported items mean that the same id can show up twice
+ // Re-exported items mean that the same id can show up twice
// in the rustdoc ast that we're looking at. We know,
- // however, that a reexported item doesn't show up in the
+ // however, that a re-exported item doesn't show up in the
// `public_items` map, so we can skip inserting into the
// paths map if there was already an entry present and we're
// not a public item.
{
// Stripped modules survive the rustdoc passes (i.e. `strip-private`)
// if they contain impls for public types. These modules can also
- // contain items such as publicly reexported structures.
+ // contain items such as publicly re-exported structures.
//
// External crates will provide links to these structures, so
// these modules are recursed into, but not rendered normally
item: &clean::Item, items: &[clean::Item]) -> fmt::Result {
document(w, cx, item)?;
- let mut indices = (0..items.len()).filter(|i| {
- if let clean::AutoImplItem(..) = items[*i].inner {
- return false;
- }
- !items[*i].is_stripped()
- }).collect::<Vec<usize>>();
+ let mut indices = (0..items.len()).filter(|i| !items[*i].is_stripped())
+ .collect::<Vec<usize>>();
// the order of item types in the listing
fn reorder(ty: ItemType) -> u8 {
if cx.shared.sort_modules_alphabetically {
indices.sort_by(|&i1, &i2| cmp(&items[i1], &items[i2], i1, i2));
}
- // This call is to remove reexport duplicates in cases such as:
+ // This call is to remove re-export duplicates in cases such as:
//
// ```
// pub mod foo {
curty = myty;
let (short, name) = match myty.unwrap() {
ItemType::ExternCrate |
- ItemType::Import => ("reexports", "Reexports"),
+ ItemType::Import => ("reexports", "Re-exports"),
ItemType::Module => ("modules", "Modules"),
ItemType::Struct => ("structs", "Structs"),
ItemType::Union => ("unions", "Unions"),
document(w, cx, it)
}
-fn implementor2item<'a>(cache: &'a Cache, imp : &Implementor) -> Option<&'a clean::Item> {
- if let Some(t_did) = imp.impl_.for_.def_id() {
- if let Some(impl_item) = cache.impls.get(&t_did).and_then(|i| i.iter()
- .find(|i| i.impl_item.def_id == imp.def_id))
- {
- let i = &impl_item.impl_item;
- return Some(i);
- }
- }
- None
-}
-
fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
t: &clean::Trait) -> fmt::Result {
let mut bounds = String::new();
// if any Types with the same name but different DefId have been found.
let mut implementor_dups: FxHashMap<&str, (DefId, bool)> = FxHashMap();
for implementor in implementors {
- match implementor.impl_.for_ {
+ match implementor.inner_impl().for_ {
clean::ResolvedPath { ref path, did, is_generic: false, .. } |
clean::BorrowedRef {
type_: box clean::ResolvedPath { ref path, did, is_generic: false, .. },
}
let (local, foreign) = implementors.iter()
- .partition::<Vec<_>, _>(|i| i.impl_.for_.def_id()
+ .partition::<Vec<_>, _>(|i| i.inner_impl().for_.def_id()
.map_or(true, |d| cache.paths.contains_key(&d)));
if !foreign.is_empty() {
")?;
for implementor in foreign {
- if let Some(i) = implementor2item(&cache, implementor) {
- let impl_ = Impl { impl_item: i.clone() };
- let assoc_link = AssocItemLink::GotoSource(
- i.def_id, &implementor.impl_.provided_trait_methods
- );
- render_impl(w, cx, &impl_, assoc_link,
- RenderMode::Normal, i.stable_since(), false)?;
- }
+ let assoc_link = AssocItemLink::GotoSource(
+ implementor.impl_item.def_id, &implementor.inner_impl().provided_trait_methods
+ );
+ render_impl(w, cx, &implementor, assoc_link,
+ RenderMode::Normal, implementor.impl_item.stable_since(), false)?;
}
}
for implementor in local {
write!(w, "<li>")?;
- if let Some(item) = implementor2item(&cache, implementor) {
- if let Some(l) = (Item { cx, item }).src_href() {
- write!(w, "<div class='out-of-band'>")?;
- write!(w, "<a class='srclink' href='{}' title='{}'>[src]</a>",
- l, "goto source code")?;
- write!(w, "</div>")?;
- }
+ if let Some(l) = (Item { cx, item: &implementor.impl_item }).src_href() {
+ write!(w, "<div class='out-of-band'>")?;
+ write!(w, "<a class='srclink' href='{}' title='{}'>[src]</a>",
+ l, "goto source code")?;
+ write!(w, "</div>")?;
}
write!(w, "<code>")?;
// If there's already another implementor that has the same abbridged name, use the
// full path, for example in `std::iter::ExactSizeIterator`
- let use_absolute = match implementor.impl_.for_ {
+ let use_absolute = match implementor.inner_impl().for_ {
clean::ResolvedPath { ref path, is_generic: false, .. } |
clean::BorrowedRef {
type_: box clean::ResolvedPath { ref path, is_generic: false, .. },
} => implementor_dups[path.last_name()].1,
_ => false,
};
- fmt_impl_for_trait_page(&implementor.impl_, w, use_absolute)?;
- for it in &implementor.impl_.items {
+ fmt_impl_for_trait_page(&implementor.inner_impl(), w, use_absolute)?;
+ for it in &implementor.inner_impl().items {
if let clean::TypedefItem(ref tydef, _) = it.inner {
write!(w, "<span class=\"where fmt-newline\"> ")?;
assoc_type(w, it, &vec![], Some(&tydef.type_), AssocItemLink::Anchor(None))?;
if let Some(impls) = c.impls.get(&did) {
for i in impls {
let impl_ = i.inner_impl();
- if impl_.trait_.def_id().and_then(|d| c.traits.get(&d))
- .map_or(false, |t| t.is_spotlight) {
+ if impl_.trait_.def_id().map_or(false, |d| c.traits[&d].is_spotlight) {
if out.is_empty() {
out.push_str(
&format!("<h3 class=\"important\">Important traits for {}</h3>\
}
let traits = &cache().traits;
- let trait_ = i.trait_did().and_then(|did| traits.get(&did));
+ let trait_ = i.trait_did().map(|did| &traits[&did]);
if !show_def_docs {
write!(w, "<span class='docblock autohide'>")?;
if let Some(implementors) = c.implementors.get(&it.def_id) {
let res = implementors.iter()
- .filter(|i| i.impl_.for_.def_id()
- .map_or(false, |d| !c.paths.contains_key(&d)))
+ .filter(|i| i.inner_impl().for_.def_id()
+ .map_or(false, |d| !c.paths.contains_key(&d)))
.filter_map(|i| {
- if let Some(item) = implementor2item(&c, i) {
- match extract_for_impl_name(&item) {
- Some((ref name, ref url)) => {
- Some(format!("<a href=\"#impl-{}\">{}</a>",
- small_url_encode(url),
- Escape(name)))
- }
- _ => None,
+ match extract_for_impl_name(&i.impl_item) {
+ Some((ref name, ref url)) => {
+ Some(format!("<a href=\"#impl-{}\">{}</a>",
+ small_url_encode(url),
+ Escape(name)))
}
- } else {
- None
+ _ => None,
}
})
.collect::<String>();
it.type_() == ItemType::Import) {
sidebar.push_str(&format!("<li><a href=\"#{id}\">{name}</a></li>",
id = "reexports",
- name = "Reexports"));
+ name = "Re-exports"));
}
// ordering taken from item_module, reorder, where it prioritized elements in a certain order
ItemType::Function, ItemType::Typedef, ItemType::Union, ItemType::Impl,
ItemType::TyMethod, ItemType::Method, ItemType::StructField, ItemType::Variant,
ItemType::AssociatedType, ItemType::AssociatedConst, ItemType::ForeignType] {
- if items.iter().any(|it| {
- if let clean::AutoImplItem(..) = it.inner {
- false
- } else {
- !it.is_stripped() && it.type_() == myty
- }
- }) {
+ if items.iter().any(|it| !it.is_stripped() && it.type_() == myty) {
let (short, name) = match myty {
ItemType::ExternCrate |
- ItemType::Import => ("reexports", "Reexports"),
+ ItemType::Import => ("reexports", "Re-exports"),
ItemType::Module => ("modules", "Modules"),
ItemType::Struct => ("structs", "Structs"),
ItemType::Union => ("unions", "Unions"),
match *clean_type {
clean::ResolvedPath { ref path, .. } => {
let segments = &path.segments;
- Some(segments[segments.len() - 1].name.clone())
+ let path_segment = segments.into_iter().last().unwrap_or_else(|| panic!(
+ "get_index_type_name(clean_type: {:?}, accept_generic: {:?}) had length zero path",
+ clean_type, accept_generic
+ ));
+ Some(path_segment.name.clone())
}
clean::Generic(ref s) if accept_generic => Some(s.clone()),
clean::Primitive(ref p) => Some(format!("{:?}", p)),
* This code is an unmodified version of the code written by Marco de Wit
* and was found at http://stackoverflow.com/a/18514751/745719
*/
- var levenshtein = (function() {
- var row2 = [];
- return function(s1, s2) {
- if (s1 === s2) {
- return 0;
+ var levenshtein_row2 = [];
+ function levenshtein(s1, s2) {
+ if (s1 === s2) {
+ return 0;
+ }
+ var s1_len = s1.length, s2_len = s2.length;
+ if (s1_len && s2_len) {
+ var i1 = 0, i2 = 0, a, b, c, c2, row = levenshtein_row2;
+ while (i1 < s1_len) {
+ row[i1] = ++i1;
}
- var s1_len = s1.length, s2_len = s2.length;
- if (s1_len && s2_len) {
- var i1 = 0, i2 = 0, a, b, c, c2, row = row2;
- while (i1 < s1_len) {
- row[i1] = ++i1;
- }
- while (i2 < s2_len) {
- c2 = s2.charCodeAt(i2);
- a = i2;
- ++i2;
- b = i2;
- for (i1 = 0; i1 < s1_len; ++i1) {
- c = a + (s1.charCodeAt(i1) !== c2 ? 1 : 0);
- a = row[i1];
- b = b < a ? (b < c ? b + 1 : c) : (a < c ? a + 1 : c);
- row[i1] = b;
- }
+ while (i2 < s2_len) {
+ c2 = s2.charCodeAt(i2);
+ a = i2;
+ ++i2;
+ b = i2;
+ for (i1 = 0; i1 < s1_len; ++i1) {
+ c = a + (s1.charCodeAt(i1) !== c2 ? 1 : 0);
+ a = row[i1];
+ b = b < a ? (b < c ? b + 1 : c) : (a < c ? a + 1 : c);
+ row[i1] = b;
}
- return b;
}
- return s1_len + s2_len;
- };
- })();
+ return b;
+ }
+ return s1_len + s2_len;
+ }
function initSearch(rawSearchIndex) {
var currentResults, index, searchIndex;
/**
* Executes the query and builds an index of results
* @param {[Object]} query [The user query]
- * @param {[type]} max [The maximum results returned]
* @param {[type]} searchWords [The list of search words to query
* against]
* @return {[type]} [A search index of results]
*/
- function execQuery(query, max, searchWords) {
+ function execQuery(query, searchWords) {
+ function itemTypeFromName(typename) {
+ for (var i = 0; i < itemTypes.length; ++i) {
+ if (itemTypes[i] === typename) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
var valLower = query.query.toLowerCase(),
val = valLower,
typeFilter = itemTypeFromName(query.type),
return true;
}
- function getQuery() {
- var matches, type, query, raw =
- document.getElementsByClassName('search-input')[0].value;
+ function getQuery(raw) {
+ var matches, type, query;
query = raw;
matches = query.match(/^(fn|mod|struct|enum|trait|type|const|macro)\s*:\s*/i);
e.preventDefault();
} else if (e.which === 16) { // shift
// Does nothing, it's just to avoid losing "focus" on the highlighted element.
+ } else if (e.which === 27) { // escape
+ removeClass(actives[currentTab][0], 'highlighted');
+ document.getElementsByClassName('search-input')[0].value = '';
+ defocusSearchBar();
} else if (actives[currentTab].length > 0) {
removeClass(actives[currentTab][0], 'highlighted');
}
}
function showResults(results) {
- var output, query = getQuery();
+ var output, query = getQuery(document.getElementsByClassName('search-input')[0].value);
currentResults = query.id;
output = '<h1>Results for ' + escape(query.query) +
resultIndex;
var params = getQueryStringParams();
- query = getQuery();
+ query = getQuery(document.getElementsByClassName('search-input')[0].value);
if (e) {
e.preventDefault();
}
}
}
- results = execQuery(query, 20000, index);
+ results = execQuery(query, index);
showResults(results);
}
- function itemTypeFromName(typename) {
- for (var i = 0; i < itemTypes.length; ++i) {
- if (itemTypes[i] === typename) {
- return i;
- }
- }
- return -1;
- }
-
function buildIndex(rawSearchIndex) {
searchIndex = [];
var searchWords = [];
flex: 0 0 auto;
box-shadow: 0 0 6px rgba(0,0,0,.2);
width: 550px;
- height: 354px;
+ height: auto;
border: 1px solid;
}
#help dt {
float: left;
- border-radius: 4px;
- border: 1px solid;
- width: 23px;
- text-align: center;
clear: left;
display: block;
- margin-top: -1px;
}
#help dd { margin: 5px 35px; }
#help .infos { padding-left: 0; }
left: -42px;
margin-top: 2px;
}
+
+kbd {
+ display: inline-block;
+ padding: 3px 5px;
+ font: 15px "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace;
+ line-height: 10px;
+ vertical-align: middle;
+ border: solid 1px;
+ border-radius: 3px;
+ box-shadow: inset 0 -1px 0;
+}
border-color: #bfbfbf;
}
-#help dt {
- border-color: #bfbfbf;
- background: #fff;
-}
-
.since {
color: grey;
}
border-bottom-color: #e0e0e0;
}
}
+
+kbd {
+ color: #444d56;
+ background-color: #fafbfc;
+ border-color: #d1d5da;
+ border-bottom-color: #c6cbd1;
+ box-shadow-color: #c6cbd1;
+}
#![feature(rustc_private)]
#![feature(box_patterns)]
#![feature(box_syntax)]
+#![feature(fs_read_write)]
#![feature(libc)]
#![feature(set_stdio)]
#![feature(slice_patterns)]
or `#![doc(html_playground_url=...)]`",
"URL")
}),
- unstable("enable-commonmark", |o| {
- o.optflag("", "enable-commonmark", "to enable commonmark doc rendering/testing")
+ unstable("disable-commonmark", |o| {
+ o.optflag("", "disable-commonmark", "to disable commonmark doc rendering/testing")
}),
unstable("display-warnings", |o| {
o.optflag("", "display-warnings", "to print code warnings when testing doc")
let css_file_extension = matches.opt_str("e").map(|s| PathBuf::from(&s));
let cfgs = matches.opt_strs("cfg");
- let render_type = if matches.opt_present("enable-commonmark") {
- RenderType::Pulldown
- } else {
+ let render_type = if matches.opt_present("disable-commonmark") {
RenderType::Hoedown
+ } else {
+ RenderType::Pulldown
};
if let Some(ref p) = css_file_extension {
// handled in the `strip-priv-imports` pass
clean::ExternCrateItem(..) | clean::ImportItem(..) => {}
- clean::AutoImplItem(..) | clean::ImplItem(..) => {}
+ clean::ImplItem(..) => {}
// tymethods/macros have no control over privacy
clean::MacroItem(..) | clean::TyMethodItem(..) => {}
opts
}
-fn run_test(test: &str, cratename: &str, filename: &FileName, cfgs: Vec<String>, libs: SearchPaths,
+fn run_test(test: &str, cratename: &str, filename: &FileName, line: usize,
+ cfgs: Vec<String>, libs: SearchPaths,
externs: Externs,
should_panic: bool, no_run: bool, as_test_harness: bool,
compile_fail: bool, mut error_codes: Vec<String>, opts: &TestOptions,
linker: Option<PathBuf>) {
// the test harness wants its own `main` & top level functions, so
// never wrap the test in `fn main() { ... }`
- let test = make_test(test, Some(cratename), as_test_harness, opts);
+ let (test, line_offset) = make_test(test, Some(cratename), as_test_harness, opts);
// FIXME(#44940): if doctests ever support path remapping, then this filename
// needs to be the result of CodeMap::span_to_unmapped_path
let input = config::Input::Str {
}
}
let data = Arc::new(Mutex::new(Vec::new()));
- let codemap = Rc::new(CodeMap::new(sessopts.file_path_mapping()));
+ let codemap = Rc::new(CodeMap::new_doctest(
+ sessopts.file_path_mapping(), filename.clone(), line as isize - line_offset as isize
+ ));
let emitter = errors::emitter::EmitterWriter::new(box Sink(data.clone()),
Some(codemap.clone()),
false);
}
}
+/// Makes the test file. Also returns the number of lines before the code begins
pub fn make_test(s: &str,
cratename: Option<&str>,
dont_insert_main: bool,
opts: &TestOptions)
- -> String {
+ -> (String, usize) {
let (crate_attrs, everything_else) = partition_source(s);
-
+ let mut line_offset = 0;
let mut prog = String::new();
if opts.attrs.is_empty() {
// commonly used to make tests fail in case they trigger warnings, so having this there in
// that case may cause some tests to pass when they shouldn't have.
prog.push_str("#![allow(unused)]\n");
+ line_offset += 1;
}
// Next, any attributes that came from the crate root via #![doc(test(attr(...)))].
for attr in &opts.attrs {
prog.push_str(&format!("#![{}]\n", attr));
+ line_offset += 1;
}
// Now push any outer attributes from the example, assuming they
if let Some(cratename) = cratename {
if s.contains(cratename) {
prog.push_str(&format!("extern crate {};\n", cratename));
+ line_offset += 1;
}
}
}
prog.push_str(&everything_else);
} else {
prog.push_str("fn main() {\n");
+ line_offset += 1;
prog.push_str(&everything_else);
prog = prog.trim().into();
prog.push_str("\n}");
info!("final test program: {}", prog);
- prog
+ (prog, line_offset)
}
// FIXME(aburka): use a real parser to deal with multiline attributes
run_test(&test,
&cratename,
&filename,
+ line,
cfgs,
libs,
externs,
use rustc::hir::def_id::{DefId, LOCAL_CRATE};
use rustc::middle::cstore::{LoadedMacro, CrateStore};
use rustc::middle::privacy::AccessLevel;
+use rustc::ty::Visibility;
use rustc::util::nodemap::FxHashSet;
use rustc::hir;
impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
pub fn new(cstore: &'tcx CrateStore,
cx: &'a core::DocContext<'a, 'tcx>) -> RustdocVisitor<'a, 'tcx> {
- // If the root is reexported, terminate all recursion.
+ // If the root is re-exported, terminate all recursion.
let mut stack = FxHashSet();
stack.insert(ast::CRATE_NODE_ID);
RustdocVisitor {
self.inside_public_path = orig_inside_public_path;
let def_id = self.cx.tcx.hir.local_def_id(id);
if let Some(exports) = self.cx.tcx.module_exports(def_id) {
- for export in exports.iter() {
+ for export in exports.iter().filter(|e| e.vis == Visibility::Public) {
if let Def::Macro(def_id, ..) = export.def {
if def_id.krate == LOCAL_CRATE || self.reexported_macros.contains(&def_id) {
continue // These are `krate.exported_macros`, handled in `self.visit()`.
let imported_from = self.cx.tcx.original_crate_name(def_id.krate);
let def = match self.cstore.load_macro_untracked(def_id, self.cx.sess()) {
LoadedMacro::MacroDef(macro_def) => macro_def,
- // FIXME(jseyfried): document proc macro reexports
+ // FIXME(jseyfried): document proc macro re-exports
LoadedMacro::ProcMacro(..) => continue,
};
om.impls.push(i);
}
},
- hir::ItemAutoImpl(unsafety, ref trait_ref) => {
- // See comment above about ItemImpl.
- if !self.inlining {
- let i = AutoImpl {
- unsafety,
- trait_: trait_ref.clone(),
- id: item.id,
- attrs: item.attrs.clone(),
- whence: item.span,
- };
- om.def_traits.push(i);
- }
- }
}
}
// except according to those terms.
#[inline]
-fn write_to_vec(vec: &mut Vec<u8>, position: usize, byte: u8) {
+pub fn write_to_vec(vec: &mut Vec<u8>, position: usize, byte: u8) {
if position == vec.len() {
vec.push(byte);
} else {
}
}
-#[inline]
-/// encodes an integer using unsigned leb128 encoding and stores
-/// the result using a callback function.
-///
-/// The callback `write` is called once for each position
-/// that is to be written to with the byte to be encoded
-/// at that position.
-pub fn write_unsigned_leb128_to<W>(mut value: u128, mut write: W) -> usize
- where W: FnMut(usize, u8)
-{
- let mut position = 0;
- loop {
- let mut byte = (value & 0x7F) as u8;
- value >>= 7;
- if value != 0 {
- byte |= 0x80;
- }
-
- write(position, byte);
- position += 1;
+#[cfg(target_pointer_width = "32")]
+const USIZE_LEB128_SIZE: usize = 5;
+#[cfg(target_pointer_width = "64")]
+const USIZE_LEB128_SIZE: usize = 10;
+
+macro_rules! leb128_size {
+ (u16) => (3);
+ (u32) => (5);
+ (u64) => (10);
+ (u128) => (19);
+ (usize) => (USIZE_LEB128_SIZE);
+}
- if value == 0 {
- break;
+macro_rules! impl_write_unsigned_leb128 {
+ ($fn_name:ident, $int_ty:ident) => (
+ #[inline]
+ pub fn $fn_name(out: &mut Vec<u8>, start_position: usize, mut value: $int_ty) -> usize {
+ let mut position = start_position;
+ for _ in 0 .. leb128_size!($int_ty) {
+ let mut byte = (value & 0x7F) as u8;
+ value >>= 7;
+ if value != 0 {
+ byte |= 0x80;
+ }
+
+ write_to_vec(out, position, byte);
+ position += 1;
+
+ if value == 0 {
+ break;
+ }
+ }
+
+ position - start_position
}
- }
-
- position
+ )
}
-pub fn write_unsigned_leb128(out: &mut Vec<u8>, start_position: usize, value: u128) -> usize {
- write_unsigned_leb128_to(value, |i, v| write_to_vec(out, start_position+i, v))
+impl_write_unsigned_leb128!(write_u16_leb128, u16);
+impl_write_unsigned_leb128!(write_u32_leb128, u32);
+impl_write_unsigned_leb128!(write_u64_leb128, u64);
+impl_write_unsigned_leb128!(write_u128_leb128, u128);
+impl_write_unsigned_leb128!(write_usize_leb128, usize);
+
+
+macro_rules! impl_read_unsigned_leb128 {
+ ($fn_name:ident, $int_ty:ident) => (
+ #[inline]
+ pub fn $fn_name(slice: &[u8]) -> ($int_ty, usize) {
+ let mut result: $int_ty = 0;
+ let mut shift = 0;
+ let mut position = 0;
+
+ for _ in 0 .. leb128_size!($int_ty) {
+ let byte = unsafe {
+ *slice.get_unchecked(position)
+ };
+ position += 1;
+ result |= ((byte & 0x7F) as $int_ty) << shift;
+ if (byte & 0x80) == 0 {
+ break;
+ }
+ shift += 7;
+ }
+
+ // Do a single bounds check at the end instead of for every byte.
+ assert!(position <= slice.len());
+
+ (result, position)
+ }
+ )
}
-#[inline]
-pub fn read_unsigned_leb128(data: &[u8], start_position: usize) -> (u128, usize) {
- let mut result = 0;
- let mut shift = 0;
- let mut position = start_position;
- loop {
- let byte = data[position];
- position += 1;
- result |= ((byte & 0x7F) as u128) << shift;
- if (byte & 0x80) == 0 {
- break;
- }
- shift += 7;
- }
+impl_read_unsigned_leb128!(read_u16_leb128, u16);
+impl_read_unsigned_leb128!(read_u32_leb128, u32);
+impl_read_unsigned_leb128!(read_u64_leb128, u64);
+impl_read_unsigned_leb128!(read_u128_leb128, u128);
+impl_read_unsigned_leb128!(read_usize_leb128, usize);
+
- (result, position - start_position)
-}
#[inline]
/// encodes an integer using signed leb128 encoding and stores
(result, position - start_position)
}
-#[test]
-fn test_unsigned_leb128() {
- let mut stream = Vec::with_capacity(10000);
-
- for x in 0..62 {
- let pos = stream.len();
- let bytes_written = write_unsigned_leb128(&mut stream, pos, 3 << x);
- assert_eq!(stream.len(), pos + bytes_written);
- }
-
- let mut position = 0;
- for x in 0..62 {
- let expected = 3 << x;
- let (actual, bytes_read) = read_unsigned_leb128(&stream, position);
- assert_eq!(expected, actual);
- position += bytes_read;
- }
- assert_eq!(stream.len(), position);
+macro_rules! impl_test_unsigned_leb128 {
+ ($test_name:ident, $write_fn_name:ident, $read_fn_name:ident, $int_ty:ident) => (
+ #[test]
+ fn $test_name() {
+ let mut stream = Vec::new();
+
+ for x in 0..62 {
+ let pos = stream.len();
+ let bytes_written = $write_fn_name(&mut stream, pos, (3u64 << x) as $int_ty);
+ assert_eq!(stream.len(), pos + bytes_written);
+ }
+
+ let mut position = 0;
+ for x in 0..62 {
+ let expected = (3u64 << x) as $int_ty;
+ let (actual, bytes_read) = $read_fn_name(&stream[position ..]);
+ assert_eq!(expected, actual);
+ position += bytes_read;
+ }
+ assert_eq!(stream.len(), position);
+ }
+ )
}
+impl_test_unsigned_leb128!(test_u16_leb128, write_u16_leb128, read_u16_leb128, u16);
+impl_test_unsigned_leb128!(test_u32_leb128, write_u32_leb128, read_u32_leb128, u32);
+impl_test_unsigned_leb128!(test_u64_leb128, write_u64_leb128, read_u64_leb128, u64);
+impl_test_unsigned_leb128!(test_u128_leb128, write_u128_leb128, read_u128_leb128, u128);
+impl_test_unsigned_leb128!(test_usize_leb128, write_usize_leb128, read_usize_leb128, usize);
+
#[test]
fn test_signed_leb128() {
let values: Vec<_> = (-500..500).map(|i| i * 0x12345789ABCDEF).collect();
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use leb128::{read_signed_leb128, read_unsigned_leb128, write_signed_leb128, write_unsigned_leb128};
+use leb128::{self, read_signed_leb128, write_signed_leb128};
use std::borrow::Cow;
use std::io::{self, Write};
use serialize;
pub fn new(cursor: &'a mut io::Cursor<Vec<u8>>) -> Encoder<'a> {
Encoder { cursor: cursor }
}
+
+ pub fn emit_raw_bytes(&mut self, s: &[u8]) -> EncodeResult {
+ self.cursor.write_all(s)
+ }
}
macro_rules! write_uleb128 {
- ($enc:expr, $value:expr) => {{
+ ($enc:expr, $value:expr, $fun:ident) => {{
let pos = $enc.cursor.position() as usize;
- let bytes_written = write_unsigned_leb128($enc.cursor.get_mut(), pos, $value as u128);
+ let bytes_written = leb128::$fun($enc.cursor.get_mut(), pos, $value);
$enc.cursor.set_position((pos + bytes_written) as u64);
Ok(())
}}
impl<'a> serialize::Encoder for Encoder<'a> {
type Error = io::Error;
+ #[inline]
fn emit_nil(&mut self) -> EncodeResult {
Ok(())
}
+ #[inline]
fn emit_usize(&mut self, v: usize) -> EncodeResult {
- write_uleb128!(self, v)
+ write_uleb128!(self, v, write_usize_leb128)
}
+ #[inline]
fn emit_u128(&mut self, v: u128) -> EncodeResult {
- write_uleb128!(self, v)
+ write_uleb128!(self, v, write_u128_leb128)
}
+ #[inline]
fn emit_u64(&mut self, v: u64) -> EncodeResult {
- write_uleb128!(self, v)
+ write_uleb128!(self, v, write_u64_leb128)
}
+ #[inline]
fn emit_u32(&mut self, v: u32) -> EncodeResult {
- write_uleb128!(self, v)
+ write_uleb128!(self, v, write_u32_leb128)
}
+ #[inline]
fn emit_u16(&mut self, v: u16) -> EncodeResult {
- write_uleb128!(self, v)
+ write_uleb128!(self, v, write_u16_leb128)
}
+ #[inline]
fn emit_u8(&mut self, v: u8) -> EncodeResult {
- let _ = self.cursor.write_all(&[v]);
+ let pos = self.cursor.position() as usize;
+ leb128::write_to_vec(self.cursor.get_mut(), pos, v);
+ self.cursor.set_position((pos + 1) as u64);
Ok(())
}
+ #[inline]
fn emit_isize(&mut self, v: isize) -> EncodeResult {
write_sleb128!(self, v)
}
+ #[inline]
fn emit_i128(&mut self, v: i128) -> EncodeResult {
write_sleb128!(self, v)
}
+ #[inline]
fn emit_i64(&mut self, v: i64) -> EncodeResult {
write_sleb128!(self, v)
}
+ #[inline]
fn emit_i32(&mut self, v: i32) -> EncodeResult {
write_sleb128!(self, v)
}
+ #[inline]
fn emit_i16(&mut self, v: i16) -> EncodeResult {
write_sleb128!(self, v)
}
+ #[inline]
fn emit_i8(&mut self, v: i8) -> EncodeResult {
let as_u8: u8 = unsafe { ::std::mem::transmute(v) };
- let _ = self.cursor.write_all(&[as_u8]);
- Ok(())
+ self.emit_u8(as_u8)
}
+ #[inline]
fn emit_bool(&mut self, v: bool) -> EncodeResult {
self.emit_u8(if v {
1
})
}
+ #[inline]
fn emit_f64(&mut self, v: f64) -> EncodeResult {
let as_u64: u64 = unsafe { ::std::mem::transmute(v) };
self.emit_u64(as_u64)
}
+ #[inline]
fn emit_f32(&mut self, v: f32) -> EncodeResult {
let as_u32: u32 = unsafe { ::std::mem::transmute(v) };
self.emit_u32(as_u32)
}
+ #[inline]
fn emit_char(&mut self, v: char) -> EncodeResult {
self.emit_u32(v as u32)
}
+ #[inline]
fn emit_str(&mut self, v: &str) -> EncodeResult {
self.emit_usize(v.len())?;
let _ = self.cursor.write_all(v.as_bytes());
}
impl<'a> Encoder<'a> {
+ #[inline]
pub fn position(&self) -> usize {
self.cursor.position() as usize
}
}
}
+ #[inline]
pub fn position(&self) -> usize {
self.position
}
+ #[inline]
pub fn set_position(&mut self, pos: usize) {
self.position = pos
}
+ #[inline]
pub fn advance(&mut self, bytes: usize) {
self.position += bytes;
}
+
+ pub fn read_raw_bytes(&mut self, s: &mut [u8]) -> Result<(), String> {
+ let start = self.position;
+ let end = start + s.len();
+
+ s.copy_from_slice(&self.data[start..end]);
+
+ self.position = end;
+
+ Ok(())
+ }
}
macro_rules! read_uleb128 {
- ($dec:expr, $t:ty) => ({
- let (value, bytes_read) = read_unsigned_leb128($dec.data, $dec.position);
+ ($dec:expr, $t:ty, $fun:ident) => ({
+ let (value, bytes_read) = leb128::$fun(&$dec.data[$dec.position ..]);
$dec.position += bytes_read;
- Ok(value as $t)
+ Ok(value)
})
}
#[inline]
fn read_u128(&mut self) -> Result<u128, Self::Error> {
- read_uleb128!(self, u128)
+ read_uleb128!(self, u128, read_u128_leb128)
}
#[inline]
fn read_u64(&mut self) -> Result<u64, Self::Error> {
- read_uleb128!(self, u64)
+ read_uleb128!(self, u64, read_u64_leb128)
}
#[inline]
fn read_u32(&mut self) -> Result<u32, Self::Error> {
- read_uleb128!(self, u32)
+ read_uleb128!(self, u32, read_u32_leb128)
}
#[inline]
fn read_u16(&mut self) -> Result<u16, Self::Error> {
- read_uleb128!(self, u16)
+ read_uleb128!(self, u16, read_u16_leb128)
}
#[inline]
#[inline]
fn read_usize(&mut self) -> Result<usize, Self::Error> {
- read_uleb128!(self, usize)
+ read_uleb128!(self, usize, read_usize_leb128)
}
#[inline]
self.search_mut(k).into_occupied_bucket().map(|bucket| pop_internal(bucket).1)
}
+ /// Removes a key from the map, returning the stored key and value if the
+ /// key was previously in the map.
+ ///
+ /// The key may be any borrowed form of the map's key type, but
+ /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for
+ /// the key type.
+ ///
+ /// [`Eq`]: ../../std/cmp/trait.Eq.html
+ /// [`Hash`]: ../../std/hash/trait.Hash.html
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(hash_map_remove_entry)]
+ /// use std::collections::HashMap;
+ ///
+ /// # fn main() {
+ /// let mut map = HashMap::new();
+ /// map.insert(1, "a");
+ /// assert_eq!(map.remove_entry(&1), Some((1, "a")));
+ /// assert_eq!(map.remove(&1), None);
+ /// # }
+ /// ```
+ #[unstable(feature = "hash_map_remove_entry", issue = "46344")]
+ pub fn remove_entry<Q: ?Sized>(&mut self, k: &Q) -> Option<(K, V)>
+ where K: Borrow<Q>,
+ Q: Hash + Eq
+ {
+ if self.table.size() == 0 {
+ return None;
+ }
+
+ self.search_mut(k)
+ .into_occupied_bucket()
+ .map(|bucket| {
+ let (k, v, _) = pop_internal(bucket);
+ (k, v)
+ })
+ }
+
/// Retains only the elements specified by the predicate.
///
/// In other words, remove all pairs `(k, v)` such that `f(&k,&mut v)` returns `false`.
}
#[test]
- fn test_pop() {
+ fn test_remove() {
let mut m = HashMap::new();
m.insert(1, 2);
assert_eq!(m.remove(&1), Some(2));
assert_eq!(m.remove(&1), None);
}
+ #[test]
+ fn test_remove_entry() {
+ let mut m = HashMap::new();
+ m.insert(1, 2);
+ assert_eq!(m.remove_entry(&1), Some((1, 2)));
+ assert_eq!(m.remove(&1), None);
+ }
+
#[test]
fn test_iterate() {
let mut m = HashMap::with_capacity(4);
/// [`Hash`] and [`Eq`] on the borrowed form *must* match those for
/// the value type.
///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::collections::HashSet;
+ ///
+ /// let set: HashSet<_> = [1, 2, 3].iter().cloned().collect();
+ /// assert_eq!(set.get(&2), Some(&2));
+ /// assert_eq!(set.get(&4), None);
+ /// ```
+ ///
/// [`Eq`]: ../../std/cmp/trait.Eq.html
/// [`Hash`]: ../../std/hash/trait.Hash.html
#[stable(feature = "set_recovery", since = "1.9.0")]
/// Adds a value to the set, replacing the existing value, if any, that is equal to the given
/// one. Returns the replaced value.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::collections::HashSet;
+ ///
+ /// let mut set = HashSet::new();
+ /// set.insert(Vec::<i32>::new());
+ ///
+ /// assert_eq!(set.get(&[][..]).unwrap().capacity(), 0);
+ /// set.replace(Vec::with_capacity(10));
+ /// assert_eq!(set.get(&[][..]).unwrap().capacity(), 10);
+ /// ```
#[stable(feature = "set_recovery", since = "1.9.0")]
pub fn replace(&mut self, value: T) -> Option<T> {
Recover::replace(&mut self.map, value)
/// [`Hash`] and [`Eq`] on the borrowed form *must* match those for
/// the value type.
///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::collections::HashSet;
+ ///
+ /// let mut set: HashSet<_> = [1, 2, 3].iter().cloned().collect();
+ /// assert_eq!(set.take(&2), Some(2));
+ /// assert_eq!(set.take(&2), None);
+ /// ```
+ ///
/// [`Eq`]: ../../std/cmp/trait.Eq.html
/// [`Hash`]: ../../std/hash/trait.Hash.html
#[stable(feature = "set_recovery", since = "1.9.0")]
use mem::{align_of, size_of, needs_drop};
use mem;
use ops::{Deref, DerefMut};
-use ptr::{self, Unique, Shared};
+use ptr::{self, Unique, NonNull};
use self::BucketState::*;
elems_left,
marker: marker::PhantomData,
},
- table: Shared::from(self),
+ table: NonNull::from(self),
marker: marker::PhantomData,
}
}
/// Iterator over the entries in a table, clearing the table.
pub struct Drain<'a, K: 'a, V: 'a> {
- table: Shared<RawTable<K, V>>,
+ table: NonNull<RawTable<K, V>>,
iter: RawBuckets<'static, K, V>,
marker: marker::PhantomData<&'a RawTable<K, V>>,
}
/// Returns the full filesystem path of the current running executable.
///
-/// The path returned is not necessarily a "real path" of the executable as
-/// there may be intermediate symlinks.
+/// # Platform-specific behavior
+///
+/// If the executable was invoked through a symbolic link, some platforms will
+/// return the path of the symbolic link and other platforms will return the
+/// path of the symbolic link’s target.
///
/// # Errors
///
/// Ok("/home/alex/foo")
/// ```
///
-/// And you make a symbolic link of the program:
+/// And you make a hard link of the program:
///
/// ```bash
/// $ ln foo bar
/// ```
///
-/// When you run it, you won't get the original executable, you'll get the
-/// symlink:
+/// When you run it, you won’t get the path of the original executable, you’ll
+/// get the path of the hard link:
///
/// ```bash
/// $ ./bar
/// ```
///
/// This sort of behavior has been known to [lead to privilege escalation] when
-/// used incorrectly, for example.
+/// used incorrectly.
///
-/// [lead to privilege escalation]: http://securityvulns.com/Wdocument183.html
+/// [lead to privilege escalation]: https://securityvulns.com/Wdocument183.html
///
/// # Examples
///
///
/// match env::current_exe() {
/// Ok(exe_path) => println!("Path of this executable is: {}",
-/// exe_path.display()),
+/// exe_path.display()),
/// Err(e) => println!("failed to get current exe path: {}", e),
/// };
/// ```
mod tests {
use super::*;
- use ffi::OsStr;
- use path::{Path, PathBuf};
+ use path::Path;
#[test]
#[cfg_attr(target_os = "emscripten", ignore)]
#[test]
#[cfg(windows)]
fn split_paths_windows() {
+ use path::PathBuf;
+
fn check_parse(unparsed: &str, parsed: &[&str]) -> bool {
split_paths(unparsed).collect::<Vec<_>>() ==
parsed.iter().map(|s| PathBuf::from(*s)).collect::<Vec<_>>()
#[test]
#[cfg(unix)]
fn split_paths_unix() {
+ use path::PathBuf;
+
fn check_parse(unparsed: &str, parsed: &[&str]) -> bool {
split_paths(unparsed).collect::<Vec<_>>() ==
parsed.iter().map(|s| PathBuf::from(*s)).collect::<Vec<_>>()
#[test]
#[cfg(unix)]
fn join_paths_unix() {
+ use ffi::OsStr;
+
fn test_eq(input: &[&str], output: &str) -> bool {
&*join_paths(input.iter().cloned()).unwrap() ==
OsStr::new(output)
#[test]
#[cfg(windows)]
fn join_paths_windows() {
+ use ffi::OsStr;
+
fn test_eq(input: &[&str], output: &str) -> bool {
&*join_paths(input.iter().cloned()).unwrap() ==
OsStr::new(output)
/// Returns the logarithm of the number with respect to an arbitrary base.
///
+ /// The result may not be correctly rounded owing to implementation details;
+ /// `self.log2()` can produce more accurate results for base 2, and
+ /// `self.log10()` can produce more accurate results for base 10.
+ ///
/// ```
/// use std::f32;
///
- /// let ten = 10.0f32;
- /// let two = 2.0f32;
- ///
- /// // log10(10) - 1 == 0
- /// let abs_difference_10 = (ten.log(10.0) - 1.0).abs();
+ /// let five = 5.0f32;
///
- /// // log2(2) - 1 == 0
- /// let abs_difference_2 = (two.log(2.0) - 1.0).abs();
+ /// // log5(5) - 1 == 0
+ /// let abs_difference = (five.log(5.0) - 1.0).abs();
///
- /// assert!(abs_difference_10 <= f32::EPSILON);
- /// assert!(abs_difference_2 <= f32::EPSILON);
+ /// assert!(abs_difference <= f32::EPSILON);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
/// Returns the logarithm of the number with respect to an arbitrary base.
///
- /// ```
- /// let ten = 10.0_f64;
- /// let two = 2.0_f64;
+ /// The result may not be correctly rounded owing to implementation details;
+ /// `self.log2()` can produce more accurate results for base 2, and
+ /// `self.log10()` can produce more accurate results for base 10.
///
- /// // log10(10) - 1 == 0
- /// let abs_difference_10 = (ten.log(10.0) - 1.0).abs();
+ /// ```
+ /// let five = 5.0_f64;
///
- /// // log2(2) - 1 == 0
- /// let abs_difference_2 = (two.log(2.0) - 1.0).abs();
+ /// // log5(5) - 1 == 0
+ /// let abs_difference = (five.log(5.0) - 1.0).abs();
///
- /// assert!(abs_difference_10 < 1e-10);
- /// assert!(abs_difference_2 < 1e-10);
+ /// assert!(abs_difference < 1e-10);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
}
}
-#[stable(feature = "shared_from_slice2", since = "1.23.0")]
+#[stable(feature = "shared_from_slice2", since = "1.24.0")]
impl From<CString> for Arc<CStr> {
#[inline]
fn from(s: CString) -> Arc<CStr> {
}
}
-#[stable(feature = "shared_from_slice2", since = "1.23.0")]
+#[stable(feature = "shared_from_slice2", since = "1.24.0")]
impl<'a> From<&'a CStr> for Arc<CStr> {
#[inline]
fn from(s: &CStr) -> Arc<CStr> {
}
}
-#[stable(feature = "shared_from_slice2", since = "1.23.0")]
+#[stable(feature = "shared_from_slice2", since = "1.24.0")]
impl From<CString> for Rc<CStr> {
#[inline]
fn from(s: CString) -> Rc<CStr> {
}
}
-#[stable(feature = "shared_from_slice2", since = "1.23.0")]
+#[stable(feature = "shared_from_slice2", since = "1.24.0")]
impl<'a> From<&'a CStr> for Rc<CStr> {
#[inline]
fn from(s: &CStr) -> Rc<CStr> {
//! terminator, so the buffer length is really `len+1` characters.
//! Rust strings don't have a nul terminator; their length is always
//! stored and does not need to be calculated. While in Rust
-//! accessing a string's length is a O(1) operation (becasue the
+//! accessing a string's length is a O(1) operation (because the
//! length is stored); in C it is an O(length) operation because the
//! length needs to be computed by scanning the string for the nul
//! terminator.
/// and platform-native string values, and in particular allowing a Rust string
/// to be converted into an "OS" string with no cost if possible.
///
-/// `OsString` is to [`OsStr`] as [`String`] is to [`&str`]: the former
+/// `OsString` is to [`&OsStr`] as [`String`] is to [`&str`]: the former
/// in each pair are owned strings; the latter are borrowed
/// references.
///
/// the traits which `OsString` implements for conversions from/to native representations.
///
/// [`OsStr`]: struct.OsStr.html
+/// [`&OsStr`]: struct.OsStr.html
/// [`From`]: ../convert/trait.From.html
/// [`String`]: ../string/struct.String.html
/// [`&str`]: ../primitive.str.html
/// This type represents a borrowed reference to a string in the operating system's preferred
/// representation.
///
-/// `OsStr` is to [`OsString`] as [`String`] is to [`&str`]: the former in each pair are borrowed
+/// `&OsStr` is to [`OsString`] as [`&str`] is to [`String`]: the former in each pair are borrowed
/// references; the latter are owned strings.
///
/// See the [module's toplevel documentation about conversions][conversions] for a discussion on
/// the traits which `OsStr` implements for conversions from/to native representations.
///
/// [`OsString`]: struct.OsString.html
+/// [`&str`]: ../primitive.str.html
+/// [`String`]: ../string/struct.String.html
/// [conversions]: index.html#conversions
#[stable(feature = "rust1", since = "1.0.0")]
pub struct OsStr {
}
}
-#[stable(feature = "shared_from_slice2", since = "1.23.0")]
+#[stable(feature = "shared_from_slice2", since = "1.24.0")]
impl From<OsString> for Arc<OsStr> {
#[inline]
fn from(s: OsString) -> Arc<OsStr> {
}
}
-#[stable(feature = "shared_from_slice2", since = "1.23.0")]
+#[stable(feature = "shared_from_slice2", since = "1.24.0")]
impl<'a> From<&'a OsStr> for Arc<OsStr> {
#[inline]
fn from(s: &OsStr) -> Arc<OsStr> {
}
}
-#[stable(feature = "shared_from_slice2", since = "1.23.0")]
+#[stable(feature = "shared_from_slice2", since = "1.24.0")]
impl From<OsString> for Rc<OsStr> {
#[inline]
fn from(s: OsString) -> Rc<OsStr> {
}
}
-#[stable(feature = "shared_from_slice2", since = "1.23.0")]
+#[stable(feature = "shared_from_slice2", since = "1.24.0")]
impl<'a> From<&'a OsStr> for Rc<OsStr> {
#[inline]
fn from(s: &OsStr) -> Rc<OsStr> {
recursive: bool,
}
+/// How large a buffer to pre-allocate before reading the entire file.
+fn initial_buffer_size(file: &File) -> usize {
+ // Allocate one extra byte so the buffer doesn't need to grow before the
+ // final `read` call at the end of the file. Don't worry about `usize`
+ // overflow because reading will fail regardless in that case.
+ file.metadata().map(|m| m.len() as usize + 1).unwrap_or(0)
+}
+
/// Read the entire contents of a file into a bytes vector.
///
/// This is a convenience function for using [`File::open`] and [`read_to_end`]
/// ```
#[unstable(feature = "fs_read_write", issue = "46588")]
pub fn read<P: AsRef<Path>>(path: P) -> io::Result<Vec<u8>> {
- let mut bytes = Vec::new();
- File::open(path)?.read_to_end(&mut bytes)?;
+ let mut file = File::open(path)?;
+ let mut bytes = Vec::with_capacity(initial_buffer_size(&file));
+ file.read_to_end(&mut bytes)?;
Ok(bytes)
}
/// ```
#[unstable(feature = "fs_read_write", issue = "46588")]
pub fn read_string<P: AsRef<Path>>(path: P) -> io::Result<String> {
- let mut string = String::new();
- File::open(path)?.read_to_string(&mut string)?;
+ let mut file = File::open(path)?;
+ let mut string = String::with_capacity(initial_buffer_size(&file));
+ file.read_to_string(&mut string)?;
Ok(string)
}
}
}
-#[cfg(all(test, not(target_os = "emscripten")))]
+#[cfg(all(test, not(any(target_os = "cloudabi", target_os = "emscripten"))))]
mod tests {
use io::prelude::*;
pub fn into_inner(self) -> R { self.inner }
}
+impl<R: Seek> BufReader<R> {
+ /// Seeks relative to the current position. If the new position lies within the buffer,
+ /// the buffer will not be flushed, allowing for more efficient seeks.
+ /// This method does not return the location of the underlying reader, so the caller
+ /// must track this information themselves if it is required.
+ #[unstable(feature = "bufreader_seek_relative", issue = "31100")]
+ pub fn seek_relative(&mut self, offset: i64) -> io::Result<()> {
+ let pos = self.pos as u64;
+ if offset < 0 {
+ if let Some(new_pos) = pos.checked_sub((-offset) as u64) {
+ self.pos = new_pos as usize;
+ return Ok(())
+ }
+ } else {
+ if let Some(new_pos) = pos.checked_add(offset as u64) {
+ if new_pos <= self.cap as u64 {
+ self.pos = new_pos as usize;
+ return Ok(())
+ }
+ }
+ }
+ self.seek(SeekFrom::Current(offset)).map(|_|())
+ }
+}
+
#[stable(feature = "rust1", since = "1.0.0")]
impl<R: Read> Read for BufReader<R> {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
/// `.into_inner()` immediately after a seek yields the underlying reader
/// at the same position.
///
+ /// To seek without discarding the internal buffer, use [`seek_relative`].
+ ///
/// See `std::io::Seek` for more details.
///
/// Note: In the edge case where you're seeking with `SeekFrom::Current(n)`
/// seeks will be performed instead of one. If the second seek returns
/// `Err`, the underlying reader will be left at the same position it would
/// have if you seeked to `SeekFrom::Current(0)`.
+ ///
+ /// [`seek_relative`]: #method.seek_relative
fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
let result: u64;
if let SeekFrom::Current(n) = pos {
///
/// let mut stream = TcpStream::connect("127.0.0.1:34254").unwrap();
///
-/// for i in 1..10 {
-/// stream.write(&[i]).unwrap();
+/// for i in 0..10 {
+/// stream.write(&[i+1]).unwrap();
/// }
/// ```
///
///
/// let mut stream = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap());
///
-/// for i in 1..10 {
-/// stream.write(&[i]).unwrap();
+/// for i in 0..10 {
+/// stream.write(&[i+1]).unwrap();
/// }
/// ```
///
assert_eq!(reader.seek(SeekFrom::Current(-2)).ok(), Some(3));
}
+ #[test]
+ fn test_buffered_reader_seek_relative() {
+ let inner: &[u8] = &[5, 6, 7, 0, 1, 2, 3, 4];
+ let mut reader = BufReader::with_capacity(2, io::Cursor::new(inner));
+
+ assert!(reader.seek_relative(3).is_ok());
+ assert_eq!(reader.fill_buf().ok(), Some(&[0, 1][..]));
+ assert!(reader.seek_relative(0).is_ok());
+ assert_eq!(reader.fill_buf().ok(), Some(&[0, 1][..]));
+ assert!(reader.seek_relative(1).is_ok());
+ assert_eq!(reader.fill_buf().ok(), Some(&[1][..]));
+ assert!(reader.seek_relative(-1).is_ok());
+ assert_eq!(reader.fill_buf().ok(), Some(&[0, 1][..]));
+ assert!(reader.seek_relative(2).is_ok());
+ assert_eq!(reader.fill_buf().ok(), Some(&[2, 3][..]));
+ }
+
#[test]
fn test_buffered_reader_seek_underflow() {
// gimmick reader that yields its position modulo 256 for each byte
fn consume(&mut self, amt: usize) { self.pos += amt as u64; }
}
+// Non-resizing write implementation
+fn slice_write(pos_mut: &mut u64, slice: &mut [u8], buf: &[u8]) -> io::Result<usize> {
+ let pos = cmp::min(*pos_mut, slice.len() as u64);
+ let amt = (&mut slice[(pos as usize)..]).write(buf)?;
+ *pos_mut += amt as u64;
+ Ok(amt)
+}
+
+// Resizing write implementation
+fn vec_write(pos_mut: &mut u64, vec: &mut Vec<u8>, buf: &[u8]) -> io::Result<usize> {
+ let pos: usize = (*pos_mut).try_into().map_err(|_| {
+ Error::new(ErrorKind::InvalidInput,
+ "cursor position exceeds maximum possible vector length")
+ })?;
+ // Make sure the internal buffer is as least as big as where we
+ // currently are
+ let len = vec.len();
+ if len < pos {
+ // use `resize` so that the zero filling is as efficient as possible
+ vec.resize(pos, 0);
+ }
+ // Figure out what bytes will be used to overwrite what's currently
+ // there (left), and what will be appended on the end (right)
+ {
+ let space = vec.len() - pos;
+ let (left, right) = buf.split_at(cmp::min(space, buf.len()));
+ vec[pos..pos + left.len()].copy_from_slice(left);
+ vec.extend_from_slice(right);
+ }
+
+ // Bump us forward
+ *pos_mut = (pos + buf.len()) as u64;
+ Ok(buf.len())
+}
+
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a> Write for Cursor<&'a mut [u8]> {
#[inline]
- fn write(&mut self, data: &[u8]) -> io::Result<usize> {
- let pos = cmp::min(self.pos, self.inner.len() as u64);
- let amt = (&mut self.inner[(pos as usize)..]).write(data)?;
- self.pos += amt as u64;
- Ok(amt)
+ fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
+ slice_write(&mut self.pos, self.inner, buf)
+ }
+ fn flush(&mut self) -> io::Result<()> { Ok(()) }
+}
+
+#[unstable(feature = "cursor_mut_vec", issue = "30132")]
+impl<'a> Write for Cursor<&'a mut Vec<u8>> {
+ fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
+ vec_write(&mut self.pos, self.inner, buf)
}
fn flush(&mut self) -> io::Result<()> { Ok(()) }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl Write for Cursor<Vec<u8>> {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
- let pos: usize = self.position().try_into().map_err(|_| {
- Error::new(ErrorKind::InvalidInput,
- "cursor position exceeds maximum possible vector length")
- })?;
- // Make sure the internal buffer is as least as big as where we
- // currently are
- let len = self.inner.len();
- if len < pos {
- // use `resize` so that the zero filling is as efficient as possible
- self.inner.resize(pos, 0);
- }
- // Figure out what bytes will be used to overwrite what's currently
- // there (left), and what will be appended on the end (right)
- {
- let space = self.inner.len() - pos;
- let (left, right) = buf.split_at(cmp::min(space, buf.len()));
- self.inner[pos..pos + left.len()].copy_from_slice(left);
- self.inner.extend_from_slice(right);
- }
-
- // Bump us forward
- self.set_position((pos + buf.len()) as u64);
- Ok(buf.len())
+ vec_write(&mut self.pos, &mut self.inner, buf)
}
fn flush(&mut self) -> io::Result<()> { Ok(()) }
}
impl Write for Cursor<Box<[u8]>> {
#[inline]
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
- let pos = cmp::min(self.pos, self.inner.len() as u64);
- let amt = (&mut self.inner[(pos as usize)..]).write(buf)?;
- self.pos += amt as u64;
- Ok(amt)
+ slice_write(&mut self.pos, &mut self.inner, buf)
}
fn flush(&mut self) -> io::Result<()> { Ok(()) }
}
assert_eq!(&writer.get_ref()[..], b);
}
+ #[test]
+ fn test_mem_mut_writer() {
+ let mut vec = Vec::new();
+ let mut writer = Cursor::new(&mut vec);
+ assert_eq!(writer.write(&[0]).unwrap(), 1);
+ assert_eq!(writer.write(&[1, 2, 3]).unwrap(), 3);
+ assert_eq!(writer.write(&[4, 5, 6, 7]).unwrap(), 4);
+ let b: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7];
+ assert_eq!(&writer.get_ref()[..], b);
+ }
+
#[test]
fn test_box_slice_writer() {
let mut writer = Cursor::new(vec![0u8; 9].into_boxed_slice());
/// [`Write`]: ../io/trait.Write.html
/// [`Seek`]: ../io/trait.Seek.html
/// [`ErrorKind`]: enum.ErrorKind.html
-#[derive(Debug)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Error {
repr: Repr,
}
+#[stable(feature = "rust1", since = "1.0.0")]
+impl fmt::Debug for Error {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ fmt::Debug::fmt(&self.repr, f)
+ }
+}
+
enum Repr {
Os(i32),
Simple(ErrorKind),
impl fmt::Debug for Repr {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
match *self {
- Repr::Os(ref code) =>
- fmt.debug_struct("Os").field("code", code)
- .field("message", &sys::os::error_string(*code)).finish(),
- Repr::Custom(ref c) => fmt.debug_tuple("Custom").field(c).finish(),
+ Repr::Os(code) =>
+ fmt.debug_struct("Os")
+ .field("code", &code)
+ .field("kind", &sys::decode_error_kind(code))
+ .field("message", &sys::os::error_string(code)).finish(),
+ Repr::Custom(ref c) => fmt::Debug::fmt(&c, fmt),
Repr::Simple(kind) => fmt.debug_tuple("Kind").field(&kind).finish(),
}
}
#[cfg(test)]
mod test {
- use super::{Error, ErrorKind};
+ use super::{Error, ErrorKind, Repr, Custom};
use error;
use fmt;
use sys::os::error_string;
+ use sys::decode_error_kind;
#[test]
fn test_debug_error() {
let code = 6;
let msg = error_string(code);
- let err = Error { repr: super::Repr::Os(code) };
- let expected = format!("Error {{ repr: Os {{ code: {:?}, message: {:?} }} }}", code, msg);
+ let kind = decode_error_kind(code);
+ let err = Error {
+ repr: Repr::Custom(box Custom {
+ kind: ErrorKind::InvalidInput,
+ error: box Error {
+ repr: super::Repr::Os(code)
+ },
+ })
+ };
+ let expected = format!(
+ "Custom {{ \
+ kind: InvalidInput, \
+ error: Os {{ \
+ code: {:?}, \
+ kind: {:?}, \
+ message: {:?} \
+ }} \
+ }}",
+ code, kind, msg
+ );
assert_eq!(format!("{:?}", err), expected);
}
read_to_end(self, buf)
}
- /// Read all bytes until EOF in this source, placing them into `buf`.
+ /// Read all bytes until EOF in this source, appending them to `buf`.
///
/// If successful, this function returns the number of bytes which were read
/// and appended to `buf`.
///
/// Calls to `write` are not guaranteed to block waiting for data to be
/// written, and a write which would otherwise block can be indicated through
- /// an `Err` variant.
+ /// an [`Err`] variant.
///
- /// If the return value is `Ok(n)` then it must be guaranteed that
+ /// If the return value is [`Ok(n)`] then it must be guaranteed that
/// `0 <= n <= buf.len()`. A return value of `0` typically means that the
/// underlying object is no longer able to accept bytes and will likely not
/// be able to in the future as well, or that the buffer provided is empty.
/// It is **not** considered an error if the entire buffer could not be
/// written to this writer.
///
- /// An error of the `ErrorKind::Interrupted` kind is non-fatal and the
+ /// An error of the [`ErrorKind::Interrupted`] kind is non-fatal and the
/// write operation should be retried if there is nothing else to do.
///
+ /// [`Err`]: ../../std/result/enum.Result.html#variant.Err
+ /// [`Ok(n)`]: ../../std/result/enum.Result.html#variant.Ok
+ /// [`ErrorKind::Interrupted`]: ../../std/io/enum.ErrorKind.html#variant.Interrupted
+ ///
/// # Examples
///
/// ```
/// Attempts to write an entire buffer into this write.
///
- /// This method will continuously call `write` until there is no more data
- /// to be written or an error of non-`ErrorKind::Interrupted` kind is
+ /// This method will continuously call [`write`] until there is no more data
+ /// to be written or an error of non-[`ErrorKind::Interrupted`] kind is
/// returned. This method will not return until the entire buffer has been
/// successfully written or such an error occurs. The first error that is
- /// not of `ErrorKind::Interrupted` kind generated from this method will be
+ /// not of [`ErrorKind::Interrupted`] kind generated from this method will be
/// returned.
///
/// # Errors
///
/// This function will return the first error of
- /// non-`ErrorKind::Interrupted` kind that `write` returns.
+ /// non-[`ErrorKind::Interrupted`] kind that [`write`] returns.
+ ///
+ /// [`ErrorKind::Interrupted`]: ../../std/io/enum.ErrorKind.html#variant.Interrupted
+ /// [`write`]: #tymethod.write
///
/// # Examples
///
// Turn warnings into errors, but only after stage0, where it can be useful for
// code to emit warnings during language transitions
-#![deny(warnings)]
+#![cfg_attr(not(stage0), deny(warnings))]
// std may use features in a platform-specific way
#![allow(unused_features)]
#![feature(placement_in_syntax)]
#![feature(placement_new_protocol)]
#![feature(prelude_import)]
+#![feature(ptr_internals)]
#![feature(rand)]
#![feature(raw)]
#![feature(repr_align)]
-#![feature(repr_simd)]
#![feature(rustc_attrs)]
-#![feature(shared)]
#![feature(sip_hash_13)]
#![feature(slice_bytes)]
#![feature(slice_concat_ext)]
#![feature(try_from)]
#![feature(unboxed_closures)]
#![feature(unicode)]
-#![feature(unique)]
#![feature(untagged_unions)]
#![feature(unwind_attributes)]
#![feature(vec_push_all)]
#[cfg(test)] extern crate test;
#[cfg(test)] extern crate rand;
-// We want to reexport a few macros from core but libcore has already been
+// 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 reexports to it.
+// 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,
debug_assert_ne, unreachable, unimplemented, write, writeln, try)]
extern crate core as __core;
// The Rust prelude
pub mod prelude;
-// Public module declarations and reexports
+// Public module declarations and re-exports
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::any;
#[stable(feature = "rust1", since = "1.0.0")]
/// Unconditionally causes compilation to fail with the given error message when encountered.
///
/// This macro should be used when a crate uses a conditional compilation strategy to provide
- /// better error messages for errornous conditions.
+ /// better error messages for erroneous conditions.
///
/// # Examples
///
}
}
-#[cfg(all(test, not(target_os = "emscripten")))]
+#[cfg(all(test, not(any(target_os = "cloudabi", target_os = "emscripten"))))]
mod tests {
use io::ErrorKind;
use io::prelude::*;
}
}
-#[cfg(all(test, not(target_os = "emscripten")))]
+#[cfg(all(test, not(any(target_os = "cloudabi", target_os = "emscripten"))))]
mod tests {
use io::ErrorKind;
use net::*;
use fmt;
use ops::{Deref, DerefMut};
use panicking;
-use ptr::{Unique, Shared};
+use ptr::{Unique, NonNull};
use rc::Rc;
use sync::{Arc, Mutex, RwLock, atomic};
use thread::Result;
#[stable(feature = "catch_unwind", since = "1.9.0")]
#[rustc_on_unimplemented = "the type {Self} may not be safely transferred \
across an unwind boundary"]
-pub trait UnwindSafe {}
+pub auto trait UnwindSafe {}
/// A marker trait representing types where a shared reference is considered
/// unwind safe.
#[rustc_on_unimplemented = "the type {Self} may contain interior mutability \
and a reference may not be safely transferrable \
across a catch_unwind boundary"]
-pub trait RefUnwindSafe {}
+pub auto trait RefUnwindSafe {}
/// A simple wrapper around a type to assert that it is unwind safe.
///
// * Unique, an owning pointer, lifts an implementation
// * Types like Mutex/RwLock which are explicilty poisoned are unwind safe
// * Our custom AssertUnwindSafe wrapper is indeed unwind safe
-#[stable(feature = "catch_unwind", since = "1.9.0")]
-#[allow(unknown_lints)]
-#[allow(auto_impl)]
-impl UnwindSafe for .. {}
+
#[stable(feature = "catch_unwind", since = "1.9.0")]
impl<'a, T: ?Sized> !UnwindSafe for &'a mut T {}
#[stable(feature = "catch_unwind", since = "1.9.0")]
impl<T: RefUnwindSafe + ?Sized> UnwindSafe for *const T {}
#[stable(feature = "catch_unwind", since = "1.9.0")]
impl<T: RefUnwindSafe + ?Sized> UnwindSafe for *mut T {}
-#[unstable(feature = "unique", issue = "27730")]
+#[unstable(feature = "ptr_internals", issue = "0")]
impl<T: UnwindSafe + ?Sized> UnwindSafe for Unique<T> {}
-#[unstable(feature = "shared", issue = "27730")]
-impl<T: RefUnwindSafe + ?Sized> UnwindSafe for Shared<T> {}
+#[stable(feature = "nonnull", since = "1.24.0")]
+impl<T: RefUnwindSafe + ?Sized> UnwindSafe for NonNull<T> {}
#[stable(feature = "catch_unwind", since = "1.9.0")]
impl<T: ?Sized> UnwindSafe for Mutex<T> {}
#[stable(feature = "catch_unwind", since = "1.9.0")]
impl<T: RefUnwindSafe + ?Sized> UnwindSafe for Arc<T> {}
// Pretty simple implementations for the `RefUnwindSafe` marker trait,
-// basically just saying that this is a marker trait and `UnsafeCell` is the
+// basically just saying that `UnsafeCell` is the
// only thing which doesn't implement it (which then transitively applies to
// everything else).
#[stable(feature = "catch_unwind", since = "1.9.0")]
-#[allow(unknown_lints)]
-#[allow(auto_impl)]
-impl RefUnwindSafe for .. {}
-#[stable(feature = "catch_unwind", since = "1.9.0")]
impl<T: ?Sized> !RefUnwindSafe for UnsafeCell<T> {}
#[stable(feature = "catch_unwind", since = "1.9.0")]
impl<T> RefUnwindSafe for AssertUnwindSafe<T> {}
/// # Examples
///
/// ```should_panic
- /// #![feature(panic_col)]
/// use std::panic;
///
/// panic::set_hook(Box::new(|panic_info| {
///
/// panic!("Normal panic");
/// ```
- #[unstable(feature = "panic_col", reason = "recently added", issue = "42939")]
+ #[stable(feature = "panic_col", since = "1.25")]
pub fn column(&self) -> u32 {
self.col
}
}
}
+#[stable(feature = "path_component_asref", since = "1.24.0")]
+impl<'a> AsRef<Path> for Component<'a> {
+ fn as_ref(&self) -> &Path {
+ self.as_os_str().as_ref()
+ }
+}
+
/// An iterator over the [`Component`]s of a [`Path`].
///
/// This `struct` is created by the [`components`] method on [`Path`].
}
}
-#[stable(feature = "shared_from_slice2", since = "1.23.0")]
+#[stable(feature = "shared_from_slice2", since = "1.24.0")]
impl From<PathBuf> for Arc<Path> {
#[inline]
fn from(s: PathBuf) -> Arc<Path> {
}
}
-#[stable(feature = "shared_from_slice2", since = "1.23.0")]
+#[stable(feature = "shared_from_slice2", since = "1.24.0")]
impl<'a> From<&'a Path> for Arc<Path> {
#[inline]
fn from(s: &Path) -> Arc<Path> {
}
}
-#[stable(feature = "shared_from_slice2", since = "1.23.0")]
+#[stable(feature = "shared_from_slice2", since = "1.24.0")]
impl From<PathBuf> for Rc<Path> {
#[inline]
fn from(s: PathBuf) -> Rc<Path> {
}
}
-#[stable(feature = "shared_from_slice2", since = "1.23.0")]
+#[stable(feature = "shared_from_slice2", since = "1.24.0")]
impl<'a> From<&'a Path> for Rc<Path> {
#[inline]
fn from(s: &Path) -> Rc<Path> {
/// let path_buf = Path::new("foo.txt").to_path_buf();
/// assert_eq!(path_buf, std::path::PathBuf::from("foo.txt"));
/// ```
+ #[rustc_conversion_suggestion]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn to_path_buf(&self) -> PathBuf {
PathBuf::from(self.inner.to_os_string())
//! # Prelude contents
//!
//! The current version of the prelude (version 1) lives in
-//! [`std::prelude::v1`], and reexports the following.
+//! [`std::prelude::v1`], and re-exports the following.
//!
//! * [`std::marker`]::{[`Copy`], [`Send`], [`Sized`], [`Sync`]}. The marker
//! traits indicate fundamental properties of types.
#![stable(feature = "rust1", since = "1.0.0")]
-// Reexported core operators
+// Re-exported core operators
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(no_inline)] pub use marker::{Copy, Send, Sized, Sync};
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(no_inline)] pub use ops::{Drop, Fn, FnMut, FnOnce};
-// Reexported functions
+// Re-exported functions
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(no_inline)] pub use mem::drop;
-// Reexported types and traits
+// Re-exported types and traits
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(no_inline)] pub use boxed::Box;
#[stable(feature = "rust1", since = "1.0.0")]
//! assert_eq!(b"Oh no, a typo!\n", output.stdout.as_slice());
//! ```
//!
-//! Note that [`ChildStderr`] and [`ChildStdout`] implement [`Write`] and
-//! [`ChildStdin`] implements [`Read`]:
+//! Note that [`ChildStderr`] and [`ChildStdout`] implement [`Read`] and
+//! [`ChildStdin`] implements [`Write`]:
//!
//! ```no_run
//! use std::process::{Command, Stdio};
::sys::os::getpid()
}
-#[cfg(all(test, not(target_os = "emscripten")))]
+#[cfg(all(test, not(any(target_os = "cloudabi", target_os = "emscripten"))))]
mod tests {
use io::prelude::*;
+++ /dev/null
-// Copyright 2013 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.
-
-//! A wrapper around any Read to treat it as an RNG.
-
-#![allow(dead_code)]
-
-use io::prelude::*;
-use rand::Rng;
-
-/// An RNG that reads random bytes straight from a `Read`. This will
-/// work best with an infinite reader, but this is not required.
-///
-/// # Panics
-///
-/// It will panic if it there is insufficient data to fulfill a request.
-pub struct ReaderRng<R> {
- reader: R
-}
-
-impl<R: Read> ReaderRng<R> {
- /// Create a new `ReaderRng` from a `Read`.
- pub fn new(r: R) -> ReaderRng<R> {
- ReaderRng {
- reader: r
- }
- }
-}
-
-impl<R: Read> Rng for ReaderRng<R> {
- fn next_u32(&mut self) -> u32 {
- // This is designed for speed: reading a LE integer on a LE
- // platform just involves blitting the bytes into the memory
- // of the u32, similarly for BE on BE; avoiding byteswapping.
- let mut bytes = [0; 4];
- self.fill_bytes(&mut bytes);
- unsafe { *(bytes.as_ptr() as *const u32) }
- }
- fn next_u64(&mut self) -> u64 {
- // see above for explanation.
- let mut bytes = [0; 8];
- self.fill_bytes(&mut bytes);
- unsafe { *(bytes.as_ptr() as *const u64) }
- }
- fn fill_bytes(&mut self, mut v: &mut [u8]) {
- while !v.is_empty() {
- let t = v;
- match self.reader.read(t) {
- Ok(0) => panic!("ReaderRng.fill_bytes: EOF reached"),
- Ok(n) => v = t.split_at_mut(n).1,
- Err(e) => panic!("ReaderRng.fill_bytes: {}", e),
- }
- }
- }
-}
-
-#[cfg(test)]
-mod tests {
- use super::ReaderRng;
- use rand::Rng;
-
- #[test]
- fn test_reader_rng_u64() {
- // transmute from the target to avoid endianness concerns.
- let v = &[0, 0, 0, 0, 0, 0, 0, 1,
- 0, 0, 0, 0, 0, 0, 0, 2,
- 0, 0, 0, 0, 0, 0, 0, 3][..];
- let mut rng = ReaderRng::new(v);
-
- assert_eq!(rng.next_u64(), 1u64.to_be());
- assert_eq!(rng.next_u64(), 2u64.to_be());
- assert_eq!(rng.next_u64(), 3u64.to_be());
- }
- #[test]
- fn test_reader_rng_u32() {
- let v = &[0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 3][..];
- let mut rng = ReaderRng::new(v);
-
- assert_eq!(rng.next_u32(), 1u32.to_be());
- assert_eq!(rng.next_u32(), 2u32.to_be());
- assert_eq!(rng.next_u32(), 3u32.to_be());
- }
- #[test]
- fn test_reader_rng_fill_bytes() {
- let v = [1, 2, 3, 4, 5, 6, 7, 8];
- let mut w = [0; 8];
-
- let mut rng = ReaderRng::new(&v[..]);
- rng.fill_bytes(&mut w);
-
- assert!(v == w);
- }
-
- #[test]
- #[should_panic]
- fn test_reader_rng_insufficient_bytes() {
- let mut rng = ReaderRng::new(&[][..]);
- let mut v = [0; 3];
- rng.fill_bytes(&mut v);
- }
-}
#![doc(hidden)]
-// Reexport some of our utilities which are expected by other crates.
+// Re-export some of our utilities which are expected by other crates.
pub use panicking::{begin_panic, begin_panic_fmt, update_panic_count};
// To reduce the generated code of the new `lang_start`, this function is doing
// the real work.
-#[cfg(not(any(test, stage0)))]
+#[cfg(not(test))]
fn lang_start_internal(main: &(Fn() -> i32 + Sync + ::panic::RefUnwindSafe),
argc: isize, argv: *const *const u8) -> isize {
use panic;
}
}
-#[cfg(not(any(test, stage0)))]
+#[cfg(not(test))]
#[lang = "start"]
fn lang_start<T: ::termination::Termination + 'static>
(main: fn() -> T, argc: isize, argv: *const *const u8) -> isize
{
lang_start_internal(&move || main().report(), argc, argv)
}
-
-#[cfg(all(not(test), stage0))]
-#[lang = "start"]
-fn lang_start(main: fn(), argc: isize, argv: *const *const u8) -> isize {
- use panic;
- use sys;
- use sys_common;
- use sys_common::thread_info;
- use thread::Thread;
- #[cfg(not(feature = "backtrace"))]
- use mem;
-
- sys::init();
-
- let failed = unsafe {
- let main_guard = sys::thread::guard::init();
- sys::stack_overflow::init();
-
- // Next, set up the current Thread with the guard information we just
- // created. Note that this isn't necessary in general for new threads,
- // but we just do this to name the main thread and to give it correct
- // info about the stack bounds.
- let thread = Thread::new(Some("main".to_owned()));
- thread_info::set(main_guard, thread);
-
- // Store our args if necessary in a squirreled away location
- sys::args::init(argc, argv);
-
- // Let's run some code!
- #[cfg(feature = "backtrace")]
- let res = panic::catch_unwind(|| {
- ::sys_common::backtrace::__rust_begin_short_backtrace(main)
- });
- #[cfg(not(feature = "backtrace"))]
- let res = panic::catch_unwind(mem::transmute::<_, fn()>(main));
- sys_common::cleanup();
- res.is_err()
- };
-
- if failed {
- 101
- } else {
- 0
- }
-}
}
}
-#[stable(feature = "mutex_from", since = "1.22.0")]
+#[stable(feature = "mutex_from", since = "1.24.0")]
impl<T> From<T> for Mutex<T> {
/// Creates a new mutex in an unlocked state ready for use.
/// This is equivalent to [`Mutex::new`].
/// required that `T` satisfies [`Send`] to be shared across threads and
/// [`Sync`] to allow concurrent access through readers. The RAII guards
/// returned from the locking methods implement [`Deref`][] (and [`DerefMut`]
-/// for the `write` methods) to allow access to the contained of the lock.
+/// for the `write` methods) to allow access to the content of the lock.
///
/// # Poisoning
///
}
}
-#[stable(feature = "rw_lock_from", since = "1.22.0")]
+#[stable(feature = "rw_lock_from", since = "1.24.0")]
impl<T> From<T> for RwLock<T> {
/// Creates a new instance of an `RwLock<T>` which is unlocked.
/// This is equivalent to [`RwLock::new`].
--- /dev/null
+// Copyright (c) 2018 Nuxi (https://nuxi.nl/) and contributors.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+// SUCH DAMAGE.
+
+// Appease Rust's tidy.
+// ignore-license
+
+#[cfg(feature = "bitflags")]
+#[macro_use]
+extern crate bitflags;
+
+// Minimal implementation of bitflags! in case we can't depend on the bitflags
+// crate. Only implements `bits()` and a `from_bits_truncate()` that doesn't
+// actually truncate.
+#[cfg(not(feature = "bitflags"))]
+macro_rules! bitflags {
+ (
+ $(#[$attr:meta])*
+ pub struct $name:ident: $type:ty {
+ $($(#[$const_attr:meta])* const $const:ident = $val:expr;)*
+ }
+ ) => {
+ $(#[$attr])*
+ #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
+ pub struct $name { bits: $type }
+ impl $name {
+ $($(#[$const_attr])* pub const $const: $name = $name{ bits: $val };)*
+ pub fn bits(&self) -> $type { self.bits }
+ pub fn from_bits_truncate(bits: $type) -> Self { $name{ bits } }
+ }
+ }
+}
--- /dev/null
+// Copyright (c) 2016-2017 Nuxi (https://nuxi.nl/) and contributors.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+// SUCH DAMAGE.
+//
+// This file is automatically generated. Do not edit.
+//
+// Source: https://github.com/NuxiNL/cloudabi
+
+// Appease Rust's tidy.
+// ignore-license
+// ignore-tidy-linelength
+
+//! **PLEASE NOTE: This entire crate including this
+//! documentation is automatically generated from
+//! [`cloudabi.txt`](https://github.com/NuxiNL/cloudabi/blob/master/cloudabi.txt)**
+//!
+//! # Nuxi CloudABI
+//!
+//! CloudABI is what you get if you take POSIX, add capability-based
+//! security, and remove everything that's incompatible with that. The
+//! result is a minimal ABI consisting of only 49 syscalls.
+//!
+//! CloudABI doesn't have its own kernel, but instead is implemented in existing
+//! kernels: FreeBSD has CloudABI support for x86-64 and arm64, and [a patch-set
+//! for NetBSD](https://github.com/NuxiNL/netbsd) and [a patch-set for
+//! Linux](https://github.com/NuxiNL/linux) are available as well. This means that
+//! CloudABI binaries can be executed on different operating systems, without any
+//! modification.
+//!
+//! ## Capability-Based Security
+//!
+//! Capability-based security means that processes can only perform
+//! actions that have no global impact. Processes cannot open files by
+//! their absolute path, cannot open network connections, and cannot
+//! observe global system state such as the process table.
+//!
+//! The capabilities of a process are fully determined by its set of open
+//! file descriptors (fds). For example, files can only be opened if the
+//! process already has a file descriptor to a directory the file is in.
+//!
+//! Unlike in POSIX, where processes are normally started with file
+//! descriptors 0, 1, and 2 reserved for standard input, output, and
+//! error, CloudABI does not reserve any file descriptor numbers for
+//! specific purposes.
+//!
+//! In CloudABI, a process depends on its parent process to launch it with
+//! the right set of resources, since the process will not be able to open
+//! any new resources. For example, a simple static web server would need
+//! to be started with a file descriptor to a [TCP
+//! listener](https://github.com/NuxiNL/flower), and a file descriptor to
+//! the directory for which to serve files. The web server will then be
+//! unable to do anything other than reading files in that directory, and
+//! process incoming network connections.
+//!
+//! So, unknown CloudABI binaries can safely be executed without the need
+//! for containers, virtual machines, or other sandboxing technologies.
+//!
+//! Watch [Ed Schouten's Talk at
+//! 32C3](https://www.youtube.com/watch?v=3N29vrPoDv8) for more
+//! information about what capability-based security for UNIX means.
+//!
+//! ## Cloudlibc
+//!
+//! [Cloudlibc](https://github.com/NuxiNL/cloudlibc) is an implementation
+//! of the C standard library, without all CloudABI-incompatible
+//! functions. For example, Cloudlibc does not have `printf`, but does
+//! have `fprintf`. It does not have `open`, but does have `openat`.
+//!
+//! ## CloudABI-Ports
+//!
+//! [CloudABI-Ports](https://github.com/NuxiNL/cloudabi-ports) is a
+//! collection of ports of commonly used libraries and applications to
+//! CloudABI. It contains software such as `zlib`, `libpng`, `boost`,
+//! `memcached`, and much more. The software is patched to not depend on
+//! any global state, such as files in `/etc` or `/dev`, using `open()`,
+//! etc.
+//!
+//! ## Using CloudABI
+//!
+//! Instructions for using CloudABI (including kernel modules/patches,
+//! toolchain, and ports) are available for several operating systems:
+//!
+//! - [Arch Linux](https://nuxi.nl/cloudabi/archlinux/)
+//! - [Debian, Ubuntu, and other Debian derivatives](https://nuxi.nl/cloudabi/debian/)
+//! - [FreeBSD, PC-BSD and DragonFly BSD](https://nuxi.nl/cloudabi/freebsd/)
+//! - [Mac OS X](https://nuxi.nl/cloudabi/mac/)
+//! - [NetBSD](https://nuxi.nl/cloudabi/netbsd/)
+//!
+//! ## Specification of the ABI
+//!
+//! The entire ABI is specified in a a file called
+//! [`cloudabi.txt`](https://github.com/NuxiNL/cloudabi/blob/master/cloudabi.txt),
+//! from which all
+//! [headers](https://github.com/NuxiNL/cloudabi/tree/master/headers)
+//! and documentation (including the one you're reading now) is generated.
+
+#![no_std]
+#![allow(non_camel_case_types)]
+
+include!("bitflags.rs");
+
+/// File or memory access pattern advisory information.
+#[repr(u8)]
+#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
+pub enum advice {
+ /// The application expects that it will not access the
+ /// specified data in the near future.
+ DONTNEED = 1,
+ /// The application expects to access the specified data
+ /// once and then not reuse it thereafter.
+ NOREUSE = 2,
+ /// The application has no advice to give on its behavior
+ /// with respect to the specified data.
+ NORMAL = 3,
+ /// The application expects to access the specified data
+ /// in a random order.
+ RANDOM = 4,
+ /// The application expects to access the specified data
+ /// sequentially from lower offsets to higher offsets.
+ SEQUENTIAL = 5,
+ /// The application expects to access the specified data
+ /// in the near future.
+ WILLNEED = 6,
+ #[doc(hidden)] _NonExhaustive = -1 as isize as u8,
+}
+
+/// Enumeration describing the kind of value stored in [`auxv`](struct.auxv.html).
+#[repr(u32)]
+#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
+pub enum auxtype {
+ /// Base address of the binary argument data provided to
+ /// [`proc_exec()`](fn.proc_exec.html).
+ ARGDATA = 256,
+ /// Length of the binary argument data provided to
+ /// [`proc_exec()`](fn.proc_exec.html).
+ ARGDATALEN = 257,
+ /// Base address at which the executable is placed in
+ /// memory.
+ BASE = 7,
+ /// Base address of a buffer of random data that may be
+ /// used for non-cryptographic purposes, for example as a
+ /// canary for stack smashing protection.
+ CANARY = 258,
+ /// Length of a buffer of random data that may be used
+ /// for non-cryptographic purposes, for example as a
+ /// canary for stack smashing protection.
+ CANARYLEN = 259,
+ /// Number of CPUs that the system this process is running
+ /// on has.
+ NCPUS = 260,
+ /// Terminator of the auxiliary vector.
+ NULL = 0,
+ /// Smallest memory object size for which individual
+ /// memory protection controls can be configured.
+ PAGESZ = 6,
+ /// Address of the first ELF program header of the
+ /// executable.
+ PHDR = 3,
+ /// Number of ELF program headers of the executable.
+ PHNUM = 4,
+ /// Identifier of the process.
+ ///
+ /// This environment does not provide any simple numerical
+ /// process identifiers, for the reason that these are not
+ /// useful in distributed contexts. Instead, processes are
+ /// identified by a UUID.
+ ///
+ /// This record should point to sixteen bytes of binary
+ /// data, containing a version 4 UUID (fully random).
+ PID = 263,
+ /// Address of the ELF header of the vDSO.
+ ///
+ /// The vDSO is a shared library that is mapped in the
+ /// address space of the process. It provides entry points
+ /// for every system call supported by the environment,
+ /// all having a corresponding symbol that is prefixed
+ /// with `cloudabi_sys_`. System calls should be invoked
+ /// through these entry points.
+ ///
+ /// The first advantage of letting processes call into a
+ /// vDSO to perform system calls instead of raising
+ /// hardware traps is that it allows for easy emulation of
+ /// executables on top of existing operating systems. The
+ /// second advantage is that in cases where an operating
+ /// system provides native support for CloudABI executables,
+ /// it may still implement partial userspace
+ /// implementations of these system calls to improve
+ /// performance (e.g., [`clock_time_get()`](fn.clock_time_get.html)). It also provides
+ /// a more dynamic way of adding, removing or replacing
+ /// system calls.
+ SYSINFO_EHDR = 262,
+ /// Thread ID of the initial thread of the process.
+ TID = 261,
+ #[doc(hidden)] _NonExhaustive = -1 as isize as u32,
+}
+
+/// Identifiers for clocks.
+#[repr(u32)]
+#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
+pub enum clockid {
+ /// The system-wide monotonic clock, which is defined as a
+ /// clock measuring real time, whose value cannot be
+ /// adjusted and which cannot have negative clock jumps.
+ ///
+ /// The epoch of this clock is undefined. The absolute
+ /// time value of this clock therefore has no meaning.
+ MONOTONIC = 1,
+ /// The CPU-time clock associated with the current
+ /// process.
+ PROCESS_CPUTIME_ID = 2,
+ /// The system-wide clock measuring real time. Time value
+ /// zero corresponds with 1970-01-01T00:00:00Z.
+ REALTIME = 3,
+ /// The CPU-time clock associated with the current thread.
+ THREAD_CPUTIME_ID = 4,
+ #[doc(hidden)] _NonExhaustive = -1 as isize as u32,
+}
+
+/// A userspace condition variable.
+#[repr(C)]
+#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
+pub struct condvar(pub u32);
+/// The condition variable is in its initial state. There
+/// are no threads waiting to be woken up. If the
+/// condition variable has any other value, the kernel
+/// must be called to wake up any sleeping threads.
+pub const CONDVAR_HAS_NO_WAITERS: condvar = condvar(0);
+
+/// Identifier for a device containing a file system. Can be used
+/// in combination with [`inode`](struct.inode.html) to uniquely identify a file on the
+/// local system.
+#[repr(C)]
+#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
+pub struct device(pub u64);
+
+/// A reference to the offset of a directory entry.
+#[repr(C)]
+#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
+pub struct dircookie(pub u64);
+/// Permanent reference to the first directory entry
+/// within a directory.
+pub const DIRCOOKIE_START: dircookie = dircookie(0);
+
+/// Error codes returned by system calls.
+///
+/// Not all of these error codes are returned by the system calls
+/// provided by this environment, but are either used in userspace
+/// exclusively or merely provided for alignment with POSIX.
+#[repr(u16)]
+#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
+pub enum errno {
+ /// No error occurred. System call completed successfully.
+ SUCCESS = 0,
+ /// Argument list too long.
+ TOOBIG = 1,
+ /// Permission denied.
+ ACCES = 2,
+ /// Address in use.
+ ADDRINUSE = 3,
+ /// Address not available.
+ ADDRNOTAVAIL = 4,
+ /// Address family not supported.
+ AFNOSUPPORT = 5,
+ /// Resource unavailable, or operation would block.
+ AGAIN = 6,
+ /// Connection already in progress.
+ ALREADY = 7,
+ /// Bad file descriptor.
+ BADF = 8,
+ /// Bad message.
+ BADMSG = 9,
+ /// Device or resource busy.
+ BUSY = 10,
+ /// Operation canceled.
+ CANCELED = 11,
+ /// No child processes.
+ CHILD = 12,
+ /// Connection aborted.
+ CONNABORTED = 13,
+ /// Connection refused.
+ CONNREFUSED = 14,
+ /// Connection reset.
+ CONNRESET = 15,
+ /// Resource deadlock would occur.
+ DEADLK = 16,
+ /// Destination address required.
+ DESTADDRREQ = 17,
+ /// Mathematics argument out of domain of function.
+ DOM = 18,
+ /// Reserved.
+ DQUOT = 19,
+ /// File exists.
+ EXIST = 20,
+ /// Bad address.
+ FAULT = 21,
+ /// File too large.
+ FBIG = 22,
+ /// Host is unreachable.
+ HOSTUNREACH = 23,
+ /// Identifier removed.
+ IDRM = 24,
+ /// Illegal byte sequence.
+ ILSEQ = 25,
+ /// Operation in progress.
+ INPROGRESS = 26,
+ /// Interrupted function.
+ INTR = 27,
+ /// Invalid argument.
+ INVAL = 28,
+ /// I/O error.
+ IO = 29,
+ /// Socket is connected.
+ ISCONN = 30,
+ /// Is a directory.
+ ISDIR = 31,
+ /// Too many levels of symbolic links.
+ LOOP = 32,
+ /// File descriptor value too large.
+ MFILE = 33,
+ /// Too many links.
+ MLINK = 34,
+ /// Message too large.
+ MSGSIZE = 35,
+ /// Reserved.
+ MULTIHOP = 36,
+ /// Filename too long.
+ NAMETOOLONG = 37,
+ /// Network is down.
+ NETDOWN = 38,
+ /// Connection aborted by network.
+ NETRESET = 39,
+ /// Network unreachable.
+ NETUNREACH = 40,
+ /// Too many files open in system.
+ NFILE = 41,
+ /// No buffer space available.
+ NOBUFS = 42,
+ /// No such device.
+ NODEV = 43,
+ /// No such file or directory.
+ NOENT = 44,
+ /// Executable file format error.
+ NOEXEC = 45,
+ /// No locks available.
+ NOLCK = 46,
+ /// Reserved.
+ NOLINK = 47,
+ /// Not enough space.
+ NOMEM = 48,
+ /// No message of the desired type.
+ NOMSG = 49,
+ /// Protocol not available.
+ NOPROTOOPT = 50,
+ /// No space left on device.
+ NOSPC = 51,
+ /// Function not supported.
+ NOSYS = 52,
+ /// The socket is not connected.
+ NOTCONN = 53,
+ /// Not a directory or a symbolic link to a directory.
+ NOTDIR = 54,
+ /// Directory not empty.
+ NOTEMPTY = 55,
+ /// State not recoverable.
+ NOTRECOVERABLE = 56,
+ /// Not a socket.
+ NOTSOCK = 57,
+ /// Not supported, or operation not supported on socket.
+ NOTSUP = 58,
+ /// Inappropriate I/O control operation.
+ NOTTY = 59,
+ /// No such device or address.
+ NXIO = 60,
+ /// Value too large to be stored in data type.
+ OVERFLOW = 61,
+ /// Previous owner died.
+ OWNERDEAD = 62,
+ /// Operation not permitted.
+ PERM = 63,
+ /// Broken pipe.
+ PIPE = 64,
+ /// Protocol error.
+ PROTO = 65,
+ /// Protocol not supported.
+ PROTONOSUPPORT = 66,
+ /// Protocol wrong type for socket.
+ PROTOTYPE = 67,
+ /// Result too large.
+ RANGE = 68,
+ /// Read-only file system.
+ ROFS = 69,
+ /// Invalid seek.
+ SPIPE = 70,
+ /// No such process.
+ SRCH = 71,
+ /// Reserved.
+ STALE = 72,
+ /// Connection timed out.
+ TIMEDOUT = 73,
+ /// Text file busy.
+ TXTBSY = 74,
+ /// Cross-device link.
+ XDEV = 75,
+ /// Extension: Capabilities insufficient.
+ NOTCAPABLE = 76,
+ #[doc(hidden)] _NonExhaustive = -1 as isize as u16,
+}
+
+bitflags! {
+ /// The state of the file descriptor subscribed to with
+ /// [`FD_READ`](enum.eventtype.html#variant.FD_READ) or [`FD_WRITE`](enum.eventtype.html#variant.FD_WRITE).
+ #[repr(C)]
+ pub struct eventrwflags: u16 {
+ /// The peer of this socket has closed or disconnected.
+ const HANGUP = 0x0001;
+ }
+}
+
+/// Type of a subscription to an event or its occurrence.
+#[repr(u8)]
+#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
+pub enum eventtype {
+ /// The time value of clock [`subscription.union.clock.clock_id`](struct.subscription_clock.html#structfield.clock_id)
+ /// has reached timestamp [`subscription.union.clock.timeout`](struct.subscription_clock.html#structfield.timeout).
+ CLOCK = 1,
+ /// Condition variable [`subscription.union.condvar.condvar`](struct.subscription_condvar.html#structfield.condvar) has
+ /// been woken up and [`subscription.union.condvar.lock`](struct.subscription_condvar.html#structfield.lock) has been
+ /// acquired for writing.
+ CONDVAR = 2,
+ /// File descriptor [`subscription.union.fd_readwrite.fd`](struct.subscription_fd_readwrite.html#structfield.fd) has
+ /// data available for reading. This event always triggers
+ /// for regular files.
+ FD_READ = 3,
+ /// File descriptor [`subscription.union.fd_readwrite.fd`](struct.subscription_fd_readwrite.html#structfield.fd) has
+ /// capacity available for writing. This event always
+ /// triggers for regular files.
+ FD_WRITE = 4,
+ /// Lock [`subscription.union.lock.lock`](struct.subscription_lock.html#structfield.lock) has been acquired for
+ /// reading.
+ LOCK_RDLOCK = 5,
+ /// Lock [`subscription.union.lock.lock`](struct.subscription_lock.html#structfield.lock) has been acquired for
+ /// writing.
+ LOCK_WRLOCK = 6,
+ /// The process associated with process descriptor
+ /// [`subscription.union.proc_terminate.fd`](struct.subscription_proc_terminate.html#structfield.fd) has terminated.
+ PROC_TERMINATE = 7,
+ #[doc(hidden)] _NonExhaustive = -1 as isize as u8,
+}
+
+/// Exit code generated by a process when exiting.
+pub type exitcode = u32;
+
+/// A file descriptor number.
+///
+/// Unlike on POSIX-compliant systems, none of the file descriptor
+/// numbers are reserved for a purpose (e.g., stdin, stdout,
+/// stderr). Operating systems are not required to allocate new
+/// file descriptors in ascending order.
+#[repr(C)]
+#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
+pub struct fd(pub u32);
+/// Returned to the child process by [`proc_fork()`](fn.proc_fork.html).
+pub const PROCESS_CHILD: fd = fd(0xffffffff);
+/// Passed to [`mem_map()`](fn.mem_map.html) when creating a mapping to
+/// anonymous memory.
+pub const MAP_ANON_FD : fd = fd(0xffffffff);
+
+bitflags! {
+ /// File descriptor flags.
+ #[repr(C)]
+ pub struct fdflags: u16 {
+ /// Append mode: Data written to the file is always
+ /// appended to the file's end.
+ const APPEND = 0x0001;
+ /// Write according to synchronized I/O data integrity
+ /// completion. Only the data stored in the file is
+ /// synchronized.
+ const DSYNC = 0x0002;
+ /// Non-blocking mode.
+ const NONBLOCK = 0x0004;
+ /// Synchronized read I/O operations.
+ const RSYNC = 0x0008;
+ /// Write according to synchronized I/O file integrity
+ /// completion. In addition to synchronizing the data
+ /// stored in the file, the system may also synchronously
+ /// update the file's metadata.
+ const SYNC = 0x0010;
+ }
+}
+
+bitflags! {
+ /// Which file descriptor attributes to adjust.
+ #[repr(C)]
+ pub struct fdsflags: u16 {
+ /// Adjust the file descriptor flags stored in
+ /// [`fdstat.fs_flags`](struct.fdstat.html#structfield.fs_flags).
+ const FLAGS = 0x0001;
+ /// Restrict the rights of the file descriptor to the
+ /// rights stored in [`fdstat.fs_rights_base`](struct.fdstat.html#structfield.fs_rights_base) and
+ /// [`fdstat.fs_rights_inheriting`](struct.fdstat.html#structfield.fs_rights_inheriting).
+ const RIGHTS = 0x0002;
+ }
+}
+
+/// Relative offset within a file.
+pub type filedelta = i64;
+
+/// Non-negative file size or length of a region within a file.
+pub type filesize = u64;
+
+/// The type of a file descriptor or file.
+#[repr(u8)]
+#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
+pub enum filetype {
+ /// The type of the file descriptor or file is unknown or
+ /// is different from any of the other types specified.
+ UNKNOWN = 0,
+ /// The file descriptor or file refers to a block device
+ /// inode.
+ BLOCK_DEVICE = 16,
+ /// The file descriptor or file refers to a character
+ /// device inode.
+ CHARACTER_DEVICE = 17,
+ /// The file descriptor or file refers to a directory
+ /// inode.
+ DIRECTORY = 32,
+ /// The file descriptor refers to a process handle.
+ PROCESS = 80,
+ /// The file descriptor or file refers to a regular file
+ /// inode.
+ REGULAR_FILE = 96,
+ /// The file descriptor refers to a shared memory object.
+ SHARED_MEMORY = 112,
+ /// The file descriptor or file refers to a datagram
+ /// socket.
+ SOCKET_DGRAM = 128,
+ /// The file descriptor or file refers to a byte-stream
+ /// socket.
+ SOCKET_STREAM = 130,
+ /// The file refers to a symbolic link inode.
+ SYMBOLIC_LINK = 144,
+ #[doc(hidden)] _NonExhaustive = -1 as isize as u8,
+}
+
+bitflags! {
+ /// Which file attributes to adjust.
+ #[repr(C)]
+ pub struct fsflags: u16 {
+ /// Adjust the last data access timestamp to the value
+ /// stored in [`filestat.st_atim`](struct.filestat.html#structfield.st_atim).
+ const ATIM = 0x0001;
+ /// Adjust the last data access timestamp to the time
+ /// of clock [`REALTIME`](enum.clockid.html#variant.REALTIME).
+ const ATIM_NOW = 0x0002;
+ /// Adjust the last data modification timestamp to the
+ /// value stored in [`filestat.st_mtim`](struct.filestat.html#structfield.st_mtim).
+ const MTIM = 0x0004;
+ /// Adjust the last data modification timestamp to the
+ /// time of clock [`REALTIME`](enum.clockid.html#variant.REALTIME).
+ const MTIM_NOW = 0x0008;
+ /// Truncate or extend the file to the size stored in
+ /// [`filestat.st_size`](struct.filestat.html#structfield.st_size).
+ const SIZE = 0x0010;
+ }
+}
+
+/// File serial number that is unique within its file system.
+#[repr(C)]
+#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
+pub struct inode(pub u64);
+
+/// Number of hard links to an inode.
+pub type linkcount = u32;
+
+/// A userspace read-recursive readers-writer lock, similar to a
+/// Linux futex or a FreeBSD umtx.
+#[repr(C)]
+#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
+pub struct lock(pub u32);
+/// Value indicating that the lock is in its initial
+/// unlocked state.
+pub const LOCK_UNLOCKED : lock = lock(0x00000000);
+/// Bitmask indicating that the lock is write-locked. If
+/// set, the lower 30 bits of the lock contain the
+/// identifier of the thread that owns the write lock.
+/// Otherwise, the lower 30 bits of the lock contain the
+/// number of acquired read locks.
+pub const LOCK_WRLOCKED : lock = lock(0x40000000);
+/// Bitmask indicating that the lock is either read locked
+/// or write locked, and that one or more threads have
+/// their execution suspended, waiting to acquire the
+/// lock. The last owner of the lock must call the
+/// kernel to unlock.
+///
+/// When the lock is acquired for reading and this bit is
+/// set, it means that one or more threads are attempting
+/// to acquire this lock for writing. In that case, other
+/// threads should only acquire additional read locks if
+/// suspending execution would cause a deadlock. It is
+/// preferred to suspend execution, as this prevents
+/// starvation of writers.
+pub const LOCK_KERNEL_MANAGED: lock = lock(0x80000000);
+/// Value indicating that the lock is in an incorrect
+/// state. A lock cannot be in its initial unlocked state,
+/// while also managed by the kernel.
+pub const LOCK_BOGUS : lock = lock(0x80000000);
+
+bitflags! {
+ /// Flags determining the method of how paths are resolved.
+ #[repr(C)]
+ pub struct lookupflags: u32 {
+ /// As long as the resolved path corresponds to a symbolic
+ /// link, it is expanded.
+ const SYMLINK_FOLLOW = 0x00000001;
+ }
+}
+
+bitflags! {
+ /// Memory mapping flags.
+ #[repr(C)]
+ pub struct mflags: u8 {
+ /// Instead of mapping the contents of the file provided,
+ /// create a mapping to anonymous memory. The file
+ /// descriptor argument must be set to [`MAP_ANON_FD`](constant.MAP_ANON_FD.html),
+ /// and the offset must be set to zero.
+ const ANON = 0x01;
+ /// Require that the mapping is performed at the base
+ /// address provided.
+ const FIXED = 0x02;
+ /// Changes are private.
+ const PRIVATE = 0x04;
+ /// Changes are shared.
+ const SHARED = 0x08;
+ }
+}
+
+bitflags! {
+ /// Memory page protection options.
+ ///
+ /// This implementation enforces the `W^X` property: Pages cannot be
+ /// mapped for execution while also mapped for writing.
+ #[repr(C)]
+ pub struct mprot: u8 {
+ /// Page can be executed.
+ const EXEC = 0x01;
+ /// Page can be written.
+ const WRITE = 0x02;
+ /// Page can be read.
+ const READ = 0x04;
+ }
+}
+
+bitflags! {
+ /// Methods of synchronizing memory with physical storage.
+ #[repr(C)]
+ pub struct msflags: u8 {
+ /// Perform asynchronous writes.
+ const ASYNC = 0x01;
+ /// Invalidate cached data.
+ const INVALIDATE = 0x02;
+ /// Perform synchronous writes.
+ const SYNC = 0x04;
+ }
+}
+
+/// Specifies the number of threads sleeping on a condition
+/// variable that should be woken up.
+pub type nthreads = u32;
+
+bitflags! {
+ /// Open flags used by [`file_open()`](fn.file_open.html).
+ #[repr(C)]
+ pub struct oflags: u16 {
+ /// Create file if it does not exist.
+ const CREAT = 0x0001;
+ /// Fail if not a directory.
+ const DIRECTORY = 0x0002;
+ /// Fail if file already exists.
+ const EXCL = 0x0004;
+ /// Truncate file to size 0.
+ const TRUNC = 0x0008;
+ }
+}
+
+bitflags! {
+ /// Flags provided to [`sock_recv()`](fn.sock_recv.html).
+ #[repr(C)]
+ pub struct riflags: u16 {
+ /// Returns the message without removing it from the
+ /// socket's receive queue.
+ const PEEK = 0x0004;
+ /// On byte-stream sockets, block until the full amount
+ /// of data can be returned.
+ const WAITALL = 0x0010;
+ }
+}
+
+bitflags! {
+ /// File descriptor rights, determining which actions may be
+ /// performed.
+ #[repr(C)]
+ pub struct rights: u64 {
+ /// The right to invoke [`fd_datasync()`](fn.fd_datasync.html).
+ ///
+ /// If [`FILE_OPEN`](struct.rights.html#associatedconstant.FILE_OPEN) is set, includes the right to
+ /// invoke [`file_open()`](fn.file_open.html) with [`DSYNC`](struct.fdflags.html#associatedconstant.DSYNC).
+ const FD_DATASYNC = 0x0000000000000001;
+ /// The right to invoke [`fd_read()`](fn.fd_read.html) and [`sock_recv()`](fn.sock_recv.html).
+ ///
+ /// If [`MEM_MAP`](struct.rights.html#associatedconstant.MEM_MAP) is set, includes the right to
+ /// invoke [`mem_map()`](fn.mem_map.html) with memory protection option
+ /// [`READ`](struct.mprot.html#associatedconstant.READ).
+ ///
+ /// If [`FD_SEEK`](struct.rights.html#associatedconstant.FD_SEEK) is set, includes the right to invoke
+ /// [`fd_pread()`](fn.fd_pread.html).
+ const FD_READ = 0x0000000000000002;
+ /// The right to invoke [`fd_seek()`](fn.fd_seek.html). This flag implies
+ /// [`FD_TELL`](struct.rights.html#associatedconstant.FD_TELL).
+ const FD_SEEK = 0x0000000000000004;
+ /// The right to invoke [`fd_stat_put()`](fn.fd_stat_put.html) with
+ /// [`FLAGS`](struct.fdsflags.html#associatedconstant.FLAGS).
+ const FD_STAT_PUT_FLAGS = 0x0000000000000008;
+ /// The right to invoke [`fd_sync()`](fn.fd_sync.html).
+ ///
+ /// If [`FILE_OPEN`](struct.rights.html#associatedconstant.FILE_OPEN) is set, includes the right to
+ /// invoke [`file_open()`](fn.file_open.html) with [`RSYNC`](struct.fdflags.html#associatedconstant.RSYNC) and
+ /// [`DSYNC`](struct.fdflags.html#associatedconstant.DSYNC).
+ const FD_SYNC = 0x0000000000000010;
+ /// The right to invoke [`fd_seek()`](fn.fd_seek.html) in such a way that the
+ /// file offset remains unaltered (i.e., [`CUR`](enum.whence.html#variant.CUR) with
+ /// offset zero).
+ const FD_TELL = 0x0000000000000020;
+ /// The right to invoke [`fd_write()`](fn.fd_write.html) and [`sock_send()`](fn.sock_send.html).
+ ///
+ /// If [`MEM_MAP`](struct.rights.html#associatedconstant.MEM_MAP) is set, includes the right to
+ /// invoke [`mem_map()`](fn.mem_map.html) with memory protection option
+ /// [`WRITE`](struct.mprot.html#associatedconstant.WRITE).
+ ///
+ /// If [`FD_SEEK`](struct.rights.html#associatedconstant.FD_SEEK) is set, includes the right to
+ /// invoke [`fd_pwrite()`](fn.fd_pwrite.html).
+ const FD_WRITE = 0x0000000000000040;
+ /// The right to invoke [`file_advise()`](fn.file_advise.html).
+ const FILE_ADVISE = 0x0000000000000080;
+ /// The right to invoke [`file_allocate()`](fn.file_allocate.html).
+ const FILE_ALLOCATE = 0x0000000000000100;
+ /// The right to invoke [`file_create()`](fn.file_create.html) with
+ /// [`DIRECTORY`](enum.filetype.html#variant.DIRECTORY).
+ const FILE_CREATE_DIRECTORY = 0x0000000000000200;
+ /// If [`FILE_OPEN`](struct.rights.html#associatedconstant.FILE_OPEN) is set, the right to invoke
+ /// [`file_open()`](fn.file_open.html) with [`CREAT`](struct.oflags.html#associatedconstant.CREAT).
+ const FILE_CREATE_FILE = 0x0000000000000400;
+ /// The right to invoke [`file_link()`](fn.file_link.html) with the file
+ /// descriptor as the source directory.
+ const FILE_LINK_SOURCE = 0x0000000000001000;
+ /// The right to invoke [`file_link()`](fn.file_link.html) with the file
+ /// descriptor as the target directory.
+ const FILE_LINK_TARGET = 0x0000000000002000;
+ /// The right to invoke [`file_open()`](fn.file_open.html).
+ const FILE_OPEN = 0x0000000000004000;
+ /// The right to invoke [`file_readdir()`](fn.file_readdir.html).
+ const FILE_READDIR = 0x0000000000008000;
+ /// The right to invoke [`file_readlink()`](fn.file_readlink.html).
+ const FILE_READLINK = 0x0000000000010000;
+ /// The right to invoke [`file_rename()`](fn.file_rename.html) with the file
+ /// descriptor as the source directory.
+ const FILE_RENAME_SOURCE = 0x0000000000020000;
+ /// The right to invoke [`file_rename()`](fn.file_rename.html) with the file
+ /// descriptor as the target directory.
+ const FILE_RENAME_TARGET = 0x0000000000040000;
+ /// The right to invoke [`file_stat_fget()`](fn.file_stat_fget.html).
+ const FILE_STAT_FGET = 0x0000000000080000;
+ /// The right to invoke [`file_stat_fput()`](fn.file_stat_fput.html) with
+ /// [`SIZE`](struct.fsflags.html#associatedconstant.SIZE).
+ ///
+ /// If [`FILE_OPEN`](struct.rights.html#associatedconstant.FILE_OPEN) is set, includes the right to
+ /// invoke [`file_open()`](fn.file_open.html) with [`TRUNC`](struct.oflags.html#associatedconstant.TRUNC).
+ const FILE_STAT_FPUT_SIZE = 0x0000000000100000;
+ /// The right to invoke [`file_stat_fput()`](fn.file_stat_fput.html) with
+ /// [`ATIM`](struct.fsflags.html#associatedconstant.ATIM), [`ATIM_NOW`](struct.fsflags.html#associatedconstant.ATIM_NOW), [`MTIM`](struct.fsflags.html#associatedconstant.MTIM),
+ /// and [`MTIM_NOW`](struct.fsflags.html#associatedconstant.MTIM_NOW).
+ const FILE_STAT_FPUT_TIMES = 0x0000000000200000;
+ /// The right to invoke [`file_stat_get()`](fn.file_stat_get.html).
+ const FILE_STAT_GET = 0x0000000000400000;
+ /// The right to invoke [`file_stat_put()`](fn.file_stat_put.html) with
+ /// [`ATIM`](struct.fsflags.html#associatedconstant.ATIM), [`ATIM_NOW`](struct.fsflags.html#associatedconstant.ATIM_NOW), [`MTIM`](struct.fsflags.html#associatedconstant.MTIM),
+ /// and [`MTIM_NOW`](struct.fsflags.html#associatedconstant.MTIM_NOW).
+ const FILE_STAT_PUT_TIMES = 0x0000000000800000;
+ /// The right to invoke [`file_symlink()`](fn.file_symlink.html).
+ const FILE_SYMLINK = 0x0000000001000000;
+ /// The right to invoke [`file_unlink()`](fn.file_unlink.html).
+ const FILE_UNLINK = 0x0000000002000000;
+ /// The right to invoke [`mem_map()`](fn.mem_map.html) with [`mprot`](struct.mprot.html) set to
+ /// zero.
+ const MEM_MAP = 0x0000000004000000;
+ /// If [`MEM_MAP`](struct.rights.html#associatedconstant.MEM_MAP) is set, the right to invoke
+ /// [`mem_map()`](fn.mem_map.html) with [`EXEC`](struct.mprot.html#associatedconstant.EXEC).
+ const MEM_MAP_EXEC = 0x0000000008000000;
+ /// If [`FD_READ`](struct.rights.html#associatedconstant.FD_READ) is set, includes the right to
+ /// invoke [`poll()`](fn.poll.html) to subscribe to [`FD_READ`](enum.eventtype.html#variant.FD_READ).
+ ///
+ /// If [`FD_WRITE`](struct.rights.html#associatedconstant.FD_WRITE) is set, includes the right to
+ /// invoke [`poll()`](fn.poll.html) to subscribe to [`FD_WRITE`](enum.eventtype.html#variant.FD_WRITE).
+ const POLL_FD_READWRITE = 0x0000000010000000;
+ /// The right to invoke [`poll()`](fn.poll.html) to subscribe to
+ /// [`PROC_TERMINATE`](enum.eventtype.html#variant.PROC_TERMINATE).
+ const POLL_PROC_TERMINATE = 0x0000000040000000;
+ /// The right to invoke [`proc_exec()`](fn.proc_exec.html).
+ const PROC_EXEC = 0x0000000100000000;
+ /// The right to invoke [`sock_shutdown()`](fn.sock_shutdown.html).
+ const SOCK_SHUTDOWN = 0x0000008000000000;
+ }
+}
+
+bitflags! {
+ /// Flags returned by [`sock_recv()`](fn.sock_recv.html).
+ #[repr(C)]
+ pub struct roflags: u16 {
+ /// Returned by [`sock_recv()`](fn.sock_recv.html): List of file descriptors
+ /// has been truncated.
+ const FDS_TRUNCATED = 0x0001;
+ /// Returned by [`sock_recv()`](fn.sock_recv.html): Message data has been
+ /// truncated.
+ const DATA_TRUNCATED = 0x0008;
+ }
+}
+
+/// Indicates whether an object is stored in private or shared
+/// memory.
+#[repr(u8)]
+#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
+pub enum scope {
+ /// The object is stored in private memory.
+ PRIVATE = 4,
+ /// The object is stored in shared memory.
+ SHARED = 8,
+ #[doc(hidden)] _NonExhaustive = -1 as isize as u8,
+}
+
+bitflags! {
+ /// Which channels on a socket need to be shut down.
+ #[repr(C)]
+ pub struct sdflags: u8 {
+ /// Disables further receive operations.
+ const RD = 0x01;
+ /// Disables further send operations.
+ const WR = 0x02;
+ }
+}
+
+bitflags! {
+ /// Flags provided to [`sock_send()`](fn.sock_send.html). As there are currently no flags
+ /// defined, it must be set to zero.
+ #[repr(C)]
+ pub struct siflags: u16 {
+ const DEFAULT = 0;
+ }
+}
+
+/// Signal condition.
+#[repr(u8)]
+#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
+pub enum signal {
+ /// Process abort signal.
+ ///
+ /// Action: Terminates the process.
+ ABRT = 1,
+ /// Alarm clock.
+ ///
+ /// Action: Terminates the process.
+ ALRM = 2,
+ /// Access to an undefined portion of a memory object.
+ ///
+ /// Action: Terminates the process.
+ BUS = 3,
+ /// Child process terminated, stopped, or continued.
+ ///
+ /// Action: Ignored.
+ CHLD = 4,
+ /// Continue executing, if stopped.
+ ///
+ /// Action: Continues executing, if stopped.
+ CONT = 5,
+ /// Erroneous arithmetic operation.
+ ///
+ /// Action: Terminates the process.
+ FPE = 6,
+ /// Hangup.
+ ///
+ /// Action: Terminates the process.
+ HUP = 7,
+ /// Illegal instruction.
+ ///
+ /// Action: Terminates the process.
+ ILL = 8,
+ /// Terminate interrupt signal.
+ ///
+ /// Action: Terminates the process.
+ INT = 9,
+ /// Kill.
+ ///
+ /// Action: Terminates the process.
+ KILL = 10,
+ /// Write on a pipe with no one to read it.
+ ///
+ /// Action: Ignored.
+ PIPE = 11,
+ /// Terminal quit signal.
+ ///
+ /// Action: Terminates the process.
+ QUIT = 12,
+ /// Invalid memory reference.
+ ///
+ /// Action: Terminates the process.
+ SEGV = 13,
+ /// Stop executing.
+ ///
+ /// Action: Stops executing.
+ STOP = 14,
+ /// Bad system call.
+ ///
+ /// Action: Terminates the process.
+ SYS = 15,
+ /// Termination signal.
+ ///
+ /// Action: Terminates the process.
+ TERM = 16,
+ /// Trace/breakpoint trap.
+ ///
+ /// Action: Terminates the process.
+ TRAP = 17,
+ /// Terminal stop signal.
+ ///
+ /// Action: Stops executing.
+ TSTP = 18,
+ /// Background process attempting read.
+ ///
+ /// Action: Stops executing.
+ TTIN = 19,
+ /// Background process attempting write.
+ ///
+ /// Action: Stops executing.
+ TTOU = 20,
+ /// High bandwidth data is available at a socket.
+ ///
+ /// Action: Ignored.
+ URG = 21,
+ /// User-defined signal 1.
+ ///
+ /// Action: Terminates the process.
+ USR1 = 22,
+ /// User-defined signal 2.
+ ///
+ /// Action: Terminates the process.
+ USR2 = 23,
+ /// Virtual timer expired.
+ ///
+ /// Action: Terminates the process.
+ VTALRM = 24,
+ /// CPU time limit exceeded.
+ ///
+ /// Action: Terminates the process.
+ XCPU = 25,
+ /// File size limit exceeded.
+ ///
+ /// Action: Terminates the process.
+ XFSZ = 26,
+ #[doc(hidden)] _NonExhaustive = -1 as isize as u8,
+}
+
+bitflags! {
+ /// Flags determining how the timestamp provided in
+ /// [`subscription.union.clock.timeout`](struct.subscription_clock.html#structfield.timeout) should be interpreted.
+ #[repr(C)]
+ pub struct subclockflags: u16 {
+ /// If set, treat the timestamp provided in
+ /// [`subscription.union.clock.timeout`](struct.subscription_clock.html#structfield.timeout) as an absolute timestamp
+ /// of clock [`subscription.union.clock.clock_id`](struct.subscription_clock.html#structfield.clock_id).
+ ///
+ /// If clear, treat the timestamp provided in
+ /// [`subscription.union.clock.timeout`](struct.subscription_clock.html#structfield.timeout) relative to the current
+ /// time value of clock [`subscription.union.clock.clock_id`](struct.subscription_clock.html#structfield.clock_id).
+ const ABSTIME = 0x0001;
+ }
+}
+
+bitflags! {
+ /// Flags influencing the method of polling for read or writing on
+ /// a file descriptor.
+ #[repr(C)]
+ pub struct subrwflags: u16 {
+ /// Deprecated. Must be set by callers and ignored by
+ /// implementations.
+ const POLL = 0x0001;
+ }
+}
+
+/// Unique system-local identifier of a thread. This identifier is
+/// only valid during the lifetime of the thread.
+///
+/// Threads must be aware of their thread identifier, as it is
+/// written it into locks when acquiring them for writing. It is
+/// not advised to use these identifiers for any other purpose.
+///
+/// As the thread identifier is also stored in [`lock`](struct.lock.html) when
+/// [`LOCK_WRLOCKED`](constant.LOCK_WRLOCKED.html) is set, the top two bits of the thread
+/// must always be set to zero.
+#[repr(C)]
+#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
+pub struct tid(pub u32);
+
+/// Timestamp in nanoseconds.
+pub type timestamp = u64;
+
+bitflags! {
+ /// Specifies whether files are unlinked or directories are
+ /// removed.
+ #[repr(C)]
+ pub struct ulflags: u8 {
+ /// If set, removes a directory. Otherwise, unlinks any
+ /// non-directory file.
+ const REMOVEDIR = 0x01;
+ }
+}
+
+/// User-provided value that can be attached to objects that is
+/// retained when extracted from the kernel.
+pub type userdata = u64;
+
+/// Relative to which position the offset of the file descriptor
+/// should be set.
+#[repr(u8)]
+#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
+pub enum whence {
+ /// Seek relative to current position.
+ CUR = 1,
+ /// Seek relative to end-of-file.
+ END = 2,
+ /// Seek relative to start-of-file.
+ SET = 3,
+ #[doc(hidden)] _NonExhaustive = -1 as isize as u8,
+}
+
+/// Auxiliary vector entry.
+///
+/// The auxiliary vector is a list of key-value pairs that is
+/// provided to the process on startup. Unlike structures, it is
+/// extensible, as it is possible to add new records later on.
+/// The auxiliary vector is always terminated by an entry having
+/// type [`NULL`](enum.auxtype.html#variant.NULL).
+///
+/// The auxiliary vector is part of the x86-64 ABI, but is used by
+/// this environment on all architectures.
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub struct auxv {
+ /// The type of the auxiliary vector entry.
+ pub a_type: auxtype,
+ pub union: auxv_union
+}
+/// A union inside `auxv`.
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub union auxv_union {
+ /// Used when `a_type` is [`ARGDATALEN`](enum.auxtype.html#variant.ARGDATALEN), [`CANARYLEN`](enum.auxtype.html#variant.CANARYLEN), [`NCPUS`](enum.auxtype.html#variant.NCPUS), [`PAGESZ`](enum.auxtype.html#variant.PAGESZ), [`PHNUM`](enum.auxtype.html#variant.PHNUM), or [`TID`](enum.auxtype.html#variant.TID).
+/// A numerical value.
+ pub a_val: usize,
+ /// Used when `a_type` is [`ARGDATA`](enum.auxtype.html#variant.ARGDATA), [`BASE`](enum.auxtype.html#variant.BASE), [`CANARY`](enum.auxtype.html#variant.CANARY), [`PHDR`](enum.auxtype.html#variant.PHDR), [`PID`](enum.auxtype.html#variant.PID), or [`SYSINFO_EHDR`](enum.auxtype.html#variant.SYSINFO_EHDR).
+/// A pointer value.
+ pub a_ptr: *mut (),
+}
+#[test]
+#[cfg(target_pointer_width = "32")]
+fn auxv_layout_test_32() {
+ assert_eq!(::core::mem::size_of::<auxv>(), 8);
+ assert_eq!(::core::mem::align_of::<auxv>(), 4);
+ unsafe {
+ let obj: auxv = ::core::mem::uninitialized();
+ let base = &obj as *const _ as usize;
+ assert_eq!(&obj.a_type as *const _ as usize - base, 0);
+ assert_eq!(&obj.union.a_val as *const _ as usize - base, 4);
+ assert_eq!(&obj.union.a_ptr as *const _ as usize - base, 4);
+ }
+}
+#[test]
+#[cfg(target_pointer_width = "64")]
+fn auxv_layout_test_64() {
+ assert_eq!(::core::mem::size_of::<auxv>(), 16);
+ assert_eq!(::core::mem::align_of::<auxv>(), 8);
+ unsafe {
+ let obj: auxv = ::core::mem::uninitialized();
+ let base = &obj as *const _ as usize;
+ assert_eq!(&obj.a_type as *const _ as usize - base, 0);
+ assert_eq!(&obj.union.a_val as *const _ as usize - base, 8);
+ assert_eq!(&obj.union.a_ptr as *const _ as usize - base, 8);
+ }
+}
+
+/// A region of memory for scatter/gather writes.
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub struct ciovec {
+ /// The address and length of the buffer to be written.
+ pub buf: (*const (), usize),
+}
+#[test]
+#[cfg(target_pointer_width = "32")]
+fn ciovec_layout_test_32() {
+ assert_eq!(::core::mem::size_of::<ciovec>(), 8);
+ assert_eq!(::core::mem::align_of::<ciovec>(), 4);
+ unsafe {
+ let obj: ciovec = ::core::mem::uninitialized();
+ let base = &obj as *const _ as usize;
+ assert_eq!(&obj.buf.0 as *const _ as usize - base, 0);
+ assert_eq!(&obj.buf.1 as *const _ as usize - base, 4);
+ }
+}
+#[test]
+#[cfg(target_pointer_width = "64")]
+fn ciovec_layout_test_64() {
+ assert_eq!(::core::mem::size_of::<ciovec>(), 16);
+ assert_eq!(::core::mem::align_of::<ciovec>(), 8);
+ unsafe {
+ let obj: ciovec = ::core::mem::uninitialized();
+ let base = &obj as *const _ as usize;
+ assert_eq!(&obj.buf.0 as *const _ as usize - base, 0);
+ assert_eq!(&obj.buf.1 as *const _ as usize - base, 8);
+ }
+}
+
+/// A directory entry.
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub struct dirent {
+ /// The offset of the next directory entry stored in this
+ /// directory.
+ pub d_next: dircookie,
+ /// The serial number of the file referred to by this
+ /// directory entry.
+ pub d_ino: inode,
+ /// The length of the name of the directory entry.
+ pub d_namlen: u32,
+ /// The type of the file referred to by this directory
+ /// entry.
+ pub d_type: filetype,
+}
+#[test]
+fn dirent_layout_test() {
+ assert_eq!(::core::mem::size_of::<dirent>(), 24);
+ assert_eq!(::core::mem::align_of::<dirent>(), 8);
+ unsafe {
+ let obj: dirent = ::core::mem::uninitialized();
+ let base = &obj as *const _ as usize;
+ assert_eq!(&obj.d_next as *const _ as usize - base, 0);
+ assert_eq!(&obj.d_ino as *const _ as usize - base, 8);
+ assert_eq!(&obj.d_namlen as *const _ as usize - base, 16);
+ assert_eq!(&obj.d_type as *const _ as usize - base, 20);
+ }
+}
+
+/// An event that occurred.
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub struct event {
+ /// User-provided value that got attached to
+ /// [`subscription.userdata`](struct.subscription.html#structfield.userdata).
+ pub userdata: userdata,
+ /// If non-zero, an error that occurred while processing
+ /// the subscription request.
+ pub error: errno,
+ /// The type of the event that occurred.
+ pub type_: eventtype,
+ pub union: event_union
+}
+/// A union inside `event`.
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub union event_union {
+ /// Used when `type_` is [`FD_READ`](enum.eventtype.html#variant.FD_READ) or [`FD_WRITE`](enum.eventtype.html#variant.FD_WRITE).
+ pub fd_readwrite: event_fd_readwrite,
+ /// Used when `type_` is [`PROC_TERMINATE`](enum.eventtype.html#variant.PROC_TERMINATE).
+ pub proc_terminate: event_proc_terminate,
+}
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub struct event_fd_readwrite {
+ /// The number of bytes available
+ /// for reading or writing.
+ pub nbytes: filesize,
+ /// Obsolete.
+ pub unused: [u8; 4],
+ /// The state of the file
+ /// descriptor.
+ pub flags: eventrwflags,
+}
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub struct event_proc_terminate {
+ /// Obsolete.
+ pub unused: [u8; 4],
+ /// If zero, the process has
+ /// exited.
+ /// Otherwise, the signal
+ /// condition causing it to
+ /// terminated.
+ pub signal: signal,
+ /// If exited, the exit code of
+ /// the process.
+ pub exitcode: exitcode,
+}
+#[test]
+fn event_layout_test() {
+ assert_eq!(::core::mem::size_of::<event>(), 32);
+ assert_eq!(::core::mem::align_of::<event>(), 8);
+ unsafe {
+ let obj: event = ::core::mem::uninitialized();
+ let base = &obj as *const _ as usize;
+ assert_eq!(&obj.userdata as *const _ as usize - base, 0);
+ assert_eq!(&obj.error as *const _ as usize - base, 8);
+ assert_eq!(&obj.type_ as *const _ as usize - base, 10);
+ assert_eq!(&obj.union.fd_readwrite.nbytes as *const _ as usize - base, 16);
+ assert_eq!(&obj.union.fd_readwrite.unused as *const _ as usize - base, 24);
+ assert_eq!(&obj.union.fd_readwrite.flags as *const _ as usize - base, 28);
+ assert_eq!(&obj.union.proc_terminate.unused as *const _ as usize - base, 16);
+ assert_eq!(&obj.union.proc_terminate.signal as *const _ as usize - base, 20);
+ assert_eq!(&obj.union.proc_terminate.exitcode as *const _ as usize - base, 24);
+ }
+}
+
+/// File descriptor attributes.
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub struct fdstat {
+ /// File type.
+ pub fs_filetype: filetype,
+ /// File descriptor flags.
+ pub fs_flags: fdflags,
+ /// Rights that apply to this file descriptor.
+ pub fs_rights_base: rights,
+ /// Maximum set of rights that can be installed on new
+ /// file descriptors that are created through this file
+ /// descriptor, e.g., through [`file_open()`](fn.file_open.html).
+ pub fs_rights_inheriting: rights,
+}
+#[test]
+fn fdstat_layout_test() {
+ assert_eq!(::core::mem::size_of::<fdstat>(), 24);
+ assert_eq!(::core::mem::align_of::<fdstat>(), 8);
+ unsafe {
+ let obj: fdstat = ::core::mem::uninitialized();
+ let base = &obj as *const _ as usize;
+ assert_eq!(&obj.fs_filetype as *const _ as usize - base, 0);
+ assert_eq!(&obj.fs_flags as *const _ as usize - base, 2);
+ assert_eq!(&obj.fs_rights_base as *const _ as usize - base, 8);
+ assert_eq!(&obj.fs_rights_inheriting as *const _ as usize - base, 16);
+ }
+}
+
+/// File attributes.
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub struct filestat {
+ /// Device ID of device containing the file.
+ pub st_dev: device,
+ /// File serial number.
+ pub st_ino: inode,
+ /// File type.
+ pub st_filetype: filetype,
+ /// Number of hard links to the file.
+ pub st_nlink: linkcount,
+ /// For regular files, the file size in bytes. For
+ /// symbolic links, the length in bytes of the pathname
+ /// contained in the symbolic link.
+ pub st_size: filesize,
+ /// Last data access timestamp.
+ pub st_atim: timestamp,
+ /// Last data modification timestamp.
+ pub st_mtim: timestamp,
+ /// Last file status change timestamp.
+ pub st_ctim: timestamp,
+}
+#[test]
+fn filestat_layout_test() {
+ assert_eq!(::core::mem::size_of::<filestat>(), 56);
+ assert_eq!(::core::mem::align_of::<filestat>(), 8);
+ unsafe {
+ let obj: filestat = ::core::mem::uninitialized();
+ let base = &obj as *const _ as usize;
+ assert_eq!(&obj.st_dev as *const _ as usize - base, 0);
+ assert_eq!(&obj.st_ino as *const _ as usize - base, 8);
+ assert_eq!(&obj.st_filetype as *const _ as usize - base, 16);
+ assert_eq!(&obj.st_nlink as *const _ as usize - base, 20);
+ assert_eq!(&obj.st_size as *const _ as usize - base, 24);
+ assert_eq!(&obj.st_atim as *const _ as usize - base, 32);
+ assert_eq!(&obj.st_mtim as *const _ as usize - base, 40);
+ assert_eq!(&obj.st_ctim as *const _ as usize - base, 48);
+ }
+}
+
+/// A region of memory for scatter/gather reads.
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub struct iovec {
+ /// The address and length of the buffer to be filled.
+ pub buf: (*mut (), usize),
+}
+#[test]
+#[cfg(target_pointer_width = "32")]
+fn iovec_layout_test_32() {
+ assert_eq!(::core::mem::size_of::<iovec>(), 8);
+ assert_eq!(::core::mem::align_of::<iovec>(), 4);
+ unsafe {
+ let obj: iovec = ::core::mem::uninitialized();
+ let base = &obj as *const _ as usize;
+ assert_eq!(&obj.buf.0 as *const _ as usize - base, 0);
+ assert_eq!(&obj.buf.1 as *const _ as usize - base, 4);
+ }
+}
+#[test]
+#[cfg(target_pointer_width = "64")]
+fn iovec_layout_test_64() {
+ assert_eq!(::core::mem::size_of::<iovec>(), 16);
+ assert_eq!(::core::mem::align_of::<iovec>(), 8);
+ unsafe {
+ let obj: iovec = ::core::mem::uninitialized();
+ let base = &obj as *const _ as usize;
+ assert_eq!(&obj.buf.0 as *const _ as usize - base, 0);
+ assert_eq!(&obj.buf.1 as *const _ as usize - base, 8);
+ }
+}
+
+/// Path lookup properties.
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub struct lookup {
+ /// The working directory at which the resolution of the
+ /// path starts.
+ pub fd: fd,
+ /// Flags determining the method of how the path is
+ /// resolved.
+ pub flags: lookupflags,
+}
+#[test]
+fn lookup_layout_test() {
+ assert_eq!(::core::mem::size_of::<lookup>(), 8);
+ assert_eq!(::core::mem::align_of::<lookup>(), 4);
+ unsafe {
+ let obj: lookup = ::core::mem::uninitialized();
+ let base = &obj as *const _ as usize;
+ assert_eq!(&obj.fd as *const _ as usize - base, 0);
+ assert_eq!(&obj.flags as *const _ as usize - base, 4);
+ }
+}
+
+/// Entry point for a process (`_start`).
+///
+/// **auxv**:
+/// The auxiliary vector. See [`auxv`](struct.auxv.html).
+pub type processentry = unsafe extern "C" fn(
+ auxv: *const auxv,
+) -> ();
+
+/// Arguments of [`sock_recv()`](fn.sock_recv.html).
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub struct recv_in {
+ /// List of scatter/gather vectors where message data
+ /// should be stored.
+ pub ri_data: (*const iovec, usize),
+ /// Buffer where numbers of incoming file descriptors
+ /// should be stored.
+ pub ri_fds: (*mut fd, usize),
+ /// Message flags.
+ pub ri_flags: riflags,
+}
+#[test]
+#[cfg(target_pointer_width = "32")]
+fn recv_in_layout_test_32() {
+ assert_eq!(::core::mem::size_of::<recv_in>(), 20);
+ assert_eq!(::core::mem::align_of::<recv_in>(), 4);
+ unsafe {
+ let obj: recv_in = ::core::mem::uninitialized();
+ let base = &obj as *const _ as usize;
+ assert_eq!(&obj.ri_data.0 as *const _ as usize - base, 0);
+ assert_eq!(&obj.ri_data.1 as *const _ as usize - base, 4);
+ assert_eq!(&obj.ri_fds.0 as *const _ as usize - base, 8);
+ assert_eq!(&obj.ri_fds.1 as *const _ as usize - base, 12);
+ assert_eq!(&obj.ri_flags as *const _ as usize - base, 16);
+ }
+}
+#[test]
+#[cfg(target_pointer_width = "64")]
+fn recv_in_layout_test_64() {
+ assert_eq!(::core::mem::size_of::<recv_in>(), 40);
+ assert_eq!(::core::mem::align_of::<recv_in>(), 8);
+ unsafe {
+ let obj: recv_in = ::core::mem::uninitialized();
+ let base = &obj as *const _ as usize;
+ assert_eq!(&obj.ri_data.0 as *const _ as usize - base, 0);
+ assert_eq!(&obj.ri_data.1 as *const _ as usize - base, 8);
+ assert_eq!(&obj.ri_fds.0 as *const _ as usize - base, 16);
+ assert_eq!(&obj.ri_fds.1 as *const _ as usize - base, 24);
+ assert_eq!(&obj.ri_flags as *const _ as usize - base, 32);
+ }
+}
+
+/// Results of [`sock_recv()`](fn.sock_recv.html).
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub struct recv_out {
+ /// Number of bytes stored in [`recv_in.ri_data`](struct.recv_in.html#structfield.ri_data).
+ pub ro_datalen: usize,
+ /// Number of file descriptors stored in [`recv_in.ri_fds`](struct.recv_in.html#structfield.ri_fds).
+ pub ro_fdslen: usize,
+ /// Fields that were used by previous implementations.
+ pub ro_unused: [u8; 40],
+ /// Message flags.
+ pub ro_flags: roflags,
+}
+#[test]
+#[cfg(target_pointer_width = "32")]
+fn recv_out_layout_test_32() {
+ assert_eq!(::core::mem::size_of::<recv_out>(), 52);
+ assert_eq!(::core::mem::align_of::<recv_out>(), 4);
+ unsafe {
+ let obj: recv_out = ::core::mem::uninitialized();
+ let base = &obj as *const _ as usize;
+ assert_eq!(&obj.ro_datalen as *const _ as usize - base, 0);
+ assert_eq!(&obj.ro_fdslen as *const _ as usize - base, 4);
+ assert_eq!(&obj.ro_unused as *const _ as usize - base, 8);
+ assert_eq!(&obj.ro_flags as *const _ as usize - base, 48);
+ }
+}
+#[test]
+#[cfg(target_pointer_width = "64")]
+fn recv_out_layout_test_64() {
+ assert_eq!(::core::mem::size_of::<recv_out>(), 64);
+ assert_eq!(::core::mem::align_of::<recv_out>(), 8);
+ unsafe {
+ let obj: recv_out = ::core::mem::uninitialized();
+ let base = &obj as *const _ as usize;
+ assert_eq!(&obj.ro_datalen as *const _ as usize - base, 0);
+ assert_eq!(&obj.ro_fdslen as *const _ as usize - base, 8);
+ assert_eq!(&obj.ro_unused as *const _ as usize - base, 16);
+ assert_eq!(&obj.ro_flags as *const _ as usize - base, 56);
+ }
+}
+
+/// Arguments of [`sock_send()`](fn.sock_send.html).
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub struct send_in {
+ /// List of scatter/gather vectors where message data
+ /// should be retrieved.
+ pub si_data: (*const ciovec, usize),
+ /// File descriptors that need to be attached to the
+ /// message.
+ pub si_fds: (*const fd, usize),
+ /// Message flags.
+ pub si_flags: siflags,
+}
+#[test]
+#[cfg(target_pointer_width = "32")]
+fn send_in_layout_test_32() {
+ assert_eq!(::core::mem::size_of::<send_in>(), 20);
+ assert_eq!(::core::mem::align_of::<send_in>(), 4);
+ unsafe {
+ let obj: send_in = ::core::mem::uninitialized();
+ let base = &obj as *const _ as usize;
+ assert_eq!(&obj.si_data.0 as *const _ as usize - base, 0);
+ assert_eq!(&obj.si_data.1 as *const _ as usize - base, 4);
+ assert_eq!(&obj.si_fds.0 as *const _ as usize - base, 8);
+ assert_eq!(&obj.si_fds.1 as *const _ as usize - base, 12);
+ assert_eq!(&obj.si_flags as *const _ as usize - base, 16);
+ }
+}
+#[test]
+#[cfg(target_pointer_width = "64")]
+fn send_in_layout_test_64() {
+ assert_eq!(::core::mem::size_of::<send_in>(), 40);
+ assert_eq!(::core::mem::align_of::<send_in>(), 8);
+ unsafe {
+ let obj: send_in = ::core::mem::uninitialized();
+ let base = &obj as *const _ as usize;
+ assert_eq!(&obj.si_data.0 as *const _ as usize - base, 0);
+ assert_eq!(&obj.si_data.1 as *const _ as usize - base, 8);
+ assert_eq!(&obj.si_fds.0 as *const _ as usize - base, 16);
+ assert_eq!(&obj.si_fds.1 as *const _ as usize - base, 24);
+ assert_eq!(&obj.si_flags as *const _ as usize - base, 32);
+ }
+}
+
+/// Results of [`sock_send()`](fn.sock_send.html).
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub struct send_out {
+ /// Number of bytes transmitted.
+ pub so_datalen: usize,
+}
+#[test]
+#[cfg(target_pointer_width = "32")]
+fn send_out_layout_test_32() {
+ assert_eq!(::core::mem::size_of::<send_out>(), 4);
+ assert_eq!(::core::mem::align_of::<send_out>(), 4);
+ unsafe {
+ let obj: send_out = ::core::mem::uninitialized();
+ let base = &obj as *const _ as usize;
+ assert_eq!(&obj.so_datalen as *const _ as usize - base, 0);
+ }
+}
+#[test]
+#[cfg(target_pointer_width = "64")]
+fn send_out_layout_test_64() {
+ assert_eq!(::core::mem::size_of::<send_out>(), 8);
+ assert_eq!(::core::mem::align_of::<send_out>(), 8);
+ unsafe {
+ let obj: send_out = ::core::mem::uninitialized();
+ let base = &obj as *const _ as usize;
+ assert_eq!(&obj.so_datalen as *const _ as usize - base, 0);
+ }
+}
+
+/// Subscription to an event.
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub struct subscription {
+ /// User-provided value that is attached to the
+ /// subscription in the kernel and returned through
+ /// [`event.userdata`](struct.event.html#structfield.userdata).
+ pub userdata: userdata,
+ /// Used by previous implementations. Ignored.
+ pub unused: u16,
+ /// The type of the event to which to subscribe.
+ ///
+ /// Currently, [`CONDVAR`](enum.eventtype.html#variant.CONDVAR),
+ /// [`LOCK_RDLOCK`](enum.eventtype.html#variant.LOCK_RDLOCK), and [`LOCK_WRLOCK`](enum.eventtype.html#variant.LOCK_WRLOCK)
+ /// must be provided as the first subscription and may
+ /// only be followed by up to one other subscription,
+ /// having type [`CLOCK`](enum.eventtype.html#variant.CLOCK).
+ pub type_: eventtype,
+ pub union: subscription_union
+}
+/// A union inside `subscription`.
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub union subscription_union {
+ /// Used when `type_` is [`CLOCK`](enum.eventtype.html#variant.CLOCK).
+ pub clock: subscription_clock,
+ /// Used when `type_` is [`CONDVAR`](enum.eventtype.html#variant.CONDVAR).
+ pub condvar: subscription_condvar,
+ /// Used when `type_` is [`FD_READ`](enum.eventtype.html#variant.FD_READ) or [`FD_WRITE`](enum.eventtype.html#variant.FD_WRITE).
+ pub fd_readwrite: subscription_fd_readwrite,
+ /// Used when `type_` is [`LOCK_RDLOCK`](enum.eventtype.html#variant.LOCK_RDLOCK) or [`LOCK_WRLOCK`](enum.eventtype.html#variant.LOCK_WRLOCK).
+ pub lock: subscription_lock,
+ /// Used when `type_` is [`PROC_TERMINATE`](enum.eventtype.html#variant.PROC_TERMINATE).
+ pub proc_terminate: subscription_proc_terminate,
+}
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub struct subscription_clock {
+ /// The user-defined unique
+ /// identifier of the clock.
+ pub identifier: userdata,
+ /// The clock against which the
+ /// timestamp should be compared.
+ pub clock_id: clockid,
+ /// The absolute or relative
+ /// timestamp.
+ pub timeout: timestamp,
+ /// The amount of time that the
+ /// kernel may wait additionally
+ /// to coalesce with other events.
+ pub precision: timestamp,
+ /// Flags specifying whether the
+ /// timeout is absolute or
+ /// relative.
+ pub flags: subclockflags,
+}
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub struct subscription_condvar {
+ /// The condition variable on
+ /// which to wait to be woken up.
+ pub condvar: *mut condvar,
+ /// The lock that will be
+ /// released while waiting.
+ ///
+ /// The lock will be reacquired
+ /// for writing when the condition
+ /// variable triggers.
+ pub lock: *mut lock,
+ /// Whether the condition variable
+ /// is stored in private or shared
+ /// memory.
+ pub condvar_scope: scope,
+ /// Whether the lock is stored in
+ /// private or shared memory.
+ pub lock_scope: scope,
+}
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub struct subscription_fd_readwrite {
+ /// The file descriptor on which
+ /// to wait for it to become ready
+ /// for reading or writing.
+ pub fd: fd,
+ /// Under which conditions to
+ /// trigger.
+ pub flags: subrwflags,
+}
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub struct subscription_lock {
+ /// The lock that will be acquired
+ /// for reading or writing.
+ pub lock: *mut lock,
+ /// Whether the lock is stored in
+ /// private or shared memory.
+ pub lock_scope: scope,
+}
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub struct subscription_proc_terminate {
+ /// The process descriptor on
+ /// which to wait for process
+ /// termination.
+ pub fd: fd,
+}
+#[test]
+#[cfg(target_pointer_width = "32")]
+fn subscription_layout_test_32() {
+ assert_eq!(::core::mem::size_of::<subscription>(), 56);
+ assert_eq!(::core::mem::align_of::<subscription>(), 8);
+ unsafe {
+ let obj: subscription = ::core::mem::uninitialized();
+ let base = &obj as *const _ as usize;
+ assert_eq!(&obj.userdata as *const _ as usize - base, 0);
+ assert_eq!(&obj.unused as *const _ as usize - base, 8);
+ assert_eq!(&obj.type_ as *const _ as usize - base, 10);
+ assert_eq!(&obj.union.clock.identifier as *const _ as usize - base, 16);
+ assert_eq!(&obj.union.clock.clock_id as *const _ as usize - base, 24);
+ assert_eq!(&obj.union.clock.timeout as *const _ as usize - base, 32);
+ assert_eq!(&obj.union.clock.precision as *const _ as usize - base, 40);
+ assert_eq!(&obj.union.clock.flags as *const _ as usize - base, 48);
+ assert_eq!(&obj.union.condvar.condvar as *const _ as usize - base, 16);
+ assert_eq!(&obj.union.condvar.lock as *const _ as usize - base, 20);
+ assert_eq!(&obj.union.condvar.condvar_scope as *const _ as usize - base, 24);
+ assert_eq!(&obj.union.condvar.lock_scope as *const _ as usize - base, 25);
+ assert_eq!(&obj.union.fd_readwrite.fd as *const _ as usize - base, 16);
+ assert_eq!(&obj.union.fd_readwrite.flags as *const _ as usize - base, 20);
+ assert_eq!(&obj.union.lock.lock as *const _ as usize - base, 16);
+ assert_eq!(&obj.union.lock.lock_scope as *const _ as usize - base, 20);
+ assert_eq!(&obj.union.proc_terminate.fd as *const _ as usize - base, 16);
+ }
+}
+#[test]
+#[cfg(target_pointer_width = "64")]
+fn subscription_layout_test_64() {
+ assert_eq!(::core::mem::size_of::<subscription>(), 56);
+ assert_eq!(::core::mem::align_of::<subscription>(), 8);
+ unsafe {
+ let obj: subscription = ::core::mem::uninitialized();
+ let base = &obj as *const _ as usize;
+ assert_eq!(&obj.userdata as *const _ as usize - base, 0);
+ assert_eq!(&obj.unused as *const _ as usize - base, 8);
+ assert_eq!(&obj.type_ as *const _ as usize - base, 10);
+ assert_eq!(&obj.union.clock.identifier as *const _ as usize - base, 16);
+ assert_eq!(&obj.union.clock.clock_id as *const _ as usize - base, 24);
+ assert_eq!(&obj.union.clock.timeout as *const _ as usize - base, 32);
+ assert_eq!(&obj.union.clock.precision as *const _ as usize - base, 40);
+ assert_eq!(&obj.union.clock.flags as *const _ as usize - base, 48);
+ assert_eq!(&obj.union.condvar.condvar as *const _ as usize - base, 16);
+ assert_eq!(&obj.union.condvar.lock as *const _ as usize - base, 24);
+ assert_eq!(&obj.union.condvar.condvar_scope as *const _ as usize - base, 32);
+ assert_eq!(&obj.union.condvar.lock_scope as *const _ as usize - base, 33);
+ assert_eq!(&obj.union.fd_readwrite.fd as *const _ as usize - base, 16);
+ assert_eq!(&obj.union.fd_readwrite.flags as *const _ as usize - base, 20);
+ assert_eq!(&obj.union.lock.lock as *const _ as usize - base, 16);
+ assert_eq!(&obj.union.lock.lock_scope as *const _ as usize - base, 24);
+ assert_eq!(&obj.union.proc_terminate.fd as *const _ as usize - base, 16);
+ }
+}
+
+/// The Thread Control Block (TCB).
+///
+/// After a thread begins execution (at program startup or when
+/// created through [`thread_create()`](fn.thread_create.html)), the CPU's registers
+/// controlling Thread-Local Storage (TLS) will already be
+/// initialized. They will point to an area only containing the
+/// TCB.
+///
+/// If the thread needs space for storing thread-specific
+/// variables, the thread may allocate a larger area and adjust
+/// the CPU's registers to point to that area instead. However, it
+/// does need to make sure that the TCB is copied over to the new
+/// TLS area.
+///
+/// The purpose of the TCB is that it allows light-weight
+/// emulators to store information related to individual threads.
+/// For example, it may be used to store a copy of the CPU
+/// registers prior emulation, so that TLS for the host system
+/// can be restored if needed.
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub struct tcb {
+ /// Pointer that may be freely assigned by the system. Its
+ /// value cannot be interpreted by the application.
+ pub parent: *mut (),
+}
+#[test]
+#[cfg(target_pointer_width = "32")]
+fn tcb_layout_test_32() {
+ assert_eq!(::core::mem::size_of::<tcb>(), 4);
+ assert_eq!(::core::mem::align_of::<tcb>(), 4);
+ unsafe {
+ let obj: tcb = ::core::mem::uninitialized();
+ let base = &obj as *const _ as usize;
+ assert_eq!(&obj.parent as *const _ as usize - base, 0);
+ }
+}
+#[test]
+#[cfg(target_pointer_width = "64")]
+fn tcb_layout_test_64() {
+ assert_eq!(::core::mem::size_of::<tcb>(), 8);
+ assert_eq!(::core::mem::align_of::<tcb>(), 8);
+ unsafe {
+ let obj: tcb = ::core::mem::uninitialized();
+ let base = &obj as *const _ as usize;
+ assert_eq!(&obj.parent as *const _ as usize - base, 0);
+ }
+}
+
+/// Entry point for additionally created threads.
+///
+/// **tid**:
+/// Thread ID of the current thread.
+///
+/// **aux**:
+/// Copy of the value stored in
+/// [`threadattr.argument`](struct.threadattr.html#structfield.argument).
+pub type threadentry = unsafe extern "C" fn(
+ tid: tid,
+ aux: *mut (),
+) -> ();
+
+/// Attributes for thread creation.
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub struct threadattr {
+ /// Initial program counter value.
+ pub entry_point: threadentry,
+ /// Region allocated to serve as stack space.
+ pub stack: (*mut (), usize),
+ /// Argument to be forwarded to the entry point function.
+ pub argument: *mut (),
+}
+#[test]
+#[cfg(target_pointer_width = "32")]
+fn threadattr_layout_test_32() {
+ assert_eq!(::core::mem::size_of::<threadattr>(), 16);
+ assert_eq!(::core::mem::align_of::<threadattr>(), 4);
+ unsafe {
+ let obj: threadattr = ::core::mem::uninitialized();
+ let base = &obj as *const _ as usize;
+ assert_eq!(&obj.entry_point as *const _ as usize - base, 0);
+ assert_eq!(&obj.stack.0 as *const _ as usize - base, 4);
+ assert_eq!(&obj.stack.1 as *const _ as usize - base, 8);
+ assert_eq!(&obj.argument as *const _ as usize - base, 12);
+ }
+}
+#[test]
+#[cfg(target_pointer_width = "64")]
+fn threadattr_layout_test_64() {
+ assert_eq!(::core::mem::size_of::<threadattr>(), 32);
+ assert_eq!(::core::mem::align_of::<threadattr>(), 8);
+ unsafe {
+ let obj: threadattr = ::core::mem::uninitialized();
+ let base = &obj as *const _ as usize;
+ assert_eq!(&obj.entry_point as *const _ as usize - base, 0);
+ assert_eq!(&obj.stack.0 as *const _ as usize - base, 8);
+ assert_eq!(&obj.stack.1 as *const _ as usize - base, 16);
+ assert_eq!(&obj.argument as *const _ as usize - base, 24);
+ }
+}
+
+/// The table with pointers to all syscall implementations.
+#[allow(improper_ctypes)]
+extern "C" {
+ fn cloudabi_sys_clock_res_get(_: clockid, _: *mut timestamp) -> errno;
+ fn cloudabi_sys_clock_time_get(_: clockid, _: timestamp, _: *mut timestamp) -> errno;
+ fn cloudabi_sys_condvar_signal(_: *mut condvar, _: scope, _: nthreads) -> errno;
+ fn cloudabi_sys_fd_close(_: fd) -> errno;
+ fn cloudabi_sys_fd_create1(_: filetype, _: *mut fd) -> errno;
+ fn cloudabi_sys_fd_create2(_: filetype, _: *mut fd, _: *mut fd) -> errno;
+ fn cloudabi_sys_fd_datasync(_: fd) -> errno;
+ fn cloudabi_sys_fd_dup(_: fd, _: *mut fd) -> errno;
+ fn cloudabi_sys_fd_pread(_: fd, _: *const iovec, _: usize, _: filesize, _: *mut usize) -> errno;
+ fn cloudabi_sys_fd_pwrite(_: fd, _: *const ciovec, _: usize, _: filesize, _: *mut usize) -> errno;
+ fn cloudabi_sys_fd_read(_: fd, _: *const iovec, _: usize, _: *mut usize) -> errno;
+ fn cloudabi_sys_fd_replace(_: fd, _: fd) -> errno;
+ fn cloudabi_sys_fd_seek(_: fd, _: filedelta, _: whence, _: *mut filesize) -> errno;
+ fn cloudabi_sys_fd_stat_get(_: fd, _: *mut fdstat) -> errno;
+ fn cloudabi_sys_fd_stat_put(_: fd, _: *const fdstat, _: fdsflags) -> errno;
+ fn cloudabi_sys_fd_sync(_: fd) -> errno;
+ fn cloudabi_sys_fd_write(_: fd, _: *const ciovec, _: usize, _: *mut usize) -> errno;
+ fn cloudabi_sys_file_advise(_: fd, _: filesize, _: filesize, _: advice) -> errno;
+ fn cloudabi_sys_file_allocate(_: fd, _: filesize, _: filesize) -> errno;
+ fn cloudabi_sys_file_create(_: fd, _: *const u8, _: usize, _: filetype) -> errno;
+ fn cloudabi_sys_file_link(_: lookup, _: *const u8, _: usize, _: fd, _: *const u8, _: usize) -> errno;
+ fn cloudabi_sys_file_open(_: lookup, _: *const u8, _: usize, _: oflags, _: *const fdstat, _: *mut fd) -> errno;
+ fn cloudabi_sys_file_readdir(_: fd, _: *mut (), _: usize, _: dircookie, _: *mut usize) -> errno;
+ fn cloudabi_sys_file_readlink(_: fd, _: *const u8, _: usize, _: *mut u8, _: usize, _: *mut usize) -> errno;
+ fn cloudabi_sys_file_rename(_: fd, _: *const u8, _: usize, _: fd, _: *const u8, _: usize) -> errno;
+ fn cloudabi_sys_file_stat_fget(_: fd, _: *mut filestat) -> errno;
+ fn cloudabi_sys_file_stat_fput(_: fd, _: *const filestat, _: fsflags) -> errno;
+ fn cloudabi_sys_file_stat_get(_: lookup, _: *const u8, _: usize, _: *mut filestat) -> errno;
+ fn cloudabi_sys_file_stat_put(_: lookup, _: *const u8, _: usize, _: *const filestat, _: fsflags) -> errno;
+ fn cloudabi_sys_file_symlink(_: *const u8, _: usize, _: fd, _: *const u8, _: usize) -> errno;
+ fn cloudabi_sys_file_unlink(_: fd, _: *const u8, _: usize, _: ulflags) -> errno;
+ fn cloudabi_sys_lock_unlock(_: *mut lock, _: scope) -> errno;
+ fn cloudabi_sys_mem_advise(_: *mut (), _: usize, _: advice) -> errno;
+ fn cloudabi_sys_mem_map(_: *mut (), _: usize, _: mprot, _: mflags, _: fd, _: filesize, _: *mut *mut ()) -> errno;
+ fn cloudabi_sys_mem_protect(_: *mut (), _: usize, _: mprot) -> errno;
+ fn cloudabi_sys_mem_sync(_: *mut (), _: usize, _: msflags) -> errno;
+ fn cloudabi_sys_mem_unmap(_: *mut (), _: usize) -> errno;
+ fn cloudabi_sys_poll(_: *const subscription, _: *mut event, _: usize, _: *mut usize) -> errno;
+ fn cloudabi_sys_proc_exec(_: fd, _: *const (), _: usize, _: *const fd, _: usize) -> errno;
+ fn cloudabi_sys_proc_exit(_: exitcode) -> !;
+ fn cloudabi_sys_proc_fork(_: *mut fd, _: *mut tid) -> errno;
+ fn cloudabi_sys_proc_raise(_: signal) -> errno;
+ fn cloudabi_sys_random_get(_: *mut (), _: usize) -> errno;
+ fn cloudabi_sys_sock_recv(_: fd, _: *const recv_in, _: *mut recv_out) -> errno;
+ fn cloudabi_sys_sock_send(_: fd, _: *const send_in, _: *mut send_out) -> errno;
+ fn cloudabi_sys_sock_shutdown(_: fd, _: sdflags) -> errno;
+ fn cloudabi_sys_thread_create(_: *mut threadattr, _: *mut tid) -> errno;
+ fn cloudabi_sys_thread_exit(_: *mut lock, _: scope) -> !;
+ fn cloudabi_sys_thread_yield() -> errno;
+}
+
+/// Obtains the resolution of a clock.
+///
+/// ## Parameters
+///
+/// **clock_id**:
+/// The clock for which the resolution needs to be
+/// returned.
+///
+/// **resolution**:
+/// The resolution of the clock.
+#[inline]
+pub unsafe fn clock_res_get(clock_id_: clockid, resolution_: &mut timestamp) -> errno {
+ cloudabi_sys_clock_res_get(clock_id_, resolution_)
+}
+
+/// Obtains the time value of a clock.
+///
+/// ## Parameters
+///
+/// **clock_id**:
+/// The clock for which the time needs to be
+/// returned.
+///
+/// **precision**:
+/// The maximum lag (exclusive) that the returned
+/// time value may have, compared to its actual
+/// value.
+///
+/// **time**:
+/// The time value of the clock.
+#[inline]
+pub unsafe fn clock_time_get(clock_id_: clockid, precision_: timestamp, time_: &mut timestamp) -> errno {
+ cloudabi_sys_clock_time_get(clock_id_, precision_, time_)
+}
+
+/// Wakes up threads waiting on a userspace condition variable.
+///
+/// If an invocation of this system call causes all waiting
+/// threads to be woken up, the value of the condition variable
+/// is set to [`CONDVAR_HAS_NO_WAITERS`](constant.CONDVAR_HAS_NO_WAITERS.html). As long as the condition
+/// variable is set to this value, it is not needed to invoke this
+/// system call.
+///
+/// ## Parameters
+///
+/// **condvar**:
+/// The userspace condition variable that has
+/// waiting threads.
+///
+/// **scope**:
+/// Whether the condition variable is stored in
+/// private or shared memory.
+///
+/// **nwaiters**:
+/// The number of threads that need to be woken
+/// up. If it exceeds the number of waiting
+/// threads, all threads are woken up.
+#[inline]
+pub unsafe fn condvar_signal(condvar_: *mut condvar, scope_: scope, nwaiters_: nthreads) -> errno {
+ cloudabi_sys_condvar_signal(condvar_, scope_, nwaiters_)
+}
+
+/// Closes a file descriptor.
+///
+/// ## Parameters
+///
+/// **fd**:
+/// The file descriptor that needs to be closed.
+#[inline]
+pub unsafe fn fd_close(fd_: fd) -> errno {
+ cloudabi_sys_fd_close(fd_)
+}
+
+/// Creates a file descriptor.
+///
+/// ## Parameters
+///
+/// **type**:
+/// Possible values:
+///
+/// - [`SHARED_MEMORY`](enum.filetype.html#variant.SHARED_MEMORY):
+/// Creates an anonymous shared memory
+/// object.
+///
+/// **fd**:
+/// The file descriptor that has been created.
+#[inline]
+pub unsafe fn fd_create1(type_: filetype, fd_: &mut fd) -> errno {
+ cloudabi_sys_fd_create1(type_, fd_)
+}
+
+/// Creates a pair of file descriptors.
+///
+/// ## Parameters
+///
+/// **type**:
+/// Possible values:
+///
+/// - [`SOCKET_DGRAM`](enum.filetype.html#variant.SOCKET_DGRAM):
+/// Creates a UNIX datagram socket pair.
+/// - [`SOCKET_STREAM`](enum.filetype.html#variant.SOCKET_STREAM):
+/// Creates a UNIX byte-stream socket
+/// pair.
+///
+/// **fd1**:
+/// The first file descriptor of the pair.
+///
+/// **fd2**:
+/// The second file descriptor of the pair.
+#[inline]
+pub unsafe fn fd_create2(type_: filetype, fd1_: &mut fd, fd2_: &mut fd) -> errno {
+ cloudabi_sys_fd_create2(type_, fd1_, fd2_)
+}
+
+/// Synchronizes the data of a file to disk.
+///
+/// ## Parameters
+///
+/// **fd**:
+/// The file descriptor of the file whose data
+/// needs to be synchronized to disk.
+#[inline]
+pub unsafe fn fd_datasync(fd_: fd) -> errno {
+ cloudabi_sys_fd_datasync(fd_)
+}
+
+/// Duplicates a file descriptor.
+///
+/// ## Parameters
+///
+/// **from**:
+/// The file descriptor that needs to be
+/// duplicated.
+///
+/// **fd**:
+/// The new file descriptor.
+#[inline]
+pub unsafe fn fd_dup(from_: fd, fd_: &mut fd) -> errno {
+ cloudabi_sys_fd_dup(from_, fd_)
+}
+
+/// Reads from a file descriptor, without using and updating the
+/// file descriptor's offset.
+///
+/// ## Parameters
+///
+/// **fd**:
+/// The file descriptor from which data should be
+/// read.
+///
+/// **iovs**:
+/// List of scatter/gather vectors where data
+/// should be stored.
+///
+/// **offset**:
+/// The offset within the file at which reading
+/// should start.
+///
+/// **nread**:
+/// The number of bytes read.
+#[inline]
+pub unsafe fn fd_pread(fd_: fd, iovs_: &[iovec], offset_: filesize, nread_: &mut usize) -> errno {
+ cloudabi_sys_fd_pread(fd_, iovs_.as_ptr(), iovs_.len(), offset_, nread_)
+}
+
+/// Writes to a file descriptor, without using and updating the
+/// file descriptor's offset.
+///
+/// ## Parameters
+///
+/// **fd**:
+/// The file descriptor to which data should be
+/// written.
+///
+/// **iovs**:
+/// List of scatter/gather vectors where data
+/// should be retrieved.
+///
+/// **offset**:
+/// The offset within the file at which writing
+/// should start.
+///
+/// **nwritten**:
+/// The number of bytes written.
+#[inline]
+pub unsafe fn fd_pwrite(fd_: fd, iovs_: &[ciovec], offset_: filesize, nwritten_: &mut usize) -> errno {
+ cloudabi_sys_fd_pwrite(fd_, iovs_.as_ptr(), iovs_.len(), offset_, nwritten_)
+}
+
+/// Reads from a file descriptor.
+///
+/// ## Parameters
+///
+/// **fd**:
+/// The file descriptor from which data should be
+/// read.
+///
+/// **iovs**:
+/// List of scatter/gather vectors where data
+/// should be stored.
+///
+/// **nread**:
+/// The number of bytes read.
+#[inline]
+pub unsafe fn fd_read(fd_: fd, iovs_: &[iovec], nread_: &mut usize) -> errno {
+ cloudabi_sys_fd_read(fd_, iovs_.as_ptr(), iovs_.len(), nread_)
+}
+
+/// Atomically replaces a file descriptor by a copy of another
+/// file descriptor.
+///
+/// Due to the strong focus on thread safety, this environment
+/// does not provide a mechanism to duplicate a file descriptor to
+/// an arbitrary number, like dup2(). This would be prone to race
+/// conditions, as an actual file descriptor with the same number
+/// could be allocated by a different thread at the same time.
+///
+/// This system call provides a way to atomically replace file
+/// descriptors, which would disappear if dup2() were to be
+/// removed entirely.
+///
+/// ## Parameters
+///
+/// **from**:
+/// The file descriptor that needs to be copied.
+///
+/// **to**:
+/// The file descriptor that needs to be
+/// overwritten.
+#[inline]
+pub unsafe fn fd_replace(from_: fd, to_: fd) -> errno {
+ cloudabi_sys_fd_replace(from_, to_)
+}
+
+/// Moves the offset of the file descriptor.
+///
+/// ## Parameters
+///
+/// **fd**:
+/// The file descriptor whose offset has to be
+/// moved.
+///
+/// **offset**:
+/// The number of bytes to move.
+///
+/// **whence**:
+/// Relative to which position the move should
+/// take place.
+///
+/// **newoffset**:
+/// The new offset of the file descriptor,
+/// relative to the start of the file.
+#[inline]
+pub unsafe fn fd_seek(fd_: fd, offset_: filedelta, whence_: whence, newoffset_: &mut filesize) -> errno {
+ cloudabi_sys_fd_seek(fd_, offset_, whence_, newoffset_)
+}
+
+/// Gets attributes of a file descriptor.
+///
+/// ## Parameters
+///
+/// **fd**:
+/// The file descriptor whose attributes have to
+/// be obtained.
+///
+/// **buf**:
+/// The buffer where the file descriptor's
+/// attributes are stored.
+#[inline]
+pub unsafe fn fd_stat_get(fd_: fd, buf_: *mut fdstat) -> errno {
+ cloudabi_sys_fd_stat_get(fd_, buf_)
+}
+
+/// Adjusts attributes of a file descriptor.
+///
+/// ## Parameters
+///
+/// **fd**:
+/// The file descriptor whose attributes have to
+/// be adjusted.
+///
+/// **buf**:
+/// The desired values of the file descriptor
+/// attributes that are adjusted.
+///
+/// **flags**:
+/// A bitmask indicating which attributes have to
+/// be adjusted.
+#[inline]
+pub unsafe fn fd_stat_put(fd_: fd, buf_: *const fdstat, flags_: fdsflags) -> errno {
+ cloudabi_sys_fd_stat_put(fd_, buf_, flags_)
+}
+
+/// Synchronizes the data and metadata of a file to disk.
+///
+/// ## Parameters
+///
+/// **fd**:
+/// The file descriptor of the file whose data
+/// and metadata needs to be synchronized to disk.
+#[inline]
+pub unsafe fn fd_sync(fd_: fd) -> errno {
+ cloudabi_sys_fd_sync(fd_)
+}
+
+/// Writes to a file descriptor.
+///
+/// ## Parameters
+///
+/// **fd**:
+/// The file descriptor to which data should be
+/// written.
+///
+/// **iovs**:
+/// List of scatter/gather vectors where data
+/// should be retrieved.
+///
+/// **nwritten**:
+/// The number of bytes written.
+#[inline]
+pub unsafe fn fd_write(fd_: fd, iovs_: &[ciovec], nwritten_: &mut usize) -> errno {
+ cloudabi_sys_fd_write(fd_, iovs_.as_ptr(), iovs_.len(), nwritten_)
+}
+
+/// Provides file advisory information on a file descriptor.
+///
+/// ## Parameters
+///
+/// **fd**:
+/// The file descriptor for which to provide file
+/// advisory information.
+///
+/// **offset**:
+/// The offset within the file to which the
+/// advisory applies.
+///
+/// **len**:
+/// The length of the region to which the advisory
+/// applies.
+///
+/// **advice**:
+/// The advice.
+#[inline]
+pub unsafe fn file_advise(fd_: fd, offset_: filesize, len_: filesize, advice_: advice) -> errno {
+ cloudabi_sys_file_advise(fd_, offset_, len_, advice_)
+}
+
+/// Forces the allocation of space in a file.
+///
+/// ## Parameters
+///
+/// **fd**:
+/// The file in which the space should be
+/// allocated.
+///
+/// **offset**:
+/// The offset at which the allocation should
+/// start.
+///
+/// **len**:
+/// The length of the area that is allocated.
+#[inline]
+pub unsafe fn file_allocate(fd_: fd, offset_: filesize, len_: filesize) -> errno {
+ cloudabi_sys_file_allocate(fd_, offset_, len_)
+}
+
+/// Creates a file of a specified type.
+///
+/// ## Parameters
+///
+/// **fd**:
+/// The working directory at which the resolution
+/// of the file to be created starts.
+///
+/// **path**:
+/// The path at which the file should be created.
+///
+/// **type**:
+/// Possible values:
+///
+/// - [`DIRECTORY`](enum.filetype.html#variant.DIRECTORY):
+/// Creates a directory.
+#[inline]
+pub unsafe fn file_create(fd_: fd, path_: &[u8], type_: filetype) -> errno {
+ cloudabi_sys_file_create(fd_, path_.as_ptr(), path_.len(), type_)
+}
+
+/// Creates a hard link.
+///
+/// ## Parameters
+///
+/// **fd1**:
+/// The working directory at which the resolution
+/// of the source path starts.
+///
+/// **path1**:
+/// The source path of the file that should be
+/// hard linked.
+///
+/// **fd2**:
+/// The working directory at which the resolution
+/// of the destination path starts.
+///
+/// **path2**:
+/// The destination path at which the hard link
+/// should be created.
+#[inline]
+pub unsafe fn file_link(fd1_: lookup, path1_: &[u8], fd2_: fd, path2_: &[u8]) -> errno {
+ cloudabi_sys_file_link(fd1_, path1_.as_ptr(), path1_.len(), fd2_, path2_.as_ptr(), path2_.len())
+}
+
+/// Opens a file.
+///
+/// ## Parameters
+///
+/// **dirfd**:
+/// The working directory at which the resolution
+/// of the file to be opened starts.
+///
+/// **path**:
+/// The path of the file that should be opened.
+///
+/// **oflags**:
+/// The method at which the file should be opened.
+///
+/// **fds**:
+/// [`fdstat.fs_rights_base`](struct.fdstat.html#structfield.fs_rights_base) and
+/// [`fdstat.fs_rights_inheriting`](struct.fdstat.html#structfield.fs_rights_inheriting) specify the
+/// initial rights of the newly created file
+/// descriptor. The operating system is allowed to
+/// return a file descriptor with fewer rights
+/// than specified, if and only if those rights do
+/// not apply to the type of file being opened.
+///
+/// [`fdstat.fs_flags`](struct.fdstat.html#structfield.fs_flags) specifies the initial flags
+/// of the file descriptor.
+///
+/// [`fdstat.fs_filetype`](struct.fdstat.html#structfield.fs_filetype) is ignored.
+///
+/// **fd**:
+/// The file descriptor of the file that has been
+/// opened.
+#[inline]
+pub unsafe fn file_open(dirfd_: lookup, path_: &[u8], oflags_: oflags, fds_: *const fdstat, fd_: &mut fd) -> errno {
+ cloudabi_sys_file_open(dirfd_, path_.as_ptr(), path_.len(), oflags_, fds_, fd_)
+}
+
+/// Reads directory entries from a directory.
+///
+/// When successful, the contents of the output buffer consist of
+/// a sequence of directory entries. Each directory entry consists
+/// of a [`dirent`](struct.dirent.html) object, followed by [`dirent.d_namlen`](struct.dirent.html#structfield.d_namlen) bytes
+/// holding the name of the directory entry.
+///
+/// This system call fills the output buffer as much as possible,
+/// potentially truncating the last directory entry. This allows
+/// the caller to grow its read buffer size in case it's too small
+/// to fit a single large directory entry, or skip the oversized
+/// directory entry.
+///
+/// ## Parameters
+///
+/// **fd**:
+/// The directory from which to read the directory
+/// entries.
+///
+/// **buf**:
+/// The buffer where directory entries are stored.
+///
+/// **cookie**:
+/// The location within the directory to start
+/// reading.
+///
+/// **bufused**:
+/// The number of bytes stored in the read buffer.
+/// If less than the size of the read buffer, the
+/// end of the directory has been reached.
+#[inline]
+pub unsafe fn file_readdir(fd_: fd, buf_: &mut [u8], cookie_: dircookie, bufused_: &mut usize) -> errno {
+ cloudabi_sys_file_readdir(fd_, buf_.as_mut_ptr() as *mut (), buf_.len(), cookie_, bufused_)
+}
+
+/// Reads the contents of a symbolic link.
+///
+/// ## Parameters
+///
+/// **fd**:
+/// The working directory at which the resolution
+/// of the path of the symbolic starts.
+///
+/// **path**:
+/// The path of the symbolic link whose contents
+/// should be read.
+///
+/// **buf**:
+/// The buffer where the contents of the symbolic
+/// link should be stored.
+///
+/// **bufused**:
+/// The number of bytes placed in the buffer.
+#[inline]
+pub unsafe fn file_readlink(fd_: fd, path_: &[u8], buf_: &mut [u8], bufused_: &mut usize) -> errno {
+ cloudabi_sys_file_readlink(fd_, path_.as_ptr(), path_.len(), buf_.as_mut_ptr(), buf_.len(), bufused_)
+}
+
+/// Renames a file.
+///
+/// ## Parameters
+///
+/// **fd1**:
+/// The working directory at which the resolution
+/// of the source path starts.
+///
+/// **path1**:
+/// The source path of the file that should be
+/// renamed.
+///
+/// **fd2**:
+/// The working directory at which the resolution
+/// of the destination path starts.
+///
+/// **path2**:
+/// The destination path to which the file should
+/// be renamed.
+#[inline]
+pub unsafe fn file_rename(fd1_: fd, path1_: &[u8], fd2_: fd, path2_: &[u8]) -> errno {
+ cloudabi_sys_file_rename(fd1_, path1_.as_ptr(), path1_.len(), fd2_, path2_.as_ptr(), path2_.len())
+}
+
+/// Gets attributes of a file by file descriptor.
+///
+/// ## Parameters
+///
+/// **fd**:
+/// The file descriptor whose attributes have to
+/// be obtained.
+///
+/// **buf**:
+/// The buffer where the file's attributes are
+/// stored.
+#[inline]
+pub unsafe fn file_stat_fget(fd_: fd, buf_: *mut filestat) -> errno {
+ cloudabi_sys_file_stat_fget(fd_, buf_)
+}
+
+/// Adjusts attributes of a file by file descriptor.
+///
+/// ## Parameters
+///
+/// **fd**:
+/// The file descriptor whose attributes have to
+/// be adjusted.
+///
+/// **buf**:
+/// The desired values of the file attributes that
+/// are adjusted.
+///
+/// **flags**:
+/// A bitmask indicating which attributes have to
+/// be adjusted.
+#[inline]
+pub unsafe fn file_stat_fput(fd_: fd, buf_: *const filestat, flags_: fsflags) -> errno {
+ cloudabi_sys_file_stat_fput(fd_, buf_, flags_)
+}
+
+/// Gets attributes of a file by path.
+///
+/// ## Parameters
+///
+/// **fd**:
+/// The working directory at which the resolution
+/// of the path whose attributes have to be
+/// obtained starts.
+///
+/// **path**:
+/// The path of the file whose attributes have to
+/// be obtained.
+///
+/// **buf**:
+/// The buffer where the file's attributes are
+/// stored.
+#[inline]
+pub unsafe fn file_stat_get(fd_: lookup, path_: &[u8], buf_: *mut filestat) -> errno {
+ cloudabi_sys_file_stat_get(fd_, path_.as_ptr(), path_.len(), buf_)
+}
+
+/// Adjusts attributes of a file by path.
+///
+/// ## Parameters
+///
+/// **fd**:
+/// The working directory at which the resolution
+/// of the path whose attributes have to be
+/// adjusted starts.
+///
+/// **path**:
+/// The path of the file whose attributes have to
+/// be adjusted.
+///
+/// **buf**:
+/// The desired values of the file attributes that
+/// are adjusted.
+///
+/// **flags**:
+/// A bitmask indicating which attributes have to
+/// be adjusted.
+#[inline]
+pub unsafe fn file_stat_put(fd_: lookup, path_: &[u8], buf_: *const filestat, flags_: fsflags) -> errno {
+ cloudabi_sys_file_stat_put(fd_, path_.as_ptr(), path_.len(), buf_, flags_)
+}
+
+/// Creates a symbolic link.
+///
+/// ## Parameters
+///
+/// **path1**:
+/// The contents of the symbolic link.
+///
+/// **fd**:
+/// The working directory at which the resolution
+/// of the destination path starts.
+///
+/// **path2**:
+/// The destination path at which the symbolic
+/// link should be created.
+#[inline]
+pub unsafe fn file_symlink(path1_: &[u8], fd_: fd, path2_: &[u8]) -> errno {
+ cloudabi_sys_file_symlink(path1_.as_ptr(), path1_.len(), fd_, path2_.as_ptr(), path2_.len())
+}
+
+/// Unlinks a file, or removes a directory.
+///
+/// ## Parameters
+///
+/// **fd**:
+/// The working directory at which the resolution
+/// of the path starts.
+///
+/// **path**:
+/// The path that needs to be unlinked or removed.
+///
+/// **flags**:
+/// Possible values:
+///
+/// - [`REMOVEDIR`](struct.ulflags.html#associatedconstant.REMOVEDIR):
+/// If set, attempt to remove a directory.
+/// Otherwise, unlink a file.
+#[inline]
+pub unsafe fn file_unlink(fd_: fd, path_: &[u8], flags_: ulflags) -> errno {
+ cloudabi_sys_file_unlink(fd_, path_.as_ptr(), path_.len(), flags_)
+}
+
+/// Unlocks a write-locked userspace lock.
+///
+/// If a userspace lock is unlocked while having its
+/// [`LOCK_KERNEL_MANAGED`](constant.LOCK_KERNEL_MANAGED.html) flag set, the lock cannot be unlocked in
+/// userspace directly. This system call needs to be performed
+/// instead, so that any waiting threads can be woken up.
+///
+/// To prevent spurious invocations of this system call, the lock
+/// must be locked for writing. This prevents other threads from
+/// acquiring additional read locks while the system call is in
+/// progress. If the lock is acquired for reading, it must first
+/// be upgraded to a write lock.
+///
+/// ## Parameters
+///
+/// **lock**:
+/// The userspace lock that is locked for writing
+/// by the calling thread.
+///
+/// **scope**:
+/// Whether the lock is stored in private or
+/// shared memory.
+#[inline]
+pub unsafe fn lock_unlock(lock_: *mut lock, scope_: scope) -> errno {
+ cloudabi_sys_lock_unlock(lock_, scope_)
+}
+
+/// Provides memory advisory information on a region of memory.
+///
+/// ## Parameters
+///
+/// **mapping**:
+/// The pages for which to provide memory advisory
+/// information.
+///
+/// **advice**:
+/// The advice.
+#[inline]
+pub unsafe fn mem_advise(mapping_: &mut [u8], advice_: advice) -> errno {
+ cloudabi_sys_mem_advise(mapping_.as_mut_ptr() as *mut (), mapping_.len(), advice_)
+}
+
+/// Creates a memory mapping, making the contents of a file
+/// accessible through memory.
+///
+/// ## Parameters
+///
+/// **addr**:
+/// If [`FIXED`](struct.mflags.html#associatedconstant.FIXED) is set, specifies to which
+/// address the file region is mapped. Otherwise,
+/// the mapping is performed at an unused
+/// location.
+///
+/// **len**:
+/// The length of the memory mapping to be
+/// created.
+///
+/// **prot**:
+/// Initial memory protection options for the
+/// memory mapping.
+///
+/// **flags**:
+/// Memory mapping flags.
+///
+/// **fd**:
+/// If [`ANON`](struct.mflags.html#associatedconstant.ANON) is set, this argument must be
+/// [`MAP_ANON_FD`](constant.MAP_ANON_FD.html). Otherwise, this argument
+/// specifies the file whose contents need to be
+/// mapped.
+///
+/// **off**:
+/// If [`ANON`](struct.mflags.html#associatedconstant.ANON) is set, this argument must be
+/// zero. Otherwise, this argument specifies the
+/// offset within the file at which the mapping
+/// starts.
+///
+/// **mem**:
+/// The starting address of the memory mapping.
+#[inline]
+pub unsafe fn mem_map(addr_: *mut (), len_: usize, prot_: mprot, flags_: mflags, fd_: fd, off_: filesize, mem_: &mut *mut ()) -> errno {
+ cloudabi_sys_mem_map(addr_, len_, prot_, flags_, fd_, off_, mem_)
+}
+
+/// Change the protection of a memory mapping.
+///
+/// ## Parameters
+///
+/// **mapping**:
+/// The pages that need their protection changed.
+///
+/// **prot**:
+/// New protection options.
+#[inline]
+pub unsafe fn mem_protect(mapping_: &mut [u8], prot_: mprot) -> errno {
+ cloudabi_sys_mem_protect(mapping_.as_mut_ptr() as *mut (), mapping_.len(), prot_)
+}
+
+/// Synchronize a region of memory with its physical storage.
+///
+/// ## Parameters
+///
+/// **mapping**:
+/// The pages that need to be synchronized.
+///
+/// **flags**:
+/// The method of synchronization.
+#[inline]
+pub unsafe fn mem_sync(mapping_: &mut [u8], flags_: msflags) -> errno {
+ cloudabi_sys_mem_sync(mapping_.as_mut_ptr() as *mut (), mapping_.len(), flags_)
+}
+
+/// Unmaps a region of memory.
+///
+/// ## Parameters
+///
+/// **mapping**:
+/// The pages that needs to be unmapped.
+#[inline]
+pub unsafe fn mem_unmap(mapping_: &mut [u8]) -> errno {
+ cloudabi_sys_mem_unmap(mapping_.as_mut_ptr() as *mut (), mapping_.len())
+}
+
+/// Concurrently polls for the occurrence of a set of events.
+///
+/// ## Parameters
+///
+/// **in**:
+/// The events to which to subscribe.
+///
+/// **out**:
+/// The events that have occurred.
+///
+/// **nsubscriptions**:
+/// Both the number of subscriptions and events.
+///
+/// **nevents**:
+/// The number of events stored.
+#[inline]
+pub unsafe fn poll(in_: *const subscription, out_: *mut event, nsubscriptions_: usize, nevents_: &mut usize) -> errno {
+ cloudabi_sys_poll(in_, out_, nsubscriptions_, nevents_)
+}
+
+/// Replaces the process by a new executable.
+///
+/// Process execution in CloudABI differs from POSIX in two ways:
+/// handling of arguments and inheritance of file descriptors.
+///
+/// CloudABI does not use string command line arguments. Instead,
+/// a buffer with binary data is copied into the address space of
+/// the new executable. The kernel does not enforce any specific
+/// structure to this data, although CloudABI's C library uses it
+/// to store a tree structure that is semantically identical to
+/// YAML.
+///
+/// Due to the strong focus on thread safety, file descriptors
+/// aren't inherited through close-on-exec flags. An explicit
+/// list of file descriptors that need to be retained needs to be
+/// provided. After execution, file descriptors are placed in the
+/// order in which they are stored in the array. This not only
+/// makes the execution process deterministic. It also prevents
+/// potential information disclosures about the layout of the
+/// original process.
+///
+/// ## Parameters
+///
+/// **fd**:
+/// A file descriptor of the new executable.
+///
+/// **data**:
+/// Binary argument data that is passed on to the
+/// new executable.
+///
+/// **fds**:
+/// The layout of the file descriptor table after
+/// execution.
+#[inline]
+pub unsafe fn proc_exec(fd_: fd, data_: &[u8], fds_: &[fd]) -> errno {
+ cloudabi_sys_proc_exec(fd_, data_.as_ptr() as *const (), data_.len(), fds_.as_ptr(), fds_.len())
+}
+
+/// Terminates the process normally.
+///
+/// ## Parameters
+///
+/// **rval**:
+/// The exit code returned by the process. The
+/// exit code can be obtained by other processes
+/// through [`event.union.proc_terminate.exitcode`](struct.event_proc_terminate.html#structfield.exitcode).
+#[inline]
+pub unsafe fn proc_exit(rval_: exitcode) -> ! {
+ cloudabi_sys_proc_exit(rval_)
+}
+
+/// Forks the process of the calling thread.
+///
+/// After forking, a new process shall be created, having only a
+/// copy of the calling thread. The parent process will obtain a
+/// process descriptor. When closed, the child process is
+/// automatically signaled with [`KILL`](enum.signal.html#variant.KILL).
+///
+/// ## Parameters
+///
+/// **fd**:
+/// In the parent process: the file descriptor
+/// number of the process descriptor.
+///
+/// In the child process: [`PROCESS_CHILD`](constant.PROCESS_CHILD.html).
+///
+/// **tid**:
+/// In the parent process: undefined.
+///
+/// In the child process: the thread ID of the
+/// initial thread of the child process.
+#[inline]
+pub unsafe fn proc_fork(fd_: &mut fd, tid_: &mut tid) -> errno {
+ cloudabi_sys_proc_fork(fd_, tid_)
+}
+
+/// Sends a signal to the process of the calling thread.
+///
+/// ## Parameters
+///
+/// **sig**:
+/// The signal condition that should be triggered.
+/// If the signal causes the process to terminate,
+/// its condition can be obtained by other
+/// processes through
+/// [`event.union.proc_terminate.signal`](struct.event_proc_terminate.html#structfield.signal).
+#[inline]
+pub unsafe fn proc_raise(sig_: signal) -> errno {
+ cloudabi_sys_proc_raise(sig_)
+}
+
+/// Obtains random data from the kernel random number generator.
+///
+/// As this interface is not guaranteed to be fast, it is advised
+/// that the random data obtained through this system call is used
+/// as the seed for a userspace pseudo-random number generator.
+///
+/// ## Parameters
+///
+/// **buf**:
+/// The buffer that needs to be filled with random
+/// data.
+#[inline]
+pub unsafe fn random_get(buf_: &mut [u8]) -> errno {
+ cloudabi_sys_random_get(buf_.as_mut_ptr() as *mut (), buf_.len())
+}
+
+/// Receives a message on a socket.
+///
+/// ## Parameters
+///
+/// **sock**:
+/// The socket on which a message should be
+/// received.
+///
+/// **in**:
+/// Input parameters.
+///
+/// **out**:
+/// Output parameters.
+#[inline]
+pub unsafe fn sock_recv(sock_: fd, in_: *const recv_in, out_: *mut recv_out) -> errno {
+ cloudabi_sys_sock_recv(sock_, in_, out_)
+}
+
+/// Sends a message on a socket.
+///
+/// ## Parameters
+///
+/// **sock**:
+/// The socket on which a message should be sent.
+///
+/// **in**:
+/// Input parameters.
+///
+/// **out**:
+/// Output parameters.
+#[inline]
+pub unsafe fn sock_send(sock_: fd, in_: *const send_in, out_: *mut send_out) -> errno {
+ cloudabi_sys_sock_send(sock_, in_, out_)
+}
+
+/// Shuts down socket send and receive channels.
+///
+/// ## Parameters
+///
+/// **sock**:
+/// The socket that needs its channels shut down.
+///
+/// **how**:
+/// Which channels on the socket need to be shut
+/// down.
+#[inline]
+pub unsafe fn sock_shutdown(sock_: fd, how_: sdflags) -> errno {
+ cloudabi_sys_sock_shutdown(sock_, how_)
+}
+
+/// Creates a new thread within the current process.
+///
+/// ## Parameters
+///
+/// **attr**:
+/// The desired attributes of the new thread.
+///
+/// **tid**:
+/// The thread ID of the new thread.
+#[inline]
+pub unsafe fn thread_create(attr_: *mut threadattr, tid_: &mut tid) -> errno {
+ cloudabi_sys_thread_create(attr_, tid_)
+}
+
+/// Terminates the calling thread.
+///
+/// This system call can also unlock a single userspace lock
+/// after termination, which can be used to implement thread
+/// joining.
+///
+/// ## Parameters
+///
+/// **lock**:
+/// Userspace lock that is locked for writing by
+/// the calling thread.
+///
+/// **scope**:
+/// Whether the lock is stored in private or
+/// shared memory.
+#[inline]
+pub unsafe fn thread_exit(lock_: *mut lock, scope_: scope) -> ! {
+ cloudabi_sys_thread_exit(lock_, scope_)
+}
+
+/// Temporarily yields execution of the calling thread.
+#[inline]
+pub unsafe fn thread_yield() -> errno {
+ cloudabi_sys_thread_yield()
+}
--- /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.
+
+#[allow(warnings)]
+mod cloudabi;
+pub use self::cloudabi::*;
--- /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.
+
+pub use sys::cloudabi::shims::args::*;
+
+#[allow(dead_code)]
+pub fn init(_: isize, _: *const *const u8) {}
+
+#[allow(dead_code)]
+pub fn cleanup() {}
--- /dev/null
+// Copyright 2014-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 error::Error;
+use ffi::CStr;
+use intrinsics;
+use io;
+use libc;
+use sys_common::backtrace::Frame;
+use unwind as uw;
+
+pub struct BacktraceContext;
+
+struct Context<'a> {
+ idx: usize,
+ frames: &'a mut [Frame],
+}
+
+#[derive(Debug)]
+struct UnwindError(uw::_Unwind_Reason_Code);
+
+impl Error for UnwindError {
+ fn description(&self) -> &'static str {
+ "unexpected return value while unwinding"
+ }
+}
+
+impl ::fmt::Display for UnwindError {
+ fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result {
+ write!(f, "{}: {:?}", self.description(), self.0)
+ }
+}
+
+#[inline(never)] // if we know this is a function call, we can skip it when
+ // tracing
+pub fn unwind_backtrace(frames: &mut [Frame]) -> io::Result<(usize, BacktraceContext)> {
+ let mut cx = Context { idx: 0, frames };
+ let result_unwind =
+ unsafe { uw::_Unwind_Backtrace(trace_fn, &mut cx as *mut Context as *mut libc::c_void) };
+ // See libunwind:src/unwind/Backtrace.c for the return values.
+ // No, there is no doc.
+ match result_unwind {
+ // These return codes seem to be benign and need to be ignored for backtraces
+ // to show up properly on all tested platforms.
+ uw::_URC_END_OF_STACK | uw::_URC_FATAL_PHASE1_ERROR | uw::_URC_FAILURE => {
+ Ok((cx.idx, BacktraceContext))
+ }
+ _ => Err(io::Error::new(
+ io::ErrorKind::Other,
+ UnwindError(result_unwind),
+ )),
+ }
+}
+
+extern "C" fn trace_fn(
+ ctx: *mut uw::_Unwind_Context,
+ arg: *mut libc::c_void,
+) -> uw::_Unwind_Reason_Code {
+ let cx = unsafe { &mut *(arg as *mut Context) };
+ let mut ip_before_insn = 0;
+ let mut ip = unsafe { uw::_Unwind_GetIPInfo(ctx, &mut ip_before_insn) as *mut libc::c_void };
+ if !ip.is_null() && ip_before_insn == 0 {
+ // this is a non-signaling frame, so `ip` refers to the address
+ // after the calling instruction. account for that.
+ ip = (ip as usize - 1) as *mut _;
+ }
+
+ let symaddr = unsafe { uw::_Unwind_FindEnclosingFunction(ip) };
+ if cx.idx < cx.frames.len() {
+ cx.frames[cx.idx] = Frame {
+ symbol_addr: symaddr as *mut u8,
+ exact_position: ip as *mut u8,
+ };
+ cx.idx += 1;
+ }
+
+ uw::_URC_NO_REASON
+}
+
+pub fn foreach_symbol_fileline<F>(_: Frame, _: F, _: &BacktraceContext) -> io::Result<bool>
+where
+ F: FnMut(&[u8], u32) -> io::Result<()>,
+{
+ // No way to obtain this information on CloudABI.
+ Ok(false)
+}
+
+pub fn resolve_symname<F>(frame: Frame, callback: F, _: &BacktraceContext) -> io::Result<()>
+where
+ F: FnOnce(Option<&str>) -> io::Result<()>,
+{
+ unsafe {
+ let mut info: Dl_info = intrinsics::init();
+ let symname =
+ if dladdr(frame.exact_position as *mut _, &mut info) == 0 || info.dli_sname.is_null() {
+ None
+ } else {
+ CStr::from_ptr(info.dli_sname).to_str().ok()
+ };
+ callback(symname)
+ }
+}
+
+#[repr(C)]
+struct Dl_info {
+ dli_fname: *const libc::c_char,
+ dli_fbase: *mut libc::c_void,
+ dli_sname: *const libc::c_char,
+ dli_saddr: *mut libc::c_void,
+}
+
+extern "C" {
+ fn dladdr(addr: *const libc::c_void, info: *mut Dl_info) -> libc::c_int;
+}
--- /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 cell::UnsafeCell;
+use mem;
+use sync::atomic::{AtomicU32, Ordering};
+use sys::cloudabi::abi;
+use sys::mutex::{self, Mutex};
+use sys::time::dur2intervals;
+use time::Duration;
+
+extern "C" {
+ #[thread_local]
+ static __pthread_thread_id: abi::tid;
+}
+
+pub struct Condvar {
+ condvar: UnsafeCell<AtomicU32>,
+}
+
+unsafe impl Send for Condvar {}
+unsafe impl Sync for Condvar {}
+
+impl Condvar {
+ pub const fn new() -> Condvar {
+ Condvar {
+ condvar: UnsafeCell::new(AtomicU32::new(abi::CONDVAR_HAS_NO_WAITERS.0)),
+ }
+ }
+
+ pub unsafe fn init(&mut self) {}
+
+ pub unsafe fn notify_one(&self) {
+ let condvar = self.condvar.get();
+ if (*condvar).load(Ordering::Relaxed) != abi::CONDVAR_HAS_NO_WAITERS.0 {
+ let ret = abi::condvar_signal(condvar as *mut abi::condvar, abi::scope::PRIVATE, 1);
+ assert_eq!(
+ ret,
+ abi::errno::SUCCESS,
+ "Failed to signal on condition variable"
+ );
+ }
+ }
+
+ pub unsafe fn notify_all(&self) {
+ let condvar = self.condvar.get();
+ if (*condvar).load(Ordering::Relaxed) != abi::CONDVAR_HAS_NO_WAITERS.0 {
+ let ret = abi::condvar_signal(
+ condvar as *mut abi::condvar,
+ abi::scope::PRIVATE,
+ abi::nthreads::max_value(),
+ );
+ assert_eq!(
+ ret,
+ abi::errno::SUCCESS,
+ "Failed to broadcast on condition variable"
+ );
+ }
+ }
+
+ pub unsafe fn wait(&self, mutex: &Mutex) {
+ let mutex = mutex::raw(mutex);
+ assert_eq!(
+ (*mutex).load(Ordering::Relaxed) & !abi::LOCK_KERNEL_MANAGED.0,
+ __pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
+ "This lock is not write-locked by this thread"
+ );
+
+ // Call into the kernel to wait on the condition variable.
+ let condvar = self.condvar.get();
+ let subscription = abi::subscription {
+ type_: abi::eventtype::CONDVAR,
+ union: abi::subscription_union {
+ condvar: abi::subscription_condvar {
+ condvar: condvar as *mut abi::condvar,
+ condvar_scope: abi::scope::PRIVATE,
+ lock: mutex as *mut abi::lock,
+ lock_scope: abi::scope::PRIVATE,
+ },
+ },
+ ..mem::zeroed()
+ };
+ let mut event: abi::event = mem::uninitialized();
+ let mut nevents: usize = mem::uninitialized();
+ let ret = abi::poll(&subscription, &mut event, 1, &mut nevents);
+ assert_eq!(
+ ret,
+ abi::errno::SUCCESS,
+ "Failed to wait on condition variable"
+ );
+ assert_eq!(
+ event.error,
+ abi::errno::SUCCESS,
+ "Failed to wait on condition variable"
+ );
+ }
+
+ pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
+ let mutex = mutex::raw(mutex);
+ assert_eq!(
+ (*mutex).load(Ordering::Relaxed) & !abi::LOCK_KERNEL_MANAGED.0,
+ __pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
+ "This lock is not write-locked by this thread"
+ );
+
+ // Call into the kernel to wait on the condition variable.
+ let condvar = self.condvar.get();
+ let subscriptions = [
+ abi::subscription {
+ type_: abi::eventtype::CONDVAR,
+ union: abi::subscription_union {
+ condvar: abi::subscription_condvar {
+ condvar: condvar as *mut abi::condvar,
+ condvar_scope: abi::scope::PRIVATE,
+ lock: mutex as *mut abi::lock,
+ lock_scope: abi::scope::PRIVATE,
+ },
+ },
+ ..mem::zeroed()
+ },
+ abi::subscription {
+ type_: abi::eventtype::CLOCK,
+ union: abi::subscription_union {
+ clock: abi::subscription_clock {
+ clock_id: abi::clockid::MONOTONIC,
+ timeout: dur2intervals(&dur),
+ ..mem::zeroed()
+ },
+ },
+ ..mem::zeroed()
+ },
+ ];
+ let mut events: [abi::event; 2] = mem::uninitialized();
+ let mut nevents: usize = mem::uninitialized();
+ let ret = abi::poll(subscriptions.as_ptr(), events.as_mut_ptr(), 2, &mut nevents);
+ assert_eq!(
+ ret,
+ abi::errno::SUCCESS,
+ "Failed to wait on condition variable"
+ );
+ for i in 0..nevents {
+ assert_eq!(
+ events[i].error,
+ abi::errno::SUCCESS,
+ "Failed to wait on condition variable"
+ );
+ if events[i].type_ == abi::eventtype::CONDVAR {
+ return true;
+ }
+ }
+ false
+ }
+
+ pub unsafe fn destroy(&self) {
+ let condvar = self.condvar.get();
+ assert_eq!(
+ (*condvar).load(Ordering::Relaxed),
+ abi::CONDVAR_HAS_NO_WAITERS.0,
+ "Attempted to destroy a condition variable with blocked threads"
+ );
+ }
+}
--- /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 io;
+use libc;
+use mem;
+
+pub mod args;
+#[cfg(feature = "backtrace")]
+pub mod backtrace;
+#[path = "../unix/cmath.rs"]
+pub mod cmath;
+pub mod condvar;
+#[path = "../unix/memchr.rs"]
+pub mod memchr;
+pub mod mutex;
+pub mod os;
+#[path = "../unix/os_str.rs"]
+pub mod os_str;
+pub mod rwlock;
+pub mod stack_overflow;
+pub mod stdio;
+pub mod thread;
+#[path = "../unix/thread_local.rs"]
+pub mod thread_local;
+pub mod time;
+
+mod abi;
+
+mod shims;
+pub use self::shims::*;
+
+#[allow(dead_code)]
+pub fn init() {}
+
+pub fn decode_error_kind(errno: i32) -> io::ErrorKind {
+ match errno {
+ x if x == abi::errno::ACCES as i32 => io::ErrorKind::PermissionDenied,
+ x if x == abi::errno::ADDRINUSE as i32 => io::ErrorKind::AddrInUse,
+ x if x == abi::errno::ADDRNOTAVAIL as i32 => io::ErrorKind::AddrNotAvailable,
+ x if x == abi::errno::AGAIN as i32 => io::ErrorKind::WouldBlock,
+ x if x == abi::errno::CONNABORTED as i32 => io::ErrorKind::ConnectionAborted,
+ x if x == abi::errno::CONNREFUSED as i32 => io::ErrorKind::ConnectionRefused,
+ x if x == abi::errno::CONNRESET as i32 => io::ErrorKind::ConnectionReset,
+ x if x == abi::errno::EXIST as i32 => io::ErrorKind::AlreadyExists,
+ x if x == abi::errno::INTR as i32 => io::ErrorKind::Interrupted,
+ x if x == abi::errno::INVAL as i32 => io::ErrorKind::InvalidInput,
+ x if x == abi::errno::NOENT as i32 => io::ErrorKind::NotFound,
+ x if x == abi::errno::NOTCONN as i32 => io::ErrorKind::NotConnected,
+ x if x == abi::errno::PERM as i32 => io::ErrorKind::PermissionDenied,
+ x if x == abi::errno::PIPE as i32 => io::ErrorKind::BrokenPipe,
+ x if x == abi::errno::TIMEDOUT as i32 => io::ErrorKind::TimedOut,
+ _ => io::ErrorKind::Other,
+ }
+}
+
+pub unsafe fn abort_internal() -> ! {
+ ::core::intrinsics::abort();
+}
+
+pub use libc::strlen;
+
+pub fn hashmap_random_keys() -> (u64, u64) {
+ unsafe {
+ let mut v = mem::uninitialized();
+ libc::arc4random_buf(&mut v as *mut _ as *mut libc::c_void, mem::size_of_val(&v));
+ v
+ }
+}
--- /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 cell::UnsafeCell;
+use mem;
+use sync::atomic::{AtomicU32, Ordering};
+use sys::cloudabi::abi;
+use sys::rwlock::{self, RWLock};
+
+extern "C" {
+ #[thread_local]
+ static __pthread_thread_id: abi::tid;
+}
+
+// Implement Mutex using an RWLock. This doesn't introduce any
+// performance overhead in this environment, as the operations would be
+// implemented identically.
+pub struct Mutex(RWLock);
+
+pub unsafe fn raw(m: &Mutex) -> *mut AtomicU32 {
+ rwlock::raw(&m.0)
+}
+
+impl Mutex {
+ pub const fn new() -> Mutex {
+ Mutex(RWLock::new())
+ }
+
+ pub unsafe fn init(&mut self) {
+ // This function should normally reinitialize the mutex after
+ // moving it to a different memory address. This implementation
+ // does not require adjustments after moving.
+ }
+
+ pub unsafe fn try_lock(&self) -> bool {
+ self.0.try_write()
+ }
+
+ pub unsafe fn lock(&self) {
+ self.0.write()
+ }
+
+ pub unsafe fn unlock(&self) {
+ self.0.write_unlock()
+ }
+
+ pub unsafe fn destroy(&self) {
+ self.0.destroy()
+ }
+}
+
+pub struct ReentrantMutex {
+ lock: UnsafeCell<AtomicU32>,
+ recursion: UnsafeCell<u32>,
+}
+
+impl ReentrantMutex {
+ pub unsafe fn uninitialized() -> ReentrantMutex {
+ mem::uninitialized()
+ }
+
+ pub unsafe fn init(&mut self) {
+ self.lock = UnsafeCell::new(AtomicU32::new(abi::LOCK_UNLOCKED.0));
+ self.recursion = UnsafeCell::new(0);
+ }
+
+ pub unsafe fn try_lock(&self) -> bool {
+ // Attempt to acquire the lock.
+ let lock = self.lock.get();
+ let recursion = self.recursion.get();
+ if let Err(old) = (*lock).compare_exchange(
+ abi::LOCK_UNLOCKED.0,
+ __pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
+ Ordering::Acquire,
+ Ordering::Relaxed,
+ ) {
+ // If we fail to acquire the lock, it may be the case
+ // that we've already acquired it and may need to recurse.
+ if old & !abi::LOCK_KERNEL_MANAGED.0 == __pthread_thread_id.0 | abi::LOCK_WRLOCKED.0 {
+ *recursion += 1;
+ true
+ } else {
+ false
+ }
+ } else {
+ // Success.
+ assert_eq!(*recursion, 0, "Mutex has invalid recursion count");
+ true
+ }
+ }
+
+ pub unsafe fn lock(&self) {
+ if !self.try_lock() {
+ // Call into the kernel to acquire a write lock.
+ let lock = self.lock.get();
+ let subscription = abi::subscription {
+ type_: abi::eventtype::LOCK_WRLOCK,
+ union: abi::subscription_union {
+ lock: abi::subscription_lock {
+ lock: lock as *mut abi::lock,
+ lock_scope: abi::scope::PRIVATE,
+ },
+ },
+ ..mem::zeroed()
+ };
+ let mut event: abi::event = mem::uninitialized();
+ let mut nevents: usize = mem::uninitialized();
+ let ret = abi::poll(&subscription, &mut event, 1, &mut nevents);
+ assert_eq!(ret, abi::errno::SUCCESS, "Failed to acquire mutex");
+ assert_eq!(event.error, abi::errno::SUCCESS, "Failed to acquire mutex");
+ }
+ }
+
+ pub unsafe fn unlock(&self) {
+ let lock = self.lock.get();
+ let recursion = self.recursion.get();
+ assert_eq!(
+ (*lock).load(Ordering::Relaxed) & !abi::LOCK_KERNEL_MANAGED.0,
+ __pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
+ "This mutex is locked by a different thread"
+ );
+
+ if *recursion > 0 {
+ *recursion -= 1;
+ } else if !(*lock)
+ .compare_exchange(
+ __pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
+ abi::LOCK_UNLOCKED.0,
+ Ordering::Release,
+ Ordering::Relaxed,
+ )
+ .is_ok()
+ {
+ // Lock is managed by kernelspace. Call into the kernel
+ // to unblock waiting threads.
+ let ret = abi::lock_unlock(lock as *mut abi::lock, abi::scope::PRIVATE);
+ assert_eq!(ret, abi::errno::SUCCESS, "Failed to unlock a mutex");
+ }
+ }
+
+ pub unsafe fn destroy(&self) {
+ let lock = self.lock.get();
+ let recursion = self.recursion.get();
+ assert_eq!(
+ (*lock).load(Ordering::Relaxed),
+ abi::LOCK_UNLOCKED.0,
+ "Attempted to destroy locked mutex"
+ );
+ assert_eq!(*recursion, 0, "Recursion counter invalid");
+ }
+}
--- /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 ffi::CStr;
+use libc::{self, c_int};
+use str;
+
+pub use sys::cloudabi::shims::os::*;
+
+pub fn errno() -> i32 {
+ extern "C" {
+ #[thread_local]
+ static errno: c_int;
+ }
+
+ unsafe { errno as i32 }
+}
+
+/// Gets a detailed string description for the given error number.
+pub fn error_string(errno: i32) -> String {
+ // cloudlibc's strerror() is guaranteed to be thread-safe. There is
+ // thus no need to use strerror_r().
+ str::from_utf8(unsafe { CStr::from_ptr(libc::strerror(errno)) }.to_bytes())
+ .unwrap()
+ .to_owned()
+}
+
+pub fn exit(code: i32) -> ! {
+ unsafe { libc::exit(code as c_int) }
+}
--- /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 cell::UnsafeCell;
+use mem;
+use sync::atomic::{AtomicU32, Ordering};
+use sys::cloudabi::abi;
+
+extern "C" {
+ #[thread_local]
+ static __pthread_thread_id: abi::tid;
+}
+
+#[thread_local]
+static mut RDLOCKS_ACQUIRED: u32 = 0;
+
+pub struct RWLock {
+ lock: UnsafeCell<AtomicU32>,
+}
+
+pub unsafe fn raw(r: &RWLock) -> *mut AtomicU32 {
+ r.lock.get()
+}
+
+unsafe impl Send for RWLock {}
+unsafe impl Sync for RWLock {}
+
+impl RWLock {
+ pub const fn new() -> RWLock {
+ RWLock {
+ lock: UnsafeCell::new(AtomicU32::new(abi::LOCK_UNLOCKED.0)),
+ }
+ }
+
+ pub unsafe fn try_read(&self) -> bool {
+ let lock = self.lock.get();
+ let mut old = abi::LOCK_UNLOCKED.0;
+ while let Err(cur) =
+ (*lock).compare_exchange_weak(old, old + 1, Ordering::Acquire, Ordering::Relaxed)
+ {
+ if (cur & abi::LOCK_WRLOCKED.0) != 0 {
+ // Another thread already has a write lock.
+ assert_ne!(
+ old & !abi::LOCK_KERNEL_MANAGED.0,
+ __pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
+ "Attempted to acquire a read lock while holding a write lock"
+ );
+ return false;
+ } else if (old & abi::LOCK_KERNEL_MANAGED.0) != 0 && RDLOCKS_ACQUIRED == 0 {
+ // Lock has threads waiting for the lock. Only acquire
+ // the lock if we have already acquired read locks. In
+ // that case, it is justified to acquire this lock to
+ // prevent a deadlock.
+ return false;
+ }
+ old = cur;
+ }
+
+ RDLOCKS_ACQUIRED += 1;
+ true
+ }
+
+ pub unsafe fn read(&self) {
+ if !self.try_read() {
+ // Call into the kernel to acquire a read lock.
+ let lock = self.lock.get();
+ let subscription = abi::subscription {
+ type_: abi::eventtype::LOCK_RDLOCK,
+ union: abi::subscription_union {
+ lock: abi::subscription_lock {
+ lock: lock as *mut abi::lock,
+ lock_scope: abi::scope::PRIVATE,
+ },
+ },
+ ..mem::zeroed()
+ };
+ let mut event: abi::event = mem::uninitialized();
+ let mut nevents: usize = mem::uninitialized();
+ let ret = abi::poll(&subscription, &mut event, 1, &mut nevents);
+ assert_eq!(ret, abi::errno::SUCCESS, "Failed to acquire read lock");
+ assert_eq!(
+ event.error,
+ abi::errno::SUCCESS,
+ "Failed to acquire read lock"
+ );
+
+ RDLOCKS_ACQUIRED += 1;
+ }
+ }
+
+ pub unsafe fn read_unlock(&self) {
+ // Perform a read unlock. We can do this in userspace, except when
+ // other threads are blocked and we are performing the last unlock.
+ // In that case, call into the kernel.
+ //
+ // Other threads may attempt to increment the read lock count,
+ // meaning that the call into the kernel could be spurious. To
+ // prevent this from happening, upgrade to a write lock first. This
+ // allows us to call into the kernel, having the guarantee that the
+ // lock value will not change in the meantime.
+ assert!(RDLOCKS_ACQUIRED > 0, "Bad lock count");
+ let mut old = 1;
+ loop {
+ let lock = self.lock.get();
+ if old == 1 | abi::LOCK_KERNEL_MANAGED.0 {
+ // Last read lock while threads are waiting. Attempt to upgrade
+ // to a write lock before calling into the kernel to unlock.
+ if let Err(cur) = (*lock).compare_exchange_weak(
+ old,
+ __pthread_thread_id.0 | abi::LOCK_WRLOCKED.0 | abi::LOCK_KERNEL_MANAGED.0,
+ Ordering::Acquire,
+ Ordering::Relaxed,
+ ) {
+ old = cur;
+ } else {
+ // Call into the kernel to unlock.
+ let ret = abi::lock_unlock(lock as *mut abi::lock, abi::scope::PRIVATE);
+ assert_eq!(ret, abi::errno::SUCCESS, "Failed to write unlock a rwlock");
+ break;
+ }
+ } else {
+ // No threads waiting or not the last read lock. Just decrement
+ // the read lock count.
+ assert_ne!(
+ old & !abi::LOCK_KERNEL_MANAGED.0,
+ 0,
+ "This rwlock is not locked"
+ );
+ assert_eq!(
+ old & abi::LOCK_WRLOCKED.0,
+ 0,
+ "Attempted to read-unlock a write-locked rwlock"
+ );
+ if let Err(cur) = (*lock).compare_exchange_weak(
+ old,
+ old - 1,
+ Ordering::Acquire,
+ Ordering::Relaxed,
+ ) {
+ old = cur;
+ } else {
+ break;
+ }
+ }
+ }
+
+ RDLOCKS_ACQUIRED -= 1;
+ }
+
+ pub unsafe fn try_write(&self) -> bool {
+ // Attempt to acquire the lock.
+ let lock = self.lock.get();
+ if let Err(old) = (*lock).compare_exchange(
+ abi::LOCK_UNLOCKED.0,
+ __pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
+ Ordering::Acquire,
+ Ordering::Relaxed,
+ ) {
+ // Failure. Crash upon recursive acquisition.
+ assert_ne!(
+ old & !abi::LOCK_KERNEL_MANAGED.0,
+ __pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
+ "Attempted to recursive write-lock a rwlock",
+ );
+ false
+ } else {
+ // Success.
+ true
+ }
+ }
+
+ pub unsafe fn write(&self) {
+ if !self.try_write() {
+ // Call into the kernel to acquire a write lock.
+ let lock = self.lock.get();
+ let subscription = abi::subscription {
+ type_: abi::eventtype::LOCK_WRLOCK,
+ union: abi::subscription_union {
+ lock: abi::subscription_lock {
+ lock: lock as *mut abi::lock,
+ lock_scope: abi::scope::PRIVATE,
+ },
+ },
+ ..mem::zeroed()
+ };
+ let mut event: abi::event = mem::uninitialized();
+ let mut nevents: usize = mem::uninitialized();
+ let ret = abi::poll(&subscription, &mut event, 1, &mut nevents);
+ assert_eq!(ret, abi::errno::SUCCESS, "Failed to acquire write lock");
+ assert_eq!(
+ event.error,
+ abi::errno::SUCCESS,
+ "Failed to acquire write lock"
+ );
+ }
+ }
+
+ pub unsafe fn write_unlock(&self) {
+ let lock = self.lock.get();
+ assert_eq!(
+ (*lock).load(Ordering::Relaxed) & !abi::LOCK_KERNEL_MANAGED.0,
+ __pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
+ "This rwlock is not write-locked by this thread"
+ );
+
+ if !(*lock)
+ .compare_exchange(
+ __pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
+ abi::LOCK_UNLOCKED.0,
+ Ordering::Release,
+ Ordering::Relaxed,
+ )
+ .is_ok()
+ {
+ // Lock is managed by kernelspace. Call into the kernel
+ // to unblock waiting threads.
+ let ret = abi::lock_unlock(lock as *mut abi::lock, abi::scope::PRIVATE);
+ assert_eq!(ret, abi::errno::SUCCESS, "Failed to write unlock a rwlock");
+ }
+ }
+
+ pub unsafe fn destroy(&self) {
+ let lock = self.lock.get();
+ assert_eq!(
+ (*lock).load(Ordering::Relaxed),
+ abi::LOCK_UNLOCKED.0,
+ "Attempted to destroy locked rwlock"
+ );
+ }
+}
--- /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 ffi::OsString;
+
+pub struct Args(());
+
+impl Args {
+ pub fn inner_debug(&self) -> &[OsString] {
+ &[]
+ }
+}
+
+impl Iterator for Args {
+ type Item = OsString;
+ fn next(&mut self) -> Option<OsString> {
+ None
+ }
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ (0, Some(0))
+ }
+}
+
+impl ExactSizeIterator for Args {
+ fn len(&self) -> usize {
+ 0
+ }
+}
+
+impl DoubleEndedIterator for Args {
+ fn next_back(&mut self) -> Option<OsString> {
+ None
+ }
+}
+
+pub fn args() -> Args {
+ Args(())
+}
--- /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.
+
+pub mod os {
+ pub const FAMILY: &'static str = "cloudabi";
+ pub const OS: &'static str = "cloudabi";
+ pub const DLL_PREFIX: &'static str = "lib";
+ pub const DLL_SUFFIX: &'static str = ".so";
+ pub const DLL_EXTENSION: &'static str = "so";
+ pub const EXE_SUFFIX: &'static str = "";
+ pub const EXE_EXTENSION: &'static str = "";
+}
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <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 ffi::OsString;
+use fmt;
+use hash::{Hash, Hasher};
+use io::{self, SeekFrom};
+use path::{Path, PathBuf};
+use sys::time::SystemTime;
+use sys::{unsupported, Void};
+
+pub struct File(Void);
+
+pub struct FileAttr(Void);
+
+pub struct ReadDir(Void);
+
+pub struct DirEntry(Void);
+
+#[derive(Clone, Debug)]
+pub struct OpenOptions {}
+
+pub struct FilePermissions(Void);
+
+pub struct FileType(Void);
+
+#[derive(Debug)]
+pub struct DirBuilder {}
+
+impl FileAttr {
+ pub fn size(&self) -> u64 {
+ match self.0 {}
+ }
+
+ pub fn perm(&self) -> FilePermissions {
+ match self.0 {}
+ }
+
+ pub fn file_type(&self) -> FileType {
+ match self.0 {}
+ }
+
+ pub fn modified(&self) -> io::Result<SystemTime> {
+ match self.0 {}
+ }
+
+ pub fn accessed(&self) -> io::Result<SystemTime> {
+ match self.0 {}
+ }
+
+ pub fn created(&self) -> io::Result<SystemTime> {
+ match self.0 {}
+ }
+}
+
+impl Clone for FileAttr {
+ fn clone(&self) -> FileAttr {
+ match self.0 {}
+ }
+}
+
+impl FilePermissions {
+ pub fn readonly(&self) -> bool {
+ match self.0 {}
+ }
+
+ pub fn set_readonly(&mut self, _readonly: bool) {
+ match self.0 {}
+ }
+}
+
+impl Clone for FilePermissions {
+ fn clone(&self) -> FilePermissions {
+ match self.0 {}
+ }
+}
+
+impl PartialEq for FilePermissions {
+ fn eq(&self, _other: &FilePermissions) -> bool {
+ match self.0 {}
+ }
+}
+
+impl Eq for FilePermissions {}
+
+impl fmt::Debug for FilePermissions {
+ fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
+ match self.0 {}
+ }
+}
+
+impl FileType {
+ pub fn is_dir(&self) -> bool {
+ match self.0 {}
+ }
+
+ pub fn is_file(&self) -> bool {
+ match self.0 {}
+ }
+
+ pub fn is_symlink(&self) -> bool {
+ match self.0 {}
+ }
+}
+
+impl Clone for FileType {
+ fn clone(&self) -> FileType {
+ match self.0 {}
+ }
+}
+
+impl Copy for FileType {}
+
+impl PartialEq for FileType {
+ fn eq(&self, _other: &FileType) -> bool {
+ match self.0 {}
+ }
+}
+
+impl Eq for FileType {}
+
+impl Hash for FileType {
+ fn hash<H: Hasher>(&self, _h: &mut H) {
+ match self.0 {}
+ }
+}
+
+impl fmt::Debug for FileType {
+ fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
+ match self.0 {}
+ }
+}
+
+impl fmt::Debug for ReadDir {
+ fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
+ match self.0 {}
+ }
+}
+
+impl Iterator for ReadDir {
+ type Item = io::Result<DirEntry>;
+
+ fn next(&mut self) -> Option<io::Result<DirEntry>> {
+ match self.0 {}
+ }
+}
+
+impl DirEntry {
+ pub fn path(&self) -> PathBuf {
+ match self.0 {}
+ }
+
+ pub fn file_name(&self) -> OsString {
+ match self.0 {}
+ }
+
+ pub fn metadata(&self) -> io::Result<FileAttr> {
+ match self.0 {}
+ }
+
+ pub fn file_type(&self) -> io::Result<FileType> {
+ match self.0 {}
+ }
+}
+
+impl OpenOptions {
+ pub fn new() -> OpenOptions {
+ OpenOptions {}
+ }
+
+ pub fn read(&mut self, _read: bool) {}
+ pub fn write(&mut self, _write: bool) {}
+ pub fn append(&mut self, _append: bool) {}
+ pub fn truncate(&mut self, _truncate: bool) {}
+ pub fn create(&mut self, _create: bool) {}
+ pub fn create_new(&mut self, _create_new: bool) {}
+}
+
+impl File {
+ pub fn open(_path: &Path, _opts: &OpenOptions) -> io::Result<File> {
+ unsupported()
+ }
+
+ pub fn file_attr(&self) -> io::Result<FileAttr> {
+ match self.0 {}
+ }
+
+ pub fn fsync(&self) -> io::Result<()> {
+ match self.0 {}
+ }
+
+ pub fn datasync(&self) -> io::Result<()> {
+ match self.0 {}
+ }
+
+ pub fn truncate(&self, _size: u64) -> io::Result<()> {
+ match self.0 {}
+ }
+
+ pub fn read(&self, _buf: &mut [u8]) -> io::Result<usize> {
+ match self.0 {}
+ }
+
+ pub fn write(&self, _buf: &[u8]) -> io::Result<usize> {
+ match self.0 {}
+ }
+
+ pub fn flush(&self) -> io::Result<()> {
+ match self.0 {}
+ }
+
+ pub fn seek(&self, _pos: SeekFrom) -> io::Result<u64> {
+ match self.0 {}
+ }
+
+ pub fn duplicate(&self) -> io::Result<File> {
+ match self.0 {}
+ }
+
+ pub fn set_permissions(&self, _perm: FilePermissions) -> io::Result<()> {
+ match self.0 {}
+ }
+
+ pub fn diverge(&self) -> ! {
+ match self.0 {}
+ }
+}
+
+impl DirBuilder {
+ pub fn new() -> DirBuilder {
+ DirBuilder {}
+ }
+
+ pub fn mkdir(&self, _p: &Path) -> io::Result<()> {
+ unsupported()
+ }
+}
+
+impl fmt::Debug for File {
+ fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
+ match self.0 {}
+ }
+}
+
+pub fn readdir(_p: &Path) -> io::Result<ReadDir> {
+ unsupported()
+}
+
+pub fn unlink(_p: &Path) -> io::Result<()> {
+ unsupported()
+}
+
+pub fn rename(_old: &Path, _new: &Path) -> io::Result<()> {
+ unsupported()
+}
+
+pub fn set_perm(_p: &Path, perm: FilePermissions) -> io::Result<()> {
+ match perm.0 {}
+}
+
+pub fn rmdir(_p: &Path) -> io::Result<()> {
+ unsupported()
+}
+
+pub fn remove_dir_all(_path: &Path) -> io::Result<()> {
+ unsupported()
+}
+
+pub fn readlink(_p: &Path) -> io::Result<PathBuf> {
+ unsupported()
+}
+
+pub fn symlink(_src: &Path, _dst: &Path) -> io::Result<()> {
+ unsupported()
+}
+
+pub fn link(_src: &Path, _dst: &Path) -> io::Result<()> {
+ unsupported()
+}
+
+pub fn stat(_p: &Path) -> io::Result<FileAttr> {
+ unsupported()
+}
+
+pub fn lstat(_p: &Path) -> io::Result<FileAttr> {
+ unsupported()
+}
+
+pub fn canonicalize(_p: &Path) -> io::Result<PathBuf> {
+ unsupported()
+}
+
+pub fn copy(_from: &Path, _to: &Path) -> io::Result<u64> {
+ unsupported()
+}
--- /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 io;
+
+pub mod args;
+pub mod env;
+pub mod fs;
+pub mod net;
+#[path = "../../unix/path.rs"]
+pub mod path;
+pub mod pipe;
+pub mod process;
+pub mod os;
+
+// This enum is used as the storage for a bunch of types which can't actually exist.
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
+pub enum Void {}
+
+pub fn unsupported<T>() -> io::Result<T> {
+ Err(io::Error::new(
+ io::ErrorKind::Other,
+ "This function is not available on CloudABI.",
+ ))
+}
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <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 fmt;
+use io;
+use net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr};
+use time::Duration;
+use sys::{unsupported, Void};
+
+pub extern crate libc as netc;
+
+pub struct TcpStream(Void);
+
+impl TcpStream {
+ pub fn connect(_: &SocketAddr) -> io::Result<TcpStream> {
+ unsupported()
+ }
+
+ pub fn connect_timeout(_: &SocketAddr, _: Duration) -> io::Result<TcpStream> {
+ unsupported()
+ }
+
+ pub fn set_read_timeout(&self, _: Option<Duration>) -> io::Result<()> {
+ match self.0 {}
+ }
+
+ pub fn set_write_timeout(&self, _: Option<Duration>) -> io::Result<()> {
+ match self.0 {}
+ }
+
+ pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
+ match self.0 {}
+ }
+
+ pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
+ match self.0 {}
+ }
+
+ pub fn peek(&self, _: &mut [u8]) -> io::Result<usize> {
+ match self.0 {}
+ }
+
+ pub fn read(&self, _: &mut [u8]) -> io::Result<usize> {
+ match self.0 {}
+ }
+
+ pub fn write(&self, _: &[u8]) -> io::Result<usize> {
+ match self.0 {}
+ }
+
+ pub fn peer_addr(&self) -> io::Result<SocketAddr> {
+ match self.0 {}
+ }
+
+ pub fn socket_addr(&self) -> io::Result<SocketAddr> {
+ match self.0 {}
+ }
+
+ pub fn shutdown(&self, _: Shutdown) -> io::Result<()> {
+ match self.0 {}
+ }
+
+ pub fn duplicate(&self) -> io::Result<TcpStream> {
+ match self.0 {}
+ }
+
+ pub fn set_nodelay(&self, _: bool) -> io::Result<()> {
+ match self.0 {}
+ }
+
+ pub fn nodelay(&self) -> io::Result<bool> {
+ match self.0 {}
+ }
+
+ pub fn set_ttl(&self, _: u32) -> io::Result<()> {
+ match self.0 {}
+ }
+
+ pub fn ttl(&self) -> io::Result<u32> {
+ match self.0 {}
+ }
+
+ pub fn take_error(&self) -> io::Result<Option<io::Error>> {
+ match self.0 {}
+ }
+
+ pub fn set_nonblocking(&self, _: bool) -> io::Result<()> {
+ match self.0 {}
+ }
+}
+
+impl fmt::Debug for TcpStream {
+ fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
+ match self.0 {}
+ }
+}
+
+pub struct TcpListener(Void);
+
+impl TcpListener {
+ pub fn bind(_: &SocketAddr) -> io::Result<TcpListener> {
+ unsupported()
+ }
+
+ pub fn socket_addr(&self) -> io::Result<SocketAddr> {
+ match self.0 {}
+ }
+
+ pub fn accept(&self) -> io::Result<(TcpStream, SocketAddr)> {
+ match self.0 {}
+ }
+
+ pub fn duplicate(&self) -> io::Result<TcpListener> {
+ match self.0 {}
+ }
+
+ pub fn set_ttl(&self, _: u32) -> io::Result<()> {
+ match self.0 {}
+ }
+
+ pub fn ttl(&self) -> io::Result<u32> {
+ match self.0 {}
+ }
+
+ pub fn set_only_v6(&self, _: bool) -> io::Result<()> {
+ match self.0 {}
+ }
+
+ pub fn only_v6(&self) -> io::Result<bool> {
+ match self.0 {}
+ }
+
+ pub fn take_error(&self) -> io::Result<Option<io::Error>> {
+ match self.0 {}
+ }
+
+ pub fn set_nonblocking(&self, _: bool) -> io::Result<()> {
+ match self.0 {}
+ }
+}
+
+impl fmt::Debug for TcpListener {
+ fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
+ match self.0 {}
+ }
+}
+
+pub struct UdpSocket(Void);
+
+impl UdpSocket {
+ pub fn bind(_: &SocketAddr) -> io::Result<UdpSocket> {
+ unsupported()
+ }
+
+ pub fn socket_addr(&self) -> io::Result<SocketAddr> {
+ match self.0 {}
+ }
+
+ pub fn recv_from(&self, _: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
+ match self.0 {}
+ }
+
+ pub fn peek_from(&self, _: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
+ match self.0 {}
+ }
+
+ pub fn send_to(&self, _: &[u8], _: &SocketAddr) -> io::Result<usize> {
+ match self.0 {}
+ }
+
+ pub fn duplicate(&self) -> io::Result<UdpSocket> {
+ match self.0 {}
+ }
+
+ pub fn set_read_timeout(&self, _: Option<Duration>) -> io::Result<()> {
+ match self.0 {}
+ }
+
+ pub fn set_write_timeout(&self, _: Option<Duration>) -> io::Result<()> {
+ match self.0 {}
+ }
+
+ pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
+ match self.0 {}
+ }
+
+ pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
+ match self.0 {}
+ }
+
+ pub fn set_broadcast(&self, _: bool) -> io::Result<()> {
+ match self.0 {}
+ }
+
+ pub fn broadcast(&self) -> io::Result<bool> {
+ match self.0 {}
+ }
+
+ pub fn set_multicast_loop_v4(&self, _: bool) -> io::Result<()> {
+ match self.0 {}
+ }
+
+ pub fn multicast_loop_v4(&self) -> io::Result<bool> {
+ match self.0 {}
+ }
+
+ pub fn set_multicast_ttl_v4(&self, _: u32) -> io::Result<()> {
+ match self.0 {}
+ }
+
+ pub fn multicast_ttl_v4(&self) -> io::Result<u32> {
+ match self.0 {}
+ }
+
+ pub fn set_multicast_loop_v6(&self, _: bool) -> io::Result<()> {
+ match self.0 {}
+ }
+
+ pub fn multicast_loop_v6(&self) -> io::Result<bool> {
+ match self.0 {}
+ }
+
+ pub fn join_multicast_v4(&self, _: &Ipv4Addr, _: &Ipv4Addr) -> io::Result<()> {
+ match self.0 {}
+ }
+
+ pub fn join_multicast_v6(&self, _: &Ipv6Addr, _: u32) -> io::Result<()> {
+ match self.0 {}
+ }
+
+ pub fn leave_multicast_v4(&self, _: &Ipv4Addr, _: &Ipv4Addr) -> io::Result<()> {
+ match self.0 {}
+ }
+
+ pub fn leave_multicast_v6(&self, _: &Ipv6Addr, _: u32) -> io::Result<()> {
+ match self.0 {}
+ }
+
+ pub fn set_ttl(&self, _: u32) -> io::Result<()> {
+ match self.0 {}
+ }
+
+ pub fn ttl(&self) -> io::Result<u32> {
+ match self.0 {}
+ }
+
+ pub fn take_error(&self) -> io::Result<Option<io::Error>> {
+ match self.0 {}
+ }
+
+ pub fn set_nonblocking(&self, _: bool) -> io::Result<()> {
+ match self.0 {}
+ }
+
+ pub fn recv(&self, _: &mut [u8]) -> io::Result<usize> {
+ match self.0 {}
+ }
+
+ pub fn peek(&self, _: &mut [u8]) -> io::Result<usize> {
+ match self.0 {}
+ }
+
+ pub fn send(&self, _: &[u8]) -> io::Result<usize> {
+ match self.0 {}
+ }
+
+ pub fn connect(&self, _: &SocketAddr) -> io::Result<()> {
+ match self.0 {}
+ }
+}
+
+impl fmt::Debug for UdpSocket {
+ fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
+ match self.0 {}
+ }
+}
+
+pub struct LookupHost(Void);
+
+impl Iterator for LookupHost {
+ type Item = SocketAddr;
+ fn next(&mut self) -> Option<SocketAddr> {
+ match self.0 {}
+ }
+}
+
+pub fn lookup_host(_: &str) -> io::Result<LookupHost> {
+ unsupported()
+}
--- /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 error::Error as StdError;
+use ffi::{OsStr, OsString};
+use fmt;
+use io;
+use iter;
+use path::{self, PathBuf};
+use sys::{unsupported, Void};
+
+pub fn getcwd() -> io::Result<PathBuf> {
+ unsupported()
+}
+
+pub fn chdir(_: &path::Path) -> io::Result<()> {
+ unsupported()
+}
+
+pub type Env = iter::Empty<(OsString, OsString)>;
+
+pub fn env() -> Env {
+ iter::empty()
+}
+
+pub fn getenv(_: &OsStr) -> io::Result<Option<OsString>> {
+ Ok(None)
+}
+
+pub fn setenv(_: &OsStr, _: &OsStr) -> io::Result<()> {
+ unsupported()
+}
+
+pub fn unsetenv(_: &OsStr) -> io::Result<()> {
+ unsupported()
+}
+
+pub struct SplitPaths<'a>(&'a Void);
+
+pub fn split_paths(_unparsed: &OsStr) -> SplitPaths {
+ panic!("unsupported")
+}
+
+impl<'a> Iterator for SplitPaths<'a> {
+ type Item = PathBuf;
+ fn next(&mut self) -> Option<PathBuf> {
+ match *self.0 {}
+ }
+}
+
+#[derive(Debug)]
+pub struct JoinPathsError;
+
+pub fn join_paths<I, T>(_paths: I) -> Result<OsString, JoinPathsError>
+where
+ I: Iterator<Item = T>,
+ T: AsRef<OsStr>,
+{
+ Err(JoinPathsError)
+}
+
+impl fmt::Display for JoinPathsError {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ "not supported on CloudABI yet".fmt(f)
+ }
+}
+
+impl StdError for JoinPathsError {
+ fn description(&self) -> &str {
+ "not supported on CloudABI yet"
+ }
+}
+
+pub fn home_dir() -> Option<PathBuf> {
+ None
+}
+
+pub fn temp_dir() -> PathBuf {
+ PathBuf::from("/tmp")
+}
+
+pub fn current_exe() -> io::Result<PathBuf> {
+ unsupported()
+}
+
+pub fn getpid() -> u32 {
+ 1
+}
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <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 io;
+use sys::Void;
+
+pub struct AnonPipe(Void);
+
+impl AnonPipe {
+ pub fn read(&self, _buf: &mut [u8]) -> io::Result<usize> {
+ match self.0 {}
+ }
+
+ pub fn write(&self, _buf: &[u8]) -> io::Result<usize> {
+ match self.0 {}
+ }
+
+ pub fn diverge(&self) -> ! {
+ match self.0 {}
+ }
+}
+
+pub fn read2(p1: AnonPipe, _v1: &mut Vec<u8>, _p2: AnonPipe, _v2: &mut Vec<u8>) -> io::Result<()> {
+ match p1.0 {}
+}
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <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 ffi::OsStr;
+use fmt;
+use io;
+use sys::fs::File;
+use sys::pipe::AnonPipe;
+use sys::{unsupported, Void};
+use sys_common::process::{CommandEnv, DefaultEnvKey};
+
+////////////////////////////////////////////////////////////////////////////////
+// Command
+////////////////////////////////////////////////////////////////////////////////
+
+pub struct Command {
+ env: CommandEnv<DefaultEnvKey>,
+}
+
+// passed back to std::process with the pipes connected to the child, if any
+// were requested
+pub struct StdioPipes {
+ pub stdin: Option<AnonPipe>,
+ pub stdout: Option<AnonPipe>,
+ pub stderr: Option<AnonPipe>,
+}
+
+pub enum Stdio {
+ Inherit,
+ Null,
+ MakePipe,
+}
+
+impl Command {
+ pub fn new(_program: &OsStr) -> Command {
+ Command {
+ env: Default::default(),
+ }
+ }
+
+ pub fn arg(&mut self, _arg: &OsStr) {}
+
+ pub fn env_mut(&mut self) -> &mut CommandEnv<DefaultEnvKey> {
+ &mut self.env
+ }
+
+ pub fn cwd(&mut self, _dir: &OsStr) {}
+
+ pub fn stdin(&mut self, _stdin: Stdio) {}
+
+ pub fn stdout(&mut self, _stdout: Stdio) {}
+
+ pub fn stderr(&mut self, _stderr: Stdio) {}
+
+ pub fn spawn(
+ &mut self,
+ _default: Stdio,
+ _needs_stdin: bool,
+ ) -> io::Result<(Process, StdioPipes)> {
+ unsupported()
+ }
+}
+
+impl From<AnonPipe> for Stdio {
+ fn from(pipe: AnonPipe) -> Stdio {
+ pipe.diverge()
+ }
+}
+
+impl From<File> for Stdio {
+ fn from(file: File) -> Stdio {
+ file.diverge()
+ }
+}
+
+impl fmt::Debug for Command {
+ fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
+ Ok(())
+ }
+}
+
+pub struct ExitStatus(Void);
+
+impl ExitStatus {
+ pub fn success(&self) -> bool {
+ match self.0 {}
+ }
+
+ pub fn code(&self) -> Option<i32> {
+ match self.0 {}
+ }
+}
+
+impl Clone for ExitStatus {
+ fn clone(&self) -> ExitStatus {
+ match self.0 {}
+ }
+}
+
+impl Copy for ExitStatus {}
+
+impl PartialEq for ExitStatus {
+ fn eq(&self, _other: &ExitStatus) -> bool {
+ match self.0 {}
+ }
+}
+
+impl Eq for ExitStatus {}
+
+impl fmt::Debug for ExitStatus {
+ fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
+ match self.0 {}
+ }
+}
+
+impl fmt::Display for ExitStatus {
+ fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
+ match self.0 {}
+ }
+}
+
+pub struct Process(Void);
+
+impl Process {
+ pub fn id(&self) -> u32 {
+ match self.0 {}
+ }
+
+ pub fn kill(&mut self) -> io::Result<()> {
+ match self.0 {}
+ }
+
+ pub fn wait(&mut self) -> io::Result<ExitStatus> {
+ match self.0 {}
+ }
+
+ pub fn try_wait(&mut self) -> io::Result<Option<ExitStatus>> {
+ match self.0 {}
+ }
+}
--- /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.
+
+#![cfg_attr(test, allow(dead_code))]
+
+pub struct Handler;
+
+impl Handler {
+ pub unsafe fn new() -> Handler {
+ Handler
+ }
+}
+
+pub unsafe fn init() {}
+
+pub unsafe fn cleanup() {}
--- /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 io;
+use sys::cloudabi::abi;
+
+pub struct Stdin(());
+pub struct Stdout(());
+pub struct Stderr(());
+
+impl Stdin {
+ pub fn new() -> io::Result<Stdin> {
+ Ok(Stdin(()))
+ }
+
+ pub fn read(&self, _: &mut [u8]) -> io::Result<usize> {
+ Ok(0)
+ }
+}
+
+impl Stdout {
+ pub fn new() -> io::Result<Stdout> {
+ Ok(Stdout(()))
+ }
+
+ pub fn write(&self, _: &[u8]) -> io::Result<usize> {
+ Err(io::Error::new(
+ io::ErrorKind::BrokenPipe,
+ "Stdout is not connected to any output in this environment",
+ ))
+ }
+
+ pub fn flush(&self) -> io::Result<()> {
+ Ok(())
+ }
+}
+
+impl Stderr {
+ pub fn new() -> io::Result<Stderr> {
+ Ok(Stderr(()))
+ }
+
+ pub fn write(&self, _: &[u8]) -> io::Result<usize> {
+ Err(io::Error::new(
+ io::ErrorKind::BrokenPipe,
+ "Stderr is not connected to any output in this environment",
+ ))
+ }
+
+ pub fn flush(&self) -> io::Result<()> {
+ Ok(())
+ }
+}
+
+// FIXME: right now this raw stderr handle is used in a few places because
+// std::io::stderr_raw isn't exposed, but once that's exposed this impl
+// should go away
+impl io::Write for Stderr {
+ fn write(&mut self, data: &[u8]) -> io::Result<usize> {
+ Stderr::write(self, data)
+ }
+
+ fn flush(&mut self) -> io::Result<()> {
+ Stderr::flush(self)
+ }
+}
+
+pub fn is_ebadf(err: &io::Error) -> bool {
+ err.raw_os_error() == Some(abi::errno::BADF as i32)
+}
+
+pub const STDIN_BUF_SIZE: usize = ::sys_common::io::DEFAULT_BUF_SIZE;
--- /dev/null
+// Copyright 2014-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 alloc::boxed::FnBox;
+use cmp;
+use ffi::CStr;
+use io;
+use libc;
+use mem;
+use ptr;
+use sys::cloudabi::abi;
+use sys::time::dur2intervals;
+use sys_common::thread::*;
+use time::Duration;
+
+pub const DEFAULT_MIN_STACK_SIZE: usize = 2 * 1024 * 1024;
+
+pub struct Thread {
+ id: libc::pthread_t,
+}
+
+// CloudABI has pthread_t as a pointer in which case we still want
+// a thread to be Send/Sync
+unsafe impl Send for Thread {}
+unsafe impl Sync for Thread {}
+
+impl Thread {
+ pub unsafe fn new<'a>(stack: usize, p: Box<FnBox() + 'a>) -> io::Result<Thread> {
+ let p = box p;
+ let mut native: libc::pthread_t = mem::zeroed();
+ let mut attr: libc::pthread_attr_t = mem::zeroed();
+ assert_eq!(libc::pthread_attr_init(&mut attr), 0);
+
+ let stack_size = cmp::max(stack, min_stack_size(&attr));
+ assert_eq!(libc::pthread_attr_setstacksize(&mut attr, stack_size), 0);
+
+ let ret = libc::pthread_create(&mut native, &attr, thread_start, &*p as *const _ as *mut _);
+ assert_eq!(libc::pthread_attr_destroy(&mut attr), 0);
+
+ return if ret != 0 {
+ Err(io::Error::from_raw_os_error(ret))
+ } else {
+ mem::forget(p); // ownership passed to pthread_create
+ Ok(Thread { id: native })
+ };
+
+ extern "C" fn thread_start(main: *mut libc::c_void) -> *mut libc::c_void {
+ unsafe {
+ start_thread(main as *mut u8);
+ }
+ ptr::null_mut()
+ }
+ }
+
+ pub fn yield_now() {
+ let ret = unsafe { abi::thread_yield() };
+ debug_assert_eq!(ret, abi::errno::SUCCESS);
+ }
+
+ pub fn set_name(_name: &CStr) {
+ // CloudABI has no way to set a thread name.
+ }
+
+ pub fn sleep(dur: Duration) {
+ unsafe {
+ let subscription = abi::subscription {
+ type_: abi::eventtype::CLOCK,
+ union: abi::subscription_union {
+ clock: abi::subscription_clock {
+ clock_id: abi::clockid::MONOTONIC,
+ timeout: dur2intervals(&dur),
+ ..mem::zeroed()
+ },
+ },
+ ..mem::zeroed()
+ };
+ let mut event: abi::event = mem::uninitialized();
+ let mut nevents: usize = mem::uninitialized();
+ let ret = abi::poll(&subscription, &mut event, 1, &mut nevents);
+ assert_eq!(ret, abi::errno::SUCCESS);
+ assert_eq!(event.error, abi::errno::SUCCESS);
+ }
+ }
+
+ pub fn join(self) {
+ unsafe {
+ let ret = libc::pthread_join(self.id, ptr::null_mut());
+ mem::forget(self);
+ assert!(
+ ret == 0,
+ "failed to join thread: {}",
+ io::Error::from_raw_os_error(ret)
+ );
+ }
+ }
+}
+
+impl Drop for Thread {
+ fn drop(&mut self) {
+ let ret = unsafe { libc::pthread_detach(self.id) };
+ debug_assert_eq!(ret, 0);
+ }
+}
+
+#[cfg_attr(test, allow(dead_code))]
+pub mod guard {
+ pub unsafe fn current() -> Option<usize> {
+ None
+ }
+ pub unsafe fn init() -> Option<usize> {
+ None
+ }
+}
+
+fn min_stack_size(_: *const libc::pthread_attr_t) -> usize {
+ libc::PTHREAD_STACK_MIN
+}
--- /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 mem;
+use sys::cloudabi::abi;
+use time::Duration;
+
+const NSEC_PER_SEC: abi::timestamp = 1_000_000_000;
+
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
+pub struct Instant {
+ t: abi::timestamp,
+}
+
+pub fn dur2intervals(dur: &Duration) -> abi::timestamp {
+ dur.as_secs()
+ .checked_mul(NSEC_PER_SEC)
+ .and_then(|nanos| nanos.checked_add(dur.subsec_nanos() as abi::timestamp))
+ .expect("overflow converting duration to nanoseconds")
+}
+
+impl Instant {
+ pub fn now() -> Instant {
+ unsafe {
+ let mut t = mem::uninitialized();
+ let ret = abi::clock_time_get(abi::clockid::MONOTONIC, 0, &mut t);
+ assert_eq!(ret, abi::errno::SUCCESS);
+ Instant { t: t }
+ }
+ }
+
+ pub fn sub_instant(&self, other: &Instant) -> Duration {
+ let diff = self.t
+ .checked_sub(other.t)
+ .expect("second instant is later than self");
+ Duration::new(diff / NSEC_PER_SEC, (diff % NSEC_PER_SEC) as u32)
+ }
+
+ pub fn add_duration(&self, other: &Duration) -> Instant {
+ Instant {
+ t: self.t
+ .checked_add(dur2intervals(other))
+ .expect("overflow when adding duration to instant"),
+ }
+ }
+
+ pub fn sub_duration(&self, other: &Duration) -> Instant {
+ Instant {
+ t: self.t
+ .checked_sub(dur2intervals(other))
+ .expect("overflow when subtracting duration from instant"),
+ }
+ }
+}
+
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
+pub struct SystemTime {
+ t: abi::timestamp,
+}
+
+impl SystemTime {
+ pub fn now() -> SystemTime {
+ unsafe {
+ let mut t = mem::uninitialized();
+ let ret = abi::clock_time_get(abi::clockid::REALTIME, 0, &mut t);
+ assert_eq!(ret, abi::errno::SUCCESS);
+ SystemTime { t: t }
+ }
+ }
+
+ pub fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> {
+ if self.t >= other.t {
+ let diff = self.t - other.t;
+ Ok(Duration::new(
+ diff / NSEC_PER_SEC,
+ (diff % NSEC_PER_SEC) as u32,
+ ))
+ } else {
+ let diff = other.t - self.t;
+ Err(Duration::new(
+ diff / NSEC_PER_SEC,
+ (diff % NSEC_PER_SEC) as u32,
+ ))
+ }
+ }
+
+ pub fn add_duration(&self, other: &Duration) -> SystemTime {
+ SystemTime {
+ t: self.t
+ .checked_add(dur2intervals(other))
+ .expect("overflow when adding duration to instant"),
+ }
+ }
+
+ pub fn sub_duration(&self, other: &Duration) -> SystemTime {
+ SystemTime {
+ t: self.t
+ .checked_sub(dur2intervals(other))
+ .expect("overflow when subtracting duration from instant"),
+ }
+ }
+}
+
+pub const UNIX_EPOCH: SystemTime = SystemTime { t: 0 };
} else if #[cfg(windows)] {
mod windows;
pub use self::windows::*;
+ } else if #[cfg(target_os = "cloudabi")] {
+ mod cloudabi;
+ pub use self::cloudabi::*;
} else if #[cfg(target_os = "redox")] {
mod redox;
pub use self::redox::*;
if #[cfg(any(unix, target_os = "redox"))] {
// On unix we'll document what's already available
pub use self::ext as unix_ext;
- } else if #[cfg(target_arch = "wasm32")] {
- // On wasm right now the module below doesn't compile (missing things
- // in `libc` which is empty) so just omit everything with an empty module
+ } else if #[cfg(any(target_os = "cloudabi", target_arch = "wasm32"))] {
+ // On CloudABI and wasm right now the module below doesn't compile
+ // (missing things in `libc` which is empty) so just omit everything
+ // with an empty module
#[unstable(issue = "0", feature = "std_internals")]
pub mod unix_ext {}
} else {
if #[cfg(windows)] {
// On windows we'll just be documenting what's already available
pub use self::ext as windows_ext;
- } else if #[cfg(target_arch = "wasm32")] {
- // On wasm right now the shim below doesn't compile, so just omit it
+ } else if #[cfg(any(target_os = "cloudabi", target_arch = "wasm32"))] {
+ // On CloudABI and wasm right now the shim below doesn't compile, so
+ // just omit it
#[unstable(issue = "0", feature = "std_internals")]
pub mod windows_ext {}
} else {
target_os = "fuchsia"))]
mod imp {
use os::unix::prelude::*;
- use mem;
+ use ptr;
use ffi::{CStr, OsString};
use marker::PhantomData;
use libc;
use sys_common::mutex::Mutex;
- static mut GLOBAL_ARGS_PTR: usize = 0;
+ static mut ARGC: isize = 0;
+ static mut ARGV: *const *const u8 = ptr::null();
static LOCK: Mutex = Mutex::new();
pub unsafe fn init(argc: isize, argv: *const *const u8) {
- let args = (0..argc).map(|i| {
- CStr::from_ptr(*argv.offset(i) as *const libc::c_char).to_bytes().to_vec()
- }).collect();
-
LOCK.lock();
- let ptr = get_global_ptr();
- assert!((*ptr).is_none());
- (*ptr) = Some(box args);
+ ARGC = argc;
+ ARGV = argv;
LOCK.unlock();
}
pub unsafe fn cleanup() {
LOCK.lock();
- *get_global_ptr() = None;
+ ARGC = 0;
+ ARGV = ptr::null();
LOCK.unlock();
}
pub fn args() -> Args {
- let bytes = clone().unwrap_or(Vec::new());
- let v: Vec<OsString> = bytes.into_iter().map(|v| {
- OsStringExt::from_vec(v)
- }).collect();
- Args { iter: v.into_iter(), _dont_send_or_sync_me: PhantomData }
+ Args {
+ iter: clone().into_iter(),
+ _dont_send_or_sync_me: PhantomData
+ }
}
- fn clone() -> Option<Vec<Vec<u8>>> {
+ fn clone() -> Vec<OsString> {
unsafe {
LOCK.lock();
- let ptr = get_global_ptr();
- let ret = (*ptr).as_ref().map(|s| (**s).clone());
+ let ret = (0..ARGC).map(|i| {
+ let cstr = CStr::from_ptr(*ARGV.offset(i) as *const libc::c_char);
+ OsStringExt::from_vec(cstr.to_bytes().to_vec())
+ }).collect();
LOCK.unlock();
return ret
}
}
-
- fn get_global_ptr() -> *mut Option<Box<Vec<Vec<u8>>>> {
- unsafe { mem::transmute(&GLOBAL_ARGS_PTR) }
- }
-
}
#[cfg(any(target_os = "macos",
#[cfg(target_os = "macos")]
pub unsafe fn current() -> Option<usize> {
- Some((libc::pthread_get_stackaddr_np(libc::pthread_self()) as usize -
- libc::pthread_get_stacksize_np(libc::pthread_self())))
+ Some(libc::pthread_get_stackaddr_np(libc::pthread_self()) as usize -
+ libc::pthread_get_stacksize_np(libc::pthread_self()))
}
#[cfg(any(target_os = "openbsd", target_os = "bitrig"))]
const DEBUG: bool = false;
pub mod args;
+#[cfg(feature = "backtrace")]
pub mod backtrace;
pub mod cmath;
pub mod condvar;
use libc::{wchar_t, size_t, c_void};
use ptr;
-#[repr(simd)]
-#[repr(C)]
-#[cfg(target_arch = "x86_64")]
-struct u64x2(u64, u64);
-
pub use self::FILE_INFO_BY_HANDLE_CLASS::*;
pub use self::EXCEPTION_DISPOSITION::*;
}
#[cfg(target_arch = "x86_64")]
-#[repr(C)]
+#[repr(C, align(16))]
pub struct CONTEXT {
- _align_hack: [u64x2; 0], // FIXME align on 16-byte
pub P1Home: DWORDLONG,
pub P2Home: DWORDLONG,
pub P3Home: DWORDLONG,
}
#[cfg(target_arch = "x86_64")]
-#[repr(C)]
+#[repr(C, align(16))]
pub struct M128A {
- _align_hack: [u64x2; 0], // FIXME align on 16-byte
pub Low: c_ulonglong,
pub High: c_longlong
}
#[cfg(target_arch = "x86_64")]
-#[repr(C)]
+#[repr(C, align(16))]
pub struct FLOATING_SAVE_AREA {
- _align_hack: [u64x2; 0], // FIXME align on 16-byte
_Dummy: [u8; 512] // FIXME: Fill this out
}
pub mod process;
cfg_if! {
- if #[cfg(any(target_os = "redox", target_os = "l4re"))] {
+ if #[cfg(any(target_os = "cloudabi", target_os = "l4re", target_os = "redox"))] {
pub use sys::net;
} else if #[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))] {
pub use sys::net;
///
/// The default implementations are returning `libc::EXIT_SUCCESS` to indicate
/// a successful execution. In case of a failure, `libc::EXIT_FAILURE` is returned.
-#[cfg_attr(not(any(stage0, test)), lang = "termination")]
+#[cfg_attr(not(test), lang = "termination")]
#[unstable(feature = "termination_trait", issue = "43301")]
#[rustc_on_unimplemented =
"`main` can only return types that implement {Termination}, not `{Self}`"]
///
/// let duration = Duration::from_millis(5432);
/// assert_eq!(duration.as_secs(), 5);
- /// assert_eq!(duration.subsec_nanos(), 432_000_000);
+ /// assert_eq!(duration.subsec_millis(), 432);
/// ```
#[unstable(feature = "duration_extras", issue = "46507")]
#[inline]
///
/// let duration = Duration::from_micros(1_234_567);
/// assert_eq!(duration.as_secs(), 1);
- /// assert_eq!(duration.subsec_nanos(), 234_567_000);
+ /// assert_eq!(duration.subsec_micros(), 234_567);
/// ```
#[unstable(feature = "duration_extras", issue = "46507")]
#[inline]
use core::fmt::{self, Write};
use tables::{conversions, derived_property, general_category, property};
-// stable reexports
+// stable re-exports
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::char::{MAX, from_digit, from_u32, from_u32_unchecked};
#[stable(feature = "rust1", since = "1.0.0")]
#[stable(feature = "char_from_str", since = "1.20.0")]
pub use core::char::ParseCharError;
-// unstable reexports
+// unstable re-exports
#[unstable(feature = "try_from", issue = "33417")]
pub use core::char::CharTryFromError;
#[unstable(feature = "decode_utf8", issue = "33906")]
[dependencies]
bitflags = "1.0"
serialize = { path = "../libserialize" }
-log = "0.3"
+log = "0.4"
syntax_pos = { path = "../libsyntax_pos" }
rustc_cratesio_shim = { path = "../librustc_cratesio_shim" }
rustc_errors = { path = "../librustc_errors" }
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Copy,
PartialOrd, Ord)]
pub enum IntTy {
- Is,
+ Isize,
I8,
I16,
I32,
impl IntTy {
pub fn ty_to_string(&self) -> &'static str {
match *self {
- IntTy::Is => "isize",
+ IntTy::Isize => "isize",
IntTy::I8 => "i8",
IntTy::I16 => "i16",
IntTy::I32 => "i32",
pub fn bit_width(&self) -> Option<usize> {
Some(match *self {
- IntTy::Is => return None,
+ IntTy::Isize => return None,
IntTy::I8 => 8,
IntTy::I16 => 16,
IntTy::I32 => 32,
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Copy,
PartialOrd, Ord)]
pub enum UintTy {
- Us,
+ Usize,
U8,
U16,
U32,
impl UintTy {
pub fn ty_to_string(&self) -> &'static str {
match *self {
- UintTy::Us => "usize",
+ UintTy::Usize => "usize",
UintTy::U8 => "u8",
UintTy::U16 => "u16",
UintTy::U32 => "u32",
pub fn bit_width(&self) -> Option<usize> {
Some(match *self {
- UintTy::Us => return None,
+ UintTy::Usize => return None,
UintTy::U8 => 8,
UintTy::U16 => 16,
UintTy::U32 => 32,
///
/// E.g. `trait Foo = Bar + Quux;`
TraitAlias(Generics, TyParamBounds),
- /// Auto trait implementation.
- ///
- /// E.g. `impl Trait for .. {}` or `impl<T> Trait<T> for .. {}`
- AutoImpl(Unsafety, TraitRef),
/// An implementation.
///
/// E.g. `impl<A> Foo<A> { .. }` or `impl<A> Trait for Foo<A> { .. }`
ItemKind::TraitAlias(..) => "trait alias",
ItemKind::Mac(..) |
ItemKind::MacroDef(..) |
- ItemKind::Impl(..) |
- ItemKind::AutoImpl(..) => "item"
+ ItemKind::Impl(..) => "item"
}
}
}
if let Some(mi) = item.word() {
let word = &*mi.name().as_str();
let hint = match word {
- // Can't use "extern" because it's not a lexical identifier.
- "C" => Some(ReprExtern),
+ "C" => Some(ReprC),
"packed" => Some(ReprPacked),
"simd" => Some(ReprSimd),
_ => match int_type_of_word(word) {
"u64" => Some(UnsignedInt(ast::UintTy::U64)),
"i128" => Some(SignedInt(ast::IntTy::I128)),
"u128" => Some(UnsignedInt(ast::UintTy::U128)),
- "isize" => Some(SignedInt(ast::IntTy::Is)),
- "usize" => Some(UnsignedInt(ast::UintTy::Us)),
+ "isize" => Some(SignedInt(ast::IntTy::Isize)),
+ "usize" => Some(UnsignedInt(ast::UintTy::Usize)),
_ => None
}
}
#[derive(PartialEq, Debug, RustcEncodable, RustcDecodable, Copy, Clone)]
pub enum ReprAttr {
ReprInt(IntType),
- ReprExtern,
+ ReprC,
ReprPacked,
ReprSimd,
ReprAlign(u32),
// -Zremap-path-prefix to all FileMaps allocated within this CodeMap.
path_mapping: FilePathMapping,
stable_id_to_filemap: RefCell<FxHashMap<StableFilemapId, Rc<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 {
file_loader: Box::new(RealFileLoader),
path_mapping,
stable_id_to_filemap: RefCell::new(FxHashMap()),
+ doctest_offset: None,
}
}
+ pub fn new_doctest(path_mapping: FilePathMapping,
+ file: FileName, line: isize) -> CodeMap {
+ CodeMap {
+ doctest_offset: Some((file, line)),
+ ..CodeMap::new(path_mapping)
+ }
+
+ }
+
pub fn with_file_loader(file_loader: Box<FileLoader>,
path_mapping: FilePathMapping)
-> CodeMap {
file_loader,
path_mapping,
stable_id_to_filemap: RefCell::new(FxHashMap()),
+ doctest_offset: None,
}
}
pub fn load_file(&self, path: &Path) -> io::Result<Rc<FileMap>> {
let src = self.file_loader.read_file(path)?;
- Ok(self.new_filemap(path.to_owned().into(), src))
+ let filename = if let Some((ref name, _)) = self.doctest_offset {
+ name.clone()
+ } else {
+ path.to_owned().into()
+ };
+ Ok(self.new_filemap(filename, src))
}
pub fn files(&self) -> Ref<Vec<Rc<FileMap>>> {
pos.col.to_usize() + 1)).to_string()
}
+ // If there is a doctest_offset, apply it to the line
+ pub fn doctest_offset_line(&self, mut orig: usize) -> usize {
+ if let Some((_, line)) = self.doctest_offset {
+ if line >= 0 {
+ orig = orig + line as usize;
+ } else {
+ orig = orig - (-line) as usize;
+ }
+ }
+ orig
+ }
+
/// Lookup source information about a BytePos
pub fn lookup_char_pos(&self, pos: BytePos) -> Loc {
let chpos = self.bytepos_to_file_charpos(pos);
}
)
}
+ fn doctest_offset_line(&self, line: usize) -> usize {
+ self.doctest_offset_line(line)
+ }
}
#[derive(Clone)]
```
"##,
+E0658: r##"
+An unstable feature was used.
+
+Erroneous code example:
+
+```compile_fail,E658
+let x = ::std::u128::MAX; // error: use of unstable library feature 'i128'
+```
+
+If you're using a stable or a beta version of rustc, you won't be able to use
+any unstable features. In order to do so, please switch to a nightly version of
+rustc (by using rustup).
+
+If you're using a nightly version of rustc, just add the corresponding feature
+to be able to use it:
+
+```
+#![feature(i128)]
+
+fn main() {
+ let x = ::std::u128::MAX; // ok!
+}
+```
+"##,
+
}
register_diagnostics! {
})
}
+#[macro_export]
+macro_rules! stringify_error_code {
+ ($code:ident) => ({
+ __diagnostic_used!($code);
+ $crate::errors::DiagnosticId::Error(stringify!($code).to_owned())
+ })
+}
+
#[macro_export]
macro_rules! type_error_struct {
($session:expr, $span:expr, $typ:expr, $code:ident, $($message:tt)*) => ({
//! currently always a crate name.
use std::collections::BTreeMap;
-use std::path::PathBuf;
+use std::env;
use std::fs::{remove_file, create_dir_all, File};
use std::io::Write;
+use std::path::PathBuf;
use std::error::Error;
use rustc_serialize::json::as_json;
use ext::base::ExtCtxt;
use diagnostics::plugin::{ErrorMap, ErrorInfo};
-// Default metadata directory to use for extended error JSON.
-const ERROR_METADATA_PREFIX: &'static str = "tmp/extended-errors";
-
/// JSON encodable/decodable version of `ErrorInfo`.
#[derive(PartialEq, RustcDecodable, RustcEncodable)]
pub struct ErrorMetadata {
///
/// See `output_metadata`.
pub fn get_metadata_dir(prefix: &str) -> PathBuf {
- PathBuf::from(ERROR_METADATA_PREFIX).join(prefix)
+ env::var_os("RUSTC_ERROR_METADATA_DST")
+ .map(PathBuf::from)
+ .expect("env var `RUSTC_ERROR_METADATA_DST` isn't set")
+ .join(prefix)
}
/// Map `name` to a path in the given directory: <directory>/<name>.json
use ast::{self, Attribute, Name, PatKind, MetaItem};
use attr::HasAttrs;
use codemap::{self, CodeMap, Spanned, respan};
-use syntax_pos::{Span, DUMMY_SP};
+use syntax_pos::{Span, MultiSpan, DUMMY_SP};
use errors::DiagnosticBuilder;
use ext::expand::{self, Expansion, Invocation};
use ext::hygiene::{Mark, SyntaxContext};
last_macro
}
- pub fn struct_span_warn(&self,
- sp: Span,
- msg: &str)
- -> DiagnosticBuilder<'a> {
+ pub fn struct_span_warn<S: Into<MultiSpan>>(&self,
+ sp: S,
+ msg: &str)
+ -> DiagnosticBuilder<'a> {
self.parse_sess.span_diagnostic.struct_span_warn(sp, msg)
}
- pub fn struct_span_err(&self,
- sp: Span,
- msg: &str)
- -> DiagnosticBuilder<'a> {
+ pub fn struct_span_err<S: Into<MultiSpan>>(&self,
+ sp: S,
+ msg: &str)
+ -> DiagnosticBuilder<'a> {
self.parse_sess.span_diagnostic.struct_span_err(sp, msg)
}
- pub fn struct_span_fatal(&self,
- sp: Span,
- msg: &str)
- -> DiagnosticBuilder<'a> {
+ pub fn struct_span_fatal<S: Into<MultiSpan>>(&self,
+ sp: S,
+ msg: &str)
+ -> DiagnosticBuilder<'a> {
self.parse_sess.span_diagnostic.struct_span_fatal(sp, msg)
}
/// in most cases one can construct a dummy expression/item to
/// substitute; we never hit resolve/type-checking so the dummy
/// value doesn't have to match anything)
- pub fn span_fatal(&self, sp: Span, msg: &str) -> ! {
+ pub fn span_fatal<S: Into<MultiSpan>>(&self, sp: S, msg: &str) -> ! {
panic!(self.parse_sess.span_diagnostic.span_fatal(sp, msg));
}
///
/// Compilation will be stopped in the near future (at the end of
/// the macro expansion phase).
- pub fn span_err(&self, sp: Span, msg: &str) {
+ pub fn span_err<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
self.parse_sess.span_diagnostic.span_err(sp, msg);
}
- pub fn mut_span_err(&self, sp: Span, msg: &str)
+ pub fn mut_span_err<S: Into<MultiSpan>>(&self, sp: S, msg: &str)
-> DiagnosticBuilder<'a> {
self.parse_sess.span_diagnostic.mut_span_err(sp, msg)
}
- pub fn span_warn(&self, sp: Span, msg: &str) {
+ pub fn span_warn<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
self.parse_sess.span_diagnostic.span_warn(sp, msg);
}
- pub fn span_unimpl(&self, sp: Span, msg: &str) -> ! {
+ pub fn span_unimpl<S: Into<MultiSpan>>(&self, sp: S, msg: &str) -> ! {
self.parse_sess.span_diagnostic.span_unimpl(sp, msg);
}
- pub fn span_bug(&self, sp: Span, msg: &str) -> ! {
+ pub fn span_bug<S: Into<MultiSpan>>(&self, sp: S, msg: &str) -> ! {
self.parse_sess.span_diagnostic.span_bug(sp, msg);
}
pub fn trace_macros_diag(&mut self) {
use ptr::P;
use symbol::{Symbol, keywords};
-// Transitional reexports so qquote can find the paths it is looking for
+// Transitional re-exports so qquote can find the paths it is looking for
mod syntax {
pub use ext;
pub use parse;
}
fn expr_usize(&self, span: Span, i: usize) -> P<ast::Expr> {
self.expr_lit(span, ast::LitKind::Int(i as u128,
- ast::LitIntType::Unsigned(ast::UintTy::Us)))
+ ast::LitIntType::Unsigned(ast::UintTy::Usize)))
}
fn expr_isize(&self, sp: Span, i: isize) -> P<ast::Expr> {
if i < 0 {
let i = (-i) as u128;
- let lit_ty = ast::LitIntType::Signed(ast::IntTy::Is);
+ let lit_ty = ast::LitIntType::Signed(ast::IntTy::Isize);
let lit = self.expr_lit(sp, ast::LitKind::Int(i, lit_ty));
self.expr_unary(sp, ast::UnOp::Neg, lit)
} else {
self.expr_lit(sp, ast::LitKind::Int(i as u128,
- ast::LitIntType::Signed(ast::IntTy::Is)))
+ ast::LitIntType::Signed(ast::IntTy::Isize)))
}
}
fn expr_u32(&self, sp: Span, u: u32) -> P<ast::Expr> {
);
}
- impl_to_tokens_int! { signed, isize, ast::IntTy::Is }
+ impl_to_tokens_int! { signed, isize, ast::IntTy::Isize }
impl_to_tokens_int! { signed, i8, ast::IntTy::I8 }
impl_to_tokens_int! { signed, i16, ast::IntTy::I16 }
impl_to_tokens_int! { signed, i32, ast::IntTy::I32 }
impl_to_tokens_int! { signed, i64, ast::IntTy::I64 }
- impl_to_tokens_int! { unsigned, usize, ast::UintTy::Us }
+ impl_to_tokens_int! { unsigned, usize, ast::UintTy::Usize }
impl_to_tokens_int! { unsigned, u8, ast::UintTy::U8 }
impl_to_tokens_int! { unsigned, u16, ast::UintTy::U16 }
impl_to_tokens_int! { unsigned, u32, ast::UintTy::U32 }
(active, link_llvm_intrinsics, "1.0.0", Some(29602)),
(active, linkage, "1.0.0", Some(29603)),
(active, quote, "1.0.0", Some(29601)),
- (active, simd, "1.0.0", Some(27731)),
// rustc internal
// OIBIT specific features
(active, optin_builtin_traits, "1.0.0", Some(13231)),
- // macro reexport needs more discussion and stabilization
+ // macro re-export needs more discussion and stabilization
(active, macro_reexport, "1.0.0", Some(29638)),
// Allows use of #[staged_api]
// Allows use of the :lifetime macro fragment specifier
(active, macro_lifetime_matcher, "1.24.0", Some(46895)),
+
+ // `extern` in paths
+ (active, extern_in_paths, "1.23.0", Some(44660)),
);
declare_features! (
(removed, unmarked_api, "1.0.0", None),
(removed, pushpop_unsafe, "1.2.0", None),
(removed, allocator, "1.0.0", None),
+ // Allows the `#[simd]` attribute -- removed in favor of `#[repr(simd)]`
+ (removed, simd, "1.0.0", Some(27731)),
);
declare_features! (
("start", Normal, Ungated),
("test", Normal, Ungated),
("bench", Normal, Ungated),
- ("simd", Normal, Ungated),
("repr", Normal, Ungated),
("path", Normal, Ungated),
("abi", Normal, Ungated),
never be stable",
cfg_fn!(rustc_attrs))),
+ // whitelists "identity-like" conversion methods to suggest on type mismatch
+ ("rustc_conversion_suggestion", Whitelisted, Gated(Stability::Unstable,
+ "rustc_attrs",
+ "this is an internal attribute that will \
+ never be stable",
+ cfg_fn!(rustc_attrs))),
+
("wasm_import_memory", Whitelisted, Gated(Stability::Unstable,
"wasm_import_memory",
"wasm_import_memory attribute is currently unstable",
};
let mut err = match level {
- GateStrength::Hard => diag.struct_span_err(span, &explanation),
+ GateStrength::Hard => {
+ diag.struct_span_err_with_code(span, &explanation, stringify_error_code!(E0658))
+ }
GateStrength::Soft => diag.struct_span_warn(span, &explanation),
};
ast::ItemKind::ExternCrate(_) => {
if let Some(attr) = attr::find_by_name(&i.attrs[..], "macro_reexport") {
gate_feature_post!(&self, macro_reexport, attr.span,
- "macros reexports are experimental \
+ "macros re-exports are experimental \
and possibly buggy");
}
}
}
ast::ItemKind::Struct(..) => {
- if let Some(attr) = attr::find_by_name(&i.attrs[..], "simd") {
- gate_feature_post!(&self, simd, attr.span,
- "SIMD types are experimental and possibly buggy");
- self.context.parse_sess.span_diagnostic.span_warn(attr.span,
- "the `#[simd]` attribute \
- is deprecated, use \
- `#[repr(simd)]` instead");
- }
if let Some(attr) = attr::find_by_name(&i.attrs[..], "repr") {
for item in attr.meta_item_list().unwrap_or_else(Vec::new) {
if item.check_name("simd") {
"trait aliases are not yet fully implemented");
}
- ast::ItemKind::AutoImpl(..) => {
- gate_feature_post!(&self, optin_builtin_traits,
- i.span,
- "auto trait implementations are experimental \
- and possibly buggy");
- }
-
ast::ItemKind::Impl(_, polarity, defaultness, _, _, _, ref impl_items) => {
if polarity == ast::ImplPolarity::Negative {
gate_feature_post!(&self, optin_builtin_traits,
if segment.identifier.name == keywords::Crate.name() {
gate_feature_post!(&self, crate_in_paths, segment.span,
"`crate` in paths is experimental");
+ } else if segment.identifier.name == keywords::Extern.name() {
+ gate_feature_post!(&self, extern_in_paths, segment.span,
+ "`extern` in paths is experimental");
}
}
let generics = folder.fold_generics(generics);
ItemKind::Union(folder.fold_variant_data(struct_def), generics)
}
- ItemKind::AutoImpl(unsafety, ref trait_ref) => {
- ItemKind::AutoImpl(unsafety, folder.fold_trait_ref((*trait_ref).clone()))
- }
ItemKind::Impl(unsafety,
polarity,
defaultness,
#[cfg(test)]
mod test_snippet;
+#[cfg(not(stage0))] // remove after the next snapshot
__build_diagnostic_array! { libsyntax, DIAGNOSTICS }
break;
}
}
- if i > line.len() {
+ if i >= line.len() {
can_trim = false;
}
if !can_trim {
err!(diag, |span, diag| diag.span_bug(span, "found empty literal suffix in Some"));
}
ty = match &*suf.as_str() {
- "isize" => ast::LitIntType::Signed(ast::IntTy::Is),
+ "isize" => ast::LitIntType::Signed(ast::IntTy::Isize),
"i8" => ast::LitIntType::Signed(ast::IntTy::I8),
"i16" => ast::LitIntType::Signed(ast::IntTy::I16),
"i32" => ast::LitIntType::Signed(ast::IntTy::I32),
"i64" => ast::LitIntType::Signed(ast::IntTy::I64),
"i128" => ast::LitIntType::Signed(ast::IntTy::I128),
- "usize" => ast::LitIntType::Unsigned(ast::UintTy::Us),
+ "usize" => ast::LitIntType::Unsigned(ast::UintTy::Usize),
"u8" => ast::LitIntType::Unsigned(ast::UintTy::U8),
"u16" => ast::LitIntType::Unsigned(ast::UintTy::U16),
"u32" => ast::LitIntType::Unsigned(ast::UintTy::U32),
use ast::{RangeEnd, RangeSyntax};
use {ast, attr};
use codemap::{self, CodeMap, Spanned, respan};
-use syntax_pos::{self, Span, BytePos, FileName, DUMMY_SP};
+use syntax_pos::{self, Span, MultiSpan, BytePos, FileName, DUMMY_SP};
use errors::{self, DiagnosticBuilder};
use parse::{self, classify, token};
use parse::common::SeqSep;
}
}
-type ItemInfo = (Ident, ItemKind, Option<Vec<Attribute> >);
+type ItemInfo = (Ident, ItemKind, Option<Vec<Attribute>>);
/// How to parse a path.
#[derive(Copy, Clone, PartialEq)]
};
}
-fn maybe_append(mut lhs: Vec<Attribute>, rhs: Option<Vec<Attribute>>)
- -> Vec<Attribute> {
- if let Some(ref attrs) = rhs {
- lhs.extend(attrs.iter().cloned())
+fn maybe_append(mut lhs: Vec<Attribute>, mut rhs: Option<Vec<Attribute>>) -> Vec<Attribute> {
+ if let Some(ref mut rhs) = rhs {
+ lhs.append(rhs);
}
lhs
}
}
impl Error {
- pub fn span_err(self, sp: Span, handler: &errors::Handler) -> DiagnosticBuilder {
+ pub fn span_err<S: Into<MultiSpan>>(self,
+ sp: S,
+ handler: &errors::Handler) -> DiagnosticBuilder {
match self {
Error::FileNotFoundForModule { ref mod_name,
ref default_path,
Parser::token_to_string(&self.token)
}
+ pub fn token_descr(&self) -> Option<&'static str> {
+ Some(match &self.token {
+ t if t.is_special_ident() => "reserved identifier",
+ t if t.is_used_keyword() => "keyword",
+ t if t.is_unused_keyword() => "reserved keyword",
+ _ => return None,
+ })
+ }
+
pub fn this_token_descr(&self) -> String {
- let prefix = match &self.token {
- t if t.is_special_ident() => "reserved identifier ",
- t if t.is_used_keyword() => "keyword ",
- t if t.is_unused_keyword() => "reserved keyword ",
- _ => "",
- };
- format!("{}`{}`", prefix, self.this_token_to_string())
+ if let Some(prefix) = self.token_descr() {
+ format!("{} `{}`", prefix, self.this_token_to_string())
+ } else {
+ format!("`{}`", self.this_token_to_string())
+ }
}
pub fn unexpected_last<T>(&self, t: &token::Token) -> PResult<'a, T> {
}
pub fn parse_ident(&mut self) -> PResult<'a, ast::Ident> {
+ self.parse_ident_common(true)
+ }
+
+ fn parse_ident_common(&mut self, recover: bool) -> PResult<'a, ast::Ident> {
match self.token {
token::Ident(i) => {
if self.token.is_reserved_ident() {
- self.span_err(self.span, &format!("expected identifier, found {}",
- self.this_token_descr()));
+ let mut err = self.struct_span_err(self.span,
+ &format!("expected identifier, found {}",
+ self.this_token_descr()));
+ if let Some(token_descr) = self.token_descr() {
+ err.span_label(self.span, format!("expected identifier, found {}",
+ token_descr));
+ } else {
+ err.span_label(self.span, "expected identifier");
+ }
+ if recover {
+ err.emit();
+ } else {
+ return Err(err);
+ }
}
self.bump();
Ok(i)
} else {
let mut err = self.fatal(&format!("expected identifier, found `{}`",
self.this_token_to_string()));
+ if let Some(token_descr) = self.token_descr() {
+ err.span_label(self.span, format!("expected identifier, found {}",
+ token_descr));
+ } else {
+ err.span_label(self.span, "expected identifier");
+ }
if self.token == token::Underscore {
err.note("`_` is a wildcard pattern, not an identifier");
}
pub fn fatal(&self, m: &str) -> DiagnosticBuilder<'a> {
self.sess.span_diagnostic.struct_span_fatal(self.span, m)
}
- pub fn span_fatal(&self, sp: Span, m: &str) -> DiagnosticBuilder<'a> {
+ pub fn span_fatal<S: Into<MultiSpan>>(&self, sp: S, m: &str) -> DiagnosticBuilder<'a> {
self.sess.span_diagnostic.struct_span_fatal(sp, m)
}
- pub fn span_fatal_err(&self, sp: Span, err: Error) -> DiagnosticBuilder<'a> {
+ pub fn span_fatal_err<S: Into<MultiSpan>>(&self, sp: S, err: Error) -> DiagnosticBuilder<'a> {
err.span_err(sp, self.diagnostic())
}
- pub fn span_fatal_help(&self, sp: Span, m: &str, help: &str) -> DiagnosticBuilder<'a> {
+ pub fn span_fatal_help<S: Into<MultiSpan>>(&self,
+ sp: S,
+ m: &str,
+ help: &str) -> DiagnosticBuilder<'a> {
let mut err = self.sess.span_diagnostic.struct_span_fatal(sp, m);
err.help(help);
err
pub fn warn(&self, m: &str) {
self.sess.span_diagnostic.span_warn(self.span, m)
}
- pub fn span_warn(&self, sp: Span, m: &str) {
+ pub fn span_warn<S: Into<MultiSpan>>(&self, sp: S, m: &str) {
self.sess.span_diagnostic.span_warn(sp, m)
}
- pub fn span_err(&self, sp: Span, m: &str) {
+ pub fn span_err<S: Into<MultiSpan>>(&self, sp: S, m: &str) {
self.sess.span_diagnostic.span_err(sp, m)
}
- pub fn struct_span_err(&self, sp: Span, m: &str) -> DiagnosticBuilder<'a> {
+ pub fn struct_span_err<S: Into<MultiSpan>>(&self, sp: S, m: &str) -> DiagnosticBuilder<'a> {
self.sess.span_diagnostic.struct_span_err(sp, m)
}
- pub fn span_err_help(&self, sp: Span, m: &str, h: &str) {
+ pub fn span_err_help<S: Into<MultiSpan>>(&self, sp: S, m: &str, h: &str) {
let mut err = self.sess.span_diagnostic.mut_span_err(sp, m);
err.help(h);
err.emit();
}
- pub fn span_bug(&self, sp: Span, m: &str) -> ! {
+ pub fn span_bug<S: Into<MultiSpan>>(&self, sp: S, m: &str) -> ! {
self.sess.span_diagnostic.span_bug(sp, m)
}
pub fn abort_if_errors(&self) {
Function Style
*/
- let unsafety = self.parse_unsafety()?;
+ let unsafety = self.parse_unsafety();
let abi = if self.eat_keyword(keywords::Extern) {
self.parse_opt_abi()?.unwrap_or(Abi::C)
} else {
})))
}
- pub fn parse_unsafety(&mut self) -> PResult<'a, Unsafety> {
+ /// Parse unsafety: `unsafe` or nothing.
+ fn parse_unsafety(&mut self) -> Unsafety {
if self.eat_keyword(keywords::Unsafe) {
- return Ok(Unsafety::Unsafe);
+ Unsafety::Unsafe
} else {
- return Ok(Unsafety::Normal);
+ Unsafety::Normal
}
}
None
};
(ident, TraitItemKind::Const(ty, default), ast::Generics::default())
- } else if self.token.is_path_start() {
+ } else if self.token.is_path_start() && !self.is_extern_non_path() {
// trait item macro.
// code copied from parse_macro_use_or_failure... abstraction!
let prev_span = self.prev_span;
self.bump();
Ok(Ident::with_empty_ctxt(name))
} else {
- self.parse_ident()
+ self.parse_ident_common(false)
}
}
hi = self.prev_span;
(fieldname, self.parse_expr()?, false)
} else {
- let fieldname = self.parse_ident()?;
+ let fieldname = self.parse_ident_common(false)?;
hi = self.prev_span;
// Mimic `x: x` for the `x` field shorthand.
fn parse_struct_expr(&mut self, lo: Span, pth: ast::Path, mut attrs: ThinVec<Attribute>)
-> PResult<'a, P<Expr>> {
+ let struct_sp = lo.to(self.prev_span);
self.bump();
let mut fields = Vec::new();
let mut base = None;
match self.parse_field() {
Ok(f) => fields.push(f),
Err(mut e) => {
+ e.span_label(struct_sp, "while parsing this struct");
e.emit();
self.recover_stmt();
break;
let mut pats = Vec::new();
loop {
pats.push(self.parse_pat()?);
- if self.check(&token::BinOp(token::Or)) { self.bump();}
- else { return Ok(pats); }
+
+ if self.token == token::OrOr {
+ let mut err = self.struct_span_err(self.span,
+ "unexpected token `||` after pattern");
+ err.span_suggestion(self.span,
+ "use a single `|` to specify multiple patterns",
+ "|".to_owned());
+ err.emit();
+ self.bump();
+ } else if self.check(&token::BinOp(token::Or)) {
+ self.bump();
+ } else {
+ return Ok(pats);
+ }
};
}
self.token.is_keyword(keywords::Crate) && self.look_ahead(1, |t| t != &token::ModSep)
}
- fn eat_auto_trait(&mut self) -> bool {
- if self.token.is_keyword(keywords::Auto)
- && self.look_ahead(1, |t| t.is_keyword(keywords::Trait))
- {
- self.eat_keyword(keywords::Auto) && self.eat_keyword(keywords::Trait)
- } else {
- false
- }
+ fn is_extern_non_path(&self) -> bool {
+ self.token.is_keyword(keywords::Extern) && self.look_ahead(1, |t| t != &token::ModSep)
}
- fn is_defaultness(&self) -> bool {
- // `pub` is included for better error messages
- self.token.is_keyword(keywords::Default) &&
- self.look_ahead(1, |t| t.is_keyword(keywords::Impl) ||
- t.is_keyword(keywords::Const) ||
- t.is_keyword(keywords::Fn) ||
- t.is_keyword(keywords::Unsafe) ||
- t.is_keyword(keywords::Extern) ||
- t.is_keyword(keywords::Type) ||
- t.is_keyword(keywords::Pub))
- }
-
- fn eat_defaultness(&mut self) -> bool {
- let is_defaultness = self.is_defaultness();
- if is_defaultness {
- self.bump()
- } else {
- self.expected_tokens.push(TokenType::Keyword(keywords::Default));
- }
- is_defaultness
+ fn is_auto_trait_item(&mut self) -> bool {
+ // auto trait
+ (self.token.is_keyword(keywords::Auto)
+ && self.look_ahead(1, |t| t.is_keyword(keywords::Trait)))
+ || // unsafe auto trait
+ (self.token.is_keyword(keywords::Unsafe) &&
+ self.look_ahead(1, |t| t.is_keyword(keywords::Auto)) &&
+ self.look_ahead(2, |t| t.is_keyword(keywords::Trait)))
}
fn eat_macro_def(&mut self, attrs: &[Attribute], vis: &Visibility, lo: Span)
node: StmtKind::Item(macro_def),
span: lo.to(self.prev_span),
}
- // Starts like a simple path, but not a union item or item with `crate` visibility.
+ // Starts like a simple path, being careful to avoid contextual keywords
+ // such as a union items, item with `crate` visibility or auto trait items.
// Our goal here is to parse an arbitrary path `a::b::c` but not something that starts
// like a path (1 token), but it fact not a path.
// `union::b::c` - path, `union U { ... }` - not a path.
// `crate::b::c` - path, `crate struct S;` - not a path.
+ // `extern::b::c` - path, `extern crate c;` - not a path.
} else if self.token.is_path_start() &&
!self.token.is_qpath_start() &&
!self.is_union_item() &&
- !self.is_crate_vis() {
+ !self.is_crate_vis() &&
+ !self.is_extern_non_path() &&
+ !self.is_auto_trait_item() {
let pth = self.parse_path(PathStyle::Expr)?;
if !self.eat(&token::Not) {
}
let lo = self.prev_span;
- // This is a temporary future proofing.
- //
// We are considering adding generics to the `where` keyword as an alternative higher-rank
// parameter syntax (as in `where<'a>` or `where<T>`. To avoid that being a breaking
- // change, for now we refuse to parse `where < (ident | lifetime) (> | , | :)`.
- if token::Lt == self.token {
- let ident_or_lifetime = self.look_ahead(1, |t| t.is_ident() || t.is_lifetime());
- if ident_or_lifetime {
- let gt_comma_or_colon = self.look_ahead(2, |t| {
- *t == token::Gt || *t == token::Comma || *t == token::Colon
- });
- if gt_comma_or_colon {
- self.span_err(self.span, "syntax `where<T>` is reserved for future use");
- }
- }
+ // change we parse those generics now, but report an error.
+ if self.choose_generics_over_qpath() {
+ let generics = self.parse_generics()?;
+ self.span_err(generics.span,
+ "generic parameters on `where` clauses are reserved for future use");
}
loop {
fn parse_item_fn(&mut self,
unsafety: Unsafety,
constness: Spanned<Constness>,
- abi: abi::Abi)
+ abi: Abi)
-> PResult<'a, ItemInfo> {
let (ident, mut generics) = self.parse_fn_header()?;
let decl = self.parse_fn_decl(false)?;
/// - `const unsafe fn`
/// - `extern fn`
/// - etc
- pub fn parse_fn_front_matter(&mut self)
- -> PResult<'a, (Spanned<ast::Constness>,
- ast::Unsafety,
- abi::Abi)> {
+ pub fn parse_fn_front_matter(&mut self) -> PResult<'a, (Spanned<Constness>, Unsafety, Abi)> {
let is_const_fn = self.eat_keyword(keywords::Const);
let const_span = self.prev_span;
- let unsafety = self.parse_unsafety()?;
+ let unsafety = self.parse_unsafety();
let (constness, unsafety, abi) = if is_const_fn {
(respan(const_span, Constness::Const), unsafety, Abi::Rust)
} else {
mut attrs: Vec<Attribute>) -> PResult<'a, ImplItem> {
let lo = self.span;
let vis = self.parse_visibility(false)?;
- let defaultness = self.parse_defaultness()?;
+ let defaultness = self.parse_defaultness();
let (name, node, generics) = if self.eat_keyword(keywords::Type) {
// This parses the grammar:
// ImplItemAssocTy = Ident ["<"...">"] ["where" ...] "=" Ty ";"
/// Parse a method or a macro invocation in a trait impl.
fn parse_impl_method(&mut self, vis: &Visibility, at_end: &mut bool)
- -> PResult<'a, (Ident, Vec<ast::Attribute>, ast::Generics,
+ -> PResult<'a, (Ident, Vec<Attribute>, ast::Generics,
ast::ImplItemKind)> {
// code copied from parse_macro_use_or_failure... abstraction!
- if self.token.is_path_start() {
+ if self.token.is_path_start() && !self.is_extern_non_path() {
// Method macro.
let prev_span = self.prev_span;
}
}
- /// Parses items implementations variants
- /// impl<T> Foo { ... }
- /// impl<T> ToString for &'static T { ... }
- /// impl Send for .. {}
- fn parse_item_impl(&mut self,
- unsafety: ast::Unsafety,
- defaultness: Defaultness) -> PResult<'a, ItemInfo> {
- let impl_span = self.span;
+ fn choose_generics_over_qpath(&self) -> bool {
+ // There's an ambiguity between generic parameters and qualified paths in impls.
+ // If we see `<` it may start both, so we have to inspect some following tokens.
+ // The following combinations can only start generics,
+ // but not qualified paths (with one exception):
+ // `<` `>` - empty generic parameters
+ // `<` `#` - generic parameters with attributes
+ // `<` (LIFETIME|IDENT) `>` - single generic parameter
+ // `<` (LIFETIME|IDENT) `,` - first generic parameter in a list
+ // `<` (LIFETIME|IDENT) `:` - generic parameter with bounds
+ // `<` (LIFETIME|IDENT) `=` - generic parameter with a default
+ // The only truly ambiguous case is
+ // `<` IDENT `>` `::` IDENT ...
+ // we disambiguate it in favor of generics (`impl<T> ::absolute::Path<T> { ... }`)
+ // because this is what almost always expected in practice, qualified paths in impls
+ // (`impl <Type>::AssocTy { ... }`) aren't even allowed by type checker at the moment.
+ self.token == token::Lt &&
+ (self.look_ahead(1, |t| t == &token::Pound || t == &token::Gt) ||
+ self.look_ahead(1, |t| t.is_lifetime() || t.is_ident()) &&
+ self.look_ahead(2, |t| t == &token::Gt || t == &token::Comma ||
+ t == &token::Colon || t == &token::Eq))
+ }
+
+ fn parse_impl_body(&mut self) -> PResult<'a, (Vec<ImplItem>, Vec<Attribute>)> {
+ self.expect(&token::OpenDelim(token::Brace))?;
+ let attrs = self.parse_inner_attributes()?;
- // First, parse type parameters if necessary.
- let mut generics = self.parse_generics()?;
+ let mut impl_items = Vec::new();
+ while !self.eat(&token::CloseDelim(token::Brace)) {
+ let mut at_end = false;
+ match self.parse_impl_item(&mut at_end) {
+ Ok(impl_item) => impl_items.push(impl_item),
+ Err(mut err) => {
+ err.emit();
+ if !at_end {
+ self.recover_stmt_(SemiColonMode::Break, BlockMode::Break);
+ }
+ }
+ }
+ }
+ Ok((impl_items, attrs))
+ }
- // Special case: if the next identifier that follows is '(', don't
- // allow this to be parsed as a trait.
- let could_be_trait = self.token != token::OpenDelim(token::Paren);
+ /// Parses an implementation item, `impl` keyword is already parsed.
+ /// impl<'a, T> TYPE { /* impl items */ }
+ /// impl<'a, T> TRAIT for TYPE { /* impl items */ }
+ /// impl<'a, T> !TRAIT for TYPE { /* impl items */ }
+ /// We actually parse slightly more relaxed grammar for better error reporting and recovery.
+ /// `impl` GENERICS `!`? TYPE `for`? (TYPE | `..`) (`where` PREDICATES)? `{` BODY `}`
+ /// `impl` GENERICS `!`? TYPE (`where` PREDICATES)? `{` BODY `}`
+ fn parse_item_impl(&mut self, unsafety: Unsafety, defaultness: Defaultness)
+ -> PResult<'a, ItemInfo> {
+ // First, parse generic parameters if necessary.
+ let mut generics = if self.choose_generics_over_qpath() {
+ self.parse_generics()?
+ } else {
+ ast::Generics::default()
+ };
- let neg_span = self.span;
- let polarity = if self.eat(&token::Not) {
+ // Disambiguate `impl !Trait for Type { ... }` and `impl ! { ... }` for the never type.
+ let polarity = if self.check(&token::Not) && self.look_ahead(1, |t| t.can_begin_type()) {
+ self.bump(); // `!`
ast::ImplPolarity::Negative
} else {
ast::ImplPolarity::Positive
};
- // Parse the trait.
- let mut ty = self.parse_ty()?;
-
- // Parse traits, if necessary.
- let opt_trait = if could_be_trait && self.eat_keyword(keywords::For) {
- // New-style trait. Reinterpret the type as a trait.
- match ty.node {
- TyKind::Path(None, ref path) => {
- Some(TraitRef {
- path: (*path).clone(),
- ref_id: ty.id,
- })
- }
- _ => {
- self.span_err(ty.span, "not a trait");
- None
- }
- }
+ // Parse both types and traits as a type, then reinterpret if necessary.
+ let ty_first = self.parse_ty()?;
+
+ // If `for` is missing we try to recover.
+ let has_for = self.eat_keyword(keywords::For);
+ let missing_for_span = self.prev_span.between(self.span);
+
+ let ty_second = if self.token == token::DotDot {
+ // We need to report this error after `cfg` expansion for compatibility reasons
+ self.bump(); // `..`, do not add it to expected tokens
+ Some(P(Ty { node: TyKind::Err, span: self.prev_span, id: ast::DUMMY_NODE_ID }))
+ } else if has_for || self.token.can_begin_type() {
+ Some(self.parse_ty()?)
} else {
- if polarity == ast::ImplPolarity::Negative {
- // This is a negated type implementation
- // `impl !MyType {}`, which is not allowed.
- self.span_err(neg_span, "inherent implementation can't be negated");
- }
None
};
- if opt_trait.is_some() && self.eat(&token::DotDot) {
- if generics.is_parameterized() {
- self.span_err(impl_span, "auto trait implementations are not \
- allowed to have generics");
- }
-
- if let ast::Defaultness::Default = defaultness {
- self.span_err(impl_span, "`default impl` is not allowed for \
- auto trait implementations");
- }
+ generics.where_clause = self.parse_where_clause()?;
- self.expect(&token::OpenDelim(token::Brace))?;
- self.expect(&token::CloseDelim(token::Brace))?;
- Ok((keywords::Invalid.ident(),
- ItemKind::AutoImpl(unsafety, opt_trait.unwrap()), None))
- } else {
- if opt_trait.is_some() {
- ty = self.parse_ty()?;
- }
- generics.where_clause = self.parse_where_clause()?;
+ let (impl_items, attrs) = self.parse_impl_body()?;
- self.expect(&token::OpenDelim(token::Brace))?;
- let attrs = self.parse_inner_attributes()?;
+ let item_kind = match ty_second {
+ Some(ty_second) => {
+ // impl Trait for Type
+ if !has_for {
+ self.span_err(missing_for_span, "missing `for` in a trait impl");
+ }
- let mut impl_items = vec![];
- while !self.eat(&token::CloseDelim(token::Brace)) {
- let mut at_end = false;
- match self.parse_impl_item(&mut at_end) {
- Ok(item) => impl_items.push(item),
- Err(mut e) => {
- e.emit();
- if !at_end {
- self.recover_stmt_(SemiColonMode::Break, BlockMode::Break);
- }
+ let ty_first = ty_first.into_inner();
+ let path = match ty_first.node {
+ // This notably includes paths passed through `ty` macro fragments (#46438).
+ TyKind::Path(None, path) => path,
+ _ => {
+ self.span_err(ty_first.span, "expected a trait, found type");
+ ast::Path::from_ident(ty_first.span, keywords::Invalid.ident())
}
- }
+ };
+ let trait_ref = TraitRef { path, ref_id: ty_first.id };
+
+ ItemKind::Impl(unsafety, polarity, defaultness,
+ generics, Some(trait_ref), ty_second, impl_items)
+ }
+ None => {
+ // impl Type
+ ItemKind::Impl(unsafety, polarity, defaultness,
+ generics, None, ty_first, impl_items)
}
+ };
- Ok((keywords::Invalid.ident(),
- ItemKind::Impl(unsafety, polarity, defaultness, generics, opt_trait, ty, impl_items),
- Some(attrs)))
- }
+ Ok((keywords::Invalid.ident(), item_kind, Some(attrs)))
}
fn parse_late_bound_lifetime_defs(&mut self) -> PResult<'a, Vec<GenericParam>> {
Ok(Visibility::Public)
}
- /// Parse defaultness: DEFAULT or nothing
- fn parse_defaultness(&mut self) -> PResult<'a, Defaultness> {
- if self.eat_defaultness() {
- Ok(Defaultness::Default)
+ /// Parse defaultness: `default` or nothing.
+ fn parse_defaultness(&mut self) -> Defaultness {
+ // `pub` is included for better error messages
+ if self.check_keyword(keywords::Default) &&
+ self.look_ahead(1, |t| t.is_keyword(keywords::Impl) ||
+ t.is_keyword(keywords::Const) ||
+ t.is_keyword(keywords::Fn) ||
+ t.is_keyword(keywords::Unsafe) ||
+ t.is_keyword(keywords::Extern) ||
+ t.is_keyword(keywords::Type) ||
+ t.is_keyword(keywords::Pub)) {
+ self.bump(); // `default`
+ Defaultness::Default
} else {
- Ok(Defaultness::Final)
+ Defaultness::Final
}
}
let (module, mut attrs) =
self.eval_src_mod(path, directory_ownership, id.to_string(), id_span)?;
if warn {
- let attr = ast::Attribute {
+ let attr = Attribute {
id: attr::mk_attr_id(),
style: ast::AttrStyle::Outer,
path: ast::Path::from_ident(syntax_pos::DUMMY_SP,
}
}
- pub fn submod_path_from_attr(attrs: &[ast::Attribute], dir_path: &Path) -> Option<PathBuf> {
+ pub fn submod_path_from_attr(attrs: &[Attribute], dir_path: &Path) -> Option<PathBuf> {
attr::first_attr_value_str_by_name(attrs, "path").map(|d| dir_path.join(&d.as_str()))
}
fn submod_path(&mut self,
id: ast::Ident,
- outer_attrs: &[ast::Attribute],
+ outer_attrs: &[Attribute],
id_sp: Span)
-> PResult<'a, ModulePathSuccess> {
if let Some(path) = Parser::submod_path_from_attr(outer_attrs, &self.directory.path) {
return Ok(ModulePathSuccess {
directory_ownership: match path.file_name().and_then(|s| s.to_str()) {
- Some("mod.rs") => DirectoryOwnership::Owned { relative: None },
- Some(_) => {
- DirectoryOwnership::Owned { relative: Some(id) }
- }
+ // All `#[path]` files are treated as though they are a `mod.rs` file.
+ // This means that `mod foo;` declarations inside `#[path]`-included
+ // files are siblings,
+ //
+ // Note that this will produce weirdness when a file named `foo.rs` is
+ // `#[path]` included and contains a `mod foo;` declaration.
+ // If you encounter this, it's your own darn fault :P
+ Some(_) => DirectoryOwnership::Owned { relative: None },
_ => DirectoryOwnership::UnownedViaMod(true),
},
path,
directory_ownership: DirectoryOwnership,
name: String,
id_sp: Span)
- -> PResult<'a, (ast::ItemKind, Vec<ast::Attribute> )> {
+ -> PResult<'a, (ast::ItemKind, Vec<Attribute> )> {
let mut included_mod_stack = self.sess.included_mod_stack.borrow_mut();
if let Some(i) = included_mod_stack.iter().position(|p| *p == path) {
let mut err = String::from("circular modules: ");
/// extern {}
fn parse_item_foreign_mod(&mut self,
lo: Span,
- opt_abi: Option<abi::Abi>,
+ opt_abi: Option<Abi>,
visibility: Visibility,
mut attrs: Vec<Attribute>)
-> PResult<'a, P<Item>> {
/// Parses a string as an ABI spec on an extern type or module. Consumes
/// the `extern` keyword, if one is found.
- fn parse_opt_abi(&mut self) -> PResult<'a, Option<abi::Abi>> {
+ fn parse_opt_abi(&mut self) -> PResult<'a, Option<Abi>> {
match self.token {
token::Literal(token::Str_(s), suf) | token::Literal(token::StrRaw(s, _), suf) => {
let sp = self.span;
return Ok(Some(item));
}
- if self.eat_keyword(keywords::Extern) {
+ if self.check_keyword(keywords::Extern) && self.is_extern_non_path() {
+ self.bump(); // `extern`
if self.eat_keyword(keywords::Crate) {
return Ok(Some(self.parse_item_extern_crate(lo, visibility, attrs)?));
}
|| (self.check_keyword(keywords::Unsafe)
&& self.look_ahead(1, |t| t.is_keyword(keywords::Fn))) {
// CONST FUNCTION ITEM
- let unsafety = if self.eat_keyword(keywords::Unsafe) {
- Unsafety::Unsafe
- } else {
- Unsafety::Normal
- };
+ let unsafety = self.parse_unsafety();
self.bump();
let (ident, item_, extra_attrs) =
self.parse_item_fn(unsafety,
self.look_ahead(1, |t| t.is_keyword(keywords::Auto)))
{
// UNSAFE TRAIT ITEM
- self.expect_keyword(keywords::Unsafe)?;
+ self.bump(); // `unsafe`
let is_auto = if self.eat_keyword(keywords::Trait) {
IsAuto::No
} else {
- self.eat_auto_trait();
+ self.expect_keyword(keywords::Auto)?;
+ self.expect_keyword(keywords::Trait)?;
IsAuto::Yes
};
let (ident, item_, extra_attrs) =
- self.parse_item_trait(is_auto, ast::Unsafety::Unsafe)?;
+ self.parse_item_trait(is_auto, Unsafety::Unsafe)?;
let prev_span = self.prev_span;
let item = self.mk_item(lo.to(prev_span),
ident,
maybe_append(attrs, extra_attrs));
return Ok(Some(item));
}
- if (self.check_keyword(keywords::Unsafe) &&
- self.look_ahead(1, |t| t.is_keyword(keywords::Impl))) ||
- (self.check_keyword(keywords::Default) &&
- self.look_ahead(1, |t| t.is_keyword(keywords::Unsafe)) &&
- self.look_ahead(2, |t| t.is_keyword(keywords::Impl)))
- {
+ if self.check_keyword(keywords::Impl) ||
+ self.check_keyword(keywords::Unsafe) &&
+ self.look_ahead(1, |t| t.is_keyword(keywords::Impl)) ||
+ self.check_keyword(keywords::Default) &&
+ self.look_ahead(1, |t| t.is_keyword(keywords::Impl)) ||
+ self.check_keyword(keywords::Default) &&
+ self.look_ahead(1, |t| t.is_keyword(keywords::Unsafe)) {
// IMPL ITEM
- let defaultness = self.parse_defaultness()?;
- self.expect_keyword(keywords::Unsafe)?;
+ let defaultness = self.parse_defaultness();
+ let unsafety = self.parse_unsafety();
self.expect_keyword(keywords::Impl)?;
- let (ident,
- item_,
- extra_attrs) = self.parse_item_impl(ast::Unsafety::Unsafe, defaultness)?;
- let prev_span = self.prev_span;
- let item = self.mk_item(lo.to(prev_span),
- ident,
- item_,
- visibility,
- maybe_append(attrs, extra_attrs));
- return Ok(Some(item));
+ let (ident, item, extra_attrs) = self.parse_item_impl(unsafety, defaultness)?;
+ let span = lo.to(self.prev_span);
+ return Ok(Some(self.mk_item(span, ident, item, visibility,
+ maybe_append(attrs, extra_attrs))));
}
if self.check_keyword(keywords::Fn) {
// FUNCTION ITEM
if self.check_keyword(keywords::Unsafe)
&& self.look_ahead(1, |t| *t != token::OpenDelim(token::Brace)) {
// UNSAFE FUNCTION ITEM
- self.bump();
+ self.bump(); // `unsafe`
let abi = if self.eat_keyword(keywords::Extern) {
self.parse_opt_abi()?.unwrap_or(Abi::C)
} else {
let is_auto = if self.eat_keyword(keywords::Trait) {
IsAuto::No
} else {
- self.eat_auto_trait();
+ self.expect_keyword(keywords::Auto)?;
+ self.expect_keyword(keywords::Trait)?;
IsAuto::Yes
};
// TRAIT ITEM
let (ident, item_, extra_attrs) =
- self.parse_item_trait(is_auto, ast::Unsafety::Normal)?;
- let prev_span = self.prev_span;
- let item = self.mk_item(lo.to(prev_span),
- ident,
- item_,
- visibility,
- maybe_append(attrs, extra_attrs));
- return Ok(Some(item));
- }
- if (self.check_keyword(keywords::Impl)) ||
- (self.check_keyword(keywords::Default) &&
- self.look_ahead(1, |t| t.is_keyword(keywords::Impl)))
- {
- // IMPL ITEM
- let defaultness = self.parse_defaultness()?;
- self.expect_keyword(keywords::Impl)?;
- let (ident,
- item_,
- extra_attrs) = self.parse_item_impl(ast::Unsafety::Normal, defaultness)?;
+ self.parse_item_trait(is_auto, Unsafety::Normal)?;
let prev_span = self.prev_span;
let item = self.mk_item(lo.to(prev_span),
ident,
Some(id) => id.name == keywords::Super.name() ||
id.name == keywords::SelfValue.name() ||
id.name == keywords::SelfType.name() ||
+ id.name == keywords::Extern.name() ||
id.name == keywords::Crate.name() ||
id.name == keywords::DollarCrate.name(),
None => false,
self.head(&visibility_qualified(&item.vis, "union"))?;
self.print_struct(struct_def, generics, item.ident, item.span, true)?;
}
- ast::ItemKind::AutoImpl(unsafety, ref trait_ref) => {
- self.head("")?;
- self.print_visibility(&item.vis)?;
- self.print_unsafety(unsafety)?;
- self.word_nbsp("impl")?;
- self.print_trait_ref(trait_ref)?;
- self.s.space()?;
- self.word_space("for")?;
- self.word_space("..")?;
- self.bopen()?;
- self.bclose(item.span)?;
- }
ast::ItemKind::Impl(unsafety,
polarity,
defaultness,
TokenStream::concat(result)
}
- fn first_tree(&self) -> Option<TokenTree> {
+ fn first_tree_and_joint(&self) -> Option<(TokenTree, bool)> {
match self.kind {
TokenStreamKind::Empty => None,
- TokenStreamKind::Tree(ref tree) |
- TokenStreamKind::JointTree(ref tree) => Some(tree.clone()),
- TokenStreamKind::Stream(ref stream) => stream.first().unwrap().first_tree(),
+ TokenStreamKind::Tree(ref tree) => Some((tree.clone(), false)),
+ TokenStreamKind::JointTree(ref tree) => Some((tree.clone(), true)),
+ TokenStreamKind::Stream(ref stream) => stream.first().unwrap().first_tree_and_joint(),
}
}
let stream = stream.into();
let last_tree_if_joint = self.0.last().and_then(TokenStream::last_tree_if_joint);
if let Some(TokenTree::Token(last_span, last_tok)) = last_tree_if_joint {
- if let Some(TokenTree::Token(span, tok)) = stream.first_tree() {
+ if let Some((TokenTree::Token(span, tok), is_joint)) = stream.first_tree_and_joint() {
if let Some(glued_tok) = last_tok.glue(tok) {
let last_stream = self.0.pop().unwrap();
self.push_all_but_last_tree(&last_stream);
let glued_span = last_span.to(span);
- self.0.push(TokenTree::Token(glued_span, glued_tok).into());
+ let glued_tt = TokenTree::Token(glued_span, glued_tok);
+ let glued_tokenstream = if is_joint {
+ glued_tt.joint()
+ } else {
+ glued_tt.into()
+ };
+ self.0.push(glued_tokenstream);
self.push_all_but_first_tree(&stream);
return
}
assert_eq!(test1.is_empty(), false);
assert_eq!(test2.is_empty(), false);
}
+
+ #[test]
+ fn test_dotdotdot() {
+ let mut builder = TokenStreamBuilder::new();
+ builder.push(TokenTree::Token(sp(0, 1), Token::Dot).joint());
+ builder.push(TokenTree::Token(sp(1, 2), Token::Dot).joint());
+ builder.push(TokenTree::Token(sp(2, 3), Token::Dot));
+ let stream = builder.build();
+ assert!(stream.eq_unspanned(&string_to_ts("...")));
+ assert_eq!(stream.trees().count(), 1);
+ }
+
}
visitor.visit_generics(type_parameters);
visitor.visit_enum_def(enum_definition, type_parameters, item.id, item.span)
}
- ItemKind::AutoImpl(_, ref trait_ref) => {
- visitor.visit_trait_ref(trait_ref)
- }
ItemKind::Impl(_, _, _,
ref type_parameters,
ref opt_trait_reference,
for r in &attr::find_repr_attrs(diagnostic, a) {
repr_type_name = match *r {
attr::ReprPacked | attr::ReprSimd | attr::ReprAlign(_) => continue,
- attr::ReprExtern => "i32",
+ attr::ReprC => "i32",
- attr::ReprInt(attr::SignedInt(ast::IntTy::Is)) => "isize",
+ attr::ReprInt(attr::SignedInt(ast::IntTy::Isize)) => "isize",
attr::ReprInt(attr::SignedInt(ast::IntTy::I8)) => "i8",
attr::ReprInt(attr::SignedInt(ast::IntTy::I16)) => "i16",
attr::ReprInt(attr::SignedInt(ast::IntTy::I32)) => "i32",
attr::ReprInt(attr::SignedInt(ast::IntTy::I64)) => "i64",
attr::ReprInt(attr::SignedInt(ast::IntTy::I128)) => "i128",
- attr::ReprInt(attr::UnsignedInt(ast::UintTy::Us)) => "usize",
+ attr::ReprInt(attr::UnsignedInt(ast::UintTy::Usize)) => "usize",
attr::ReprInt(attr::UnsignedInt(ast::UintTy::U8)) => "u8",
attr::ReprInt(attr::UnsignedInt(ast::UintTy::U16)) => "u16",
attr::ReprInt(attr::UnsignedInt(ast::UintTy::U32)) => "u32",
let (sp, msg) = errs.into_iter().next().unwrap();
cx.ecx.struct_span_err(sp, msg)
} else {
- let mut diag = cx.ecx.struct_span_err(cx.fmtsp,
- "multiple unused formatting arguments");
-
- // Ignoring message, as it gets repetitive
- // Then use MultiSpan to not clutter up errors
- for (sp, _) in errs {
- diag.span_label(sp, "unused");
- }
-
+ let mut diag = cx.ecx.struct_span_err(
+ errs.iter().map(|&(sp, _)| sp).collect::<Vec<Span>>(),
+ "multiple unused formatting arguments"
+ );
+ diag.span_label(cx.fmtsp, "multiple unused arguments in this statement");
diag
}
};
/// Extend a syntax context with a given mark
pub fn apply_mark(self, mark: Mark) -> SyntaxContext {
+ if mark.kind() == MarkKind::Modern {
+ return self.apply_mark_internal(mark);
+ }
+
+ let call_site_ctxt =
+ mark.expn_info().map_or(SyntaxContext::empty(), |info| info.call_site.ctxt()).modern();
+ if call_site_ctxt == SyntaxContext::empty() {
+ return self.apply_mark_internal(mark);
+ }
+
+ // Otherwise, `mark` is a macros 1.0 definition and the call site is in a
+ // macros 2.0 expansion, i.e. a macros 1.0 invocation is in a macros 2.0 definition.
+ //
+ // In this case, the tokens from the macros 1.0 definition inherit the hygiene
+ // at their invocation. That is, we pretend that the macros 1.0 definition
+ // was defined at its invocation (i.e. inside the macros 2.0 definition)
+ // so that the macros 2.0 definition remains hygienic.
+ //
+ // See the example at `test/run-pass/hygiene/legacy_interaction.rs`.
+ let mut ctxt = call_site_ctxt;
+ for mark in self.marks() {
+ ctxt = ctxt.apply_mark_internal(mark);
+ }
+ ctxt.apply_mark_internal(mark)
+ }
+
+ fn apply_mark_internal(self, mark: Mark) -> SyntaxContext {
HygieneData::with(|data| {
let syntax_contexts = &mut data.syntax_contexts;
let mut modern = syntax_contexts[self.0 as usize].modern;
})
}
+ pub fn marks(mut self) -> Vec<Mark> {
+ HygieneData::with(|data| {
+ let mut marks = Vec::new();
+ while self != SyntaxContext::empty() {
+ marks.push(data.syntax_contexts[self.0 as usize].outer_mark);
+ self = data.syntax_contexts[self.0 as usize].prev_ctxt;
+ }
+ marks.reverse();
+ marks
+ })
+ }
+
/// Adjust this context for resolution in a scope created by the given expansion.
/// For example, consider the following three resolutions of `f`:
///
#![feature(asm)]
#![feature(fnbox)]
-#![cfg_attr(unix, feature(libc))]
+#![cfg_attr(any(unix, target_os = "cloudabi"), feature(libc))]
#![feature(set_stdio)]
#![feature(panic_unwind)]
#![feature(staged_api)]
extern crate getopts;
extern crate term;
-#[cfg(unix)]
+#[cfg(any(unix, target_os = "cloudabi"))]
extern crate libc;
extern crate panic_unwind;
1
}
- #[cfg(any(target_os = "linux",
- target_os = "macos",
- target_os = "ios",
- target_os = "android",
- target_os = "solaris",
+ #[cfg(any(target_os = "android",
+ target_os = "cloudabi",
target_os = "emscripten",
- target_os = "fuchsia"))]
+ target_os = "fuchsia",
+ target_os = "ios",
+ target_os = "linux",
+ target_os = "macos",
+ target_os = "solaris"))]
fn num_cpus() -> usize {
unsafe { libc::sysconf(libc::_SC_NPROCESSORS_ONLN) as usize }
}
-Subproject commit 6d08185a5cf488d0a853b065a8a3a6d7a29f084f
+Subproject commit 2717444753318e461e0c3b30dacd03ffbac96903
#[lang = "sized"]
trait Sized {}
#[lang = "sync"]
-trait Sync {}
-#[allow(unknown_lints)]
-#[allow(auto_impl)]
-impl Sync for .. {}
+auto trait Sync {}
#[lang = "copy"]
trait Copy {}
#[lang = "freeze"]
-trait Freeze {}
-#[allow(unknown_lints)]
-#[allow(auto_impl)]
-impl Freeze for .. {}
+auto trait Freeze {}
#[lang = "drop_in_place"]
#[inline]
#[lang = "copy"]
trait Copy {}
#[lang = "freeze"]
-trait Freeze {}
-#[allow(unknown_lints)]
-#[allow(auto_impl)]
-impl Freeze for .. {}
+auto trait Freeze {}
#[lang = "drop_in_place"]
#[inline]
unwrap(Module)->setDataLayout(Target->createDataLayout());
}
-extern "C" LLVMTargetDataRef LLVMRustGetModuleDataLayout(LLVMModuleRef M) {
- return wrap(&unwrap(M)->getDataLayout());
-}
-
extern "C" void LLVMRustSetModulePIELevel(LLVMModuleRef M) {
unwrap(M)->setPIELevel(PIELevel::Level::Large);
}
return Ret;
}
-void LLVMRustSetLastError(const char *Err) {
+extern "C" void LLVMRustSetLastError(const char *Err) {
free((void *)LastError);
LastError = strdup(Err);
}
+extern "C" LLVMContextRef LLVMRustContextCreate(bool shouldDiscardNames) {
+ auto ctx = new LLVMContext();
+ ctx->setDiscardValueNames(shouldDiscardNames);
+ return wrap(ctx);
+}
+
extern "C" void LLVMRustSetNormalizedTarget(LLVMModuleRef M,
const char *Triple) {
unwrap(M)->setTargetTriple(Triple::normalize(Triple));
return wrap(unwrap(B)->CreateFence(fromRust(Order), fromRust(Scope)));
}
-extern "C" void LLVMRustSetDebug(int Enabled) {
-#ifndef NDEBUG
- DebugFlag = Enabled;
-#endif
-}
-
enum class LLVMRustAsmDialect {
Other,
Att,
return true;
}
-extern "C" bool LLVMRustLinkInParsedExternalBitcode(
- LLVMModuleRef DstRef, LLVMModuleRef SrcRef) {
-#if LLVM_VERSION_GE(4, 0)
- Module *Dst = unwrap(DstRef);
- std::unique_ptr<Module> Src(unwrap(SrcRef));
-
- if (Linker::linkModules(*Dst, std::move(Src))) {
- LLVMRustSetLastError("failed to link modules");
- return false;
- }
- return true;
-#else
- LLVMRustSetLastError("can't link parsed modules on this LLVM");
- return false;
-#endif
-}
-
// Note that the two following functions look quite similar to the
// LLVMGetSectionName function. Sadly, it appears that this function only
// returns a char* pointer, which isn't guaranteed to be null-terminated. The
}
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(Twine, LLVMTwineRef)
-DEFINE_SIMPLE_CONVERSION_FUNCTIONS(DebugLoc, LLVMDebugLocRef)
extern "C" void LLVMRustWriteTwineToString(LLVMTwineRef T, RustStringRef Str) {
RawRustStringOstream OS(Str);
report_fatal_error("Unhandled TypeID.");
}
-extern "C" void LLVMRustWriteDebugLocToString(LLVMContextRef C,
- LLVMDebugLocRef DL,
- RustStringRef Str) {
- RawRustStringOstream OS(Str);
- unwrap(DL)->print(OS);
-}
-
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(SMDiagnostic, LLVMSMDiagnosticRef)
extern "C" void LLVMRustSetInlineAsmDiagnosticHandler(
unwrap(D)->print("", OS);
}
-extern "C" LLVMValueRef
-LLVMRustBuildLandingPad(LLVMBuilderRef B, LLVMTypeRef Ty,
- LLVMValueRef PersFn, unsigned NumClauses,
- const char *Name, LLVMValueRef F) {
- return LLVMBuildLandingPad(B, Ty, PersFn, NumClauses, Name);
-}
-
extern "C" LLVMValueRef LLVMRustBuildCleanupPad(LLVMBuilderRef B,
LLVMValueRef ParentPad,
unsigned ArgCount,
return true;
}
-extern "C" LLVMContextRef LLVMRustGetValueContext(LLVMValueRef V) {
- return wrap(&unwrap(V)->getContext());
-}
-
enum class LLVMRustVisibility {
Default = 0,
Hidden = 1,
extern "C" uint64_t
LLVMRustModuleCost(LLVMModuleRef M) {
- Module &Mod = *unwrap(M);
- uint64_t cost = 0;
- for (auto &F : Mod.functions()) {
- (void)F;
- cost += 1;
- }
- return cost;
+ auto f = unwrap(M)->functions();
+ return std::distance(std::begin(f), std::end(f));
}
# If this file is modified, then llvm will be (optionally) cleaned and then rebuilt.
# The actual contents of this file do not matter, but to trigger a change on the
# build bots then the contents should be changed so git updates the mtime.
-2017-11-07
+2017-11-08
#include "llvm/IR/IRPrintingPasses.h"
#include "llvm/Linker/Linker.h"
-void LLVMRustSetLastError(const char *);
+extern "C" void LLVMRustSetLastError(const char *);
enum class LLVMRustResult { Success, Failure };
typedef struct OpaqueRustString *RustStringRef;
typedef struct LLVMOpaqueTwine *LLVMTwineRef;
-typedef struct LLVMOpaqueDebugLoc *LLVMDebugLocRef;
typedef struct LLVMOpaqueSMDiagnostic *LLVMSMDiagnosticRef;
-typedef struct LLVMOpaqueRustJITMemoryManager *LLVMRustJITMemoryManagerRef;
extern "C" void LLVMRustStringWriteImpl(RustStringRef Str, const char *Ptr,
size_t Size);
# 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: 2017-11-21
+date: 2018-01-02
rustc: beta
cargo: beta
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <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 4.0
+// compile-flags: -O
+
+#![crate_type="rlib"]
+
+// CHECK-LABEL: @memzero
+// CHECK-NOT: store
+// CHECK: call void @llvm.memset
+// CHECK-NOT: store
+#[no_mangle]
+pub fn memzero(data: &mut [u8]) {
+ for i in 0..data.len() {
+ data[i] = 0;
+ }
+}
--- /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.
+
+// -C no-prepopulate-passes
+#![crate_type="staticlib"]
+
+#[repr(C)]
+pub struct Foo(u64);
+
+// CHECK: define {{.*}} @foo(
+#[no_mangle]
+pub extern fn foo(_: Foo) -> Foo { loop {} }
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <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 we don't emit unneeded `resume` cleanup blocks for every
+// destructor.
+
+// CHECK-NOT: Unwind
+
+#![feature(test)]
+#![crate_type="rlib"]
+
+extern crate test;
+
+struct Foo {}
+
+impl Drop for Foo {
+ fn drop(&mut self) {
+ test::black_box(());
+ }
+}
+
+#[no_mangle]
+pub fn foo() {
+ let _foo = Foo {};
+}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// Test that macro reexports item are gated by `macro_reexport` feature gate.
+// Test that macro re-exports item are gated by `macro_reexport` feature gate.
// aux-build:macro_reexport_1.rs
// gate-test-macro_reexport
#![crate_type = "dylib"]
#[macro_reexport(reexported)]
-//~^ ERROR macros reexports are experimental and possibly buggy
+//~^ ERROR macros re-exports are experimental and possibly buggy
#[macro_use] #[no_link]
extern crate macro_reexport_1;
struct Foo;
-unsafe impl !Clone for Foo { } //~ ERROR negative implementations are not unsafe [E0198]
+unsafe impl !Send for Foo { } //~ ERROR E0198
fn main() {
}
}
pub use foo as foo2;
-//~^ ERROR `foo` is private, and cannot be reexported [E0365]
+//~^ ERROR `foo` is private, and cannot be re-exported [E0365]
fn main() {}
--- /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() {
+ let _ = ::std::u128::MAX; //~ ERROR E0658
+}
+++ /dev/null
-// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <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(optin_builtin_traits)]
-
-trait Foo {}
-impl Foo for .. {}
-//~^ ERROR The form `impl Foo for .. {}` will be removed, please use `auto trait Foo {}`
-//~^^ WARN this was previously accepted by the compiler
#![feature(optin_builtin_traits)]
auto trait Generic<T> {}
-//~^ ERROR auto traits cannot have generics
-//~^^ traits with auto impls (`e.g. impl Trait for ..`) can not have type parameters
+//~^ auto traits cannot have generic parameters [E0567]
auto trait Bound : Copy {}
-//~^ ERROR auto traits cannot have super traits
-//~^^ traits with auto impls (`e.g. impl Trait for ..`) cannot have predicates
+//~^ auto traits cannot have super traits [E0568]
auto trait MyTrait { fn foo() {} }
-//~^ ERROR auto traits cannot contain items
-//~^^ traits with default impls (`e.g. impl Trait for ..`) must have no methods or associated items
+//~^ auto traits cannot have methods or associated items [E0380]
fn main() {}
fn foo() {}
}
- // these are public so the parent can reexport them.
+ // these are public so the parent can re-export them.
pub static reexported_a: isize = 0;
pub fn reexported_b() {}
pub struct reexported_c;
#![feature(optin_builtin_traits, core)]
#![crate_type = "rlib"]
-pub trait DefaultedTrait { }
-#[allow(auto_impl)]
-impl DefaultedTrait for .. { }
+pub auto trait DefaultedTrait { }
pub struct Something<T> { t: T }
fn foo(x: &()) {
bar(|| {
- //~^ ERROR does not fulfill
+ //~^ ERROR explicit lifetime required in the type of `x` [E0621]
let _ = x;
})
}
#![feature(optin_builtin_traits)]
-trait MyTrait { fn foo() {} }
+auto trait MySafeTrait {}
-#[allow(auto_impl)]
-impl MyTrait for .. {}
-//~^ ERROR redundant auto implementations of trait `MyTrait`
+struct Foo;
-#[allow(auto_impl)]
-impl MyTrait for .. {}
-
-trait MySafeTrait {}
-
-#[allow(auto_impl)]
-unsafe impl MySafeTrait for .. {}
+unsafe impl MySafeTrait for Foo {}
//~^ ERROR implementing the trait `MySafeTrait` is not unsafe
-unsafe trait MyUnsafeTrait {}
+unsafe auto trait MyUnsafeTrait {}
-#[allow(auto_impl)]
-impl MyUnsafeTrait for .. {}
+impl MyUnsafeTrait for Foo {}
//~^ ERROR the trait `MyUnsafeTrait` requires an `unsafe impl` declaration
fn main() {}
struct TestType;
unsafe impl !Send for TestType {}
-//~^ ERROR negative implementations are not unsafe
+//~^ ERROR negative impls cannot be unsafe
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.
-
-// error-pattern: mod statements in non-mod.rs files are unstable
-
-#[path="mod_file_not_owning_aux3.rs"]
-mod foo;
-
-fn main() {}
use std::fmt::Debug;
fn elided(x: &i32) -> impl Copy { x }
-//~^ ERROR cannot infer an appropriate lifetime
+//~^ ERROR explicit lifetime required in the type of `x` [E0621]
fn explicit<'a>(x: &'a i32) -> impl Copy { x }
//~^ ERROR cannot infer an appropriate lifetime
mod foo {}
mod a {
- pub use super::foo; //~ ERROR cannot be reexported
+ pub use super::foo; //~ ERROR cannot be re-exported
pub use super::*; //~ ERROR must import something with the glob's visibility
}
}
pub mod a {
pub use super::foo; // This is OK since the value `foo` is visible enough.
- fn f(_: foo::S) {} // `foo` is imported in the type namespace (but not `pub` reexported).
+ fn f(_: foo::S) {} // `foo` is imported in the type namespace (but not `pub` re-exported).
}
pub mod b {
pub use super::*; // This is also OK since the value `foo` is visible enough.
- fn f(_: foo::S) {} // Again, the module `foo` is imported (but not `pub` reexported).
+ fn f(_: foo::S) {} // Again, the module `foo` is imported (but not `pub` re-exported).
}
}
mod c {
- // Test that `foo` is not reexported.
+ // Test that `foo` is not re-exported.
use b::a::foo::S; //~ ERROR `foo`
use b::b::foo::S as T; //~ ERROR `foo`
}
fn foo<T: Any>(value: &T) -> Box<Any> {
Box::new(value) as Box<Any>
- //~^ ERROR: cannot infer an appropriate lifetime
+ //~^ ERROR explicit lifetime required in the type of `value` [E0621]
}
fn main() {
#![feature(optin_builtin_traits)]
-unsafe trait Trait {
+unsafe auto trait Trait {
//~^ ERROR E0380
type Output;
}
-#[allow(auto_impl)]
-unsafe impl Trait for .. {}
-
fn call_method<T: Trait>(x: T) {}
fn main() {
// ICE
call_method(());
+ //~^ ERROR
}
#![feature(optin_builtin_traits)]
-unsafe trait Trait {
+unsafe auto trait Trait {
//~^ ERROR E0380
fn method(&self) {
println!("Hello");
}
}
-#[allow(auto_impl)]
-unsafe impl Trait for .. {}
-
fn call_method<T: Trait>(x: T) {
x.method();
}
enum bird {
pub duck,
//~^ ERROR: expected identifier, found keyword `pub`
- //~^^ ERROR: expected
+ //~| ERROR: expected
goose
}
--- /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(fn_traits)]
+
+fn main() {
+ <fn() as Fn()>::call;
+ //~^ ERROR associated type bindings are not allowed here [E0229]
+}
--- /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 xyz() -> u8 { 42 }
+
+const NUM: u8 = xyz();
+//~^ ERROR calls in constants are limited to constant functions, struct and enum constructors
+
+fn main() {
+ match 1 {
+ NUM => unimplemented!(),
+ _ => unimplemented!(),
+ }
+}
--- /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(attr_literals)]
+
+#[link(name="foo", cfg("rlib"))] //~ ERROR invalid argument for `cfg(..)`
+extern {}
+
+fn main() {}
--- /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.
+
+#[link(name="foo", cfg())] //~ ERROR `cfg()` must have an argument
+extern {}
+
+fn main() {}
}
fn test_args(b: Box<i32>) { //[ast]~ NOTE first assignment
- //[mir]~^ NOTE first assignment
+ //[mir]~^ NOTE argument not declared as `mut`
b = Box::new(2); //[ast]~ ERROR cannot assign twice to immutable variable
- //[mir]~^ ERROR cannot assign twice to immutable variable `b`
+ //[mir]~^ ERROR cannot assign to immutable argument `b`
//[ast]~| NOTE cannot assign twice to immutable
- //[mir]~| NOTE cannot assign twice to immutable
+ //[mir]~| NOTE cannot assign to immutable argument
}
fn main() {}
mod rank {
pub use self::Professor::*;
- //~^ ERROR enum is private and its variants cannot be reexported
+ //~^ ERROR enum is private and its variants cannot be re-exported
pub use self::Lieutenant::{JuniorGrade, Full};
- //~^ ERROR variant `JuniorGrade` is private and cannot be reexported
- //~| ERROR variant `Full` is private and cannot be reexported
+ //~^ ERROR variant `JuniorGrade` is private and cannot be re-exported
+ //~| ERROR variant `Full` is private and cannot be re-exported
pub use self::PettyOfficer::*;
- //~^ ERROR enum is private and its variants cannot be reexported
+ //~^ ERROR enum is private and its variants cannot be re-exported
pub use self::Crewman::*;
- //~^ ERROR enum is private and its variants cannot be reexported
+ //~^ ERROR enum is private and its variants cannot be re-exported
enum Professor {
Adjunct,
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <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! m {
+ ($my_type: ty) => {
+ impl $my_type for u8 {}
+ }
+}
+
+trait Trait {}
+
+m!(Tr);
+
+m!(&'static u8); //~ ERROR expected a trait, found type
+
+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.
+
+#![feature(extern_in_paths)]
+
+fn main() {
+ let extern = 0; //~ ERROR expected unit struct/variant or constant, found module `extern`
+}
type __ = isize; //~ ERROR type `__` should have a camel case name such as `CamelCase`
+struct X86_64;
+
+struct X86__64; //~ ERROR type `X86__64` should have a camel case name such as `X86_64`
+
+struct Abc_123; //~ ERROR type `Abc_123` should have a camel case name such as `Abc123`
+
+struct A1_b2_c3; //~ ERROR type `A1_b2_c3` should have a camel case name such as `A1B2C3`
+
fn main() { }
#[derive(Eq, PartialEq)]
struct X { y: bool }
impl X {
- fn foo(&self) -> bool { self.y }
+ fn foo(&self, conjunct: bool) -> bool { self.y && conjunct }
}
fn foo() -> isize {
return (1); //~ ERROR unnecessary parentheses around `return` value
}
-fn bar() -> X {
- return (X { y: true }); //~ ERROR unnecessary parentheses around `return` value
+fn bar(y: bool) -> X {
+ return (X { y }); //~ ERROR unnecessary parentheses around `return` value
}
fn main() {
foo();
- bar();
+ bar((true)); //~ ERROR unnecessary parentheses around function argument
if (true) {} //~ ERROR unnecessary parentheses around `if` condition
while (true) {} //~ ERROR unnecessary parentheses around `while` condition
if (X { y: true } == v) {}
if (X { y: false }.y) {}
- while (X { y: false }.foo()) {}
+ while (X { y: false }.foo(true)) {}
while (true | X { y: false }.y) {}
match (X { y: false }) {
_ => {}
}
+ X { y: false }.foo((true)); //~ ERROR unnecessary parentheses around method argument
+
let mut _a = (0); //~ ERROR unnecessary parentheses around assigned value
_a = (0); //~ ERROR unnecessary parentheses around assigned value
_a += (1); //~ ERROR unnecessary parentheses around assigned value
extern crate lint_unused_extern_crate5; //~ ERROR: unused extern crate
-pub extern crate lint_unused_extern_crate4; // no error, it is reexported
+pub extern crate lint_unused_extern_crate4; // no error, it is re-exported
extern crate lint_unused_extern_crate3; // no error, it is used
#![feature(macro_reexport)]
#[allow(unused_extern_crates)]
-#[macro_reexport] //~ ERROR bad macro reexport
+#[macro_reexport] //~ ERROR bad macro re-export
extern crate std;
#![feature(macro_reexport)]
#[allow(unused_extern_crates)]
-#[macro_reexport="foo"] //~ ERROR bad macro reexport
+#[macro_reexport="foo"] //~ ERROR bad macro re-export
extern crate std;
#![feature(macro_reexport)]
#[allow(unused_extern_crates)]
-#[macro_reexport(foo="bar")] //~ ERROR bad macro reexport
+#[macro_reexport(foo="bar")] //~ ERROR bad macro re-export
extern crate std;
#![feature(macro_reexport)]
#[macro_use(macro_two)]
-#[macro_reexport(no_way)] //~ ERROR reexported macro not found
+#[macro_reexport(no_way)] //~ ERROR re-exported macro not found
extern crate two_macros;
pub fn main() {
// `Box<SomeTrait>` defaults to a `'static` bound, so this return
// is illegal.
- ss.r //~ ERROR cannot infer an appropriate lifetime
+ ss.r //~ ERROR explicit lifetime required in the type of `ss` [E0621]
}
fn store(ss: &mut SomeStruct, b: Box<SomeTrait>) {
// except according to those terms.
// Ensure that OIBIT checks `T` when it encounters a `PhantomData<T>` field, instead of checking
-// the `PhantomData<T>` type itself (which almost always implements a "default" trait
-// (`impl Trait for ..`))
+// the `PhantomData<T>` type itself (which almost always implements an auto trait)
#![feature(optin_builtin_traits)]
use std::marker::{PhantomData};
-unsafe trait Zen {}
-
-#[allow(auto_impl)]
-unsafe impl Zen for .. {}
+unsafe auto trait Zen {}
unsafe impl<'a, T: 'a> Zen for &'a T where T: Sync {}
#![feature(optin_builtin_traits)]
-trait MarkerTr {}
pub trait Tr {
fn f();
const C: u8;
}
struct Ts(pub u8);
-#[allow(auto_impl)]
-pub impl MarkerTr for .. {} //~ ERROR unnecessary visibility qualifier
pub impl Tr for S { //~ ERROR unnecessary visibility qualifier
pub fn f() {} //~ ERROR unnecessary visibility qualifier
pub const C: u8 = 0; //~ ERROR unnecessary visibility qualifier
}
const MAIN: u8 = {
- trait MarkerTr {}
pub trait Tr {
fn f();
const C: u8;
}
struct Ts(pub u8);
- #[allow(auto_impl)]
- pub impl MarkerTr for .. {} //~ ERROR unnecessary visibility qualifier
pub impl Tr for S { //~ ERROR unnecessary visibility qualifier
pub fn f() {} //~ ERROR unnecessary visibility qualifier
pub const C: u8 = 0; //~ ERROR unnecessary visibility qualifier
};
fn main() {
- trait MarkerTr {}
pub trait Tr {
fn f();
const C: u8;
}
struct Ts(pub u8);
- #[allow(auto_impl)]
- pub impl MarkerTr for .. {} //~ ERROR unnecessary visibility qualifier
pub impl Tr for S { //~ ERROR unnecessary visibility qualifier
pub fn f() {} //~ ERROR unnecessary visibility qualifier
pub const C: u8 = 0; //~ ERROR unnecessary visibility qualifier
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+// ignore-tidy-linelength
+
#![allow(unused)]
use m::S;
use S;
fn f() {
S(10);
- //~^ ERROR private struct constructors are not usable through reexports in outer modules
+ //~^ ERROR private struct constructors are not usable through re-exports in outer modules
//~| WARN this was previously accepted
}
}
fn f() {
use foo::bar::S;
pub(self) use foo::bar::f; // ok
- pub(super) use foo::bar::f as g; //~ ERROR cannot be reexported
+ pub(super) use foo::bar::f as g; //~ ERROR cannot be re-exported
S::default().x; // ok
S::default().f(); // ok
S::g(); // ok
type AssocAlias = m::Pub3;
}
- impl (<Priv as PrivTr>::AssocAlias) { //~ ERROR no base type found for inherent implementation
+ impl <Priv as PrivTr>::AssocAlias { //~ ERROR no base type found for inherent implementation
pub fn f(arg: Priv) {} // private type `aliases_pub::Priv` in public interface
}
}
type AssocAlias = Priv3;
}
- impl (<Priv as PrivTr>::AssocAlias) { //~ ERROR no base type found for inherent implementation
+ impl <Priv as PrivTr>::AssocAlias { //~ ERROR no base type found for inherent implementation
pub fn f(arg: Priv) {} // OK
}
}
// except according to those terms.
mod m1 {
- pub use ::E::V; //~ ERROR variant `V` is private and cannot be reexported
+ pub use ::E::V; //~ ERROR variant `V` is private and cannot be re-exported
}
mod m2 {
- pub use ::E::{V}; //~ ERROR variant `V` is private and cannot be reexported
+ pub use ::E::{V}; //~ ERROR variant `V` is private and cannot be re-exported
}
mod m3 {
- pub use ::E::V::{self}; //~ ERROR variant `V` is private and cannot be reexported
+ pub use ::E::V::{self}; //~ ERROR variant `V` is private and cannot be re-exported
}
mod m4 {
- pub use ::E::*; //~ ERROR enum is private and its variants cannot be reexported
+ pub use ::E::*; //~ ERROR enum is private and its variants cannot be re-exported
}
enum E { V }
#![allow(unused)]
extern crate core;
-pub use core as reexported_core; //~ ERROR `core` is private, and cannot be reexported
+pub use core as reexported_core; //~ ERROR `core` is private, and cannot be re-exported
//~^ WARN this was previously accepted
mod foo1 {
}
mod foo2 {
- use foo1::core; //~ ERROR `core` is private, and cannot be reexported
+ use foo1::core; //~ ERROR `core` is private, and cannot be re-exported
//~^ WARN this was previously accepted
pub mod bar {
extern crate core;
}
mod baz {
- pub use foo2::bar::core; //~ ERROR `core` is private, and cannot be reexported
+ pub use foo2::bar::core; //~ ERROR `core` is private, and cannot be re-exported
//~^ WARN this was previously accepted
}
fn a(v: &[u8]) -> Box<Foo + 'static> {
let x: Box<Foo + 'static> = Box::new(v);
- //~^ ERROR cannot infer an appropriate lifetime due to conflicting
+ //~^ ERROR explicit lifetime required in the type of `v` [E0621]
x
}
fn b(v: &[u8]) -> Box<Foo + 'static> {
Box::new(v)
- //~^ ERROR cannot infer an appropriate lifetime due to conflicting
+ //~^ ERROR explicit lifetime required in the type of `v` [E0621]
}
fn c(v: &[u8]) -> Box<Foo> {
// same as previous case due to RFC 599
Box::new(v)
- //~^ ERROR cannot infer an appropriate lifetime due to conflicting
+ //~^ ERROR explicit lifetime required in the type of `v` [E0621]
}
fn d<'a,'b>(v: &'a [u8]) -> Box<Foo+'b> {
fn static_proc(x: &isize) -> Box<FnMut()->(isize) + 'static> {
// This is illegal, because the region bound on `proc` is 'static.
- Box::new(move|| { *x }) //~ ERROR cannot infer an appropriate lifetime
+ Box::new(move|| { *x }) //~ ERROR explicit lifetime required in the type of `x` [E0621]
}
fn main() { }
}
fn error(u: &(), v: &()) {
- static_id(&u); //[ll]~ ERROR cannot infer an appropriate lifetime
+ static_id(&u); //[ll]~ ERROR explicit lifetime required in the type of `u` [E0621]
//[nll]~^ WARNING not reporting region error due to -Znll
- //[nll]~| ERROR free region `` does not outlive free region `'static`
- static_id_indirect(&v); //[ll]~ ERROR cannot infer an appropriate lifetime
+ //[nll]~| ERROR explicit lifetime required in the type of `u` [E0621]
+ static_id_indirect(&v); //[ll]~ ERROR explicit lifetime required in the type of `v` [E0621]
//[nll]~^ WARNING not reporting region error due to -Znll
- //[nll]~| ERROR free region `` does not outlive free region `'static`
+ //[nll]~| ERROR explicit lifetime required in the type of `v` [E0621]
}
fn main() {}
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <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.
+
+#[derive(Debug)]
+pub struct S;
+
+#[derive(Debug)]
+pub struct Z;
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <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(extern_in_paths)]
+
+use extern::xcrate::S; //~ ERROR can't find crate for `xcrate`
+
+fn main() {}
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <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(extern_in_paths)]
+
+fn main() {
+ let s = extern::xcrate::S; //~ ERROR can't find crate for `xcrate`
+}
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <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(extern_in_paths)]
+
+use extern::ycrate; //~ ERROR can't find crate for `ycrate`
+
+fn main() {}
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <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:xcrate.rs
+
+#![feature(extern_in_paths)]
+
+use extern; //~ ERROR unresolved import `extern`
+ //~^ NOTE no `extern` in the root
+use extern::*; //~ ERROR unresolved import `extern::*`
+ //~^ NOTE cannot glob-import all possible crates
+
+fn main() {
+ let s = extern::xcrate; //~ ERROR expected value, found module `extern::xcrate`
+ //~^ NOTE not a value
+}
+++ /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.
-
-#![feature(specialization)]
-#![feature(optin_builtin_traits)]
-
-trait Foo {}
-
-#[allow(auto_impl)]
-default impl Foo for .. {}
-//~^ ERROR `default impl` is not allowed for auto trait implementations
-
-fn main() {}
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <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(optin_builtin_traits)]
+#![feature(specialization)]
+
+struct S;
+struct Z;
+
+default impl S {} //~ ERROR inherent impls cannot be default
+
+default unsafe impl Send for S {} //~ ERROR impls of auto traits cannot be default
+default impl !Send for Z {} //~ ERROR impls of auto traits cannot be default
+
+trait Tr {}
+default impl !Tr for S {} //~ ERROR negative impls are only allowed for auto traits
#![feature(optin_builtin_traits)]
#![feature(specialization)]
-trait Foo {}
-
-#[allow(auto_impl)]
-impl Foo for .. {}
+auto trait Foo {}
impl<T> Foo for T {}
impl !Foo for u8 {} //~ ERROR E0119
-trait Bar {}
-
-#[allow(auto_impl)]
-impl Bar for .. {}
+auto trait Bar {}
impl<T> !Bar for T {}
impl Bar for u8 {} //~ ERROR E0119
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+#![feature(const_fn)]
+
struct WithDtor;
impl Drop for WithDtor {
const EARLY_DROP_C: i32 = (WithDtor, 0).1;
//~^ ERROR destructors cannot be evaluated at compile-time
+const fn const_drop<T>(_: T) {}
+//~^ ERROR destructors cannot be evaluated at compile-time
+
+const fn const_drop2<T>(x: T) {
+ (x, ()).1
+ //~^ ERROR destructors cannot be evaluated at compile-time
+}
+
fn main () {}
trait TestTrait {}
-unsafe impl !Send for TestType {}
+impl !Send for TestType {}
//~^ ERROR negative trait bounds
fn main() {}
--- /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.
+
+#![feature(optin_builtin_traits)]
+
+use std::marker::Send;
+
+struct TestType;
+
+impl !TestType {}
+//~^ ERROR inherent impls cannot be negative
+
+trait TestTrait {}
+
+unsafe impl !Send for TestType {}
+//~^ ERROR negative impls cannot be unsafe
+impl !TestTrait for TestType {}
+//~^ ERROR negative impls are only allowed for auto traits
+
+struct TestType2<T>(T);
+
+impl<T> !TestType2<T> {}
+//~^ ERROR inherent impls cannot be negative
+
+unsafe impl<T> !Send for TestType2<T> {}
+//~^ ERROR negative impls cannot be unsafe
+impl<T> !TestTrait for TestType2<T> {}
+//~^ ERROR negative impls are only allowed for auto traits
+
+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.
-
-#![feature(optin_builtin_traits)]
-
-trait MyAutoImpl {}
-
-#[allow(auto_impl)]
-impl<T> MyAutoImpl for .. {}
-//~^ ERROR auto trait implementations are not allowed to have generics
-
-fn main() {}
struct SomeStruct;
-unsafe impl SomeStruct { //~ ERROR inherent impls cannot be declared as unsafe
+unsafe impl SomeStruct { //~ ERROR inherent impls cannot be unsafe
fn foo(self) { }
}
#![feature(optin_builtin_traits)]
-trait Magic: Copy {} //~ ERROR E0568
-#[allow(auto_impl)]
-impl Magic for .. {}
+auto trait Magic: Copy {} //~ ERROR E0568
fn copy<T: Magic>(x: T) -> (T, T) { (x, x) }
struct NoClone;
fn main() {
- let (a, b) = copy(NoClone);
+ let (a, b) = copy(NoClone); //~ ERROR
println!("{:?} {:?}", a, b);
}
#![feature(optin_builtin_traits)]
-trait Magic : Sized where Option<Self> : Magic {} //~ ERROR E0568
-#[allow(auto_impl)]
-impl Magic for .. {}
+auto trait Magic : Sized where Option<Self> : Magic {} //~ ERROR E0568
impl<T:Magic> Magic for T {}
fn copy<T: Magic>(x: T) -> (T, T) { (x, x) }
#![feature(optin_builtin_traits)]
-trait Magic: Copy {} //~ ERROR E0568
-#[allow(auto_impl)]
-impl Magic for .. {}
+auto trait Magic: Copy {} //~ ERROR E0568
impl<T:Magic> Magic for T {}
fn copy<T: Magic>(x: T) -> (T, T) { (x, x) }
+++ /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.
-
-#![feature(optin_builtin_traits)]
-
-trait Magic<T> {} //~ ERROR E0567
-#[allow(auto_impl)]
-impl Magic<isize> for .. {}
#![feature(optin_builtin_traits)]
-trait MyTrait {}
-
-#[allow(auto_impl)]
-impl MyTrait for .. {}
+auto trait MyTrait {}
struct MyS;
#![feature(optin_builtin_traits)]
-trait MyTrait {}
+auto trait MyTrait {}
-#[allow(auto_impl)]
-impl MyTrait for .. {}
impl<T> !MyTrait for *mut T {}
struct MyS;
#![feature(optin_builtin_traits)]
-trait MyTrait {}
+auto trait MyTrait {}
-#[allow(auto_impl)]
-impl MyTrait for .. {}
-
-unsafe trait MyUnsafeTrait {}
-
-#[allow(auto_impl)]
-unsafe impl MyUnsafeTrait for .. {}
+unsafe auto trait MyUnsafeTrait {}
struct ThisImplsTrait;
// Test that declaring that `&T` is `Defaulted` if `T:Signed` implies
// that other `&T` is NOT `Defaulted` if `T:Signed` does not hold. In
-// other words, the `..` impl only applies if there are no existing
+// other words, the auto impl only applies if there are no existing
// impls whose types unify.
#![feature(optin_builtin_traits)]
-trait Defaulted { }
-#[allow(auto_impl)]
-impl Defaulted for .. { }
+auto trait Defaulted { }
impl<'a,T:Signed> Defaulted for &'a T { }
impl<'a,T:Signed> Defaulted for &'a mut T { }
fn is_defaulted<T:Defaulted>() { }
}
impl !TestTrait for TestType {}
-//~^ ERROR negative impls are only allowed for traits with default impls (e.g., `Send` and `Sync`)
+//~^ ERROR negative impls are only allowed for auto traits (e.g., `Send` and `Sync`)
fn main() {}
// except according to those terms.
// min-lldb-version: 310
+// ignore-gdb // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155
// compile-flags:-g
// gdb-command:run
// its numerical value.
// min-lldb-version: 310
+// ignore-gdb // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155
// compile-flags:-g
// gdb-command:run
// except according to those terms.
// min-lldb-version: 310
+// ignore-gdb // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155
// compile-flags:-g
// gdb-command:run
// its numerical value.
// min-lldb-version: 310
+// ignore-gdb // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155
// compile-flags:-g
// except according to those terms.
// ignore-tidy-linelength
+// ignore-test // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155
// min-lldb-version: 310
// compile-flags:-g
// except according to those terms.
// ignore-aarch64
+// ignore-gdb // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155
// min-lldb-version: 310
// compile-flags:-g
// ignore-windows
// ignore-android
+// ignore-test // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155
// min-lldb-version: 310
#![allow(unused)]
// except according to those terms.
// ignore-tidy-linelength
-
+// ignore-test // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155
// min-lldb-version: 310
// This test case checks if function arguments already have the correct value
// min-lldb-version: 310
// ignore-gdb
+// ignore-test // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155
// compile-flags:-g
// lldb-command:breakpoint set --name immediate_args
// except according to those terms.
// min-lldb-version: 310
+// ignore-gdb // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155
// compile-flags:-g
// ignore-lldb
+// ignore-gdb // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155
// compile-flags:-C debuginfo=1
// ignore-android
// ignore-aarch64
// min-lldb-version: 310
+// ignore-gdb // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155
// aux-build:macro-stepping.rs
// ignore-tidy-linelength
// min-lldb-version: 310
+// ignore-test // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155
// compile-flags:-g
// except according to those terms.
// ignore-tidy-linelength
+// ignore-test // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155
+
// min-lldb-version: 310
// compile-flags:-g
// ignore-windows failing on win32 bot
// ignore-freebsd: gdb package too new
+// ignore-test // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155
// ignore-android: FIXME(#10381)
// compile-flags:-g
// min-gdb-version 7.7
// except according to those terms.
// min-lldb-version: 310
-
// compile-flags:-g
// === GDB TESTS ===================================================================================
// gdb-command:continue
// gdb-command:print x
-// gdb-check:$5 = 10.5
+// gdb-check:$7 = 10.5
// gdb-command:print y
-// gdb-check:$6 = 20
+// gdb-check:$8 = 20
// gdb-command:continue
// gdb-command:print x
-// gdb-check:$5 = 11.5
+// gdb-check:$9 = 11.5
// gdb-command:print y
-// gdb-check:$6 = 20
+// gdb-check:$10 = 20
// gdb-command:continue
// === LLDB TESTS ==================================================================================
// lldb-command:continue
// lldb-command:print x
-// lldb-check:[...]$4 = 10.5
+// lldb-check:[...]$6 = 10.5
// lldb-command:print y
-// lldb-check:[...]$5 = 20
+// lldb-check:[...]$7 = 20
// lldb-command:continue
// lldb-command:print x
-// lldb-check:[...]$4 = 11.5
+// lldb-check:[...]$8 = 11.5
// lldb-command:print y
-// lldb-check:[...]$5 = 20
+// lldb-check:[...]$9 = 20
// lldb-command:continue
#![feature(omit_gdb_pretty_printer_section)]
--- /dev/null
+// Copyright 2013-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.
+
+// min-lldb-version: 310
+
+// == Test [gdb|lldb]-[command|check] are parsed correctly ===
+// should-fail
+// compile-flags:-g
+
+// === GDB TESTS ===================================================================================
+
+// gdb-command: run
+
+// gdb-command: print x
+// gdb-check:$1 = 5
+
+// === LLDB TESTS ==================================================================================
+
+// lldb-command:run
+
+// lldb-command:print x
+// lldb-check:[...]$0 = 5
+
+fn main() {
+ let x = 1;
+
+ zzz(); // #break
+}
+
+fn zzz() {()}
+
// except according to those terms.
// min-lldb-version: 310
+// ignore-gdb // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155
// compile-flags:-g
// except according to those terms.
// min-lldb-version: 310
+// ignore-gdb // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155
// compile-flags:-g
// ignore-tidy-linelength
// min-lldb-version: 310
// ignore-gdb-version: 7.11.90 - 7.12.9
+// ignore-test // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155
// compile-flags:-g
// ignore-tidy-linelength
// ignore-lldb
+// ignore-gdb // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155
// ignore-android: FIXME(#24958)
// ignore-arm: FIXME(#24958)
// ignore-aarch64: FIXME(#24958)
// except according to those terms.
// min-lldb-version: 310
+// ignore-gdb // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155
+
// ignore-gdb-version: 7.11.90 - 7.12.9
// compile-flags:-g
// except according to those terms.
// ignore-windows
+// ignore-gdb // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155
// min-lldb-version: 310
// compile-flags:-g
// except according to those terms.
// min-lldb-version: 310
+// ignore-gdb // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155
// compile-flags:-g
--- /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.
+
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+// Add a function to shift DefIndex of registrar function
+#[cfg(cfail2)]
+fn foo() {}
+
+#[proc_macro_derive(IncrementalMacro)]
+pub fn derive(input: TokenStream) -> TokenStream {
+ #[cfg(cfail2)]
+ {
+ foo();
+ }
+
+ "".parse().unwrap()
+}
--- /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:incremental_proc_macro_aux.rs
+// ignore-stage1
+// revisions: cfail1 cfail2
+// must-compile-successfully
+
+// This test makes sure that we still find the proc-macro registrar function
+// when we compile proc-macros incrementally (see #47292).
+
+#![crate_type = "rlib"]
+
+#[macro_use]
+extern crate incremental_proc_macro_aux;
+
+#[derive(IncrementalMacro)]
+pub struct Foo {
+ x: u32
+}
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <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.
+
+// compile-flags: -Z parse-only
+
+impl <*const u8>::AssocTy {} // OK
+impl <Type as Trait>::AssocTy {} // OK
+impl <'a + Trait>::AssocTy {} // OK
+impl <<Type>::AssocTy>::AssocTy {} // OK
+
+FAIL //~ ERROR
let mut _b = 0;
let mut _ = 0; //~ ERROR expected identifier, found `_`
//~^ NOTE `_` is a wildcard pattern, not an identifier
+ //~| NOTE expected identifier
}
+++ /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.
-
-// compile-flags: -Z parse-only
-
-// This file was auto-generated using 'src/etc/generate-keyword-tests.py extern'
-
-fn main() {
- let extern = "foo"; //~ error: expected pattern, found keyword `extern`
-}
+++ /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.
-
-// compile-flags: -Z parse-only -Z continue-parse-after-error
-
-#![feature(optin_builtin_traits)]
-
-use std::marker::Send;
-
-struct TestType;
-
-impl !TestType {}
-//~^ ERROR inherent implementation can't be negated
-
-trait TestTrait {}
-
-unsafe impl !Send for TestType {}
-impl !TestTrait for TestType {}
-
-struct TestType2<T>;
-
-impl<T> !TestType2<T> {}
-//~^ ERROR inherent implementation can't be negated
-
-unsafe impl<T> !Send for TestType2<T> {}
-impl<T> !TestTrait for TestType2<T> {}
-
-fn main() {}
struct Bar;
-impl Foo + Owned for Bar {
-//~^ ERROR not a trait
-//~^^ ERROR expected one of `where` or `{`, found `Bar`
+impl Foo + Owned for Bar { //~ ERROR expected a trait, found type
}
fn main() { }
// compile-flags: -Z parse-only
fn foo<T>() where <T>::Item: ToString, T: Iterator { }
- //~^ syntax `where<T>` is reserved for future use
+//~^ ERROR generic parameters on `where` clauses are reserved for future use
fn main() {}
# Make sure we don't ICE if the linker prints a non-UTF-8 error message.
-ifdef IS_WINDOWS
-# ignore windows
+# Ignore Windows and Apple
# This does not work in its current form on windows, possibly due to
# gcc bugs or something about valid Windows paths. See issue #29151
# for more information.
-all:
+ifndef IS_WINDOWS
-else
+# This also does not work on Apple APFS due to the filesystem requiring
+# valid UTF-8 paths.
+ifneq ($(shell uname),Darwin)
# The zzz it to allow humans to tab complete or glob this thing.
bad_dir := $(TMPDIR)/zzz$$'\xff'
mkdir $(bad_dir)
mv $(TMPDIR)/liblibrary.a $(bad_dir)
LIBRARY_PATH=$(bad_dir) $(RUSTC) exec.rs 2>&1 | $(CGREP) this_symbol_not_defined
+else
+all:
+
+endif
+
+else
+all:
endif
--- /dev/null
+-include ../tools.mk
+
+# Test that hir-tree output doens't crash and includes
+# the string constant we would expect to see.
+
+all:
+ $(RUSTDOC) --test input.rs > $(TMPDIR)/output || true
+ $(CGREP) 'input.rs:17:15' < $(TMPDIR)/output
--- /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.
+
+// Test for #45868
+
+// random #![feature] to ensure that crate attrs
+// do not offset things
+/// ```rust
+/// #![feature(nll)]
+/// let x: char = 1;
+/// ```
+pub fn foo() {
+
+}
}
#[lang = "freeze"]
-trait Freeze {}
-#[allow(auto_impl)]
-impl Freeze for .. {}
+auto trait Freeze {}
trait Sized { }
#[lang = "freeze"]
-trait Freeze {}
-#[allow(auto_impl)]
-impl Freeze for .. {}
+auto trait Freeze {}
#[lang="start"]
fn start(_main: *const u8, _argc: isize, _argv: *const *const u8) -> isize { 0 }
// compile-fail/type-mismatch-same-crate-name.rs
// but deals with the case where one of the crates
// is only introduced as an indirect dependency.
-// and the type is accessed via a reexport.
+// and the type is accessed via a re-export.
// This is similar to how the error can be introduced
// when using cargo's automatic dependency resolution.
use rustc::hir;
use syntax::attr;
-declare_lint!(CRATE_NOT_OKAY, Warn, "crate not marked with #![crate_okay]");
+macro_rules! fake_lint_pass {
+ ($struct:ident, $lints:expr, $($attr:expr),*) => {
+ struct $struct;
+
+ impl LintPass for $struct {
+ fn get_lints(&self) -> LintArray {
+ $lints
+ }
+ }
-struct Pass;
+ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for $struct {
+ fn check_crate(&mut self, cx: &LateContext, krate: &hir::Crate) {
+ $(
+ if !attr::contains_name(&krate.attrs, $attr) {
+ cx.span_lint(CRATE_NOT_OKAY, krate.span,
+ &format!("crate is not marked with #![{}]", $attr));
+ }
+ )*
+ }
+ }
-impl LintPass for Pass {
- fn get_lints(&self) -> LintArray {
- lint_array!(CRATE_NOT_OKAY)
}
}
-impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
- fn check_crate(&mut self, cx: &LateContext, krate: &hir::Crate) {
- if !attr::contains_name(&krate.attrs, "crate_okay") {
- cx.span_lint(CRATE_NOT_OKAY, krate.span,
- "crate is not marked with #![crate_okay]");
- }
- }
+declare_lint!(CRATE_NOT_OKAY, Warn, "crate not marked with #![crate_okay]");
+declare_lint!(CRATE_NOT_RED, Warn, "crate not marked with #![crate_red]");
+declare_lint!(CRATE_NOT_BLUE, Warn, "crate not marked with #![crate_blue]");
+declare_lint!(CRATE_NOT_GREY, Warn, "crate not marked with #![crate_grey]");
+declare_lint!(CRATE_NOT_GREEN, Warn, "crate not marked with #![crate_green]");
+
+fake_lint_pass! {
+ PassOkay,
+ lint_array!(CRATE_NOT_OKAY), // Single lint
+ "crate_okay"
+}
+
+fake_lint_pass! {
+ PassRedBlue,
+ lint_array!(CRATE_NOT_RED, CRATE_NOT_BLUE), // Multiple lints
+ "crate_red", "crate_blue"
+}
+
+fake_lint_pass! {
+ PassGreyGreen,
+ lint_array!(CRATE_NOT_GREY, CRATE_NOT_GREEN, ), // Trailing comma
+ "crate_grey", "crate_green"
}
#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) {
- reg.register_late_lint_pass(box Pass);
+ reg.register_late_lint_pass(box PassOkay);
+ reg.register_late_lint_pass(box PassRedBlue);
+ reg.register_late_lint_pass(box PassGreyGreen);
}
#![feature(plugin, custom_attribute)]
#![plugin(lint_for_crate)]
#![crate_okay]
+#![crate_blue]
+#![crate_red]
+#![crate_grey]
+#![crate_green]
pub fn main() { }
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(allocator_api, unique)]
+#![feature(allocator_api, nonnull)]
use std::heap::{Heap, Alloc};
#![feature(optin_builtin_traits)]
auto trait Auto {}
-// Redundant but accepted until we remove it.
-#[allow(auto_impl)]
-impl Auto for .. {}
-
unsafe auto trait AutoUnsafe {}
impl !Auto for bool {}
fn take_auto_unsafe<T: AutoUnsafe>(_: T) {}
fn main() {
+ // Parse inside functions.
+ auto trait AutoInner {}
+ unsafe auto trait AutoUnsafeInner {}
+
take_auto(0);
take_auto(AutoBool(true));
take_auto_unsafe(0);
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <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.
+
+// ignore-pretty pretty-printing is unhygienic
+
+#[macro_export]
+macro_rules! m {
+ () => {
+ fn f() {} // (2)
+ g(); // (1)
+ }
+}
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <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.
+
+pub fn f() {}
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <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.
+
+#![crate_type = "lib"]
+
+extern crate my_crate;
+
+pub fn g() {} // (a)
+
+#[macro_export]
+macro_rules! unhygienic_macro {
+ () => {
+ // (1) unhygienic: depends on `my_crate` in the crate root at the invocation site.
+ ::my_crate::f();
+
+ // (2) unhygienic: defines `f` at the invocation site (in addition to the above point).
+ use my_crate::f;
+ f();
+
+ g(); // (3) unhygienic: `g` needs to be in scope at use site.
+
+ $crate::g(); // (4) hygienic: this always resolves to (a)
+ }
+}
+
+#[allow(unused)]
+fn test_unhygienic() {
+ unhygienic_macro!();
+ f(); // `f` was defined at the use site
+}
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <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.
+
+// ignore-pretty pretty-printing is unhygienic
+
+// aux-build:legacy_interaction.rs
+
+#![feature(decl_macro)]
+#[allow(unused)]
+
+extern crate legacy_interaction;
+// ^ defines
+// ```rust
+// macro_rules! m {
+// () => {
+// fn f() // (1)
+// g() // (2)
+// }
+// }
+// ```rust
+
+mod def_site {
+ // Unless this macro opts out of hygiene, it should resolve the same wherever it is invoked.
+ pub macro m2() {
+ ::legacy_interaction::m!();
+ f(); // This should resolve to (1)
+ fn g() {} // We want (2) resolve to this, not to (4)
+ }
+}
+
+mod use_site {
+ fn test() {
+ fn f() -> bool { true } // (3)
+ fn g() -> bool { true } // (4)
+
+ ::def_site::m2!();
+
+ let _: bool = f(); // This should resolve to (3)
+ let _: bool = g(); // This should resolve to (4)
+ }
+}
+
+fn main() {}
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <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.
+
+// ignore-pretty pretty-printing is unhygienic
+
+// aux-build:my_crate.rs
+// aux-build:unhygienic_example.rs
+
+#![feature(decl_macro)]
+
+extern crate unhygienic_example;
+extern crate my_crate; // (b)
+
+// Hygienic version of `unhygienic_macro`.
+pub macro hygienic_macro() {
+ fn g() {} // (c)
+ ::unhygienic_example::unhygienic_macro!();
+ // ^ Even though we invoke an unhygienic macro, `hygienic_macro` remains hygienic.
+ // In the above expansion:
+ // (1) `my_crate` always resolves to (b) regardless of invocation site.
+ // (2) The defined function `f` is only usable inside this macro definition.
+ // (3) `g` always resolves to (c) regardless of invocation site.
+ // (4) `$crate::g` remains hygienic and continues to resolve to (a).
+
+ f();
+}
+
+#[allow(unused)]
+fn test_hygienic_macro() {
+ hygienic_macro!();
+
+ fn f() {} // (d) no conflict
+ f(); // resolves to (d)
+}
+
+fn main() {}
universal_impl_trait,
fn_traits,
step_trait,
- unboxed_closures
+ unboxed_closures,
+ copy_closures,
+ clone_closures
)]
//! Derived from: <https://raw.githubusercontent.com/quickfur/dcal/master/dcal.d>.
}
}
-/// Wrapper for zero-sized closures.
-// HACK(eddyb) Only needed because closures can't implement Copy.
-struct Fn0<F>(std::marker::PhantomData<F>);
-
-impl<F> Copy for Fn0<F> {}
-impl<F> Clone for Fn0<F> {
- fn clone(&self) -> Self { *self }
-}
-
-impl<F: FnOnce<A>, A> FnOnce<A> for Fn0<F> {
- type Output = F::Output;
-
- extern "rust-call" fn call_once(self, args: A) -> Self::Output {
- let f = unsafe { std::mem::uninitialized::<F>() };
- f.call_once(args)
- }
-}
-
-impl<F: FnMut<A>, A> FnMut<A> for Fn0<F> {
- extern "rust-call" fn call_mut(&mut self, args: A) -> Self::Output {
- let mut f = unsafe { std::mem::uninitialized::<F>() };
- f.call_mut(args)
- }
-}
-
-trait AsFn0<A>: Sized {
- fn copyable(self) -> Fn0<Self>;
-}
-
-impl<F: FnMut<A>, A> AsFn0<A> for F {
- fn copyable(self) -> Fn0<Self> {
- assert_eq!(std::mem::size_of::<F>(), 0);
- Fn0(std::marker::PhantomData)
- }
-}
-
/// GroupBy implementation.
struct GroupBy<It: Iterator, F> {
it: std::iter::Peekable<It>,
}
impl<It, F> Clone for GroupBy<It, F>
-where It: Iterator + Clone, It::Item: Clone, F: Clone {
- fn clone(&self) -> GroupBy<It, F> {
+where
+ It: Iterator + Clone,
+ It::Item: Clone,
+ F: Clone,
+{
+ fn clone(&self) -> Self {
GroupBy {
it: self.it.clone(),
- f: self.f.clone()
+ f: self.f.clone(),
}
}
}
}
trait IteratorExt: Iterator + Sized {
- fn group_by<G, F>(self, f: F) -> GroupBy<Self, Fn0<F>>
- where F: FnMut(&Self::Item) -> G,
+ fn group_by<G, F>(self, f: F) -> GroupBy<Self, F>
+ where F: Clone + FnMut(&Self::Item) -> G,
G: Eq
{
- GroupBy {
- it: self.peekable(),
- f: f.copyable(),
- }
+ GroupBy { it: self.peekable(), f }
}
fn join(mut self, sep: &str) -> String
fn dates_in_year(year: i32) -> impl Iterator<Item=NaiveDate>+Clone {
InGroup {
it: NaiveDate::from_ymd(year, 1, 1)..,
- f: (|d: &NaiveDate| d.year()).copyable(),
+ f: |d: &NaiveDate| d.year(),
g: year
}
}
// Don't fail if we encounter a NonZero<*T> where T is an unsized type
-#![feature(unique)]
-
-use std::ptr::Unique;
+use std::ptr::NonNull;
fn main() {
let mut a = [0u8; 5];
- let b: Option<Unique<[u8]>> = Some(Unique::from(&mut a));
+ let b: Option<NonNull<[u8]>> = Some(NonNull::from(&mut a));
match b {
Some(_) => println!("Got `Some`"),
None => panic!("Unexpected `None`"),
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-pub trait Paramters { type SelfRef; }
+pub trait Parameters { type SelfRef; }
struct RP<'a> { _marker: std::marker::PhantomData<&'a ()> }
struct BP;
-impl<'a> Paramters for RP<'a> { type SelfRef = &'a X<RP<'a>>; }
-impl Paramters for BP { type SelfRef = Box<X<BP>>; }
+impl<'a> Parameters for RP<'a> { type SelfRef = &'a X<RP<'a>>; }
+impl Parameters for BP { type SelfRef = Box<X<BP>>; }
pub struct Y;
-pub enum X<P: Paramters> {
+pub enum X<P: Parameters> {
Nothing,
SameAgain(P::SelfRef, Y)
}
#![feature(optin_builtin_traits)]
-trait NotSame {}
-#[allow(auto_impl)]
-impl NotSame for .. {}
+auto trait NotSame {}
+
impl<A> !NotSame for (A, A) {}
trait OneOfEach {}
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <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.
+
+// Issue 33903:
+// Built-in indexing should be used even when the index is not
+// trivially an integer
+// Only built-in indexing can be used in constant expresssions
+
+const FOO: i32 = [12, 34][0 + 1];
+
+fn main() {}
+
--- /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(conservative_impl_trait)]
+fn foo() -> impl Copy {
+ foo
+}
+fn main() {
+ 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.
+
+#![feature(specialization)]
+
+trait Iterate<'a> {
+ type Ty: Valid;
+ fn iterate(self);
+}
+impl<'a, T> Iterate<'a> for T where T: Check {
+ default type Ty = ();
+ default fn iterate(self) {}
+}
+
+trait Check {}
+impl<'a, T> Check for T where <T as Iterate<'a>>::Ty: Valid {}
+
+trait Valid {}
+
+fn main() {
+ Iterate::iterate(0);
+}
--- /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.
+
+struct Zst;
+
+fn main() {
+ unsafe { ::std::ptr::write_volatile(1 as *mut Zst, Zst) }
+}
--- /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(associated_consts)]
+
+impl A for i32 {
+ type Foo = u32;
+}
+impl B for u32 {
+ const BAR: i32 = 0;
+}
+
+trait A {
+ type Foo: B;
+}
+
+trait B {
+ const BAR: i32;
+}
+
+fn generic<T: A>() {
+ // This panics if the universal function call syntax is used as well
+ println!("{}", T::Foo::BAR);
+}
+
+fn main() {}
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <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.
+
+struct A;
+
+impl A {
+ fn take_mutably(&mut self) {}
+}
+
+fn identity<T>(t: T) -> T {
+ t
+}
+
+// Issue 46095
+// Built-in indexing should be used even when the index is not
+// trivially an integer
+// Overloaded indexing would cause wrapped to be borrowed mutably
+
+fn main() {
+ let mut a1 = A;
+ let mut a2 = A;
+
+ let wrapped = [&mut a1, &mut a2];
+
+ {
+ wrapped[0 + 1 - 1].take_mutably();
+ }
+
+ {
+ wrapped[identity(0)].take_mutably();
+ }
+}
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <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 CURSOR_PARTITION_LABEL: &'static [u8] = b"partition";
+const CURSOR_EVENT_TYPE_LABEL: &'static [u8] = b"event_type";
+const BYTE_PATTERN: &'static [u8; 5] = b"hello";
+
+fn match_slice(x: &[u8]) -> u32 {
+ match x {
+ CURSOR_PARTITION_LABEL => 0,
+ CURSOR_EVENT_TYPE_LABEL => 1,
+ _ => 2,
+ }
+}
+
+fn match_array(x: &[u8; 5]) -> bool {
+ match x {
+ BYTE_PATTERN => true,
+ _ => false
+ }
+}
+
+fn main() {
+ assert_eq!(match_slice(b"abcde"), 2);
+ assert_eq!(match_slice(b"event_type"), 1);
+ assert_eq!(match_slice(b"partition"), 0);
+
+ assert_eq!(match_array(b"hello"), true);
+ assert_eq!(match_array(b"hella"), false);
+}
+++ /dev/null
-// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <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.
-
-pub fn foo() {}
+++ /dev/null
-// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <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.
-
-pub mod innest;
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <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.
+
+pub fn foo() {}
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <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.
+
+pub mod innest;
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <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:xcrate.rs
+
+#![feature(extern_in_paths)]
+
+use extern::xcrate::Z;
+
+fn f() {
+ use extern::xcrate;
+ use extern::xcrate as ycrate;
+ let s = xcrate::S;
+ assert_eq!(format!("{:?}", s), "S");
+ let z = ycrate::Z;
+ assert_eq!(format!("{:?}", z), "Z");
+}
+
+fn main() {
+ let s = extern::xcrate::S;
+ assert_eq!(format!("{:?}", s), "S");
+ let z = Z;
+ assert_eq!(format!("{:?}", z), "Z");
+}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// Tests that the reexports of `FnOnce` et al from the prelude work.
+// Tests that the re-exports of `FnOnce` et al from the prelude work.
// pretty-expanded FIXME #23616
--- /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 QUERY = 'String';
+
+const EXPECTED = {
+ 'others': [
+ { 'path': 'std::string', 'name': 'String' },
+ { 'path': 'std::ffi', 'name': 'OsString' },
+ { 'path': 'std::ffi', 'name': 'CString' },
+ ],
+ 'in_args': [
+ { 'path': 'std::str', 'name': 'eq' },
+ ],
+ 'returned': [
+ { 'path': 'std::string::String', 'name': '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.
+
+const QUERY = 'enum:Option';
+
+const EXPECTED = {
+ 'others': [
+ { 'path': 'std::option', 'name': 'Option' },
+ ],
+};
--- /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 QUERY = 'fn:forget';
+
+const EXPECTED = {
+ 'others': [
+ { 'path': 'std::mem', 'name': 'forget' },
+ { 'path': 'std::fmt', 'name': 'format' },
+ ],
+};
--- /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 QUERY = 'from_u';
+
+const EXPECTED = {
+ 'others': [
+ { 'path': 'std::char', 'name': 'from_u32' },
+ { 'path': 'std::str', 'name': 'from_utf8' },
+ { 'path': 'std::string::String', 'name': 'from_utf8' },
+ { 'path': 'std::i32', 'name': 'from_unsigned' },
+ { 'path': 'std::i128', 'name': 'from_unsigned' },
+ ],
+};
--- /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 QUERY = 'macro:print';
+
+const EXPECTED = {
+ 'others': [
+ { 'path': 'std', 'name': 'print' },
+ { 'path': 'std', 'name': 'eprint' },
+ { 'path': 'std', 'name': 'println' },
+ { 'path': 'std', 'name': 'eprintln' },
+ ],
+};
--- /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 QUERY = 'String::from_ut';
+
+const EXPECTED = {
+ 'others': [
+ { 'path': 'std::string::String', 'name': 'from_utf8' },
+ { 'path': 'std::string::String', 'name': 'from_utf8' },
+ { 'path': 'std::string::String', 'name': 'from_utf8_lossy' },
+ { 'path': 'std::string::String', 'name': 'from_utf16_lossy' },
+ { 'path': 'std::string::String', 'name': 'from_utf8_unchecked' },
+ ],
+};
--- /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 QUERY = 'struct:Vec';
+
+const EXPECTED = {
+ 'others': [
+ { 'path': 'std::vec', 'name': 'Vec' },
+ { 'path': 'std::collections', 'name': 'VecDeque' },
+ { 'path': 'alloc::raw_vec', 'name': 'RawVec' },
+ ],
+};
pub mod bar {
use std::marker;
- pub trait Bar {}
-
- #[allow(auto_impl)]
- impl Bar for .. {}
+ pub auto trait Bar {}
pub trait Foo {
fn foo(&self) {}
#![feature(optin_builtin_traits)]
-pub trait AnOibit {}
-
-#[allow(auto_impl)]
-impl AnOibit for .. {}
+pub auto trait AnOibit {}
#![feature(optin_builtin_traits)]
-pub trait AnOibit {}
-
-#[allow(auto_impl)]
-impl AnOibit for .. {}
+pub auto trait AnOibit {}
pub struct Foo<T> { field: T }
--- /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.
+
+pub trait MyTrait {
+ /// docs for my_trait_method
+ fn my_trait_method() {}
+}
+
+pub struct MyStruct;
+
+impl MyTrait for MyStruct {}
pub struct Wobble;
- // these should only be shown if they're reexported correctly
+ // these should only be shown if they're re-exported correctly
impl Qux for ::Foo {}
impl Qux for Wobble {}
impl ::Bark for Wobble {}
--- /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:impl-inline-without-trait.rs
+// build-aux-docs
+// ignore-cross-compile
+
+#![crate_name = "foo"]
+
+extern crate impl_inline_without_trait;
+
+// @has 'foo/struct.MyStruct.html'
+// @has - '//*[@id="method.my_trait_method"]' 'fn my_trait_method()'
+// @has - '//*[@class="docblock"]' 'docs for my_trait_method'
+pub use impl_inline_without_trait::MyStruct;
impl SomeTrait for SomeStruct {
// deliberately multi-line impl
}
+
+pub trait AnotherTrait {}
+
+// @has foo/trait.AnotherTrait.html '//a/@href' '../src/foo/issue-43893.rs.html#29'
+impl<T> AnotherTrait for T {}
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <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(universal_impl_trait)]
+pub fn ice(f: impl Fn()) {}
--- /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(decl_macro)]
+
+#![crate_name = "foo"]
+
+use std::vec;
+
+// @has 'foo/index.html'
+// @!has - '//*[@id="macros"]' 'Macros'
+// @!has - '//a/@href' 'macro.vec.html'
+// @!has 'foo/macro.vec.html'
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <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.
+
+// @has issue_47197_blank_line_in_doc_block/fn.whose_woods_these_are_i_think_i_know.html
+
+/**
+* snow
+
+* ice
+*/
+pub fn whose_woods_these_are_i_think_i_know() {}
--- /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.
+
+// no-prefer-dynamic
+#![feature(proc_macro)]
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::{TokenStream, TokenTree, TokenNode, Span};
+
+fn lit_span(tt: TokenTree) -> (Span, String) {
+ use TokenNode::*;
+ match tt.kind {
+ Literal(..) | Group(..) => (tt.span, tt.to_string().trim().into()),
+ _ => panic!("expected a literal in token tree, got: {:?}", tt)
+ }
+}
+
+#[proc_macro]
+pub fn parent_source_spans(input: TokenStream) -> TokenStream {
+ let mut tokens = input.into_iter();
+ let (sp1, str1) = lit_span(tokens.next().expect("first string"));
+ let _ = tokens.next();
+ let (sp2, str2) = lit_span(tokens.next().expect("second string"));
+
+ sp1.error(format!("first final: {}", str1)).emit();
+ sp2.error(format!("second final: {}", str2)).emit();
+
+ if let (Some(p1), Some(p2)) = (sp1.parent(), sp2.parent()) {
+ p1.error(format!("first parent: {}", str1)).emit();
+ p2.error(format!("second parent: {}", str2)).emit();
+
+ if let (Some(gp1), Some(gp2)) = (p1.parent(), p2.parent()) {
+ gp1.error(format!("first grandparent: {}", str1)).emit();
+ gp2.error(format!("second grandparent: {}", str2)).emit();
+ }
+ }
+
+ sp1.source().error(format!("first source: {}", str1)).emit();
+ sp2.source().error(format!("second source: {}", str2)).emit();
+
+ "ok".parse().unwrap()
+}
--- /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:parent-source-spans.rs
+// ignore-stage1
+
+#![feature(proc_macro, decl_macro)]
+
+extern crate parent_source_spans;
+
+use parent_source_spans::parent_source_spans;
+
+macro one($a:expr, $b:expr) {
+ two!($a, $b);
+ //~^ ERROR first parent: "hello"
+ //~| ERROR second parent: "world"
+}
+
+macro two($a:expr, $b:expr) {
+ three!($a, $b);
+ //~^ ERROR first final: "hello"
+ //~| ERROR second final: "world"
+ //~| ERROR first final: "yay"
+ //~| ERROR second final: "rust"
+}
+
+// forwarding tokens directly doesn't create a new source chain
+macro three($($tokens:tt)*) {
+ four!($($tokens)*);
+}
+
+macro four($($tokens:tt)*) {
+ parent_source_spans!($($tokens)*);
+}
+
+fn main() {
+ one!("hello", "world");
+ //~^ ERROR first grandparent: "hello"
+ //~| ERROR second grandparent: "world"
+ //~| ERROR first source: "hello"
+ //~| ERROR second source: "world"
+
+ two!("yay", "rust");
+ //~^ ERROR first parent: "yay"
+ //~| ERROR second parent: "rust"
+ //~| ERROR first source: "yay"
+ //~| ERROR second source: "rust"
+
+ three!("hip", "hop");
+ //~^ ERROR first final: "hip"
+ //~| ERROR second final: "hop"
+ //~| ERROR first source: "hip"
+ //~| ERROR second source: "hop"
+}
--- /dev/null
+error: first final: "hello"
+ --> $DIR/parent-source-spans.rs:27:12
+ |
+27 | three!($a, $b);
+ | ^^
+...
+44 | one!("hello", "world");
+ | ----------------------- in this macro invocation
+
+error: second final: "world"
+ --> $DIR/parent-source-spans.rs:27:16
+ |
+27 | three!($a, $b);
+ | ^^
+...
+44 | one!("hello", "world");
+ | ----------------------- in this macro invocation
+
+error: first parent: "hello"
+ --> $DIR/parent-source-spans.rs:21:5
+ |
+21 | two!($a, $b);
+ | ^^^^^^^^^^^^^
+...
+44 | one!("hello", "world");
+ | ----------------------- in this macro invocation
+
+error: second parent: "world"
+ --> $DIR/parent-source-spans.rs:21:5
+ |
+21 | two!($a, $b);
+ | ^^^^^^^^^^^^^
+...
+44 | one!("hello", "world");
+ | ----------------------- in this macro invocation
+
+error: first grandparent: "hello"
+ --> $DIR/parent-source-spans.rs:44:5
+ |
+44 | one!("hello", "world");
+ | ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: second grandparent: "world"
+ --> $DIR/parent-source-spans.rs:44:5
+ |
+44 | one!("hello", "world");
+ | ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: first source: "hello"
+ --> $DIR/parent-source-spans.rs:44:5
+ |
+44 | one!("hello", "world");
+ | ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: second source: "world"
+ --> $DIR/parent-source-spans.rs:44:5
+ |
+44 | one!("hello", "world");
+ | ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: first final: "yay"
+ --> $DIR/parent-source-spans.rs:27:12
+ |
+27 | three!($a, $b);
+ | ^^
+...
+50 | two!("yay", "rust");
+ | -------------------- in this macro invocation
+
+error: second final: "rust"
+ --> $DIR/parent-source-spans.rs:27:16
+ |
+27 | three!($a, $b);
+ | ^^
+...
+50 | two!("yay", "rust");
+ | -------------------- in this macro invocation
+
+error: first parent: "yay"
+ --> $DIR/parent-source-spans.rs:50:5
+ |
+50 | two!("yay", "rust");
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: second parent: "rust"
+ --> $DIR/parent-source-spans.rs:50:5
+ |
+50 | two!("yay", "rust");
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: first source: "yay"
+ --> $DIR/parent-source-spans.rs:50:5
+ |
+50 | two!("yay", "rust");
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: second source: "rust"
+ --> $DIR/parent-source-spans.rs:50:5
+ |
+50 | two!("yay", "rust");
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: first final: "hip"
+ --> $DIR/parent-source-spans.rs:56:12
+ |
+56 | three!("hip", "hop");
+ | ^^^^^
+
+error: second final: "hop"
+ --> $DIR/parent-source-spans.rs:56:19
+ |
+56 | three!("hip", "hop");
+ | ^^^^^
+
+error: first source: "hip"
+ --> $DIR/parent-source-spans.rs:56:12
+ |
+56 | three!("hip", "hop");
+ | ^^^^^
+
+error: second source: "hop"
+ --> $DIR/parent-source-spans.rs:56:19
+ |
+56 | three!("hip", "hop");
+ | ^^^^^
+
+error: aborting due to 18 previous errors
+
--> $DIR/resolve-error.rs:62:5
|
62 | FooWithLongNama!();
- | ^^^^^^^^^^^^^^^ help: you could try the macro: `FooWithLongNam!`
+ | ^^^^^^^^^^^^^^^ help: you could try the macro: `FooWithLongNam`
error: cannot find macro `attr_proc_macra!` in this scope
--> $DIR/resolve-error.rs:65:5
|
65 | attr_proc_macra!();
- | ^^^^^^^^^^^^^^^ help: you could try the macro: `attr_proc_mac!`
+ | ^^^^^^^^^^^^^^^ help: you could try the macro: `attr_proc_mac`
error: cannot find macro `Dlona!` in this scope
--> $DIR/resolve-error.rs:68:5
--> $DIR/resolve-error.rs:71:5
|
71 | bang_proc_macrp!();
- | ^^^^^^^^^^^^^^^ help: you could try the macro: `bang_proc_macro!`
+ | ^^^^^^^^^^^^^^^ help: you could try the macro: `bang_proc_macro`
error: aborting due to 10 previous errors
| |
| expected signature of `for<'r, 's> fn(&'r (), &'s ()) -> _`
|
- = note: required by `f1`
+note: required by `f1`
+ --> $DIR/anonymous-higher-ranked-lifetime.rs:26:1
+ |
+26 | fn f1<F>(_: F) where F: Fn(&(), &()) {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0631]: type mismatch in closure arguments
--> $DIR/anonymous-higher-ranked-lifetime.rs:13:5
| |
| expected signature of `for<'a, 'r> fn(&'a (), &'r ()) -> _`
|
- = note: required by `f2`
+note: required by `f2`
+ --> $DIR/anonymous-higher-ranked-lifetime.rs:27:1
+ |
+27 | fn f2<F>(_: F) where F: for<'a> Fn(&'a (), &()) {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0631]: type mismatch in closure arguments
--> $DIR/anonymous-higher-ranked-lifetime.rs:14:5
| |
| expected signature of `for<'r> fn(&(), &'r ()) -> _`
|
- = note: required by `f3`
+note: required by `f3`
+ --> $DIR/anonymous-higher-ranked-lifetime.rs:28:1
+ |
+28 | fn f3<'a, F>(_: F) where F: Fn(&'a (), &()) {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0631]: type mismatch in closure arguments
--> $DIR/anonymous-higher-ranked-lifetime.rs:15:5
| |
| expected signature of `for<'s, 'r> fn(&'s (), &'r ()) -> _`
|
- = note: required by `f4`
+note: required by `f4`
+ --> $DIR/anonymous-higher-ranked-lifetime.rs:29:1
+ |
+29 | fn f4<F>(_: F) where F: for<'r> Fn(&(), &'r ()) {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0631]: type mismatch in closure arguments
--> $DIR/anonymous-higher-ranked-lifetime.rs:16:5
| |
| expected signature of `for<'r> fn(&'r (), &'r ()) -> _`
|
- = note: required by `f5`
+note: required by `f5`
+ --> $DIR/anonymous-higher-ranked-lifetime.rs:30:1
+ |
+30 | fn f5<F>(_: F) where F: for<'r> Fn(&'r (), &'r ()) {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0631]: type mismatch in closure arguments
--> $DIR/anonymous-higher-ranked-lifetime.rs:17:5
| |
| expected signature of `for<'r> fn(&'r (), std::boxed::Box<for<'s> std::ops::Fn(&'s ()) + 'static>) -> _`
|
- = note: required by `g1`
+note: required by `g1`
+ --> $DIR/anonymous-higher-ranked-lifetime.rs:33:1
+ |
+33 | fn g1<F>(_: F) where F: Fn(&(), Box<Fn(&())>) {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0631]: type mismatch in closure arguments
--> $DIR/anonymous-higher-ranked-lifetime.rs:18:5
| |
| expected signature of `for<'r> fn(&'r (), for<'s> fn(&'s ())) -> _`
|
- = note: required by `g2`
+note: required by `g2`
+ --> $DIR/anonymous-higher-ranked-lifetime.rs:34:1
+ |
+34 | fn g2<F>(_: F) where F: Fn(&(), fn(&())) {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0631]: type mismatch in closure arguments
--> $DIR/anonymous-higher-ranked-lifetime.rs:19:5
| |
| expected signature of `for<'s> fn(&'s (), std::boxed::Box<for<'r> std::ops::Fn(&'r ()) + 'static>) -> _`
|
- = note: required by `g3`
+note: required by `g3`
+ --> $DIR/anonymous-higher-ranked-lifetime.rs:35:1
+ |
+35 | fn g3<F>(_: F) where F: for<'s> Fn(&'s (), Box<Fn(&())>) {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0631]: type mismatch in closure arguments
--> $DIR/anonymous-higher-ranked-lifetime.rs:20:5
| |
| expected signature of `for<'s> fn(&'s (), for<'r> fn(&'r ())) -> _`
|
- = note: required by `g4`
+note: required by `g4`
+ --> $DIR/anonymous-higher-ranked-lifetime.rs:36:1
+ |
+36 | fn g4<F>(_: F) where F: Fn(&(), for<'r> fn(&'r ())) {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0631]: type mismatch in closure arguments
--> $DIR/anonymous-higher-ranked-lifetime.rs:21:5
| |
| expected signature of `for<'r, 's> fn(&'r (), std::boxed::Box<for<'t0> std::ops::Fn(&'t0 ()) + 'static>, &'s (), for<'t0, 't1> fn(&'t0 (), &'t1 ())) -> _`
|
- = note: required by `h1`
+note: required by `h1`
+ --> $DIR/anonymous-higher-ranked-lifetime.rs:39:1
+ |
+39 | fn h1<F>(_: F) where F: Fn(&(), Box<Fn(&())>, &(), fn(&(), &())) {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0631]: type mismatch in closure arguments
--> $DIR/anonymous-higher-ranked-lifetime.rs:22:5
| |
| expected signature of `for<'r, 't0> fn(&'r (), std::boxed::Box<for<'s> std::ops::Fn(&'s ()) + 'static>, &'t0 (), for<'s, 't1> fn(&'s (), &'t1 ())) -> _`
|
- = note: required by `h2`
+note: required by `h2`
+ --> $DIR/anonymous-higher-ranked-lifetime.rs:40:1
+ |
+40 | fn h2<F>(_: F) where F: for<'t0> Fn(&(), Box<Fn(&())>, &'t0 (), fn(&(), &())) {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 11 previous errors
--- /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.
+
+//compile-flags: -Z emit-end-regions -Z borrowck=compare
+
+fn foo(_x: u32) {
+ _x = 4;
+ //~^ ERROR cannot assign to immutable argument `_x` (Mir)
+ //~^^ ERROR cannot assign twice to immutable variable `_x` (Ast)
+}
+
+fn main() {}
+
--- /dev/null
+error[E0384]: cannot assign twice to immutable variable `_x` (Ast)
+ --> $DIR/immutable-arg.rs:14:5
+ |
+13 | fn foo(_x: u32) {
+ | -- first assignment to `_x`
+14 | _x = 4;
+ | ^^^^^^ cannot assign twice to immutable variable
+
+error[E0384]: cannot assign to immutable argument `_x` (Mir)
+ --> $DIR/immutable-arg.rs:14:5
+ |
+13 | fn foo(_x: u32) {
+ | -- argument not declared as `mut`
+14 | _x = 4;
+ | ^^^^^^ cannot assign to immutable argument
+
+error: aborting due to 2 previous errors
+
--> $DIR/deref-suggestion.rs:18:9
|
18 | foo(s); //~ ERROR mismatched types
- | ^ expected struct `std::string::String`, found reference
+ | ^
+ | |
+ | expected struct `std::string::String`, found reference
+ | help: try using a conversion method: `s.to_string()`
|
= note: expected type `std::string::String`
found type `&std::string::String`
- = help: here are some functions which might fulfill your needs:
- - .escape_debug()
- - .escape_default()
- - .escape_unicode()
- - .to_ascii_lowercase()
- - .to_ascii_uppercase()
error[E0308]: mismatched types
--> $DIR/deref-suggestion.rs:23:10
<i8 as Foo<u32>>
<i8 as Foo<u64>>
<i8 as Foo<bool>>
- = note: required by `Foo::bar`
+note: required by `Foo::bar`
+ --> $DIR/issue-39802-show-5-trait-impls.rs:12:5
+ |
+12 | fn bar(&self){}
+ | ^^^^^^^^^^^^^
error[E0277]: the trait bound `u8: Foo<i32>` is not satisfied
--> $DIR/issue-39802-show-5-trait-impls.rs:35:5
<u8 as Foo<u32>>
<u8 as Foo<u64>>
<u8 as Foo<bool>>
- = note: required by `Foo::bar`
+note: required by `Foo::bar`
+ --> $DIR/issue-39802-show-5-trait-impls.rs:12:5
+ |
+12 | fn bar(&self){}
+ | ^^^^^^^^^^^^^
error[E0277]: the trait bound `bool: Foo<i32>` is not satisfied
--> $DIR/issue-39802-show-5-trait-impls.rs:36:5
<bool as Foo<u32>>
<bool as Foo<u64>>
and 2 others
- = note: required by `Foo::bar`
+note: required by `Foo::bar`
+ --> $DIR/issue-39802-show-5-trait-impls.rs:12:5
+ |
+12 | fn bar(&self){}
+ | ^^^^^^^^^^^^^
error: aborting due to 3 previous errors
--- /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() {
+ let x = 3;
+ match x {
+ 1 | 2 || 3 => (), //~ ERROR unexpected token `||` after pattern
+ _ => (),
+ }
+}
--- /dev/null
+error: unexpected token `||` after pattern
+ --> $DIR/multiple-pattern-typo.rs:14:15
+ |
+14 | 1 | 2 || 3 => (), //~ ERROR unexpected token `||` after pattern
+ | ^^ help: use a single `|` to specify multiple patterns: `|`
+
+error: aborting due to previous error
+
= note: required because it appears within the type `C`
= note: required because it appears within the type `B`
= note: required because it appears within the type `A`
- = note: required by `is_send`
+note: required by `is_send`
+ --> $DIR/recursion_limit.rs:41:1
+ |
+41 | fn is_send<T:Send>() { }
+ | ^^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error
62 | let x: &Bottom = &t; //~ ERROR mismatched types
| ^^ deref recursion limit reached
|
- = help: consider adding a `#[recursion_limit="20"]` attribute to your crate
+ = help: consider adding a `#![recursion_limit="20"]` attribute to your crate
error[E0055]: reached the recursion limit while auto-dereferencing I
|
- = help: consider adding a `#[recursion_limit="20"]` attribute to your crate
+ = help: consider adding a `#![recursion_limit="20"]` attribute to your crate
error[E0308]: mismatched types
--> $DIR/recursion_limit_deref.rs:62:22
|
21 | a as isize; //~ ERROR casting
| ^^^^^^^^^^
+ |
+ = help: cast through a raw pointer first
error[E0606]: casting `&[i32]` as `i16` is invalid
--> $DIR/fat-ptr-cast.rs:22:5
|
22 | a as i16; //~ ERROR casting `&[i32]` as `i16` is invalid
| ^^^^^^^^
+ |
+ = help: cast through a raw pointer first
error[E0606]: casting `&[i32]` as `u32` is invalid
--> $DIR/fat-ptr-cast.rs:23:5
|
23 | a as u32; //~ ERROR casting `&[i32]` as `u32` is invalid
| ^^^^^^^^
+ |
+ = help: cast through a raw pointer first
error[E0605]: non-primitive cast: `std::boxed::Box<[i32]>` as `usize`
--> $DIR/fat-ptr-cast.rs:24:5
-error: msp430-interrupt ABI is experimental and subject to change (see issue #38487)
+error[E0658]: msp430-interrupt ABI is experimental and subject to change (see issue #38487)
--> $DIR/feature-gate-abi-msp430-interrupt.rs:14:1
|
14 | extern "msp430-interrupt" fn foo() {}
-error: intrinsics are subject to change
+error[E0658]: intrinsics are subject to change
--> $DIR/feature-gate-abi.rs:19:1
|
19 | extern "rust-intrinsic" fn f1() {} //~ ERROR intrinsics are subject to change
|
= help: add #![feature(intrinsics)] to the crate attributes to enable
-error: platform intrinsics are experimental and possibly buggy (see issue #27731)
+error[E0658]: platform intrinsics are experimental and possibly buggy (see issue #27731)
--> $DIR/feature-gate-abi.rs:20:1
|
20 | extern "platform-intrinsic" fn f2() {} //~ ERROR platform intrinsics are experimental
|
= help: add #![feature(platform_intrinsics)] to the crate attributes to enable
-error: vectorcall is experimental and subject to change
+error[E0658]: vectorcall is experimental and subject to change
--> $DIR/feature-gate-abi.rs:21:1
|
21 | extern "vectorcall" fn f3() {} //~ ERROR vectorcall is experimental and subject to change
|
= help: add #![feature(abi_vectorcall)] to the crate attributes to enable
-error: rust-call ABI is subject to change (see issue #29625)
+error[E0658]: rust-call ABI is subject to change (see issue #29625)
--> $DIR/feature-gate-abi.rs:22:1
|
22 | extern "rust-call" fn f4() {} //~ ERROR rust-call ABI is subject to change
|
= help: add #![feature(unboxed_closures)] to the crate attributes to enable
-error: msp430-interrupt ABI is experimental and subject to change (see issue #38487)
+error[E0658]: msp430-interrupt ABI is experimental and subject to change (see issue #38487)
--> $DIR/feature-gate-abi.rs:23:1
|
23 | extern "msp430-interrupt" fn f5() {} //~ ERROR msp430-interrupt ABI is experimental
|
= help: add #![feature(abi_msp430_interrupt)] to the crate attributes to enable
-error: PTX ABIs are experimental and subject to change
+error[E0658]: PTX ABIs are experimental and subject to change
--> $DIR/feature-gate-abi.rs:24:1
|
24 | extern "ptx-kernel" fn f6() {} //~ ERROR PTX ABIs are experimental and subject to change
|
= help: add #![feature(abi_ptx)] to the crate attributes to enable
-error: x86-interrupt ABI is experimental and subject to change (see issue #40180)
+error[E0658]: x86-interrupt ABI is experimental and subject to change (see issue #40180)
--> $DIR/feature-gate-abi.rs:25:1
|
25 | extern "x86-interrupt" fn f7() {} //~ ERROR x86-interrupt ABI is experimental
|
= help: add #![feature(abi_x86_interrupt)] to the crate attributes to enable
-error: thiscall is experimental and subject to change
+error[E0658]: thiscall is experimental and subject to change
--> $DIR/feature-gate-abi.rs:26:1
|
26 | extern "thiscall" fn f8() {} //~ ERROR thiscall is experimental and subject to change
|
= help: add #![feature(abi_thiscall)] to the crate attributes to enable
-error: intrinsics are subject to change
+error[E0658]: intrinsics are subject to change
--> $DIR/feature-gate-abi.rs:30:5
|
30 | extern "rust-intrinsic" fn m1(); //~ ERROR intrinsics are subject to change
|
= help: add #![feature(intrinsics)] to the crate attributes to enable
-error: platform intrinsics are experimental and possibly buggy (see issue #27731)
+error[E0658]: platform intrinsics are experimental and possibly buggy (see issue #27731)
--> $DIR/feature-gate-abi.rs:31:5
|
31 | extern "platform-intrinsic" fn m2(); //~ ERROR platform intrinsics are experimental
|
= help: add #![feature(platform_intrinsics)] to the crate attributes to enable
-error: vectorcall is experimental and subject to change
+error[E0658]: vectorcall is experimental and subject to change
--> $DIR/feature-gate-abi.rs:32:5
|
32 | extern "vectorcall" fn m3(); //~ ERROR vectorcall is experimental and subject to change
|
= help: add #![feature(abi_vectorcall)] to the crate attributes to enable
-error: rust-call ABI is subject to change (see issue #29625)
+error[E0658]: rust-call ABI is subject to change (see issue #29625)
--> $DIR/feature-gate-abi.rs:33:5
|
33 | extern "rust-call" fn m4(); //~ ERROR rust-call ABI is subject to change
|
= help: add #![feature(unboxed_closures)] to the crate attributes to enable
-error: msp430-interrupt ABI is experimental and subject to change (see issue #38487)
+error[E0658]: msp430-interrupt ABI is experimental and subject to change (see issue #38487)
--> $DIR/feature-gate-abi.rs:34:5
|
34 | extern "msp430-interrupt" fn m5(); //~ ERROR msp430-interrupt ABI is experimental
|
= help: add #![feature(abi_msp430_interrupt)] to the crate attributes to enable
-error: PTX ABIs are experimental and subject to change
+error[E0658]: PTX ABIs are experimental and subject to change
--> $DIR/feature-gate-abi.rs:35:5
|
35 | extern "ptx-kernel" fn m6(); //~ ERROR PTX ABIs are experimental and subject to change
|
= help: add #![feature(abi_ptx)] to the crate attributes to enable
-error: x86-interrupt ABI is experimental and subject to change (see issue #40180)
+error[E0658]: x86-interrupt ABI is experimental and subject to change (see issue #40180)
--> $DIR/feature-gate-abi.rs:36:5
|
36 | extern "x86-interrupt" fn m7(); //~ ERROR x86-interrupt ABI is experimental
|
= help: add #![feature(abi_x86_interrupt)] to the crate attributes to enable
-error: thiscall is experimental and subject to change
+error[E0658]: thiscall is experimental and subject to change
--> $DIR/feature-gate-abi.rs:37:5
|
37 | extern "thiscall" fn m8(); //~ ERROR thiscall is experimental and subject to change
|
= help: add #![feature(abi_thiscall)] to the crate attributes to enable
-error: intrinsics are subject to change
+error[E0658]: intrinsics are subject to change
--> $DIR/feature-gate-abi.rs:39:5
|
39 | extern "rust-intrinsic" fn dm1() {} //~ ERROR intrinsics are subject to change
|
= help: add #![feature(intrinsics)] to the crate attributes to enable
-error: platform intrinsics are experimental and possibly buggy (see issue #27731)
+error[E0658]: platform intrinsics are experimental and possibly buggy (see issue #27731)
--> $DIR/feature-gate-abi.rs:40:5
|
40 | extern "platform-intrinsic" fn dm2() {} //~ ERROR platform intrinsics are experimental
|
= help: add #![feature(platform_intrinsics)] to the crate attributes to enable
-error: vectorcall is experimental and subject to change
+error[E0658]: vectorcall is experimental and subject to change
--> $DIR/feature-gate-abi.rs:41:5
|
41 | extern "vectorcall" fn dm3() {} //~ ERROR vectorcall is experimental and subject to change
|
= help: add #![feature(abi_vectorcall)] to the crate attributes to enable
-error: rust-call ABI is subject to change (see issue #29625)
+error[E0658]: rust-call ABI is subject to change (see issue #29625)
--> $DIR/feature-gate-abi.rs:42:5
|
42 | extern "rust-call" fn dm4() {} //~ ERROR rust-call ABI is subject to change
|
= help: add #![feature(unboxed_closures)] to the crate attributes to enable
-error: msp430-interrupt ABI is experimental and subject to change (see issue #38487)
+error[E0658]: msp430-interrupt ABI is experimental and subject to change (see issue #38487)
--> $DIR/feature-gate-abi.rs:43:5
|
43 | extern "msp430-interrupt" fn dm5() {} //~ ERROR msp430-interrupt ABI is experimental
|
= help: add #![feature(abi_msp430_interrupt)] to the crate attributes to enable
-error: PTX ABIs are experimental and subject to change
+error[E0658]: PTX ABIs are experimental and subject to change
--> $DIR/feature-gate-abi.rs:44:5
|
44 | extern "ptx-kernel" fn dm6() {} //~ ERROR PTX ABIs are experimental and subject to change
|
= help: add #![feature(abi_ptx)] to the crate attributes to enable
-error: x86-interrupt ABI is experimental and subject to change (see issue #40180)
+error[E0658]: x86-interrupt ABI is experimental and subject to change (see issue #40180)
--> $DIR/feature-gate-abi.rs:45:5
|
45 | extern "x86-interrupt" fn dm7() {} //~ ERROR x86-interrupt ABI is experimental
|
= help: add #![feature(abi_x86_interrupt)] to the crate attributes to enable
-error: thiscall is experimental and subject to change
+error[E0658]: thiscall is experimental and subject to change
--> $DIR/feature-gate-abi.rs:46:5
|
46 | extern "thiscall" fn dm8() {} //~ ERROR thiscall is experimental and subject to change
|
= help: add #![feature(abi_thiscall)] to the crate attributes to enable
-error: intrinsics are subject to change
+error[E0658]: intrinsics are subject to change
--> $DIR/feature-gate-abi.rs:53:5
|
53 | extern "rust-intrinsic" fn m1() {} //~ ERROR intrinsics are subject to change
|
= help: add #![feature(intrinsics)] to the crate attributes to enable
-error: platform intrinsics are experimental and possibly buggy (see issue #27731)
+error[E0658]: platform intrinsics are experimental and possibly buggy (see issue #27731)
--> $DIR/feature-gate-abi.rs:54:5
|
54 | extern "platform-intrinsic" fn m2() {} //~ ERROR platform intrinsics are experimental
|
= help: add #![feature(platform_intrinsics)] to the crate attributes to enable
-error: vectorcall is experimental and subject to change
+error[E0658]: vectorcall is experimental and subject to change
--> $DIR/feature-gate-abi.rs:55:5
|
55 | extern "vectorcall" fn m3() {} //~ ERROR vectorcall is experimental and subject to change
|
= help: add #![feature(abi_vectorcall)] to the crate attributes to enable
-error: rust-call ABI is subject to change (see issue #29625)
+error[E0658]: rust-call ABI is subject to change (see issue #29625)
--> $DIR/feature-gate-abi.rs:56:5
|
56 | extern "rust-call" fn m4() {} //~ ERROR rust-call ABI is subject to change
|
= help: add #![feature(unboxed_closures)] to the crate attributes to enable
-error: msp430-interrupt ABI is experimental and subject to change (see issue #38487)
+error[E0658]: msp430-interrupt ABI is experimental and subject to change (see issue #38487)
--> $DIR/feature-gate-abi.rs:57:5
|
57 | extern "msp430-interrupt" fn m5() {} //~ ERROR msp430-interrupt ABI is experimental
|
= help: add #![feature(abi_msp430_interrupt)] to the crate attributes to enable
-error: PTX ABIs are experimental and subject to change
+error[E0658]: PTX ABIs are experimental and subject to change
--> $DIR/feature-gate-abi.rs:58:5
|
58 | extern "ptx-kernel" fn m6() {} //~ ERROR PTX ABIs are experimental and subject to change
|
= help: add #![feature(abi_ptx)] to the crate attributes to enable
-error: x86-interrupt ABI is experimental and subject to change (see issue #40180)
+error[E0658]: x86-interrupt ABI is experimental and subject to change (see issue #40180)
--> $DIR/feature-gate-abi.rs:59:5
|
59 | extern "x86-interrupt" fn m7() {} //~ ERROR x86-interrupt ABI is experimental
|
= help: add #![feature(abi_x86_interrupt)] to the crate attributes to enable
-error: thiscall is experimental and subject to change
+error[E0658]: thiscall is experimental and subject to change
--> $DIR/feature-gate-abi.rs:60:5
|
60 | extern "thiscall" fn m8() {} //~ ERROR thiscall is experimental and subject to change
|
= help: add #![feature(abi_thiscall)] to the crate attributes to enable
-error: intrinsics are subject to change
+error[E0658]: intrinsics are subject to change
--> $DIR/feature-gate-abi.rs:65:5
|
65 | extern "rust-intrinsic" fn im1() {} //~ ERROR intrinsics are subject to change
|
= help: add #![feature(intrinsics)] to the crate attributes to enable
-error: platform intrinsics are experimental and possibly buggy (see issue #27731)
+error[E0658]: platform intrinsics are experimental and possibly buggy (see issue #27731)
--> $DIR/feature-gate-abi.rs:66:5
|
66 | extern "platform-intrinsic" fn im2() {} //~ ERROR platform intrinsics are experimental
|
= help: add #![feature(platform_intrinsics)] to the crate attributes to enable
-error: vectorcall is experimental and subject to change
+error[E0658]: vectorcall is experimental and subject to change
--> $DIR/feature-gate-abi.rs:67:5
|
67 | extern "vectorcall" fn im3() {} //~ ERROR vectorcall is experimental and subject to change
|
= help: add #![feature(abi_vectorcall)] to the crate attributes to enable
-error: rust-call ABI is subject to change (see issue #29625)
+error[E0658]: rust-call ABI is subject to change (see issue #29625)
--> $DIR/feature-gate-abi.rs:68:5
|
68 | extern "rust-call" fn im4() {} //~ ERROR rust-call ABI is subject to change
|
= help: add #![feature(unboxed_closures)] to the crate attributes to enable
-error: msp430-interrupt ABI is experimental and subject to change (see issue #38487)
+error[E0658]: msp430-interrupt ABI is experimental and subject to change (see issue #38487)
--> $DIR/feature-gate-abi.rs:69:5
|
69 | extern "msp430-interrupt" fn im5() {} //~ ERROR msp430-interrupt ABI is experimental
|
= help: add #![feature(abi_msp430_interrupt)] to the crate attributes to enable
-error: PTX ABIs are experimental and subject to change
+error[E0658]: PTX ABIs are experimental and subject to change
--> $DIR/feature-gate-abi.rs:70:5
|
70 | extern "ptx-kernel" fn im6() {} //~ ERROR PTX ABIs are experimental and subject to change
|
= help: add #![feature(abi_ptx)] to the crate attributes to enable
-error: x86-interrupt ABI is experimental and subject to change (see issue #40180)
+error[E0658]: x86-interrupt ABI is experimental and subject to change (see issue #40180)
--> $DIR/feature-gate-abi.rs:71:5
|
71 | extern "x86-interrupt" fn im7() {} //~ ERROR x86-interrupt ABI is experimental
|
= help: add #![feature(abi_x86_interrupt)] to the crate attributes to enable
-error: thiscall is experimental and subject to change
+error[E0658]: thiscall is experimental and subject to change
--> $DIR/feature-gate-abi.rs:72:5
|
72 | extern "thiscall" fn im8() {} //~ ERROR thiscall is experimental and subject to change
|
= help: add #![feature(abi_thiscall)] to the crate attributes to enable
-error: intrinsics are subject to change
+error[E0658]: intrinsics are subject to change
--> $DIR/feature-gate-abi.rs:76:11
|
76 | type A1 = extern "rust-intrinsic" fn(); //~ ERROR intrinsics are subject to change
|
= help: add #![feature(intrinsics)] to the crate attributes to enable
-error: platform intrinsics are experimental and possibly buggy (see issue #27731)
+error[E0658]: platform intrinsics are experimental and possibly buggy (see issue #27731)
--> $DIR/feature-gate-abi.rs:77:11
|
77 | type A2 = extern "platform-intrinsic" fn(); //~ ERROR platform intrinsics are experimental
|
= help: add #![feature(platform_intrinsics)] to the crate attributes to enable
-error: vectorcall is experimental and subject to change
+error[E0658]: vectorcall is experimental and subject to change
--> $DIR/feature-gate-abi.rs:78:11
|
78 | type A3 = extern "vectorcall" fn(); //~ ERROR vectorcall is experimental and subject to change
|
= help: add #![feature(abi_vectorcall)] to the crate attributes to enable
-error: rust-call ABI is subject to change (see issue #29625)
+error[E0658]: rust-call ABI is subject to change (see issue #29625)
--> $DIR/feature-gate-abi.rs:79:11
|
79 | type A4 = extern "rust-call" fn(); //~ ERROR rust-call ABI is subject to change
|
= help: add #![feature(unboxed_closures)] to the crate attributes to enable
-error: msp430-interrupt ABI is experimental and subject to change (see issue #38487)
+error[E0658]: msp430-interrupt ABI is experimental and subject to change (see issue #38487)
--> $DIR/feature-gate-abi.rs:80:11
|
80 | type A5 = extern "msp430-interrupt" fn(); //~ ERROR msp430-interrupt ABI is experimental
|
= help: add #![feature(abi_msp430_interrupt)] to the crate attributes to enable
-error: PTX ABIs are experimental and subject to change
+error[E0658]: PTX ABIs are experimental and subject to change
--> $DIR/feature-gate-abi.rs:81:11
|
81 | type A6 = extern "ptx-kernel" fn (); //~ ERROR PTX ABIs are experimental and subject to change
|
= help: add #![feature(abi_ptx)] to the crate attributes to enable
-error: x86-interrupt ABI is experimental and subject to change (see issue #40180)
+error[E0658]: x86-interrupt ABI is experimental and subject to change (see issue #40180)
--> $DIR/feature-gate-abi.rs:82:11
|
82 | type A7 = extern "x86-interrupt" fn(); //~ ERROR x86-interrupt ABI is experimental
|
= help: add #![feature(abi_x86_interrupt)] to the crate attributes to enable
-error: thiscall is experimental and subject to change
+error[E0658]: thiscall is experimental and subject to change
--> $DIR/feature-gate-abi.rs:83:11
|
83 | type A8 = extern "thiscall" fn(); //~ ERROR thiscall is experimental and subject to change
|
= help: add #![feature(abi_thiscall)] to the crate attributes to enable
-error: intrinsics are subject to change
+error[E0658]: intrinsics are subject to change
--> $DIR/feature-gate-abi.rs:86:1
|
86 | extern "rust-intrinsic" {} //~ ERROR intrinsics are subject to change
|
= help: add #![feature(intrinsics)] to the crate attributes to enable
-error: platform intrinsics are experimental and possibly buggy (see issue #27731)
+error[E0658]: platform intrinsics are experimental and possibly buggy (see issue #27731)
--> $DIR/feature-gate-abi.rs:87:1
|
87 | extern "platform-intrinsic" {} //~ ERROR platform intrinsics are experimental
|
= help: add #![feature(platform_intrinsics)] to the crate attributes to enable
-error: vectorcall is experimental and subject to change
+error[E0658]: vectorcall is experimental and subject to change
--> $DIR/feature-gate-abi.rs:88:1
|
88 | extern "vectorcall" {} //~ ERROR vectorcall is experimental and subject to change
|
= help: add #![feature(abi_vectorcall)] to the crate attributes to enable
-error: rust-call ABI is subject to change (see issue #29625)
+error[E0658]: rust-call ABI is subject to change (see issue #29625)
--> $DIR/feature-gate-abi.rs:89:1
|
89 | extern "rust-call" {} //~ ERROR rust-call ABI is subject to change
|
= help: add #![feature(unboxed_closures)] to the crate attributes to enable
-error: msp430-interrupt ABI is experimental and subject to change (see issue #38487)
+error[E0658]: msp430-interrupt ABI is experimental and subject to change (see issue #38487)
--> $DIR/feature-gate-abi.rs:90:1
|
90 | extern "msp430-interrupt" {} //~ ERROR msp430-interrupt ABI is experimental
|
= help: add #![feature(abi_msp430_interrupt)] to the crate attributes to enable
-error: PTX ABIs are experimental and subject to change
+error[E0658]: PTX ABIs are experimental and subject to change
--> $DIR/feature-gate-abi.rs:91:1
|
91 | extern "ptx-kernel" {} //~ ERROR PTX ABIs are experimental and subject to change
|
= help: add #![feature(abi_ptx)] to the crate attributes to enable
-error: x86-interrupt ABI is experimental and subject to change (see issue #40180)
+error[E0658]: x86-interrupt ABI is experimental and subject to change (see issue #40180)
--> $DIR/feature-gate-abi.rs:92:1
|
92 | extern "x86-interrupt" {} //~ ERROR x86-interrupt ABI is experimental
|
= help: add #![feature(abi_x86_interrupt)] to the crate attributes to enable
-error: thiscall is experimental and subject to change
+error[E0658]: thiscall is experimental and subject to change
--> $DIR/feature-gate-abi.rs:93:1
|
93 | extern "thiscall" {} //~ ERROR thiscall is experimental and subject to change
-error: unadjusted ABI is an implementation detail and perma-unstable
+error[E0658]: unadjusted ABI is an implementation detail and perma-unstable
--> $DIR/feature-gate-abi_unadjusted.rs:11:1
|
11 | / extern "unadjusted" fn foo() {
-error: multiple-element slice matches anywhere but at the end of a slice (e.g. `[0, ..xs, 0]`) are experimental (see issue #23121)
+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
|
18 | [ xs.., 4, 5 ] => {} //~ ERROR multiple-element slice matches
|
= help: add #![feature(advanced_slice_patterns)] to the crate attributes to enable
-error: multiple-element slice matches anywhere but at the end of a slice (e.g. `[0, ..xs, 0]`) are experimental (see issue #23121)
+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
|
19 | [ 1, xs.., 5 ] => {} //~ ERROR multiple-element slice matches
-error: the `#[default_lib_allocator]` attribute is an experimental feature
+error[E0658]: the `#[default_lib_allocator]` attribute is an experimental feature
--> $DIR/feature-gate-allocator_internals.rs:11:1
|
11 | #![default_lib_allocator] //~ ERROR: attribute is an experimental feature
-error: allow_internal_unsafe side-steps the unsafe_code lint
+error[E0658]: allow_internal_unsafe side-steps the unsafe_code lint
--> $DIR/feature-gate-allow-internal-unsafe-nested-macro.rs:18:9
|
18 | #[allow_internal_unsafe] //~ ERROR allow_internal_unsafe side-steps
-error: allow_internal_unstable side-steps feature gating and stability checks
+error[E0658]: allow_internal_unstable side-steps feature gating and stability checks
--> $DIR/feature-gate-allow-internal-unstable-nested-macro.rs:18:9
|
18 | #[allow_internal_unstable] //~ ERROR allow_internal_unstable side-steps
-error: allow_internal_unstable side-steps feature gating and stability checks
+error[E0658]: allow_internal_unstable side-steps feature gating and stability checks
--> $DIR/feature-gate-allow-internal-unstable-struct.rs:14:1
|
14 | #[allow_internal_unstable] //~ ERROR allow_internal_unstable side-steps
-error: allow_internal_unstable side-steps feature gating and stability checks
+error[E0658]: allow_internal_unstable side-steps feature gating and stability checks
--> $DIR/feature-gate-allow-internal-unstable.rs:13:1
|
13 | #[allow_internal_unstable] //~ ERROR allow_internal_unstable side-steps
-error: allow_fail attribute is currently unstable (see issue #42219)
+error[E0658]: allow_fail attribute is currently unstable (see issue #42219)
--> $DIR/feature-gate-allow_fail.rs:13:1
|
13 | #[allow_fail] //~ ERROR allow_fail attribute is currently unstable
-error: arbitrary `self` types are unstable (see issue #44874)
+error[E0658]: arbitrary `self` types are unstable (see issue #44874)
--> $DIR/feature-gate-arbitrary-self-types.rs:14:18
|
14 | fn foo(self: Rc<Box<Self>>); //~ ERROR arbitrary `self` types are unstable
= help: add #![feature(arbitrary_self_types)] to the crate attributes to enable
= help: consider changing to `self`, `&self`, `&mut self`, or `self: Box<Self>`
-error: arbitrary `self` types are unstable (see issue #44874)
+error[E0658]: arbitrary `self` types are unstable (see issue #44874)
--> $DIR/feature-gate-arbitrary-self-types.rs:20:18
|
20 | fn foo(self: Rc<Box<Self>>) {} //~ ERROR arbitrary `self` types are unstable
= help: add #![feature(arbitrary_self_types)] to the crate attributes to enable
= help: consider changing to `self`, `&self`, `&mut self`, or `self: Box<Self>`
-error: arbitrary `self` types are unstable (see issue #44874)
+error[E0658]: arbitrary `self` types are unstable (see issue #44874)
--> $DIR/feature-gate-arbitrary-self-types.rs:24:18
|
24 | fn bar(self: Box<Rc<Self>>) {} //~ ERROR arbitrary `self` types are unstable
-error: raw pointer `self` is unstable (see issue #44874)
+error[E0658]: raw pointer `self` is unstable (see issue #44874)
--> $DIR/feature-gate-arbitrary_self_types-raw-pointer.rs:19:18
|
19 | fn bar(self: *const Self);
= help: add #![feature(arbitrary_self_types)] to the crate attributes to enable
= help: consider changing to `self`, `&self`, `&mut self`, or `self: Box<Self>`
-error: raw pointer `self` is unstable (see issue #44874)
+error[E0658]: raw pointer `self` is unstable (see issue #44874)
--> $DIR/feature-gate-arbitrary_self_types-raw-pointer.rs:14:18
|
14 | fn foo(self: *const Self) {}
= help: add #![feature(arbitrary_self_types)] to the crate attributes to enable
= help: consider changing to `self`, `&self`, `&mut self`, or `self: Box<Self>`
-error: raw pointer `self` is unstable (see issue #44874)
+error[E0658]: raw pointer `self` is unstable (see issue #44874)
--> $DIR/feature-gate-arbitrary_self_types-raw-pointer.rs:24:18
|
24 | fn bar(self: *const Self) {}
-error: inline assembly is not stable enough for use and is subject to change (see issue #29722)
+error[E0658]: inline assembly is not stable enough for use and is subject to change (see issue #29722)
--> $DIR/feature-gate-asm.rs:13:9
|
13 | asm!(""); //~ ERROR inline assembly is not stable enough
-error: inline assembly is not stable enough for use and is subject to change (see issue #29722)
+error[E0658]: inline assembly is not stable enough for use and is subject to change (see issue #29722)
--> $DIR/feature-gate-asm2.rs:15:24
|
15 | println!("{}", asm!("")); //~ ERROR inline assembly is not stable
-error: associated type defaults are unstable (see issue #29661)
+error[E0658]: associated type defaults are unstable (see issue #29661)
--> $DIR/feature-gate-assoc-type-defaults.rs:14:5
|
14 | type Bar = u8; //~ ERROR associated type defaults are unstable
-error: box expression syntax is experimental; you can call `Box::new` instead. (see issue #27779)
+error[E0658]: box expression syntax is experimental; you can call `Box::new` instead. (see issue #27779)
--> $DIR/feature-gate-box-expr.rs:22:13
|
22 | let x = box 'c'; //~ ERROR box expression syntax is experimental
-error: box pattern syntax is experimental (see issue #29641)
+error[E0658]: box pattern syntax is experimental (see issue #29641)
--> $DIR/feature-gate-box_patterns.rs:12:9
|
12 | let box x = Box::new('c'); //~ ERROR box pattern syntax is experimental
-error: box expression syntax is experimental; you can call `Box::new` instead. (see issue #27779)
+error[E0658]: box expression syntax is experimental; you can call `Box::new` instead. (see issue #27779)
--> $DIR/feature-gate-box_syntax.rs:14:13
|
14 | let x = box 3;
-error: `catch` expression is experimental (see issue #31436)
+error[E0658]: `catch` expression is experimental (see issue #31436)
--> $DIR/feature-gate-catch_expr.rs:12:24
|
12 | let catch_result = do catch { //~ ERROR `catch` expression is experimental
-error: `cfg(target_feature)` is experimental and subject to change (see issue #29717)
+error[E0658]: `cfg(target_feature)` is experimental and subject to change (see issue #29717)
--> $DIR/feature-gate-cfg-target-feature.rs:12:12
|
12 | #[cfg_attr(target_feature = "x", x)] //~ ERROR `cfg(target_feature)` is experimental
|
= help: add #![feature(cfg_target_feature)] to the crate attributes to enable
-error: `cfg(target_feature)` is experimental and subject to change (see issue #29717)
+error[E0658]: `cfg(target_feature)` is experimental and subject to change (see issue #29717)
--> $DIR/feature-gate-cfg-target-feature.rs:11:7
|
11 | #[cfg(target_feature = "x")] //~ ERROR `cfg(target_feature)` is experimental
|
= help: add #![feature(cfg_target_feature)] to the crate attributes to enable
-error: `cfg(target_feature)` is experimental and subject to change (see issue #29717)
+error[E0658]: `cfg(target_feature)` is experimental and subject to change (see issue #29717)
--> $DIR/feature-gate-cfg-target-feature.rs:15:19
|
15 | #[cfg(not(any(all(target_feature = "x"))))] //~ ERROR `cfg(target_feature)` is experimental
|
= help: add #![feature(cfg_target_feature)] to the crate attributes to enable
-error: `cfg(target_feature)` is experimental and subject to change (see issue #29717)
+error[E0658]: `cfg(target_feature)` is experimental and subject to change (see issue #29717)
--> $DIR/feature-gate-cfg-target-feature.rs:19:10
|
19 | cfg!(target_feature = "x");
-error: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
--> $DIR/feature-gate-cfg-target-has-atomic.rs:23:7
|
23 | #[cfg(target_has_atomic = "8")]
|
= help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable
-error: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
--> $DIR/feature-gate-cfg-target-has-atomic.rs:29:7
|
29 | #[cfg(target_has_atomic = "8")]
|
= help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable
-error: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
--> $DIR/feature-gate-cfg-target-has-atomic.rs:34:7
|
34 | #[cfg(target_has_atomic = "16")]
|
= help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable
-error: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
--> $DIR/feature-gate-cfg-target-has-atomic.rs:39:7
|
39 | #[cfg(target_has_atomic = "16")]
|
= help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable
-error: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
--> $DIR/feature-gate-cfg-target-has-atomic.rs:44:7
|
44 | #[cfg(target_has_atomic = "32")]
|
= help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable
-error: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
--> $DIR/feature-gate-cfg-target-has-atomic.rs:49:7
|
49 | #[cfg(target_has_atomic = "32")]
|
= help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable
-error: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
--> $DIR/feature-gate-cfg-target-has-atomic.rs:54:7
|
54 | #[cfg(target_has_atomic = "64")]
|
= help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable
-error: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
--> $DIR/feature-gate-cfg-target-has-atomic.rs:59:7
|
59 | #[cfg(target_has_atomic = "64")]
|
= help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable
-error: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
--> $DIR/feature-gate-cfg-target-has-atomic.rs:64:7
|
64 | #[cfg(target_has_atomic = "ptr")]
|
= help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable
-error: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
--> $DIR/feature-gate-cfg-target-has-atomic.rs:69:7
|
69 | #[cfg(target_has_atomic = "ptr")]
|
= help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable
-error: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
--> $DIR/feature-gate-cfg-target-has-atomic.rs:76:10
|
76 | cfg!(target_has_atomic = "8");
|
= help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable
-error: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
--> $DIR/feature-gate-cfg-target-has-atomic.rs:78:10
|
78 | cfg!(target_has_atomic = "16");
|
= help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable
-error: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
--> $DIR/feature-gate-cfg-target-has-atomic.rs:80:10
|
80 | cfg!(target_has_atomic = "32");
|
= help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable
-error: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
--> $DIR/feature-gate-cfg-target-has-atomic.rs:82:10
|
82 | cfg!(target_has_atomic = "64");
|
= help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable
-error: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
--> $DIR/feature-gate-cfg-target-has-atomic.rs:84:10
|
84 | cfg!(target_has_atomic = "ptr");
-error: `cfg(target_thread_local)` is experimental and subject to change (see issue #29594)
+error[E0658]: `cfg(target_thread_local)` is experimental and subject to change (see issue #29594)
--> $DIR/feature-gate-cfg-target-thread-local.rs:19:16
|
19 | #[cfg_attr(target_thread_local, thread_local)]
-error: `cfg(target_vendor)` is experimental and subject to change (see issue #29718)
+error[E0658]: `cfg(target_vendor)` is experimental and subject to change (see issue #29718)
--> $DIR/feature-gate-cfg-target-vendor.rs:12:12
|
12 | #[cfg_attr(target_vendor = "x", x)] //~ ERROR `cfg(target_vendor)` is experimental
|
= help: add #![feature(cfg_target_vendor)] to the crate attributes to enable
-error: `cfg(target_vendor)` is experimental and subject to change (see issue #29718)
+error[E0658]: `cfg(target_vendor)` is experimental and subject to change (see issue #29718)
--> $DIR/feature-gate-cfg-target-vendor.rs:11:7
|
11 | #[cfg(target_vendor = "x")] //~ ERROR `cfg(target_vendor)` is experimental
|
= help: add #![feature(cfg_target_vendor)] to the crate attributes to enable
-error: `cfg(target_vendor)` is experimental and subject to change (see issue #29718)
+error[E0658]: `cfg(target_vendor)` is experimental and subject to change (see issue #29718)
--> $DIR/feature-gate-cfg-target-vendor.rs:15:19
|
15 | #[cfg(not(any(all(target_vendor = "x"))))] //~ ERROR `cfg(target_vendor)` is experimental
|
= help: add #![feature(cfg_target_vendor)] to the crate attributes to enable
-error: `cfg(target_vendor)` is experimental and subject to change (see issue #29718)
+error[E0658]: `cfg(target_vendor)` is experimental and subject to change (see issue #29718)
--> $DIR/feature-gate-cfg-target-vendor.rs:19:10
|
19 | cfg!(target_vendor = "x");
-error: the `#[compiler_builtins]` attribute is used to identify the `compiler_builtins` crate which contains compiler-rt intrinsics and will never be stable
+error[E0658]: the `#[compiler_builtins]` attribute is used to identify the `compiler_builtins` crate which contains compiler-rt intrinsics and will never be stable
--> $DIR/feature-gate-compiler-builtins.rs:11:1
|
11 | #![compiler_builtins] //~ ERROR the `#[compiler_builtins]` attribute is
-error: `concat_idents` is not stable enough for use and is subject to change (see issue #29599)
+error[E0658]: `concat_idents` is not stable enough for use and is subject to change (see issue #29599)
--> $DIR/feature-gate-concat_idents.rs:15:13
|
15 | let a = concat_idents!(X, Y_1); //~ ERROR `concat_idents` is not stable
|
= help: add #![feature(concat_idents)] to the crate attributes to enable
-error: `concat_idents` is not stable enough for use and is subject to change (see issue #29599)
+error[E0658]: `concat_idents` is not stable enough for use and is subject to change (see issue #29599)
--> $DIR/feature-gate-concat_idents.rs:16:13
|
16 | let b = concat_idents!(X, Y_2); //~ ERROR `concat_idents` is not stable
-error: `concat_idents` is not stable enough for use and is subject to change (see issue #29599)
+error[E0658]: `concat_idents` is not stable enough for use and is subject to change (see issue #29599)
--> $DIR/feature-gate-concat_idents2.rs:14:5
|
14 | concat_idents!(a, b); //~ ERROR `concat_idents` is not stable enough
-error: `concat_idents` is not stable enough for use and is subject to change (see issue #29599)
+error[E0658]: `concat_idents` is not stable enough for use and is subject to change (see issue #29599)
--> $DIR/feature-gate-concat_idents3.rs:17:20
|
17 | assert_eq!(10, concat_idents!(X, Y_1)); //~ ERROR `concat_idents` is not stable
|
= help: add #![feature(concat_idents)] to the crate attributes to enable
-error: `concat_idents` is not stable enough for use and is subject to change (see issue #29599)
+error[E0658]: `concat_idents` is not stable enough for use and is subject to change (see issue #29599)
--> $DIR/feature-gate-concat_idents3.rs:18:20
|
18 | assert_eq!(20, concat_idents!(X, Y_2)); //~ ERROR `concat_idents` is not stable
-error: `impl Trait` in return position is experimental (see issue #34511)
+error[E0658]: `impl Trait` in return position is experimental (see issue #34511)
--> $DIR/feature-gate-conservative_impl_trait.rs:11:13
|
11 | fn foo() -> impl Fn() { || {} }
27 | const fn foo() -> u32 { 0 } //~ ERROR const fn is unstable
| ^^^^^ trait fns cannot be const
-error: const fn is unstable (see issue #24111)
+error[E0658]: const fn is unstable (see issue #24111)
--> $DIR/feature-gate-const_fn.rs:13:1
|
13 | const fn foo() -> usize { 0 } //~ ERROR const fn is unstable
|
= help: add #![feature(const_fn)] to the crate attributes to enable
-error: const fn is unstable (see issue #24111)
+error[E0658]: const fn is unstable (see issue #24111)
--> $DIR/feature-gate-const_fn.rs:16:5
|
16 | const fn foo() -> u32; //~ ERROR const fn is unstable
|
= help: add #![feature(const_fn)] to the crate attributes to enable
-error: const fn is unstable (see issue #24111)
+error[E0658]: const fn is unstable (see issue #24111)
--> $DIR/feature-gate-const_fn.rs:18:5
|
18 | const fn bar() -> u32 { 0 } //~ ERROR const fn is unstable
|
= help: add #![feature(const_fn)] to the crate attributes to enable
-error: const fn is unstable (see issue #24111)
+error[E0658]: const fn is unstable (see issue #24111)
--> $DIR/feature-gate-const_fn.rs:23:5
|
23 | const fn baz() -> u32 { 0 } //~ ERROR const fn is unstable
|
= help: add #![feature(const_fn)] to the crate attributes to enable
-error: const fn is unstable (see issue #24111)
+error[E0658]: const fn is unstable (see issue #24111)
--> $DIR/feature-gate-const_fn.rs:27:5
|
27 | const fn foo() -> u32 { 0 } //~ ERROR const fn is unstable
-error: `crate` in paths is experimental (see issue #45477)
+error[E0658]: `crate` in paths is experimental (see issue #45477)
--> $DIR/feature-gate-crate_in_paths.rs:14:15
|
14 | let _ = ::crate::S; //~ ERROR `crate` in paths is experimental
-error: `crate` visibility modifier is experimental (see issue #45388)
+error[E0658]: `crate` visibility modifier is experimental (see issue #45388)
--> $DIR/feature-gate-crate_visibility_modifier.rs:11:1
|
11 | crate struct Bender { //~ ERROR `crate` visibility modifier is experimental
-error: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
--> $DIR/feature-gate-custom_attribute.rs:17:1
|
17 | #[fake_attr] //~ ERROR attribute `fake_attr` is currently unknown
|
= help: add #![feature(custom_attribute)] to the crate attributes to enable
-error: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
--> $DIR/feature-gate-custom_attribute.rs:18:1
|
18 | #[fake_attr(100)] //~ ERROR attribute `fake_attr` is currently unknown
|
= help: add #![feature(custom_attribute)] to the crate attributes to enable
-error: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
--> $DIR/feature-gate-custom_attribute.rs:19:1
|
19 | #[fake_attr(1, 2, 3)] //~ ERROR attribute `fake_attr` is currently unknown
|
= help: add #![feature(custom_attribute)] to the crate attributes to enable
-error: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
--> $DIR/feature-gate-custom_attribute.rs:20:1
|
20 | #[fake_attr("hello")] //~ ERROR attribute `fake_attr` is currently unknown
|
= help: add #![feature(custom_attribute)] to the crate attributes to enable
-error: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
--> $DIR/feature-gate-custom_attribute.rs:21:1
|
21 | #[fake_attr(name = "hello")] //~ ERROR attribute `fake_attr` is currently unknown
|
= help: add #![feature(custom_attribute)] to the crate attributes to enable
-error: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
--> $DIR/feature-gate-custom_attribute.rs:22:1
|
22 | #[fake_attr(1, "hi", key = 12, true, false)] //~ ERROR attribute `fake_attr` is currently unknown
|
= help: add #![feature(custom_attribute)] to the crate attributes to enable
-error: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
--> $DIR/feature-gate-custom_attribute.rs:23:1
|
23 | #[fake_attr(key = "hello", val = 10)] //~ ERROR attribute `fake_attr` is currently unknown
|
= help: add #![feature(custom_attribute)] to the crate attributes to enable
-error: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
--> $DIR/feature-gate-custom_attribute.rs:24:1
|
24 | #[fake_attr(key("hello"), val(10))] //~ ERROR attribute `fake_attr` is currently unknown
|
= help: add #![feature(custom_attribute)] to the crate attributes to enable
-error: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
--> $DIR/feature-gate-custom_attribute.rs:25:1
|
25 | #[fake_attr(enabled = true, disabled = false)] //~ ERROR attribute `fake_attr` is currently unknown
|
= help: add #![feature(custom_attribute)] to the crate attributes to enable
-error: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
--> $DIR/feature-gate-custom_attribute.rs:26:1
|
26 | #[fake_attr(true)] //~ ERROR attribute `fake_attr` is currently unknown
|
= help: add #![feature(custom_attribute)] to the crate attributes to enable
-error: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
--> $DIR/feature-gate-custom_attribute.rs:27:1
|
27 | #[fake_attr(pi = 3.14159)] //~ ERROR attribute `fake_attr` is currently unknown
|
= help: add #![feature(custom_attribute)] to the crate attributes to enable
-error: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
--> $DIR/feature-gate-custom_attribute.rs:28:1
|
28 | #[fake_attr(b"hi")] //~ ERROR attribute `fake_attr` is currently unknown
|
= help: add #![feature(custom_attribute)] to the crate attributes to enable
-error: The attribute `fake_doc` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `fake_doc` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
--> $DIR/feature-gate-custom_attribute.rs:29:1
|
29 | #[fake_doc(r"doc")] //~ ERROR attribute `fake_doc` is currently unknown
-error: The attribute `lt_struct` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `lt_struct` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
--> $DIR/feature-gate-custom_attribute2.rs:23:13
|
23 | struct StLt<#[lt_struct] 'a>(&'a u32);
|
= help: add #![feature(custom_attribute)] to the crate attributes to enable
-error: The attribute `ty_struct` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `ty_struct` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
--> $DIR/feature-gate-custom_attribute2.rs:25:13
|
25 | struct StTy<#[ty_struct] I>(I);
|
= help: add #![feature(custom_attribute)] to the crate attributes to enable
-error: The attribute `lt_enum` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `lt_enum` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
--> $DIR/feature-gate-custom_attribute2.rs:28:11
|
28 | enum EnLt<#[lt_enum] 'b> { A(&'b u32), B }
|
= help: add #![feature(custom_attribute)] to the crate attributes to enable
-error: The attribute `ty_enum` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `ty_enum` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
--> $DIR/feature-gate-custom_attribute2.rs:30:11
|
30 | enum EnTy<#[ty_enum] J> { A(J), B }
|
= help: add #![feature(custom_attribute)] to the crate attributes to enable
-error: The attribute `lt_trait` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `lt_trait` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
--> $DIR/feature-gate-custom_attribute2.rs:33:12
|
33 | trait TrLt<#[lt_trait] 'c> { fn foo(&self, _: &'c [u32]) -> &'c u32; }
|
= help: add #![feature(custom_attribute)] to the crate attributes to enable
-error: The attribute `ty_trait` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `ty_trait` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
--> $DIR/feature-gate-custom_attribute2.rs:35:12
|
35 | trait TrTy<#[ty_trait] K> { fn foo(&self, _: K); }
|
= help: add #![feature(custom_attribute)] to the crate attributes to enable
-error: The attribute `lt_type` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `lt_type` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
--> $DIR/feature-gate-custom_attribute2.rs:38:11
|
38 | type TyLt<#[lt_type] 'd> = &'d u32;
|
= help: add #![feature(custom_attribute)] to the crate attributes to enable
-error: The attribute `ty_type` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `ty_type` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
--> $DIR/feature-gate-custom_attribute2.rs:40:11
|
40 | type TyTy<#[ty_type] L> = (L, );
|
= help: add #![feature(custom_attribute)] to the crate attributes to enable
-error: The attribute `lt_inherent` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `lt_inherent` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
--> $DIR/feature-gate-custom_attribute2.rs:43:6
|
43 | impl<#[lt_inherent] 'e> StLt<'e> { }
|
= help: add #![feature(custom_attribute)] to the crate attributes to enable
-error: The attribute `ty_inherent` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `ty_inherent` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
--> $DIR/feature-gate-custom_attribute2.rs:45:6
|
45 | impl<#[ty_inherent] M> StTy<M> { }
|
= help: add #![feature(custom_attribute)] to the crate attributes to enable
-error: The attribute `lt_impl_for` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `lt_impl_for` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
--> $DIR/feature-gate-custom_attribute2.rs:48:6
|
48 | impl<#[lt_impl_for] 'f> TrLt<'f> for StLt<'f> {
|
= help: add #![feature(custom_attribute)] to the crate attributes to enable
-error: The attribute `ty_impl_for` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `ty_impl_for` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
--> $DIR/feature-gate-custom_attribute2.rs:52:6
|
52 | impl<#[ty_impl_for] N> TrTy<N> for StTy<N> {
|
= help: add #![feature(custom_attribute)] to the crate attributes to enable
-error: The attribute `lt_fn` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `lt_fn` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
--> $DIR/feature-gate-custom_attribute2.rs:57:9
|
57 | fn f_lt<#[lt_fn] 'g>(_: &'g [u32]) -> &'g u32 { loop { } }
|
= help: add #![feature(custom_attribute)] to the crate attributes to enable
-error: The attribute `ty_fn` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `ty_fn` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
--> $DIR/feature-gate-custom_attribute2.rs:59:9
|
59 | fn f_ty<#[ty_fn] O>(_: O) { }
|
= help: add #![feature(custom_attribute)] to the crate attributes to enable
-error: The attribute `lt_meth` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `lt_meth` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
--> $DIR/feature-gate-custom_attribute2.rs:63:13
|
63 | fn m_lt<#[lt_meth] 'h>(_: &'h [u32]) -> &'h u32 { loop { } }
|
= help: add #![feature(custom_attribute)] to the crate attributes to enable
-error: The attribute `ty_meth` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `ty_meth` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
--> $DIR/feature-gate-custom_attribute2.rs:65:13
|
65 | fn m_ty<#[ty_meth] P>(_: P) { }
|
= help: add #![feature(custom_attribute)] to the crate attributes to enable
-error: The attribute `lt_hof` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `lt_hof` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
--> $DIR/feature-gate-custom_attribute2.rs:70:19
|
70 | where Q: for <#[lt_hof] 'i> Fn(&'i [u32]) -> &'i u32
-error: attributes of the form `#[derive_*]` are reserved for the compiler (see issue #29644)
+error[E0658]: attributes of the form `#[derive_*]` are reserved for the compiler (see issue #29644)
--> $DIR/feature-gate-custom_derive.rs:11:1
|
11 | #[derive_Clone]
-error: `macro` is experimental (see issue #39412)
+error[E0658]: `macro` is experimental (see issue #39412)
--> $DIR/feature-gate-decl_macro.rs:13:1
|
13 | macro m() {} //~ ERROR `macro` is experimental (see issue #39412)
-error: #[doc(cfg(...))] is experimental (see issue #43781)
+error[E0658]: #[doc(cfg(...))] is experimental (see issue #43781)
--> $DIR/feature-gate-doc_cfg.rs:11:1
|
11 | #[doc(cfg(unix))] //~ ERROR: #[doc(cfg(...))] is experimental
-error: #[doc(masked)] is experimental (see issue #44027)
+error[E0658]: #[doc(masked)] is experimental (see issue #44027)
--> $DIR/feature-gate-doc_masked.rs:11:1
|
11 | #[doc(masked)] //~ ERROR: #[doc(masked)] is experimental
-error: #[doc(spotlight)] is experimental (see issue #45040)
+error[E0658]: #[doc(spotlight)] is experimental (see issue #45040)
--> $DIR/feature-gate-doc_spotlight.rs:11:1
|
11 | #[doc(spotlight)] //~ ERROR: #[doc(spotlight)] is experimental
-error: `..=` syntax in patterns is experimental (see issue #28237)
+error[E0658]: `..=` syntax in patterns is experimental (see issue #28237)
--> $DIR/feature-gate-dotdoteq_in_patterns.rs:13:9
|
13 | 0 ..= 3 => {} //~ ERROR `..=` syntax in patterns is experimental
-error: unsafe_destructor_blind_to_params has been replaced by may_dangle and will be removed in the future (see issue #28498)
+error[E0658]: unsafe_destructor_blind_to_params has been replaced by may_dangle and will be removed in the future (see issue #28498)
--> $DIR/feature-gate-dropck-ugeh.rs:29:5
|
29 | #[unsafe_destructor_blind_to_params] // This is the UGEH attribute
-error: `dyn Trait` syntax is unstable (see issue #44662)
+error[E0658]: `dyn Trait` syntax is unstable (see issue #44662)
--> $DIR/feature-gate-dyn-trait.rs:12:14
|
12 | type A = Box<dyn Trait>; //~ ERROR `dyn Trait` syntax is unstable
-error: exclusive range pattern syntax is experimental (see issue #37854)
+error[E0658]: exclusive range pattern syntax is experimental (see issue #37854)
--> $DIR/feature-gate-exclusive-range-pattern.rs:13:9
|
13 | 0 .. 3 => {} //~ ERROR exclusive range pattern syntax is experimental
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <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.
+
+struct S;
+
+fn main() {
+ let _ = extern::std::vec::Vec::new(); //~ ERROR `extern` in paths is experimental
+}
--- /dev/null
+error[E0658]: `extern` in paths is experimental (see issue #44660)
+ --> $DIR/feature-gate-extern_in_paths.rs:14:13
+ |
+14 | let _ = extern::std::vec::Vec::new(); //~ ERROR `extern` in paths is experimental
+ | ^^^^^^
+ |
+ = help: add #![feature(extern_in_paths)] to the crate attributes to enable
+
+error: aborting due to previous error
+
-error: extern types are experimental (see issue #43467)
+error[E0658]: extern types are experimental (see issue #43467)
--> $DIR/feature-gate-extern_types.rs:12:5
|
12 | type T; //~ ERROR extern types are experimental
-error: #[doc(include = "...")] is experimental (see issue #44732)
+error[E0658]: #[doc(include = "...")] is experimental (see issue #44732)
--> $DIR/feature-gate-external_doc.rs:11:1
|
11 | #[doc(include="asdf.md")] //~ ERROR: #[doc(include = "...")] is experimental
-error: the `#[fundamental]` attribute is an experimental feature (see issue #29635)
+error[E0658]: the `#[fundamental]` attribute is an experimental feature (see issue #29635)
--> $DIR/feature-gate-fundamental.rs:11:1
|
11 | #[fundamental] //~ ERROR the `#[fundamental]` attribute is an experimental feature
-error: yield syntax is experimental
+error[E0658]: yield syntax is experimental
--> $DIR/feature-gate-generators.rs:12:5
|
12 | yield true; //~ ERROR yield syntax is experimental
-error: generic associated types are unstable (see issue #44265)
+error[E0658]: generic associated types are unstable (see issue #44265)
--> $DIR/feature-gate-generic_associated_types.rs:14:5
|
14 | type Pointer<T>: Deref<Target = T>;
|
= help: add #![feature(generic_associated_types)] to the crate attributes to enable
-error: generic associated types are unstable (see issue #44265)
+error[E0658]: generic associated types are unstable (see issue #44265)
--> $DIR/feature-gate-generic_associated_types.rs:16:5
|
16 | type Pointer2<T>: Deref<Target = T> where T: Clone, U: Clone;
|
= help: add #![feature(generic_associated_types)] to the crate attributes to enable
-error: generic associated types are unstable (see issue #44265)
+error[E0658]: generic associated types are unstable (see issue #44265)
--> $DIR/feature-gate-generic_associated_types.rs:22:5
|
22 | type Pointer<usize> = Box<usize>;
|
= help: add #![feature(generic_associated_types)] to the crate attributes to enable
-error: generic associated types are unstable (see issue #44265)
+error[E0658]: generic associated types are unstable (see issue #44265)
--> $DIR/feature-gate-generic_associated_types.rs:24:5
|
24 | type Pointer2<u32> = Box<u32>;
-error: attributes on lifetime bindings are experimental (see issue #34761)
+error[E0658]: attributes on lifetime bindings are experimental (see issue #34761)
--> $DIR/feature-gate-generic_param_attrs.rs:22:13
|
22 | struct StLt<#[rustc_lt_struct] 'a>(&'a u32);
|
= help: add #![feature(generic_param_attrs)] to the crate attributes to enable
-error: attributes on type parameter bindings are experimental (see issue #34761)
+error[E0658]: attributes on type parameter bindings are experimental (see issue #34761)
--> $DIR/feature-gate-generic_param_attrs.rs:24:13
|
24 | struct StTy<#[rustc_ty_struct] I>(I);
|
= help: add #![feature(generic_param_attrs)] to the crate attributes to enable
-error: attributes on lifetime bindings are experimental (see issue #34761)
+error[E0658]: attributes on lifetime bindings are experimental (see issue #34761)
--> $DIR/feature-gate-generic_param_attrs.rs:27:11
|
27 | enum EnLt<#[rustc_lt_enum] 'b> { A(&'b u32), B }
|
= help: add #![feature(generic_param_attrs)] to the crate attributes to enable
-error: attributes on type parameter bindings are experimental (see issue #34761)
+error[E0658]: attributes on type parameter bindings are experimental (see issue #34761)
--> $DIR/feature-gate-generic_param_attrs.rs:29:11
|
29 | enum EnTy<#[rustc_ty_enum] J> { A(J), B }
|
= help: add #![feature(generic_param_attrs)] to the crate attributes to enable
-error: attributes on lifetime bindings are experimental (see issue #34761)
+error[E0658]: attributes on lifetime bindings are experimental (see issue #34761)
--> $DIR/feature-gate-generic_param_attrs.rs:32:12
|
32 | trait TrLt<#[rustc_lt_trait] 'c> { fn foo(&self, _: &'c [u32]) -> &'c u32; }
|
= help: add #![feature(generic_param_attrs)] to the crate attributes to enable
-error: attributes on type parameter bindings are experimental (see issue #34761)
+error[E0658]: attributes on type parameter bindings are experimental (see issue #34761)
--> $DIR/feature-gate-generic_param_attrs.rs:34:12
|
34 | trait TrTy<#[rustc_ty_trait] K> { fn foo(&self, _: K); }
|
= help: add #![feature(generic_param_attrs)] to the crate attributes to enable
-error: attributes on lifetime bindings are experimental (see issue #34761)
+error[E0658]: attributes on lifetime bindings are experimental (see issue #34761)
--> $DIR/feature-gate-generic_param_attrs.rs:37:11
|
37 | type TyLt<#[rustc_lt_type] 'd> = &'d u32;
|
= help: add #![feature(generic_param_attrs)] to the crate attributes to enable
-error: attributes on type parameter bindings are experimental (see issue #34761)
+error[E0658]: attributes on type parameter bindings are experimental (see issue #34761)
--> $DIR/feature-gate-generic_param_attrs.rs:39:11
|
39 | type TyTy<#[rustc_ty_type] L> = (L, );
|
= help: add #![feature(generic_param_attrs)] to the crate attributes to enable
-error: attributes on lifetime bindings are experimental (see issue #34761)
+error[E0658]: attributes on lifetime bindings are experimental (see issue #34761)
--> $DIR/feature-gate-generic_param_attrs.rs:42:6
|
42 | impl<#[rustc_lt_inherent] 'e> StLt<'e> { }
|
= help: add #![feature(generic_param_attrs)] to the crate attributes to enable
-error: attributes on type parameter bindings are experimental (see issue #34761)
+error[E0658]: attributes on type parameter bindings are experimental (see issue #34761)
--> $DIR/feature-gate-generic_param_attrs.rs:44:6
|
44 | impl<#[rustc_ty_inherent] M> StTy<M> { }
|
= help: add #![feature(generic_param_attrs)] to the crate attributes to enable
-error: attributes on lifetime bindings are experimental (see issue #34761)
+error[E0658]: attributes on lifetime bindings are experimental (see issue #34761)
--> $DIR/feature-gate-generic_param_attrs.rs:47:6
|
47 | impl<#[rustc_lt_impl_for] 'f> TrLt<'f> for StLt<'f> {
|
= help: add #![feature(generic_param_attrs)] to the crate attributes to enable
-error: attributes on type parameter bindings are experimental (see issue #34761)
+error[E0658]: attributes on type parameter bindings are experimental (see issue #34761)
--> $DIR/feature-gate-generic_param_attrs.rs:51:6
|
51 | impl<#[rustc_ty_impl_for] N> TrTy<N> for StTy<N> {
|
= help: add #![feature(generic_param_attrs)] to the crate attributes to enable
-error: attributes on lifetime bindings are experimental (see issue #34761)
+error[E0658]: attributes on lifetime bindings are experimental (see issue #34761)
--> $DIR/feature-gate-generic_param_attrs.rs:56:9
|
56 | fn f_lt<#[rustc_lt_fn] 'g>(_: &'g [u32]) -> &'g u32 { loop { } }
|
= help: add #![feature(generic_param_attrs)] to the crate attributes to enable
-error: attributes on type parameter bindings are experimental (see issue #34761)
+error[E0658]: attributes on type parameter bindings are experimental (see issue #34761)
--> $DIR/feature-gate-generic_param_attrs.rs:58:9
|
58 | fn f_ty<#[rustc_ty_fn] O>(_: O) { }
|
= help: add #![feature(generic_param_attrs)] to the crate attributes to enable
-error: attributes on lifetime bindings are experimental (see issue #34761)
+error[E0658]: attributes on lifetime bindings are experimental (see issue #34761)
--> $DIR/feature-gate-generic_param_attrs.rs:62:13
|
62 | fn m_lt<#[rustc_lt_meth] 'h>(_: &'h [u32]) -> &'h u32 { loop { } }
|
= help: add #![feature(generic_param_attrs)] to the crate attributes to enable
-error: attributes on type parameter bindings are experimental (see issue #34761)
+error[E0658]: attributes on type parameter bindings are experimental (see issue #34761)
--> $DIR/feature-gate-generic_param_attrs.rs:64:13
|
64 | fn m_ty<#[rustc_ty_meth] P>(_: P) { }
|
= help: add #![feature(generic_param_attrs)] to the crate attributes to enable
-error: attributes on lifetime bindings are experimental (see issue #34761)
+error[E0658]: attributes on lifetime bindings are experimental (see issue #34761)
--> $DIR/feature-gate-generic_param_attrs.rs:69:19
|
69 | where Q: for <#[rustc_lt_hof] 'i> Fn(&'i [u32]) -> &'i u32
-error: the `#[global_allocator]` attribute is an experimental feature
+error[E0658]: the `#[global_allocator]` attribute is an experimental feature
--> $DIR/feature-gate-global_allocator.rs:11:1
|
11 | #[global_allocator] //~ ERROR: attribute is an experimental feature
-error: `global_asm!` is not stable enough for use and is subject to change (see issue #35119)
+error[E0658]: `global_asm!` is not stable enough for use and is subject to change (see issue #35119)
--> $DIR/feature-gate-global_asm.rs:11:1
|
11 | global_asm!(""); //~ ERROR `global_asm!` is not stable
-error: 128-bit integers are not stable (see issue #35118)
+error[E0658]: 128-bit integers are not stable (see issue #35118)
--> $DIR/feature-gate-i128_type.rs:12:5
|
12 | 0i128; //~ ERROR 128-bit integers are not stable
|
= help: add #![feature(i128_type)] to the crate attributes to enable
-error: 128-bit integers are not stable (see issue #35118)
+error[E0658]: 128-bit integers are not stable (see issue #35118)
--> $DIR/feature-gate-i128_type.rs:16:5
|
16 | 0u128; //~ ERROR 128-bit integers are not stable
-error: 128-bit type is unstable (see issue #35118)
+error[E0658]: 128-bit type is unstable (see issue #35118)
--> $DIR/feature-gate-i128_type2.rs:13:15
|
13 | fn test1() -> i128 { //~ ERROR 128-bit type is unstable
|
= help: add #![feature(i128_type)] to the crate attributes to enable
-error: 128-bit type is unstable (see issue #35118)
+error[E0658]: 128-bit type is unstable (see issue #35118)
--> $DIR/feature-gate-i128_type2.rs:17:17
|
17 | fn test1_2() -> u128 { //~ ERROR 128-bit type is unstable
|
= help: add #![feature(i128_type)] to the crate attributes to enable
-error: 128-bit type is unstable (see issue #35118)
+error[E0658]: 128-bit type is unstable (see issue #35118)
--> $DIR/feature-gate-i128_type2.rs:22:12
|
22 | let x: i128 = 0; //~ ERROR 128-bit type is unstable
|
= help: add #![feature(i128_type)] to the crate attributes to enable
-error: 128-bit type is unstable (see issue #35118)
+error[E0658]: 128-bit type is unstable (see issue #35118)
--> $DIR/feature-gate-i128_type2.rs:26:12
|
26 | let x: u128 = 0; //~ ERROR 128-bit type is unstable
error[E0601]: main function not found
-error: repr with 128-bit type is unstable (see issue #35118)
+error[E0658]: repr with 128-bit type is unstable (see issue #35118)
--> $DIR/feature-gate-i128_type2.rs:30:1
|
30 | / enum A { //~ ERROR 128-bit type is unstable
-error: intrinsics are subject to change
+error[E0658]: intrinsics are subject to change
--> $DIR/feature-gate-intrinsics.rs:11:1
|
11 | / extern "rust-intrinsic" { //~ ERROR intrinsics are subject to change
|
= help: add #![feature(intrinsics)] to the crate attributes to enable
-error: intrinsics are subject to change
+error[E0658]: intrinsics are subject to change
--> $DIR/feature-gate-intrinsics.rs:15:1
|
15 | / extern "rust-intrinsic" fn baz() { //~ ERROR intrinsics are subject to change
-error: language items are subject to change
+error[E0658]: language items are subject to change
--> $DIR/feature-gate-lang-items.rs:11:1
|
11 | #[lang="foo"] //~ ERROR language items are subject to change
-error: the `link_args` attribute is experimental and not portable across platforms, it is recommended to use `#[link(name = "foo")] instead (see issue #29596)
+error[E0658]: the `link_args` attribute is experimental and not portable across platforms, it is recommended to use `#[link(name = "foo")] instead (see issue #29596)
--> $DIR/feature-gate-link_args.rs:22:1
|
22 | #[link_args = "-l expected_use_case"]
|
= help: add #![feature(link_args)] to the crate attributes to enable
-error: the `link_args` attribute is experimental and not portable across platforms, it is recommended to use `#[link(name = "foo")] instead (see issue #29596)
+error[E0658]: the `link_args` attribute is experimental and not portable across platforms, it is recommended to use `#[link(name = "foo")] instead (see issue #29596)
--> $DIR/feature-gate-link_args.rs:26:1
|
26 | #[link_args = "-l unexected_use_on_non_extern_item"]
|
= help: add #![feature(link_args)] to the crate attributes to enable
-error: the `link_args` attribute is experimental and not portable across platforms, it is recommended to use `#[link(name = "foo")] instead (see issue #29596)
+error[E0658]: the `link_args` attribute is experimental and not portable across platforms, it is recommended to use `#[link(name = "foo")] instead (see issue #29596)
--> $DIR/feature-gate-link_args.rs:19:1
|
19 | #![link_args = "-l unexpected_use_as_inner_attr_on_mod"]
-error: is feature gated (see issue #37406)
+error[E0658]: is feature gated (see issue #37406)
--> $DIR/feature-gate-link_cfg.rs:11:1
|
11 | #[link(name = "foo", cfg(foo))]
-error: linking to LLVM intrinsics is experimental (see issue #29602)
+error[E0658]: linking to LLVM intrinsics is experimental (see issue #29602)
--> $DIR/feature-gate-link_llvm_intrinsics.rs:13:5
|
13 | fn sqrt(x: f32) -> f32;
-error: the `linkage` attribute is experimental and not portable across platforms (see issue #29603)
+error[E0658]: the `linkage` attribute is experimental and not portable across platforms (see issue #29603)
--> $DIR/feature-gate-linkage.rs:12:5
|
12 | #[linkage = "extern_weak"] static foo: isize;
-error: the `#[used]` attribute is an experimental feature (see issue #40289)
+error[E0658]: the `#[used]` attribute is an experimental feature (see issue #40289)
--> $DIR/feature-gate-linker-flavor.rs:16:1
|
16 | #[used]
-error: `log_syntax!` is not stable enough for use and is subject to change (see issue #29598)
+error[E0658]: `log_syntax!` is not stable enough for use and is subject to change (see issue #29598)
--> $DIR/feature-gate-log_syntax.rs:12:5
|
12 | log_syntax!() //~ ERROR `log_syntax!` is not stable enough
-error: `log_syntax!` is not stable enough for use and is subject to change (see issue #29598)
+error[E0658]: `log_syntax!` is not stable enough for use and is subject to change (see issue #29598)
--> $DIR/feature-gate-log_syntax2.rs:14:20
|
14 | println!("{}", log_syntax!()); //~ ERROR `log_syntax!` is not stable
-error: :lifetime fragment specifier is experimental and subject to change (see issue #46895)
+error[E0658]: :lifetime fragment specifier is experimental and subject to change (see issue #46895)
--> $DIR/feature-gate-macro-lifetime-matcher.rs:14:19
|
14 | macro_rules! m { ($lt:lifetime) => {} }
-error: :vis fragment specifier is experimental and subject to change (see issue #41022)
+error[E0658]: :vis fragment specifier is experimental and subject to change (see issue #41022)
--> $DIR/feature-gate-macro-vis-matcher.rs:14:19
|
14 | macro_rules! m { ($v:vis) => {} }
-error: declaration of a nonstandard #[main] function may change over time, for now a top-level `fn main()` is required (see issue #29634)
+error[E0658]: declaration of a nonstandard #[main] function may change over time, for now a top-level `fn main()` is required (see issue #29634)
--> $DIR/feature-gate-main.rs:12:1
|
12 | fn foo() {} //~ ERROR: declaration of a nonstandard #[main] function may change over time
-error: Use of a '|' at the beginning of a match arm is experimental (see issue #44101)
+error[E0658]: Use of a '|' at the beginning of a match arm is experimental (see issue #44101)
--> $DIR/feature-gate-match_beginning_vert.rs:24:9
|
24 | | A => println!("A"),
|
= help: add #![feature(match_beginning_vert)] to the crate attributes to enable
-error: Use of a '|' at the beginning of a match arm is experimental (see issue #44101)
+error[E0658]: Use of a '|' at the beginning of a match arm is experimental (see issue #44101)
--> $DIR/feature-gate-match_beginning_vert.rs:26:9
|
26 | | B | C => println!("BC!"),
|
= help: add #![feature(match_beginning_vert)] to the crate attributes to enable
-error: Use of a '|' at the beginning of a match arm is experimental (see issue #44101)
+error[E0658]: Use of a '|' at the beginning of a match arm is experimental (see issue #44101)
--> $DIR/feature-gate-match_beginning_vert.rs:28:9
|
28 | | _ => {},
-error: non-reference pattern used to match a reference (see issue #42640)
+error[E0658]: non-reference pattern used to match a reference (see issue #42640)
--> $DIR/feature-gate-match_default_bindings.rs:13:9
|
13 | Some(n) => {},
-error: may_dangle has unstable semantics and may be removed in the future (see issue #34761)
+error[E0658]: may_dangle has unstable semantics and may be removed in the future (see issue #34761)
--> $DIR/feature-gate-may-dangle.rs:18:6
|
18 | impl<#[may_dangle] A> Drop for Pt<A> {
-error: the `#[naked]` attribute is an experimental feature (see issue #32408)
+error[E0658]: the `#[naked]` attribute is an experimental feature (see issue #32408)
--> $DIR/feature-gate-naked_functions.rs:11:1
|
11 | #[naked]
|
= help: add #![feature(naked_functions)] to the crate attributes to enable
-error: the `#[naked]` attribute is an experimental feature (see issue #32408)
+error[E0658]: the `#[naked]` attribute is an experimental feature (see issue #32408)
--> $DIR/feature-gate-naked_functions.rs:15:1
|
15 | #[naked]
-error: the `#[needs_allocator]` attribute is an experimental feature
+error[E0658]: the `#[needs_allocator]` attribute is an experimental feature
--> $DIR/feature-gate-needs-allocator.rs:11:1
|
11 | #![needs_allocator] //~ ERROR the `#[needs_allocator]` attribute is
-error: The `!` type is experimental (see issue #35121)
+error[E0658]: The `!` type is experimental (see issue #35121)
--> $DIR/feature-gate-never_type.rs:17:17
|
17 | type Ma = (u32, !, i32); //~ ERROR type is experimental
|
= help: add #![feature(never_type)] to the crate attributes to enable
-error: The `!` type is experimental (see issue #35121)
+error[E0658]: The `!` type is experimental (see issue #35121)
--> $DIR/feature-gate-never_type.rs:18:20
|
18 | type Meeshka = Vec<!>; //~ ERROR type is experimental
|
= help: add #![feature(never_type)] to the crate attributes to enable
-error: The `!` type is experimental (see issue #35121)
+error[E0658]: The `!` type is experimental (see issue #35121)
--> $DIR/feature-gate-never_type.rs:19:16
|
19 | type Mow = &fn(!) -> !; //~ ERROR type is experimental
|
= help: add #![feature(never_type)] to the crate attributes to enable
-error: The `!` type is experimental (see issue #35121)
+error[E0658]: The `!` type is experimental (see issue #35121)
--> $DIR/feature-gate-never_type.rs:20:19
|
20 | type Skwoz = &mut !; //~ ERROR type is experimental
|
= help: add #![feature(never_type)] to the crate attributes to enable
-error: The `!` type is experimental (see issue #35121)
+error[E0658]: The `!` type is experimental (see issue #35121)
--> $DIR/feature-gate-never_type.rs:23:16
|
23 | type Wub = !; //~ ERROR type is experimental
-error: the `#[no_debug]` attribute was an experimental feature that has been deprecated due to lack of demand (see issue #29721)
+error[E0658]: the `#[no_debug]` attribute was an experimental feature that has been deprecated due to lack of demand (see issue #29721)
--> $DIR/feature-gate-no-debug.rs:13:1
|
13 | #[no_debug] //~ ERROR the `#[no_debug]` attribute was
-error: no_core is experimental (see issue #29639)
+error[E0658]: no_core is experimental (see issue #29639)
--> $DIR/feature-gate-no_core.rs:11:1
|
11 | #![no_core] //~ ERROR no_core is experimental
-error: non-ascii idents are not fully supported. (see issue #28979)
+error[E0658]: non-ascii idents are not fully supported. (see issue #28979)
--> $DIR/feature-gate-non_ascii_idents.rs:11:1
|
11 | extern crate core as bäz; //~ ERROR non-ascii idents
|
= help: add #![feature(non_ascii_idents)] to the crate attributes to enable
-error: non-ascii idents are not fully supported. (see issue #28979)
+error[E0658]: non-ascii idents are not fully supported. (see issue #28979)
--> $DIR/feature-gate-non_ascii_idents.rs:13:5
|
13 | use föö::bar; //~ ERROR non-ascii idents
|
= help: add #![feature(non_ascii_idents)] to the crate attributes to enable
-error: non-ascii idents are not fully supported. (see issue #28979)
+error[E0658]: non-ascii idents are not fully supported. (see issue #28979)
--> $DIR/feature-gate-non_ascii_idents.rs:15:1
|
15 | mod föö { //~ ERROR non-ascii idents
|
= help: add #![feature(non_ascii_idents)] to the crate attributes to enable
-error: non-ascii idents are not fully supported. (see issue #28979)
+error[E0658]: non-ascii idents are not fully supported. (see issue #28979)
--> $DIR/feature-gate-non_ascii_idents.rs:19:1
|
19 | / fn bär( //~ ERROR non-ascii idents
|
= help: add #![feature(non_ascii_idents)] to the crate attributes to enable
-error: non-ascii idents are not fully supported. (see issue #28979)
+error[E0658]: non-ascii idents are not fully supported. (see issue #28979)
--> $DIR/feature-gate-non_ascii_idents.rs:20:5
|
20 | bäz: isize //~ ERROR non-ascii idents
|
= help: add #![feature(non_ascii_idents)] to the crate attributes to enable
-error: non-ascii idents are not fully supported. (see issue #28979)
+error[E0658]: non-ascii idents are not fully supported. (see issue #28979)
--> $DIR/feature-gate-non_ascii_idents.rs:22:9
|
22 | let _ö: isize; //~ ERROR non-ascii idents
|
= help: add #![feature(non_ascii_idents)] to the crate attributes to enable
-error: non-ascii idents are not fully supported. (see issue #28979)
+error[E0658]: non-ascii idents are not fully supported. (see issue #28979)
--> $DIR/feature-gate-non_ascii_idents.rs:25:10
|
25 | (_ä, _) => {} //~ ERROR non-ascii idents
|
= help: add #![feature(non_ascii_idents)] to the crate attributes to enable
-error: non-ascii idents are not fully supported. (see issue #28979)
+error[E0658]: non-ascii idents are not fully supported. (see issue #28979)
--> $DIR/feature-gate-non_ascii_idents.rs:29:1
|
29 | struct Föö { //~ ERROR non-ascii idents
|
= help: add #![feature(non_ascii_idents)] to the crate attributes to enable
-error: non-ascii idents are not fully supported. (see issue #28979)
+error[E0658]: non-ascii idents are not fully supported. (see issue #28979)
--> $DIR/feature-gate-non_ascii_idents.rs:30:5
|
30 | föö: isize //~ ERROR non-ascii idents
|
= help: add #![feature(non_ascii_idents)] to the crate attributes to enable
-error: non-ascii idents are not fully supported. (see issue #28979)
+error[E0658]: non-ascii idents are not fully supported. (see issue #28979)
--> $DIR/feature-gate-non_ascii_idents.rs:33:1
|
33 | enum Bär { //~ ERROR non-ascii idents
|
= help: add #![feature(non_ascii_idents)] to the crate attributes to enable
-error: non-ascii idents are not fully supported. (see issue #28979)
+error[E0658]: non-ascii idents are not fully supported. (see issue #28979)
--> $DIR/feature-gate-non_ascii_idents.rs:34:5
|
34 | Bäz { //~ ERROR non-ascii idents
|
= help: add #![feature(non_ascii_idents)] to the crate attributes to enable
-error: non-ascii idents are not fully supported. (see issue #28979)
+error[E0658]: non-ascii idents are not fully supported. (see issue #28979)
--> $DIR/feature-gate-non_ascii_idents.rs:35:9
|
35 | qüx: isize //~ ERROR non-ascii idents
|
= help: add #![feature(non_ascii_idents)] to the crate attributes to enable
-error: non-ascii idents are not fully supported. (see issue #28979)
+error[E0658]: non-ascii idents are not fully supported. (see issue #28979)
--> $DIR/feature-gate-non_ascii_idents.rs:40:5
|
40 | fn qüx(); //~ ERROR non-ascii idents
-error: non exhaustive is an experimental feature (see issue #44109)
+error[E0658]: non exhaustive is an experimental feature (see issue #44109)
--> $DIR/feature-gate-non_exhaustive.rs:13:1
|
13 | #[non_exhaustive] //~ERROR non exhaustive is an experimental feature (see issue #44109)
-error: the `#[omit_gdb_pretty_printer_section]` attribute is just used for the Rust test suite
+error[E0658]: the `#[omit_gdb_pretty_printer_section]` attribute is just used for the Rust test suite
--> $DIR/feature-gate-omit-gdb-pretty-printer-section.rs:11:1
|
11 | #[omit_gdb_pretty_printer_section] //~ ERROR the `#[omit_gdb_pretty_printer_section]` attribute is
-error: the `#[rustc_on_unimplemented]` attribute is an experimental feature (see issue #29628)
+error[E0658]: the `#[rustc_on_unimplemented]` attribute is an experimental feature (see issue #29628)
--> $DIR/feature-gate-on-unimplemented.rs:14:1
|
14 | #[rustc_on_unimplemented = "test error `{Self}` with `{Bar}`"]
auto trait AutoDummyTrait {}
//~^ ERROR auto traits are experimental and possibly buggy
-#[allow(auto_impl)]
-impl DummyTrait for .. {}
-//~^ ERROR auto trait implementations are experimental and possibly buggy
-
impl !DummyTrait for DummyStruct {}
//~^ ERROR negative trait bounds are not yet fully implemented; use marker types for now
-error: auto traits are experimental and possibly buggy (see issue #13231)
+error[E0658]: auto traits are experimental and possibly buggy (see issue #13231)
--> $DIR/feature-gate-optin-builtin-traits.rs:20:1
|
20 | auto trait AutoDummyTrait {}
|
= help: add #![feature(optin_builtin_traits)] to the crate attributes to enable
-error: auto trait implementations are experimental and possibly buggy (see issue #13231)
- --> $DIR/feature-gate-optin-builtin-traits.rs:24:1
+error[E0658]: negative trait bounds are not yet fully implemented; use marker types for now (see issue #13231)
+ --> $DIR/feature-gate-optin-builtin-traits.rs:23:1
|
-24 | impl DummyTrait for .. {}
- | ^^^^^^^^^^^^^^^^^^^^^^^^^
- |
- = help: add #![feature(optin_builtin_traits)] to the crate attributes to enable
-
-error: negative trait bounds are not yet fully implemented; use marker types for now (see issue #13231)
- --> $DIR/feature-gate-optin-builtin-traits.rs:27:1
- |
-27 | impl !DummyTrait for DummyStruct {}
+23 | impl !DummyTrait for DummyStruct {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: add #![feature(optin_builtin_traits)] to the crate attributes to enable
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
-error: placement-in expression syntax is experimental and subject to change. (see issue #27779)
+error[E0658]: placement-in expression syntax is experimental and subject to change. (see issue #27779)
--> $DIR/feature-gate-placement-expr.rs:24:13
|
24 | let x = HEAP <- 'c'; //~ ERROR placement-in expression syntax is experimental
-error: compiler plugins are experimental and possibly buggy (see issue #29597)
+error[E0658]: compiler plugins are experimental and possibly buggy (see issue #29597)
--> $DIR/feature-gate-plugin.rs:13:1
|
13 | #![plugin(foo)]
-error: compiler plugins are experimental and possibly buggy (see issue #29597)
+error[E0658]: compiler plugins are experimental and possibly buggy (see issue #29597)
--> $DIR/feature-gate-plugin_registrar.rs:16:1
|
16 | pub fn registrar() {}
-error: `#[prelude_import]` is for use by rustc only
+error[E0658]: `#[prelude_import]` is for use by rustc only
--> $DIR/feature-gate-prelude_import.rs:11:1
|
11 | #[prelude_import] //~ ERROR `#[prelude_import]` is for use by rustc only
-error: the `#[profiler_runtime]` attribute is used to identify the `profiler_builtins` crate which contains the profiler runtime and will never be stable
+error[E0658]: the `#[profiler_runtime]` attribute is used to identify the `profiler_builtins` crate which contains the profiler runtime and will never be stable
--> $DIR/feature-gate-profiler-runtime.rs:11:1
|
11 | #![profiler_runtime] //~ ERROR the `#[profiler_runtime]` attribute is
-error: SIMD types are experimental and possibly buggy (see issue #27731)
+error[E0658]: SIMD types are experimental and possibly buggy (see issue #27731)
--> $DIR/feature-gate-repr-simd.rs:11:1
|
11 | #[repr(simd)] //~ error: SIMD types are experimental
-error: repr with 128-bit type is unstable (see issue #35118)
+error[E0658]: repr with 128-bit type is unstable (see issue #35118)
--> $DIR/feature-gate-repr128.rs:12:1
|
12 | / enum A { //~ ERROR repr with 128-bit type is unstable
-error: the struct `#[repr(align(u16))]` attribute is experimental (see issue #33626)
+error[E0658]: the struct `#[repr(align(u16))]` attribute is experimental (see issue #33626)
--> $DIR/feature-gate-repr_align.rs:12:1
|
12 | #[repr(align(64))] //~ error: the struct `#[repr(align(u16))]` attribute is experimental
-error: the `#[rustc_variance]` attribute is just used for rustc unit tests and will never be stable (see issue #29642)
+error[E0658]: the `#[rustc_variance]` attribute is just used for rustc unit tests and will never be stable (see issue #29642)
--> $DIR/feature-gate-rustc-attrs.rs:15:1
|
15 | #[rustc_variance] //~ ERROR the `#[rustc_variance]` attribute is just used for rustc unit tests and will never be stable
|
= help: add #![feature(rustc_attrs)] to the crate attributes to enable
-error: the `#[rustc_error]` attribute is just used for rustc unit tests and will never be stable (see issue #29642)
+error[E0658]: the `#[rustc_error]` attribute is just used for rustc unit tests and will never be stable (see issue #29642)
--> $DIR/feature-gate-rustc-attrs.rs:16:1
|
16 | #[rustc_error] //~ ERROR the `#[rustc_error]` attribute is just used for rustc unit tests and will never be stable
|
= help: add #![feature(rustc_attrs)] to the crate attributes to enable
-error: unless otherwise specified, attributes with the prefix `rustc_` are reserved for internal compiler diagnostics (see issue #29642)
+error[E0658]: unless otherwise specified, attributes with the prefix `rustc_` are reserved for internal compiler diagnostics (see issue #29642)
--> $DIR/feature-gate-rustc-attrs.rs:17:1
|
17 | #[rustc_foo]
-error: the `#[rustc_const_unstable]` attribute is an internal feature
+error[E0658]: the `#[rustc_const_unstable]` attribute is an internal feature
--> $DIR/feature-gate-rustc_const_unstable.rs:18:1
|
18 | #[rustc_const_unstable(feature="fzzzzzt")] //~ERROR internal feature
-error: the `#[sanitizer_runtime]` attribute is used to identify crates that contain the runtime of a sanitizer and will never be stable
+error[E0658]: the `#[sanitizer_runtime]` attribute is used to identify crates that contain the runtime of a sanitizer and will never be stable
--> $DIR/feature-gate-sanitizer-runtime.rs:11:1
|
11 | #![sanitizer_runtime] //~ ERROR the `#[sanitizer_runtime]` attribute is
-error: SIMD types are experimental and possibly buggy (see issue #27731)
+error[E0658]: SIMD types are experimental and possibly buggy (see issue #27731)
--> $DIR/feature-gate-simd.rs:14:1
|
14 | #[repr(simd)] //~ ERROR SIMD types are experimental
-error: slice pattern syntax is experimental (see issue #23121)
+error[E0658]: slice pattern syntax is experimental (see issue #23121)
--> $DIR/feature-gate-slice-patterns.rs:16:9
|
16 | [1, 2, xs..] => {} //~ ERROR slice pattern syntax is experimental
-error: a #[start] function is an experimental feature whose signature may change over time (see issue #29633)
+error[E0658]: a #[start] function is an experimental feature whose signature may change over time (see issue #29633)
--> $DIR/feature-gate-start.rs:12:1
|
12 | fn foo() {} //~ ERROR: a #[start] function is an experimental feature
-error: kind="static-nobundle" is feature gated (see issue #37403)
+error[E0658]: kind="static-nobundle" is feature gated (see issue #37403)
--> $DIR/feature-gate-static-nobundle.rs:11:1
|
11 | #[link(name="foo", kind="static-nobundle")]
-error: attributes on non-item statements and expressions are experimental. (see issue #15701)
+error[E0658]: attributes on non-item statements and expressions are experimental. (see issue #15701)
--> $DIR/feature-gate-stmt_expr_attributes.rs:11:16
|
11 | const X: i32 = #[allow(dead_code)] 8;
-error: the `#[target_feature]` attribute is an experimental feature
+error[E0658]: the `#[target_feature]` attribute is an experimental feature
--> $DIR/feature-gate-target_feature.rs:11:1
|
11 | #[target_feature = "+sse2"]
-error: `#[thread_local]` is an experimental feature, and does not currently handle destructors. There is no corresponding `#[task_local]` mapping to the task model (see issue #29594)
+error[E0658]: `#[thread_local]` is an experimental feature, and does not currently handle destructors. There is no corresponding `#[task_local]` mapping to the task model (see issue #29594)
--> $DIR/feature-gate-thread_local.rs:18:1
|
18 | #[thread_local] //~ ERROR `#[thread_local]` is an experimental feature
-error: `trace_macros` is not stable enough for use and is subject to change (see issue #29598)
+error[E0658]: `trace_macros` is not stable enough for use and is subject to change (see issue #29598)
--> $DIR/feature-gate-trace_macros.rs:12:5
|
12 | trace_macros!(true); //~ ERROR: `trace_macros` is not stable
-error: type ascription is experimental (see issue #23416)
+error[E0658]: type ascription is experimental (see issue #23416)
--> $DIR/feature-gate-type_ascription.rs:14:13
|
14 | let a = 10: u8; //~ ERROR type ascription is experimental
-error: rust-call ABI is subject to change (see issue #29625)
+error[E0658]: rust-call ABI is subject to change (see issue #29625)
--> $DIR/feature-gate-unboxed-closures-manual-impls.rs:20:5
|
20 | extern "rust-call" fn call(self, args: ()) -> () {}
|
= help: add #![feature(unboxed_closures)] to the crate attributes to enable
-error: rust-call ABI is subject to change (see issue #29625)
+error[E0658]: rust-call ABI is subject to change (see issue #29625)
--> $DIR/feature-gate-unboxed-closures-manual-impls.rs:25:5
|
25 | extern "rust-call" fn call_once(self, args: ()) -> () {}
|
= help: add #![feature(unboxed_closures)] to the crate attributes to enable
-error: rust-call ABI is subject to change (see issue #29625)
+error[E0658]: rust-call ABI is subject to change (see issue #29625)
--> $DIR/feature-gate-unboxed-closures-manual-impls.rs:30:5
|
30 | extern "rust-call" fn call_mut(&self, args: ()) -> () {}
|
= help: add #![feature(unboxed_closures)] to the crate attributes to enable
-error: rust-call ABI is subject to change (see issue #29625)
+error[E0658]: rust-call ABI is subject to change (see issue #29625)
--> $DIR/feature-gate-unboxed-closures-manual-impls.rs:35:5
|
35 | extern "rust-call" fn call_once(&self, args: ()) -> () {}
-error: use of unstable library feature 'fn_traits' (see issue #29625)
+error[E0658]: use of unstable library feature 'fn_traits' (see issue #29625)
--> $DIR/feature-gate-unboxed-closures-method-calls.rs:14:7
|
14 | f.call(()); //~ ERROR use of unstable library feature 'fn_traits'
|
= help: add #![feature(fn_traits)] to the crate attributes to enable
-error: use of unstable library feature 'fn_traits' (see issue #29625)
+error[E0658]: use of unstable library feature 'fn_traits' (see issue #29625)
--> $DIR/feature-gate-unboxed-closures-method-calls.rs:15:7
|
15 | f.call_mut(()); //~ ERROR use of unstable library feature 'fn_traits'
|
= help: add #![feature(fn_traits)] to the crate attributes to enable
-error: use of unstable library feature 'fn_traits' (see issue #29625)
+error[E0658]: use of unstable library feature 'fn_traits' (see issue #29625)
--> $DIR/feature-gate-unboxed-closures-method-calls.rs:16:7
|
16 | f.call_once(()); //~ ERROR use of unstable library feature 'fn_traits'
-error: use of unstable library feature 'fn_traits' (see issue #29625)
+error[E0658]: use of unstable library feature 'fn_traits' (see issue #29625)
--> $DIR/feature-gate-unboxed-closures-ufcs-calls.rs:14:5
|
14 | Fn::call(&f, ()); //~ ERROR use of unstable library feature 'fn_traits'
|
= help: add #![feature(fn_traits)] to the crate attributes to enable
-error: use of unstable library feature 'fn_traits' (see issue #29625)
+error[E0658]: use of unstable library feature 'fn_traits' (see issue #29625)
--> $DIR/feature-gate-unboxed-closures-ufcs-calls.rs:15:5
|
15 | FnMut::call_mut(&mut f, ()); //~ ERROR use of unstable library feature 'fn_traits'
|
= help: add #![feature(fn_traits)] to the crate attributes to enable
-error: use of unstable library feature 'fn_traits' (see issue #29625)
+error[E0658]: use of unstable library feature 'fn_traits' (see issue #29625)
--> $DIR/feature-gate-unboxed-closures-ufcs-calls.rs:16:5
|
16 | FnOnce::call_once(f, ()); //~ ERROR use of unstable library feature 'fn_traits'
-error: rust-call ABI is subject to change (see issue #29625)
+error[E0658]: rust-call ABI is subject to change (see issue #29625)
--> $DIR/feature-gate-unboxed-closures.rs:16:5
|
16 | / extern "rust-call" fn call_once(self, (a, b): (u32, u32)) -> u32 {
-error: underscore lifetimes are unstable (see issue #44524)
+error[E0658]: underscore lifetimes are unstable (see issue #44524)
--> $DIR/feature-gate-underscore-lifetimes.rs:13:23
|
13 | fn foo(x: &u8) -> Foo<'_> { //~ ERROR underscore lifetimes are unstable
-error: `impl Trait` in argument position is experimental (see issue #34511)
+error[E0658]: `impl Trait` in argument position is experimental (see issue #34511)
--> $DIR/feature-gate-universal.rs:13:11
|
13 | fn foo(x: impl std::fmt::Debug) { print!("{:?}", x); }
-error: Unsized tuple coercion is not stable enough for use and is subject to change (see issue #42877)
+error[E0658]: Unsized tuple coercion is not stable enough for use and is subject to change (see issue #42877)
--> $DIR/feature-gate-unsized_tuple_coercion.rs:12:24
|
12 | let _ : &(Send,) = &((),);
-error: unions with non-`Copy` fields are unstable (see issue #32836)
+error[E0658]: unions with non-`Copy` fields are unstable (see issue #32836)
--> $DIR/feature-gate-untagged_unions.rs:19:1
|
19 | / union U3 { //~ ERROR unions with non-`Copy` fields are unstable
|
= help: add #![feature(untagged_unions)] to the crate attributes to enable
-error: unions with non-`Copy` fields are unstable (see issue #32836)
+error[E0658]: unions with non-`Copy` fields are unstable (see issue #32836)
--> $DIR/feature-gate-untagged_unions.rs:23:1
|
23 | / union U4<T> { //~ ERROR unions with non-`Copy` fields are unstable
|
= help: add #![feature(untagged_unions)] to the crate attributes to enable
-error: unions with `Drop` implementations are unstable (see issue #32836)
+error[E0658]: unions with `Drop` implementations are unstable (see issue #32836)
--> $DIR/feature-gate-untagged_unions.rs:27:1
|
27 | / union U5 { //~ ERROR unions with `Drop` implementations are unstable
-error: #[unwind] is experimental
+error[E0658]: #[unwind] is experimental
--> $DIR/feature-gate-unwind-attributes.rs:21:5
|
21 | #[unwind] //~ ERROR #[unwind] is experimental
-error: nested groups in `use` are experimental (see issue #44494)
+error[E0658]: nested groups in `use` are experimental (see issue #44494)
--> $DIR/feature-gate-use_nested_groups.rs:27:12
|
27 | use a::{B, d::{*, g::H}}; //~ ERROR glob imports in `use` groups are experimental
|
= help: add #![feature(use_nested_groups)] to the crate attributes to enable
-error: glob imports in `use` groups are experimental (see issue #44494)
+error[E0658]: glob imports in `use` groups are experimental (see issue #44494)
--> $DIR/feature-gate-use_nested_groups.rs:27:16
|
27 | use a::{B, d::{*, g::H}}; //~ ERROR glob imports in `use` groups are experimental
|
= help: add #![feature(use_nested_groups)] to the crate attributes to enable
-error: paths in `use` groups are experimental (see issue #44494)
+error[E0658]: paths in `use` groups are experimental (see issue #44494)
--> $DIR/feature-gate-use_nested_groups.rs:27:19
|
27 | use a::{B, d::{*, g::H}}; //~ ERROR glob imports in `use` groups are experimental
-error: the `#[used]` attribute is an experimental feature (see issue #40289)
+error[E0658]: the `#[used]` attribute is an experimental feature (see issue #40289)
--> $DIR/feature-gate-used.rs:11:1
|
11 | #[used]
-error: wasm_import_memory attribute is currently unstable
+error[E0658]: wasm_import_memory attribute is currently unstable
--> $DIR/feature-gate-wasm_import_memory.rs:11:1
|
11 | #![wasm_import_memory] //~ ERROR: currently unstable
#![start = "x4300"] //~ WARN unused attribute
// see issue-43106-gating-of-test.rs for crate-level; but non crate-level is below at "4200"
// see issue-43106-gating-of-bench.rs for crate-level; but non crate-level is below at "4100"
-#![simd = "4000"] //~ WARN unused attribute
#![repr = "3900"] //~ WARN unused attribute
#![path = "3800"] //~ WARN unused attribute
#![abi = "3700"] //~ WARN unused attribute
impl S { }
}
-#[simd = "4000"]
-//~^ WARN unused attribute
-mod simd {
- mod inner { #![simd="4000"] }
- //~^ WARN unused attribute
-
- #[simd = "4000"] fn f() { }
- //~^ WARN unused attribute
-
- struct S; // for `struct S` case, see feature-gate-repr-simd.rs
-
- #[simd = "4000"] type T = S;
- //~^ WARN unused attribute
-
- #[simd = "4000"] impl S { }
- //~^ WARN unused attribute
-}
-
#[repr = "3900"]
//~^ WARN unused attribute
mod repr {
warning: macro_escape is a deprecated synonym for macro_use
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:532:1
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:513:1
|
-532 | #[macro_escape]
+513 | #[macro_escape]
| ^^^^^^^^^^^^^^^
warning: macro_escape is a deprecated synonym for macro_use
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:535:17
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:516:17
|
-535 | mod inner { #![macro_escape] }
+516 | mod inner { #![macro_escape] }
| ^^^^^^^^^^^^^^^^
|
= help: consider an outer attribute, #[macro_use] mod ...
warning: `#[must_use]` on functions is experimental (see issue #43302)
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:682:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:663:5
|
-682 | #[must_use = "1400"] fn f() { }
+663 | #[must_use = "1400"] fn f() { }
| ^^^^^^^^^^^^^^^^^^^^
|
= help: add #![feature(fn_must_use)] to the crate attributes to enable
| ^^^^^
warning: unknown lint: `x5400`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:114:8
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:113:8
|
-114 | #[warn(x5400)]
+113 | #[warn(x5400)]
| ^^^^^
warning: unknown lint: `x5400`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:117:25
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:116:25
|
-117 | mod inner { #![warn(x5400)] }
+116 | mod inner { #![warn(x5400)] }
| ^^^^^
warning: unknown lint: `x5400`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:120:12
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:119:12
|
-120 | #[warn(x5400)] fn f() { }
+119 | #[warn(x5400)] fn f() { }
| ^^^^^
warning: unknown lint: `x5400`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:123:12
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:122:12
|
-123 | #[warn(x5400)] struct S;
+122 | #[warn(x5400)] struct S;
| ^^^^^
warning: unknown lint: `x5400`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:126:12
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:125:12
|
-126 | #[warn(x5400)] type T = S;
+125 | #[warn(x5400)] type T = S;
| ^^^^^
warning: unknown lint: `x5400`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:129:12
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:128:12
|
-129 | #[warn(x5400)] impl S { }
+128 | #[warn(x5400)] impl S { }
| ^^^^^
warning: unknown lint: `x5300`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:133:9
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:132:9
|
-133 | #[allow(x5300)]
+132 | #[allow(x5300)]
| ^^^^^
warning: unknown lint: `x5300`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:136:26
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:135:26
|
-136 | mod inner { #![allow(x5300)] }
+135 | mod inner { #![allow(x5300)] }
| ^^^^^
warning: unknown lint: `x5300`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:139:13
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:138:13
|
-139 | #[allow(x5300)] fn f() { }
+138 | #[allow(x5300)] fn f() { }
| ^^^^^
warning: unknown lint: `x5300`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:142:13
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:141:13
|
-142 | #[allow(x5300)] struct S;
+141 | #[allow(x5300)] struct S;
| ^^^^^
warning: unknown lint: `x5300`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:145:13
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:144:13
|
-145 | #[allow(x5300)] type T = S;
+144 | #[allow(x5300)] type T = S;
| ^^^^^
warning: unknown lint: `x5300`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:148:13
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:147:13
|
-148 | #[allow(x5300)] impl S { }
+147 | #[allow(x5300)] impl S { }
| ^^^^^
warning: unknown lint: `x5200`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:152:10
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:151:10
|
-152 | #[forbid(x5200)]
+151 | #[forbid(x5200)]
| ^^^^^
warning: unknown lint: `x5200`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:155:27
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:154:27
|
-155 | mod inner { #![forbid(x5200)] }
+154 | mod inner { #![forbid(x5200)] }
| ^^^^^
warning: unknown lint: `x5200`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:158:14
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:157:14
|
-158 | #[forbid(x5200)] fn f() { }
+157 | #[forbid(x5200)] fn f() { }
| ^^^^^
warning: unknown lint: `x5200`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:161:14
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:160:14
|
-161 | #[forbid(x5200)] struct S;
+160 | #[forbid(x5200)] struct S;
| ^^^^^
warning: unknown lint: `x5200`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:164:14
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:163:14
|
-164 | #[forbid(x5200)] type T = S;
+163 | #[forbid(x5200)] type T = S;
| ^^^^^
warning: unknown lint: `x5200`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:167:14
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:166:14
|
-167 | #[forbid(x5200)] impl S { }
+166 | #[forbid(x5200)] impl S { }
| ^^^^^
warning: unknown lint: `x5100`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:171:8
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:170:8
|
-171 | #[deny(x5100)]
+170 | #[deny(x5100)]
| ^^^^^
warning: unknown lint: `x5100`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:174:25
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:173:25
|
-174 | mod inner { #![deny(x5100)] }
+173 | mod inner { #![deny(x5100)] }
| ^^^^^
warning: unknown lint: `x5100`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:177:12
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:176:12
|
-177 | #[deny(x5100)] fn f() { }
+176 | #[deny(x5100)] fn f() { }
| ^^^^^
warning: unknown lint: `x5100`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:180:12
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:179:12
|
-180 | #[deny(x5100)] struct S;
+179 | #[deny(x5100)] struct S;
| ^^^^^
warning: unknown lint: `x5100`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:183:12
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:182:12
|
-183 | #[deny(x5100)] type T = S;
+182 | #[deny(x5100)] type T = S;
| ^^^^^
warning: unknown lint: `x5100`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:186:12
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:185:12
|
-186 | #[deny(x5100)] impl S { }
+185 | #[deny(x5100)] impl S { }
| ^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:193:17
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:192:17
|
-193 | mod inner { #![macro_reexport="5000"] }
+192 | mod inner { #![macro_reexport="5000"] }
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: lint level defined here
| ^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:196:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:195:5
|
-196 | #[macro_reexport = "5000"] fn f() { }
+195 | #[macro_reexport = "5000"] fn f() { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:199:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:198:5
|
-199 | #[macro_reexport = "5000"] struct S;
+198 | #[macro_reexport = "5000"] struct S;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:202:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:201:5
|
-202 | #[macro_reexport = "5000"] type T = S;
+201 | #[macro_reexport = "5000"] type T = S;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:205:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:204:5
|
-205 | #[macro_reexport = "5000"] impl S { }
+204 | #[macro_reexport = "5000"] impl S { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:190:1
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:189:1
|
-190 | #[macro_reexport = "5000"]
+189 | #[macro_reexport = "5000"]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:213:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:212:5
|
-213 | #[macro_use] fn f() { }
+212 | #[macro_use] fn f() { }
| ^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:216:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:215:5
|
-216 | #[macro_use] struct S;
+215 | #[macro_use] struct S;
| ^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:219:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:218:5
|
-219 | #[macro_use] type T = S;
+218 | #[macro_use] type T = S;
| ^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:222:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:221:5
|
-222 | #[macro_use] impl S { }
+221 | #[macro_use] impl S { }
| ^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:229:17
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:228:17
|
-229 | mod inner { #![macro_export="4800"] }
+228 | mod inner { #![macro_export="4800"] }
| ^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:232:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:231:5
|
-232 | #[macro_export = "4800"] fn f() { }
+231 | #[macro_export = "4800"] fn f() { }
| ^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:235:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:234:5
|
-235 | #[macro_export = "4800"] struct S;
+234 | #[macro_export = "4800"] struct S;
| ^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:238:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:237:5
|
-238 | #[macro_export = "4800"] type T = S;
+237 | #[macro_export = "4800"] type T = S;
| ^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:241:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:240:5
|
-241 | #[macro_export = "4800"] impl S { }
+240 | #[macro_export = "4800"] impl S { }
| ^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:226:1
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:225:1
|
-226 | #[macro_export = "4800"]
+225 | #[macro_export = "4800"]
| ^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:248:17
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:247:17
|
-248 | mod inner { #![plugin_registrar="4700"] }
+247 | mod inner { #![plugin_registrar="4700"] }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:253:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:252:5
|
-253 | #[plugin_registrar = "4700"] struct S;
+252 | #[plugin_registrar = "4700"] struct S;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:256:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:255:5
|
-256 | #[plugin_registrar = "4700"] type T = S;
+255 | #[plugin_registrar = "4700"] type T = S;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:259:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:258:5
|
-259 | #[plugin_registrar = "4700"] impl S { }
+258 | #[plugin_registrar = "4700"] impl S { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:245:1
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:244:1
|
-245 | #[plugin_registrar = "4700"]
+244 | #[plugin_registrar = "4700"]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:266:17
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:265:17
|
-266 | mod inner { #![main="4300"] }
+265 | mod inner { #![main="4300"] }
| ^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:271:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:270:5
|
-271 | #[main = "4400"] struct S;
+270 | #[main = "4400"] struct S;
| ^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:274:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:273:5
|
-274 | #[main = "4400"] type T = S;
+273 | #[main = "4400"] type T = S;
| ^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:277:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:276:5
|
-277 | #[main = "4400"] impl S { }
+276 | #[main = "4400"] impl S { }
| ^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:263:1
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:262:1
|
-263 | #[main = "4400"]
+262 | #[main = "4400"]
| ^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:284:17
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:283:17
|
-284 | mod inner { #![start="4300"] }
+283 | mod inner { #![start="4300"] }
| ^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:289:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:288:5
|
-289 | #[start = "4300"] struct S;
+288 | #[start = "4300"] struct S;
| ^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:292:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:291:5
|
-292 | #[start = "4300"] type T = S;
+291 | #[start = "4300"] type T = S;
| ^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:295:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:294:5
|
-295 | #[start = "4300"] impl S { }
+294 | #[start = "4300"] impl S { }
| ^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:281:1
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:280:1
|
-281 | #[start = "4300"]
+280 | #[start = "4300"]
| ^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:334:17
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:333:17
|
-334 | mod inner { #![simd="4000"] }
+333 | mod inner { #![repr="3900"] }
| ^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:337:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:336:5
|
-337 | #[simd = "4000"] fn f() { }
+336 | #[repr = "3900"] fn f() { }
| ^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:342:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:341:5
|
-342 | #[simd = "4000"] type T = S;
+341 | #[repr = "3900"] type T = S;
| ^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:345:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:344:5
|
-345 | #[simd = "4000"] impl S { }
+344 | #[repr = "3900"] impl S { }
| ^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:331:1
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:330:1
|
-331 | #[simd = "4000"]
+330 | #[repr = "3900"]
| ^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:352:17
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:352:5
|
-352 | mod inner { #![repr="3900"] }
- | ^^^^^^^^^^^^^^^
-
-warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:355:5
- |
-355 | #[repr = "3900"] fn f() { }
+352 | #[path = "3800"] fn f() { }
| ^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:360:5
- |
-360 | #[repr = "3900"] type T = S;
- | ^^^^^^^^^^^^^^^^
-
-warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:363:5
- |
-363 | #[repr = "3900"] impl S { }
- | ^^^^^^^^^^^^^^^^
-
-warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:349:1
- |
-349 | #[repr = "3900"]
- | ^^^^^^^^^^^^^^^^
-
-warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:371:5
- |
-371 | #[path = "3800"] fn f() { }
- | ^^^^^^^^^^^^^^^^
-
-warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:374:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:355:5
|
-374 | #[path = "3800"] struct S;
+355 | #[path = "3800"] struct S;
| ^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:377:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:358:5
|
-377 | #[path = "3800"] type T = S;
+358 | #[path = "3800"] type T = S;
| ^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:380:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:361:5
|
-380 | #[path = "3800"] impl S { }
+361 | #[path = "3800"] impl S { }
| ^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:387:17
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:368:17
|
-387 | mod inner { #![abi="3700"] }
+368 | mod inner { #![abi="3700"] }
| ^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:390:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:371:5
|
-390 | #[abi = "3700"] fn f() { }
+371 | #[abi = "3700"] fn f() { }
| ^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:393:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:374:5
|
-393 | #[abi = "3700"] struct S;
+374 | #[abi = "3700"] struct S;
| ^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:396:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:377:5
|
-396 | #[abi = "3700"] type T = S;
+377 | #[abi = "3700"] type T = S;
| ^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:399:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:380:5
|
-399 | #[abi = "3700"] impl S { }
+380 | #[abi = "3700"] impl S { }
| ^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:384:1
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:365:1
|
-384 | #[abi = "3700"]
+365 | #[abi = "3700"]
| ^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:406:17
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:387:17
|
-406 | mod inner { #![automatically_derived="3600"] }
+387 | mod inner { #![automatically_derived="3600"] }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:409:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:390:5
|
-409 | #[automatically_derived = "3600"] fn f() { }
+390 | #[automatically_derived = "3600"] fn f() { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:412:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:393:5
|
-412 | #[automatically_derived = "3600"] struct S;
+393 | #[automatically_derived = "3600"] struct S;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:415:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:396:5
|
-415 | #[automatically_derived = "3600"] type T = S;
+396 | #[automatically_derived = "3600"] type T = S;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:418:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:399:5
|
-418 | #[automatically_derived = "3600"] impl S { }
+399 | #[automatically_derived = "3600"] impl S { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:403:1
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:384:1
|
-403 | #[automatically_derived = "3600"]
+384 | #[automatically_derived = "3600"]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: function is marked #[no_mangle], but not exported
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:426:27
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:407:27
|
-426 | #[no_mangle = "3500"] fn f() { }
+407 | #[no_mangle = "3500"] fn f() { }
| -^^^^^^^^^
| |
| help: try making it public: `pub`
= note: #[warn(private_no_mangle_fns)] on by default
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:439:17
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:420:17
|
-439 | mod inner { #![no_link="3400"] }
+420 | mod inner { #![no_link="3400"] }
| ^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:442:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:423:5
|
-442 | #[no_link = "3400"] fn f() { }
+423 | #[no_link = "3400"] fn f() { }
| ^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:445:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:426:5
|
-445 | #[no_link = "3400"] struct S;
+426 | #[no_link = "3400"] struct S;
| ^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:448:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:429:5
|
-448 | #[no_link = "3400"]type T = S;
+429 | #[no_link = "3400"]type T = S;
| ^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:451:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:432:5
|
-451 | #[no_link = "3400"] impl S { }
+432 | #[no_link = "3400"] impl S { }
| ^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:436:1
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:417:1
|
-436 | #[no_link = "3400"]
+417 | #[no_link = "3400"]
| ^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:458:17
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:439:17
|
-458 | mod inner { #![should_panic="3200"] }
+439 | mod inner { #![should_panic="3200"] }
| ^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:461:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:442:5
|
-461 | #[should_panic = "3200"] fn f() { }
+442 | #[should_panic = "3200"] fn f() { }
| ^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:464:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:445:5
|
-464 | #[should_panic = "3200"] struct S;
+445 | #[should_panic = "3200"] struct S;
| ^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:467:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:448:5
|
-467 | #[should_panic = "3200"] type T = S;
+448 | #[should_panic = "3200"] type T = S;
| ^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:470:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:451:5
|
-470 | #[should_panic = "3200"] impl S { }
+451 | #[should_panic = "3200"] impl S { }
| ^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:455:1
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:436:1
|
-455 | #[should_panic = "3200"]
+436 | #[should_panic = "3200"]
| ^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:477:17
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:458:17
|
-477 | mod inner { #![ignore="3100"] }
+458 | mod inner { #![ignore="3100"] }
| ^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:480:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:461:5
|
-480 | #[ignore = "3100"] fn f() { }
+461 | #[ignore = "3100"] fn f() { }
| ^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:483:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:464:5
|
-483 | #[ignore = "3100"] struct S;
+464 | #[ignore = "3100"] struct S;
| ^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:486:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:467:5
|
-486 | #[ignore = "3100"] type T = S;
+467 | #[ignore = "3100"] type T = S;
| ^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:489:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:470:5
|
-489 | #[ignore = "3100"] impl S { }
+470 | #[ignore = "3100"] impl S { }
| ^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:474:1
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:455:1
|
-474 | #[ignore = "3100"]
+455 | #[ignore = "3100"]
| ^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:496:17
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:477:17
|
-496 | mod inner { #![no_implicit_prelude="3000"] }
+477 | mod inner { #![no_implicit_prelude="3000"] }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:499:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:480:5
|
-499 | #[no_implicit_prelude = "3000"] fn f() { }
+480 | #[no_implicit_prelude = "3000"] fn f() { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:502:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:483:5
|
-502 | #[no_implicit_prelude = "3000"] struct S;
+483 | #[no_implicit_prelude = "3000"] struct S;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:505:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:486:5
|
-505 | #[no_implicit_prelude = "3000"] type T = S;
+486 | #[no_implicit_prelude = "3000"] type T = S;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:508:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:489:5
|
-508 | #[no_implicit_prelude = "3000"] impl S { }
+489 | #[no_implicit_prelude = "3000"] impl S { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:493:1
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:474:1
|
-493 | #[no_implicit_prelude = "3000"]
+474 | #[no_implicit_prelude = "3000"]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:515:17
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:496:17
|
-515 | mod inner { #![reexport_test_harness_main="2900"] }
+496 | mod inner { #![reexport_test_harness_main="2900"] }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:518:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:499:5
|
-518 | #[reexport_test_harness_main = "2900"] fn f() { }
+499 | #[reexport_test_harness_main = "2900"] fn f() { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:521:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:502:5
|
-521 | #[reexport_test_harness_main = "2900"] struct S;
+502 | #[reexport_test_harness_main = "2900"] struct S;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:524:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:505:5
|
-524 | #[reexport_test_harness_main = "2900"] type T = S;
+505 | #[reexport_test_harness_main = "2900"] type T = S;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:527:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:508:5
|
-527 | #[reexport_test_harness_main = "2900"] impl S { }
+508 | #[reexport_test_harness_main = "2900"] impl S { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:512:1
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:493:1
|
-512 | #[reexport_test_harness_main = "2900"]
+493 | #[reexport_test_harness_main = "2900"]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:538:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:519:5
|
-538 | #[macro_escape] fn f() { }
+519 | #[macro_escape] fn f() { }
| ^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:541:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:522:5
|
-541 | #[macro_escape] struct S;
+522 | #[macro_escape] struct S;
| ^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:544:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:525:5
|
-544 | #[macro_escape] type T = S;
+525 | #[macro_escape] type T = S;
| ^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:547:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:528:5
|
-547 | #[macro_escape] impl S { }
+528 | #[macro_escape] impl S { }
| ^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:555:17
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:536:17
|
-555 | mod inner { #![no_std="2600"] }
+536 | mod inner { #![no_std="2600"] }
| ^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be in the root module
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:555:17
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:536:17
|
-555 | mod inner { #![no_std="2600"] }
+536 | mod inner { #![no_std="2600"] }
| ^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:559:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:540:5
|
-559 | #[no_std = "2600"] fn f() { }
+540 | #[no_std = "2600"] fn f() { }
| ^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:559:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:540:5
|
-559 | #[no_std = "2600"] fn f() { }
+540 | #[no_std = "2600"] fn f() { }
| ^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:563:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:544:5
|
-563 | #[no_std = "2600"] struct S;
+544 | #[no_std = "2600"] struct S;
| ^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:563:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:544:5
|
-563 | #[no_std = "2600"] struct S;
+544 | #[no_std = "2600"] struct S;
| ^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:567:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:548:5
|
-567 | #[no_std = "2600"] type T = S;
+548 | #[no_std = "2600"] type T = S;
| ^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:567:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:548:5
|
-567 | #[no_std = "2600"] type T = S;
+548 | #[no_std = "2600"] type T = S;
| ^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:571:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:552:5
|
-571 | #[no_std = "2600"] impl S { }
+552 | #[no_std = "2600"] impl S { }
| ^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:571:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:552:5
|
-571 | #[no_std = "2600"] impl S { }
+552 | #[no_std = "2600"] impl S { }
| ^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:551:1
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:532:1
|
-551 | #[no_std = "2600"]
+532 | #[no_std = "2600"]
| ^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:551:1
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:532:1
|
-551 | #[no_std = "2600"]
+532 | #[no_std = "2600"]
| ^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:711:17
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:692:17
|
-711 | mod inner { #![crate_name="0900"] }
+692 | mod inner { #![crate_name="0900"] }
| ^^^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be in the root module
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:711:17
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:692:17
|
-711 | mod inner { #![crate_name="0900"] }
+692 | mod inner { #![crate_name="0900"] }
| ^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:715:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:696:5
|
-715 | #[crate_name = "0900"] fn f() { }
+696 | #[crate_name = "0900"] fn f() { }
| ^^^^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:715:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:696:5
|
-715 | #[crate_name = "0900"] fn f() { }
+696 | #[crate_name = "0900"] fn f() { }
| ^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:719:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:700:5
|
-719 | #[crate_name = "0900"] struct S;
+700 | #[crate_name = "0900"] struct S;
| ^^^^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:719:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:700:5
|
-719 | #[crate_name = "0900"] struct S;
+700 | #[crate_name = "0900"] struct S;
| ^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:723:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:704:5
|
-723 | #[crate_name = "0900"] type T = S;
+704 | #[crate_name = "0900"] type T = S;
| ^^^^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:723:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:704:5
|
-723 | #[crate_name = "0900"] type T = S;
+704 | #[crate_name = "0900"] type T = S;
| ^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:727:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:708:5
|
-727 | #[crate_name = "0900"] impl S { }
+708 | #[crate_name = "0900"] impl S { }
| ^^^^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:727:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:708:5
|
-727 | #[crate_name = "0900"] impl S { }
+708 | #[crate_name = "0900"] impl S { }
| ^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:707:1
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:688:1
|
-707 | #[crate_name = "0900"]
+688 | #[crate_name = "0900"]
| ^^^^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:707:1
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:688:1
|
-707 | #[crate_name = "0900"]
+688 | #[crate_name = "0900"]
| ^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:736:17
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:717:17
|
-736 | mod inner { #![crate_type="0800"] }
+717 | mod inner { #![crate_type="0800"] }
| ^^^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be in the root module
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:736:17
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:717:17
|
-736 | mod inner { #![crate_type="0800"] }
+717 | mod inner { #![crate_type="0800"] }
| ^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:740:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:721:5
|
-740 | #[crate_type = "0800"] fn f() { }
+721 | #[crate_type = "0800"] fn f() { }
| ^^^^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:740:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:721:5
|
-740 | #[crate_type = "0800"] fn f() { }
+721 | #[crate_type = "0800"] fn f() { }
| ^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:744:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:725:5
|
-744 | #[crate_type = "0800"] struct S;
+725 | #[crate_type = "0800"] struct S;
| ^^^^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:744:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:725:5
|
-744 | #[crate_type = "0800"] struct S;
+725 | #[crate_type = "0800"] struct S;
| ^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:748:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:729:5
|
-748 | #[crate_type = "0800"] type T = S;
+729 | #[crate_type = "0800"] type T = S;
| ^^^^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:748:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:729:5
|
-748 | #[crate_type = "0800"] type T = S;
+729 | #[crate_type = "0800"] type T = S;
| ^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:752:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:733:5
|
-752 | #[crate_type = "0800"] impl S { }
+733 | #[crate_type = "0800"] impl S { }
| ^^^^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:752:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:733:5
|
-752 | #[crate_type = "0800"] impl S { }
+733 | #[crate_type = "0800"] impl S { }
| ^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:732:1
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:713:1
|
-732 | #[crate_type = "0800"]
+713 | #[crate_type = "0800"]
| ^^^^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:732:1
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:713:1
|
-732 | #[crate_type = "0800"]
+713 | #[crate_type = "0800"]
| ^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:761:17
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:742:17
|
-761 | mod inner { #![feature(x0600)] }
+742 | mod inner { #![feature(x0600)] }
| ^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be in the root module
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:761:17
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:742:17
|
-761 | mod inner { #![feature(x0600)] }
+742 | mod inner { #![feature(x0600)] }
| ^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:765:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:746:5
|
-765 | #[feature(x0600)] fn f() { }
+746 | #[feature(x0600)] fn f() { }
| ^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:765:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:746:5
|
-765 | #[feature(x0600)] fn f() { }
+746 | #[feature(x0600)] fn f() { }
| ^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:769:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:750:5
|
-769 | #[feature(x0600)] struct S;
+750 | #[feature(x0600)] struct S;
| ^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:769:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:750:5
|
-769 | #[feature(x0600)] struct S;
+750 | #[feature(x0600)] struct S;
| ^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:773:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:754:5
|
-773 | #[feature(x0600)] type T = S;
+754 | #[feature(x0600)] type T = S;
| ^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:773:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:754:5
|
-773 | #[feature(x0600)] type T = S;
+754 | #[feature(x0600)] type T = S;
| ^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:777:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:758:5
|
-777 | #[feature(x0600)] impl S { }
+758 | #[feature(x0600)] impl S { }
| ^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:777:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:758:5
|
-777 | #[feature(x0600)] impl S { }
+758 | #[feature(x0600)] impl S { }
| ^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:757:1
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:738:1
|
-757 | #[feature(x0600)]
+738 | #[feature(x0600)]
| ^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:757:1
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:738:1
|
-757 | #[feature(x0600)]
+738 | #[feature(x0600)]
| ^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:787:17
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:768:17
|
-787 | mod inner { #![no_main="0400"] }
+768 | mod inner { #![no_main="0400"] }
| ^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be in the root module
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:787:17
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:768:17
|
-787 | mod inner { #![no_main="0400"] }
+768 | mod inner { #![no_main="0400"] }
| ^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:791:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:772:5
|
-791 | #[no_main = "0400"] fn f() { }
+772 | #[no_main = "0400"] fn f() { }
| ^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:791:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:772:5
|
-791 | #[no_main = "0400"] fn f() { }
+772 | #[no_main = "0400"] fn f() { }
| ^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:795:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:776:5
|
-795 | #[no_main = "0400"] struct S;
+776 | #[no_main = "0400"] struct S;
| ^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:795:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:776:5
|
-795 | #[no_main = "0400"] struct S;
+776 | #[no_main = "0400"] struct S;
| ^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:799:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:780:5
|
-799 | #[no_main = "0400"] type T = S;
+780 | #[no_main = "0400"] type T = S;
| ^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:799:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:780:5
|
-799 | #[no_main = "0400"] type T = S;
+780 | #[no_main = "0400"] type T = S;
| ^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:803:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:784:5
|
-803 | #[no_main = "0400"] impl S { }
+784 | #[no_main = "0400"] impl S { }
| ^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:803:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:784:5
|
-803 | #[no_main = "0400"] impl S { }
+784 | #[no_main = "0400"] impl S { }
| ^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:783:1
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:764:1
|
-783 | #[no_main = "0400"]
+764 | #[no_main = "0400"]
| ^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:783:1
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:764:1
|
-783 | #[no_main = "0400"]
+764 | #[no_main = "0400"]
| ^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:825:17
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:806:17
|
-825 | mod inner { #![recursion_limit="0200"] }
+806 | mod inner { #![recursion_limit="0200"] }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be in the root module
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:825:17
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:806:17
|
-825 | mod inner { #![recursion_limit="0200"] }
+806 | mod inner { #![recursion_limit="0200"] }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:829:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:810:5
|
-829 | #[recursion_limit="0200"] fn f() { }
+810 | #[recursion_limit="0200"] fn f() { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:829:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:810:5
|
-829 | #[recursion_limit="0200"] fn f() { }
+810 | #[recursion_limit="0200"] fn f() { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:833:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:814:5
|
-833 | #[recursion_limit="0200"] struct S;
+814 | #[recursion_limit="0200"] struct S;
| ^^^^^^^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:833:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:814:5
|
-833 | #[recursion_limit="0200"] struct S;
+814 | #[recursion_limit="0200"] struct S;
| ^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:837:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:818:5
|
-837 | #[recursion_limit="0200"] type T = S;
+818 | #[recursion_limit="0200"] type T = S;
| ^^^^^^^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:837:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:818:5
|
-837 | #[recursion_limit="0200"] type T = S;
+818 | #[recursion_limit="0200"] type T = S;
| ^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:841:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:822:5
|
-841 | #[recursion_limit="0200"] impl S { }
+822 | #[recursion_limit="0200"] impl S { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:841:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:822:5
|
-841 | #[recursion_limit="0200"] impl S { }
+822 | #[recursion_limit="0200"] impl S { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:821:1
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:802:1
|
-821 | #[recursion_limit="0200"]
+802 | #[recursion_limit="0200"]
| ^^^^^^^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:821:1
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:802:1
|
-821 | #[recursion_limit="0200"]
+802 | #[recursion_limit="0200"]
| ^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:850:17
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:831:17
|
-850 | mod inner { #![type_length_limit="0100"] }
+831 | mod inner { #![type_length_limit="0100"] }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be in the root module
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:850:17
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:831:17
|
-850 | mod inner { #![type_length_limit="0100"] }
+831 | mod inner { #![type_length_limit="0100"] }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:854:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:835:5
|
-854 | #[type_length_limit="0100"] fn f() { }
+835 | #[type_length_limit="0100"] fn f() { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:854:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:835:5
|
-854 | #[type_length_limit="0100"] fn f() { }
+835 | #[type_length_limit="0100"] fn f() { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:858:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:839:5
|
-858 | #[type_length_limit="0100"] struct S;
+839 | #[type_length_limit="0100"] struct S;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:858:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:839:5
|
-858 | #[type_length_limit="0100"] struct S;
+839 | #[type_length_limit="0100"] struct S;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:862:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:843:5
|
-862 | #[type_length_limit="0100"] type T = S;
+843 | #[type_length_limit="0100"] type T = S;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:862:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:843:5
|
-862 | #[type_length_limit="0100"] type T = S;
+843 | #[type_length_limit="0100"] type T = S;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:866:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:847:5
|
-866 | #[type_length_limit="0100"] impl S { }
+847 | #[type_length_limit="0100"] impl S { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:866:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:847:5
|
-866 | #[type_length_limit="0100"] impl S { }
+847 | #[type_length_limit="0100"] impl S { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:846:1
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:827:1
|
-846 | #[type_length_limit="0100"]
+827 | #[type_length_limit="0100"]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:846:1
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:827:1
|
-846 | #[type_length_limit="0100"]
+827 | #[type_length_limit="0100"]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
warning: unused attribute
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:63:1
|
-63 | #![simd = "4000"] //~ WARN unused attribute
+63 | #![repr = "3900"] //~ WARN unused attribute
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:64:1
|
-64 | #![repr = "3900"] //~ WARN unused attribute
+64 | #![path = "3800"] //~ WARN unused attribute
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:65:1
|
-65 | #![path = "3800"] //~ WARN unused attribute
+65 | #![abi = "3700"] //~ WARN unused attribute
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:66:1
|
-66 | #![abi = "3700"] //~ WARN unused attribute
+66 | #![automatically_derived = "3600"] //~ WARN unused attribute
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:67:1
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:68:1
|
-67 | #![automatically_derived = "3600"] //~ WARN unused attribute
+68 | #![no_link = "3400"] //~ WARN unused attribute
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:69:1
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:70:1
|
-69 | #![no_link = "3400"] //~ WARN unused attribute
+70 | #![should_panic = "3200"] //~ WARN unused attribute
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:71:1
|
-71 | #![should_panic = "3200"] //~ WARN unused attribute
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:72:1
- |
-72 | #![ignore = "3100"] //~ WARN unused attribute
+71 | #![ignore = "3100"] //~ WARN unused attribute
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:78:1
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:77:1
|
-78 | #![proc_macro_derive = "2500"] //~ WARN unused attribute
+77 | #![proc_macro_derive = "2500"] //~ WARN unused attribute
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: compilation successful
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:877:1
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:858:1
|
-877 | / fn main() { //~ ERROR compilation successful
-878 | | println!("Hello World");
-879 | | }
+858 | / fn main() { //~ ERROR compilation successful
+859 | | println!("Hello World");
+860 | | }
| |_^
+error[E0601]: main function not found
+
error[E0518]: attribute should be applied to function
--> $DIR/issue-43106-gating-of-inline.rs:21:1
|
35 | #[inline = "2100"] impl S { }
| ^^^^^^^^^^^^^^^^^^ ---------- not a function
-error[E0601]: main function not found
-
error: aborting due to 6 previous errors
= note: required because it appears within the type `[std::fmt::ArgumentV1<'_>]`
= note: required because of the requirements on the impl of `std::marker::Send` for `&[std::fmt::ArgumentV1<'_>]`
= note: required because it appears within the type `std::fmt::Arguments<'_>`
- = note: required by `send`
+note: required by `send`
+ --> $DIR/send-sync.rs:11:1
+ |
+11 | fn send<T: Send>(_: T) {}
+ | ^^^^^^^^^^^^^^^^^^^^^^
error[E0277]: the trait bound `*mut std::ops::Fn() + 'static: std::marker::Sync` is not satisfied in `std::fmt::Arguments<'_>`
--> $DIR/send-sync.rs:19:5
= note: required because it appears within the type `[std::fmt::ArgumentV1<'_>]`
= note: required because it appears within the type `&[std::fmt::ArgumentV1<'_>]`
= note: required because it appears within the type `std::fmt::Arguments<'_>`
- = note: required by `sync`
+note: required by `sync`
+ --> $DIR/send-sync.rs:12:1
+ |
+12 | fn sync<T: Sync>(_: T) {}
+ | ^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 2 previous errors
= help: the trait `std::marker::Sync` is not implemented for `std::cell::Cell<i32>`
= note: required because of the requirements on the impl of `std::marker::Send` for `&std::cell::Cell<i32>`
= note: required because it appears within the type `[generator@$DIR/not-send-sync.rs:26:17: 30:6 a:&std::cell::Cell<i32> _]`
- = note: required by `main::assert_send`
+note: required by `main::assert_send`
+ --> $DIR/not-send-sync.rs:17:5
+ |
+17 | fn assert_send<T: Send>(_: T) {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0277]: the trait bound `std::cell::Cell<i32>: std::marker::Sync` is not satisfied in `[generator@$DIR/not-send-sync.rs:19:17: 23:6 (std::cell::Cell<i32>, ())]`
--> $DIR/not-send-sync.rs:19:5
= help: within `[generator@$DIR/not-send-sync.rs:19:17: 23:6 (std::cell::Cell<i32>, ())]`, the trait `std::marker::Sync` is not implemented for `std::cell::Cell<i32>`
= note: required because it appears within the type `(std::cell::Cell<i32>, ())`
= note: required because it appears within the type `[generator@$DIR/not-send-sync.rs:19:17: 23:6 (std::cell::Cell<i32>, ())]`
- = note: required by `main::assert_sync`
+note: required by `main::assert_sync`
+ --> $DIR/not-send-sync.rs:16:5
+ |
+16 | fn assert_sync<T: Sync>(_: T) {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 2 previous errors
= help: within `impl std::ops::Fn<(i32,)>`, the trait `std::marker::Send` is not implemented for `std::rc::Rc<std::cell::Cell<i32>>`
= note: required because it appears within the type `[closure@$DIR/auto-trait-leak.rs:21:5: 21:22 p:std::rc::Rc<std::cell::Cell<i32>>]`
= note: required because it appears within the type `impl std::ops::Fn<(i32,)>`
- = note: required by `send`
+note: required by `send`
+ --> $DIR/auto-trait-leak.rs:24:1
+ |
+24 | fn send<T: Send>(_: T) {}
+ | ^^^^^^^^^^^^^^^^^^^^^^
error[E0277]: the trait bound `std::rc::Rc<std::cell::Cell<i32>>: std::marker::Send` is not satisfied in `impl std::ops::Fn<(i32,)>`
--> $DIR/auto-trait-leak.rs:30:5
= help: within `impl std::ops::Fn<(i32,)>`, the trait `std::marker::Send` is not implemented for `std::rc::Rc<std::cell::Cell<i32>>`
= note: required because it appears within the type `[closure@$DIR/auto-trait-leak.rs:38:5: 38:22 p:std::rc::Rc<std::cell::Cell<i32>>]`
= note: required because it appears within the type `impl std::ops::Fn<(i32,)>`
- = note: required by `send`
+note: required by `send`
+ --> $DIR/auto-trait-leak.rs:24:1
+ |
+24 | fn send<T: Send>(_: T) {}
+ | ^^^^^^^^^^^^^^^^^^^^^^
error[E0391]: unsupported cyclic reference between types/traits detected
--> $DIR/auto-trait-leak.rs:44:1
14 | impl <'l0, 'l1, T0> Trait1<'l0, T0> for bool where T0 : Trait0<'l0>, T0 : Trait0<'l1> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: required by `Trait0`
+note: required by `Trait0`
+ --> $DIR/issue-24424.rs:12:1
+ |
+12 | trait Trait0<'l0> {}
+ | ^^^^^^^^^^^^^^^^^
error: aborting due to previous error
impl issue_41652_b::Tr for S {
fn f() {
3.f()
- //~^ ERROR no method named `f` found for type `{integer}` in the current scope
+ //~^ ERROR can't call method `f` on ambiguous numeric type `{integer}`
}
}
-error[E0599]: no method named `f` found for type `{integer}` in the current scope
+error[E0689]: can't call method `f` on ambiguous numeric type `{integer}`
--> $DIR/issue_41652.rs:19:11
|
19 | 3.f()
| ^
+help: you must specify a concrete type for this numeric value, like `i32`
|
- = note: found the following associated functions; to be used as methods, functions must have a `self` parameter
- = help: try with `{integer}::f`
-note: candidate #1 is defined in the trait `issue_41652_b::Tr`
- --> $DIR/auxiliary/issue_41652_b.rs:14:5
- |
-14 | / fn f()
-15 | | where Self: Sized;
- | |__________________________^
- = help: to disambiguate the method call, write `issue_41652_b::Tr::f(3)` instead
+19 | 3_i32.f()
+ | ^^^^^
error: aborting due to previous error
--> $DIR/issue-44406.rs:18:10
|
18 | foo!(true); //~ ERROR expected type, found keyword
- | ^^^^
+ | ^^^^ expected identifier, found keyword
error: expected type, found keyword `true`
--> $DIR/issue-44406.rs:18:10
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// Issue 46112: An extern crate pub reexporting libcore was causing
+// Issue 46112: An extern crate pub re-exporting libcore was causing
// paths rooted from `std` to be misrendered in the diagnostic output.
// ignore-windows
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <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(nll)]
+
+fn foo(x: &u32) -> &'static u32 {
+ &*x
+ //~^ ERROR explicit lifetime required in the type of `x` [E0621]
+}
+
+fn main() {}
--- /dev/null
+error[E0621]: explicit lifetime required in the type of `x`
+ --> $DIR/issue-46983.rs:14:5
+ |
+13 | fn foo(x: &u32) -> &'static u32 {
+ | - consider changing the type of `x` to `&'static u32`
+14 | &*x
+ | ^^^ lifetime `'static` required
+
+error: aborting due to previous error
+
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <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.
+// ignore-tidy-tab
+fn main() {
+ let b = "hello";
+ let _a = b + ", World!";
+ //~^ ERROR E0369
+}
--- /dev/null
+error[E0369]: binary operation `+` cannot be applied to type `&str`
+ --> $DIR/issue-47377.rs:13:12
+ |
+13 | let _a = b + ", World!";
+ | ^^^^^^^^^^^^^^ `+` can't be used to concatenate two `&str` strings
+help: `to_owned()` can be used to create an owned `String` from a string reference. String concatenation appends the string on the right to the string on the left and may require reallocation. This requires ownership of the string on the left
+ |
+13 | let _a = b.to_owned() + ", World!";
+ | ^^^^^^^^^^^^
+
+error: aborting due to previous error
+
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <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 b = "hello";
+ println!("🦀🦀🦀🦀🦀"); let _a = b + ", World!";
+ //~^ ERROR E0369
+}
--- /dev/null
+error[E0369]: binary operation `+` cannot be applied to type `&str`
+ --> $DIR/issue-47380.rs:12:33
+ |
+12 | println!("🦀🦀🦀🦀🦀"); let _a = b + ", World!";
+ | ^^^^^^^^^^^^^^ `+` can't be used to concatenate two `&str` strings
+help: `to_owned()` can be used to create an owned `String` from a string reference. String concatenation appends the string on the right to the string on the left and may require reallocation. This requires ownership of the string on the left
+ |
+12 | println!("🦀🦀🦀🦀🦀"); let _a = b.to_owned() + ", World!";
+ | ^^^^^^^^^^^^
+
+error: aborting due to previous error
+
fn rio_grande() {} // should suggest `pub`
//~^ WARN function is marked
+mod badlands {
+ // The private-no-mangle lints shouldn't suggest inserting `pub` when the
+ // item is already `pub` (but triggered the lint because, e.g., it's in a
+ // private module). (Issue #47383)
+ #[no_mangle] pub static DAUNTLESS: bool = true;
+ //~^ WARN static is marked
+ #[no_mangle] pub fn val_jean() {}
+ //~^ WARN function is marked
+}
+
struct Equinox {
warp_factor: f32,
}
warning: unnecessary parentheses around assigned value
- --> $DIR/suggestions.rs:36:21
+ --> $DIR/suggestions.rs:46:21
|
-36 | let mut a = (1); // should suggest no `mut`, no parens
+46 | let mut a = (1); // should suggest no `mut`, no parens
| ^^^ help: remove these parentheses
|
note: lint level defined here
| ^^^^^^^^^^^^^
warning: use of deprecated attribute `no_debug`: the `#[no_debug]` attribute was an experimental feature that has been deprecated due to lack of demand. See https://github.com/rust-lang/rust/issues/29721
- --> $DIR/suggestions.rs:31:1
+ --> $DIR/suggestions.rs:41:1
|
-31 | #[no_debug] // should suggest removal of deprecated attribute
+41 | #[no_debug] // should suggest removal of deprecated attribute
| ^^^^^^^^^^^ help: remove this attribute
|
= note: #[warn(deprecated)] on by default
warning: variable does not need to be mutable
- --> $DIR/suggestions.rs:36:13
+ --> $DIR/suggestions.rs:46:13
|
-36 | let mut a = (1); // should suggest no `mut`, no parens
+46 | let mut a = (1); // should suggest no `mut`, no parens
| ---^^
| |
| help: remove this `mut`
|
= note: #[warn(private_no_mangle_fns)] on by default
+warning: static is marked #[no_mangle], but not exported
+ --> $DIR/suggestions.rs:31:18
+ |
+31 | #[no_mangle] pub static DAUNTLESS: bool = true;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: function is marked #[no_mangle], but not exported
+ --> $DIR/suggestions.rs:33:18
+ |
+33 | #[no_mangle] pub fn val_jean() {}
+ | ^^^^^^^^^^^^^^^^^^^^
+
warning: denote infinite loops with `loop { ... }`
- --> $DIR/suggestions.rs:34:5
+ --> $DIR/suggestions.rs:44:5
|
-34 | while true { // should suggest `loop`
+44 | while true { // should suggest `loop`
| ^^^^^^^^^^ help: use `loop`
|
= note: #[warn(while_true)] on by default
warning: the `warp_factor:` in this pattern is redundant
- --> $DIR/suggestions.rs:41:23
+ --> $DIR/suggestions.rs:51:23
|
-41 | Equinox { warp_factor: warp_factor } => {} // should suggest shorthand
+51 | Equinox { warp_factor: warp_factor } => {} // should suggest shorthand
| ------------^^^^^^^^^^^^
| |
| help: remove this
// except according to those terms.
fn main() {
- println!("%.*3$s %s!\n", "Hello,", "World", 4);
+ println!("%.*3$s %s!\n", "Hello,", "World", 4); //~ ERROR multiple unused formatting arguments
println!("%1$*2$.*3$f", 123.456); //~ ERROR never used
// This should *not* produce hints, on the basis that there's equally as
error: multiple unused formatting arguments
- --> $DIR/format-foreign.rs:12:5
+ --> $DIR/format-foreign.rs:12:30
|
-12 | println!("%.*3$s %s!/n", "Hello,", "World", 4);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^--------^^-------^^-^^
- | | | |
- | | | unused
- | | unused
- | unused
+12 | println!("%.*3$s %s!/n", "Hello,", "World", 4); //~ ERROR multiple unused formatting arguments
+ | -------------------------^^^^^^^^--^^^^^^^--^-- multiple unused arguments in this statement
|
= help: `%.*3$s` should be written as `{:.2$}`
= help: `%s` should be written as `{}`
fn main() {
println!("Test", 123, 456, 789);
+ //~^ ERROR multiple unused formatting arguments
println!("Test2",
- 123,
+ 123, //~ ERROR multiple unused formatting arguments
456,
789
);
println!("Some stuff", UNUSED="args"); //~ ERROR named argument never used
println!("Some more $STUFF",
- "woo!",
+ "woo!", //~ ERROR multiple unused formatting arguments
STUFF=
"things"
, UNUSED="args");
error: multiple unused formatting arguments
- --> $DIR/format-unused-lables.rs:12:5
+ --> $DIR/format-unused-lables.rs:12:22
|
12 | println!("Test", 123, 456, 789);
- | ^^^^^^^^^^^^^^^^^---^^---^^---^^
- | | | |
- | | | unused
- | | unused
- | unused
+ | -----------------^^^--^^^--^^^-- multiple unused arguments in this statement
|
= 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: multiple unused formatting arguments
- --> $DIR/format-unused-lables.rs:14:5
+ --> $DIR/format-unused-lables.rs:16:9
|
-14 | / println!("Test2",
-15 | | 123,
- | | --- unused
-16 | | 456,
- | | --- unused
-17 | | 789
- | | --- unused
-18 | | );
- | |______^
+15 | / println!("Test2",
+16 | | 123, //~ ERROR multiple unused formatting arguments
+ | | ^^^
+17 | | 456,
+ | | ^^^
+18 | | 789
+ | | ^^^
+19 | | );
+ | |______- multiple unused arguments in this statement
|
= 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: named argument never used
- --> $DIR/format-unused-lables.rs:20:35
+ --> $DIR/format-unused-lables.rs:21:35
|
-20 | println!("Some stuff", UNUSED="args"); //~ ERROR named argument never used
+21 | println!("Some stuff", UNUSED="args"); //~ ERROR named argument never used
| ^^^^^^
error: multiple unused formatting arguments
- --> $DIR/format-unused-lables.rs:22:5
+ --> $DIR/format-unused-lables.rs:24:9
|
-22 | / println!("Some more $STUFF",
-23 | | "woo!",
- | | ------ unused
-24 | | STUFF=
-25 | | "things"
- | | -------- unused
-26 | | , UNUSED="args");
- | |_______________________------_^
- | |
- | unused
+23 | / println!("Some more $STUFF",
+24 | | "woo!", //~ ERROR multiple unused formatting arguments
+ | | ^^^^^^
+25 | | STUFF=
+26 | | "things"
+ | | ^^^^^^^^
+27 | | , UNUSED="args");
+ | |_______________________^^^^^^_- multiple unused arguments in this statement
|
= help: `$STUFF` should be written as `{STUFF}`
= note: shell formatting not supported; see the documentation for `std::fmt`
}
}
+macro_rules! real_method_stmt {
+ () => {
+ 2.0.powi(2) //~ ERROR can't call method `powi` on ambiguous numeric type `{float}`
+ }
+}
+
+macro_rules! real_method_expr {
+ () => {
+ 2.0.powi(2) //~ ERROR can't call method `powi` on ambiguous numeric type `{float}`
+ }
+}
+
fn main() {
fake_method_stmt!();
fake_field_stmt!();
fake_anon_field_stmt!();
+ real_method_stmt!();
let _ = fake_method_expr!();
let _ = fake_field_expr!();
let _ = fake_anon_field_expr!();
+ let _ = real_method_expr!();
}
15 | 1.fake() //~ ERROR no method
| ^^^^
...
-50 | fake_method_stmt!();
+62 | fake_method_stmt!();
| -------------------- in this macro invocation
error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields
21 | 1.fake //~ ERROR doesn't have fields
| ^^^^
...
-51 | fake_field_stmt!();
+63 | fake_field_stmt!();
| ------------------- in this macro invocation
error[E0609]: no field `0` on type `{integer}`
27 | (1).0 //~ ERROR no field
| ^^^^^
...
-52 | fake_anon_field_stmt!();
+64 | fake_anon_field_stmt!();
| ------------------------ in this macro invocation
+error[E0689]: can't call method `powi` on ambiguous numeric type `{float}`
+ --> $DIR/macro-backtrace-invalid-internals.rs:51:15
+ |
+51 | 2.0.powi(2) //~ ERROR can't call method `powi` on ambiguous numeric type `{float}`
+ | ^^^^
+...
+65 | real_method_stmt!();
+ | -------------------- in this macro invocation
+help: you must specify a concrete type for this numeric value, like `f32`
+ |
+51 | 2.0_f32.powi(2) //~ ERROR can't call method `powi` on ambiguous numeric type `{float}`
+ | ^^^^^^^
+
error[E0599]: no method named `fake` found for type `{integer}` in the current scope
--> $DIR/macro-backtrace-invalid-internals.rs:33:13
|
33 | 1.fake() //~ ERROR no method
| ^^^^
...
-54 | let _ = fake_method_expr!();
+67 | let _ = fake_method_expr!();
| ------------------- in this macro invocation
error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields
39 | 1.fake //~ ERROR doesn't have fields
| ^^^^
...
-55 | let _ = fake_field_expr!();
+68 | let _ = fake_field_expr!();
| ------------------ in this macro invocation
error[E0609]: no field `0` on type `{integer}`
45 | (1).0 //~ ERROR no field
| ^^^^^
...
-56 | let _ = fake_anon_field_expr!();
+69 | let _ = fake_anon_field_expr!();
| ----------------------- in this macro invocation
-error: aborting due to 6 previous errors
+error[E0689]: can't call method `powi` on ambiguous numeric type `{float}`
+ --> $DIR/macro-backtrace-invalid-internals.rs:57:15
+ |
+57 | 2.0.powi(2) //~ ERROR can't call method `powi` on ambiguous numeric type `{float}`
+ | ^^^^
+...
+70 | let _ = real_method_expr!();
+ | ------------------- in this macro invocation
+help: you must specify a concrete type for this numeric value, like `f32`
+ |
+57 | 2.0_f32.powi(2) //~ ERROR can't call method `powi` on ambiguous numeric type `{float}`
+ | ^^^^^^^
+
+error: aborting due to 8 previous errors
--> $DIR/macro-name-typo.rs:12:5
|
12 | printlx!("oh noes!"); //~ ERROR cannot find
- | ^^^^^^^ help: you could try the macro: `println!`
+ | ^^^^^^^ help: you could try the macro: `println`
error: aborting due to previous error
--> $DIR/macro_undefined.rs:21:5
|
21 | k!(); //~ ERROR cannot find
- | ^ help: you could try the macro: `kl!`
+ | ^ help: you could try the macro: `kl`
error: aborting due to 2 previous errors
| |
| expected signature of `fn(usize) -> _`
|
- = note: required by `foo`
+note: required by `foo`
+ --> $DIR/E0631.rs:13:1
+ |
+13 | fn foo<F: Fn(usize)>(_: F) {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0631]: type mismatch in closure arguments
--> $DIR/E0631.rs:18:5
| |
| expected signature of `fn(usize) -> _`
|
- = note: required by `bar`
+note: required by `bar`
+ --> $DIR/E0631.rs:14:1
+ |
+14 | fn bar<F: Fn<usize>>(_: F) {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0631]: type mismatch in function arguments
--> $DIR/E0631.rs:19:5
19 | foo(f); //~ ERROR type mismatch
| ^^^ expected signature of `fn(usize) -> _`
|
- = note: required by `foo`
+note: required by `foo`
+ --> $DIR/E0631.rs:13:1
+ |
+13 | fn foo<F: Fn(usize)>(_: F) {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0631]: type mismatch in function arguments
--> $DIR/E0631.rs:20:5
20 | bar(f); //~ ERROR type mismatch
| ^^^ expected signature of `fn(usize) -> _`
|
- = note: required by `bar`
+note: required by `bar`
+ --> $DIR/E0631.rs:14:1
+ |
+14 | fn bar<F: Fn<usize>>(_: F) {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 4 previous errors
| |
| expected closure that takes 1 argument
|
- = note: required by `f`
+note: required by `f`
+ --> $DIR/closure-arg-count.rs:13:1
+ |
+13 | fn f<F: Fn<usize>>(_: F) {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
error[E0593]: closure is expected to take a single tuple as argument, but it takes 2 distinct arguments
--> $DIR/closure-arg-count.rs:24:53
| expected signature of `for<'r> fn(*mut &'r u32) -> _`
| found signature of `fn(*mut &'a u32) -> _`
|
- = note: required by `baz`
+note: required by `baz`
+ --> $DIR/closure-arg-type-mismatch.rs:18:1
+ |
+18 | fn baz<F: Fn(*mut &u32)>(_: F) {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0271]: type mismatch resolving `for<'r> <fn(*mut &'a u32) as std::ops::FnOnce<(*mut &'r u32,)>>::Output == ()`
--> $DIR/closure-arg-type-mismatch.rs:20:5
20 | baz(f); //~ ERROR type mismatch
| ^^^ expected bound lifetime parameter, found concrete lifetime
|
- = note: required by `baz`
+note: required by `baz`
+ --> $DIR/closure-arg-type-mismatch.rs:18:1
+ |
+18 | fn baz<F: Fn(*mut &u32)>(_: F) {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 5 previous errors
| ^^^ expected bound lifetime parameter, found concrete lifetime
|
= note: required because of the requirements on the impl of `Foo` for `[closure@$DIR/closure-mismatch.rs:18:9: 18:15]`
- = note: required by `baz`
+note: required by `baz`
+ --> $DIR/closure-mismatch.rs:15:1
+ |
+15 | fn baz<T: Foo>(_: T) {}
+ | ^^^^^^^^^^^^^^^^^^^^
error[E0631]: type mismatch in closure arguments
--> $DIR/closure-mismatch.rs:18:5
| expected signature of `for<'r> fn(&'r ()) -> _`
|
= note: required because of the requirements on the impl of `Foo` for `[closure@$DIR/closure-mismatch.rs:18:9: 18:15]`
- = note: required by `baz`
+note: required by `baz`
+ --> $DIR/closure-mismatch.rs:15:1
+ |
+15 | fn baz<T: Foo>(_: T) {}
+ | ^^^^^^^^^^^^^^^^^^^^
error: aborting due to 2 previous errors
21 | apply(&3, takes_mut);
| ^^^^^ expected signature of `fn(&{integer}) -> _`
|
- = note: required by `apply`
+note: required by `apply`
+ --> $DIR/fn-variance-1.rs:15:1
+ |
+15 | fn apply<T, F>(t: T, f: F) where F: FnOnce(T) {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0631]: type mismatch in function arguments
--> $DIR/fn-variance-1.rs:25:5
25 | apply(&mut 3, takes_imm);
| ^^^^^ expected signature of `fn(&mut {integer}) -> _`
|
- = note: required by `apply`
+note: required by `apply`
+ --> $DIR/fn-variance-1.rs:15:1
+ |
+15 | fn apply<T, F>(t: T, f: F) where F: FnOnce(T) {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 2 previous errors
fn to_fn_mut<A,F:FnMut<A>>(f: F) -> F { f }
fn call_it<F:FnMut(isize,isize)->isize>(y: isize, mut f: F) -> isize {
+//~^ NOTE required by `call_it`
f(2, y)
}
pub fn main() {
let f = to_fn_mut(|x: usize, y: isize| -> isize { (x as isize) + y });
+ //~^ NOTE found signature of `fn(usize, isize) -> _`
let z = call_it(3, f);
//~^ ERROR type mismatch
- //~| required by `call_it`
+ //~| NOTE expected signature of `fn(isize, isize) -> _`
println!("{}", z);
}
error[E0631]: type mismatch in closure arguments
- --> $DIR/unboxed-closures-vtable-mismatch.rs:23:13
+ --> $DIR/unboxed-closures-vtable-mismatch.rs:25:13
|
-22 | let f = to_fn_mut(|x: usize, y: isize| -> isize { (x as isize) + y });
+23 | let f = to_fn_mut(|x: usize, y: isize| -> isize { (x as isize) + y });
| ----------------------------- found signature of `fn(usize, isize) -> _`
-23 | let z = call_it(3, f);
+24 | //~^ NOTE found signature of `fn(usize, isize) -> _`
+25 | let z = call_it(3, f);
| ^^^^^^^ expected signature of `fn(isize, isize) -> _`
|
- = note: required by `call_it`
+note: required by `call_it`
+ --> $DIR/unboxed-closures-vtable-mismatch.rs:17:1
+ |
+17 | fn call_it<F:FnMut(isize,isize)->isize>(y: isize, mut f: F) -> isize {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
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.
+
+// Regression test for issue #45045
+
+#![feature(nll)]
+
+enum Xyz {
+ A,
+ B,
+}
+
+fn main() {
+ let mut e = Xyz::A;
+ let f = &mut e;
+ let g = f;
+ match e {
+ Xyz::A => println!("a"),
+ //~^ cannot use `e` because it was mutably borrowed [E0503]
+ Xyz::B => println!("b"),
+ };
+ *g = Xyz::B;
+}
--- /dev/null
+error[E0503]: cannot use `e` because it was mutably borrowed
+ --> $DIR/borrowed-match-issue-45045.rs:25:9
+ |
+22 | let f = &mut e;
+ | ------ borrow of `e` occurs here
+...
+25 | Xyz::A => println!("a"),
+ | ^^^^^^ use of borrowed `e`
+
+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.
+
+// Regression test for issue #38899
+
+#![feature(nll)]
+#![allow(dead_code)]
+
+pub struct Block<'a> {
+ current: &'a u8,
+ unrelated: &'a u8,
+}
+
+fn bump<'a>(mut block: &mut Block<'a>) {
+ let x = &mut block;
+ println!("{}", x.current);
+ let p: &'a u8 = &*block.current;
+ //~^ ERROR cannot borrow `*block.current` as immutable because it is also borrowed as mutable
+ drop(x);
+ drop(p);
+}
+
+fn main() {}
--- /dev/null
+error[E0502]: cannot borrow `*block.current` as immutable because it is also borrowed as mutable
+ --> $DIR/borrowed-referent-issue-38899.rs:24:21
+ |
+22 | let x = &mut block;
+ | ---------- mutable borrow occurs here
+23 | println!("{}", x.current);
+24 | let p: &'a u8 = &*block.current;
+ | ^^^^^^^^^^^^^^^ immutable borrow occurs here
+
+error: aborting due to previous error
+
fn foo(x: &u32) -> &'static u32 {
&*x
//~^ WARN not reporting region error due to -Znll
- //~| ERROR does not outlive free region
+ //~| ERROR explicit lifetime required in the type of `x`
}
fn main() { }
19 | &*x
| ^^^
-error: free region `ReFree(DefId(0/0:3 ~ region_lbr_anon_does_not_outlive_static[317d]::foo[0]), BrAnon(0))` does not outlive free region `ReStatic`
+error[E0621]: explicit lifetime required in the type of `x`
--> $DIR/region-lbr-anon-does-not-outlive-static.rs:19:5
|
+18 | fn foo(x: &u32) -> &'static u32 {
+ | - consider changing the type of `x` to `&ReStatic u32`
19 | &*x
- | ^^^
+ | ^^^ lifetime `ReStatic` required
error: aborting due to previous error
fn bar(s: &Box<(i32,)>) -> &'static i32 {
// FIXME(#46983): error message should be better
- &s.0 //~ ERROR free region `` does not outlive free region `'static`
+ &s.0 //~ ERROR explicit lifetime required in the type of `s` [E0621]
}
fn main() {
19 | *s = (2,); //~ ERROR cannot assign to `*s`
| ^^^^^^^^^ assignment to borrowed `*s` occurs here
-error: free region `` does not outlive free region `'static`
+error[E0621]: explicit lifetime required in the type of `s`
--> $DIR/guarantor-issue-46974.rs:25:5
|
-25 | &s.0 //~ ERROR free region `` does not outlive free region `'static`
- | ^^^^
+23 | fn bar(s: &Box<(i32,)>) -> &'static i32 {
+ | - consider changing the type of `s` to `&'static std::boxed::Box<(i32,)>`
+24 | // FIXME(#46983): error message should be better
+25 | &s.0 //~ ERROR explicit lifetime required in the type of `s` [E0621]
+ | ^^^^ lifetime `'static` required
error: aborting due to 2 previous errors
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <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.
+
+// must-compile-successfully
+
+#![allow(warnings)]
+#![feature(nll)]
+
+struct LoadedObject {
+ bodies: Vec<Body>,
+ color: Color,
+}
+
+struct Body;
+
+#[derive(Clone)]
+struct Color;
+
+struct Graphic {
+ color: Color,
+}
+
+fn convert(objects: Vec<LoadedObject>) -> (Vec<Body>, Vec<Graphic>) {
+ objects
+ .into_iter()
+ .flat_map(|LoadedObject { bodies, color, .. }| {
+ bodies.into_iter().map(move |body| {
+ (
+ body,
+ Graphic {
+ color: color.clone(),
+ },
+ )
+ })
+ })
+ .unzip()
+}
+
+fn main() {}
+
--- /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.
+
+// Regression test for issue #46557
+
+#![feature(nll)]
+#![allow(dead_code)]
+
+fn gimme_static_mut() -> &'static mut u32 {
+ let ref mut x = 1234543; //~ ERROR borrowed value does not live long enough [E0597]
+ x
+}
+
+fn main() {}
--- /dev/null
+error[E0597]: borrowed value does not live long enough
+ --> $DIR/return-ref-mut-issue-46557.rs:17:21
+ |
+17 | let ref mut x = 1234543; //~ ERROR borrowed value does not live long enough [E0597]
+ | ^^^^^^^ temporary value does not live long enough
+18 | x
+19 | }
+ | - temporary value only lives until here
+ |
+ = note: borrowed value must be valid for lifetime '_#2r...
+
+error: aborting due to previous error
+
-error: mod statements in non-mod.rs files are unstable (see issue #44660)
+error[E0658]: mod statements in non-mod.rs files are unstable (see issue #44660)
--> $DIR/modrs_mod/inner_foors_mod.rs:11:9
|
11 | pub mod innest;
= help: add #![feature(non_modrs_mods)] to the crate attributes to enable
= help: on stable builds, rename this file to inner_foors_mod/mod.rs
-error: mod statements in non-mod.rs files are unstable (see issue #44660)
+error[E0658]: mod statements in non-mod.rs files are unstable (see issue #44660)
--> $DIR/foors_mod.rs:13:9
|
13 | pub mod inner_modrs_mod;
= help: add #![feature(non_modrs_mods)] to the crate attributes to enable
= help: on stable builds, rename this file to foors_mod/mod.rs
-error: mod statements in non-mod.rs files are unstable (see issue #44660)
+error[E0658]: mod statements in non-mod.rs files are unstable (see issue #44660)
--> $DIR/foors_mod.rs:14:9
|
14 | pub mod inner_foors_mod;
= help: add #![feature(non_modrs_mods)] to the crate attributes to enable
= help: on stable builds, rename this file to foors_mod/mod.rs
-error: mod statements in non-mod.rs files are unstable (see issue #44660)
+error[E0658]: mod statements in non-mod.rs files are unstable (see issue #44660)
--> $DIR/foors_mod/inner_foors_mod.rs:11:9
|
11 | pub mod innest;
= help: add #![feature(non_modrs_mods)] to the crate attributes to enable
= help: on stable builds, rename this file to inner_foors_mod/mod.rs
-error: mod statements in non-mod.rs files are unstable (see issue #44660)
- --> $DIR/some_crazy_attr_mod_dir/arbitrary_name.rs:11:9
- |
-11 | pub mod inner_modrs_mod;
- | ^^^^^^^^^^^^^^^
- |
- = help: add #![feature(non_modrs_mods)] to the crate attributes to enable
- = help: on stable builds, rename this file to attr_mod/mod.rs
-
-error: aborting due to 5 previous errors
+error: aborting due to 4 previous errors
+++ /dev/null
-// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <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.
-
-pub fn foo() {}
+++ /dev/null
-// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <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.
-
-pub mod innest;
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <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.
+
+pub fn foo() {}
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <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.
+
+pub mod innest;
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <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.
+
+trait Trait1 {}
+trait Trait2 {}
+
+#[cfg(not_enabled)]
+impl Trait1 for .. {}
+
+impl Trait2 for .. {} //~ ERROR `impl Trait for .. {}` is an obsolete syntax
+
+fn main() {}
--- /dev/null
+error: `impl Trait for .. {}` is an obsolete syntax
+ --> $DIR/obsolete-syntax-impl-for-dotdot.rs:17:1
+ |
+17 | impl Trait2 for .. {} //~ ERROR `impl Trait for .. {}` is an obsolete syntax
+ | ^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: use `auto trait Trait {}` instead
+
+error: aborting due to previous error
+
| ^^^^^^^^^^^^ trait message
|
= help: the trait `Index<u32>` is not implemented for `[i32]`
- = note: required by `Index::index`
+note: required by `Index::index`
+ --> $DIR/multiple-impls.rs:22:5
+ |
+22 | fn index(&self, index: Idx) -> &Self::Output;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0277]: the trait bound `[i32]: Index<u32>` is not satisfied
--> $DIR/multiple-impls.rs:43:5
| ^^^^^^^^^^^^ on impl for Foo
|
= help: the trait `Index<Foo<u32>>` is not implemented for `[i32]`
- = note: required by `Index::index`
+note: required by `Index::index`
+ --> $DIR/multiple-impls.rs:22:5
+ |
+22 | fn index(&self, index: Idx) -> &Self::Output;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0277]: the trait bound `[i32]: Index<Foo<u32>>` is not satisfied
--> $DIR/multiple-impls.rs:46:5
| ^^^^^^^^^^^^ on impl for Bar
|
= help: the trait `Index<Bar<u32>>` is not implemented for `[i32]`
- = note: required by `Index::index`
+note: required by `Index::index`
+ --> $DIR/multiple-impls.rs:22:5
+ |
+22 | fn index(&self, index: Idx) -> &Self::Output;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0277]: the trait bound `[i32]: Index<Bar<u32>>` is not satisfied
--> $DIR/multiple-impls.rs:49:5
| ^^^^^^^^^^^^^^^^^^^ a usize is required to index into a slice
|
= help: the trait `Index<u32>` is not implemented for `[i32]`
- = note: required by `Index::index`
+note: required by `Index::index`
+ --> $DIR/on-impl.rs:19:5
+ |
+19 | fn index(&self, index: Idx) -> &Self::Output;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0277]: the trait bound `[i32]: Index<u32>` is not satisfied
--> $DIR/on-impl.rs:32:5
| ^^^^^^^ a collection of type `std::option::Option<std::vec::Vec<u8>>` cannot be built from an iterator over elements of type `&u8`
|
= help: the trait `MyFromIterator<&u8>` is not implemented for `std::option::Option<std::vec::Vec<u8>>`
- = note: required by `collect`
+note: required by `collect`
+ --> $DIR/on-trait.rs:31:1
+ |
+31 | fn collect<A, I: Iterator<Item=A>, B: MyFromIterator<A>>(it: I) -> B {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0277]: the trait bound `std::string::String: Bar::Foo<u8, _, u32>` is not satisfied
--> $DIR/on-trait.rs:40:21
| ^^^^^^ test error `std::string::String` with `u8` `_` `u32` in `Bar::Foo`
|
= help: the trait `Bar::Foo<u8, _, u32>` is not implemented for `std::string::String`
- = note: required by `foobar`
+note: required by `foobar`
+ --> $DIR/on-trait.rs:21:1
+ |
+21 | fn foobar<U: Clone, T: Foo<u8, U, u32>>() -> T {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 2 previous errors
-error: non-reference pattern used to match a reference (see issue #42640)
+error[E0658]: non-reference pattern used to match a reference (see issue #42640)
--> $DIR/pat-slice-old-style.rs:19:9
|
19 | [a, b..] => {},
--> $DIR/pub-restricted-error.rs:16:16
|
16 | pub(crate) () foo: usize, //~ ERROR expected identifier
- | ^
+ | ^ expected identifier
error: aborting due to previous error
--> $DIR/pub-restricted-non-path.rs:13:6
|
13 | pub (.) fn afn() {} //~ ERROR expected identifier
- | ^
+ | ^ expected identifier
error: aborting due to previous error
-error: non-reference pattern used to match a reference (see issue #42640)
+error[E0658]: non-reference pattern used to match a reference (see issue #42640)
--> $DIR/suggestion.rs:12:12
|
12 | if let Some(y) = &Some(22) { //~ ERROR non-reference pattern
|
= note: expected type `usize`
found type `std::string::String`
- = help: here are some functions which might fulfill your needs:
- - .capacity()
- - .len()
error[E0308]: mismatched types
--> $DIR/coerce-suggestions.rs:19:19
--> $DIR/coerce-suggestions.rs:27:9
|
27 | f = box f;
- | ^^^^^ cyclic type of infinite size
+ | ^^^^^
+ | |
+ | cyclic type of infinite size
+ | help: try using a conversion method: `box f.to_string()`
error[E0308]: mismatched types
--> $DIR/coerce-suggestions.rs:31:9
-error: the struct `#[repr(align(u16))]` attribute is experimental (see issue #33626)
+error[E0658]: the struct `#[repr(align(u16))]` attribute is experimental (see issue #33626)
--> $DIR/gated-features-attr-spans.rs:13:1
|
13 | #[repr(align(16))] //~ ERROR is experimental
|
= help: add #![feature(repr_align)] to the crate attributes to enable
-error: SIMD types are experimental and possibly buggy (see issue #27731)
+error[E0658]: SIMD types are experimental and possibly buggy (see issue #27731)
--> $DIR/gated-features-attr-spans.rs:20:1
|
20 | #[repr(simd)] //~ ERROR are experimental
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <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.
+
+// compile-flags: -Z parse-only -Z continue-parse-after-error
+
+impl ! {} // OK
+impl ! where u8: Copy {} // OK
+
+impl Trait Type {} //~ ERROR missing `for` in a trait impl
+impl Trait .. {} //~ ERROR missing `for` in a trait impl
+impl ?Sized for Type {} //~ ERROR expected a trait, found type
+impl ?Sized for .. {} //~ ERROR expected a trait, found type
+
+default unsafe FAIL //~ ERROR expected `impl`, found `FAIL`
--- /dev/null
+error: missing `for` in a trait impl
+ --> $DIR/impl-parsing.rs:16:11
+ |
+16 | impl Trait Type {} //~ ERROR missing `for` in a trait impl
+ | ^
+
+error: missing `for` in a trait impl
+ --> $DIR/impl-parsing.rs:17:11
+ |
+17 | impl Trait .. {} //~ ERROR missing `for` in a trait impl
+ | ^
+
+error: expected a trait, found type
+ --> $DIR/impl-parsing.rs:18:6
+ |
+18 | impl ?Sized for Type {} //~ ERROR expected a trait, found type
+ | ^^^^^^
+
+error: expected a trait, found type
+ --> $DIR/impl-parsing.rs:19:6
+ |
+19 | impl ?Sized for .. {} //~ ERROR expected a trait, found type
+ | ^^^^^^
+
+error: expected `impl`, found `FAIL`
+ --> $DIR/impl-parsing.rs:21:16
+ |
+21 | default unsafe FAIL //~ ERROR expected `impl`, found `FAIL`
+ | ^^^^ expected `impl` here
+
+error: aborting due to 5 previous errors
+
17 | let a: u8 = Tr::C; //~ ERROR the trait bound `u8: Tr` is not satisfied
| ^^^^^ the trait `Tr` is not implemented for `u8`
|
- = note: required by `Tr::C`
+note: required by `Tr::C`
+ --> $DIR/issue-29595.rs:13:5
+ |
+13 | const C: Self;
+ | ^^^^^^^^^^^^^^
error: aborting due to previous error
|
= note: expected type `usize`
found type `&'static str`
- = help: here are some functions which might fulfill your needs:
- - .len()
error[E0061]: this function takes 2 parameters but 3 parameters were supplied
--> $DIR/issue-34264.rs:20:5
-error: The attribute `foo` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `foo` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
--> $DIR/issue-36530.rs:11:1
|
11 | #[foo] //~ ERROR is currently unknown to the compiler
|
= help: add #![feature(custom_attribute)] to the crate attributes to enable
-error: The attribute `foo` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `foo` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
--> $DIR/issue-36530.rs:13:5
|
13 | #![foo] //~ ERROR is currently unknown to the compiler
-error: specialization is unstable (see issue #31844)
+error[E0658]: specialization is unstable (see issue #31844)
--> $DIR/specialization-feature-gate-default.rs:20:5
|
20 | default fn foo(&self) {} //~ ERROR specialization is unstable
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <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 std::path::{Path, PathBuf};
+
+
+fn main() {
+ let _tis_an_instants_play: String = "'Tis a fond Ambush—"; //~ ERROR mismatched types
+ let _just_to_make_bliss: PathBuf = Path::new("/ern/her/own/surprise");
+ //~^ ERROR mismatched types
+
+ let _but_should_the_play: String = 2; // Perhaps surprisingly, we suggest .to_string() here
+ //~^ ERROR mismatched types
+
+ let _prove_piercing_earnest: Vec<usize> = &[1, 2, 3]; //~ ERROR mismatched types
+}
--- /dev/null
+error[E0308]: mismatched types
+ --> $DIR/conversion-methods.rs:15:41
+ |
+15 | let _tis_an_instants_play: String = "'Tis a fond Ambush—"; //~ ERROR mismatched types
+ | ^^^^^^^^^^^^^^^^^^^^^
+ | |
+ | expected struct `std::string::String`, found reference
+ | help: try using a conversion method: `"'Tis a fond Ambush—".to_string()`
+ |
+ = note: expected type `std::string::String`
+ found type `&'static str`
+
+error[E0308]: mismatched types
+ --> $DIR/conversion-methods.rs:16:40
+ |
+16 | let _just_to_make_bliss: PathBuf = Path::new("/ern/her/own/surprise");
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | |
+ | expected struct `std::path::PathBuf`, found reference
+ | help: try using a conversion method: `Path::new("/ern/her/own/surprise").to_path_buf()`
+ |
+ = note: expected type `std::path::PathBuf`
+ found type `&std::path::Path`
+
+error[E0308]: mismatched types
+ --> $DIR/conversion-methods.rs:19:40
+ |
+19 | let _but_should_the_play: String = 2; // Perhaps surprisingly, we suggest .to_string() here
+ | ^
+ | |
+ | expected struct `std::string::String`, found integral variable
+ | help: try using a conversion method: `2.to_string()`
+ |
+ = note: expected type `std::string::String`
+ found type `{integer}`
+
+error[E0308]: mismatched types
+ --> $DIR/conversion-methods.rs:22:47
+ |
+22 | let _prove_piercing_earnest: Vec<usize> = &[1, 2, 3]; //~ ERROR mismatched types
+ | ^^^^^^^^^^
+ | |
+ | expected struct `std::vec::Vec`, found reference
+ | help: try using a conversion method: `&[1, 2, 3].to_vec()`
+ |
+ = note: expected type `std::vec::Vec<usize>`
+ found type `&[{integer}; 3]`
+
+error: aborting due to 4 previous errors
+
-error: non-reference pattern used to match a reference (see issue #42640)
+error[E0658]: non-reference pattern used to match a reference (see issue #42640)
--> $DIR/dont-suggest-dereference-on-arg.rs:16:18
|
16 | .filter(|&(ref a, _)| foo(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.
+
+pub fn bar<F: Fn()>(_f: F) {}
+
+pub fn foo() {
+ let mut x = 0;
+ bar(move || x = 1);
+ //~^ ERROR cannot assign to captured outer variable in an `Fn` closure
+ //~| NOTE `Fn` closures cannot capture their enclosing environment for modifications
+}
+
+fn main() {}
--- /dev/null
+error[E0594]: cannot assign to captured outer variable in an `Fn` closure
+ --> $DIR/fn-closure-mutable-capture.rs:15:17
+ |
+15 | bar(move || x = 1);
+ | ^^^^^
+ |
+ = note: `Fn` closures cannot capture their enclosing environment for modifications
+help: consider changing this closure to take self by mutable reference
+ --> $DIR/fn-closure-mutable-capture.rs:15:9
+ |
+15 | bar(move || x = 1);
+ | ^^^^^^^^^^^^^
+
+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.
+
+#[no_mangle] pub const RAH: usize = 5;
+//~^ ERROR const items should never be #[no_mangle]
+
+fn main() {}
--- /dev/null
+error: const items should never be #[no_mangle]
+ --> $DIR/issue-45562.rs:11:14
+ |
+11 | #[no_mangle] pub const RAH: usize = 5;
+ | ---------^^^^^^^^^^^^^^^^
+ | |
+ | help: try a static value: `pub static`
+ |
+ = note: #[deny(no_mangle_const_items)] on by default
+
+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.
+
+fn main() {
+ let x = 2.0.powi(2);
+ //~^ ERROR can't call method `powi` on ambiguous numeric type `{float}`
+ let y = 2.0;
+ let x = y.powi(2);
+ //~^ ERROR can't call method `powi` on ambiguous numeric type `{float}`
+ println!("{:?}", x);
+}
--- /dev/null
+error[E0689]: can't call method `powi` on ambiguous numeric type `{float}`
+ --> $DIR/method-on-ambiguous-numeric-type.rs:12:17
+ |
+12 | let x = 2.0.powi(2);
+ | ^^^^
+help: you must specify a concrete type for this numeric value, like `f32`
+ |
+12 | let x = 2.0_f32.powi(2);
+ | ^^^^^^^
+
+error[E0689]: can't call method `powi` on ambiguous numeric type `{float}`
+ --> $DIR/method-on-ambiguous-numeric-type.rs:15:15
+ |
+15 | let x = y.powi(2);
+ | ^^^^
+help: you must specify a type for this binding, like `f32`
+ |
+14 | let y: f32 = 2.0;
+ | ^^^^^^
+
+error: aborting due to 2 previous errors
+
25 | try_trait_generic::<()>(); //~ ERROR the trait bound
| ^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::ops::Try` is not implemented for `()`
|
- = note: required by `try_trait_generic`
+note: required by `try_trait_generic`
+ --> $DIR/try-operator-on-main.rs:30:1
+ |
+30 | fn try_trait_generic<T: Try>() -> T {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0277]: the `?` operator can only be applied to values that implement `std::ops::Try`
--> $DIR/try-operator-on-main.rs:32:5
--- /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.
+
+// ignore-arm
+// ignore-aarch64
+// ignore-wasm
+// ignore-emscripten
+
+#![feature(target_feature)]
+
+#[target_feature = "+sse2"]
+//~^ WARN: deprecated
+#[target_feature(enable = "foo")]
+//~^ ERROR: not valid for this target
+#[target_feature(bar)]
+//~^ ERROR: only accepts sub-keys
+#[target_feature(disable = "baz")]
+//~^ ERROR: only accepts sub-keys
+unsafe fn foo() {}
+
+#[target_feature(enable = "sse2")]
+//~^ ERROR: can only be applied to `unsafe` function
+fn bar() {}
+
+fn main() {
+ unsafe {
+ foo();
+ bar();
+ }
+}
--- /dev/null
+warning: #[target_feature = ".."] is deprecated and will eventually be removed, use #[target_feature(enable = "..")] instead
+ --> $DIR/target-feature-wrong.rs:18:1
+ |
+18 | #[target_feature = "+sse2"]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: the feature named `foo` is not valid for this target
+ --> $DIR/target-feature-wrong.rs:20:18
+ |
+20 | #[target_feature(enable = "foo")]
+ | ^^^^^^^^^^^^^^
+
+error: #[target_feature(..)] only accepts sub-keys of `enable` currently
+ --> $DIR/target-feature-wrong.rs:22:18
+ |
+22 | #[target_feature(bar)]
+ | ^^^
+
+error: #[target_feature(..)] only accepts sub-keys of `enable` currently
+ --> $DIR/target-feature-wrong.rs:24:18
+ |
+24 | #[target_feature(disable = "baz")]
+ | ^^^^^^^^^^^^^^^
+
+error: #[target_feature(..)] can only be applied to `unsafe` function
+ --> $DIR/target-feature-wrong.rs:28:1
+ |
+28 | #[target_feature(enable = "sse2")]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 4 previous errors
+
--- /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 std::io;
+
+fn main(){
+ let x: io::IoResult<()> = Ok(());
+ //~^ ERROR cannot find type `IoResult` in module `io`
+ //~| NOTE did you mean `Result`?
+ match x {
+ Err(ref e) if e.kind == io::EndOfFile {
+ //~^ NOTE while parsing this struct
+ return
+ //~^ ERROR expected identifier, found keyword `return`
+ //~| NOTE expected identifier, found keyword
+ }
+ //~^ NOTE expected one of `.`, `=>`, `?`, or an operator here
+ _ => {}
+ //~^ ERROR expected one of `.`, `=>`, `?`, or an operator, found `_`
+ //~| NOTE unexpected token
+ }
+}
--- /dev/null
+error: expected identifier, found keyword `return`
+ --> $DIR/issue-15980.rs:20:13
+ |
+18 | Err(ref e) if e.kind == io::EndOfFile {
+ | ------------- while parsing this struct
+19 | //~^ NOTE while parsing this struct
+20 | return
+ | ^^^^^^ expected identifier, found keyword
+
+error: expected one of `.`, `=>`, `?`, or an operator, found `_`
+ --> $DIR/issue-15980.rs:25:9
+ |
+23 | }
+ | - expected one of `.`, `=>`, `?`, or an operator here
+24 | //~^ NOTE expected one of `.`, `=>`, `?`, or an operator here
+25 | _ => {}
+ | ^ unexpected token
+
+error[E0412]: cannot find type `IoResult` in module `io`
+ --> $DIR/issue-15980.rs:14:16
+ |
+14 | let x: io::IoResult<()> = Ok(());
+ | ^^^^^^^^ did you mean `Result`?
+
+error: aborting due to 3 previous errors
+
--- /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 foo<T: Into<String>>(x: i32) {}
+//~^ NOTE required by
+
+fn main() {
+ foo(42);
+ //~^ ERROR type annotations required
+}
--- /dev/null
+error[E0283]: type annotations required: cannot resolve `_: std::convert::Into<std::string::String>`
+ --> $DIR/type-annotation-needed.rs:15:5
+ |
+15 | foo(42);
+ | ^^^
+ |
+note: required by `foo`
+ --> $DIR/type-annotation-needed.rs:11:1
+ |
+11 | fn foo<T: Into<String>>(x: i32) {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
21 | | }
| |_^
|
- = note: required by `Foo`
+note: required by `Foo`
+ --> $DIR/issue-40294.rs:11:1
+ |
+11 | trait Foo: Sized {
+ | ^^^^^^^^^^^^^^^^
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.
-
-#![feature(optin_builtin_traits)]
-
-#[allow(auto_impl)]
-impl Copy for .. {} //~ ERROR E0318
-fn main() {}
+++ /dev/null
-error[E0318]: cannot create default implementations for traits outside the crate they're defined in; define a new trait instead
- --> $DIR/typeck-default-trait-impl-outside-crate.rs:14:6
- |
-14 | impl Copy for .. {} //~ ERROR E0318
- | ^^^^ `Copy` trait not defined in this crate
-
-error: aborting due to previous error
-
"i386-apple-ios",
"i586-pc-windows-msvc",
"i586-unknown-linux-gnu",
+ "i586-unknown-linux-musl",
"i686-apple-darwin",
"i686-linux-android",
"i686-pc-windows-gnu",
-Subproject commit a88fbace48ac42ab21e1d8609012480d0aeab982
+Subproject commit 6a8eb71f6d226f9ac869dbacd5ff6aa76deef1c4
env_logger = { version = "0.4", default-features = false }
filetime = "0.1"
getopts = "0.2"
-log = "0.3"
+log = "0.4"
regex = "0.2"
rustc-serialize = "0.3"
iter_header(testfile,
None,
&mut |ln| {
+ // we should check if any only-<platform> exists and if it exists
+ // and does not matches the current platform, skip the test
props.ignore =
props.ignore ||
config.parse_cfg_name_directive(ln, "ignore") ||
+ (config.has_cfg_prefix(ln, "only") &&
+ !config.parse_cfg_name_directive(ln, "only")) ||
ignore_gdb(config, ln) ||
ignore_lldb(config, ln) ||
ignore_llvm(config, ln);
}
}
+ fn has_cfg_prefix(&self, line: &str, prefix: &str) -> bool {
+ // returns whether this line contains this prefix or not. For prefix
+ // "ignore", returns true if line says "ignore-x86_64", "ignore-arch",
+ // "ignore-andorid" etc.
+ line.starts_with(prefix) && line.as_bytes().get(prefix.len()) == Some(&b'-')
+ }
+
fn parse_name_directive(&self, line: &str, directive: &str) -> bool {
// Ensure the directive is a whole word. Do not match "ignore-x86" when
// the line says "ignore-x86_64".
use util::logv;
use regex::Regex;
+use std::collections::VecDeque;
use std::collections::HashMap;
use std::collections::HashSet;
use std::env;
}
}
+#[derive(Debug, PartialEq)]
+pub enum DiffLine {
+ Context(String),
+ Expected(String),
+ Resulting(String),
+}
+
+#[derive(Debug, PartialEq)]
+pub struct Mismatch {
+ pub line_number: u32,
+ pub lines: Vec<DiffLine>,
+}
+
+impl Mismatch {
+ fn new(line_number: u32) -> Mismatch {
+ Mismatch {
+ line_number: line_number,
+ lines: Vec::new(),
+ }
+ }
+}
+
+// Produces a diff between the expected output and actual output.
+pub fn make_diff(expected: &str, actual: &str, context_size: usize) -> Vec<Mismatch> {
+ let mut line_number = 1;
+ let mut context_queue: VecDeque<&str> = VecDeque::with_capacity(context_size);
+ let mut lines_since_mismatch = context_size + 1;
+ let mut results = Vec::new();
+ let mut mismatch = Mismatch::new(0);
+
+ for result in diff::lines(actual, expected) {
+ match result {
+ diff::Result::Left(str) => {
+ if lines_since_mismatch >= context_size && lines_since_mismatch > 0 {
+ results.push(mismatch);
+ mismatch = Mismatch::new(line_number - context_queue.len() as u32);
+ }
+
+ while let Some(line) = context_queue.pop_front() {
+ mismatch.lines.push(DiffLine::Context(line.to_owned()));
+ }
+
+ mismatch.lines.push(DiffLine::Resulting(str.to_owned()));
+ lines_since_mismatch = 0;
+ }
+ diff::Result::Right(str) => {
+ if lines_since_mismatch >= context_size && lines_since_mismatch > 0 {
+ results.push(mismatch);
+ mismatch = Mismatch::new(line_number - context_queue.len() as u32);
+ }
+
+ while let Some(line) = context_queue.pop_front() {
+ mismatch.lines.push(DiffLine::Context(line.to_owned()));
+ }
+
+ mismatch.lines.push(DiffLine::Expected(str.to_owned()));
+ line_number += 1;
+ lines_since_mismatch = 0;
+ }
+ diff::Result::Both(str, _) => {
+ if context_queue.len() >= context_size {
+ let _ = context_queue.pop_front();
+ }
+
+ if lines_since_mismatch < context_size {
+ mismatch.lines.push(DiffLine::Context(str.to_owned()));
+ } else if context_size > 0 {
+ context_queue.push_back(str);
+ }
+
+ line_number += 1;
+ lines_since_mismatch += 1;
+ }
+ }
+ }
+
+ results.push(mismatch);
+ results.remove(0);
+
+ results
+}
+
pub fn run(config: Config, testpaths: &TestPaths) {
match &*config.target {
"arm-linux-androideabi" | "armv7-linux-androideabi" | "aarch64-linux-android" => {
for line in reader.lines() {
match line {
Ok(line) => {
+ let line =
+ if line.starts_with("//") {
+ line[2..].trim_left()
+ } else {
+ line.as_str()
+ };
+
if line.contains("#break") {
breakpoint_lines.push(counter);
}
rustc.args(&["-Z", "incremental-queries"]);
}
+ if self.config.mode == CodegenUnits {
+ rustc.args(&["-Z", "human_readable_cgu_names"]);
+ }
+
match self.config.mode {
CompileFail | ParseFail | Incremental => {
// If we are extracting and matching errors in the new
return 0;
}
- println!("normalized {}:\n{}\n", kind, actual);
- println!("expected {}:\n{}\n", kind, expected);
- println!("diff of {}:\n", kind);
-
- for diff in diff::lines(expected, actual) {
- match diff {
- diff::Result::Left(l) => println!("-{}", l),
- diff::Result::Both(l, _) => println!(" {}", l),
- diff::Result::Right(r) => println!("+{}", r),
+ if expected.is_empty() {
+ println!("normalized {}:\n{}\n", kind, actual);
+ } else {
+ println!("diff of {}:\n", kind);
+ let diff_results = make_diff(expected, actual, 3);
+ for result in diff_results {
+ let mut line_number = result.line_number;
+ for line in result.lines {
+ match line {
+ DiffLine::Expected(e) => {
+ println!("-\t{}", e);
+ line_number += 1;
+ },
+ DiffLine::Context(c) => {
+ println!("{}\t{}", line_number, c);
+ line_number += 1;
+ },
+ DiffLine::Resulting(r) => {
+ println!("+\t{}", r);
+ },
+ }
+ }
+ println!("");
}
}
*skipped += data.len();
if data.len() <= TAIL_LEN {
tail[..data.len()].copy_from_slice(data);
- tail.rotate(data.len());
+ tail.rotate_left(data.len());
} else {
tail.copy_from_slice(&data[(data.len() - TAIL_LEN)..]);
}
}
fn footer(&self, output: &mut Write) -> Result<(), Box<Error>> {
- write!(output, "</body>\n</html>")?;
+ write!(output, r##"<script>
+function onEach(arr, func) {{
+ if (arr && arr.length > 0 && func) {{
+ for (var i = 0; i < arr.length; i++) {{
+ func(arr[i]);
+ }}
+ }}
+}}
+
+function hasClass(elem, className) {{
+ if (elem && className && elem.className) {{
+ var elemClass = elem.className;
+ var start = elemClass.indexOf(className);
+ if (start === -1) {{
+ return false;
+ }} else if (elemClass.length === className.length) {{
+ return true;
+ }} else {{
+ if (start > 0 && elemClass[start - 1] !== ' ') {{
+ return false;
+ }}
+ var end = start + className.length;
+ if (end < elemClass.length && elemClass[end] !== ' ') {{
+ return false;
+ }}
+ return true;
+ }}
+ if (start > 0 && elemClass[start - 1] !== ' ') {{
+ return false;
+ }}
+ var end = start + className.length;
+ if (end < elemClass.length && elemClass[end] !== ' ') {{
+ return false;
+ }}
+ return true;
+ }}
+ return false;
+}}
+
+onEach(document.getElementsByClassName('rust-example-rendered'), function(e) {{
+ if (hasClass(e, 'compile_fail')) {{
+ e.addEventListener("mouseover", function(event) {{
+ e.previousElementSibling.childNodes[0].style.color = '#f00';
+ }});
+ e.addEventListener("mouseout", function(event) {{
+ e.previousElementSibling.childNodes[0].style.color = '';
+ }});
+ }} else if (hasClass(e, 'ignore')) {{
+ e.addEventListener("mouseover", function(event) {{
+ e.previousElementSibling.childNodes[0].style.color = '#ff9200';
+ }});
+ e.addEventListener("mouseout", function(event) {{
+ e.previousElementSibling.childNodes[0].style.color = '';
+ }});
+ }}
+}});
+</script>
+</body>
+</html>"##)?;
Ok(())
}
}
file.ends_with("sync/struct.RwLock.html") {
return None;
}
- // FIXME(#47038)
- if file.ends_with("deriving/generic/index.html") ||
- file.ends_with("deriving/generic/macro.vec.html") ||
- file.ends_with("deriving/custom/macro.panic.html") ||
- file.ends_with("proc_macro_impl/macro.panic.html") {
- return None;
- }
let res = load_file(cache, root, file, SkipRedirect);
let (pretty_file, contents) = match res {
for part in Path::new(base).join(url).components() {
match part {
Component::Prefix(_) |
- Component::RootDir => panic!(),
+ Component::RootDir => {
+ // Avoid absolute paths as they make the docs not
+ // relocatable by making assumptions on where the docs
+ // are hosted relative to the site root.
+ *errors = true;
+ println!("{}:{}: absolute path - {}",
+ pretty_file.display(),
+ i + 1,
+ Path::new(base).join(url).display());
+ return;
+ }
Component::CurDir => {}
Component::ParentDir => { path.pop(); }
Component::Normal(s) => { path.push(s); }
-Subproject commit 745a020e924c0532b01e8f017ed72820913642ee
+Subproject commit b55e0fc77590cf5d23a01dedeb2104d8cbb48efc
--- /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 fs = require('fs');
+
+const TEST_FOLDER = 'src/test/rustdoc-js/';
+
+// Stupid function extractor based on indent.
+function extractFunction(content, functionName) {
+ var x = content.split('\n');
+ var in_func = false;
+ var indent = 0;
+ var lines = [];
+
+ for (var i = 0; i < x.length; ++i) {
+ if (in_func === false) {
+ var splitter = "function " + functionName + "(";
+ if (x[i].trim().startsWith(splitter)) {
+ in_func = true;
+ indent = x[i].split(splitter)[0].length;
+ lines.push(x[i]);
+ }
+ } else {
+ lines.push(x[i]);
+ if (x[i].trim() === "}" && x[i].split("}")[0].length === indent) {
+ return lines.join("\n");
+ }
+ }
+ }
+ return null;
+}
+
+// Stupid function extractor for array.
+function extractArrayVariable(content, arrayName) {
+ var x = content.split('\n');
+ var found_var = false;
+ var lines = [];
+
+ for (var i = 0; i < x.length; ++i) {
+ if (found_var === false) {
+ var splitter = "var " + arrayName + " = [";
+ if (x[i].trim().startsWith(splitter)) {
+ found_var = true;
+ i -= 1;
+ }
+ } else {
+ lines.push(x[i]);
+ if (x[i].endsWith('];')) {
+ return lines.join("\n");
+ }
+ }
+ }
+ return null;
+}
+
+// Stupid function extractor for variable.
+function extractVariable(content, varName) {
+ var x = content.split('\n');
+ var found_var = false;
+ var lines = [];
+
+ for (var i = 0; i < x.length; ++i) {
+ if (found_var === false) {
+ var splitter = "var " + varName + " = ";
+ if (x[i].trim().startsWith(splitter)) {
+ found_var = true;
+ i -= 1;
+ }
+ } else {
+ lines.push(x[i]);
+ if (x[i].endsWith(';')) {
+ return lines.join("\n");
+ }
+ }
+ }
+ return null;
+}
+
+function loadContent(content) {
+ var Module = module.constructor;
+ var m = new Module();
+ m._compile(content, "tmp.js");
+ return m.exports;
+}
+
+function readFile(filePath) {
+ return fs.readFileSync(filePath, 'utf8');
+}
+
+function loadThings(thingsToLoad, kindOfLoad, funcToCall, fileContent) {
+ var content = '';
+ for (var i = 0; i < thingsToLoad.length; ++i) {
+ var tmp = funcToCall(fileContent, thingsToLoad[i]);
+ if (tmp === null) {
+ console.error('enable to find ' + kindOfLoad + ' "' + thingsToLoad[i] + '"');
+ process.exit(1);
+ }
+ content += tmp;
+ content += 'exports.' + thingsToLoad[i] + ' = ' + thingsToLoad[i] + ';';
+ }
+ return content;
+}
+
+function lookForEntry(entry, data) {
+ for (var i = 0; i < data.length; ++i) {
+ var allGood = true;
+ for (var key in entry) {
+ if (!entry.hasOwnProperty(key)) {
+ continue;
+ }
+ var value = data[i][key];
+ // To make our life easier, if there is a "parent" type, we add it to the path.
+ if (key === 'path' && data[i]['parent'] !== undefined) {
+ if (value.length > 0) {
+ value += '::' + data[i]['parent']['name'];
+ } else {
+ value = data[i]['parent']['name'];
+ }
+ }
+ if (value !== entry[key]) {
+ allGood = false;
+ break;
+ }
+ }
+ if (allGood === true) {
+ return true;
+ }
+ }
+ return false;
+}
+
+function main(argv) {
+ if (argv.length !== 3) {
+ console.error("Expected toolchain to check as argument (for example 'x86_64-apple-darwin'");
+ return 1;
+ }
+ var toolchain = argv[2];
+
+ var mainJs = readFile("build/" + toolchain + "/doc/main.js");
+ var searchIndex = readFile("build/" + toolchain + "/doc/search-index.js").split("\n");
+ if (searchIndex[searchIndex.length - 1].length === 0) {
+ searchIndex.pop();
+ }
+ searchIndex.pop();
+ searchIndex = loadContent(searchIndex.join("\n") + '\nexports.searchIndex = searchIndex;');
+ finalJS = "";
+
+ var arraysToLoad = ["itemTypes"];
+ var variablesToLoad = ["MAX_LEV_DISTANCE", "MAX_RESULTS", "TY_PRIMITIVE", "levenshtein_row2"];
+ // execQuery first parameter is built in getQuery (which takes in the search input).
+ // execQuery last parameter is built in buildIndex.
+ // buildIndex requires the hashmap from search-index.
+ var functionsToLoad = ["levenshtein", "validateResult", "getQuery", "buildIndex", "execQuery"];
+
+ finalJS += 'window = { "currentCrate": "std" };\n';
+ finalJS += loadThings(arraysToLoad, 'array', extractArrayVariable, mainJs);
+ finalJS += loadThings(variablesToLoad, 'variable', extractVariable, mainJs);
+ finalJS += loadThings(functionsToLoad, 'function', extractFunction, mainJs);
+
+ var loaded = loadContent(finalJS);
+ var index = loaded.buildIndex(searchIndex.searchIndex);
+
+ var errors = 0;
+
+ fs.readdirSync(TEST_FOLDER).forEach(function(file) {
+ var loadedFile = loadContent(readFile(TEST_FOLDER + file) +
+ 'exports.QUERY = QUERY;exports.EXPECTED = EXPECTED;');
+ const expected = loadedFile.EXPECTED;
+ const query = loadedFile.QUERY;
+ var results = loaded.execQuery(loaded.getQuery(query), index);
+ process.stdout.write('Checking "' + file + '" ... ');
+ var error_text = [];
+ for (var key in expected) {
+ if (!expected.hasOwnProperty(key)) {
+ continue;
+ }
+ if (!results.hasOwnProperty(key)) {
+ error_text.push('==> Unknown key "' + key + '"');
+ break;
+ }
+ var entry = expected[key];
+ var found = false;
+ for (var i = 0; i < entry.length; ++i) {
+ if (lookForEntry(entry[i], results[key]) === true) {
+ found = true;
+ } else {
+ error_text.push("==> Result not found in '" + key + "': '" +
+ JSON.stringify(entry[i]) + "'");
+ }
+ }
+ }
+ if (error_text.length !== 0) {
+ errors += 1;
+ console.error("FAILED");
+ console.error(error_text.join("\n"));
+ } else {
+ console.log("OK");
+ }
+ });
+ return errors;
+}
+
+process.exit(main(process.argv));
-Subproject commit 6714a447d063b079de8fb2884ded2c8c3e96bc1d
+Subproject commit e0e3e22248cd14ebbe0253e9720261a0328bfc59
let prev_newline_idx = contents[..prev_newline_idx].rfind('\n');
if let Some(nl) = prev_newline_idx {
let prev_line = &contents[nl + 1 .. mod_tests_idx];
- let emcc_cfg = "cfg(all(test, not(target_os";
- if prev_line.contains(emcc_cfg) {
+ if prev_line.contains("cfg(all(test, not(target_os")
+ || prev_line.contains("cfg(all(test, not(any(target_os") {
nl
} else {
mod_tests_idx
features
.iter()
.filter(|&(_, ref f)| f.level == Status::Unstable)
- .map(|(name, _)| name.to_owned())
+ .map(|(name, _)| name.replace('_', "-"))
.collect()
}
.map(|entry| entry.expect("could not read directory entry"))
.filter(dir_entry_is_file)
.map(|entry| entry.file_name().into_string().unwrap())
- .map(|n| n.trim_right_matches(".md").replace('-', "_"))
+ .map(|n| n.trim_right_matches(".md").to_owned())
.collect()
}
set
.iter()
.map(|ref n| format!(" - [{}]({}/{}.md)",
- n,
+ n.replace('-', "_"),
dir,
- n.replace('_', "-")))
+ n))
.fold("".to_owned(), |s, a| s + &a + "\n")
}
let unstable_section_file_names = collect_unstable_book_section_file_names(src);
t!(fs::create_dir_all(&out));
for feature_name in &unstable_features - &unstable_section_file_names {
- let file_name = format!("{}.md", feature_name.replace('_', "-"));
+ let feature_name_underscore = feature_name.replace('-', "_");
+ let file_name = format!("{}.md", feature_name);
let out_file_path = out.join(&file_name);
- let feature = &features[&feature_name];
+ let feature = &features[&feature_name_underscore];
if has_valid_tracking_issue(&feature) {
- generate_stub_issue(&out_file_path, &feature_name, feature.tracking_issue.unwrap());
+ generate_stub_issue(&out_file_path,
+ &feature_name_underscore,
+ feature.tracking_issue.unwrap());
} else {
- generate_stub_no_issue(&out_file_path, &feature_name);
+ generate_stub_no_issue(&out_file_path, &feature_name_underscore);
}
}
}