Fixes issue #43205: ICE in Rvalue::Len evaluation.
- fixes evaluation of array length for zero-sized type referenced by rvalue operand.
- adds test to verify fix.
*Cause of the issue*.
Zero-sized aggregates are handled as operands, not lvalues. Therefore while visiting `Assign` statement by `LocalAnalyser`, `mark_as_lvalue()` is not called for related `Local`. This behaviour is controlled by `rvalue_creates_operand()` method.
As result it causes error later, when rvalue operand is evaluated in `trans_rvalue_operand()` while handling `Rvalue::Len` case. Array length evaluation invokes `trans_lvalue()` which expects referenced `Local` to be value, not operand.
*How it is fixed*.
In certain cases result of `Rvalue::Len` can be evaluated without calling
`trans_lvalue()`. Method `evaluate_array_len()` is introduced to handle length
evaluation for zero-sized types referenced by Locals.
*Some concerns*.
- `trans_lvalue()` has two other entry points in `rvalue.rs`: it is invoked while handling `Rvalue::Ref` and `Rvalue::Discriminant`. There is a chance those may produce the same issue, but I've failed to write a specific test that leads to this.
- `evaluate_array_len()` performs the same check (matches lvalue and `Local`), which is performed again in `trans_lvalue()`. Without changing `trans_lvalue()` signature to make it aware that caller deals with rvalue, it seems there is no cheap solution to avoid this check.
- `i686-pc-windows-msvc`
- `x86_64-pc-windows-msvc`
-The build triple can be specified by either specifying `--build=ABI` when
+The build triple can be specified by either specifying `--build=<triple>` when
invoking `x.py` commands, or by copying the `config.toml` file (as described
in Building From Source), and modifying the `build` option under the `[build]`
section.
# - set PATH=%PATH%;%CD% -- this already happens above for sccache
# Install InnoSetup to get `iscc` used to produce installers
- - appveyor-retry choco install -y InnoSetup
+ - appveyor-retry appveyor DownloadFile https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-08-22-is.exe
+ - 2017-08-22-is.exe /VERYSILENT /SUPPRESSMSGBOXES /NORESTART /SP-
- set PATH="C:\Program Files (x86)\Inno Setup 5";%PATH%
# Help debug some handle issues on AppVeyor
"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.29 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-demangle 0.1.4 (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)",
]
"lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 1.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "toml 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "build-manifest"
version = "0.1.0"
dependencies = [
- "serde 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "toml 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
[[package]]
name = "cargo"
version = "0.22.0"
-source = "git+https://github.com/rust-lang/cargo#88aa6423a164774d09abc78a24e74e8e665f651b"
+source = "git+https://github.com/rust-lang/cargo#bcf3997b1fa177afc5b6c632a6fbbf6cc75df427"
replace = "cargo 0.22.0"
[[package]]
"atty 0.2.2 (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.4 (registry+https://github.com/rust-lang/crates.io-index)",
"crates-io 0.11.0",
"crossbeam 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
"curl 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 1.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "openssl 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "openssl 0.9.17 (registry+https://github.com/rust-lang/crates.io-index)",
"psapi-sys 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "same-file 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
"scoped-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"semver 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_ignored 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"shell-escape 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
"tar 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)",
"tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
"termcolor 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "toml 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
"url 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)",
]
name = "cargotest"
version = "0.1.0"
dependencies = [
- "bufstream 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
"cargo 0.22.0",
"filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"flate2 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)",
"git2 0.6.6 (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)",
- "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"tar 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)",
- "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
"url 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)",
]
[[package]]
[[package]]
name = "clap"
-version = "2.25.1"
+version = "2.26.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
"bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
"strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
"term_size 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "textwrap 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "unicode-segmentation 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "textwrap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
"vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"yaml-rust 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.0.0",
]
+[[package]]
+name = "core-foundation"
+version = "0.4.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "core-foundation-sys 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "core-foundation-sys"
+version = "0.4.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
[[package]]
name = "crates-io"
version = "0.11.0"
dependencies = [
"curl 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"error-chain 0.11.0-rc.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
"curl-sys 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)",
"openssl-probe 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "openssl-sys 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)",
- "socket2 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "openssl-sys 0.9.17 (registry+https://github.com/rust-lang/crates.io-index)",
+ "socket2 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)",
]
"gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)",
"libz-sys 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)",
- "openssl-sys 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "openssl-sys 0.9.17 (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)",
dependencies = [
"lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
"strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
name = "find_all_refs_no_cfg_test"
version = "0.1.0"
+[[package]]
+name = "find_impls"
+version = "0.1.0"
+
[[package]]
name = "flate2"
version = "0.2.19"
"libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)",
"libgit2-sys 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
"openssl-probe 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "openssl-sys 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "openssl-sys 0.9.17 (registry+https://github.com/rust-lang/crates.io-index)",
"url 1.5.1 (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.0 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
"walkdir 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
+[[package]]
+name = "infer_bin"
+version = "0.1.0"
+
+[[package]]
+name = "infer_custom_bin"
+version = "0.1.0"
+
+[[package]]
+name = "infer_lib"
+version = "0.1.0"
+
[[package]]
name = "installer"
version = "0.0.0"
dependencies = [
- "clap 2.25.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "clap 2.26.0 (registry+https://github.com/rust-lang/crates.io-index)",
"error-chain 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
"flate2 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)",
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
[[package]]
name = "jsonrpc-core"
-version = "7.0.1"
+version = "7.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"futures 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
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.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"url_serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)",
"libssh2-sys 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
"libz-sys 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)",
- "openssl-sys 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "openssl-sys 0.9.17 (registry+https://github.com/rust-lang/crates.io-index)",
"pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
]
"cmake 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)",
"libz-sys 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)",
- "openssl-sys 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "openssl-sys 0.9.17 (registry+https://github.com/rust-lang/crates.io-index)",
"pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "lzma-sys"
-version = "0.1.7"
+version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
version = "0.0.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "clap 2.25.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "clap 2.26.0 (registry+https://github.com/rust-lang/crates.io-index)",
"env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
"handlebars 0.26.2 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"open 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"pulldown-cmark 0.0.14 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "toml 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "toml 0.4.5 (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)",
- "net2 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)",
+ "net2 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "net2"
-version = "0.2.30"
+version = "0.2.31"
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)",
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"num-bigint 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
- "num-complex 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num-complex 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
"num-integer 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
"num-iter 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)",
"num-rational 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)",
[[package]]
name = "num-complex"
-version = "0.1.39"
+version = "0.1.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)",
]
+[[package]]
+name = "omit_init_build"
+version = "0.1.0"
+
[[package]]
name = "open"
version = "1.2.0"
[[package]]
name = "openssl"
-version = "0.9.15"
+version = "0.9.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
"foreign-types 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)",
- "openssl-sys 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "openssl-sys 0.9.17 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
[[package]]
name = "openssl-sys"
-version = "0.9.15"
+version = "0.9.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.29 (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)",
]
[[package]]
[[package]]
name = "racer"
-version = "2.0.9"
+version = "2.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "clap 2.25.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "clap 2.26.0 (registry+https://github.com/rust-lang/crates.io-index)",
"env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"syntex_errors 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)",
"syntex_syntax 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)",
"toml 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
dependencies = [
"cargo 0.22.0 (git+https://github.com/rust-lang/cargo)",
"env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "jsonrpc-core 7.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "jsonrpc-core 7.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"languageserver-types 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "racer 2.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "racer 2.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
"rls-analysis 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
"rls-data 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rls-vfs 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustfmt-nightly 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustfmt-nightly 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "toml 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
"url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"url_serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
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.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.11 (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.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "racer 2.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "racer 2.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
"rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
name = "rustbook"
version = "0.1.0"
dependencies = [
- "clap 2.25.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "clap 2.26.0 (registry+https://github.com/rust-lang/crates.io-index)",
"mdbook 0.0.22 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rustc-demangle"
-version = "0.1.4"
+version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
"graphviz 0.0.0",
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc 0.0.0",
- "rustc_data_structures 0.0.0",
"rustc_errors 0.0.0",
"rustc_mir 0.0.0",
"syntax 0.0.0",
"proc_macro 0.0.0",
"rustc 0.0.0",
"rustc_back 0.0.0",
- "rustc_const_math 0.0.0",
"rustc_data_structures 0.0.0",
"rustc_errors 0.0.0",
"serialize 0.0.0",
"num_cpus 1.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
"owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc 0.0.0",
- "rustc-demangle 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-demangle 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc_allocator 0.0.0",
"rustc_back 0.0.0",
"rustc_bitflags 0.0.0",
name = "rustc_tsan"
version = "0.0.0"
dependencies = [
+ "alloc 0.0.0",
"alloc_system 0.0.0",
"build_helper 0.1.0",
"cmake 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)",
[[package]]
name = "rustfmt-nightly"
-version = "0.2.1"
+version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"diff 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"strings 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "toml 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "unicode-segmentation 1.1.0 (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)",
]
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.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
[[package]]
name = "serde"
-version = "1.0.10"
+version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "serde_derive"
-version = "1.0.10"
+version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
version = "0.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "serde 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
"dtoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
[[package]]
name = "socket2"
-version = "0.2.1"
+version = "0.2.2"
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)",
version = "0.0.0"
dependencies = [
"fmt_macros 0.0.0",
- "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"proc_macro 0.0.0",
"rustc_errors 0.0.0",
"syntax 0.0.0",
[[package]]
name = "textwrap"
-version = "0.6.0"
+version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"term_size 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
[[package]]
name = "toml"
-version = "0.4.2"
+version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "serde 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
[[package]]
name = "unicode-segmentation"
-version = "1.1.0"
+version = "1.2.0"
source = "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.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
"url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "lzma-sys 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lzma-sys 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
"checksum bufstream 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f2f382711e76b9de6c744cc00d0497baba02fb00a787f088c879f01d09468e32"
"checksum cargo 0.22.0 (git+https://github.com/rust-lang/cargo)" = "<none>"
"checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de"
-"checksum clap 2.25.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7f1aabf260a8f3fefa8871f16b531038c98dd9eab1cfa2c575e78c459abfa3a0"
+"checksum clap 2.26.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2267a8fdd4dce6956ba6649e130f62fb279026e5e84b92aa939ac8f85ce3f9f0"
"checksum cmake 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)" = "b8ebbb35d3dc9cd09497168f33de1acb79b265d350ab0ac34133b98f8509af1f"
+"checksum core-foundation 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5909502e547762013619f4c4e01cc7393c20fe2d52d7fa471c1210adb2320dc7"
+"checksum core-foundation-sys 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bc9fb3d6cb663e6fd7cf1c63f9b144ee2b1e4a78595a0451dd34bff85b9a3387"
"checksum crossbeam 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "0c5ea215664ca264da8a9d9c3be80d2eaf30923c259d03e870388eb927508f97"
"checksum curl 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7034c534a1d7d22f7971d6088aa9d281d219ef724026c3428092500f41ae9c2c"
"checksum curl-sys 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d5481162dc4f424d088581db2f979fa7d4c238fe9794595de61d8d7522e277de"
"checksum ignore 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b3fcaf2365eb14b28ec7603c98c06cc531f19de9eb283d89a3dff8417c8c99f5"
"checksum itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eb2f404fbc66fd9aac13e998248505e7ecb2ad8e44ab6388684c5fb11c6c251c"
"checksum jobserver 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "443ae8bc0af6c106e6e8b77e04684faecc1a5ce94e058f4c2b0a037b0ea1b133"
-"checksum jsonrpc-core 7.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "da622868a84d3f4fd897f6408ba6714aabf663302802358564b384157c1a5bfa"
+"checksum jsonrpc-core 7.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "903e5eee845f3d83c1436d12848d97b1247cf850ff06a8e1db2f1ce3543af2cf"
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
"checksum languageserver-types 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d52e477b23bf52cd3ca0f9fc6c5d14be954eec97e3b9cdfbd962d911bd533caf"
"checksum lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3b37545ab726dd833ec6420aaba8231c5b320814b9029ad585555d2a03e94fbf"
"checksum libssh2-sys 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0db4ec23611747ef772db1c4d650f8bd762f07b461727ec998f953c614024b75"
"checksum libz-sys 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)" = "3fdd64ef8ee652185674455c1d450b83cbc8ad895625d543b5324d923f82e4d8"
"checksum log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "880f77541efa6e5cc74e76910c9884d9859683118839d6a1dc3b11e63512565b"
-"checksum lzma-sys 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "013fa6506eb7d26040c46dab9ecb7ccb4e2896b5bf24a9d65932501ea9f67af8"
+"checksum lzma-sys 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "66b2e318eb97ab84f05725471f90c52a09c964053a5899a13fd0165acc26d00b"
"checksum matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "100aabe6b8ff4e4a7e32c1c13523379802df0772b82466207ac25b013f193376"
"checksum mdbook 0.0.22 (registry+https://github.com/rust-lang/crates.io-index)" = "22911d86cde6f80fa9f0fb2a68bbbde85d97af4fe0ce267141c83a4187d28700"
"checksum memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d8b629fb514376c675b98c1421e80b151d3817ac42d7c667717d282761418d20"
"checksum memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1dbccc0e46f1ea47b9f17e6d67c5a96bd27030519c519c9c91327e31275a47b4"
"checksum miniz-sys 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "28eaee17666671fa872e567547e8428e83308ebe5808cdf6a0e28397dbe2c726"
"checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919"
-"checksum net2 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)" = "94101fd932816f97eb9a5116f6c1a11511a1fed7db21c5ccd823b2dc11abf566"
+"checksum net2 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)" = "3a80f842784ef6c9a958b68b7516bc7e35883c614004dd94959a4dca1b716c09"
"checksum num 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "a311b77ebdc5dd4cf6449d81e4135d9f0e3b153839ac90e648a8ef538f923525"
"checksum num-bigint 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "8fd0f8dbb4c0960998958a796281d88c16fbe68d87b1baa6f31e2979e81fd0bd"
-"checksum num-complex 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "eb24db7f1904e67a5dfe5f7f62b82f5c963e0f777b23f98cde9c5094fc4fa179"
+"checksum num-complex 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "503e668405c5492d67cf662a81e05be40efe2e6bcf10f7794a07bd9865e704e6"
"checksum num-integer 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)" = "d1452e8b06e448a07f0e6ebb0bb1d92b8890eea63288c0b627331d53514d0fba"
"checksum num-iter 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)" = "7485fcc84f85b4ecd0ea527b14189281cf27d60e583ae65ebc9c088b13dffe01"
"checksum num-rational 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "288629c76fac4b33556f4b7ab57ba21ae202da65ba8b77466e6d598e31990790"
"checksum num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "99843c856d68d8b4313b03a17e33c4bb42ae8f6610ea81b28abe076ac721b9b0"
"checksum num_cpus 1.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "aec53c34f2d0247c5ca5d32cca1478762f301740468ee9ee6dcb7a0dd7a0c584"
"checksum open 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3478ed1686bd1300c8a981a940abc92b06fac9cbef747f4c668d4e032ff7b842"
-"checksum openssl 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)" = "f776f1d8af832fd2c637ee182c801e8f7ea8895718a2be9914cca001f6e2c40a"
+"checksum openssl 0.9.17 (registry+https://github.com/rust-lang/crates.io-index)" = "085aaedcc89a2fac1eb2bc19cd66f29d4ea99fec60f82a5f3a88a6be7dbd90b5"
"checksum openssl-probe 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d98df0270d404ccd3c050a41d579c52d1db15375168bb3471e04ec0f5f378daf"
-"checksum openssl-sys 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)" = "ad95f8160d1c150c4f44d4c4959732e048ac046c37f597fe362f8bf57561ffb4"
+"checksum openssl-sys 0.9.17 (registry+https://github.com/rust-lang/crates.io-index)" = "7e3a9845a4c9fdb321931868aae5549e96bb7b979bf9af7de03603d74691b5f3"
"checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37"
"checksum percent-encoding 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de154f638187706bde41d9b4738748933d64e6b37bdbffc0b47a97d16a6ae356"
"checksum pest 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0a6dda33d67c26f0aac90d324ab2eb7239c819fc7b2552fe9faa4fe88441edc8"
"checksum quick-error 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c36987d4978eb1be2e422b1e0423a557923a5c3e7e6f31d5699e9aafaefa469"
"checksum quote 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4c5cf478fe1006dbcc72567121d23dbdae5f1632386068c5c86ff4f645628504"
"checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a"
-"checksum racer 2.0.9 (registry+https://github.com/rust-lang/crates.io-index)" = "9079a128fdb6f0c8850010e1478b215d4c00134654bf995bfda41824951ce9bd"
+"checksum racer 2.0.10 (registry+https://github.com/rust-lang/crates.io-index)" = "f120c7510ef7aff254aeb06067fb6fac573ec96a1660e194787cf9dced412bf0"
"checksum rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "022e0636ec2519ddae48154b028864bdce4eaf7d35226ab8e65c611be97b189d"
"checksum regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)" = "4fd4ace6a8cf7860714a2c2280d6c1f7e6a413486c13298bbc86fd3da019402f"
"checksum regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1731164734096285ec2a5ec7fea5248ae2f5485b3feeb0115af4fda2183b2d1b"
"checksum rls-data 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "11d339f1888e33e74d8032de0f83c40b2bdaaaf04a8cfc03b32186c3481fb534"
"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-demangle 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3058a43ada2c2d0b92b3ae38007a2d0fa5e9db971be260e0171408a4ff471c95"
+"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 rustfmt-nightly 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "aa1ffc66e1e1786355f22e8a958a57bd67fbf9564f522f87f31de9586715f8f6"
+"checksum rustfmt-nightly 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6eea0d0590ae793fc4d281df56e01dc7531575c8ed9a72fadf5fdc7305a0d32f"
"checksum same-file 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d931a44fdaa43b8637009e7632a02adc4f2b2e0733c08caa4cf00e8da4a117a7"
"checksum scoped-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f417c22df063e9450888a7561788e9bd46d3bb3c1466435b4eccb903807f147d"
"checksum scopeguard 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "59a076157c1e2dc561d8de585151ee6965d910dd4dcb5dabb7ae3e83981a6c57"
"checksum semver 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3fdd61b85a0fa777f7fb7c454b9189b2941b110d1385ce84d7f76efdf1606a85"
"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
-"checksum serde 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)" = "433d7d9f8530d5a939ad5e0e72a6243d2e42a24804f70bf592c679363dcacb2f"
-"checksum serde_derive 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)" = "7b707cf0d4cab852084f573058def08879bb467fda89d99052485e7d00edd624"
+"checksum serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)" = "f7726f29ddf9731b17ff113c461e362c381d9d69433f79de4f3dd572488823e9"
+"checksum serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)" = "cf823e706be268e73e7747b147aa31c8f633ab4ba31f115efb57e5047c3a76dd"
"checksum serde_derive_internals 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)" = "37aee4e0da52d801acfbc0cc219eb1eda7142112339726e427926a6f6ee65d3a"
"checksum serde_ignored 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c10e798e4405d7dcec3658989e35ee6706f730a9ed7c1184d5ebd84317e82f46"
"checksum serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "48b04779552e92037212c3615370f6bd57a40ebba7f20e554ff9f55e41a69a7b"
"checksum shell-escape 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "dd5cc96481d54583947bfe88bf30c23d53f883c6cd0145368b69989d97b84ef8"
-"checksum socket2 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "12cdbddbaa27bf94cc194b8e37f5811db6fe83cea96cf99cf1f8e92b65a41371"
+"checksum socket2 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4daf80fcf54186fac4fe049e0b39d36a5cfde69a11a06413e61e77f553cccf9a"
"checksum stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "15132e0e364248108c5e2c02e3ab539be8d6f5d52a01ca9bbf27ed657316f02b"
"checksum strings 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "da75d8bf2c4d210d63dd09581a041b036001f9f6e03d9b151dbff810fb7ba26a"
"checksum strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d15c810519a91cf877e7e36e63fe068815c678181439f2f29e2562147c3694"
"checksum term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "fa63644f74ce96fbeb9b794f66aff2a52d601cbd5e80f4b97123e3899f4570f1"
"checksum term_size 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2b6b55df3198cc93372e85dd2ed817f0e38ce8cc0f22eb32391bfad9c4bf209"
"checksum termcolor 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9a5193a56b8d82014662c4b933dea6bec851daf018a2b01722e007daaf5f9dca"
-"checksum textwrap 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f86300c3e7416ee233abd7cda890c492007a3980f941f79185c753a701257167"
+"checksum textwrap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f728584ea33b0ad19318e20557cb0a39097751dbb07171419673502f848c7af6"
"checksum thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9539db560102d1cef46b8b78ce737ff0bb64e7e18d35b2a5688f7d097d0ff03"
"checksum thread_local 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "8576dbbfcaef9641452d5cf0df9b0e7eeab7694956dd33bb61515fb8f18cfdd5"
"checksum thread_local 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1697c4b57aeeb7a536b647165a2825faddffb1d3bad386d507709bd51a90bb14"
"checksum toml 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "736b60249cb25337bc196faa43ee12c705e426f3d55c214d73a4e7be06f92cb4"
-"checksum toml 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b0601da6c97135c8d330c7a13a013ca6cd4143221b01de2f8d4edc50a9e551c7"
+"checksum toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a7540f4ffc193e0d3c94121edb19b055670d369f77d5804db11ae053a45b6e7e"
"checksum typed-arena 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5934776c3ac1bea4a9d56620d6bf2d483b20d394e49581db40f187e1118ff667"
"checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5"
"checksum unicode-normalization 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "51ccda9ef9efa3f7ef5d91e8f9b83bbe6955f9bf86aec89d5cce2c874625920f"
-"checksum unicode-segmentation 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "18127285758f0e2c6cf325bb3f3d138a12fee27de4f23e146cd6a179f26c2cf3"
+"checksum unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a8083c594e02b8ae1654ae26f0ade5158b119bd88ad0e8227a5d8fcd72407946"
"checksum unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bf3a113775714a22dcb774d8ea3655c53a32debae63a063acc00a91cc586245f"
"checksum unicode-xid 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "36dff09cafb4ec7c8cf0023eb0b686cb6ce65499116a12201c9e11840ca01beb"
"checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc"
"tools/rls/test_data/multiple_bins",
"tools/rls/test_data/bin_lib",
"tools/rls/test_data/reformat_with_range",
+ "tools/rls/test_data/find_impls",
+ "tools/rls/test_data/infer_bin",
+ "tools/rls/test_data/infer_custom_bin",
+ "tools/rls/test_data/infer_lib",
+ "tools/rls/test_data/omit_init_build",
]
# Curiously, compiletest will segfault if compiled with opt-level=3 on 64-bit
}
// Ninja is currently only used for LLVM itself.
- // Some Linux distros rename `ninja` to `ninja-build`.
- // CMake can work with either binary name.
- if building_llvm && build.config.ninja && cmd_finder.maybe_have("ninja-build").is_none() {
- cmd_finder.must_have("ninja");
+ if building_llvm {
+ if build.config.ninja {
+ // Some Linux distros rename `ninja` to `ninja-build`.
+ // CMake can work with either binary name.
+ if cmd_finder.maybe_have("ninja-build").is_none() {
+ cmd_finder.must_have("ninja");
+ }
+ }
+
+ // If ninja isn't enabled but we're building for MSVC then we try
+ // doubly hard to enable it. It was realized in #43767 that the msbuild
+ // CMake generator for MSVC doesn't respect configuration options like
+ // disabling LLVM assertions, which can often be quite important!
+ //
+ // In these cases we automatically enable Ninja if we find it in the
+ // environment.
+ if !build.config.ninja && build.config.build.contains("msvc") {
+ if cmd_finder.maybe_have("ninja").is_some() {
+ build.config.ninja = true;
+ }
+ }
}
build.config.python = build.config.python.take().map(|p| cmd_finder.must_have(p))
In order to avoid one-off dependencies for this task, this script uses
a reasonably working HTML parser and the existing XPath implementation
-from Python 2's standard library. Hopefully we won't render
+from Python's standard library. Hopefully we won't render
non-well-formed HTML.
# Commands
import re
import shlex
from collections import namedtuple
-from HTMLParser import HTMLParser
+try:
+ from html.parser import HTMLParser
+except ImportError:
+ from HTMLParser import HTMLParser
from xml.etree import cElementTree as ET
# ⇤/⇥ are not in HTML 4 but are in HTML 5
-from htmlentitydefs import entitydefs
+try:
+ from html.entities import entitydefs
+except ImportError:
+ from htmlentitydefs import entitydefs
entitydefs['larrb'] = u'\u21e4'
entitydefs['rarrb'] = u'\u21e5'
entitydefs['nbsp'] = ' '
VOID_ELEMENTS = set(['area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'keygen',
'link', 'menuitem', 'meta', 'param', 'source', 'track', 'wbr'])
+# Python 2 -> 3 compatibility
+try:
+ unichr
+except NameError:
+ unichr = chr
class CustomHTMLParser(HTMLParser):
"""simplified HTML parser.
# strip the common prefix from the current line if needed
if lastline is not None:
- maxprefix = 0
- for i in xrange(min(len(line), len(lastline))):
- if line[i] != lastline[i]:
- break
- maxprefix += 1
- line = line[maxprefix:].lstrip()
+ common_prefix = os.path.commonprefix([line, lastline])
+ line = line[len(common_prefix):].lstrip()
firstlineno = firstlineno or lineno
if line.endswith('\\'):
def get_commands(template):
- with open(template, 'rUb') as f:
+ with open(template, 'rU') as f:
for lineno, line in concat_multi_lines(f):
m = LINE_PATTERN.search(line)
if not m:
cache.get_file(c.args[0])
ret = True
except FailedCheck as err:
- cerr = err.message
+ cerr = str(err)
ret = False
elif len(c.args) == 2: # @has/matches <path> <pat> = string test
cerr = "`PATTERN` did not match"
except FailedCheck as err:
message = '@{}{} check failed'.format('!' if c.negated else '', c.cmd)
- print_err(c.lineno, c.context, err.message, message)
+ print_err(c.lineno, c.context, str(err), message)
except InvalidCheck as err:
- print_err(c.lineno, c.context, err.message)
+ print_err(c.lineno, c.context, str(err))
def check(target, commands):
cache = CachedFiles(target)
/// Creates a layout, bypassing all checks.
///
- /// # Unsafety
+ /// # Safety
///
/// This function is unsafe as it does not verify that `align` is
/// a power-of-two that is also less than or equal to 2^31, nor
/// behavior, e.g. to ensure initialization to particular sets of
/// bit patterns.)
///
- /// # Unsafety
+ /// # Safety
///
/// This function is unsafe because undefined behavior can result
/// if the caller does not ensure that `layout` has non-zero size.
/// Deallocate the memory referenced by `ptr`.
///
- /// # Unsafety
+ /// # Safety
///
/// This function is unsafe because undefined behavior can result
/// if the caller does not ensure all of the following:
/// behavior is well-defined (though underspecified) when this
/// constraint is violated; further discussion below.
///
- /// # Unsafety
+ /// # Safety
///
/// This function is unsafe because undefined behavior can result
/// if the caller does not ensure all of the following:
/// Behaves like `alloc`, but also ensures that the contents
/// are set to zero before being returned.
///
- /// # Unsafety
+ /// # Safety
///
/// This function is unsafe for the same reasons that `alloc` is.
///
/// the returned block. For some `layout` inputs, like arrays, this
/// may include extra storage usable for additional data.
///
- /// # Unsafety
+ /// # Safety
///
/// This function is unsafe for the same reasons that `alloc` is.
///
/// the returned block. For some `layout` inputs, like arrays, this
/// may include extra storage usable for additional data.
///
- /// # Unsafety
+ /// # Safety
///
/// This function is unsafe for the same reasons that `realloc` is.
///
/// memory block referenced by `ptr` has not been transferred, and
/// the contents of the memory block are unaltered.
///
- /// # Unsafety
+ /// # Safety
///
/// This function is unsafe because undefined behavior can result
/// if the caller does not ensure all of the following:
/// the memory block has not been transferred, and the contents of
/// the memory block are unaltered.
///
- /// # Unsafety
+ /// # Safety
///
/// This function is unsafe because undefined behavior can result
/// if the caller does not ensure all of the following:
///
/// Captures a common usage pattern for allocators.
///
- /// # Unsafety
+ /// # Safety
///
/// This function is unsafe because undefined behavior can result
/// if the caller does not ensure both:
/// The returned block is suitable for passing to the
/// `alloc`/`realloc` methods of this allocator.
///
- /// # Unsafety
+ /// # Safety
///
/// This function is unsafe because undefined behavior can result
/// if the caller does not ensure all of the following:
///
/// Captures a common usage pattern for allocators.
///
- /// # Unsafety
+ /// # Safety
///
/// This function is unsafe because undefined behavior can result
/// if the caller does not ensure both:
//!
//! [arc]: struct.Arc.html
-use boxed::Box;
-
use core::sync::atomic;
use core::sync::atomic::Ordering::{Acquire, Relaxed, Release, SeqCst};
use core::borrow;
use core::fmt;
use core::cmp::Ordering;
use core::intrinsics::abort;
-use core::mem;
-use core::mem::uninitialized;
+use core::mem::{self, size_of_val, uninitialized};
use core::ops::Deref;
use core::ops::CoerceUnsized;
use core::ptr::{self, Shared};
use core::{isize, usize};
use core::convert::From;
-use heap::{Heap, Alloc, Layout};
+use heap::{Heap, Alloc, Layout, box_free};
+use boxed::Box;
+use string::String;
+use vec::Vec;
/// A soft limit on the amount of references that may be made to an `Arc`.
///
}
}
+impl<T: ?Sized> Arc<T> {
+ // Allocates an `ArcInner<T>` with sufficient space for an unsized value
+ unsafe fn allocate_for_ptr(ptr: *const T) -> *mut ArcInner<T> {
+ // Create a fake ArcInner to find allocation size and alignment
+ let fake_ptr = ptr as *mut ArcInner<T>;
+
+ let layout = Layout::for_value(&*fake_ptr);
+
+ let mem = Heap.alloc(layout)
+ .unwrap_or_else(|e| Heap.oom(e));
+
+ // Initialize the real ArcInner
+ let inner = set_data_ptr(ptr as *mut T, mem) as *mut ArcInner<T>;
+
+ ptr::write(&mut (*inner).strong, atomic::AtomicUsize::new(1));
+ ptr::write(&mut (*inner).weak, atomic::AtomicUsize::new(1));
+
+ inner
+ }
+
+ fn from_box(v: Box<T>) -> Arc<T> {
+ unsafe {
+ let bptr = Box::into_raw(v);
+
+ let value_size = size_of_val(&*bptr);
+ let ptr = Self::allocate_for_ptr(bptr);
+
+ // Copy value as bytes
+ ptr::copy_nonoverlapping(
+ bptr as *const T as *const u8,
+ &mut (*ptr).data as *mut _ as *mut u8,
+ value_size);
+
+ // Free the allocation without dropping its contents
+ box_free(bptr);
+
+ Arc { ptr: Shared::new_unchecked(ptr) }
+ }
+ }
+}
+
+// Sets the data pointer of a `?Sized` raw pointer.
+//
+// For a slice/trait object, this sets the `data` field and leaves the rest
+// unchanged. For a sized raw pointer, this simply sets the pointer.
+unsafe fn set_data_ptr<T: ?Sized, U>(mut ptr: *mut T, data: *mut U) -> *mut T {
+ ptr::write(&mut ptr as *mut _ as *mut *mut u8, data as *mut u8);
+ ptr
+}
+
+impl<T> Arc<[T]> {
+ // Copy elements from slice into newly allocated Arc<[T]>
+ //
+ // Unsafe because the caller must either take ownership or bind `T: Copy`
+ unsafe fn copy_from_slice(v: &[T]) -> Arc<[T]> {
+ let v_ptr = v as *const [T];
+ let ptr = Self::allocate_for_ptr(v_ptr);
+
+ ptr::copy_nonoverlapping(
+ v.as_ptr(),
+ &mut (*ptr).data as *mut [T] as *mut T,
+ v.len());
+
+ Arc { ptr: Shared::new_unchecked(ptr) }
+ }
+}
+
+// Specialization trait used for From<&[T]>
+trait ArcFromSlice<T> {
+ fn from_slice(slice: &[T]) -> Self;
+}
+
+impl<T: Clone> ArcFromSlice<T> for Arc<[T]> {
+ #[inline]
+ default fn from_slice(v: &[T]) -> Self {
+ // Panic guard while cloning T elements.
+ // In the event of a panic, elements that have been written
+ // into the new ArcInner will be dropped, then the memory freed.
+ struct Guard<T> {
+ mem: *mut u8,
+ elems: *mut T,
+ layout: Layout,
+ n_elems: usize,
+ }
+
+ impl<T> Drop for Guard<T> {
+ fn drop(&mut self) {
+ use core::slice::from_raw_parts_mut;
+
+ unsafe {
+ let slice = from_raw_parts_mut(self.elems, self.n_elems);
+ ptr::drop_in_place(slice);
+
+ Heap.dealloc(self.mem, self.layout.clone());
+ }
+ }
+ }
+
+ unsafe {
+ let v_ptr = v as *const [T];
+ let ptr = Self::allocate_for_ptr(v_ptr);
+
+ let mem = ptr as *mut _ as *mut u8;
+ let layout = Layout::for_value(&*ptr);
+
+ // Pointer to first element
+ let elems = &mut (*ptr).data as *mut [T] as *mut T;
+
+ let mut guard = Guard{
+ mem: mem,
+ elems: elems,
+ layout: layout,
+ n_elems: 0,
+ };
+
+ for (i, item) in v.iter().enumerate() {
+ ptr::write(elems.offset(i as isize), item.clone());
+ guard.n_elems += 1;
+ }
+
+ // All clear. Forget the guard so it doesn't free the new ArcInner.
+ mem::forget(guard);
+
+ Arc { ptr: Shared::new_unchecked(ptr) }
+ }
+ }
+}
+
+impl<T: Copy> ArcFromSlice<T> for Arc<[T]> {
+ #[inline]
+ fn from_slice(v: &[T]) -> Self {
+ unsafe { Arc::copy_from_slice(v) }
+ }
+}
+
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> Clone for Arc<T> {
/// Makes a clone of the `Arc` pointer.
}
}
+#[stable(feature = "shared_from_slice", since = "1.21.0")]
+impl<'a, T: Clone> From<&'a [T]> for Arc<[T]> {
+ #[inline]
+ fn from(v: &[T]) -> Arc<[T]> {
+ <Self as ArcFromSlice<T>>::from_slice(v)
+ }
+}
+
+#[stable(feature = "shared_from_slice", since = "1.21.0")]
+impl<'a> From<&'a str> for Arc<str> {
+ #[inline]
+ fn from(v: &str) -> Arc<str> {
+ unsafe { mem::transmute(<Arc<[u8]>>::from(v.as_bytes())) }
+ }
+}
+
+#[stable(feature = "shared_from_slice", since = "1.21.0")]
+impl From<String> for Arc<str> {
+ #[inline]
+ fn from(v: String) -> Arc<str> {
+ Arc::from(&v[..])
+ }
+}
+
+#[stable(feature = "shared_from_slice", since = "1.21.0")]
+impl<T: ?Sized> From<Box<T>> for Arc<T> {
+ #[inline]
+ fn from(v: Box<T>) -> Arc<T> {
+ Arc::from_box(v)
+ }
+}
+
+#[stable(feature = "shared_from_slice", since = "1.21.0")]
+impl<T> From<Vec<T>> for Arc<[T]> {
+ #[inline]
+ fn from(mut v: Vec<T>) -> Arc<[T]> {
+ unsafe {
+ let arc = Arc::copy_from_slice(&v);
+
+ // Allow the Vec to free its memory, but not destroy its contents
+ v.set_len(0);
+
+ arc
+ }
+ }
+}
+
#[cfg(test)]
mod tests {
+ use std::boxed::Box;
use std::clone::Clone;
use std::sync::mpsc::channel;
use std::mem::drop;
}
t.join().unwrap();
}
+
+ #[test]
+ fn test_from_str() {
+ let r: Arc<str> = Arc::from("foo");
+
+ assert_eq!(&r[..], "foo");
+ }
+
+ #[test]
+ fn test_copy_from_slice() {
+ let s: &[u32] = &[1, 2, 3];
+ let r: Arc<[u32]> = Arc::from(s);
+
+ assert_eq!(&r[..], [1, 2, 3]);
+ }
+
+ #[test]
+ fn test_clone_from_slice() {
+ #[derive(Clone, Debug, Eq, PartialEq)]
+ struct X(u32);
+
+ let s: &[X] = &[X(1), X(2), X(3)];
+ let r: Arc<[X]> = Arc::from(s);
+
+ assert_eq!(&r[..], s);
+ }
+
+ #[test]
+ #[should_panic]
+ fn test_clone_from_slice_panic() {
+ use std::string::{String, ToString};
+
+ struct Fail(u32, String);
+
+ impl Clone for Fail {
+ fn clone(&self) -> Fail {
+ if self.0 == 2 {
+ panic!();
+ }
+ Fail(self.0, self.1.clone())
+ }
+ }
+
+ let s: &[Fail] = &[
+ Fail(0, "foo".to_string()),
+ Fail(1, "bar".to_string()),
+ Fail(2, "baz".to_string()),
+ ];
+
+ // Should panic, but not cause memory corruption
+ let _r: Arc<[Fail]> = Arc::from(s);
+ }
+
+ #[test]
+ fn test_from_box() {
+ let b: Box<u32> = box 123;
+ let r: Arc<u32> = Arc::from(b);
+
+ assert_eq!(*r, 123);
+ }
+
+ #[test]
+ fn test_from_box_str() {
+ use std::string::String;
+
+ let s = String::from("foo").into_boxed_str();
+ let r: Arc<str> = Arc::from(s);
+
+ assert_eq!(&r[..], "foo");
+ }
+
+ #[test]
+ fn test_from_box_slice() {
+ let s = vec![1, 2, 3].into_boxed_slice();
+ let r: Arc<[u32]> = Arc::from(s);
+
+ assert_eq!(&r[..], [1, 2, 3]);
+ }
+
+ #[test]
+ fn test_from_box_trait() {
+ use std::fmt::Display;
+ use std::string::ToString;
+
+ let b: Box<Display> = box 123;
+ let r: Arc<Display> = Arc::from(b);
+
+ assert_eq!(r.to_string(), "123");
+ }
+
+ #[test]
+ fn test_from_box_trait_zero_sized() {
+ use std::fmt::Debug;
+
+ let b: Box<Debug> = box ();
+ let r: Arc<Debug> = Arc::from(b);
+
+ assert_eq!(format!("{:?}", r), "()");
+ }
+
+ #[test]
+ fn test_from_vec() {
+ let v = vec![1, 2, 3];
+ let r: Arc<[u32]> = Arc::from(v);
+
+ assert_eq!(&r[..], [1, 2, 3]);
+ }
}
#[stable(feature = "rust1", since = "1.0.0")]
/// that `FnBox` may be deprecated in the future if `Box<FnOnce()>`
/// closures become directly usable.)
///
-/// ### Example
+/// # Examples
///
/// Here is a snippet of code which creates a hashmap full of boxed
/// once closures and then removes them one by one, calling each
//! The [`heap`](heap/index.html) module defines the low-level interface to the
//! default global allocator. It is not compatible with the libc allocator API.
-#![crate_name = "alloc"]
-#![crate_type = "rlib"]
#![allow(unused_attributes)]
#![unstable(feature = "alloc",
reason = "this library is unlikely to be stabilized in its current \
#![feature(unsize)]
#![feature(allocator_internals)]
-#![cfg_attr(not(test), feature(fused, fn_traits, placement_new_protocol))]
+#![cfg_attr(not(test), feature(fused, fn_traits, placement_new_protocol, swap_with_slice))]
#![cfg_attr(test, feature(test, box_heap))]
// Allow testing this library
use core::intrinsics::abort;
use core::marker;
use core::marker::Unsize;
-use core::mem::{self, forget, size_of, size_of_val, uninitialized};
+use core::mem::{self, forget, size_of_val, uninitialized};
use core::ops::Deref;
use core::ops::CoerceUnsized;
use core::ptr::{self, Shared};
use core::convert::From;
use heap::{Heap, Alloc, Layout, box_free};
-use raw_vec::RawVec;
+use string::String;
+use vec::Vec;
struct RcBox<T: ?Sized> {
strong: Cell<usize>,
}
}
-impl Rc<str> {
- /// Constructs a new `Rc<str>` from a string slice.
- #[doc(hidden)]
- #[unstable(feature = "rustc_private",
- reason = "for internal use in rustc",
- issue = "27812")]
- pub fn __from_str(value: &str) -> Rc<str> {
- unsafe {
- // Allocate enough space for `RcBox<str>`.
- let aligned_len = 2 + (value.len() + size_of::<usize>() - 1) / size_of::<usize>();
- let vec = RawVec::<usize>::with_capacity(aligned_len);
- let ptr = vec.ptr();
- forget(vec);
- // Initialize fields of `RcBox<str>`.
- *ptr.offset(0) = 1; // strong: Cell::new(1)
- *ptr.offset(1) = 1; // weak: Cell::new(1)
- ptr::copy_nonoverlapping(value.as_ptr(), ptr.offset(2) as *mut u8, value.len());
- // Combine the allocation address and the string length into a fat pointer to `RcBox`.
- let rcbox_ptr: *mut RcBox<str> = mem::transmute([ptr as usize, value.len()]);
- assert!(aligned_len * size_of::<usize>() == size_of_val(&*rcbox_ptr));
- Rc { ptr: Shared::new_unchecked(rcbox_ptr) }
- }
- }
-}
-
-impl<T> Rc<[T]> {
- /// Constructs a new `Rc<[T]>` from a `Box<[T]>`.
- #[doc(hidden)]
- #[unstable(feature = "rustc_private",
- reason = "for internal use in rustc",
- issue = "27812")]
- pub fn __from_array(value: Box<[T]>) -> Rc<[T]> {
- unsafe {
- let ptr: *mut RcBox<[T]> =
- mem::transmute([mem::align_of::<RcBox<[T; 1]>>(), value.len()]);
- // FIXME(custom-DST): creating this invalid &[T] is dubiously defined,
- // we should have a better way of getting the size/align
- // of a DST from its unsized part.
- let ptr = Heap.alloc(Layout::for_value(&*ptr))
- .unwrap_or_else(|e| Heap.oom(e));
- let ptr: *mut RcBox<[T]> = mem::transmute([ptr as usize, value.len()]);
-
- // Initialize the new RcBox.
- ptr::write(&mut (*ptr).strong, Cell::new(1));
- ptr::write(&mut (*ptr).weak, Cell::new(1));
- ptr::copy_nonoverlapping(
- value.as_ptr(),
- &mut (*ptr).value as *mut [T] as *mut T,
- value.len());
-
- // Free the original allocation without freeing its (moved) contents.
- box_free(Box::into_raw(value));
-
- Rc { ptr: Shared::new_unchecked(ptr as *mut _) }
- }
- }
-}
-
impl<T: ?Sized> Rc<T> {
/// Creates a new [`Weak`][weak] pointer to this value.
///
}
}
+impl<T: ?Sized> Rc<T> {
+ // Allocates an `RcBox<T>` with sufficient space for an unsized value
+ unsafe fn allocate_for_ptr(ptr: *const T) -> *mut RcBox<T> {
+ // Create a fake RcBox to find allocation size and alignment
+ let fake_ptr = ptr as *mut RcBox<T>;
+
+ let layout = Layout::for_value(&*fake_ptr);
+
+ let mem = Heap.alloc(layout)
+ .unwrap_or_else(|e| Heap.oom(e));
+
+ // Initialize the real RcBox
+ let inner = set_data_ptr(ptr as *mut T, mem) as *mut RcBox<T>;
+
+ ptr::write(&mut (*inner).strong, Cell::new(1));
+ ptr::write(&mut (*inner).weak, Cell::new(1));
+
+ inner
+ }
+
+ fn from_box(v: Box<T>) -> Rc<T> {
+ unsafe {
+ let bptr = Box::into_raw(v);
+
+ let value_size = size_of_val(&*bptr);
+ let ptr = Self::allocate_for_ptr(bptr);
+
+ // Copy value as bytes
+ ptr::copy_nonoverlapping(
+ bptr as *const T as *const u8,
+ &mut (*ptr).value as *mut _ as *mut u8,
+ value_size);
+
+ // Free the allocation without dropping its contents
+ box_free(bptr);
+
+ Rc { ptr: Shared::new_unchecked(ptr) }
+ }
+ }
+}
+
+// Sets the data pointer of a `?Sized` raw pointer.
+//
+// For a slice/trait object, this sets the `data` field and leaves the rest
+// unchanged. For a sized raw pointer, this simply sets the pointer.
+unsafe fn set_data_ptr<T: ?Sized, U>(mut ptr: *mut T, data: *mut U) -> *mut T {
+ ptr::write(&mut ptr as *mut _ as *mut *mut u8, data as *mut u8);
+ ptr
+}
+
+impl<T> Rc<[T]> {
+ // Copy elements from slice into newly allocated Rc<[T]>
+ //
+ // Unsafe because the caller must either take ownership or bind `T: Copy`
+ unsafe fn copy_from_slice(v: &[T]) -> Rc<[T]> {
+ let v_ptr = v as *const [T];
+ let ptr = Self::allocate_for_ptr(v_ptr);
+
+ ptr::copy_nonoverlapping(
+ v.as_ptr(),
+ &mut (*ptr).value as *mut [T] as *mut T,
+ v.len());
+
+ Rc { ptr: Shared::new_unchecked(ptr) }
+ }
+}
+
+trait RcFromSlice<T> {
+ fn from_slice(slice: &[T]) -> Self;
+}
+
+impl<T: Clone> RcFromSlice<T> for Rc<[T]> {
+ #[inline]
+ default fn from_slice(v: &[T]) -> Self {
+ // Panic guard while cloning T elements.
+ // In the event of a panic, elements that have been written
+ // into the new RcBox will be dropped, then the memory freed.
+ struct Guard<T> {
+ mem: *mut u8,
+ elems: *mut T,
+ layout: Layout,
+ n_elems: usize,
+ }
+
+ impl<T> Drop for Guard<T> {
+ fn drop(&mut self) {
+ use core::slice::from_raw_parts_mut;
+
+ unsafe {
+ let slice = from_raw_parts_mut(self.elems, self.n_elems);
+ ptr::drop_in_place(slice);
+
+ Heap.dealloc(self.mem, self.layout.clone());
+ }
+ }
+ }
+
+ unsafe {
+ let v_ptr = v as *const [T];
+ let ptr = Self::allocate_for_ptr(v_ptr);
+
+ let mem = ptr as *mut _ as *mut u8;
+ let layout = Layout::for_value(&*ptr);
+
+ // Pointer to first element
+ let elems = &mut (*ptr).value as *mut [T] as *mut T;
+
+ let mut guard = Guard{
+ mem: mem,
+ elems: elems,
+ layout: layout,
+ n_elems: 0,
+ };
+
+ for (i, item) in v.iter().enumerate() {
+ ptr::write(elems.offset(i as isize), item.clone());
+ guard.n_elems += 1;
+ }
+
+ // All clear. Forget the guard so it doesn't free the new RcBox.
+ forget(guard);
+
+ Rc { ptr: Shared::new_unchecked(ptr) }
+ }
+ }
+}
+
+impl<T: Copy> RcFromSlice<T> for Rc<[T]> {
+ #[inline]
+ fn from_slice(v: &[T]) -> Self {
+ unsafe { Rc::copy_from_slice(v) }
+ }
+}
+
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> Deref for Rc<T> {
type Target = T;
}
}
+#[stable(feature = "shared_from_slice", since = "1.21.0")]
+impl<'a, T: Clone> From<&'a [T]> for Rc<[T]> {
+ #[inline]
+ fn from(v: &[T]) -> Rc<[T]> {
+ <Self as RcFromSlice<T>>::from_slice(v)
+ }
+}
+
+#[stable(feature = "shared_from_slice", since = "1.21.0")]
+impl<'a> From<&'a str> for Rc<str> {
+ #[inline]
+ fn from(v: &str) -> Rc<str> {
+ unsafe { mem::transmute(<Rc<[u8]>>::from(v.as_bytes())) }
+ }
+}
+
+#[stable(feature = "shared_from_slice", since = "1.21.0")]
+impl From<String> for Rc<str> {
+ #[inline]
+ fn from(v: String) -> Rc<str> {
+ Rc::from(&v[..])
+ }
+}
+
+#[stable(feature = "shared_from_slice", since = "1.21.0")]
+impl<T: ?Sized> From<Box<T>> for Rc<T> {
+ #[inline]
+ fn from(v: Box<T>) -> Rc<T> {
+ Rc::from_box(v)
+ }
+}
+
+#[stable(feature = "shared_from_slice", since = "1.21.0")]
+impl<T> From<Vec<T>> for Rc<[T]> {
+ #[inline]
+ fn from(mut v: Vec<T>) -> Rc<[T]> {
+ unsafe {
+ let rc = Rc::copy_from_slice(&v);
+
+ // Allow the Vec to free its memory, but not destroy its contents
+ v.set_len(0);
+
+ rc
+ }
+ }
+}
+
/// `Weak` is a version of [`Rc`] that holds a non-owning reference to the
/// managed value. The value is accessed by calling [`upgrade`] on the `Weak`
/// pointer, which returns an [`Option`]`<`[`Rc`]`<T>>`.
assert!(Rc::ptr_eq(&five, &same_five));
assert!(!Rc::ptr_eq(&five, &other_five));
}
+
+ #[test]
+ fn test_from_str() {
+ let r: Rc<str> = Rc::from("foo");
+
+ assert_eq!(&r[..], "foo");
+ }
+
+ #[test]
+ fn test_copy_from_slice() {
+ let s: &[u32] = &[1, 2, 3];
+ let r: Rc<[u32]> = Rc::from(s);
+
+ assert_eq!(&r[..], [1, 2, 3]);
+ }
+
+ #[test]
+ fn test_clone_from_slice() {
+ #[derive(Clone, Debug, Eq, PartialEq)]
+ struct X(u32);
+
+ let s: &[X] = &[X(1), X(2), X(3)];
+ let r: Rc<[X]> = Rc::from(s);
+
+ assert_eq!(&r[..], s);
+ }
+
+ #[test]
+ #[should_panic]
+ fn test_clone_from_slice_panic() {
+ use std::string::{String, ToString};
+
+ struct Fail(u32, String);
+
+ impl Clone for Fail {
+ fn clone(&self) -> Fail {
+ if self.0 == 2 {
+ panic!();
+ }
+ Fail(self.0, self.1.clone())
+ }
+ }
+
+ let s: &[Fail] = &[
+ Fail(0, "foo".to_string()),
+ Fail(1, "bar".to_string()),
+ Fail(2, "baz".to_string()),
+ ];
+
+ // Should panic, but not cause memory corruption
+ let _r: Rc<[Fail]> = Rc::from(s);
+ }
+
+ #[test]
+ fn test_from_box() {
+ let b: Box<u32> = box 123;
+ let r: Rc<u32> = Rc::from(b);
+
+ assert_eq!(*r, 123);
+ }
+
+ #[test]
+ fn test_from_box_str() {
+ use std::string::String;
+
+ let s = String::from("foo").into_boxed_str();
+ let r: Rc<str> = Rc::from(s);
+
+ assert_eq!(&r[..], "foo");
+ }
+
+ #[test]
+ fn test_from_box_slice() {
+ let s = vec![1, 2, 3].into_boxed_slice();
+ let r: Rc<[u32]> = Rc::from(s);
+
+ assert_eq!(&r[..], [1, 2, 3]);
+ }
+
+ #[test]
+ fn test_from_box_trait() {
+ use std::fmt::Display;
+ use std::string::ToString;
+
+ let b: Box<Display> = box 123;
+ let r: Rc<Display> = Rc::from(b);
+
+ assert_eq!(r.to_string(), "123");
+ }
+
+ #[test]
+ fn test_from_box_trait_zero_sized() {
+ use std::fmt::Debug;
+
+ let b: Box<Debug> = box ();
+ let r: Rc<Debug> = Rc::from(b);
+
+ assert_eq!(format!("{:?}", r), "()");
+ }
+
+ #[test]
+ fn test_from_vec() {
+ let v = vec![1, 2, 3];
+ let r: Rc<[u32]> = Rc::from(v);
+
+ assert_eq!(&r[..], [1, 2, 3]);
+ }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T> [T] {
/// Returns the number of elements in the slice.
///
- /// # Example
+ /// # Examples
///
/// ```
/// let a = [1, 2, 3];
/// Returns `true` if the slice has a length of 0.
///
- /// # Example
+ /// # Examples
///
/// ```
/// let a = [1, 2, 3];
/// Reverses the order of elements in the slice, in place.
///
- /// # Example
+ /// # Examples
///
/// ```
/// let mut v = [1, 2, 3];
///
/// Panics if `size` is 0.
///
- /// # Example
+ /// # Examples
///
/// ```
/// let slice = ['r', 'u', 's', 't'];
///
/// Panics if `size` is 0.
///
- /// # Example
+ /// # Examples
///
/// ```
/// let slice = ['l', 'o', 'r', 'e', 'm'];
/// `Err` is returned, containing the index where a matching
/// element could be inserted while maintaining sorted order.
///
- /// # Example
+ /// # Examples
///
/// Looks up a series of four elements. The first is found, with a
/// uniquely determined position; the second and third are not
/// `Err` is returned, containing the index where a matching
/// element could be inserted while maintaining sorted order.
///
- /// # Example
+ /// # Examples
///
/// Looks up a series of four elements. The first is found, with a
/// uniquely determined position; the second and third are not
///
/// This function will panic if the two slices have different lengths.
///
- /// # Example
+ /// # Examples
///
/// ```
/// let mut dst = [0, 0, 0];
///
/// This function will panic if the two slices have different lengths.
///
- /// # Example
+ /// # Examples
///
/// ```
/// let mut dst = [0, 0, 0];
core_slice::SliceExt::copy_from_slice(self, src)
}
+ /// Swaps all elements in `self` with those in `src`.
+ ///
+ /// The length of `src` must be the same as `self`.
+ ///
+ /// # Panics
+ ///
+ /// This function will panic if the two slices have different lengths.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// #![feature(swap_with_slice)]
+ ///
+ /// let mut src = [1, 2, 3];
+ /// let mut dst = [7, 8, 9];
+ ///
+ /// src.swap_with_slice(&mut dst);
+ /// assert_eq!(src, [7, 8, 9]);
+ /// assert_eq!(dst, [1, 2, 3]);
+ /// ```
+ #[unstable(feature = "swap_with_slice", issue = "44030")]
+ pub fn swap_with_slice(&mut self, src: &mut [T]) {
+ core_slice::SliceExt::swap_with_slice(self, src)
+ }
+
/// Copies `self` into a new `Vec`.
///
/// # Examples
///
/// [`Err`]: str/trait.FromStr.html#associatedtype.Err
///
- /// # Example
+ /// # Examples
///
/// Basic usage
///
///
/// # Examples
///
-/// You can create a `String` from a literal string with `String::from`:
+/// You can create a `String` from a literal string with [`String::from`]:
///
/// ```
/// let hello = String::from("Hello, world!");
/// hello.push_str("orld!");
/// ```
///
+/// [`String::from`]: #method.from
/// [`char`]: ../../std/primitive.char.html
/// [`push`]: #method.push
/// [`push_str`]: #method.push_str
#![deny(warnings)]
-#![feature(alloc)]
#![feature(attr_literals)]
#![feature(box_syntax)]
#![feature(inclusive_range_syntax)]
#![feature(splice)]
#![feature(str_escape)]
#![feature(string_retain)]
-#![feature(test)]
#![feature(unboxed_closures)]
#![feature(unicode)]
-extern crate alloc;
-extern crate test;
extern crate std_unicode;
-extern crate core;
use std::hash::{Hash, Hasher};
use std::collections::hash_map::DefaultHasher;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![crate_name = "alloc_jemalloc"]
-#![crate_type = "rlib"]
#![no_std]
#![unstable(feature = "alloc_jemalloc",
reason = "this library is unlikely to be stabilized in its current \
#![feature(libc)]
#![feature(linkage)]
#![feature(staged_api)]
-#![cfg_attr(dummy_jemalloc, allow(dead_code))]
+#![cfg_attr(dummy_jemalloc, allow(dead_code, unused_extern_crates))]
#![cfg_attr(not(dummy_jemalloc), feature(allocator_api))]
extern crate alloc;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![crate_name = "alloc_system"]
-#![crate_type = "rlib"]
#![no_std]
#![deny(warnings)]
#![unstable(feature = "alloc_system",
//! This crate implements `TypedArena`, a simple arena that can only hold
//! objects of a single type.
-#![crate_name = "arena"]
-#![crate_type = "rlib"]
-#![crate_type = "dylib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
html_root_url = "https://doc.rust-lang.org/nightly/",
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![crate_name = "collections"]
-#![crate_type = "rlib"]
#![allow(unused_attributes)]
#![unstable(feature = "collections",
reason = "this library is unlikely to be stabilized in its current \
/// A method would interfere with methods of the same name on the contents
/// of a `RefCell` used through `Deref`.
///
- /// # Example
+ /// # Examples
///
/// ```
/// use std::cell::{RefCell, Ref};
/// `RefMut::map(...)`. A method would interfere with methods of the same
/// name on the contents of a `RefCell` used through `Deref`.
///
- /// # Example
+ /// # Examples
///
/// ```
/// use std::cell::{RefCell, RefMut};
/// [`Formatter::debug_struct`](struct.Formatter.html#method.debug_struct)
/// method.
///
-/// # Example
+/// # Examples
///
/// ```
/// use std::fmt;
/// [`Formatter::debug_tuple`](struct.Formatter.html#method.debug_tuple)
/// method.
///
-/// # Example
+/// # Examples
///
/// ```
/// use std::fmt;
/// [`Formatter::debug_set`](struct.Formatter.html#method.debug_set)
/// method.
///
-/// # Example
+/// # Examples
///
/// ```
/// use std::fmt;
/// [`Formatter::debug_list`](struct.Formatter.html#method.debug_list)
/// method.
///
-/// # Example
+/// # Examples
///
/// ```
/// use std::fmt;
/// [`Formatter::debug_map`](struct.Formatter.html#method.debug_map)
/// method.
///
-/// # Example
+/// # Examples
///
/// ```
/// use std::fmt;
// Since libcore defines many fundamental lang items, all tests live in a
// separate crate, libcoretest, to avoid bizarre issues.
-#![crate_name = "core"]
#![stable(feature = "core", since = "1.6.0")]
-#![crate_type = "rlib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
html_root_url = "https://doc.rust-lang.org/nightly/",
/// Manually drops the contained value.
///
- /// # Unsafety
+ /// # Safety
///
/// This function runs the destructor of the contained value and thus the wrapped value
/// now represents uninitialized data. It is up to the user of this method to ensure the
#[stable(feature = "copy_from_slice", since = "1.9.0")]
fn copy_from_slice(&mut self, src: &[Self::Item]) where Self::Item: Copy;
+ #[unstable(feature = "swap_with_slice", issue = "44030")]
+ fn swap_with_slice(&mut self, src: &mut [Self::Item]);
+
#[stable(feature = "sort_unstable", since = "1.20.0")]
fn sort_unstable(&mut self)
where Self::Item: Ord;
}
}
+ #[inline]
+ fn swap_with_slice(&mut self, src: &mut [T]) {
+ assert!(self.len() == src.len(),
+ "destination and source slices have different lengths");
+ unsafe {
+ ptr::swap_nonoverlapping(
+ self.as_mut_ptr(), src.as_mut_ptr(), self.len());
+ }
+ }
+
#[inline]
fn binary_search_by_key<'a, B, F, Q: ?Sized>(&'a self, b: &Q, mut f: F) -> Result<usize, usize>
where F: FnMut(&'a Self::Item) -> B,
#![feature(inclusive_range)]
#![feature(inclusive_range_syntax)]
#![feature(iter_rfind)]
-#![feature(libc)]
#![feature(nonzero)]
#![feature(ord_max_min)]
#![feature(rand)]
#![feature(test)]
#![feature(trusted_len)]
#![feature(try_from)]
-#![feature(unicode)]
#![feature(unique)]
extern crate core;
extern crate test;
-extern crate libc;
-extern crate std_unicode;
extern crate rand;
mod any;
//! Parsing does not happen at runtime: structures of `std::fmt::rt` are
//! generated instead.
-#![crate_name = "fmt_macros"]
-#![crate_type = "rlib"]
-#![crate_type = "dylib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
html_root_url = "https://doc.rust-lang.org/nightly/",
//! }
//! ```
-#![crate_name = "getopts"]
-#![crate_type = "rlib"]
-#![crate_type = "dylib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
html_root_url = "https://doc.rust-lang.org/nightly/",
//!
//! * [DOT language](http://www.graphviz.org/doc/info/lang.html)
-#![crate_name = "graphviz"]
-#![crate_type = "rlib"]
-#![crate_type = "dylib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
html_root_url = "https://doc.rust-lang.org/nightly/",
//! simpler! That being said, it's not quite as versatile, but here goes!
#![no_std]
-#![crate_name = "panic_abort"]
-#![crate_type = "rlib"]
#![unstable(feature = "panic_abort", issue = "32837")]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
//! module.
#![no_std]
-#![crate_name = "panic_unwind"]
-#![crate_type = "rlib"]
#![unstable(feature = "panic_unwind", issue = "32837")]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
#![feature(core_intrinsics)]
#![feature(lang_items)]
#![feature(libc)]
-#![feature(panic_unwind)]
+#![cfg_attr(not(any(target_env = "msvc",
+ all(windows, target_arch = "x86_64", target_env = "gnu"))),
+ feature(panic_unwind))]
#![feature(raw)]
#![feature(staged_api)]
#![feature(unwind_attributes)]
extern crate alloc;
extern crate libc;
+#[cfg(not(any(target_env = "msvc", all(windows, target_arch = "x86_64", target_env = "gnu"))))]
extern crate unwind;
use core::intrinsics;
//!
//! See [the book](../book/first-edition/procedural-macros.html) for more.
-#![crate_name = "proc_macro"]
#![stable(feature = "proc_macro_lib", since = "1.15.0")]
-#![crate_type = "rlib"]
-#![crate_type = "dylib"]
#![deny(warnings)]
#![deny(missing_docs)]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
pub enum Delimiter {
/// `( ... )`
Parenthesis,
- /// `[ ... ]`
- Brace,
/// `{ ... }`
+ Brace,
+ /// `[ ... ]`
Bracket,
/// An implicit delimiter, e.g. `$var`, where $var is `...`.
None,
#![unstable(feature = "profiler_runtime_lib",
reason = "internal implementation detail of rustc right now",
issue = "0")]
-#![crate_name = "profiler_builtins"]
-#![crate_type = "rlib"]
#![allow(unused_features)]
#![feature(staged_api)]
//! is not recommended to use this library directly, but rather the official
//! interface through `std::rand`.
-#![crate_name = "rand"]
-#![crate_type = "rlib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk.png",
html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
html_root_url = "https://doc.rust-lang.org/nightly/",
[] DylibDepFormats(DefId),
[] IsAllocator(DefId),
[] IsPanicRuntime(DefId),
+ [] IsCompilerBuiltins(DefId),
+ [] HasGlobalAllocator(DefId),
[] ExternCrate(DefId),
[] LintLevels,
);
self.edges.insert((source, target));
}
- pub fn add_node(&mut self, node: DepNode) {
- self.get_or_create_node(node);
+ pub fn add_node(&mut self, node: DepNode) -> DepNodeIndex {
+ self.get_or_create_node(node)
}
#[inline]
use session::config::OutputType;
use std::cell::{Ref, RefCell};
use std::rc::Rc;
+use util::common::{ProfileQueriesMsg, profq_msg};
use super::dep_node::{DepNode, DepKind, WorkProductId};
use super::query::DepGraphQuery;
{
if let Some(ref data) = self.data {
data.edges.borrow_mut().push_task(key);
+ if cfg!(debug_assertions) {
+ profq_msg(ProfileQueriesMsg::TaskBegin(key.clone()))
+ };
let result = task(cx, arg);
+ if cfg!(debug_assertions) {
+ profq_msg(ProfileQueriesMsg::TaskEnd)
+ };
let dep_node_index = data.edges.borrow_mut().pop_task(key);
(result, dep_node_index)
} else {
self.data.as_ref().unwrap().edges.borrow_mut().add_node(node);
}
+ pub fn alloc_input_node(&self, node: DepNode) -> DepNodeIndex {
+ if let Some(ref data) = self.data {
+ data.edges.borrow_mut().add_node(node)
+ } else {
+ DepNodeIndex::INVALID
+ }
+ }
+
/// Indicates that a previous work product exists for `v`. This is
/// invoked during initial start-up based on what nodes are clean
/// (and what files exist in the incr. directory).
See also https://doc.rust-lang.org/book/first-edition/no-stdlib.html
"##,
+E0214: r##"
+A generic type was described using parentheses rather than angle brackets. For
+example:
+
+```compile_fail,E0214
+fn main() {
+ let v: Vec(&str) = vec!["foo"];
+}
+```
+
+This is not currently supported: `v` should be defined as `Vec<&str>`.
+Parentheses are currently only used with generic types when defining parameters
+for `Fn`-family traits.
+"##,
+
E0261: r##"
When using a lifetime like `'a` in a type, it must be declared before being
used.
pub fn walk_path_parameters<'v, V: Visitor<'v>>(visitor: &mut V,
_path_span: Span,
path_parameters: &'v PathParameters) {
- match *path_parameters {
- AngleBracketedParameters(ref data) => {
- walk_list!(visitor, visit_ty, &data.types);
- walk_list!(visitor, visit_lifetime, &data.lifetimes);
- walk_list!(visitor, visit_assoc_type_binding, &data.bindings);
- }
- ParenthesizedParameters(ref data) => {
- walk_list!(visitor, visit_ty, &data.inputs);
- walk_list!(visitor, visit_ty, &data.output);
- }
- }
+ walk_list!(visitor, visit_lifetime, &path_parameters.lifetimes);
+ walk_list!(visitor, visit_ty, &path_parameters.types);
+ walk_list!(visitor, visit_assoc_type_binding, &path_parameters.bindings);
}
pub fn walk_assoc_type_binding<'v, V: Visitor<'v>>(visitor: &mut V,
pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplItem) {
// NB: Deliberately force a compilation error if/when new fields are added.
- let ImplItem { id: _, name, ref vis, ref defaultness, ref attrs, ref node, span } = *impl_item;
+ let ImplItem {
+ id: _,
+ hir_id: _,
+ name,
+ ref vis,
+ ref defaultness,
+ ref attrs,
+ ref node,
+ span
+ } = *impl_item;
visitor.visit_name(span, name);
visitor.visit_vis(vis);
use hir::map::definitions::DefPathData;
use hir::def_id::{DefIndex, DefId, CRATE_DEF_INDEX};
use hir::def::{Def, PathResolution};
+use lint::builtin::PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES;
use rustc_data_structures::indexed_vec::IndexVec;
use session::Session;
+use util::common::FN_OUTPUT_NAME;
use util::nodemap::{DefIdMap, FxHashMap, NodeMap};
use std::collections::BTreeMap;
use std::fmt::Debug;
use std::iter;
use std::mem;
-
use syntax::attr;
use syntax::ast::*;
use syntax::errors;
hir_id: hir::HirId,
}
+enum ParenthesizedGenericArgs {
+ Ok,
+ Warn,
+ Err,
+}
+
impl<'a> LoweringContext<'a> {
fn lower_crate(mut self, c: &Crate) -> hir::Crate {
/// Full-crate AST visitor that inserts into a fresh
Def::Trait(def_id) if i + 1 == proj_start => Some(def_id),
_ => None
};
+ let parenthesized_generic_args = match resolution.base_def() {
+ // `a::b::Trait(Args)`
+ Def::Trait(..) if i + 1 == proj_start => ParenthesizedGenericArgs::Ok,
+ // `a::b::Trait(Args)::TraitItem`
+ Def::Method(..) |
+ Def::AssociatedConst(..) |
+ Def::AssociatedTy(..) if i + 2 == proj_start => ParenthesizedGenericArgs::Ok,
+ // Avoid duplicated errors
+ Def::Err => ParenthesizedGenericArgs::Ok,
+ // An error
+ Def::Struct(..) | Def::Enum(..) | Def::Union(..) | Def::TyAlias(..) |
+ Def::Variant(..) if i + 1 == proj_start => ParenthesizedGenericArgs::Err,
+ // A warning for now, for compatibility reasons
+ _ => ParenthesizedGenericArgs::Warn,
+ };
let num_lifetimes = type_def_id.map_or(0, |def_id| {
if let Some(&n) = self.type_def_lifetime_params.get(&def_id) {
self.type_def_lifetime_params.insert(def_id, n);
n
});
- self.lower_path_segment(p.span, segment, param_mode, num_lifetimes)
+ self.lower_path_segment(p.span, segment, param_mode, num_lifetimes,
+ parenthesized_generic_args)
}).collect(),
span: p.span,
});
// 3. `<<std::vec::Vec<T>>::IntoIter>::Item`
// * final path is `<<<std::vec::Vec<T>>::IntoIter>::Item>::clone`
for (i, segment) in p.segments.iter().enumerate().skip(proj_start) {
- let segment = P(self.lower_path_segment(p.span, segment, param_mode, 0));
+ let segment = P(self.lower_path_segment(p.span, segment, param_mode, 0,
+ ParenthesizedGenericArgs::Warn));
let qpath = hir::QPath::TypeRelative(ty, segment);
// It's finished, return the extension of the right node type.
hir::Path {
def: self.expect_full_def(id),
segments: segments.map(|segment| {
- self.lower_path_segment(p.span, segment, param_mode, 0)
+ self.lower_path_segment(p.span, segment, param_mode, 0,
+ ParenthesizedGenericArgs::Err)
}).chain(name.map(|name| {
hir::PathSegment {
name,
path_span: Span,
segment: &PathSegment,
param_mode: ParamMode,
- expected_lifetimes: usize)
+ expected_lifetimes: usize,
+ parenthesized_generic_args: ParenthesizedGenericArgs)
-> hir::PathSegment {
let mut parameters = if let Some(ref parameters) = segment.parameters {
+ let msg = "parenthesized parameters may only be used with a trait";
match **parameters {
PathParameters::AngleBracketed(ref data) => {
- let data = self.lower_angle_bracketed_parameter_data(data, param_mode);
- hir::AngleBracketedParameters(data)
+ self.lower_angle_bracketed_parameter_data(data, param_mode)
}
- PathParameters::Parenthesized(ref data) => {
- hir::ParenthesizedParameters(self.lower_parenthesized_parameter_data(data))
+ PathParameters::Parenthesized(ref data) => match parenthesized_generic_args {
+ ParenthesizedGenericArgs::Ok => self.lower_parenthesized_parameter_data(data),
+ ParenthesizedGenericArgs::Warn => {
+ self.sess.buffer_lint(PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES,
+ CRATE_NODE_ID, data.span, msg.into());
+ hir::PathParameters::none()
+ }
+ ParenthesizedGenericArgs::Err => {
+ struct_span_err!(self.sess, data.span, E0214, "{}", msg)
+ .span_label(data.span, "only traits may use parentheses").emit();
+ hir::PathParameters::none()
+ }
}
}
} else {
- let data = self.lower_angle_bracketed_parameter_data(&Default::default(), param_mode);
- hir::AngleBracketedParameters(data)
+ self.lower_angle_bracketed_parameter_data(&Default::default(), param_mode)
};
- if let hir::AngleBracketedParameters(ref mut data) = parameters {
- if data.lifetimes.is_empty() {
- data.lifetimes = (0..expected_lifetimes).map(|_| {
- self.elided_lifetime(path_span)
- }).collect();
- }
+ if !parameters.parenthesized && parameters.lifetimes.is_empty() {
+ parameters.lifetimes = (0..expected_lifetimes).map(|_| {
+ self.elided_lifetime(path_span)
+ }).collect();
}
hir::PathSegment {
fn lower_angle_bracketed_parameter_data(&mut self,
data: &AngleBracketedParameterData,
param_mode: ParamMode)
- -> hir::AngleBracketedParameterData {
+ -> hir::PathParameters {
let &AngleBracketedParameterData { ref lifetimes, ref types, ref bindings, .. } = data;
- hir::AngleBracketedParameterData {
+ hir::PathParameters {
lifetimes: self.lower_lifetimes(lifetimes),
types: types.iter().map(|ty| self.lower_ty(ty)).collect(),
infer_types: types.is_empty() && param_mode == ParamMode::Optional,
bindings: bindings.iter().map(|b| self.lower_ty_binding(b)).collect(),
+ parenthesized: false,
}
}
fn lower_parenthesized_parameter_data(&mut self,
data: &ParenthesizedParameterData)
- -> hir::ParenthesizedParameterData {
+ -> hir::PathParameters {
let &ParenthesizedParameterData { ref inputs, ref output, span } = data;
- hir::ParenthesizedParameterData {
- inputs: inputs.iter().map(|ty| self.lower_ty(ty)).collect(),
- output: output.as_ref().map(|ty| self.lower_ty(ty)),
- span,
+ let inputs = inputs.iter().map(|ty| self.lower_ty(ty)).collect();
+ let mk_tup = |this: &mut Self, tys, span| {
+ P(hir::Ty { node: hir::TyTup(tys), id: this.next_id().node_id, span })
+ };
+
+ hir::PathParameters {
+ lifetimes: hir::HirVec::new(),
+ types: hir_vec![mk_tup(self, inputs, span)],
+ infer_types: false,
+ bindings: hir_vec![hir::TypeBinding {
+ id: self.next_id().node_id,
+ name: Symbol::intern(FN_OUTPUT_NAME),
+ ty: output.as_ref().map(|ty| self.lower_ty(&ty))
+ .unwrap_or_else(|| mk_tup(self, hir::HirVec::new(), span)),
+ span: output.as_ref().map_or(span, |ty| ty.span),
+ }],
+ parenthesized: true,
}
}
path.span = span;
self.allocate_hir_id_counter(import.id, import);
- self.with_hir_id_owner(import.id, |this| {
+ let LoweredNodeId {
+ node_id: import_node_id,
+ hir_id: import_hir_id,
+ } = self.lower_node_id(import.id);
+
+ self.with_hir_id_owner(import_node_id, |this| {
let vis = match *vis {
hir::Visibility::Public => hir::Visibility::Public,
hir::Visibility::Crate => hir::Visibility::Crate,
}
};
- this.items.insert(import.id, hir::Item {
- id: import.id,
+ this.items.insert(import_node_id, hir::Item {
+ id: import_node_id,
+ hir_id: import_hir_id,
name: import.rename.unwrap_or(ident).name,
attrs: attrs.clone(),
node: hir::ItemUse(P(path), hir::UseKind::Single),
fn lower_trait_item(&mut self, i: &TraitItem) -> hir::TraitItem {
self.with_parent_def(i.id, |this| {
+ let LoweredNodeId { node_id, hir_id } = this.lower_node_id(i.id);
+
hir::TraitItem {
- id: this.lower_node_id(i.id).node_id,
+ id: node_id,
+ hir_id,
name: this.lower_ident(i.ident),
attrs: this.lower_attrs(&i.attrs),
node: match i.node {
fn lower_impl_item(&mut self, i: &ImplItem) -> hir::ImplItem {
self.with_parent_def(i.id, |this| {
+ let LoweredNodeId { node_id, hir_id } = this.lower_node_id(i.id);
+
hir::ImplItem {
- id: this.lower_node_id(i.id).node_id,
+ id: node_id,
+ hir_id,
name: this.lower_ident(i.ident),
attrs: this.lower_attrs(&i.attrs),
vis: this.lower_visibility(&i.vis, None),
this.lower_item_kind(i.id, &mut name, &attrs, &mut vis, &i.node)
});
+ let LoweredNodeId { node_id, hir_id } = self.lower_node_id(i.id);
+
Some(hir::Item {
- id: self.lower_node_id(i.id).node_id,
+ id: node_id,
+ hir_id,
name,
attrs,
node,
hir::ExprCall(f, args.iter().map(|x| self.lower_expr(x)).collect())
}
ExprKind::MethodCall(ref seg, ref args) => {
- let hir_seg = self.lower_path_segment(e.span, seg, ParamMode::Optional, 0);
+ let hir_seg = self.lower_path_segment(e.span, seg, ParamMode::Optional, 0,
+ ParenthesizedGenericArgs::Err);
let args = args.iter().map(|x| self.lower_expr(x)).collect();
hir::ExprMethodCall(hir_seg, seg.span, args)
}
use super::*;
+use dep_graph::{DepGraph, DepKind, DepNodeIndex};
use hir::intravisit::{Visitor, NestedVisitorMap};
use std::iter::repeat;
use syntax::ast::{NodeId, CRATE_NODE_ID};
use syntax_pos::Span;
/// A Visitor that walks over the HIR and collects Nodes into a HIR map
-pub struct NodeCollector<'hir> {
+pub(super) struct NodeCollector<'a, 'hir> {
/// The crate
- pub krate: &'hir Crate,
+ krate: &'hir Crate,
/// The node map
- pub(super) map: Vec<MapEntry<'hir>>,
+ map: Vec<MapEntry<'hir>>,
/// The parent of this node
- pub parent_node: NodeId,
+ parent_node: NodeId,
+
+ current_dep_node_owner: DefIndex,
+ current_dep_node_index: DepNodeIndex,
+
+ dep_graph: &'a DepGraph,
+ definitions: &'a definitions::Definitions,
}
-impl<'hir> NodeCollector<'hir> {
- pub fn root(krate: &'hir Crate) -> NodeCollector<'hir> {
+impl<'a, 'hir> NodeCollector<'a, 'hir> {
+ pub(super) fn root(krate: &'hir Crate,
+ dep_graph: &'a DepGraph,
+ definitions: &'a definitions::Definitions)
+ -> NodeCollector<'a, 'hir> {
+ let root_mod_def_path_hash = definitions.def_path_hash(CRATE_DEF_INDEX);
+ let root_mod_dep_node = root_mod_def_path_hash.to_dep_node(DepKind::Hir);
+ let root_mod_dep_node_index = dep_graph.alloc_input_node(root_mod_dep_node);
+
let mut collector = NodeCollector {
krate,
map: vec![],
parent_node: CRATE_NODE_ID,
+ current_dep_node_index: root_mod_dep_node_index,
+ current_dep_node_owner: CRATE_DEF_INDEX,
+ dep_graph,
+ definitions,
};
- collector.insert_entry(CRATE_NODE_ID, RootCrate);
+ collector.insert_entry(CRATE_NODE_ID, RootCrate(root_mod_dep_node_index));
collector
}
+ pub(super) fn into_map(self) -> Vec<MapEntry<'hir>> {
+ self.map
+ }
+
fn insert_entry(&mut self, id: NodeId, entry: MapEntry<'hir>) {
debug!("hir_map: {:?} => {:?}", id, entry);
let len = self.map.len();
}
fn insert(&mut self, id: NodeId, node: Node<'hir>) {
- let entry = MapEntry::from_node(self.parent_node, node);
+ let parent = self.parent_node;
+ let dep_node_index = self.current_dep_node_index;
+
+ let entry = match node {
+ NodeItem(n) => EntryItem(parent, dep_node_index, n),
+ NodeForeignItem(n) => EntryForeignItem(parent, dep_node_index, n),
+ NodeTraitItem(n) => EntryTraitItem(parent, dep_node_index, n),
+ NodeImplItem(n) => EntryImplItem(parent, dep_node_index, n),
+ NodeVariant(n) => EntryVariant(parent, dep_node_index, n),
+ NodeField(n) => EntryField(parent, dep_node_index, n),
+ NodeExpr(n) => EntryExpr(parent, dep_node_index, n),
+ NodeStmt(n) => EntryStmt(parent, dep_node_index, n),
+ NodeTy(n) => EntryTy(parent, dep_node_index, n),
+ NodeTraitRef(n) => EntryTraitRef(parent, dep_node_index, n),
+ NodeBinding(n) => EntryBinding(parent, dep_node_index, n),
+ NodePat(n) => EntryPat(parent, dep_node_index, n),
+ NodeBlock(n) => EntryBlock(parent, dep_node_index, n),
+ NodeStructCtor(n) => EntryStructCtor(parent, dep_node_index, n),
+ NodeLifetime(n) => EntryLifetime(parent, dep_node_index, n),
+ NodeTyParam(n) => EntryTyParam(parent, dep_node_index, n),
+ NodeVisibility(n) => EntryVisibility(parent, dep_node_index, n),
+ NodeLocal(n) => EntryLocal(parent, dep_node_index, n),
+ };
+
+ // Make sure that the DepNode of some node coincides with the HirId
+ // owner of that node.
+ if cfg!(debug_assertions) {
+ let hir_id_owner = self.definitions.node_to_hir_id(id).owner;
+
+ if hir_id_owner != self.current_dep_node_owner {
+ let node_str = match self.definitions.opt_def_index(id) {
+ Some(def_index) => {
+ self.definitions.def_path(def_index).to_string_no_crate()
+ }
+ None => format!("{:?}", node)
+ };
+
+ bug!("inconsistent DepNode for `{}`: \
+ current_dep_node_owner={}, hir_id.owner={}",
+ node_str,
+ self.definitions
+ .def_path(self.current_dep_node_owner)
+ .to_string_no_crate(),
+ self.definitions.def_path(hir_id_owner).to_string_no_crate())
+ }
+ }
+
self.insert_entry(id, entry);
+
}
fn with_parent<F: FnOnce(&mut Self)>(&mut self, parent_id: NodeId, f: F) {
f(self);
self.parent_node = parent_node;
}
+
+ fn with_dep_node_owner<F: FnOnce(&mut Self)>(&mut self,
+ dep_node_owner: DefIndex,
+ f: F) {
+ let prev_owner = self.current_dep_node_owner;
+ let prev_index = self.current_dep_node_index;
+
+ // When we enter a new owner (item, impl item, or trait item), we always
+ // start out again with DepKind::Hir.
+ let new_dep_node = self.definitions
+ .def_path_hash(dep_node_owner)
+ .to_dep_node(DepKind::Hir);
+ self.current_dep_node_index = self.dep_graph.alloc_input_node(new_dep_node);
+ self.current_dep_node_owner = dep_node_owner;
+ f(self);
+ self.current_dep_node_index = prev_index;
+ self.current_dep_node_owner = prev_owner;
+ }
}
-impl<'hir> Visitor<'hir> for NodeCollector<'hir> {
+impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
/// Because we want to track parent items and so forth, enable
/// deep walking so that we walk nested items in the context of
/// their outer items.
}
fn visit_nested_body(&mut self, id: BodyId) {
+ // When we enter a body, we switch to DepKind::HirBody.
+ // Note that current_dep_node_index might already be DepKind::HirBody,
+ // e.g. when entering the body of a closure that is already part of a
+ // surrounding body. That's expected and not a problem.
+ let prev_index = self.current_dep_node_index;
+ let new_dep_node = self.definitions
+ .def_path_hash(self.current_dep_node_owner)
+ .to_dep_node(DepKind::HirBody);
+ self.current_dep_node_index = self.dep_graph.alloc_input_node(new_dep_node);
self.visit_body(self.krate.body(id));
+ self.current_dep_node_index = prev_index;
}
fn visit_item(&mut self, i: &'hir Item) {
debug!("visit_item: {:?}", i);
-
- self.insert(i.id, NodeItem(i));
-
- self.with_parent(i.id, |this| {
- match i.node {
- ItemStruct(ref struct_def, _) => {
- // If this is a tuple-like struct, register the constructor.
- if !struct_def.is_struct() {
- this.insert(struct_def.id(), NodeStructCtor(struct_def));
+ debug_assert_eq!(i.hir_id.owner,
+ self.definitions.opt_def_index(i.id).unwrap());
+ self.with_dep_node_owner(i.hir_id.owner, |this| {
+ this.insert(i.id, NodeItem(i));
+ this.with_parent(i.id, |this| {
+ match i.node {
+ ItemStruct(ref struct_def, _) => {
+ // If this is a tuple-like struct, register the constructor.
+ if !struct_def.is_struct() {
+ this.insert(struct_def.id(), NodeStructCtor(struct_def));
+ }
}
+ _ => {}
}
- _ => {}
- }
- intravisit::walk_item(this, i);
+ intravisit::walk_item(this, i);
+ });
});
}
}
fn visit_trait_item(&mut self, ti: &'hir TraitItem) {
- self.insert(ti.id, NodeTraitItem(ti));
-
- self.with_parent(ti.id, |this| {
- intravisit::walk_trait_item(this, ti);
+ debug_assert_eq!(ti.hir_id.owner,
+ self.definitions.opt_def_index(ti.id).unwrap());
+ self.with_dep_node_owner(ti.hir_id.owner, |this| {
+ this.insert(ti.id, NodeTraitItem(ti));
+
+ this.with_parent(ti.id, |this| {
+ intravisit::walk_trait_item(this, ti);
+ });
});
}
fn visit_impl_item(&mut self, ii: &'hir ImplItem) {
- self.insert(ii.id, NodeImplItem(ii));
-
- self.with_parent(ii.id, |this| {
- intravisit::walk_impl_item(this, ii);
+ debug_assert_eq!(ii.hir_id.owner,
+ self.definitions.opt_def_index(ii.id).unwrap());
+ self.with_dep_node_owner(ii.hir_id.owner, |this| {
+ this.insert(ii.id, NodeImplItem(ii));
+
+ this.with_parent(ii.id, |this| {
+ intravisit::walk_impl_item(this, ii);
+ });
});
}
intravisit::walk_struct_field(this, field);
});
}
+
+ fn visit_trait_item_ref(&mut self, ii: &'hir TraitItemRef) {
+ // Do not visit the duplicate information in TraitItemRef. We want to
+ // map the actual nodes, not the duplicate ones in the *Ref.
+ let TraitItemRef {
+ id,
+ name: _,
+ kind: _,
+ span: _,
+ defaultness: _,
+ } = *ii;
+
+ self.visit_nested_trait_item(id);
+ }
+
+ fn visit_impl_item_ref(&mut self, ii: &'hir ImplItemRef) {
+ // Do not visit the duplicate information in ImplItemRef. We want to
+ // map the actual nodes, not the duplicate ones in the *Ref.
+ let ImplItemRef {
+ id,
+ name: _,
+ kind: _,
+ span: _,
+ vis: _,
+ defaultness: _,
+ } = *ii;
+
+ self.visit_nested_impl_item(id);
+ }
}
pub use self::definitions::{Definitions, DefKey, DefPath, DefPathData,
DisambiguatedDefPathData, DefPathHash};
-use dep_graph::{DepGraph, DepNode, DepKind};
+use dep_graph::{DepGraph, DepNode, DepKind, DepNodeIndex};
use hir::def_id::{CRATE_DEF_INDEX, DefId, DefIndexAddressSpace};
NotPresent,
/// All the node types, with a parent ID.
- EntryItem(NodeId, &'hir Item),
- EntryForeignItem(NodeId, &'hir ForeignItem),
- EntryTraitItem(NodeId, &'hir TraitItem),
- EntryImplItem(NodeId, &'hir ImplItem),
- EntryVariant(NodeId, &'hir Variant),
- EntryField(NodeId, &'hir StructField),
- EntryExpr(NodeId, &'hir Expr),
- EntryStmt(NodeId, &'hir Stmt),
- EntryTy(NodeId, &'hir Ty),
- EntryTraitRef(NodeId, &'hir TraitRef),
- EntryBinding(NodeId, &'hir Pat),
- EntryPat(NodeId, &'hir Pat),
- EntryBlock(NodeId, &'hir Block),
- EntryStructCtor(NodeId, &'hir VariantData),
- EntryLifetime(NodeId, &'hir Lifetime),
- EntryTyParam(NodeId, &'hir TyParam),
- EntryVisibility(NodeId, &'hir Visibility),
- EntryLocal(NodeId, &'hir Local),
-
- /// Roots for node trees.
- RootCrate,
+ EntryItem(NodeId, DepNodeIndex, &'hir Item),
+ EntryForeignItem(NodeId, DepNodeIndex, &'hir ForeignItem),
+ EntryTraitItem(NodeId, DepNodeIndex, &'hir TraitItem),
+ EntryImplItem(NodeId, DepNodeIndex, &'hir ImplItem),
+ EntryVariant(NodeId, DepNodeIndex, &'hir Variant),
+ EntryField(NodeId, DepNodeIndex, &'hir StructField),
+ EntryExpr(NodeId, DepNodeIndex, &'hir Expr),
+ EntryStmt(NodeId, DepNodeIndex, &'hir Stmt),
+ EntryTy(NodeId, DepNodeIndex, &'hir Ty),
+ EntryTraitRef(NodeId, DepNodeIndex, &'hir TraitRef),
+ EntryBinding(NodeId, DepNodeIndex, &'hir Pat),
+ EntryPat(NodeId, DepNodeIndex, &'hir Pat),
+ EntryBlock(NodeId, DepNodeIndex, &'hir Block),
+ EntryStructCtor(NodeId, DepNodeIndex, &'hir VariantData),
+ EntryLifetime(NodeId, DepNodeIndex, &'hir Lifetime),
+ EntryTyParam(NodeId, DepNodeIndex, &'hir TyParam),
+ EntryVisibility(NodeId, DepNodeIndex, &'hir Visibility),
+ EntryLocal(NodeId, DepNodeIndex, &'hir Local),
+
+ /// Roots for node trees. The DepNodeIndex is the dependency node of the
+ /// crate's root module.
+ RootCrate(DepNodeIndex),
}
impl<'hir> Clone for MapEntry<'hir> {
}
impl<'hir> MapEntry<'hir> {
- fn from_node(p: NodeId, node: Node<'hir>) -> MapEntry<'hir> {
- match node {
- NodeItem(n) => EntryItem(p, n),
- NodeForeignItem(n) => EntryForeignItem(p, n),
- NodeTraitItem(n) => EntryTraitItem(p, n),
- NodeImplItem(n) => EntryImplItem(p, n),
- NodeVariant(n) => EntryVariant(p, n),
- NodeField(n) => EntryField(p, n),
- NodeExpr(n) => EntryExpr(p, n),
- NodeStmt(n) => EntryStmt(p, n),
- NodeTy(n) => EntryTy(p, n),
- NodeTraitRef(n) => EntryTraitRef(p, n),
- NodeBinding(n) => EntryBinding(p, n),
- NodePat(n) => EntryPat(p, n),
- NodeBlock(n) => EntryBlock(p, n),
- NodeStructCtor(n) => EntryStructCtor(p, n),
- NodeLifetime(n) => EntryLifetime(p, n),
- NodeTyParam(n) => EntryTyParam(p, n),
- NodeVisibility(n) => EntryVisibility(p, n),
- NodeLocal(n) => EntryLocal(p, n),
- }
- }
-
fn parent_node(self) -> Option<NodeId> {
Some(match self {
- EntryItem(id, _) => id,
- EntryForeignItem(id, _) => id,
- EntryTraitItem(id, _) => id,
- EntryImplItem(id, _) => id,
- EntryVariant(id, _) => id,
- EntryField(id, _) => id,
- EntryExpr(id, _) => id,
- EntryStmt(id, _) => id,
- EntryTy(id, _) => id,
- EntryTraitRef(id, _) => id,
- EntryBinding(id, _) => id,
- EntryPat(id, _) => id,
- EntryBlock(id, _) => id,
- EntryStructCtor(id, _) => id,
- EntryLifetime(id, _) => id,
- EntryTyParam(id, _) => id,
- EntryVisibility(id, _) => id,
- EntryLocal(id, _) => id,
+ EntryItem(id, _, _) => id,
+ EntryForeignItem(id, _, _) => id,
+ EntryTraitItem(id, _, _) => id,
+ EntryImplItem(id, _, _) => id,
+ EntryVariant(id, _, _) => id,
+ EntryField(id, _, _) => id,
+ EntryExpr(id, _, _) => id,
+ EntryStmt(id, _, _) => id,
+ EntryTy(id, _, _) => id,
+ EntryTraitRef(id, _, _) => id,
+ EntryBinding(id, _, _) => id,
+ EntryPat(id, _, _) => id,
+ EntryBlock(id, _, _) => id,
+ EntryStructCtor(id, _, _) => id,
+ EntryLifetime(id, _, _) => id,
+ EntryTyParam(id, _, _) => id,
+ EntryVisibility(id, _, _) => id,
+ EntryLocal(id, _, _) => id,
NotPresent |
- RootCrate => return None,
+ RootCrate(_) => return None,
})
}
fn to_node(self) -> Option<Node<'hir>> {
Some(match self {
- EntryItem(_, n) => NodeItem(n),
- EntryForeignItem(_, n) => NodeForeignItem(n),
- EntryTraitItem(_, n) => NodeTraitItem(n),
- EntryImplItem(_, n) => NodeImplItem(n),
- EntryVariant(_, n) => NodeVariant(n),
- EntryField(_, n) => NodeField(n),
- EntryExpr(_, n) => NodeExpr(n),
- EntryStmt(_, n) => NodeStmt(n),
- EntryTy(_, n) => NodeTy(n),
- EntryTraitRef(_, n) => NodeTraitRef(n),
- EntryBinding(_, n) => NodeBinding(n),
- EntryPat(_, n) => NodePat(n),
- EntryBlock(_, n) => NodeBlock(n),
- EntryStructCtor(_, n) => NodeStructCtor(n),
- EntryLifetime(_, n) => NodeLifetime(n),
- EntryTyParam(_, n) => NodeTyParam(n),
- EntryVisibility(_, n) => NodeVisibility(n),
- EntryLocal(_, n) => NodeLocal(n),
+ EntryItem(_, _, n) => NodeItem(n),
+ EntryForeignItem(_, _, n) => NodeForeignItem(n),
+ EntryTraitItem(_, _, n) => NodeTraitItem(n),
+ EntryImplItem(_, _, n) => NodeImplItem(n),
+ EntryVariant(_, _, n) => NodeVariant(n),
+ EntryField(_, _, n) => NodeField(n),
+ EntryExpr(_, _, n) => NodeExpr(n),
+ EntryStmt(_, _, n) => NodeStmt(n),
+ EntryTy(_, _, n) => NodeTy(n),
+ EntryTraitRef(_, _, n) => NodeTraitRef(n),
+ EntryBinding(_, _, n) => NodeBinding(n),
+ EntryPat(_, _, n) => NodePat(n),
+ EntryBlock(_, _, n) => NodeBlock(n),
+ EntryStructCtor(_, _, n) => NodeStructCtor(n),
+ EntryLifetime(_, _, n) => NodeLifetime(n),
+ EntryTyParam(_, _, n) => NodeTyParam(n),
+ EntryVisibility(_, _, n) => NodeVisibility(n),
+ EntryLocal(_, _, n) => NodeLocal(n),
_ => return None
})
}
fn associated_body(self) -> Option<BodyId> {
match self {
- EntryItem(_, item) => {
+ EntryItem(_, _, item) => {
match item.node {
ItemConst(_, body) |
ItemStatic(.., body) |
}
}
- EntryTraitItem(_, item) => {
+ EntryTraitItem(_, _, item) => {
match item.node {
TraitItemKind::Const(_, Some(body)) |
TraitItemKind::Method(_, TraitMethod::Provided(body)) => Some(body),
}
}
- EntryImplItem(_, item) => {
+ EntryImplItem(_, _, item) => {
match item.node {
ImplItemKind::Const(_, body) |
ImplItemKind::Method(_, body) => Some(body),
}
}
- EntryExpr(_, expr) => {
+ EntryExpr(_, _, expr) => {
match expr.node {
ExprClosure(.., body, _) => Some(body),
_ => None,
/// read recorded). If the function just returns a DefId or
/// NodeId, no actual content was returned, so no read is needed.
pub fn read(&self, id: NodeId) {
- self.dep_graph.read(self.dep_node(id));
- }
-
- fn dep_node(&self, id0: NodeId) -> DepNode {
- let mut id = id0;
- let mut last_expr = None;
- loop {
- let entry = self.map[id.as_usize()];
- match entry {
- EntryItem(..) |
- EntryTraitItem(..) |
- EntryImplItem(..) => {
- let def_index = self.definitions.opt_def_index(id).unwrap();
+ let entry = self.map[id.as_usize()];
+ match entry {
+ EntryItem(_, dep_node_index, _) |
+ EntryTraitItem(_, dep_node_index, _) |
+ EntryImplItem(_, dep_node_index, _) |
+ EntryVariant(_, dep_node_index, _) |
+ EntryForeignItem(_, dep_node_index, _) |
+ EntryField(_, dep_node_index, _) |
+ EntryStmt(_, dep_node_index, _) |
+ EntryTy(_, dep_node_index, _) |
+ EntryTraitRef(_, dep_node_index, _) |
+ EntryBinding(_, dep_node_index, _) |
+ EntryPat(_, dep_node_index, _) |
+ EntryBlock(_, dep_node_index, _) |
+ EntryStructCtor(_, dep_node_index, _) |
+ EntryLifetime(_, dep_node_index, _) |
+ EntryTyParam(_, dep_node_index, _) |
+ EntryVisibility(_, dep_node_index, _) |
+ EntryExpr(_, dep_node_index, _) |
+ EntryLocal(_, dep_node_index, _) |
+ RootCrate(dep_node_index) => {
+ self.dep_graph.read_index(dep_node_index);
+ }
+ NotPresent => {
+ // Some nodes, notably macro definitions, are not
+ // present in the map for whatever reason, but
+ // they *do* have def-ids. So if we encounter an
+ // empty hole, check for that case.
+ if let Some(def_index) = self.definitions.opt_def_index(id) {
let def_path_hash = self.definitions.def_path_hash(def_index);
-
- if let Some(last_id) = last_expr {
- // The body may have a separate dep node
- if entry.is_body_owner(last_id) {
- return def_path_hash.to_dep_node(DepKind::HirBody);
- }
- }
- return def_path_hash.to_dep_node(DepKind::Hir);
- }
-
- EntryVariant(p, v) => {
- id = p;
-
- if last_expr.is_some() {
- if v.node.disr_expr.map(|e| e.node_id) == last_expr {
- // The enum parent holds both Hir and HirBody nodes.
- let def_index = self.definitions.opt_def_index(id).unwrap();
- let def_path_hash = self.definitions.def_path_hash(def_index);
- return def_path_hash.to_dep_node(DepKind::HirBody);
- }
- }
- }
-
- EntryForeignItem(p, _) |
- EntryField(p, _) |
- EntryStmt(p, _) |
- EntryTy(p, _) |
- EntryTraitRef(p, _) |
- EntryBinding(p, _) |
- EntryPat(p, _) |
- EntryBlock(p, _) |
- EntryStructCtor(p, _) |
- EntryLifetime(p, _) |
- EntryTyParam(p, _) |
- EntryVisibility(p, _) |
- EntryLocal(p, _) =>
- id = p,
-
- EntryExpr(p, _) => {
- last_expr = Some(id);
- id = p;
- }
-
- RootCrate => {
- let def_path_hash = self.definitions.def_path_hash(CRATE_DEF_INDEX);
- return def_path_hash.to_dep_node(DepKind::Hir);
+ self.dep_graph.read(def_path_hash.to_dep_node(DepKind::Hir));
+ } else {
+ bug!("called HirMap::read() with invalid NodeId")
}
-
- NotPresent =>
- // Some nodes, notably macro definitions, are not
- // present in the map for whatever reason, but
- // they *do* have def-ids. So if we encounter an
- // empty hole, check for that case.
- return self.definitions.opt_def_index(id)
- .map(|def_index| {
- let def_path_hash = self.definitions.def_path_hash(def_index);
- def_path_hash.to_dep_node(DepKind::Hir)
- })
- .unwrap_or_else(|| {
- bug!("Walking parents from `{}` \
- led to `NotPresent` at `{}`",
- id0, id)
- }),
}
}
}
Some(body_id)
} else {
// For some expressions, the expression is its own body.
- if let EntryExpr(_, expr) = entry {
+ if let EntryExpr(_, _, expr) = entry {
Some(BodyId { node_id: expr.id })
} else {
None
pub fn get_foreign_abi(&self, id: NodeId) -> Abi {
let parent = self.get_parent(id);
let abi = match self.find_entry(parent) {
- Some(EntryItem(_, i)) => {
+ Some(EntryItem(_, _, i)) => {
match i.node {
ItemForeignMod(ref nm) => Some(nm.abi),
_ => None
pub fn span(&self, id: NodeId) -> Span {
self.read(id); // reveals span from node
match self.find_entry(id) {
- Some(EntryItem(_, item)) => item.span,
- Some(EntryForeignItem(_, foreign_item)) => foreign_item.span,
- Some(EntryTraitItem(_, trait_method)) => trait_method.span,
- Some(EntryImplItem(_, impl_item)) => impl_item.span,
- Some(EntryVariant(_, variant)) => variant.span,
- Some(EntryField(_, field)) => field.span,
- Some(EntryExpr(_, expr)) => expr.span,
- Some(EntryStmt(_, stmt)) => stmt.span,
- Some(EntryTy(_, ty)) => ty.span,
- Some(EntryTraitRef(_, tr)) => tr.path.span,
- Some(EntryBinding(_, pat)) => pat.span,
- Some(EntryPat(_, pat)) => pat.span,
- Some(EntryBlock(_, block)) => block.span,
- Some(EntryStructCtor(_, _)) => self.expect_item(self.get_parent(id)).span,
- Some(EntryLifetime(_, lifetime)) => lifetime.span,
- Some(EntryTyParam(_, ty_param)) => ty_param.span,
- Some(EntryVisibility(_, &Visibility::Restricted { ref path, .. })) => path.span,
- Some(EntryVisibility(_, v)) => bug!("unexpected Visibility {:?}", v),
- Some(EntryLocal(_, local)) => local.span,
-
- Some(RootCrate) => self.forest.krate.span,
+ Some(EntryItem(_, _, item)) => item.span,
+ Some(EntryForeignItem(_, _, foreign_item)) => foreign_item.span,
+ Some(EntryTraitItem(_, _, trait_method)) => trait_method.span,
+ Some(EntryImplItem(_, _, impl_item)) => impl_item.span,
+ Some(EntryVariant(_, _, variant)) => variant.span,
+ Some(EntryField(_, _, field)) => field.span,
+ Some(EntryExpr(_, _, expr)) => expr.span,
+ Some(EntryStmt(_, _, stmt)) => stmt.span,
+ Some(EntryTy(_, _, ty)) => ty.span,
+ Some(EntryTraitRef(_, _, tr)) => tr.path.span,
+ Some(EntryBinding(_, _, pat)) => pat.span,
+ Some(EntryPat(_, _, pat)) => pat.span,
+ Some(EntryBlock(_, _, block)) => block.span,
+ Some(EntryStructCtor(_, _, _)) => self.expect_item(self.get_parent(id)).span,
+ Some(EntryLifetime(_, _, lifetime)) => lifetime.span,
+ Some(EntryTyParam(_, _, ty_param)) => ty_param.span,
+ Some(EntryVisibility(_, _, &Visibility::Restricted { ref path, .. })) => path.span,
+ Some(EntryVisibility(_, _, v)) => bug!("unexpected Visibility {:?}", v),
+ Some(EntryLocal(_, _, local)) => local.span,
+
+ Some(RootCrate(_)) => self.forest.krate.span,
Some(NotPresent) | None => {
bug!("hir::map::Map::span: id not in map: {:?}", id)
}
}
self.idx = NodeId::from_u32(self.idx.as_u32() + 1);
let name = match self.map.find_entry(idx) {
- Some(EntryItem(_, n)) => n.name(),
- Some(EntryForeignItem(_, n))=> n.name(),
- Some(EntryTraitItem(_, n)) => n.name(),
- Some(EntryImplItem(_, n)) => n.name(),
- Some(EntryVariant(_, n)) => n.name(),
- Some(EntryField(_, n)) => n.name(),
+ Some(EntryItem(_, _, n)) => n.name(),
+ Some(EntryForeignItem(_, _, n))=> n.name(),
+ Some(EntryTraitItem(_, _, n)) => n.name(),
+ Some(EntryImplItem(_, _, n)) => n.name(),
+ Some(EntryVariant(_, _, n)) => n.name(),
+ Some(EntryField(_, _, n)) => n.name(),
_ => continue,
};
if self.matches_names(self.map.get_parent(idx), name) {
pub fn map_crate<'hir>(forest: &'hir mut Forest,
definitions: Definitions)
-> Map<'hir> {
- let mut collector = NodeCollector::root(&forest.krate);
- intravisit::walk_crate(&mut collector, &forest.krate);
- let map = collector.map;
+ let map = {
+ let mut collector = NodeCollector::root(&forest.krate,
+ &forest.dep_graph,
+ &definitions);
+ intravisit::walk_crate(&mut collector, &forest.krate);
+ collector.into_map()
+ };
if log_enabled!(::log::LogLevel::Debug) {
// This only makes sense for ordered stores; note the
pub use self::UnOp::*;
pub use self::UnsafeSource::*;
pub use self::Visibility::{Public, Inherited};
-pub use self::PathParameters::*;
use hir::def::Def;
use hir::def_id::{DefId, DefIndex, CRATE_DEF_INDEX};
}
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
-pub enum PathParameters {
- /// The `<'a, A,B,C>` in `foo::bar::baz::<'a, A,B,C>`
- AngleBracketedParameters(AngleBracketedParameterData),
- /// The `(A,B)` and `C` in `Foo(A,B) -> C`
- ParenthesizedParameters(ParenthesizedParameterData),
-}
-
-impl PathParameters {
- pub fn none() -> PathParameters {
- AngleBracketedParameters(AngleBracketedParameterData {
- lifetimes: HirVec::new(),
- types: HirVec::new(),
- infer_types: true,
- bindings: HirVec::new(),
- })
- }
-
- /// Returns the types that the user wrote. Note that these do not necessarily map to the type
- /// parameters in the parenthesized case.
- pub fn types(&self) -> HirVec<&P<Ty>> {
- match *self {
- AngleBracketedParameters(ref data) => {
- data.types.iter().collect()
- }
- ParenthesizedParameters(ref data) => {
- data.inputs
- .iter()
- .chain(data.output.iter())
- .collect()
- }
- }
- }
-
- pub fn lifetimes(&self) -> HirVec<&Lifetime> {
- match *self {
- AngleBracketedParameters(ref data) => {
- data.lifetimes.iter().collect()
- }
- ParenthesizedParameters(_) => {
- HirVec::new()
- }
- }
- }
-
- pub fn bindings(&self) -> HirVec<&TypeBinding> {
- match *self {
- AngleBracketedParameters(ref data) => {
- data.bindings.iter().collect()
- }
- ParenthesizedParameters(_) => {
- HirVec::new()
- }
- }
- }
-}
-
-/// A path like `Foo<'a, T>`
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
-pub struct AngleBracketedParameterData {
+pub struct PathParameters {
/// The lifetime parameters for this path segment.
pub lifetimes: HirVec<Lifetime>,
/// The type parameters for this path segment, if present.
/// Bindings (equality constraints) on associated types, if present.
/// E.g., `Foo<A=Bar>`.
pub bindings: HirVec<TypeBinding>,
+ /// Were parameters written in parenthesized form `Fn(T) -> U`?
+ /// This is required mostly for pretty-printing and diagnostics,
+ /// but also for changing lifetime elision rules to be "function-like".
+ pub parenthesized: bool,
}
-/// A path like `Foo(A,B) -> C`
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
-pub struct ParenthesizedParameterData {
- /// Overall span
- pub span: Span,
-
- /// `(A,B)`
- pub inputs: HirVec<P<Ty>>,
+impl PathParameters {
+ pub fn none() -> Self {
+ Self {
+ lifetimes: HirVec::new(),
+ types: HirVec::new(),
+ infer_types: true,
+ bindings: HirVec::new(),
+ parenthesized: false,
+ }
+ }
- /// `C`
- pub output: Option<P<Ty>>,
+ pub fn inputs(&self) -> &[P<Ty>] {
+ if self.parenthesized {
+ if let Some(ref ty) = self.types.get(0) {
+ if let TyTup(ref tys) = ty.node {
+ return tys;
+ }
+ }
+ }
+ bug!("PathParameters::inputs: not a `Fn(T) -> U`");
+ }
}
/// The AST represents all type param bounds as types.
pub struct TraitItem {
pub id: NodeId,
pub name: Name,
+ pub hir_id: HirId,
pub attrs: HirVec<Attribute>,
pub node: TraitItemKind,
pub span: Span,
pub struct ImplItem {
pub id: NodeId,
pub name: Name,
+ pub hir_id: HirId,
pub vis: Visibility,
pub defaultness: Defaultness,
pub attrs: HirVec<Attribute>,
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub struct Item {
pub name: Name,
- pub attrs: HirVec<Attribute>,
pub id: NodeId,
+ pub hir_id: HirId,
+ pub attrs: HirVec<Attribute>,
pub node: Item_,
pub vis: Visibility,
pub span: Span,
self.print_expr(&args[0])?;
self.s.word(".")?;
self.print_name(segment.name)?;
- if !segment.parameters.lifetimes().is_empty() ||
- !segment.parameters.types().is_empty() ||
- !segment.parameters.bindings().is_empty() {
+ if !segment.parameters.lifetimes.is_empty() ||
+ !segment.parameters.types.is_empty() ||
+ !segment.parameters.bindings.is_empty() {
self.print_path_parameters(&segment.parameters, true)?;
}
self.print_call_post(base_args)
parameters: &hir::PathParameters,
colons_before_params: bool)
-> io::Result<()> {
- match *parameters {
- hir::AngleBracketedParameters(ref data) => {
- let start = if colons_before_params { "::<" } else { "<" };
- let empty = Cell::new(true);
- let start_or_comma = |this: &mut Self| {
- if empty.get() {
- empty.set(false);
- this.s.word(start)
- } else {
- this.word_space(",")
- }
- };
+ if parameters.parenthesized {
+ self.s.word("(")?;
+ self.commasep(Inconsistent, parameters.inputs(), |s, ty| s.print_type(&ty))?;
+ self.s.word(")")?;
- if !data.lifetimes.iter().all(|lt| lt.is_elided()) {
- for lifetime in &data.lifetimes {
- start_or_comma(self)?;
- self.print_lifetime(lifetime)?;
- }
- }
-
- if !data.types.is_empty() {
- start_or_comma(self)?;
- self.commasep(Inconsistent, &data.types, |s, ty| s.print_type(&ty))?;
+ self.space_if_not_bol()?;
+ self.word_space("->")?;
+ self.print_type(¶meters.bindings[0].ty)?;
+ } else {
+ let start = if colons_before_params { "::<" } else { "<" };
+ let empty = Cell::new(true);
+ let start_or_comma = |this: &mut Self| {
+ if empty.get() {
+ empty.set(false);
+ this.s.word(start)
+ } else {
+ this.word_space(",")
}
+ };
- // FIXME(eddyb) This would leak into error messages, e.g.:
- // "non-exhaustive patterns: `Some::<..>(_)` not covered".
- if data.infer_types && false {
+ if !parameters.lifetimes.iter().all(|lt| lt.is_elided()) {
+ for lifetime in ¶meters.lifetimes {
start_or_comma(self)?;
- self.s.word("..")?;
+ self.print_lifetime(lifetime)?;
}
+ }
- for binding in data.bindings.iter() {
- start_or_comma(self)?;
- self.print_name(binding.name)?;
- self.s.space()?;
- self.word_space("=")?;
- self.print_type(&binding.ty)?;
- }
+ if !parameters.types.is_empty() {
+ start_or_comma(self)?;
+ self.commasep(Inconsistent, ¶meters.types, |s, ty| s.print_type(&ty))?;
+ }
- if !empty.get() {
- self.s.word(">")?
- }
+ // FIXME(eddyb) This would leak into error messages, e.g.:
+ // "non-exhaustive patterns: `Some::<..>(_)` not covered".
+ if parameters.infer_types && false {
+ start_or_comma(self)?;
+ self.s.word("..")?;
}
- hir::ParenthesizedParameters(ref data) => {
- self.s.word("(")?;
- self.commasep(Inconsistent, &data.inputs, |s, ty| s.print_type(&ty))?;
- self.s.word(")")?;
+ for binding in parameters.bindings.iter() {
+ start_or_comma(self)?;
+ self.print_name(binding.name)?;
+ self.s.space()?;
+ self.word_space("=")?;
+ self.print_type(&binding.ty)?;
+ }
- if let Some(ref ty) = data.output {
- self.space_if_not_bol()?;
- self.word_space("->")?;
- self.print_type(&ty)?;
- }
+ if !empty.get() {
+ self.s.word(">")?
}
}
parameters
});
-impl_stable_hash_for!(enum hir::PathParameters {
- AngleBracketedParameters(data),
- ParenthesizedParameters(data)
-});
-
-impl_stable_hash_for!(struct hir::AngleBracketedParameterData {
+impl_stable_hash_for!(struct hir::PathParameters {
lifetimes,
types,
infer_types,
- bindings
-});
-
-impl_stable_hash_for!(struct hir::ParenthesizedParameterData {
- span,
- inputs,
- output
+ bindings,
+ parenthesized
});
impl_stable_hash_for!(enum hir::TyParamBound {
hasher: &mut StableHasher<W>) {
let hir::TraitItem {
id,
+ hir_id: _,
name,
ref attrs,
ref node,
hasher: &mut StableHasher<W>) {
let hir::ImplItem {
id,
+ hir_id: _,
name,
ref vis,
defaultness,
name,
ref attrs,
id,
+ hir_id: _,
ref node,
ref vis,
span
// { x.push(y); }.
// The example gives
// fn foo(x: &mut Vec<&u8>, y: &u8) {
- // --- --- these references must have the same lifetime
+ // --- --- these references are declared with different lifetimes...
// x.push(y);
- // ^ data from `y` flows into `x` here
- // It will later be extended to trait objects and structs.
+ // ^ ...but data from `y` flows into `x` here
+ // It has been extended for the case of structs too.
+ // Consider the example
+ // struct Ref<'a> { x: &'a u32 }
+ // fn foo(mut x: Vec<Ref>, y: Ref) {
+ // --- --- these structs are declared with different lifetimes...
+ // x.push(y);
+ // ^ ...but data from `y` flows into `x` here
+ // }
+ // It will later be extended to trait objects.
pub fn try_report_anon_anon_conflict(&self, error: &RegionResolutionError<'tcx>) -> bool {
-
let (span, sub, sup) = match *error {
ConcreteFailure(ref origin, sub, sup) => (origin.span(), sub, sup),
_ => return false, // inapplicable
};
// Determine whether the sub and sup consist of both anonymous (elided) regions.
- let (ty1, ty2) = if self.is_suitable_anonymous_region(sup).is_some() &&
- self.is_suitable_anonymous_region(sub).is_some() {
- if let (Some(anon_reg1), Some(anon_reg2)) =
- (self.is_suitable_anonymous_region(sup), self.is_suitable_anonymous_region(sub)) {
- let ((_, br1), (_, br2)) = (anon_reg1, anon_reg2);
- if self.find_anon_type(sup, &br1).is_some() &&
- self.find_anon_type(sub, &br2).is_some() {
- (self.find_anon_type(sup, &br1).unwrap(),
- self.find_anon_type(sub, &br2).unwrap())
- } else {
- return false;
- }
- } else {
- return false;
- }
- } else {
- return false; // inapplicable
- };
+ let anon_reg_sup = or_false!(self.is_suitable_anonymous_region(sup));
- if let (Some(sup_arg), Some(sub_arg)) =
+ let anon_reg_sub = or_false!(self.is_suitable_anonymous_region(sub));
+ let scope_def_id_sup = anon_reg_sup.def_id;
+ let bregion_sup = anon_reg_sup.boundregion;
+ let scope_def_id_sub = anon_reg_sub.def_id;
+ let bregion_sub = anon_reg_sub.boundregion;
+
+ let ty_sup = or_false!(self.find_anon_type(sup, &bregion_sup));
+
+ let ty_sub = or_false!(self.find_anon_type(sub, &bregion_sub));
+
+ let (main_label, label1, label2) = if let (Some(sup_arg), Some(sub_arg)) =
(self.find_arg_with_anonymous_region(sup, sup),
self.find_arg_with_anonymous_region(sub, sub)) {
- let ((anon_arg1, _, _, _), (anon_arg2, _, _, _)) = (sup_arg, sub_arg);
- let span_label_var1 = if let Some(simple_name) = anon_arg1.pat.simple_name() {
- format!(" from `{}` ", simple_name)
- } else {
- format!(" ")
- };
+ let (anon_arg_sup, is_first_sup, anon_arg_sub, is_first_sub) =
+ (sup_arg.arg, sup_arg.is_first, sub_arg.arg, sub_arg.is_first);
+ if self.is_self_anon(is_first_sup, scope_def_id_sup) ||
+ self.is_self_anon(is_first_sub, scope_def_id_sub) {
+ return false;
+ }
- let span_label_var2 = if let Some(simple_name) = anon_arg2.pat.simple_name() {
- format!(" into `{}` ", simple_name)
+ if self.is_return_type_anon(scope_def_id_sup, bregion_sup) ||
+ self.is_return_type_anon(scope_def_id_sub, bregion_sub) {
+ return false;
+ }
+
+ if anon_arg_sup == anon_arg_sub {
+ (format!("this type was declared with multiple lifetimes..."),
+ format!(" with one lifetime"),
+ format!(" into the other"))
} else {
- format!(" ")
- };
-
- struct_span_err!(self.tcx.sess, span, E0623, "lifetime mismatch")
- .span_label(ty1.span,
- format!("these references are not declared with the same lifetime..."))
- .span_label(ty2.span, format!(""))
- .span_label(span,
- format!("...but data{}flows{}here", span_label_var1, span_label_var2))
- .emit();
+ let span_label_var1 = if let Some(simple_name) = anon_arg_sup.pat.simple_name() {
+ format!(" from `{}`", simple_name)
+ } else {
+ format!("")
+ };
+
+ let span_label_var2 = if let Some(simple_name) = anon_arg_sub.pat.simple_name() {
+ format!(" into `{}`", simple_name)
+ } else {
+ format!("")
+ };
+
+ let span_label =
+ format!("these two types are declared with different lifetimes...",);
+
+ (span_label, span_label_var1, span_label_var2)
+ }
} else {
return false;
- }
+ };
+ struct_span_err!(self.tcx.sess, span, E0623, "lifetime mismatch")
+ .span_label(ty_sup.span, main_label)
+ .span_label(ty_sub.span, format!(""))
+ .span_label(span, format!("...but data{} flows{} here", label1, label2))
+ .emit();
return true;
}
/// contains the anonymous type.
///
/// # Arguments
- ///
/// region - the anonymous region corresponding to the anon_anon conflict
/// br - the bound region corresponding to the above region which is of type `BrAnon(_)`
///
/// ```
/// The function returns the nested type corresponding to the anonymous region
/// for e.g. `&u8` and Vec<`&u8`.
- fn find_anon_type(&self, region: Region<'tcx>, br: &ty::BoundRegion) -> Option<&hir::Ty> {
+ pub fn find_anon_type(&self, region: Region<'tcx>, br: &ty::BoundRegion) -> Option<&hir::Ty> {
if let Some(anon_reg) = self.is_suitable_anonymous_region(region) {
- let (def_id, _) = anon_reg;
+ let def_id = anon_reg.def_id;
if let Some(node_id) = self.tcx.hir.as_local_node_id(def_id) {
let ret_ty = self.tcx.type_of(def_id);
if let ty::TyFnDef(_, _) = ret_ty.sty {
- if let hir_map::NodeItem(it) = self.tcx.hir.get(node_id) {
- if let hir::ItemFn(ref fndecl, _, _, _, _, _) = it.node {
- return fndecl
- .inputs
- .iter()
- .filter_map(|arg| {
- let mut nested_visitor = FindNestedTypeVisitor {
- infcx: &self,
- hir_map: &self.tcx.hir,
- bound_region: *br,
- found_type: None,
- };
- nested_visitor.visit_ty(&**arg);
- if nested_visitor.found_type.is_some() {
- nested_visitor.found_type
- } else {
- None
- }
- })
- .next();
- }
- }
+ let inputs: &[_] =
+ match self.tcx.hir.get(node_id) {
+ hir_map::NodeItem(&hir::Item {
+ node: hir::ItemFn(ref fndecl, ..), ..
+ }) => &fndecl.inputs,
+ hir_map::NodeTraitItem(&hir::TraitItem {
+ node: hir::TraitItemKind::Method(ref fndecl, ..),
+ ..
+ }) => &fndecl.decl.inputs,
+ hir_map::NodeImplItem(&hir::ImplItem {
+ node: hir::ImplItemKind::Method(ref fndecl, ..),
+ ..
+ }) => &fndecl.decl.inputs,
+
+ _ => &[],
+ };
+
+ return inputs
+ .iter()
+ .filter_map(|arg| {
+ self.find_component_for_bound_region(&**arg, br)
+ })
+ .next();
}
}
}
None
}
+
+ // This method creates a FindNestedTypeVisitor which returns the type corresponding
+ // to the anonymous region.
+ fn find_component_for_bound_region(&self,
+ arg: &'gcx hir::Ty,
+ br: &ty::BoundRegion)
+ -> Option<(&'gcx hir::Ty)> {
+ let mut nested_visitor = FindNestedTypeVisitor {
+ infcx: &self,
+ hir_map: &self.tcx.hir,
+ bound_region: *br,
+ found_type: None,
+ };
+ nested_visitor.visit_ty(arg);
+ nested_visitor.found_type
+ }
}
// The FindNestedTypeVisitor captures the corresponding `hir::Ty` of the
hir::TyRptr(ref lifetime, _) => {
match self.infcx.tcx.named_region_map.defs.get(&lifetime.id) {
// the lifetime of the TyRptr
- Some(&rl::Region::LateBoundAnon(debuijn_index, anon_index)) => {
- if debuijn_index.depth == 1 && anon_index == br_index {
+ Some(&rl::Region::LateBoundAnon(debruijn_index, anon_index)) => {
+ if debruijn_index.depth == 1 && anon_index == br_index {
self.found_type = Some(arg);
return; // we can stop visiting now
}
}
}
}
+ // Checks if it is of type `hir::TyPath` which corresponds to a struct.
+ hir::TyPath(_) => {
+ let subvisitor = &mut TyPathVisitor {
+ infcx: self.infcx,
+ found_it: false,
+ bound_region: self.bound_region,
+ hir_map: self.hir_map,
+ };
+ intravisit::walk_ty(subvisitor, arg); // call walk_ty; as visit_ty is empty,
+ // this will visit only outermost type
+ if subvisitor.found_it {
+ self.found_type = Some(arg);
+ }
+ }
_ => {}
}
// walk the embedded contents: e.g., if we are visiting `Vec<&Foo>`,
intravisit::walk_ty(self, arg);
}
}
+
+// The visitor captures the corresponding `hir::Ty` of the anonymous region
+// in the case of structs ie. `hir::TyPath`.
+// This visitor would be invoked for each lifetime corresponding to a struct,
+// and would walk the types like Vec<Ref> in the above example and Ref looking for the HIR
+// where that lifetime appears. This allows us to highlight the
+// specific part of the type in the error message.
+struct TyPathVisitor<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
+ infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
+ hir_map: &'a hir::map::Map<'gcx>,
+ found_it: bool,
+ bound_region: ty::BoundRegion,
+}
+
+impl<'a, 'gcx, 'tcx> Visitor<'gcx> for TyPathVisitor<'a, 'gcx, 'tcx> {
+ fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'gcx> {
+ NestedVisitorMap::OnlyBodies(&self.hir_map)
+ }
+
+ fn visit_lifetime(&mut self, lifetime: &hir::Lifetime) {
+ let br_index = match self.bound_region {
+ ty::BrAnon(index) => index,
+ _ => return,
+ };
+
+ match self.infcx.tcx.named_region_map.defs.get(&lifetime.id) {
+ // the lifetime of the TyPath!
+ Some(&rl::Region::LateBoundAnon(debruijn_index, anon_index)) => {
+ if debruijn_index.depth == 1 && anon_index == br_index {
+ self.found_it = true;
+ }
+ }
+ Some(&rl::Region::Static) |
+ Some(&rl::Region::EarlyBound(_, _)) |
+ Some(&rl::Region::LateBound(_, _)) |
+ Some(&rl::Region::Free(_, _)) |
+ None => {
+ debug!("no arg found");
+ }
+ }
+ }
+
+ fn visit_ty(&mut self, arg: &'gcx hir::Ty) {
+ // ignore nested types
+ //
+ // If you have a type like `Foo<'a, &Ty>` we
+ // are only interested in the immediate lifetimes ('a).
+ //
+ // Making `visit_ty` empty will ignore the `&Ty` embedded
+ // inside, it will get reached by the outer visitor.
+ debug!("`Ty` corresponding to a struct is {:?}", arg);
+ }
+}
mod note;
mod need_type_info;
-mod util;
+
mod named_anon_conflict;
+#[macro_use]
+mod util;
mod anon_anon_conflict;
impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
//! Error Reporting for Anonymous Region Lifetime Errors
//! where one region is named and the other is anonymous.
use infer::InferCtxt;
-use ty;
use infer::region_inference::RegionResolutionError::*;
use infer::region_inference::RegionResolutionError;
// where the anonymous region appears (there must always be one; we
// only introduced anonymous regions in parameters) as well as a
// version new_ty of its type where the anonymous region is replaced
- // with the named one.
- let (named, (arg, new_ty, br, is_first), (scope_def_id, _)) =
+ // with the named one.//scope_def_id
+ let (named, anon_arg_info, region_info) =
if sub.is_named_region() && self.is_suitable_anonymous_region(sup).is_some() {
(sub,
self.find_arg_with_anonymous_region(sup, sub).unwrap(),
return false; // inapplicable
};
- // Here, we check for the case where the anonymous region
- // is in the return type.
- // FIXME(#42703) - Need to handle certain cases here.
- let ret_ty = self.tcx.type_of(scope_def_id);
- match ret_ty.sty {
- ty::TyFnDef(_, _) => {
- let sig = ret_ty.fn_sig(self.tcx);
- let late_bound_regions = self.tcx
- .collect_referenced_late_bound_regions(&sig.output());
- if late_bound_regions.iter().any(|r| *r == br) {
- return false;
- }
- }
- _ => {}
- }
-
- // Here we check for the case where anonymous region
- // corresponds to self and if yes, we display E0312.
- // FIXME(#42700) - Need to format self properly to
- // enable E0621 for it.
- if is_first &&
- self.tcx
- .opt_associated_item(scope_def_id)
- .map(|i| i.method_has_self_argument)
- .unwrap_or(false) {
+ let (arg, new_ty, br, is_first, scope_def_id, is_impl_item) = (anon_arg_info.arg,
+ anon_arg_info.arg_ty,
+ anon_arg_info.bound_region,
+ anon_arg_info.is_first,
+ region_info.def_id,
+ region_info.is_impl_item);
+ if is_impl_item {
return false;
}
- let (error_var, span_label_var) = if let Some(simple_name) = arg.pat.simple_name() {
- (format!("the type of `{}`", simple_name), format!("the type of `{}`", simple_name))
+ if self.is_return_type_anon(scope_def_id, br) || self.is_self_anon(is_first, scope_def_id) {
+ return false;
} else {
- ("parameter type".to_owned(), "type".to_owned())
- };
- struct_span_err!(self.tcx.sess,
- span,
- E0621,
- "explicit lifetime required in {}",
- error_var)
- .span_label(arg.pat.span,
- format!("consider changing {} to `{}`", span_label_var, new_ty))
- .span_label(span, format!("lifetime `{}` required", named))
- .emit();
+ let (error_var, span_label_var) = if let Some(simple_name) = arg.pat.simple_name() {
+ (format!("the type of `{}`", simple_name), format!("the type of `{}`", simple_name))
+ } else {
+ ("parameter type".to_owned(), "type".to_owned())
+ };
+
+ struct_span_err!(self.tcx.sess,
+ span,
+ E0621,
+ "explicit lifetime required in {}",
+ error_var)
+ .span_label(arg.pat.span,
+ format!("consider changing {} to `{}`", span_label_var, new_ty))
+ .span_label(span, format!("lifetime `{}` required", named))
+ .emit();
+
+ }
return true;
}
}
use hir::def_id::DefId;
use hir::map as hir_map;
+macro_rules! or_false {
+ ($v:expr) => {
+ match $v {
+ Some(v) => v,
+ None => return false,
+ }
+ }
+}
+
+// The struct contains the information about the anonymous region
+// we are searching for.
+pub struct AnonymousArgInfo<'tcx> {
+ // the argument corresponding to the anonymous region
+ pub arg: &'tcx hir::Arg,
+ // the type corresponding to the anonymopus region argument
+ pub arg_ty: ty::Ty<'tcx>,
+ // the ty::BoundRegion corresponding to the anonymous region
+ pub bound_region: ty::BoundRegion,
+ // corresponds to id the argument is the first parameter
+ // in the declaration
+ pub is_first: bool,
+}
+
+// This struct contains information regarding the
+// Refree((FreeRegion) corresponding to lifetime conflict
+pub struct FreeRegionInfo {
+ // def id corresponding to FreeRegion
+ pub def_id: DefId,
+ // the bound region corresponding to FreeRegion
+ pub boundregion: ty::BoundRegion,
+ // checks if bound region is in Impl Item
+ pub is_impl_item: bool,
+}
+
impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
// This method walks the Type of the function body arguments using
// `fold_regions()` function and returns the
// i32, which is the type of y but with the anonymous region replaced
// with 'a, the corresponding bound region and is_first which is true if
// the hir::Arg is the first argument in the function declaration.
- pub fn find_arg_with_anonymous_region
- (&self,
- anon_region: Region<'tcx>,
- replace_region: Region<'tcx>)
- -> Option<(&hir::Arg, ty::Ty<'tcx>, ty::BoundRegion, bool)> {
+ pub fn find_arg_with_anonymous_region(&self,
+ anon_region: Region<'tcx>,
+ replace_region: Region<'tcx>)
+ -> Option<AnonymousArgInfo> {
if let ty::ReFree(ref free_region) = *anon_region {
-
let id = free_region.scope;
let hir = &self.tcx.hir;
if let Some(node_id) = hir.as_local_node_id(id) {
});
if found_anon_region {
let is_first = index == 0;
- Some((arg, new_arg_ty, free_region.bound_region, is_first))
+ Some(AnonymousArgInfo {
+ arg: arg,
+ arg_ty: new_arg_ty,
+ bound_region: free_region.bound_region,
+ is_first: is_first,
+ })
} else {
None
}
// This method returns whether the given Region is Anonymous
// and returns the DefId and the BoundRegion corresponding to the given region.
- pub fn is_suitable_anonymous_region(&self,
- region: Region<'tcx>)
- -> Option<(DefId, ty::BoundRegion)> {
+ pub fn is_suitable_anonymous_region(&self, region: Region<'tcx>) -> Option<FreeRegionInfo> {
if let ty::ReFree(ref free_region) = *region {
- if let ty::BrAnon(..) = free_region.bound_region{
- let anonymous_region_binding_scope = free_region.scope;
- let node_id = self.tcx
- .hir
- .as_local_node_id(anonymous_region_binding_scope)
- .unwrap();
- match self.tcx.hir.find(node_id) {
- Some(hir_map::NodeItem(..)) |
- Some(hir_map::NodeTraitItem(..)) => {
- // Success -- proceed to return Some below
- }
- Some(hir_map::NodeImplItem(..)) => {
- let container_id = self.tcx
- .associated_item(anonymous_region_binding_scope)
- .container
- .id();
- if self.tcx.impl_trait_ref(container_id).is_some() {
- // For now, we do not try to target impls of traits. This is
- // because this message is going to suggest that the user
- // change the fn signature, but they may not be free to do so,
- // since the signature must match the trait.
- //
- // FIXME(#42706) -- in some cases, we could do better here.
- return None;
- }
- }
- _ => return None, // inapplicable
- // we target only top-level functions
+ if let ty::BrAnon(..) = free_region.bound_region {
+ let anonymous_region_binding_scope = free_region.scope;
+ let node_id = self.tcx
+ .hir
+ .as_local_node_id(anonymous_region_binding_scope)
+ .unwrap();
+ let mut is_impl_item = false;
+ match self.tcx.hir.find(node_id) {
+
+ Some(hir_map::NodeItem(..)) |
+ Some(hir_map::NodeTraitItem(..)) => {
+ // Success -- proceed to return Some below
}
- return Some((anonymous_region_binding_scope, free_region.bound_region));
+ Some(hir_map::NodeImplItem(..)) => {
+ is_impl_item =
+ self.is_bound_region_in_impl_item(anonymous_region_binding_scope);
+ }
+ _ => return None,
}
+ return Some(FreeRegionInfo {
+ def_id: anonymous_region_binding_scope,
+ boundregion: free_region.bound_region,
+ is_impl_item: is_impl_item,
+ });
}
- None
}
+ None
+ }
+
+ // Here, we check for the case where the anonymous region
+ // is in the return type.
+ // FIXME(#42703) - Need to handle certain cases here.
+ pub fn is_return_type_anon(&self, scope_def_id: DefId, br: ty::BoundRegion) -> bool {
+ let ret_ty = self.tcx.type_of(scope_def_id);
+ match ret_ty.sty {
+ ty::TyFnDef(_, _) => {
+ let sig = ret_ty.fn_sig(self.tcx);
+ let late_bound_regions = self.tcx
+ .collect_referenced_late_bound_regions(&sig.output());
+ if late_bound_regions.iter().any(|r| *r == br) {
+ return true;
+ }
+ }
+ _ => {}
+ }
+ false
+ }
+ // Here we check for the case where anonymous region
+ // corresponds to self and if yes, we display E0312.
+ // FIXME(#42700) - Need to format self properly to
+ // enable E0621 for it.
+ pub fn is_self_anon(&self, is_first: bool, scope_def_id: DefId) -> bool {
+ is_first &&
+ self.tcx
+ .opt_associated_item(scope_def_id)
+ .map(|i| i.method_has_self_argument) == Some(true)
+ }
+
+ // Here we check if the bound region is in Impl Item.
+ pub fn is_bound_region_in_impl_item(&self, anonymous_region_binding_scope: DefId) -> bool {
+ let container_id = self.tcx
+ .associated_item(anonymous_region_binding_scope)
+ .container
+ .id();
+ if self.tcx.impl_trait_ref(container_id).is_some() {
+ // For now, we do not try to target impls of traits. This is
+ // because this message is going to suggest that the user
+ // change the fn signature, but they may not be free to do so,
+ // since the signature must match the trait.
+ //
+ // FIXME(#42706) -- in some cases, we could do better here.
+ return true;
+ }
+ false
+ }
}
//!
//! This API is completely unstable and subject to change.
-#![crate_name = "rustc"]
-#![crate_type = "dylib"]
-#![crate_type = "rlib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
html_root_url = "https://doc.rust-lang.org/nightly/")]
#![feature(core_intrinsics)]
#![feature(discriminant_value)]
#![feature(i128_type)]
-#![feature(libc)]
+#![cfg_attr(windows, feature(libc))]
#![feature(never_type)]
#![feature(nonzero)]
#![feature(quote)]
extern crate fmt_macros;
extern crate getopts;
extern crate graphviz;
+#[cfg(windows)]
extern crate libc;
extern crate owning_ref;
extern crate rustc_back;
// Note that librustc doesn't actually depend on these crates, see the note in
// `Cargo.toml` for this crate about why these are here.
+#[allow(unused_extern_crates)]
extern crate flate2;
+#[allow(unused_extern_crates)]
extern crate test;
#[macro_use]
declare_lint! {
pub UNUSED_EXTERN_CRATES,
- Allow,
+ Warn,
"extern crates that are never used"
}
def: Def,
depth: usize,
params: &'tcx hir::PathParameters) {
- let data = match *params {
- hir::ParenthesizedParameters(ref data) => {
- self.visit_fn_like_elision(&data.inputs, data.output.as_ref());
- return;
- }
- hir::AngleBracketedParameters(ref data) => data
- };
+ if params.parenthesized {
+ self.visit_fn_like_elision(params.inputs(), Some(¶ms.bindings[0].ty));
+ return;
+ }
- if data.lifetimes.iter().all(|l| l.is_elided()) {
- self.resolve_elided_lifetimes(&data.lifetimes);
+ if params.lifetimes.iter().all(|l| l.is_elided()) {
+ self.resolve_elided_lifetimes(¶ms.lifetimes);
} else {
- for l in &data.lifetimes { self.visit_lifetime(l); }
+ for l in ¶ms.lifetimes { self.visit_lifetime(l); }
}
// Figure out if this is a type/trait segment,
Some(Region::Static)
}
}
- Set1::One(r) => r.subst(&data.lifetimes, map),
+ Set1::One(r) => r.subst(¶ms.lifetimes, map),
Set1::Many => None
}
}).collect()
});
- for (i, ty) in data.types.iter().enumerate() {
+ for (i, ty) in params.types.iter().enumerate() {
if let Some(<) = object_lifetime_defaults.get(i) {
let scope = Scope::ObjectLifetimeDefault {
lifetime: lt,
}
}
- for b in &data.bindings { self.visit_assoc_type_binding(b); }
+ for b in ¶ms.bindings { self.visit_assoc_type_binding(b); }
}
fn visit_fn_like_elision(&mut self, inputs: &'tcx [P<hir::Ty>],
"dump the dependency graph to $RUST_DEP_GRAPH (default: /tmp/dep_graph.gv)"),
query_dep_graph: bool = (false, parse_bool, [UNTRACKED],
"enable queries of the dependency graph for regression testing"),
+ profile_queries: bool = (false, parse_bool, [UNTRACKED],
+ "trace and profile the queries of the incremental compilation framework"),
+ profile_queries_and_keys: bool = (false, parse_bool, [UNTRACKED],
+ "trace and profile the queries and keys of the incremental compilation framework"),
no_analysis: bool = (false, parse_bool, [UNTRACKED],
"parse and expand the source, but run no analysis"),
extra_plugins: Vec<String> = (Vec::new(), parse_list, [TRACKED],
}
pub fn verbose(&self) -> bool { self.opts.debugging_opts.verbose }
pub fn time_passes(&self) -> bool { self.opts.debugging_opts.time_passes }
+ pub fn profile_queries(&self) -> bool {
+ self.opts.debugging_opts.profile_queries ||
+ self.opts.debugging_opts.profile_queries_and_keys
+ }
+ pub fn profile_queries_and_keys(&self) -> bool {
+ self.opts.debugging_opts.profile_queries_and_keys
+ }
pub fn count_llvm_insns(&self) -> bool {
self.opts.debugging_opts.count_llvm_insns
}
pub maybe_unused_trait_imports: NodeSet,
+ pub maybe_unused_extern_crates: Vec<(NodeId, Span)>,
+
// Internal cache for metadata decoding. No need to track deps on this.
pub rcache: RefCell<FxHashMap<ty::CReaderCacheKey, Ty<'tcx>>>,
mir_passes,
freevars: RefCell::new(resolutions.freevars),
maybe_unused_trait_imports: resolutions.maybe_unused_trait_imports,
+ maybe_unused_extern_crates: resolutions.maybe_unused_extern_crates,
rcache: RefCell::new(FxHashMap()),
normalized_cache: RefCell::new(FxHashMap()),
inhabitedness_cache: RefCell::new(FxHashMap()),
use ty::{self, Ty, TyCtxt};
use syntax::ast;
use syntax::symbol::Symbol;
-use syntax_pos::DUMMY_SP;
use std::cell::Cell;
let use_types = !self.is_default_impl(impl_def_id) && (!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 && {
- // Otherwise, use types if we can query them without inducing a cycle.
- ty::queries::impl_trait_ref::try_get(self, DUMMY_SP, impl_def_id).is_ok() &&
- ty::queries::type_of::try_get(self, DUMMY_SP, impl_def_id).is_ok()
- }
+ !force_no_types
});
if !use_types {
// except according to those terms.
use dep_graph::{DepConstructor, DepNode, DepNodeIndex};
+use errors::{Diagnostic, DiagnosticBuilder};
use hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
use hir::def::Def;
use hir;
use ty::subst::Substs;
use ty::fast_reject::SimplifiedType;
use util::nodemap::{DefIdSet, NodeSet};
+use util::common::{profq_msg, ProfileQueriesMsg};
use rustc_data_structures::indexed_vec::IndexVec;
use rustc_data_structures::fx::FxHashMap;
-use std::cell::{RefCell, RefMut};
+use std::cell::{RefCell, RefMut, Cell};
use std::fmt::Debug;
use std::hash::Hash;
use std::marker::PhantomData;
struct QueryMap<D: QueryDescription> {
phantom: PhantomData<D>,
- map: FxHashMap<D::Key, (D::Value, DepNodeIndex)>,
+ map: FxHashMap<D::Key, QueryValue<D::Value>>,
+}
+
+struct QueryValue<T> {
+ value: T,
+ index: DepNodeIndex,
+ diagnostics: Option<Box<QueryDiagnostics>>,
+}
+
+struct QueryDiagnostics {
+ diagnostics: Vec<Diagnostic>,
+ emitted_diagnostics: Cell<bool>,
}
impl<M: QueryDescription> QueryMap<M> {
}
}
-pub struct CycleError<'a, 'tcx: 'a> {
+struct CycleError<'a, 'tcx: 'a> {
span: Span,
cycle: RefMut<'a, [(Span, Query<'tcx>)]>,
}
impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
- pub fn report_cycle(self, CycleError { span, cycle }: CycleError) {
+ fn report_cycle(self, CycleError { span, cycle }: CycleError)
+ -> DiagnosticBuilder<'a>
+ {
// Subtle: release the refcell lock before invoking `describe()`
// below by dropping `cycle`.
let stack = cycle.to_vec();
err.note(&format!("...which then again requires {}, completing the cycle.",
stack[0].1.describe(self)));
- err.emit();
- });
+ return err
+ })
}
fn cycle_check<F, R>(self, span: Span, query: Query<'gcx>, compute: F)
}
}
+impl<'tcx> QueryDescription for queries::is_compiler_builtins<'tcx> {
+ fn describe(_: TyCtxt, _: DefId) -> String {
+ "checking if the crate is_compiler_builtins".to_string()
+ }
+}
+
+impl<'tcx> QueryDescription for queries::has_global_allocator<'tcx> {
+ fn describe(_: TyCtxt, _: DefId) -> String {
+ "checking if the crate has_global_allocator".to_string()
+ }
+}
+
impl<'tcx> QueryDescription for queries::extern_crate<'tcx> {
fn describe(_: TyCtxt, _: DefId) -> String {
"getting crate's ExternCrateData".to_string()
}
}
+// If enabled, send a message to the profile-queries thread
+macro_rules! profq_msg {
+ ($tcx:expr, $msg:expr) => {
+ if cfg!(debug_assertions) {
+ if $tcx.sess.profile_queries() {
+ profq_msg($msg)
+ }
+ }
+ }
+}
+
+// If enabled, format a key using its debug string, which can be
+// expensive to compute (in terms of time).
+macro_rules! profq_key {
+ ($tcx:expr, $key:expr) => {
+ if cfg!(debug_assertions) {
+ if $tcx.sess.profile_queries_and_keys() {
+ Some(format!("{:?}", $key))
+ } else { None }
+ } else { None }
+ }
+}
+
macro_rules! define_maps {
(<$tcx:tt>
$($(#[$attr:meta])*
$($(#[$attr])* $name($K)),*
}
+ #[allow(bad_style)]
+ #[derive(Clone, Debug, PartialEq, Eq)]
+ pub enum QueryMsg {
+ $($name(Option<String>)),*
+ }
+
impl<$tcx> Query<$tcx> {
pub fn describe(&self, tcx: TyCtxt) -> String {
match *self {
key,
span);
- if let Some(&(ref result, dep_node_index)) = tcx.maps.$name.borrow().map.get(&key) {
- tcx.dep_graph.read_index(dep_node_index);
- return Ok(f(result));
+ profq_msg!(tcx,
+ ProfileQueriesMsg::QueryBegin(
+ span.clone(),
+ QueryMsg::$name(profq_key!(tcx, key))
+ )
+ );
+
+ if let Some(value) = tcx.maps.$name.borrow().map.get(&key) {
+ if let Some(ref d) = value.diagnostics {
+ if !d.emitted_diagnostics.get() {
+ d.emitted_diagnostics.set(true);
+ let handle = tcx.sess.diagnostic();
+ for diagnostic in d.diagnostics.iter() {
+ DiagnosticBuilder::new_diagnostic(handle, diagnostic.clone())
+ .emit();
+ }
+ }
+ }
+ profq_msg!(tcx, ProfileQueriesMsg::CacheHit);
+ tcx.dep_graph.read_index(value.index);
+ return Ok(f(&value.value));
}
+ // else, we are going to run the provider:
+ profq_msg!(tcx, ProfileQueriesMsg::ProviderBegin);
// FIXME(eddyb) Get more valid Span's on queries.
// def_span guard is necessary to prevent a recursive loop,
span = key.default_span(tcx)
}
- let (result, dep_node_index) = tcx.cycle_check(span, Query::$name(key), || {
+ let res = tcx.cycle_check(span, Query::$name(key), || {
let dep_node = Self::to_dep_node(tcx, &key);
- if dep_node.kind.is_anon() {
- tcx.dep_graph.with_anon_task(dep_node.kind, || {
- let provider = tcx.maps.providers[key.map_crate()].$name;
- provider(tcx.global_tcx(), key)
- })
- } else {
- fn run_provider<'a, 'tcx, 'lcx>(tcx: TyCtxt<'a, 'tcx, 'lcx>,
- key: $K)
- -> $V {
- let provider = tcx.maps.providers[key.map_crate()].$name;
- provider(tcx.global_tcx(), key)
+ tcx.sess.diagnostic().track_diagnostics(|| {
+ if dep_node.kind.is_anon() {
+ tcx.dep_graph.with_anon_task(dep_node.kind, || {
+ let provider = tcx.maps.providers[key.map_crate()].$name;
+ provider(tcx.global_tcx(), key)
+ })
+ } else {
+ fn run_provider<'a, 'tcx, 'lcx>(tcx: TyCtxt<'a, 'tcx, 'lcx>,
+ key: $K)
+ -> $V {
+ let provider = tcx.maps.providers[key.map_crate()].$name;
+ provider(tcx.global_tcx(), key)
+ }
+
+ tcx.dep_graph.with_task(dep_node, tcx, key, run_provider)
}
-
- tcx.dep_graph.with_task(dep_node, tcx, key, run_provider)
- }
+ })
})?;
+ profq_msg!(tcx, ProfileQueriesMsg::ProviderEnd);
+ let ((result, dep_node_index), diagnostics) = res;
tcx.dep_graph.read_index(dep_node_index);
+ let value = QueryValue {
+ value: result,
+ index: dep_node_index,
+ diagnostics: if diagnostics.len() == 0 {
+ None
+ } else {
+ Some(Box::new(QueryDiagnostics {
+ diagnostics,
+ emitted_diagnostics: Cell::new(true),
+ }))
+ },
+ };
+
Ok(f(&tcx.maps
.$name
.borrow_mut()
.map
.entry(key)
- .or_insert((result, dep_node_index))
- .0))
+ .or_insert(value)
+ .value))
}
pub fn try_get(tcx: TyCtxt<'a, $tcx, 'lcx>, span: Span, key: $K)
- -> Result<$V, CycleError<'a, $tcx>> {
- Self::try_get_with(tcx, span, key, Clone::clone)
+ -> Result<$V, DiagnosticBuilder<'a>> {
+ match Self::try_get_with(tcx, span, key, Clone::clone) {
+ Ok(e) => Ok(e),
+ Err(e) => Err(tcx.report_cycle(e)),
+ }
}
pub fn force(tcx: TyCtxt<'a, $tcx, 'lcx>, span: Span, key: $K) {
match Self::try_get_with(tcx, span, key, |_| ()) {
Ok(()) => {}
- Err(e) => tcx.report_cycle(e)
+ Err(e) => tcx.report_cycle(e).emit(),
}
}
})*
impl<'a, $tcx, 'lcx> TyCtxtAt<'a, $tcx, 'lcx> {
$($(#[$attr])*
pub fn $name(self, key: $K) -> $V {
- queries::$name::try_get(self.tcx, self.span, key).unwrap_or_else(|e| {
- self.report_cycle(e);
+ queries::$name::try_get(self.tcx, self.span, key).unwrap_or_else(|mut e| {
+ e.emit();
Value::from_cycle_error(self.global_tcx())
})
})*
[] is_allocator: IsAllocator(DefId) -> bool,
[] is_panic_runtime: IsPanicRuntime(DefId) -> bool,
+ [] is_compiler_builtins: IsCompilerBuiltins(DefId) -> bool,
+ [] has_global_allocator: HasGlobalAllocator(DefId) -> bool,
[] extern_crate: ExternCrate(DefId) -> Rc<Option<ExternCrate>>,
pub freevars: FreevarMap,
pub trait_map: TraitMap,
pub maybe_unused_trait_imports: NodeSet,
+ pub maybe_unused_extern_crates: Vec<(NodeId, Span)>,
pub export_map: ExportMap,
}
pub fn sized_constraint(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> &'tcx [Ty<'tcx>] {
match queries::adt_sized_constraint::try_get(tcx, DUMMY_SP, self.did) {
Ok(tys) => tys,
- Err(_) => {
+ Err(mut bug) => {
debug!("adt_sized_constraint: {:?} is recursive", self);
// This should be reported as an error by `check_representable`.
//
// Consider the type as Sized in the meanwhile to avoid
- // further errors.
+ // further errors. Delay our `bug` diagnostic here to get
+ // emitted later as well in case we accidentally otherwise don't
+ // emit an error.
+ bug.delay_as_bug();
tcx.intern_type_list(&[tcx.types.err])
}
}
let needs_drop = |ty: Ty<'tcx>| -> bool {
match ty::queries::needs_drop_raw::try_get(tcx, DUMMY_SP, param_env.and(ty)) {
Ok(v) => v,
- Err(_) => {
+ Err(mut bug) => {
// Cycles should be reported as an error by `check_representable`.
//
- // Consider the type as not needing drop in the meanwhile to avoid
- // further errors.
+ // Consider the type as not needing drop in the meanwhile to
+ // avoid further errors.
+ //
+ // In case we forgot to emit a bug elsewhere, delay our
+ // diagnostic to get emitted as a compiler bug.
+ bug.delay_as_bug();
false
}
}
-> Vec<traits::PredicateObligation<'tcx>>
{
let mut wf = WfPredicates { infcx, param_env, body_id, span, out: vec![] };
- wf.compute_trait_ref(trait_ref);
+ wf.compute_trait_ref(trait_ref, Elaborate::All);
wf.normalize()
}
// (*) ok to skip binders, because wf code is prepared for it
match *predicate {
ty::Predicate::Trait(ref t) => {
- wf.compute_trait_ref(&t.skip_binder().trait_ref); // (*)
+ wf.compute_trait_ref(&t.skip_binder().trait_ref, Elaborate::None); // (*)
}
ty::Predicate::Equate(ref t) => {
wf.compute(t.skip_binder().0);
out: Vec<traits::PredicateObligation<'tcx>>,
}
+/// Controls whether we "elaborate" supertraits and so forth on the WF
+/// predicates. This is a kind of hack to address #43784. The
+/// underlying problem in that issue was a trait structure like:
+///
+/// ```
+/// trait Foo: Copy { }
+/// trait Bar: Foo { }
+/// impl<T: Bar> Foo for T { }
+/// impl<T> Bar for T { }
+/// ```
+///
+/// Here, in the `Foo` impl, we will check that `T: Copy` holds -- but
+/// we decide that this is true because `T: Bar` is in the
+/// where-clauses (and we can elaborate that to include `T:
+/// Copy`). This wouldn't be a problem, except that when we check the
+/// `Bar` impl, we decide that `T: Foo` must hold because of the `Foo`
+/// impl. And so nowhere did we check that `T: Copy` holds!
+///
+/// To resolve this, we elaborate the WF requirements that must be
+/// proven when checking impls. This means that (e.g.) the `impl Bar
+/// for T` will be forced to prove not only that `T: Foo` but also `T:
+/// Copy` (which it won't be able to do, because there is no `Copy`
+/// impl for `T`).
+#[derive(Debug, PartialEq, Eq, Copy, Clone)]
+enum Elaborate {
+ All,
+ None,
+}
+
impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> {
fn cause(&mut self, code: traits::ObligationCauseCode<'tcx>) -> traits::ObligationCause<'tcx> {
traits::ObligationCause::new(self.span, self.body_id, code)
/// Pushes the obligations required for `trait_ref` to be WF into
/// `self.out`.
- fn compute_trait_ref(&mut self, trait_ref: &ty::TraitRef<'tcx>) {
+ fn compute_trait_ref(&mut self, trait_ref: &ty::TraitRef<'tcx>, elaborate: Elaborate) {
let obligations = self.nominal_obligations(trait_ref.def_id, trait_ref.substs);
- self.out.extend(obligations);
let cause = self.cause(traits::MiscObligation);
let param_env = self.param_env;
+
+ if let Elaborate::All = elaborate {
+ let predicates = obligations.iter()
+ .map(|obligation| obligation.predicate.clone())
+ .collect();
+ let implied_obligations = traits::elaborate_predicates(self.infcx.tcx, predicates);
+ let implied_obligations = implied_obligations.map(|pred| {
+ traits::Obligation::new(cause.clone(), param_env, pred)
+ });
+ self.out.extend(implied_obligations);
+ }
+
+ self.out.extend(obligations);
+
self.out.extend(
trait_ref.substs.types()
.filter(|ty| !ty.has_escaping_regions())
// WF and (b) the trait-ref holds. (It may also be
// normalizable and be WF that way.)
let trait_ref = data.trait_ref(self.infcx.tcx);
- self.compute_trait_ref(&trait_ref);
+ self.compute_trait_ref(&trait_ref, Elaborate::None);
if !data.has_escaping_regions() {
let predicate = trait_ref.to_predicate();
use std::path::Path;
use std::time::{Duration, Instant};
+use std::sync::mpsc::{Sender};
+use syntax_pos::{Span};
+use ty::maps::{QueryMsg};
+use dep_graph::{DepNode};
+
// The name of the associated type for `Fn` return types
pub const FN_OUTPUT_NAME: &'static str = "Output";
thread_local!(static TIME_DEPTH: Cell<usize> = Cell::new(0));
+/// Initialized for -Z profile-queries
+thread_local!(static PROFQ_CHAN: RefCell<Option<Sender<ProfileQueriesMsg>>> = RefCell::new(None));
+
+/// Parameters to the `Dump` variant of type `ProfileQueriesMsg`.
+#[derive(Clone,Debug)]
+pub struct ProfQDumpParams {
+ /// A base path for the files we will dump
+ pub path:String,
+ /// To ensure that the compiler waits for us to finish our dumps
+ pub ack:Sender<()>,
+ /// toggle dumping a log file with every `ProfileQueriesMsg`
+ pub dump_profq_msg_log:bool,
+}
+
+/// A sequence of these messages induce a trace of query-based incremental compilation.
+/// FIXME(matthewhammer): Determine whether we should include cycle detection here or not.
+#[derive(Clone,Debug)]
+pub enum ProfileQueriesMsg {
+ /// begin a timed pass
+ TimeBegin(String),
+ /// end a timed pass
+ TimeEnd,
+ /// begin a task (see dep_graph::graph::with_task)
+ TaskBegin(DepNode),
+ /// end a task
+ TaskEnd,
+ /// begin a new query
+ QueryBegin(Span, QueryMsg),
+ /// query is satisfied by using an already-known value for the given key
+ CacheHit,
+ /// query requires running a provider; providers may nest, permitting queries to nest.
+ ProviderBegin,
+ /// query is satisfied by a provider terminating with a value
+ ProviderEnd,
+ /// dump a record of the queries to the given path
+ Dump(ProfQDumpParams),
+ /// halt the profiling/monitoring background thread
+ Halt
+}
+
+/// If enabled, send a message to the profile-queries thread
+pub fn profq_msg(msg: ProfileQueriesMsg) {
+ PROFQ_CHAN.with(|sender|{
+ if let Some(s) = sender.borrow().as_ref() {
+ s.send(msg).unwrap()
+ } else {
+ // Do nothing.
+ //
+ // FIXME(matthewhammer): Multi-threaded translation phase triggers the panic below.
+ // From backtrace: rustc_trans::back::write::spawn_work::{{closure}}.
+ //
+ // panic!("no channel on which to send profq_msg: {:?}", msg)
+ }
+ })
+}
+
+/// Set channel for profile queries channel
+pub fn profq_set_chan(s: Sender<ProfileQueriesMsg>) -> bool {
+ PROFQ_CHAN.with(|chan|{
+ if chan.borrow().is_none() {
+ *chan.borrow_mut() = Some(s);
+ true
+ } else { false }
+ })
+}
+
/// Read the current depth of `time()` calls. This is used to
/// encourage indentation across threads.
pub fn time_depth() -> usize {
r
});
+ if cfg!(debug_assertions) {
+ profq_msg(ProfileQueriesMsg::TimeBegin(what.to_string()))
+ };
let start = Instant::now();
let rv = f();
let dur = start.elapsed();
+ if cfg!(debug_assertions) {
+ profq_msg(ProfileQueriesMsg::TimeEnd)
+ };
print_time_passes_entry_internal(what, dur);
// rem <- sig % 10
// sig <- sig / 10
let mut rem = 0;
- for limb in sig.iter_mut().rev() {
- // We don't have an integer doubly wide than Limb,
- // so we have to split the divrem on two halves.
- const HALF_BITS: usize = LIMB_BITS / 2;
- let mut halves = [*limb & ((1 << HALF_BITS) - 1), *limb >> HALF_BITS];
- for half in halves.iter_mut().rev() {
- *half |= rem << HALF_BITS;
- rem = *half % 10;
- *half /= 10;
- }
- *limb = halves[0] | (halves[1] << HALF_BITS);
- }
+
+ // Use 64-bit division and remainder, with 32-bit chunks from sig.
+ sig::each_chunk(&mut sig, 32, |chunk| {
+ let chunk = chunk as u32;
+ let combined = ((rem as u64) << 32) | (chunk as u64);
+ rem = (combined % 10) as u8;
+ (combined / 10) as u32 as Limb
+ });
+
// Reduce the sigificand to avoid wasting time dividing 0's.
while sig.last() == Some(&0) {
sig.pop();
exp += 1;
} else {
in_trail = false;
- buffer.push(b'0' + digit as u8);
+ buffer.push(b'0' + digit);
}
}
};
// Attempt dec_sig * 10^dec_exp with increasing precision.
- let mut attempt = 1;
+ let mut attempt = 0;
loop {
let calc_precision = (LIMB_BITS << attempt) - 1;
attempt += 1;
limbs.iter().all(|&l| l == 0)
}
+ /// One, not zero, based LSB. That is, returns 0 for a zeroed significand.
+ pub(super) fn olsb(limbs: &[Limb]) -> usize {
+ for i in 0..limbs.len() {
+ if limbs[i] != 0 {
+ return i * LIMB_BITS + limbs[i].trailing_zeros() as usize + 1;
+ }
+ }
+
+ 0
+ }
+
/// One, not zero, based MSB. That is, returns 0 for a zeroed significand.
pub(super) fn omsb(limbs: &[Limb]) -> usize {
for i in (0..limbs.len()).rev() {
}
}
+ /// For every consecutive chunk of `bits` bits from `limbs`,
+ /// going from most significant to the least significant bits,
+ /// call `f` to transform those bits and store the result back.
+ pub(super) fn each_chunk<F: FnMut(Limb) -> Limb>(limbs: &mut [Limb], bits: usize, mut f: F) {
+ assert_eq!(LIMB_BITS % bits, 0);
+ for limb in limbs.iter_mut().rev() {
+ let mut r = 0;
+ for i in (0..LIMB_BITS / bits).rev() {
+ r |= f((*limb >> (i * bits)) & ((1 << bits) - 1)) << (i * bits);
+ }
+ *limb = r;
+ }
+ }
+
/// Increment in-place, return the carry flag.
pub(super) fn increment(dst: &mut [Limb]) -> Limb {
for x in dst {
divisor: &mut [Limb],
precision: usize,
) -> Loss {
- // Zero the quotient before setting bits in it.
- for x in &mut quotient[..limbs_for_bits(precision)] {
- *x = 0;
- }
// Normalize the divisor.
let bits = precision - omsb(divisor);
let bits = precision - omsb(dividend);
shift_left(dividend, exp, bits);
+ // Division by 1.
+ let olsb_divisor = olsb(divisor);
+ if olsb_divisor == precision {
+ quotient.copy_from_slice(dividend);
+ return Loss::ExactlyZero;
+ }
+
// Ensure the dividend >= divisor initially for the loop below.
// Incidentally, this means that the division loop below is
// guaranteed to set the integer bit to one.
assert_ne!(cmp(dividend, divisor), Ordering::Less)
}
+ // Helper for figuring out the lost fraction.
+ let lost_fraction = |dividend: &[Limb], divisor: &[Limb]| {
+ match cmp(dividend, divisor) {
+ Ordering::Greater => Loss::MoreThanHalf,
+ Ordering::Equal => Loss::ExactlyHalf,
+ Ordering::Less => {
+ if is_all_zeros(dividend) {
+ Loss::ExactlyZero
+ } else {
+ Loss::LessThanHalf
+ }
+ }
+ }
+ };
+
+ // Try to perform a (much faster) short division for small divisors.
+ let divisor_bits = precision - (olsb_divisor - 1);
+ macro_rules! try_short_div {
+ ($W:ty, $H:ty, $half:expr) => {
+ if divisor_bits * 2 <= $half {
+ // Extract the small divisor.
+ let _: Loss = shift_right(divisor, &mut 0, olsb_divisor - 1);
+ let divisor = divisor[0] as $H as $W;
+
+ // Shift the dividend to produce a quotient with the unit bit set.
+ let top_limb = *dividend.last().unwrap();
+ let mut rem = (top_limb >> (LIMB_BITS - (divisor_bits - 1))) as $H;
+ shift_left(dividend, &mut 0, divisor_bits - 1);
+
+ // Apply short division in place on $H (of $half bits) chunks.
+ each_chunk(dividend, $half, |chunk| {
+ let chunk = chunk as $H;
+ let combined = ((rem as $W) << $half) | (chunk as $W);
+ rem = (combined % divisor) as $H;
+ (combined / divisor) as $H as Limb
+ });
+ quotient.copy_from_slice(dividend);
+
+ return lost_fraction(&[(rem as Limb) << 1], &[divisor as Limb]);
+ }
+ }
+ }
+
+ try_short_div!(u32, u16, 16);
+ try_short_div!(u64, u32, 32);
+ try_short_div!(u128, u64, 64);
+
+ // Zero the quotient before setting bits in it.
+ for x in &mut quotient[..limbs_for_bits(precision)] {
+ *x = 0;
+ }
+
// Long division.
for bit in (0..precision).rev() {
if cmp(dividend, divisor) != Ordering::Less {
shift_left(dividend, &mut 0, 1);
}
- // Figure out the lost fraction.
- match cmp(dividend, divisor) {
- Ordering::Greater => Loss::MoreThanHalf,
- Ordering::Equal => Loss::ExactlyHalf,
- Ordering::Less => {
- if is_all_zeros(dividend) {
- Loss::ExactlyZero
- } else {
- Loss::LessThanHalf
- }
- }
- }
+ lost_fraction(dividend, divisor)
}
}
//!
//! This API is completely unstable and subject to change.
-#![crate_name = "rustc_apfloat"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
html_root_url = "https://doc.rust-lang.org/nightly/")]
//! one that doesn't; the one that doesn't might get decent parallel
//! build speedups.
-#![crate_name = "rustc_back"]
-#![crate_type = "dylib"]
-#![crate_type = "rlib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
html_root_url = "https://doc.rust-lang.org/nightly/")]
target_family: Some("unix".to_string()),
relro_level: RelroLevel::Full,
linker_is_gnu: true,
- no_integrated_as: true,
.. Default::default()
}
}
use LinkerFlavor;
use target::{LinkArgs, TargetOptions};
use std::default::Default;
+use std::env;
+use std::process::Command;
-pub fn opts() -> TargetOptions {
+// Use GCC to locate code for crt* libraries from the host, not from L4Re. Note
+// that a few files also come from L4Re, for these, the function shouldn't be
+// used. This uses GCC for the location of the file, but GCC is required for L4Re anyway.
+fn get_path_or(filename: &str) -> String {
+ let child = Command::new("gcc")
+ .arg(format!("-print-file-name={}", filename)).output()
+ .expect("Failed to execute GCC");
+ String::from_utf8(child.stdout)
+ .expect("Couldn't read path from GCC").trim().into()
+}
+
+pub fn opts() -> Result<TargetOptions, String> {
+ let l4re_lib_path = env::var_os("L4RE_LIBDIR").ok_or("Unable to find L4Re \
+ library directory: L4RE_LIBDIR not set.")?.into_string().unwrap();
let mut pre_link_args = LinkArgs::new();
pre_link_args.insert(LinkerFlavor::Ld, vec![
- "-nostdlib".to_string(),
+ format!("-T{}/main_stat.ld", l4re_lib_path),
+ "--defsym=__executable_start=0x01000000".to_string(),
+ "--defsym=__L4_KIP_ADDR__=0x6ffff000".to_string(),
+ format!("{}/crt1.o", l4re_lib_path),
+ format!("{}/crti.o", l4re_lib_path),
+ get_path_or("crtbeginT.o"),
+ ]);
+ let mut post_link_args = LinkArgs::new();
+ post_link_args.insert(LinkerFlavor::Ld, vec![
+ format!("{}/l4f/libpthread.a", l4re_lib_path),
+ format!("{}/l4f/libc_be_sig.a", l4re_lib_path),
+ format!("{}/l4f/libc_be_sig_noop.a", l4re_lib_path),
+ format!("{}/l4f/libc_be_socket_noop.a", l4re_lib_path),
+ format!("{}/l4f/libc_be_fs_noop.a", l4re_lib_path),
+ format!("{}/l4f/libc_be_sem_noop.a", l4re_lib_path),
+ format!("{}/l4f/libl4re-vfs.o.a", l4re_lib_path),
+ format!("{}/l4f/lib4re.a", l4re_lib_path),
+ format!("{}/l4f/lib4re-util.a", l4re_lib_path),
+ format!("{}/l4f/libc_support_misc.a", l4re_lib_path),
+ format!("{}/l4f/libsupc++.a", l4re_lib_path),
+ format!("{}/l4f/lib4shmc.a", l4re_lib_path),
+ format!("{}/l4f/lib4re-c.a", l4re_lib_path),
+ format!("{}/l4f/lib4re-c-util.a", l4re_lib_path),
+ get_path_or("libgcc_eh.a"),
+ format!("{}/l4f/libdl.a", l4re_lib_path),
+ "--start-group".to_string(),
+ format!("{}/l4f/libl4util.a", l4re_lib_path),
+ format!("{}/l4f/libc_be_l4re.a", l4re_lib_path),
+ format!("{}/l4f/libuc_c.a", l4re_lib_path),
+ format!("{}/l4f/libc_be_l4refile.a", l4re_lib_path),
+ "--end-group".to_string(),
+ format!("{}/l4f/libl4sys.a", l4re_lib_path),
+ "-gc-sections".to_string(),
+ get_path_or("crtend.o"),
+ format!("{}/crtn.o", l4re_lib_path),
]);
- TargetOptions {
+ Ok(TargetOptions {
executables: true,
has_elf_tls: false,
- exe_allocation_crate: Some("alloc_system".to_string()),
+ exe_allocation_crate: None,
panic_strategy: PanicStrategy::Abort,
linker: "ld".to_string(),
pre_link_args,
+ post_link_args,
target_family: Some("unix".to_string()),
.. Default::default()
- }
+ })
}
use target::{Target, TargetResult};
pub fn target() -> TargetResult {
- let mut base = super::l4re_base::opts();
+ let mut base = super::l4re_base::opts()?;
base.cpu = "x86-64".to_string();
base.max_atomic_width = Some(64);
// except according to those terms.
-#![crate_name = "rustc_bitflags"]
-#![crate_type = "rlib"]
#![no_std]
#![deny(warnings)]
syntax_pos = { path = "../libsyntax_pos" }
graphviz = { path = "../libgraphviz" }
rustc = { path = "../librustc" }
-rustc_data_structures = { path = "../librustc_data_structures" }
rustc_mir = { path = "../librustc_mir" }
rustc_errors = { path = "../librustc_errors" }
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![crate_name = "rustc_borrowck"]
-#![crate_type = "dylib"]
-#![crate_type = "rlib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
html_root_url = "https://doc.rust-lang.org/nightly/")]
extern crate graphviz as dot;
#[macro_use]
extern crate rustc;
-extern crate rustc_data_structures;
extern crate rustc_mir;
-extern crate core; // for NonZero
pub use borrowck::check_crate;
pub use borrowck::build_borrowck_dataflow_data_for_fn;
//!
//! This API is completely unstable and subject to change.
-#![crate_name = "rustc_const_eval"]
-#![crate_type = "dylib"]
-#![crate_type = "rlib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
html_root_url = "https://doc.rust-lang.org/nightly/")]
//!
//! This API is completely unstable and subject to change.
-#![crate_name = "rustc_const_math"]
-#![crate_type = "dylib"]
-#![crate_type = "rlib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
html_root_url = "https://doc.rust-lang.org/nightly/")]
//!
//! This API is completely unstable and subject to change.
-#![crate_name = "rustc_data_structures"]
-#![crate_type = "dylib"]
-#![crate_type = "rlib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
html_favicon_url = "https://www.rust-lang.org/favicon.ico",
html_root_url = "https://doc.rust-lang.org/nightly/")]
use derive_registrar;
+use profile;
+
pub fn compile_input(sess: &Session,
cstore: &CStore,
input: &Input,
sess.abort_if_errors();
}
+ if sess.profile_queries() {
+ profile::begin();
+ }
+
// We need nested scopes here, because the intermediate results can keep
// large chunks of memory alive and we want to free them as soon as
// possible to keep the peak memory usage low
-> PResult<'a, ast::Crate> {
sess.diagnostic().set_continue_after_error(control.continue_parse_after_error);
+ if sess.profile_queries() {
+ profile::begin();
+ }
+
let krate = time(sess.time_passes(), "parsing", || {
match *input {
Input::File(ref file) => {
})
})?;
- time(time_passes,
- "early lint checks",
- || lint::check_ast_crate(sess, &krate));
-
// Lower ast -> hir.
let hir_forest = time(time_passes, "lowering ast -> hir", || {
let hir_crate = lower_crate(sess, &krate, &mut resolver);
hir_map::Forest::new(hir_crate, &sess.dep_graph)
});
+ time(time_passes,
+ "early lint checks",
+ || lint::check_ast_crate(sess, &krate));
+
// Discard hygiene data, which isn't required after lowering to HIR.
if !keep_hygiene_data(sess) {
syntax::ext::hygiene::clear_markings();
export_map: resolver.export_map,
trait_map: resolver.trait_map,
maybe_unused_trait_imports: resolver.maybe_unused_trait_imports,
+ maybe_unused_extern_crates: resolver.maybe_unused_extern_crates,
},
hir_forest,
})
"translation",
move || trans::trans_crate(tcx, analysis, incremental_hashes_map, output_filenames));
+ if tcx.sess.profile_queries() {
+ profile::dump("profile_queries".to_string())
+ }
+
translation
}
//!
//! This API is completely unstable and subject to change.
-#![crate_name = "rustc_driver"]
-#![crate_type = "dylib"]
-#![crate_type = "rlib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
html_root_url = "https://doc.rust-lang.org/nightly/")]
#![deny(warnings)]
#![feature(box_syntax)]
-#![feature(libc)]
+#![cfg_attr(unix, feature(libc))]
#![feature(quote)]
#![feature(rustc_diagnostic_macros)]
#![feature(set_stdio)]
extern crate getopts;
extern crate graphviz;
extern crate env_logger;
+#[cfg(unix)]
extern crate libc;
extern crate rustc;
extern crate rustc_allocator;
#[cfg(test)]
mod test;
+pub mod profile;
pub mod driver;
pub mod pretty;
pub mod target_features;
--- /dev/null
+// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use rustc::util::common::{ProfQDumpParams, ProfileQueriesMsg, profq_msg, profq_set_chan};
+use std::sync::mpsc::{Receiver};
+use std::io::{Write};
+use rustc::dep_graph::{DepNode};
+use std::time::{Duration, Instant};
+
+pub mod trace;
+
+/// begin a profile thread, if not already running
+pub fn begin() {
+ use std::thread;
+ use std::sync::mpsc::{channel};
+ let (tx, rx) = channel();
+ if profq_set_chan(tx) {
+ thread::spawn(move||profile_queries_thread(rx));
+ }
+}
+
+/// dump files with profiling information to the given base path, and
+/// wait for this dump to complete.
+///
+/// wraps the RPC (send/recv channel logic) of requesting a dump.
+pub fn dump(path:String) {
+ use std::sync::mpsc::{channel};
+ let (tx, rx) = channel();
+ let params = ProfQDumpParams{
+ path, ack:tx,
+ // FIXME: Add another compiler flag to toggle whether this log
+ // is written; false for now
+ dump_profq_msg_log:true,
+ };
+ profq_msg(ProfileQueriesMsg::Dump(params));
+ let _ = rx.recv().unwrap();
+}
+
+// State for parsing recursive trace structure in separate thread, via messages
+#[derive(Clone, Eq, PartialEq)]
+enum ParseState {
+ // No (local) parse state; may be parsing a tree, focused on a
+ // sub-tree that could be anything.
+ Clear,
+ // Have Query information from the last message
+ HaveQuery(trace::Query, Instant),
+ // Have "time-begin" information from the last message (doit flag, and message)
+ HaveTimeBegin(String, Instant),
+ // Have "task-begin" information from the last message
+ HaveTaskBegin(DepNode, Instant),
+}
+struct StackFrame {
+ pub parse_st: ParseState,
+ pub traces: Vec<trace::Rec>,
+}
+
+fn total_duration(traces: &Vec<trace::Rec>) -> Duration {
+ let mut sum : Duration = Duration::new(0,0);
+ for t in traces.iter() { sum += t.dur_total; }
+ return sum
+}
+
+// profiling thread; retains state (in local variables) and dump traces, upon request.
+fn profile_queries_thread(r:Receiver<ProfileQueriesMsg>) {
+ use self::trace::*;
+ use std::fs::File;
+ use std::time::{Instant};
+
+ let mut profq_msgs : Vec<ProfileQueriesMsg> = vec![];
+ let mut frame : StackFrame = StackFrame{ parse_st:ParseState::Clear, traces:vec![] };
+ let mut stack : Vec<StackFrame> = vec![];
+ loop {
+ let msg = r.recv();
+ if let Err(_recv_err) = msg {
+ // FIXME: Perhaps do something smarter than simply quitting?
+ break
+ };
+ let msg = msg.unwrap();
+ debug!("profile_queries_thread: {:?}", msg);
+
+ // Meta-level versus _actual_ queries messages
+ match msg {
+ ProfileQueriesMsg::Halt => return,
+ ProfileQueriesMsg::Dump(params) => {
+ assert!(stack.len() == 0);
+ assert!(frame.parse_st == ParseState::Clear);
+ {
+ // write log of all messages
+ if params.dump_profq_msg_log {
+ let mut log_file =
+ File::create(format!("{}.log.txt", params.path)).unwrap();
+ for m in profq_msgs.iter() {
+ writeln!(&mut log_file, "{:?}", m).unwrap()
+ };
+ }
+
+ // write HTML file, and counts file
+ let html_path = format!("{}.html", params.path);
+ let mut html_file = File::create(&html_path).unwrap();
+
+ let counts_path = format!("{}.counts.txt", params.path);
+ let mut counts_file = File::create(&counts_path).unwrap();
+
+ write!(html_file, "<html>\n").unwrap();
+ write!(html_file,
+ "<head>\n<link rel=\"stylesheet\" type=\"text/css\" href=\"{}\">\n",
+ "profile_queries.css").unwrap();
+ write!(html_file, "<style>\n").unwrap();
+ trace::write_style(&mut html_file);
+ write!(html_file, "</style>\n").unwrap();
+ write!(html_file, "</head>\n").unwrap();
+ write!(html_file, "<body>\n").unwrap();
+ trace::write_traces(&mut html_file, &mut counts_file, &frame.traces);
+ write!(html_file, "</body>\n</html>\n").unwrap();
+
+ let ack_path = format!("{}.ack", params.path);
+ let ack_file = File::create(&ack_path).unwrap();
+ drop(ack_file);
+
+ // Tell main thread that we are done, e.g., so it can exit
+ params.ack.send(()).unwrap();
+ }
+ continue
+ }
+ // Actual query message:
+ msg => {
+ // Record msg in our log
+ profq_msgs.push(msg.clone());
+ // Respond to the message, knowing that we've already handled Halt and Dump, above.
+ match (frame.parse_st.clone(), msg) {
+ (_,ProfileQueriesMsg::Halt) => unreachable!(),
+ (_,ProfileQueriesMsg::Dump(_)) => unreachable!(),
+
+ // Parse State: Clear
+ (ParseState::Clear,
+ ProfileQueriesMsg::QueryBegin(span,querymsg)) => {
+ let start = Instant::now();
+ frame.parse_st = ParseState::HaveQuery
+ (Query{span:span, msg:querymsg}, start)
+ },
+ (ParseState::Clear,
+ ProfileQueriesMsg::CacheHit) => {
+ panic!("parse error: unexpected CacheHit; expected QueryBegin")
+ },
+ (ParseState::Clear,
+ ProfileQueriesMsg::ProviderBegin) => {
+ panic!("parse error: expected QueryBegin before beginning a provider")
+ },
+ (ParseState::Clear,
+ ProfileQueriesMsg::ProviderEnd) => {
+ let provider_extent = frame.traces;
+ match stack.pop() {
+ None =>
+ panic!("parse error: expected a stack frame; found an empty stack"),
+ Some(old_frame) => {
+ match old_frame.parse_st {
+ ParseState::HaveQuery(q, start) => {
+ let duration = start.elapsed();
+ frame = StackFrame{
+ parse_st:ParseState::Clear,
+ traces:old_frame.traces
+ };
+ let dur_extent = total_duration(&provider_extent);
+ let trace = Rec {
+ effect: Effect::QueryBegin(q, CacheCase::Miss),
+ extent: Box::new(provider_extent),
+ start: start,
+ dur_self: duration - dur_extent,
+ dur_total: duration,
+ };
+ frame.traces.push( trace );
+ },
+ _ => panic!("internal parse error: malformed parse stack")
+ }
+ }
+ }
+ },
+
+
+ (ParseState::Clear,
+ ProfileQueriesMsg::TimeBegin(msg)) => {
+ let start = Instant::now();
+ frame.parse_st = ParseState::HaveTimeBegin(msg, start);
+ stack.push(frame);
+ frame = StackFrame{parse_st:ParseState::Clear, traces:vec![]};
+ },
+ (_, ProfileQueriesMsg::TimeBegin(_)) =>
+ panic!("parse error; did not expect time begin here"),
+
+ (ParseState::Clear,
+ ProfileQueriesMsg::TimeEnd) => {
+ let provider_extent = frame.traces;
+ match stack.pop() {
+ None =>
+ panic!("parse error: expected a stack frame; found an empty stack"),
+ Some(old_frame) => {
+ match old_frame.parse_st {
+ ParseState::HaveTimeBegin(msg, start) => {
+ let duration = start.elapsed();
+ frame = StackFrame{
+ parse_st:ParseState::Clear,
+ traces:old_frame.traces
+ };
+ let dur_extent = total_duration(&provider_extent);
+ let trace = Rec {
+ effect: Effect::TimeBegin(msg),
+ extent: Box::new(provider_extent),
+ start: start,
+ dur_total: duration,
+ dur_self: duration - dur_extent,
+ };
+ frame.traces.push( trace );
+ },
+ _ => panic!("internal parse error: malformed parse stack")
+ }
+ }
+ }
+ },
+ (_, ProfileQueriesMsg::TimeEnd) => { panic!("parse error") }
+
+ (ParseState::Clear,
+ ProfileQueriesMsg::TaskBegin(key)) => {
+ let start = Instant::now();
+ frame.parse_st = ParseState::HaveTaskBegin(key, start);
+ stack.push(frame);
+ frame = StackFrame{parse_st:ParseState::Clear, traces:vec![]};
+ },
+ (_, ProfileQueriesMsg::TaskBegin(_)) =>
+ panic!("parse error; did not expect time begin here"),
+
+ (ParseState::Clear,
+ ProfileQueriesMsg::TaskEnd) => {
+ let provider_extent = frame.traces;
+ match stack.pop() {
+ None =>
+ panic!("parse error: expected a stack frame; found an empty stack"),
+ Some(old_frame) => {
+ match old_frame.parse_st {
+ ParseState::HaveTaskBegin(key, start) => {
+ let duration = start.elapsed();
+ frame = StackFrame{
+ parse_st:ParseState::Clear,
+ traces:old_frame.traces
+ };
+ let dur_extent = total_duration(&provider_extent);
+ let trace = Rec {
+ effect: Effect::TaskBegin(key),
+ extent: Box::new(provider_extent),
+ start: start,
+ dur_total: duration,
+ dur_self: duration - dur_extent,
+ };
+ frame.traces.push( trace );
+ },
+ _ => panic!("internal parse error: malformed parse stack")
+ }
+ }
+ }
+ },
+ (_, ProfileQueriesMsg::TaskEnd) => { panic!("parse error") }
+
+ // Parse State: HaveQuery
+ (ParseState::HaveQuery(q,start),
+ ProfileQueriesMsg::CacheHit) => {
+ let duration = start.elapsed();
+ let trace : Rec = Rec{
+ effect: Effect::QueryBegin(q, CacheCase::Hit),
+ extent: Box::new(vec![]),
+ start: start,
+ dur_self: duration,
+ dur_total: duration,
+ };
+ frame.traces.push( trace );
+ frame.parse_st = ParseState::Clear;
+ },
+ (ParseState::HaveQuery(_,_),
+ ProfileQueriesMsg::ProviderBegin) => {
+ stack.push(frame);
+ frame = StackFrame{parse_st:ParseState::Clear, traces:vec![]};
+ },
+
+ //
+ //
+ // Parse errors:
+
+ (ParseState::HaveQuery(q,_),
+ ProfileQueriesMsg::ProviderEnd) => {
+ panic!("parse error: unexpected ProviderEnd; \
+ expected something else to follow BeginQuery for {:?}", q)
+ },
+ (ParseState::HaveQuery(q1,_),
+ ProfileQueriesMsg::QueryBegin(span2,querymsg2)) => {
+ panic!("parse error: unexpected QueryBegin; \
+ earlier query is unfinished: {:?} and now {:?}",
+ q1, Query{span:span2, msg:querymsg2})
+ },
+
+ (ParseState::HaveTimeBegin(_, _), _) => {
+ unreachable!()
+ },
+ (ParseState::HaveTaskBegin(_, _), _) => {
+ unreachable!()
+ },
+ }
+
+ }
+ }
+ }
+}
--- /dev/null
+// Copyright 2012-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 super::*;
+use syntax_pos::Span;
+use rustc::ty::maps::QueryMsg;
+use std::fs::File;
+use std::time::{Duration, Instant};
+use std::collections::hash_map::HashMap;
+use rustc::dep_graph::{DepNode};
+
+#[derive(Debug, Clone, Eq, PartialEq)]
+pub struct Query {
+ pub span: Span,
+ pub msg: QueryMsg,
+}
+pub enum Effect {
+ QueryBegin(Query, CacheCase),
+ TimeBegin(String),
+ TaskBegin(DepNode),
+}
+pub enum CacheCase {
+ Hit, Miss
+}
+/// Recursive trace structure
+pub struct Rec {
+ pub effect: Effect,
+ pub start: Instant,
+ pub dur_self: Duration,
+ pub dur_total: Duration,
+ pub extent: Box<Vec<Rec>>,
+}
+pub struct QueryMetric {
+ pub count: usize,
+ pub dur_self: Duration,
+ pub dur_total: Duration,
+}
+
+pub fn cons_of_query_msg(q: &trace::Query) -> String {
+ let s = format!("{:?}", q.msg);
+ let cons: Vec<&str> = s.split(|d| d == '(' || d == '{').collect();
+ assert!(cons.len() > 0 && cons[0] != "");
+ cons[0].to_string()
+}
+
+pub fn cons_of_key(k: &DepNode) -> String {
+ let s = format!("{:?}", k);
+ let cons: Vec<&str> = s.split(|d| d == '(' || d == '{').collect();
+ assert!(cons.len() > 0 && cons[0] != "");
+ cons[0].to_string()
+}
+
+// First return value is text; second return value is a CSS class
+pub fn html_of_effect(eff: &Effect) -> (String, String) {
+ match *eff {
+ Effect::TimeBegin(ref msg) => {
+ (msg.clone(),
+ format!("time-begin"))
+ },
+ Effect::TaskBegin(ref key) => {
+ let cons = cons_of_key(key);
+ (cons.clone(), format!("{} task-begin", cons))
+ },
+ Effect::QueryBegin(ref qmsg, ref cc) => {
+ let cons = cons_of_query_msg(qmsg);
+ (cons.clone(),
+ format!("{} {}",
+ cons,
+ match *cc {
+ CacheCase::Hit => "hit",
+ CacheCase::Miss => "miss",
+ }))
+ }
+ }
+}
+
+// First return value is text; second return value is a CSS class
+fn html_of_duration(_start: &Instant, dur: &Duration) -> (String, String) {
+ use rustc::util::common::duration_to_secs_str;
+ (duration_to_secs_str(dur.clone()),
+ "".to_string()
+ )
+}
+
+fn html_of_fraction(frac: f64) -> (String, String) {
+ let css = {
+ if frac > 0.50 { format!("frac-50") }
+ else if frac > 0.40 { format!("frac-40") }
+ else if frac > 0.30 { format!("frac-30") }
+ else if frac > 0.20 { format!("frac-20") }
+ else if frac > 0.10 { format!("frac-10") }
+ else if frac > 0.05 { format!("frac-05") }
+ else if frac > 0.02 { format!("frac-02") }
+ else if frac > 0.01 { format!("frac-01") }
+ else if frac > 0.001 { format!("frac-001") }
+ else { format!("frac-0") }
+ };
+ let percent = frac * 100.0;
+ if percent > 0.1 { (format!("{:.1}%", percent), css) }
+ else { (format!("< 0.1%", ), css) }
+}
+
+fn total_duration(traces: &Vec<Rec>) -> Duration {
+ let mut sum : Duration = Duration::new(0,0);
+ for t in traces.iter() {
+ sum += t.dur_total;
+ }
+ return sum
+}
+
+fn duration_div(nom: Duration, den: Duration) -> f64 {
+ fn to_nanos(d: Duration) -> u64 {
+ d.as_secs() * 1_000_000_000 + d.subsec_nanos() as u64
+ }
+
+ to_nanos(nom) as f64 / to_nanos(den) as f64
+}
+
+fn write_traces_rec(file: &mut File, traces: &Vec<Rec>, total: Duration, depth: usize) {
+ for t in traces {
+ let (eff_text, eff_css_classes) = html_of_effect(&t.effect);
+ let (dur_text, dur_css_classes) = html_of_duration(&t.start, &t.dur_total);
+ let fraction = duration_div(t.dur_total, total);
+ let percent = fraction * 100.0;
+ let (frc_text, frc_css_classes) = html_of_fraction(fraction);
+ write!(file, "<div class=\"trace depth-{} extent-{}{} {} {} {}\">\n",
+ depth,
+ t.extent.len(),
+ /* Heuristic for 'important' CSS class: */
+ if t.extent.len() > 5 || percent >= 1.0 {
+ " important" }
+ else { "" },
+ eff_css_classes,
+ dur_css_classes,
+ frc_css_classes,
+ ).unwrap();
+ write!(file, "<div class=\"eff\">{}</div>\n", eff_text).unwrap();
+ write!(file, "<div class=\"dur\">{}</div>\n", dur_text).unwrap();
+ write!(file, "<div class=\"frc\">{}</div>\n", frc_text).unwrap();
+ write_traces_rec(file, &t.extent, total, depth + 1);
+ write!(file, "</div>\n").unwrap();
+ }
+}
+
+fn compute_counts_rec(counts: &mut HashMap<String,QueryMetric>, traces: &Vec<Rec>) {
+ for t in traces.iter() {
+ match t.effect {
+ Effect::TimeBegin(ref msg) => {
+ let qm = match counts.get(msg) {
+ Some(_qm) => { panic!("TimeBegin with non-unique, repeat message") }
+ None => QueryMetric{
+ count: 1,
+ dur_self: t.dur_self,
+ dur_total: t.dur_total,
+ }};
+ counts.insert(msg.clone(), qm);
+ },
+ Effect::TaskBegin(ref key) => {
+ let cons = cons_of_key(key);
+ let qm = match counts.get(&cons) {
+ Some(qm) =>
+ QueryMetric{
+ count: qm.count + 1,
+ dur_self: qm.dur_self + t.dur_self,
+ dur_total: qm.dur_total + t.dur_total,
+ },
+ None => QueryMetric{
+ count: 1,
+ dur_self: t.dur_self,
+ dur_total: t.dur_total,
+ }};
+ counts.insert(cons, qm);
+ },
+ Effect::QueryBegin(ref qmsg, ref _cc) => {
+ let qcons = cons_of_query_msg(qmsg);
+ let qm = match counts.get(&qcons) {
+ Some(qm) =>
+ QueryMetric{
+ count: qm.count + 1,
+ dur_total: qm.dur_total + t.dur_total,
+ dur_self: qm.dur_self + t.dur_self
+ },
+ None => QueryMetric{
+ count: 1,
+ dur_total: t.dur_total,
+ dur_self: t.dur_self,
+ }
+ };
+ counts.insert(qcons, qm);
+ }
+ }
+ compute_counts_rec(counts, &t.extent)
+ }
+}
+
+pub fn write_counts(count_file: &mut File, counts: &mut HashMap<String,QueryMetric>) {
+ use rustc::util::common::duration_to_secs_str;
+ use std::cmp::Ordering;
+
+ let mut data = vec![];
+ for (ref cons, ref qm) in counts.iter() {
+ data.push((cons.clone(), qm.count.clone(), qm.dur_total.clone(), qm.dur_self.clone()));
+ };
+ data.sort_by(|&(_,_,_,self1),&(_,_,_,self2)|
+ if self1 > self2 { Ordering::Less } else { Ordering::Greater } );
+ for (cons, count, dur_total, dur_self) in data {
+ write!(count_file, "{}, {}, {}, {}\n",
+ cons, count,
+ duration_to_secs_str(dur_total),
+ duration_to_secs_str(dur_self)
+ ).unwrap();
+ }
+}
+
+pub fn write_traces(html_file: &mut File, counts_file: &mut File, traces: &Vec<Rec>) {
+ let mut counts : HashMap<String,QueryMetric> = HashMap::new();
+ compute_counts_rec(&mut counts, traces);
+ write_counts(counts_file, &mut counts);
+
+ let total : Duration = total_duration(traces);
+ write_traces_rec(html_file, traces, total, 0)
+}
+
+pub fn write_style(html_file: &mut File) {
+ write!(html_file,"{}", "
+body {
+ font-family: sans-serif;
+ background: black;
+}
+.trace {
+ color: black;
+ display: inline-block;
+ border-style: solid;
+ border-color: red;
+ border-width: 1px;
+ border-radius: 5px;
+ padding: 0px;
+ margin: 1px;
+ font-size: 0px;
+}
+.task-begin {
+ border-width: 1px;
+ color: white;
+ border-color: #ff8;
+ font-size: 0px;
+}
+.miss {
+ border-color: red;
+ border-width: 1px;
+}
+.extent-0 {
+ padding: 2px;
+}
+.time-begin {
+ border-width: 4px;
+ font-size: 12px;
+ color: white;
+ border-color: #afa;
+}
+.important {
+ border-width: 3px;
+ font-size: 12px;
+ color: white;
+ border-color: #f77;
+}
+.hit {
+ padding: 0px;
+ border-color: blue;
+ border-width: 3px;
+}
+.eff {
+ color: #fff;
+ display: inline-block;
+}
+.frc {
+ color: #7f7;
+ display: inline-block;
+}
+.dur {
+ display: none
+}
+.frac-50 {
+ padding: 10px;
+ border-width: 10px;
+ font-size: 32px;
+}
+.frac-40 {
+ padding: 8px;
+ border-width: 8px;
+ font-size: 24px;
+}
+.frac-30 {
+ padding: 6px;
+ border-width: 6px;
+ font-size: 18px;
+}
+.frac-20 {
+ padding: 4px;
+ border-width: 6px;
+ font-size: 16px;
+}
+.frac-10 {
+ padding: 2px;
+ border-width: 6px;
+ font-size: 14px;
+}
+").unwrap();
+}
}
};
- self.handler.emitter.borrow_mut().emit(&self);
+ self.handler.emit_db(&self);
self.cancel();
if is_error {
// }
}
+ /// Delay emission of this diagnostic as a bug.
+ ///
+ /// This can be useful in contexts where an error indicates a bug but
+ /// typically this only happens when other compilation errors have already
+ /// happened. In those cases this can be used to defer emission of this
+ /// diagnostic as a bug in the compiler only if no other errors have been
+ /// emitted.
+ ///
+ /// In the meantime, though, callsites are required to deal with the "bug"
+ /// locally in whichever way makes the most sense.
+ pub fn delay_as_bug(&mut self) {
+ self.level = Level::Bug;
+ *self.handler.delayed_span_bug.borrow_mut() = Some(self.diagnostic.clone());
+ self.cancel();
+ }
+
/// Add a span/label to be included in the resulting snippet.
/// This is pushed onto the `MultiSpan` that was created when the
/// diagnostic was first built. If you don't call this function at
code: Option<String>,
message: &str)
-> DiagnosticBuilder<'a> {
- DiagnosticBuilder {
- handler,
- diagnostic: Diagnostic::new_with_code(level, code, message)
- }
+ let diagnostic = Diagnostic::new_with_code(level, code, message);
+ DiagnosticBuilder::new_diagnostic(handler, diagnostic)
+ }
+
+ /// Creates a new `DiagnosticBuilder` with an already constructed
+ /// diagnostic.
+ pub fn new_diagnostic(handler: &'a Handler, diagnostic: Diagnostic)
+ -> DiagnosticBuilder<'a> {
+ DiagnosticBuilder { handler, diagnostic }
}
}
if line.annotations.len() == 1 {
if let Some(ref ann) = line.annotations.get(0) {
if let AnnotationType::MultilineStart(depth) = ann.annotation_type {
- if source_string[0..ann.start_col].trim() == "" {
+ if source_string.chars()
+ .take(ann.start_col)
+ .all(|c| c.is_whitespace()) {
let style = if ann.is_primary {
Style::UnderlinePrimary
} else {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![crate_name = "rustc_errors"]
-#![crate_type = "dylib"]
-#![crate_type = "rlib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
html_root_url = "https://doc.rust-lang.org/nightly/")]
#![feature(custom_attribute)]
#![allow(unused_attributes)]
#![feature(range_contains)]
-#![feature(libc)]
+#![cfg_attr(unix, feature(libc))]
#![feature(conservative_impl_trait)]
extern crate term;
+#[cfg(unix)]
extern crate libc;
extern crate serialize as rustc_serialize;
extern crate syntax_pos;
use std::borrow::Cow;
use std::cell::{RefCell, Cell};
-use std::{error, fmt};
+use std::mem;
use std::rc::Rc;
+use std::{error, fmt};
mod diagnostic;
mod diagnostic_builder;
pub can_emit_warnings: bool,
treat_err_as_bug: bool,
continue_after_error: Cell<bool>,
- delayed_span_bug: RefCell<Option<(MultiSpan, String)>>,
+ delayed_span_bug: RefCell<Option<Diagnostic>>,
+ tracked_diagnostics: RefCell<Option<Vec<Diagnostic>>>,
}
impl Handler {
treat_err_as_bug,
continue_after_error: Cell::new(true),
delayed_span_bug: RefCell::new(None),
+ tracked_diagnostics: RefCell::new(None),
}
}
if self.treat_err_as_bug {
self.span_bug(sp, msg);
}
- let mut delayed = self.delayed_span_bug.borrow_mut();
- *delayed = Some((sp.into(), msg.to_string()));
+ let mut diagnostic = Diagnostic::new(Level::Bug, msg);
+ diagnostic.set_span(sp.into());
+ *self.delayed_span_bug.borrow_mut() = Some(diagnostic);
}
pub fn span_bug_no_panic<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
self.emit(&sp.into(), msg, Bug);
let s;
match self.err_count.get() {
0 => {
- let delayed_bug = self.delayed_span_bug.borrow();
- match *delayed_bug {
- Some((ref span, ref errmsg)) => {
- self.span_bug(span.clone(), errmsg);
- }
- _ => {}
+ if let Some(bug) = self.delayed_span_bug.borrow_mut().take() {
+ DiagnosticBuilder::new_diagnostic(self, bug).emit();
}
-
return;
}
1 => s = "aborting due to previous error".to_string(),
self.abort_if_errors();
}
}
+
+ pub fn track_diagnostics<F, R>(&self, f: F) -> (R, Vec<Diagnostic>)
+ where F: FnOnce() -> R
+ {
+ let prev = mem::replace(&mut *self.tracked_diagnostics.borrow_mut(),
+ Some(Vec::new()));
+ let ret = f();
+ let diagnostics = mem::replace(&mut *self.tracked_diagnostics.borrow_mut(), prev)
+ .unwrap();
+ (ret, diagnostics)
+ }
+
+ fn emit_db(&self, db: &DiagnosticBuilder) {
+ if let Some(ref mut list) = *self.tracked_diagnostics.borrow_mut() {
+ list.push((**db).clone());
+ }
+ self.emitter.borrow_mut().emit(db);
+ }
}
//! Support for serializing the dep-graph and reloading it.
-#![crate_name = "rustc_incremental"]
-#![crate_type = "dylib"]
-#![crate_type = "rlib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
html_root_url = "https://doc.rust-lang.org/nightly/")]
//!
//! This API is completely unstable and subject to change.
-#![crate_name = "rustc_lint"]
-#![crate_type = "dylib"]
-#![crate_type = "rlib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
html_root_url = "https://doc.rust-lang.org/nightly/")]
};
let mut fn_warned = false;
- let maybe_def = match expr.node {
- hir::ExprCall(ref callee, _) => {
- match callee.node {
- hir::ExprPath(ref qpath) => Some(cx.tables.qpath_def(qpath, callee.hir_id)),
- _ => None
- }
- },
- hir::ExprMethodCall(..) => {
- cx.tables.type_dependent_defs().get(expr.hir_id).cloned()
- },
- _ => { None }
- };
- if let Some(def) = maybe_def {
- let def_id = def.def_id();
- fn_warned = check_must_use(cx, def_id, s.span, "return value of ");
+ if cx.tcx.sess.features.borrow().fn_must_use {
+ let maybe_def = match expr.node {
+ hir::ExprCall(ref callee, _) => {
+ match callee.node {
+ hir::ExprPath(ref qpath) => {
+ Some(cx.tables.qpath_def(qpath, callee.hir_id))
+ },
+ _ => None
+ }
+ },
+ hir::ExprMethodCall(..) => {
+ cx.tables.type_dependent_defs().get(expr.hir_id).cloned()
+ },
+ _ => None
+ };
+ if let Some(def) = maybe_def {
+ let def_id = def.def_id();
+ fn_warned = check_must_use(cx, def_id, s.span, "return value of ");
+ }
}
if !(ty_warned || fn_warned) {
#![allow(non_snake_case)]
#![allow(dead_code)]
-#![crate_name = "rustc_llvm"]
-#![crate_type = "dylib"]
-#![crate_type = "rlib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
html_root_url = "https://doc.rust-lang.org/nightly/")]
proc_macro = { path = "../libproc_macro" }
rustc = { path = "../librustc" }
rustc_back = { path = "../librustc_back" }
-rustc_const_math = { path = "../librustc_const_math" }
rustc_data_structures = { path = "../librustc_data_structures" }
rustc_errors = { path = "../librustc_errors" }
serialize = { path = "../libserialize" }
dylib_dependency_formats => { Rc::new(cdata.get_dylib_dependency_formats(&tcx.dep_graph)) }
is_panic_runtime => { cdata.is_panic_runtime(&tcx.dep_graph) }
+ is_compiler_builtins => { cdata.is_compiler_builtins(&tcx.dep_graph) }
+ has_global_allocator => { cdata.has_global_allocator(&tcx.dep_graph) }
extern_crate => { Rc::new(cdata.extern_crate.get()) }
}
if def_key.disambiguated_data.data == DefPathData::StructCtor {
item = self.entry(def_key.parent.unwrap());
}
- let result = Rc::__from_array(self.get_attributes(&item).into_boxed_slice());
+ let result: Rc<[ast::Attribute]> = Rc::from(self.get_attributes(&item));
let vec_ = &mut self.attribute_cache.borrow_mut()[node_as];
if vec_.len() < node_index + 1 {
vec_.resize(node_index + 1, None);
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![crate_name = "rustc_metadata"]
-#![crate_type = "dylib"]
-#![crate_type = "rlib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
html_root_url = "https://doc.rust-lang.org/nightly/")]
#[macro_use]
extern crate rustc;
extern crate rustc_back;
-extern crate rustc_const_math;
extern crate rustc_data_structures;
mod diagnostics;
// We have to eagerly translate the "spine" of the statements
// in order to get the lexical scoping correctly.
let stmts = mirror_stmts(cx, self.id, &*self.stmts);
- let opt_def_id = cx.tcx.hir.opt_local_def_id(self.id);
- let opt_destruction_extent = opt_def_id.and_then(|def_id| {
- cx.tcx.region_maps(def_id).opt_destruction_extent(self.id)
- });
+ let opt_destruction_extent = cx.region_maps.opt_destruction_extent(self.id);
Block {
targeted_by_break: self.targeted_by_break,
extent: CodeExtent::Misc(self.id),
stmts: &'tcx [hir::Stmt])
-> Vec<StmtRef<'tcx>> {
let mut result = vec![];
- let opt_def_id = cx.tcx.hir.opt_local_def_id(block_id);
for (index, stmt) in stmts.iter().enumerate() {
- let opt_dxn_ext = opt_def_id.and_then(|def_id| {
- cx.tcx.region_maps(def_id).opt_destruction_extent(stmt.node.id())
- });
+ let opt_dxn_ext = cx.region_maps.opt_destruction_extent(stmt.node.id());
match stmt.node {
hir::StmtExpr(ref expr, id) |
hir::StmtSemi(ref expr, id) => {
*/
-#![crate_name = "rustc_mir"]
-#![crate_type = "rlib"]
-#![crate_type = "dylib"]
#![deny(warnings)]
#![feature(box_patterns)]
Ok(ref callee_mir) if self.should_inline(callsite, callee_mir) => {
callee_mir.subst(self.tcx, callsite.substs)
}
+ Ok(_) => continue,
- _ => continue,
+ Err(mut bug) => {
+ // FIXME(#43542) shouldn't have to cancel an error
+ bug.cancel();
+ continue
+ }
};
let start = caller_mir.basic_blocks().len();
ExprKind::Continue(Some(ident)) => {
self.check_label(ident.node, ident.span);
}
- ExprKind::MethodCall(ref segment, ..) => {
- if let Some(ref params) = segment.parameters {
- if let PathParameters::Parenthesized(..) = **params {
- self.err_handler().span_err(expr.span,
- "parenthesized parameters cannot be used on method calls");
- }
- }
- }
_ => {}
}
//!
//! This API is completely unstable and subject to change.
-#![crate_name = "rustc_passes"]
-#![crate_type = "dylib"]
-#![crate_type = "rlib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
html_root_url = "https://doc.rust-lang.org/nightly/")]
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![crate_name = "rustc_platform_intrinsics"]
-#![crate_type = "dylib"]
-#![crate_type = "rlib"]
#![deny(warnings)]
#![allow(bad_style)]
//! See the [`plugin` feature](../../unstable-book/language-features/plugin.html) of
//! the Unstable Book for more examples.
-#![crate_name = "rustc_plugin"]
-#![crate_type = "dylib"]
-#![crate_type = "rlib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
html_root_url = "https://doc.rust-lang.org/nightly/")]
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![crate_name = "rustc_privacy"]
-#![crate_type = "dylib"]
-#![crate_type = "rlib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
html_root_url = "https://doc.rust-lang.org/nightly/")]
directive.vis.get() == ty::Visibility::Public ||
directive.span.source_equal(&DUMMY_SP) => {}
ImportDirectiveSubclass::ExternCrate => {
- let lint = lint::builtin::UNUSED_EXTERN_CRATES;
- let msg = "unused extern crate";
- ; resolver.session.buffer_lint(lint, directive.id, directive.span, msg)
+ resolver.maybe_unused_extern_crates.push((directive.id, directive.span));
}
ImportDirectiveSubclass::MacroUse => {
let lint = lint::builtin::UNUSED_IMPORTS;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![crate_name = "rustc_resolve"]
-#![crate_type = "dylib"]
-#![crate_type = "rlib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
html_root_url = "https://doc.rust-lang.org/nightly/")]
used_imports: FxHashSet<(NodeId, Namespace)>,
pub maybe_unused_trait_imports: NodeSet,
+ pub maybe_unused_extern_crates: Vec<(NodeId, Span)>,
/// privacy errors are delayed until the end in order to deduplicate them
privacy_errors: Vec<PrivacyError<'a>>,
used_imports: FxHashSet(),
maybe_unused_trait_imports: NodeSet(),
+ maybe_unused_extern_crates: Vec::new(),
privacy_errors: Vec::new(),
ambiguity_errors: Vec::new(),
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![crate_name = "rustc_save_analysis"]
-#![crate_type = "dylib"]
-#![crate_type = "rlib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
html_root_url = "https://doc.rust-lang.org/nightly/")]
//!
//! This API is completely unstable and subject to change.
-#![crate_name = "rustc_trans"]
-#![crate_type = "dylib"]
-#![crate_type = "rlib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
html_root_url = "https://doc.rust-lang.org/nightly/")]
//!
//! This API is completely unstable and subject to change.
-#![crate_name = "rustc_trans_utils"]
-#![crate_type = "dylib"]
-#![crate_type = "rlib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
html_root_url = "https://doc.rust-lang.org/nightly/")]
cmake = "0.1.18"
[dependencies]
+alloc = { path = "../liballoc" }
alloc_system = { path = "../liballoc_system" }
core = { path = "../libcore" }
// except according to those terms.
#![sanitizer_runtime]
-#![feature(sanitizer_runtime)]
#![feature(alloc_system)]
+#![feature(allocator_api)]
+#![feature(global_allocator)]
+#![feature(sanitizer_runtime)]
#![feature(staged_api)]
#![no_std]
#![unstable(feature = "sanitizer_runtime_lib",
issue = "0")]
extern crate alloc_system;
+
+use alloc_system::System;
+
+#[global_allocator]
+static ALLOC: System = System;
use rustc::traits;
use rustc::ty::{self, Ty, TyCtxt, ToPredicate, TypeFoldable};
use rustc::ty::wf::object_region_bounds;
-use rustc::lint::builtin::PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES;
use rustc_back::slice;
use require_c_abi_if_variadic;
-use util::common::{ErrorReported, FN_OUTPUT_NAME};
+use util::common::ErrorReported;
use util::nodemap::FxHashSet;
use std::iter;
use syntax::{abi, ast};
use syntax::feature_gate::{GateIssue, emit_feature_err};
-use syntax::symbol::Symbol;
use syntax_pos::Span;
pub trait AstConv<'gcx, 'tcx> {
item_segment: &hir::PathSegment)
-> &'tcx Substs<'tcx>
{
- let tcx = self.tcx();
-
- match item_segment.parameters {
- hir::AngleBracketedParameters(_) => {}
- hir::ParenthesizedParameters(..) => {
- self.prohibit_parenthesized_params(item_segment, true);
-
- return Substs::for_item(tcx, def_id, |_, _| {
- tcx.types.re_static
- }, |_, _| {
- tcx.types.err
- });
- }
- }
-
let (substs, assoc_bindings) =
self.create_substs_for_ast_path(span,
def_id,
parameters={:?})",
def_id, self_ty, parameters);
- let (lifetimes, num_types_provided, infer_types) = match *parameters {
- hir::AngleBracketedParameters(ref data) => {
- (&data.lifetimes[..], data.types.len(), data.infer_types)
- }
- hir::ParenthesizedParameters(_) => (&[][..], 1, false)
- };
-
// If the type is parameterized by this region, then replace this
// region with the current anon region binding (in other words,
// whatever & would get replaced with).
let decl_generics = tcx.generics_of(def_id);
+ let num_types_provided = parameters.types.len();
let expected_num_region_params = decl_generics.regions.len();
- let supplied_num_region_params = lifetimes.len();
+ let supplied_num_region_params = parameters.lifetimes.len();
if expected_num_region_params != supplied_num_region_params {
report_lifetime_number_error(tcx, span,
supplied_num_region_params,
// Check the number of type parameters supplied by the user.
let ty_param_defs = &decl_generics.types[self_ty.is_some() as usize..];
- if !infer_types || num_types_provided > ty_param_defs.len() {
+ if !parameters.infer_types || num_types_provided > ty_param_defs.len() {
check_type_argument_count(tcx, span, num_types_provided, ty_param_defs);
}
false
};
- let mut output_assoc_binding = None;
let substs = Substs::for_item(tcx, def_id, |def, _| {
let i = def.index as usize - self_ty.is_some() as usize;
- if let Some(lifetime) = lifetimes.get(i) {
+ if let Some(lifetime) = parameters.lifetimes.get(i) {
self.ast_region_to_region(lifetime, Some(def))
} else {
tcx.types.re_static
let i = i - self_ty.is_some() as usize - decl_generics.regions.len();
if i < num_types_provided {
// A provided type parameter.
- match *parameters {
- hir::AngleBracketedParameters(ref data) => {
- self.ast_ty_to_ty(&data.types[i])
- }
- hir::ParenthesizedParameters(ref data) => {
- assert_eq!(i, 0);
- let (ty, assoc) = self.convert_parenthesized_parameters(data);
- output_assoc_binding = Some(assoc);
- ty
- }
- }
- } else if infer_types {
+ self.ast_ty_to_ty(¶meters.types[i])
+ } else if parameters.infer_types {
// No type parameters were provided, we can infer all.
let ty_var = if !default_needs_object_self(def) {
self.ty_infer_for_def(def, substs, span)
}
});
- let assoc_bindings = match *parameters {
- hir::AngleBracketedParameters(ref data) => {
- data.bindings.iter().map(|b| {
- ConvertedBinding {
- item_name: b.name,
- ty: self.ast_ty_to_ty(&b.ty),
- span: b.span
- }
- }).collect()
- }
- hir::ParenthesizedParameters(ref data) => {
- vec![output_assoc_binding.unwrap_or_else(|| {
- // This is an error condition, but we should
- // get the associated type binding anyway.
- self.convert_parenthesized_parameters(data).1
- })]
+ let assoc_bindings = parameters.bindings.iter().map(|binding| {
+ ConvertedBinding {
+ item_name: binding.name,
+ ty: self.ast_ty_to_ty(&binding.ty),
+ span: binding.span,
}
- };
+ }).collect();
debug!("create_substs_for_ast_path(decl_generics={:?}, self_ty={:?}) -> {:?}",
decl_generics, self_ty, substs);
(substs, assoc_bindings)
}
- fn convert_parenthesized_parameters(&self,
- data: &hir::ParenthesizedParameterData)
- -> (Ty<'tcx>, ConvertedBinding<'tcx>)
- {
- let inputs = self.tcx().mk_type_list(data.inputs.iter().map(|a_t| {
- self.ast_ty_to_ty(a_t)
- }));
-
- let (output, output_span) = match data.output {
- Some(ref output_ty) => {
- (self.ast_ty_to_ty(output_ty), output_ty.span)
- }
- None => {
- (self.tcx().mk_nil(), data.span)
- }
- };
-
- let output_binding = ConvertedBinding {
- item_name: Symbol::intern(FN_OUTPUT_NAME),
- ty: output,
- span: output_span
- };
-
- (self.tcx().mk_ty(ty::TyTuple(inputs, false)), output_binding)
- }
-
/// Instantiates the path for the given trait reference, assuming that it's
/// bound to a valid trait type. Returns the def_id for the defining trait.
/// Fails if the type is a type other than a trait type.
let trait_def = self.tcx().trait_def(trait_def_id);
- match trait_segment.parameters {
- hir::AngleBracketedParameters(_) => {
- // For now, require that parenthetical notation be used
- // only with `Fn()` etc.
- if !self.tcx().sess.features.borrow().unboxed_closures && trait_def.paren_sugar {
- emit_feature_err(&self.tcx().sess.parse_sess,
- "unboxed_closures", span, GateIssue::Language,
- "\
- the precise format of `Fn`-family traits' \
- type parameters is subject to change. \
- Use parenthetical notation (Fn(Foo, Bar) -> Baz) instead");
- }
- }
- hir::ParenthesizedParameters(_) => {
- // For now, require that parenthetical notation be used
- // only with `Fn()` etc.
- if !self.tcx().sess.features.borrow().unboxed_closures && !trait_def.paren_sugar {
- emit_feature_err(&self.tcx().sess.parse_sess,
- "unboxed_closures", span, GateIssue::Language,
- "\
- parenthetical notation is only stable when used with `Fn`-family traits");
- }
- }
+ if !self.tcx().sess.features.borrow().unboxed_closures &&
+ trait_segment.parameters.parenthesized != trait_def.paren_sugar {
+ // For now, require that parenthetical notation be used only with `Fn()` etc.
+ let msg = if trait_def.paren_sugar {
+ "the precise format of `Fn`-family traits' type parameters is subject to change. \
+ Use parenthetical notation (Fn(Foo, Bar) -> Baz) instead"
+ } else {
+ "parenthetical notation is only stable when used with `Fn`-family traits"
+ };
+ emit_feature_err(&self.tcx().sess.parse_sess, "unboxed_closures",
+ span, GateIssue::Language, msg);
}
self.create_substs_for_ast_path(span,
pub fn prohibit_type_params(&self, segments: &[hir::PathSegment]) {
for segment in segments {
- if let hir::ParenthesizedParameters(_) = segment.parameters {
- self.prohibit_parenthesized_params(segment, false);
- break;
- }
- for typ in segment.parameters.types() {
+ for typ in &segment.parameters.types {
struct_span_err!(self.tcx().sess, typ.span, E0109,
"type parameters are not allowed on this type")
.span_label(typ.span, "type parameter not allowed")
.emit();
break;
}
- for lifetime in segment.parameters.lifetimes() {
+ for lifetime in &segment.parameters.lifetimes {
struct_span_err!(self.tcx().sess, lifetime.span, E0110,
"lifetime parameters are not allowed on this type")
.span_label(lifetime.span,
.emit();
break;
}
- for binding in segment.parameters.bindings() {
+ for binding in &segment.parameters.bindings {
self.prohibit_projection(binding.span);
break;
}
}
}
- pub fn prohibit_parenthesized_params(&self, segment: &hir::PathSegment, emit_error: bool) {
- if let hir::ParenthesizedParameters(ref data) = segment.parameters {
- if emit_error {
- struct_span_err!(self.tcx().sess, data.span, E0214,
- "parenthesized parameters may only be used with a trait")
- .span_label(data.span, "only traits may use parentheses")
- .emit();
- } else {
- let msg = "parenthesized parameters may only be used with a trait";
- self.tcx().lint_node(PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES,
- ast::CRATE_NODE_ID, data.span, msg);
- }
- }
- }
-
pub fn prohibit_projection(&self, span: Span) {
let mut err = struct_span_err!(self.tcx().sess, span, E0229,
"associated type bindings are not allowed here");
Some(trait_did) == tcx.lang_items.sync_trait() {
let segments = &bound.trait_ref.path.segments;
let parameters = &segments[segments.len() - 1].parameters;
- if !parameters.types().is_empty() {
+ if !parameters.types.is_empty() {
check_type_argument_count(tcx, bound.trait_ref.path.span,
- parameters.types().len(), &[]);
+ parameters.types.len(), &[]);
}
- if !parameters.lifetimes().is_empty() {
+ if !parameters.lifetimes.is_empty() {
report_lifetime_number_error(tcx, bound.trait_ref.path.span,
- parameters.lifetimes().len(), 0);
+ parameters.lifetimes.len(), 0);
}
true
} else {
// Create subst for early-bound lifetime parameters, combining
// parameters from the type and those from the method.
- let (supplied_types, supplied_lifetimes) = match segment.parameters {
- hir::AngleBracketedParameters(ref data) => (&data.types, &data.lifetimes),
- _ => bug!("unexpected generic arguments: {:?}", segment.parameters),
- };
assert_eq!(method_generics.parent_count(), parent_substs.len());
+ let provided = &segment.parameters;
Substs::for_item(self.tcx, pick.item.def_id, |def, _| {
let i = def.index as usize;
if i < parent_substs.len() {
parent_substs.region_at(i)
- } else if let Some(lifetime) =
- supplied_lifetimes.get(i - parent_substs.len()) {
+ } else if let Some(lifetime)
+ = provided.lifetimes.get(i - parent_substs.len()) {
AstConv::ast_region_to_region(self.fcx, lifetime, Some(def))
} else {
self.region_var_for_def(self.span, def)
let i = def.index as usize;
if i < parent_substs.len() {
parent_substs.type_at(i)
- } else if let Some(ast_ty) =
- supplied_types.get(i - parent_substs.len() - method_generics.regions.len()) {
+ } else if let Some(ast_ty)
+ = provided.types.get(i - parent_substs.len() - method_generics.regions.len()) {
self.to_ty(ast_ty)
} else {
self.type_var_for_def(self.span, def, cur_substs)
i -= fn_start;
fn_segment
};
- let lifetimes = match segment.map(|(s, _)| &s.parameters) {
- Some(&hir::AngleBracketedParameters(ref data)) => &data.lifetimes[..],
- Some(&hir::ParenthesizedParameters(_)) => bug!(),
- None => &[]
- };
+ let lifetimes = segment.map_or(&[][..], |(s, _)| &s.parameters.lifetimes[..]);
if let Some(lifetime) = lifetimes.get(i) {
AstConv::ast_region_to_region(self, lifetime, Some(def))
i -= fn_start;
fn_segment
};
- let (types, infer_types) = match segment.map(|(s, _)| &s.parameters) {
- Some(&hir::AngleBracketedParameters(ref data)) => {
- (&data.types[..], data.infer_types)
- }
- Some(&hir::ParenthesizedParameters(_)) => bug!(),
- None => (&[][..], true)
- };
+ let (types, infer_types) = segment.map_or((&[][..], true), |(s, _)| {
+ (&s.parameters.types[..], s.parameters.infer_types)
+ });
// Skip over the lifetimes in the same segment.
if let Some((_, generics)) = segment {
span: Span,
segment: &mut Option<(&hir::PathSegment, &ty::Generics)>,
is_method_call: bool) {
- let (lifetimes, types, infer_types, bindings) = {
- match segment.map(|(s, _)| &s.parameters) {
- Some(&hir::AngleBracketedParameters(ref data)) => {
- (&data.lifetimes[..], &data.types[..], data.infer_types, &data.bindings[..])
- }
- Some(&hir::ParenthesizedParameters(_)) => {
- AstConv::prohibit_parenthesized_params(self, &segment.as_ref().unwrap().0,
- false);
- (&[][..], &[][..], true, &[][..])
- }
- None => (&[][..], &[][..], true, &[][..])
- }
- };
+ let (lifetimes, types, infer_types, bindings) = segment.map_or(
+ (&[][..], &[][..], true, &[][..]),
+ |(s, _)| (&s.parameters.lifetimes[..], &s.parameters.types[..],
+ s.parameters.infer_types, &s.parameters.bindings[..]));
let infer_lifetimes = lifetimes.len() == 0;
let count_lifetime_params = |n| {
}
if !bindings.is_empty() {
- span_err!(self.tcx.sess, bindings[0].span, E0182,
- "unexpected binding of associated item in expression path \
- (only allowed in type paths)");
+ AstConv::prohibit_projection(self, bindings[0].span);
}
// Check provided lifetime parameters.
let mut visitor = CheckVisitor { tcx, used_trait_imports };
tcx.hir.krate().visit_all_item_likes(&mut visitor);
+
+ for &(id, span) in &tcx.maybe_unused_extern_crates {
+ let cnum = tcx.sess.cstore.extern_mod_stmt_cnum(id).unwrap().as_def_id();
+ if !tcx.is_compiler_builtins(cnum)
+ && !tcx.is_panic_runtime(cnum)
+ && !tcx.has_global_allocator(cnum) {
+ let lint = lint::builtin::UNUSED_EXTERN_CRATES;
+ let msg = "unused extern crate";
+ tcx.lint_node(lint, id, span, msg);
+ }
+ }
}
```
"##,
-E0182: r##"
-You bound an associated type in an expression path which is not
-allowed.
-
-Erroneous code example:
-
-```compile_fail,E0182
-trait Foo {
- type A;
- fn bar() -> isize;
-}
-
-impl Foo for isize {
- type A = usize;
- fn bar() -> isize { 42 }
-}
-
-// error: unexpected binding of associated item in expression path
-let x: isize = Foo::<A=usize>::bar();
-```
-
-To give a concrete type when using the Universal Function Call Syntax,
-use "Type as Trait". Example:
-
-```
-trait Foo {
- type A;
- fn bar() -> isize;
-}
-
-impl Foo for isize {
- type A = usize;
- fn bar() -> isize { 42 }
-}
-
-let x: isize = <isize as Foo>::bar(); // ok!
-```
-"##,
-
E0184: r##"
Explicitly implementing both Drop and Copy for a type is currently disallowed.
This feature can make some sense in theory, but the current implementation is
"##,
*/
-E0214: r##"
-A generic type was described using parentheses rather than angle brackets. For
-example:
-
-```compile_fail,E0214
-fn main() {
- let v: Vec(&str) = vec!["foo"];
-}
-```
-
-This is not currently supported: `v` should be defined as `Vec<&str>`.
-Parentheses are currently only used with generic types when defining parameters
-for `Fn`-family traits.
-"##,
-
E0220: r##"
You used an associated type which isn't defined in the trait.
Erroneous code example:
// E0172, // non-trait found in a type sum, moved to resolve
// E0173, // manual implementations of unboxed closure traits are experimental
// E0174,
+// E0182, // merged into E0229
E0183,
// E0187, // can't infer the kind of the closure
// E0188, // can not cast an immutable reference to a mutable pointer
*/
-#![crate_name = "rustc_typeck"]
-#![crate_type = "dylib"]
-#![crate_type = "rlib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
html_root_url = "https://doc.rust-lang.org/nightly/")]
pub fn is_union(&self) -> bool {
self.type_() == ItemType::Union
}
+ pub fn is_import(&self) -> bool {
+ self.type_() == ItemType::Import
+ }
+
pub fn is_stripped(&self) -> bool {
match self.inner { StrippedItem(..) => true, _ => false }
}
let mut lt_substs = FxHashMap();
for (i, ty_param) in generics.ty_params.iter().enumerate() {
let ty_param_def = Def::TyParam(cx.tcx.hir.local_def_id(ty_param.id));
- if let Some(ty) = provided_params.types().get(i).cloned()
- .cloned() {
+ if let Some(ty) = provided_params.types.get(i).cloned() {
ty_substs.insert(ty_param_def, ty.unwrap().clean(cx));
} else if let Some(default) = ty_param.default.clone() {
ty_substs.insert(ty_param_def, default.unwrap().clean(cx));
}
}
for (i, lt_param) in generics.lifetimes.iter().enumerate() {
- if let Some(lt) = provided_params.lifetimes().get(i).cloned()
- .cloned() {
+ if let Some(lt) = provided_params.lifetimes.get(i).cloned() {
if !lt.is_elided() {
lt_substs.insert(lt_param.lifetime.id, lt.clean(cx));
}
impl Clean<PathParameters> for hir::PathParameters {
fn clean(&self, cx: &DocContext) -> PathParameters {
- match *self {
- hir::AngleBracketedParameters(ref data) => {
- PathParameters::AngleBracketed {
- lifetimes: if data.lifetimes.iter().all(|lt| lt.is_elided()) {
- vec![]
- } else {
- data.lifetimes.clean(cx)
- },
- types: data.types.clean(cx),
- bindings: data.bindings.clean(cx),
- }
+ if self.parenthesized {
+ let output = self.bindings[0].ty.clean(cx);
+ PathParameters::Parenthesized {
+ inputs: self.inputs().clean(cx),
+ output: if output != Type::Tuple(Vec::new()) { Some(output) } else { None }
}
-
- hir::ParenthesizedParameters(ref data) => {
- PathParameters::Parenthesized {
- inputs: data.inputs.clean(cx),
- output: data.output.clean(cx),
- }
+ } else {
+ PathParameters::AngleBracketed {
+ lifetimes: if self.lifetimes.iter().all(|lt| lt.is_elided()) {
+ vec![]
+ } else {
+ self.lifetimes.clean(cx)
+ },
+ types: self.types.clean(cx),
+ bindings: self.bindings.clean(cx),
}
}
}
}
indices.sort_by(|&i1, &i2| cmp(&items[i1], &items[i2], i1, i2));
+ // This call is to remove reexport duplicates in cases such as:
+ //
+ // ```
+ // pub mod foo {
+ // pub mod bar {
+ // pub trait Double { fn foo(); }
+ // }
+ // }
+ //
+ // pub use foo::bar::*;
+ // pub use foo::*;
+ // ```
+ //
+ // `Double` will appear twice in the generated docs.
+ //
+ // FIXME: This code is quite ugly and could be improved. Small issue: DefId
+ // can be identical even if the elements are different (mostly in imports).
+ // So in case this is an import, we keep everything by adding a "unique id"
+ // (which is the position in the vector).
+ indices.dedup_by_key(|i| (items[*i].def_id,
+ if items[*i].name.as_ref().is_some() {
+ Some(full_path(cx, &items[*i]).clone())
+ } else {
+ None
+ },
+ items[*i].type_(),
+ if items[*i].is_import() {
+ *i
+ } else {
+ 0
+ }));
debug!("{:?}", indices);
let mut curty = None;
fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLink,
render_mode: RenderMode, outer_version: Option<&str>) -> fmt::Result {
if render_mode == RenderMode::Normal {
- write!(w, "<h3 class='impl'><span class='in-band'><code>{}</code>", i.inner_impl())?;
+ let id = derive_id(match i.inner_impl().trait_ {
+ Some(ref t) => format!("impl-{}", Escape(&format!("{:#}", t))),
+ None => "impl".to_string(),
+ });
+ write!(w, "<h3 id='{}' class='impl'><span class='in-band'><code>{}</code>",
+ id, i.inner_impl())?;
+ write!(w, "<a href='#{}' class='anchor'></a>", id)?;
write!(w, "</span><span class='out-of-band'>")?;
let since = i.impl_item.stability.as_ref().map(|s| &s.since[..]);
if let Some(l) = (Item { item: &i.impl_item, cx: cx }).src_href() {
margin: 0 0 .6em 0;
}
+summary {
+ outline: none;
+}
+
code, pre {
font-family: "Source Code Pro", Menlo, Monaco, Consolas, "DejaVu Sans Mono", Inconsolata, monospace;
white-space: pre-wrap;
.small-section-header:hover > .anchor {
display: initial;
}
+
+.in-band:hover > .anchor {
+ display: initial;
+}
.anchor {
display: none;
}
h2, h3:not(.impl):not(.method):not(.type):not(.tymethod), h4:not(.method):not(.type):not(.tymethod) {
border-bottom-color: #DDDDDD;
}
+
.in-band {
background-color: white;
}
}
:target { background: #FDFFD3; }
+
+:target > .in-band {
+ background: #FDFFD3;
+}
+
.content .highlighted {
color: #000 !important;
background-color: #ccc;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![crate_name = "rustdoc"]
-#![crate_type = "dylib"]
-#![crate_type = "rlib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
html_root_url = "https://doc.rust-lang.org/nightly/",
Core encoding and decoding interfaces.
*/
-#![crate_name = "serialize"]
-#![crate_type = "rlib"]
-#![crate_type = "dylib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
html_root_url = "https://doc.rust-lang.org/nightly/",
/// `Read`er - the method only takes `&self` so that it can be used through
/// trait objects.
///
- /// # Unsafety
+ /// # Safety
///
/// This method is unsafe because a `Read`er could otherwise return a
/// non-zeroing `Initializer` from another `Read` type without an `unsafe`
/// Returns a new `Initializer` which will not zero out buffers.
///
- /// # Unsafety
+ /// # Safety
///
/// This may only be called by `Read`ers which guarantee that they will not
/// read from buffers passed to `Read` methods, and that the return value of
//! Note the documentation for the primitives [`str`] and [`[T]`][slice] (also
//! called 'slice'). Many method calls on [`String`] and [`Vec<T>`] are actually
//! calls to methods on [`str`] and [`[T]`][slice] respectively, via [deref
-//! coercions].
+//! coercions][deref-coercions].
//!
//! Third, the standard library defines [The Rust Prelude], a small collection
//! of items - mostly traits - that are imported into every module of every
//! [`use`]: ../book/first-edition/crates-and-modules.html#importing-modules-with-use
//! [crate root]: ../book/first-edition/crates-and-modules.html#basic-terminology-crates-and-modules
//! [crates.io]: https://crates.io
-//! [deref coercions]: ../book/first-edition/deref-coercions.html
+//! [deref-coercions]: ../book/second-edition/ch15-02-deref.html#implicit-deref-coercions-with-functions-and-methods
//! [files]: fs/struct.File.html
//! [multithreading]: thread/index.html
//! [other]: #what-is-in-the-standard-library-documentation
//! [primitive types]: ../book/first-edition/primitive-types.html
-#![crate_name = "std"]
#![stable(feature = "rust1", since = "1.0.0")]
-#![crate_type = "rlib"]
-#![crate_type = "dylib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
html_root_url = "https://doc.rust-lang.org/nightly/",
extern crate libc;
// We always need an unwinder currently for backtraces
+#[allow(unused_extern_crates)]
extern crate unwind;
// compiler-rt intrinsics
/// magnitude faster than `haystack.iter().position(|&b| b == needle)`.
/// (See benchmarks.)
///
-/// # Example
+/// # Examples
///
/// This shows how to find the first position of a byte in a byte string.
///
/// Returns the index corresponding to the last occurrence of `needle` in
/// `haystack`, or `None` if one is not found.
///
-/// # Example
+/// # Examples
///
/// This shows how to find the last position of a byte in a byte string.
///
mem::transmute(s)
}
+// Detect scheme on Redox
+fn has_redox_scheme(s: &[u8]) -> bool {
+ cfg!(target_os = "redox") && s.split(|b| *b == b'/').next().unwrap_or(b"").contains(&b':')
+}
+
////////////////////////////////////////////////////////////////////////////////
// Cross-platform, iterator-independent parsing
////////////////////////////////////////////////////////////////////////////////
#[stable(feature = "rust1", since = "1.0.0")]
#[allow(deprecated)]
pub fn is_absolute(&self) -> bool {
- // FIXME: Remove target_os = "redox" and allow Redox prefixes
- self.has_root() && (cfg!(unix) || cfg!(target_os = "redox") || self.prefix().is_some())
+ if !cfg!(target_os = "redox") {
+ self.has_root() && (cfg!(unix) || self.prefix().is_some())
+ } else {
+ // FIXME: Allow Redox prefixes
+ has_redox_scheme(self.as_u8_slice())
+ }
}
/// Returns `true` if the `Path` is relative, i.e. not absolute.
Components {
path: self.as_u8_slice(),
prefix,
- has_physical_root: has_physical_root(self.as_u8_slice(), prefix),
+ has_physical_root: has_physical_root(self.as_u8_slice(), prefix) ||
+ has_redox_scheme(self.as_u8_slice()),
front: State::Prefix,
back: State::Body,
}
//! On a technical level, Rust inserts
//!
//! ```
+//! # #[allow(unused_extern_crates)]
//! extern crate std;
//! ```
//!
/// Working with raw pointers in Rust is uncommon,
/// typically limited to a few patterns.
///
-/// Use the [`null`] function to create null pointers, and the [`is_null`] method
-/// of the `*const T` type to check for null. The `*const T` type also defines
-/// the [`offset`] method, for pointer math.
+/// Use the [`null`] and [`null_mut`] functions to create null pointers, and the
+/// [`is_null`] method of the `*const T` and `*mut T` types to check for null.
+/// The `*const T` and `*mut T` types also define the [`offset`] method, for
+/// pointer math.
///
/// # Common ways to create raw pointers
///
/// *[See also the `std::ptr` module](ptr/index.html).*
///
/// [`null`]: ../std/ptr/fn.null.html
+/// [`null_mut`]: ../std/ptr/fn.null_mut.html
/// [`is_null`]: ../std/primitive.pointer.html#method.is_null
/// [`offset`]: ../std/primitive.pointer.html#method.offset
/// [`into_raw`]: ../std/boxed/struct.Box.html#method.into_raw
//! For now, this module is limited to extracting file descriptors,
//! but its functionality will grow over time.
//!
-//! # Example
+//! # Examples
//!
//! ```no_run
//! use std::fs::File;
/// # Examples
///
/// ```no_run
- /// # #![feature(libc)]
- /// extern crate libc;
/// use std::fs::OpenOptions;
/// use std::os::unix::fs::OpenOptionsExt;
///
//! For now, this module is limited to extracting file descriptors,
//! but its functionality will grow over time.
//!
-//! # Example
+//! # Examples
//!
//! ```no_run
//! use std::fs::File;
unsafe {
let ret = libc::pthread_join(self.id, ptr::null_mut());
mem::forget(self);
- debug_assert_eq!(ret, 0);
+ assert!(ret == 0,
+ "failed to join thread: {}", io::Error::from_raw_os_error(ret));
}
}
pub const WAIT_OBJECT_0: DWORD = 0x00000000;
pub const WAIT_TIMEOUT: DWORD = 258;
+pub const WAIT_FAILED: DWORD = 0xFFFFFFFF;
#[cfg(target_env = "msvc")]
pub const MAX_SYM_NAME: usize = 2000;
}
pub fn join(self) {
- unsafe { c::WaitForSingleObject(self.handle.raw(), c::INFINITE); }
+ let rc = unsafe { c::WaitForSingleObject(self.handle.raw(), c::INFINITE) };
+ if rc == c::WAIT_FAILED {
+ panic!("failed to join on thread: {}",
+ io::Error::last_os_error());
+ }
}
pub fn yield_now() {
{
let Builder { name, stack_size } = self;
- let stack_size = stack_size.unwrap_or(util::min_stack());
+ let stack_size = stack_size.unwrap_or_else(util::min_stack);
let my_thread = Thread::new(name);
let their_thread = my_thread.clone();
/// Platforms which do not support nanosecond precision for sleeping will have
/// `dur` rounded up to the nearest granularity of time they can sleep for.
///
-/// # Example
+/// # Examples
///
/// Waiting for the complete expiration of the timeout:
///
/// [`Err`]: ../../std/result/enum.Result.html#variant.Err
/// [`panic`]: ../../std/macro.panic.html
///
+ /// # Panics
+ ///
+ /// This function may panic on some platforms if a thread attempts to join
+ /// itself or otherwise may create a deadlock with joining threads.
+ ///
/// # Examples
///
/// ```
//! provide for basic string-related manipulations. This crate does not
//! (yet) aim to provide a full set of Unicode tables.
-#![crate_name = "std_unicode"]
#![unstable(feature = "unicode", issue = "27783")]
-#![crate_type = "rlib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
html_root_url = "https://doc.rust-lang.org/nightly/",
// was set. This is most important for knowing when a particular feature became
// stable (active).
//
-// NB: The featureck.py script parses this information directly out of the source
-// so take care when modifying it.
+// NB: tools/tidy/src/features.rs parses this information directly out of the
+// source, so take care when modifying it.
declare_features! (
(active, asm, "1.0.0", Some(29722)),
// #[doc(cfg(...))]
(active, doc_cfg, "1.21.0", Some(43781)),
+
+ // allow `#[must_use]` on functions (RFC 1940)
+ (active, fn_must_use, "1.21.0", Some(43302)),
);
declare_features! (
}
macro_rules! gate_feature_fn {
- ($cx: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr) => {{
- let (cx, has_feature, span, name, explain) = ($cx, $has_feature, $span, $name, $explain);
+ ($cx: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr, $level: expr) => {{
+ let (cx, has_feature, span,
+ name, explain, level) = ($cx, $has_feature, $span, $name, $explain, $level);
let has_feature: bool = has_feature(&$cx.features);
debug!("gate_feature(feature = {:?}, span = {:?}); has? {}", name, span, has_feature);
if !has_feature && !span.allows_unstable() {
- emit_feature_err(cx.parse_sess, name, span, GateIssue::Language, explain);
+ leveled_feature_err(cx.parse_sess, name, span, GateIssue::Language, explain, level)
+ .emit();
}
}}
}
macro_rules! gate_feature {
($cx: expr, $feature: ident, $span: expr, $explain: expr) => {
- gate_feature_fn!($cx, |x:&Features| x.$feature, $span, stringify!($feature), $explain)
- }
+ gate_feature_fn!($cx, |x:&Features| x.$feature, $span,
+ stringify!($feature), $explain, GateStrength::Hard)
+ };
+ ($cx: expr, $feature: ident, $span: expr, $explain: expr, $level: expr) => {
+ gate_feature_fn!($cx, |x:&Features| x.$feature, $span,
+ stringify!($feature), $explain, $level)
+ };
}
impl<'a> Context<'a> {
for &(n, ty, ref gateage) in BUILTIN_ATTRIBUTES {
if name == n {
if let Gated(_, name, desc, ref has_feature) = *gateage {
- gate_feature_fn!(self, has_feature, attr.span, name, desc);
+ gate_feature_fn!(self, has_feature, attr.span, name, desc, GateStrength::Hard);
}
debug!("check_attribute: {:?} is builtin, {:?}, {:?}", attr.path, ty, gateage);
return;
Library(Option<u32>)
}
+#[derive(Debug, Copy, Clone, PartialEq, Eq)]
+pub enum GateStrength {
+ /// A hard error. (Most feature gates should use this.)
+ Hard,
+ /// Only a warning. (Use this only as backwards-compatibility demands.)
+ Soft,
+}
+
pub fn emit_feature_err(sess: &ParseSess, feature: &str, span: Span, issue: GateIssue,
explain: &str) {
feature_err(sess, feature, span, issue, explain).emit();
}
pub fn feature_err<'a>(sess: &'a ParseSess, feature: &str, span: Span, issue: GateIssue,
- explain: &str) -> DiagnosticBuilder<'a> {
+ explain: &str) -> DiagnosticBuilder<'a> {
+ leveled_feature_err(sess, feature, span, issue, explain, GateStrength::Hard)
+}
+
+fn leveled_feature_err<'a>(sess: &'a ParseSess, feature: &str, span: Span, issue: GateIssue,
+ explain: &str, level: GateStrength) -> DiagnosticBuilder<'a> {
let diag = &sess.span_diagnostic;
let issue = match issue {
GateIssue::Library(lib) => lib,
};
- let mut err = if let Some(n) = issue {
- diag.struct_span_err(span, &format!("{} (see issue #{})", explain, n))
+ let explanation = if let Some(n) = issue {
+ format!("{} (see issue #{})", explain, n)
} else {
- diag.struct_span_err(span, explain)
+ explain.to_owned()
+ };
+
+ let mut err = match level {
+ GateStrength::Hard => diag.struct_span_err(span, &explanation),
+ GateStrength::Soft => diag.struct_span_warn(span, &explanation),
};
// #23973: do not suggest `#![feature(...)]` if we are in beta/stable
feature));
}
+ // If we're on stable and only emitting a "soft" warning, add a note to
+ // clarify that the feature isn't "on" (rather than being on but
+ // warning-worthy).
+ if !sess.unstable_features.is_nightly_build() && level == GateStrength::Soft {
+ err.help("a nightly build of the compiler is required to enable this feature");
+ }
+
err
+
}
const EXPLAIN_BOX_SYNTAX: &'static str =
if !span.allows_unstable() {
gate_feature!(cx.context, $feature, span, $explain)
}
+ }};
+ ($cx: expr, $feature: ident, $span: expr, $explain: expr, $level: expr) => {{
+ let (cx, span) = ($cx, $span);
+ if !span.allows_unstable() {
+ gate_feature!(cx.context, $feature, span, $explain, $level)
+ }
}}
}
function may change over time, for now \
a top-level `fn main()` is required");
}
+ if attr::contains_name(&i.attrs[..], "must_use") {
+ gate_feature_post!(&self, fn_must_use, i.span,
+ "`#[must_use]` on functions is experimental",
+ GateStrength::Soft);
+ }
}
ast::ItemKind::Struct(..) => {
and possibly buggy");
}
- ast::ItemKind::Impl(_, polarity, defaultness, _, _, _, _) => {
+ ast::ItemKind::Impl(_, polarity, defaultness, _, _, _, ref impl_items) => {
if polarity == ast::ImplPolarity::Negative {
gate_feature_post!(&self, optin_builtin_traits,
i.span,
i.span,
"specialization is unstable");
}
+
+ for impl_item in impl_items {
+ if let ast::ImplItemKind::Method(..) = impl_item.node {
+ if attr::contains_name(&impl_item.attrs[..], "must_use") {
+ gate_feature_post!(&self, fn_must_use, impl_item.span,
+ "`#[must_use]` on methods is experimental",
+ GateStrength::Soft);
+ }
+ }
+ }
}
ast::ItemKind::MacroDef(ast::MacroDef { legacy: false, .. }) => {
//!
//! This API is completely unstable and subject to change.
-#![crate_name = "syntax"]
-#![crate_type = "dylib"]
-#![crate_type = "rlib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
html_root_url = "https://doc.rust-lang.org/nightly/",
}
struct TestCtxt<'a> {
- sess: &'a ParseSess,
span_diagnostic: &'a errors::Handler,
path: Vec<Ident>,
ext_cx: ExtCtxt<'a>,
testfns: Vec<Test>,
reexport_test_harness_main: Option<Symbol>,
- is_test_crate: bool,
+ is_libtest: bool,
ctxt: SyntaxContext,
// top-level re-export submodule, filled out after folding is finished
let krate = cleaner.fold_crate(krate);
let mark = Mark::fresh(Mark::root());
+
let mut cx: TestCtxt = TestCtxt {
- sess,
span_diagnostic: sd,
ext_cx: ExtCtxt::new(sess, ExpansionConfig::default("test".to_string()), resolver),
path: Vec::new(),
testfns: Vec::new(),
reexport_test_harness_main,
- is_test_crate: is_test_crate(&krate),
+ // NB: doesn't consider the value of `--crate-name` passed on the command line.
+ is_libtest: attr::find_crate_name(&krate.attrs).map(|s| s == "test").unwrap_or(false),
toplevel_reexport: None,
ctxt: SyntaxContext::empty().apply_mark(mark),
};
fn mk_std(cx: &TestCtxt) -> P<ast::Item> {
let id_test = Ident::from_str("test");
let sp = ignored_span(cx, DUMMY_SP);
- let (vi, vis, ident) = if cx.is_test_crate {
+ let (vi, vis, ident) = if cx.is_libtest {
(ast::ItemKind::Use(
P(nospan(ast::ViewPathSimple(id_test,
path_node(vec![id_test]))))),
test_descs)
}
-fn is_test_crate(krate: &ast::Crate) -> bool {
- match attr::find_crate_name(&krate.attrs) {
- Some(s) if "test" == s.as_str() => true,
- _ => false
- }
-}
-
fn mk_test_descs(cx: &TestCtxt) -> P<ast::Expr> {
debug!("building test vector from {} tests", cx.testfns.len());
[dependencies]
fmt_macros = { path = "../libfmt_macros" }
-log = "0.3"
proc_macro = { path = "../libproc_macro" }
rustc_errors = { path = "../librustc_errors" }
syntax = { path = "../libsyntax" }
//! Syntax extensions in the Rust compiler.
-#![crate_name = "syntax_ext"]
-#![crate_type = "dylib"]
-#![crate_type = "rlib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
html_root_url = "https://doc.rust-lang.org/nightly/")]
#![feature(proc_macro_internals)]
extern crate fmt_macros;
-extern crate log;
#[macro_use]
extern crate syntax;
extern crate syntax_pos;
//!
//! This API is completely unstable and subject to change.
-#![crate_name = "syntax_pos"]
-#![crate_type = "dylib"]
-#![crate_type = "rlib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
html_root_url = "https://doc.rust-lang.org/nightly/")]
//! [win]: http://msdn.microsoft.com/en-us/library/windows/desktop/ms682010%28v=vs.85%29.aspx
//! [ti]: https://en.wikipedia.org/wiki/Terminfo
-#![crate_name = "term"]
-#![crate_type = "rlib"]
-#![crate_type = "dylib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
html_root_url = "https://doc.rust-lang.org/nightly/",
// running tests while providing a base that other test frameworks may
// build off of.
+// NB: this is also specified in this crate's Cargo.toml, but libsyntax contains logic specific to
+// this crate, which relies on this attribute (rather than the value of `--crate-name` passed by
+// cargo) to detect this crate.
#![crate_name = "test"]
#![unstable(feature = "test", issue = "27812")]
-#![crate_type = "rlib"]
-#![crate_type = "dylib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
html_root_url = "https://doc.rust-lang.org/nightly/",
#![deny(warnings)]
#![feature(asm)]
-#![feature(libc)]
+#![cfg_attr(unix, feature(libc))]
#![feature(set_stdio)]
#![feature(panic_unwind)]
#![feature(staged_api)]
extern crate getopts;
extern crate term;
+#[cfg(unix)]
extern crate libc;
extern crate panic_unwind;
// except according to those terms.
#![no_std]
-#![crate_name = "unwind"]
-#![crate_type = "rlib"]
#![unstable(feature = "panic_unwind", issue = "32837")]
#![deny(warnings)]
#[cfg(not(target_env = "msvc"))]
pub use libunwind::*;
-#[cfg(target_env = "musl")]
-#[link(name = "unwind", kind = "static-nobundle", cfg(target_feature = "crt-static"))]
+#[cfg(all(target_env = "musl", not(target_arch = "mips")))]
+#[link(name = "unwind", kind = "static", cfg(target_feature = "crt-static"))]
#[link(name = "gcc_s", cfg(not(target_feature = "crt-static")))]
extern {}
// libsyntax is not compiled for it.
#![deny(plugin_as_library)]
+#![allow(unused_extern_crates)]
extern crate macro_crate_test; //~ ERROR compiler plugin used as an ordinary library
// except according to those terms.
#![feature(alloc)]
+#![allow(unused_extern_crates)]
extern crate alloc;
//~^ NOTE previous import of the extern crate `alloc` here
// except according to those terms.
#![feature(alloc, libc)]
+#![allow(unused_extern_crates)]
extern crate alloc;
//~^ NOTE previous import of the extern crate `alloc` here
// except according to those terms.
#![feature(alloc)]
+#![allow(unused_extern_crates)]
extern crate alloc;
//~^ NOTE previous import of the extern crate `alloc` here
pub fn main() {
let x: isize = Foo::<A=usize>::bar();
- //~^ ERROR unexpected binding of associated item in expression path
+ //~^ ERROR associated type bindings are not allowed here
}
--- /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.
#![deny(non_snake_case)] // To trigger a hard error
// Shouldn't generate a warning about unstable features
+#[allow(unused_extern_crates)]
extern crate stability_cfg2;
pub fn BOGUS() { } //~ 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.
+
+#![feature(rustc_attrs)]
+
+struct MyStruct;
+
+impl MyStruct {
+ #[must_use]
+ fn need_to_use_method() -> bool { true } //~ WARN `#[must_use]` on methods is experimental
+}
+
+#[must_use]
+fn need_to_use_it() -> bool { true } //~ WARN `#[must_use]` on functions is experimental
+
+
+// Feature gates are tidy-required to have a specially named (or
+// comment-annotated) compile-fail test (which MUST fail), but for
+// backwards-compatibility reasons, we want `#[must_use]` on functions to be
+// compilable even if the `fn_must_use` feature is absent, thus necessitating
+// the usage of `#[rustc_error]` here, pragmatically if awkwardly solving this
+// dilemma until a superior solution can be devised.
+#[rustc_error]
+fn main() {} //~ ERROR compilation successful
mod inner { #![must_use="1400"] }
#[must_use = "1400"] fn f() { }
+ //~^ WARN `#[must_use]` on functions is experimental
#[must_use = "1400"] struct S;
// aux-build:issue-36881-aux.rs
fn main() {
+ #[allow(unused_extern_crates)]
extern crate issue_36881_aux;
use issue_36881_aux::Foo; //~ ERROR unresolved import
}
--- /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(fn_traits)]
+
+trait CallSingle<A, B> {
+ fn call(&self, a: A) -> B where Self: Fn(A) -> B;
+}
+
+impl<A, B, F: Fn(A) -> B> CallSingle<A, B> for F {
+ fn call(&self, a: A) -> B {
+ <Self as Fn(A) -> B>::call(self, (a,))
+ //~^ ERROR associated type bindings are not allowed here
+ }
+}
+
+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.
+
+pub trait Partial<X: ?Sized>: Copy {
+}
+
+pub trait Complete {
+ type Assoc: Partial<Self>;
+}
+
+impl<T> Partial<T> for T::Assoc where
+ T: Complete
+{
+}
+
+impl<T> Complete for T { //~ ERROR the trait bound `T: std::marker::Copy` is not satisfied
+ type Assoc = 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.
+
+pub trait Partial: Copy {
+}
+
+pub trait Complete: Partial {
+}
+
+impl<T> Partial for T where T: Complete {}
+impl<T> Complete for T {} //~ ERROR the trait bound `T: std::marker::Copy` is not satisfied
// aux-build:stability_cfg2.rs
#![warn(deprecated)]
-#![allow(dead_code)]
+#![allow(dead_code, unused_extern_crates)]
#![feature(staged_api, test_feature, rustc_attrs)]
#![stable(feature = "rust1", since = "1.0.0")]
// aux-build:lint_unused_extern_crate2.rs
// aux-build:lint_unused_extern_crate3.rs
// aux-build:lint_unused_extern_crate4.rs
+// aux-build:lint_unused_extern_crate5.rs
#![deny(unused_extern_crates)]
#![allow(unused_variables)]
#![allow(deprecated)]
-extern crate lint_unused_extern_crate4; //~ ERROR: unused extern crate
+extern crate lint_unused_extern_crate5; //~ ERROR: unused extern crate
+
+pub extern crate lint_unused_extern_crate4; // no error, it is reexported
extern crate lint_unused_extern_crate3; // no error, it is used
#![no_std]
#![feature(macro_reexport)]
+#[allow(unused_extern_crates)]
#[macro_reexport] //~ ERROR bad macro reexport
extern crate std;
#![no_std]
#![feature(macro_reexport)]
+#[allow(unused_extern_crates)]
#[macro_reexport="foo"] //~ ERROR bad macro reexport
extern crate std;
#![no_std]
#![feature(macro_reexport)]
+#[allow(unused_extern_crates)]
#[macro_reexport(foo="bar")] //~ ERROR bad macro reexport
extern crate std;
#![no_std]
+#[allow(unused_extern_crates)]
#[macro_use(foo(bar))] //~ ERROR bad macro import
extern crate std;
#![no_std]
+#[allow(unused_extern_crates)]
#[macro_use(foo="bar")] //~ ERROR bad macro import
extern crate std;
// except according to those terms.
fn main() {
- 0.clone::<T = u8>(); //~ ERROR unexpected binding of associated item
+ 0.clone::<T = u8>(); //~ ERROR associated type bindings are not allowed here
}
// except according to those terms.
#![no_std]
+#![allow(unused_extern_crates)]
extern crate core; //~ ERROR: the name `core` is defined multiple times
extern crate std;
#![feature(placement_in_syntax)]
-extern crate core;
-
fn main() {
use std::boxed::HEAP; //~ ERROR use of unstable library feature
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+#[allow(unused_extern_crates)]
extern crate std;
//~^ ERROR the name `std` is defined multiple times
// except according to those terms.
#![feature(alloc)]
+#![allow(unused_extern_crates)]
mod a {
extern crate alloc;
fn foo(b: Box<Bar()>) {
//~^ ERROR parenthesized parameters may only be used with a trait
+ //~| ERROR the type placeholder `_` is not allowed within types on item signatures
}
fn main() { }
// except according to those terms.
#![deny(unused_attributes)]
-#![allow(dead_code, unused_imports)]
+#![allow(dead_code, unused_imports, unused_extern_crates)]
#![feature(custom_attribute)]
#![foo] //~ ERROR unused attribute
--- /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 identify_regions -Z span_free_formats
+// ignore-tidy-linelength
+
+// Regression test for #43457: an `EndRegion` was missing from output
+// because compiler was using a faulty means for region map lookup.
+
+use std::cell::RefCell;
+
+fn rc_refcell_test(r: RefCell<i32>) {
+ r.borrow_mut();
+}
+
+fn main() { }
+
+// END RUST SOURCE
+// START rustc.node5.SimplifyCfg-qualify-consts.after.mir
+//
+// fn rc_refcell_test(_1: std::cell::RefCell<i32>) -> () {
+// let mut _0: ();
+// scope 1 {
+// let _2: std::cell::RefCell<i32>;
+// }
+// let mut _3: std::cell::RefMut<'17dce, i32>;
+// let mut _4: &'17dce std::cell::RefCell<i32>;
+//
+// bb0: {
+// StorageLive(_2);
+// _2 = _1;
+// StorageLive(_4);
+// _4 = &'17dce _2;
+// _3 = const <std::cell::RefCell<T>>::borrow_mut(_4) -> bb1;
+// }
+//
+// bb1: {
+// drop(_3) -> bb2;
+// }
+//
+// bb2: {
+// StorageDead(_4);
+// EndRegion('17dce);
+// _0 = ();
+// StorageDead(_2);
+// return;
+// }
+// }
all:
$(RUSTC) fakealloc.rs
- $(RUSTC) ../../../liballoc/lib.rs --cfg feature=\"external_crate\" --extern external=$(TMPDIR)/$(shell $(RUSTC) --print file-names fakealloc.rs)
+ $(RUSTC) --crate-type=rlib ../../../liballoc/lib.rs --cfg feature=\"external_crate\" --extern external=$(TMPDIR)/$(shell $(RUSTC) --print file-names fakealloc.rs)
// aux-build:union.rs
-// FIXME: This test case makes little-endian assumptions.
-// ignore-s390x
-// ignore-sparc
-
extern crate union;
use std::mem::{size_of, align_of, zeroed};
assert_eq!(w.b, 0);
w.a = 1;
assert_eq!(w.a, 1);
- assert_eq!(w.b, 1);
+ assert_eq!(w.b.to_le(), 1);
}
}
assert_eq!(w.b, 0);
w.a = 1;
assert_eq!(w.a, 1);
- assert_eq!(w.b, 1);
+ assert_eq!(w.b.to_le(), 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.
+//
+// compile-flags: -O
+
+use std::collections::HashSet;
+
+#[derive(PartialEq, Debug, Hash, Eq, Clone, PartialOrd, Ord)]
+enum MyEnum {
+ E0,
+
+ E1,
+
+ E2,
+ E3,
+ E4,
+
+ E5,
+ E6,
+ E7,
+}
+
+
+fn main() {
+ use MyEnum::*;
+ let s: HashSet<_> = [E4, E1].iter().cloned().collect();
+ let mut v: Vec<_> = s.into_iter().collect();
+ v.sort();
+
+ assert_eq!([E1, E4], &v[..]);
+}
--- /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.
+
+#![crate_name = "foo"]
+
+mod foo {
+ pub use bar::*;
+ pub mod bar {
+ pub trait Foo {
+ fn foo();
+ }
+ }
+}
+
+// @count foo/index.html '//*[@class="trait"]' 1
+pub use foo::bar::*;
+pub use 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.
+
+#![feature(non_ascii_idents)]
+
+pub fn main () {}
+
+fn საჭმელად_გემრიელი_სადილი ( ) -> isize {
+}
--- /dev/null
+error[E0308]: mismatched types
+ --> $DIR/issue-44023.rs:15:42
+ |
+15 | fn საჭმელად_გემრიელი_სადილი ( ) -> isize {
+ | __________________________________________^
+16 | | }
+ | |_^ expected isize, found ()
+ |
+ = note: expected type `isize`
+ found type `()`
+
+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() {
+ "😊"";
+}
--- /dev/null
+error: unterminated double quote string
+ --> $DIR/issue-44078.rs:12:8
+ |
+12 | "😊"";
+ | ________^
+13 | | }
+ | |__^
+
+error: aborting due to previous error
+
-error[E0308]: mismatched types
+error[E0623]: lifetime mismatch
--> $DIR/ex2b-push-no-existing-names.rs:16:12
|
+15 | fn foo(x: &mut Vec<Ref<i32>>, y: Ref<i32>) {
+ | -------- -------- these two types are declared with different lifetimes...
16 | x.push(y);
- | ^ lifetime mismatch
- |
- = note: expected type `Ref<'_, _>`
- found type `Ref<'_, _>`
-note: the anonymous lifetime #3 defined on the function body at 15:1...
- --> $DIR/ex2b-push-no-existing-names.rs:15:1
- |
-15 | / fn foo(x: &mut Vec<Ref<i32>>, y: Ref<i32>) {
-16 | | x.push(y);
-17 | | }
- | |_^
-note: ...does not necessarily outlive the anonymous lifetime #2 defined on the function body at 15:1
- --> $DIR/ex2b-push-no-existing-names.rs:15:1
- |
-15 | / fn foo(x: &mut Vec<Ref<i32>>, y: Ref<i32>) {
-16 | | x.push(y);
-17 | | }
- | |_^
+ | ^ ...but data from `y` flows into `x` here
error: aborting due to previous error
--> $DIR/ex3-both-anon-regions-2.rs:12:9
|
11 | fn foo((v, w): (&u8, &u8), x: &u8) {
- | --- --- these references are not declared with the same lifetime...
+ | --- --- these two types are declared with different lifetimes...
12 | v = x;
| ^ ...but data from `x` flows here
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-fn foo((v, w): (&u8, &u8), (x, y): (&u8, &u8)) {
- v = x;
+fn foo(z: &mut Vec<(&u8,&u8)>, (x, y): (&u8, &u8)) {
+ z.push((x,y));
}
fn main() { }
+
error[E0623]: lifetime mismatch
- --> $DIR/ex3-both-anon-regions-3.rs:12:9
+ --> $DIR/ex3-both-anon-regions-3.rs:12:13
|
-11 | fn foo((v, w): (&u8, &u8), (x, y): (&u8, &u8)) {
- | --- --- these references are not declared with the same lifetime...
-12 | v = x;
- | ^ ...but data flows here
+11 | fn foo(z: &mut Vec<(&u8,&u8)>, (x, y): (&u8, &u8)) {
+ | --- --- these two types are declared with different lifetimes...
+12 | z.push((x,y));
+ | ^ ...but data flows into `z` here
-error: aborting due to previous error
+error[E0623]: lifetime mismatch
+ --> $DIR/ex3-both-anon-regions-3.rs:12:15
+ |
+11 | fn foo(z: &mut Vec<(&u8,&u8)>, (x, y): (&u8, &u8)) {
+ | --- --- these two types are declared with different lifetimes...
+12 | z.push((x,y));
+ | ^ ...but data flows into `z` here
+
+error: aborting due to 2 previous errors
+++ /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.
-
-fn foo(z: &mut Vec<(&u8,&u8)>, (x, y): (&u8, &u8)) {
- z.push((x,y));
-}
+++ /dev/null
-error[E0601]: main function not found
-
-error[E0623]: lifetime mismatch
- --> $DIR/ex3-both-anon-regions-4.rs:12:13
- |
-11 | fn foo(z: &mut Vec<(&u8,&u8)>, (x, y): (&u8, &u8)) {
- | --- --- these references are not declared with the same lifetime...
-12 | z.push((x,y));
- | ^ ...but data flows into `z` here
-
-error[E0623]: lifetime mismatch
- --> $DIR/ex3-both-anon-regions-4.rs:12:15
- |
-11 | fn foo(z: &mut Vec<(&u8,&u8)>, (x, y): (&u8, &u8)) {
- | --- --- these references are not declared with the same lifetime...
-12 | z.push((x,y));
- | ^ ...but data flows into `z` here
-
-error: aborting due to 3 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.
+struct Ref<'a, 'b> {
+ a: &'a u32,
+ b: &'b u32,
+}
+
+fn foo(mut x: Ref, y: Ref) {
+ x.b = y.b;
+}
+
+fn main() {}
--- /dev/null
+error[E0623]: lifetime mismatch
+ --> $DIR/ex3-both-anon-regions-both-are-structs-2.rs:16:11
+ |
+15 | fn foo(mut x: Ref, y: Ref) {
+ | --- --- these two types are declared with different lifetimes...
+16 | x.b = y.b;
+ | ^^^ ...but data from `y` flows into `x` here
+
+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.
+struct Ref<'a, 'b> {
+ a: &'a u32,
+ b: &'b u32,
+}
+
+fn foo(mut x: Ref) {
+ x.a = x.b;
+}
+
+fn main() {}
\ No newline at end of file
--- /dev/null
+error[E0623]: lifetime mismatch
+ --> $DIR/ex3-both-anon-regions-both-are-structs-3.rs:16:11
+ |
+15 | fn foo(mut x: Ref) {
+ | ---
+ | |
+ | this type was declared with multiple lifetimes...
+16 | x.a = x.b;
+ | ^^^ ...but data with one lifetime flows into the other here
+
+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.
+struct Ref<'a> {
+ x: &'a u32,
+}
+
+fn foo(mut x: Vec<Ref>, y: Ref) {
+ x.push(y);
+}
+
+fn main() {}
--- /dev/null
+error[E0623]: lifetime mismatch
+ --> $DIR/ex3-both-anon-regions-both-are-structs.rs:15:12
+ |
+14 | fn foo(mut x: Vec<Ref>, y: Ref) {
+ | --- --- these two types are declared with different lifetimes...
+15 | x.push(y);
+ | ^ ...but data from `y` flows into `x` here
+
+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.
+
+struct Ref<'a, 'b> { a: &'a u32, b: &'b u32 }
+
+fn foo(mut x: Ref, y: &u32) {
+ y = x.b;
+}
+
+fn main() { }
--- /dev/null
+error[E0623]: lifetime mismatch
+ --> $DIR/ex3-both-anon-regions-one-is-struct-2.rs:14:9
+ |
+13 | fn foo(mut x: Ref, y: &u32) {
+ | --- ----
+ | |
+ | these two types are declared with different lifetimes...
+14 | y = x.b;
+ | ^^^ ...but data from `x` flows into `y` here
+
+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.
+
+struct Ref<'a, 'b> { a: &'a u32, b: &'b u32 }
+
+fn foo(mut y: Ref, x: &u32) {
+ y.b = x;
+}
+
+fn main() { }
--- /dev/null
+error[E0623]: lifetime mismatch
+ --> $DIR/ex3-both-anon-regions-one-is-struct-3.rs:14:11
+ |
+13 | fn foo(mut y: Ref, x: &u32) {
+ | --- ---- these two types are declared with different lifetimes...
+14 | y.b = x;
+ | ^ ...but data from `x` flows into `y` here
+
+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.
+
+struct Ref<'a, 'b> {
+ a: &'a u32,
+ b: &'b u32,
+}
+
+fn foo(mut x: Ref, y: &u32) {
+ x.b = y;
+}
+
+fn main() {}
--- /dev/null
+error[E0623]: lifetime mismatch
+ --> $DIR/ex3-both-anon-regions-one-is-struct.rs:17:11
+ |
+16 | fn foo(mut x: Ref, y: &u32) {
+ | --- ---- these two types are declared with different lifetimes...
+17 | x.b = y;
+ | ^ ...but data from `y` flows into `x` here
+
+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.
+
+struct Foo {
+ field: i32
+}
+
+impl Foo {
+ fn foo<'a>(&self, x: &i32) -> &i32 {
+ x
+ }
+}
+
+fn main() { }
+
--- /dev/null
+error[E0312]: lifetime of reference outlives lifetime of borrowed content...
+ --> $DIR/ex3-both-anon-regions-return-type-is-anon.rs:17:5
+ |
+17 | x
+ | ^
+ |
+note: ...the reference is valid for the anonymous lifetime #1 defined on the method body at 16:3...
+ --> $DIR/ex3-both-anon-regions-return-type-is-anon.rs:16:3
+ |
+16 | / fn foo<'a>(&self, x: &i32) -> &i32 {
+17 | | x
+18 | | }
+ | |___^
+note: ...but the borrowed content is only valid for the anonymous lifetime #2 defined on the method body at 16:3
+ --> $DIR/ex3-both-anon-regions-return-type-is-anon.rs:16:3
+ |
+16 | / fn foo<'a>(&self, x: &i32) -> &i32 {
+17 | | x
+18 | | }
+ | |___^
+
+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.
+
+struct Foo {
+ field: i32,
+}
+
+impl Foo {
+ fn foo<'a>(&self, x: &Foo) -> &Foo {
+ if true { x } else { self }
+ }
+}
+
+fn main() {}
+
--- /dev/null
+error[E0312]: lifetime of reference outlives lifetime of borrowed content...
+ --> $DIR/ex3-both-anon-regions-self-is-anon.rs:17:19
+ |
+17 | if true { x } else { self }
+ | ^
+ |
+note: ...the reference is valid for the anonymous lifetime #1 defined on the method body at 16:5...
+ --> $DIR/ex3-both-anon-regions-self-is-anon.rs:16:5
+ |
+16 | / fn foo<'a>(&self, x: &Foo) -> &Foo {
+17 | | if true { x } else { self }
+18 | | }
+ | |_____^
+note: ...but the borrowed content is only valid for the anonymous lifetime #2 defined on the method body at 16:5
+ --> $DIR/ex3-both-anon-regions-self-is-anon.rs:16:5
+ |
+16 | / fn foo<'a>(&self, x: &Foo) -> &Foo {
+17 | | if true { x } else { self }
+18 | | }
+ | |_____^
+
+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.
+trait Foo {
+ fn foo<'a>(x: &mut Vec<&u8>, y: &u8);
+}
+impl Foo for () {
+ fn foo(x: &mut Vec<&u8>, y: &u8) {
+ x.push(y);
+ }
+}
+fn main() {}
--- /dev/null
+error[E0623]: lifetime mismatch
+ --> $DIR/ex3-both-anon-regions-using-impl-items.rs:15:16
+ |
+14 | fn foo(x: &mut Vec<&u8>, y: &u8) {
+ | --- --- these two types are declared with different lifetimes...
+15 | x.push(y);
+ | ^ ...but data from `y` flows into `x` here
+
+error: aborting due to previous error
+
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// 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.
//
--> $DIR/ex3-both-anon-regions.rs:12:12
|
11 | fn foo(x: &mut Vec<&u8>, y: &u8) {
- | --- --- these references are not declared with the same lifetime...
+ | --- --- these two types are declared with different lifetimes...
12 | x.push(y);
| ^ ...but data from `y` flows into `x` here
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+#![feature(fn_must_use)]
#![warn(unused_must_use)]
struct MyStruct {
warning: unused return value of `need_to_use_this_value` which must be used: it's important
- --> $DIR/fn_must_use.rs:30:5
+ --> $DIR/fn_must_use.rs:31:5
|
-30 | need_to_use_this_value();
+31 | need_to_use_this_value();
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: lint level defined here
- --> $DIR/fn_must_use.rs:11:9
+ --> $DIR/fn_must_use.rs:12:9
|
-11 | #![warn(unused_must_use)]
+12 | #![warn(unused_must_use)]
| ^^^^^^^^^^^^^^^
warning: unused return value of `MyStruct::need_to_use_this_method_value` which must be used
- --> $DIR/fn_must_use.rs:33:5
+ --> $DIR/fn_must_use.rs:34:5
|
-33 | m.need_to_use_this_method_value();
+34 | m.need_to_use_this_method_value();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-Subproject commit 7704f7b1fd52607104cc7fdc435d636c9de1fe90
+Subproject commit 3d3f2c05d742e5f907e951aa8849b03f0bc1a895
#![deny(warnings)]
+#[cfg(any(target_os = "macos", target_os = "ios"))]
extern crate libc;
extern crate test;
extern crate getopts;
use self::header::EarlyProps;
-pub mod procsrv;
pub mod util;
mod json;
pub mod header;
+++ /dev/null
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <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::env;
-use std::ffi::OsString;
-use std::io::prelude::*;
-use std::io;
-use std::path::PathBuf;
-use std::process::{Child, Command, ExitStatus, Output, Stdio};
-
-/// Get the name of the environment variable that holds dynamic library
-/// locations
-pub fn dylib_env_var() -> &'static str {
- if cfg!(windows) {
- "PATH"
- } else if cfg!(target_os = "macos") {
- "DYLD_LIBRARY_PATH"
- } else if cfg!(target_os = "haiku") {
- "LIBRARY_PATH"
- } else {
- "LD_LIBRARY_PATH"
- }
-}
-
-/// Add `lib_path` and `aux_path` (if it is `Some`) to the dynamic library
-/// env var
-fn add_target_env(cmd: &mut Command, lib_path: &str, aux_path: Option<&str>) {
- // Need to be sure to put both the lib_path and the aux path in the dylib
- // search path for the child.
- let var = dylib_env_var();
- let mut path = env::split_paths(&env::var_os(var).unwrap_or(OsString::new()))
- .collect::<Vec<_>>();
- if let Some(p) = aux_path {
- path.insert(0, PathBuf::from(p))
- }
- path.insert(0, PathBuf::from(lib_path));
-
- // Add the new dylib search path var
- let newpath = env::join_paths(&path).unwrap();
- cmd.env(var, newpath);
-}
-
-/// Represents exit status, stdout and stderr of a completed process
-pub struct Result {
- pub status: ExitStatus,
- pub out: String,
- pub err: String,
-}
-
-/// Runs a test program
-///
-/// # Params
-/// - `lib_path` Path to search for required library
-/// - `prog` command to run
-/// - `aux_path` Optional extra path to search for required
-/// auxiliary libraries
-/// - `args` List of arguments to pass to `prog`
-/// - `env` List of environment variables to set, `.0` is variable name,
-/// `.1` is value
-/// - `input` String to be fed as stdin
-/// - `current_dir` Optional working dir to run command in
-///
-pub fn run(lib_path: &str,
- prog: &str,
- aux_path: Option<&str>,
- args: &[String],
- env: Vec<(String, String)>,
- input: Option<String>,
- current_dir: Option<String>)
- -> io::Result<Result> {
-
- let mut cmd = Command::new(prog);
- cmd.args(args)
- .stdout(Stdio::piped())
- .stderr(Stdio::piped())
- .stdin(Stdio::piped());
-
- add_target_env(&mut cmd, lib_path, aux_path);
- for (key, val) in env {
- cmd.env(&key, &val);
- }
- if let Some(cwd) = current_dir {
- cmd.current_dir(cwd);
- }
-
- let mut process = cmd.spawn()?;
- if let Some(input) = input {
- process.stdin.as_mut().unwrap().write_all(input.as_bytes()).unwrap();
- }
- let Output { status, stdout, stderr } = process.wait_with_output().unwrap();
-
- Ok(Result {
- status,
- out: String::from_utf8(stdout).unwrap(),
- err: String::from_utf8(stderr).unwrap(),
- })
-}
-
-/// Same as `run`, but return process rather than waiting on completion
-pub fn run_background(lib_path: &str,
- prog: &str,
- aux_path: Option<&str>,
- args: &[String],
- env: Vec<(String, String)>,
- input: Option<String>,
- current_dir: Option<String>)
- -> io::Result<Child> {
-
- let mut cmd = Command::new(prog);
- cmd.args(args)
- .stdin(Stdio::piped())
- .stdout(Stdio::piped());
- add_target_env(&mut cmd, lib_path, aux_path);
- for (key, val) in env {
- cmd.env(&key, &val);
- }
- if let Some(cwd) = current_dir {
- cmd.current_dir(cwd);
- }
-
- let mut process = cmd.spawn()?;
- if let Some(input) = input {
- process.stdin.as_mut().unwrap().write_all(input.as_bytes()).unwrap();
- }
-
- Ok(process)
-}
use filetime::FileTime;
use json;
use header::TestProps;
-use procsrv;
use test::TestPaths;
use util::logv;
+use std::collections::HashMap;
use std::collections::HashSet;
use std::env;
+use std::ffi::OsString;
use std::fs::{self, File, create_dir_all};
use std::io::prelude::*;
use std::io::{self, BufReader};
use std::path::{Path, PathBuf};
-use std::process::{Command, Output, ExitStatus};
+use std::process::{Command, Output, ExitStatus, Stdio};
use std::str;
-use std::collections::HashMap;
use extract_gdb_version;
+/// The name of the environment variable that holds dynamic library locations.
+pub fn dylib_env_var() -> &'static str {
+ if cfg!(windows) {
+ "PATH"
+ } else if cfg!(target_os = "macos") {
+ "DYLD_LIBRARY_PATH"
+ } else if cfg!(target_os = "haiku") {
+ "LIBRARY_PATH"
+ } else {
+ "LD_LIBRARY_PATH"
+ }
+}
+
pub fn run(config: Config, testpaths: &TestPaths) {
match &*config.target {
}
}
- fn print_source(&self,
- src: String,
- pretty_type: &str)
- -> ProcRes {
+ fn print_source(&self, src: String, pretty_type: &str) -> ProcRes {
let aux_dir = self.aux_output_dir_name();
- self.compose_and_run(self.make_pp_args(pretty_type.to_owned()),
- self.props.exec_env.clone(),
+
+ let mut rustc = Command::new(&self.config.rustc_path);
+ rustc.arg("-")
+ .arg("-Zunstable-options")
+ .args(&["--unpretty", &pretty_type])
+ .args(&["--target", &self.config.target])
+ .arg("-L").arg(&aux_dir)
+ .args(self.split_maybe_args(&self.config.target_rustcflags))
+ .args(&self.props.compile_flags)
+ .envs(self.props.exec_env.clone());
+
+ self.compose_and_run(rustc,
self.config.compile_lib_path.to_str().unwrap(),
Some(aux_dir.to_str().unwrap()),
- Some(src),
- None)
- }
-
- fn make_pp_args(&self,
- pretty_type: String)
- -> ProcArgs {
- let aux_dir = self.aux_output_dir_name();
- // FIXME (#9639): This needs to handle non-utf8 paths
- let mut args = vec!["-".to_owned(),
- "-Zunstable-options".to_owned(),
- "--unpretty".to_owned(),
- pretty_type,
- format!("--target={}", self.config.target),
- "-L".to_owned(),
- aux_dir.to_str().unwrap().to_owned()];
- args.extend(self.split_maybe_args(&self.config.target_rustcflags));
- args.extend(self.props.compile_flags.iter().cloned());
- ProcArgs {
- prog: self.config.rustc_path.to_str().unwrap().to_owned(),
- args,
- }
+ Some(src))
}
fn compare_source(&self,
}
fn typecheck_source(&self, src: String) -> ProcRes {
- let args = self.make_typecheck_args();
- self.compose_and_run_compiler(args, Some(src))
- }
+ let mut rustc = Command::new(&self.config.rustc_path);
+
+ let out_dir = self.output_base_name().with_extension("pretty-out");
+ let _ = fs::remove_dir_all(&out_dir);
+ create_dir_all(&out_dir).unwrap();
- fn make_typecheck_args(&self) -> ProcArgs {
- let aux_dir = self.aux_output_dir_name();
let target = if self.props.force_host {
&*self.config.host
} else {
&*self.config.target
};
- let out_dir = self.output_base_name().with_extension("pretty-out");
- let _ = fs::remove_dir_all(&out_dir);
- create_dir_all(&out_dir).unwrap();
+ let aux_dir = self.aux_output_dir_name();
+
+ rustc.arg("-")
+ .arg("-Zno-trans")
+ .arg("--out-dir").arg(&out_dir)
+ .arg(&format!("--target={}", target))
+ .arg("-L").arg(&self.config.build_base)
+ .arg("-L").arg(aux_dir);
- // FIXME (#9639): This needs to handle non-utf8 paths
- let mut args = vec!["-".to_owned(),
- "-Zno-trans".to_owned(),
- "--out-dir".to_owned(),
- out_dir.to_str().unwrap().to_owned(),
- format!("--target={}", target),
- "-L".to_owned(),
- self.config.build_base.to_str().unwrap().to_owned(),
- "-L".to_owned(),
- aux_dir.to_str().unwrap().to_owned()];
if let Some(revision) = self.revision {
- args.extend(vec![
- "--cfg".to_string(),
- revision.to_string(),
- ]);
- }
- args.extend(self.split_maybe_args(&self.config.target_rustcflags));
- args.extend(self.props.compile_flags.iter().cloned());
- // FIXME (#9639): This needs to handle non-utf8 paths
- ProcArgs {
- prog: self.config.rustc_path.to_str().unwrap().to_owned(),
- args,
+ rustc.args(&["--cfg", revision]);
}
+
+ rustc.args(self.split_maybe_args(&self.config.target_rustcflags));
+ rustc.args(&self.props.compile_flags);
+
+ self.compose_and_run_compiler(rustc, Some(src))
}
fn run_debuginfo_gdb_test(&self) {
debug!("script_str = {}", script_str);
self.dump_output_file(&script_str, "debugger.script");
+ let adb_path = &self.config.adb_path;
- procsrv::run("",
- &self.config.adb_path,
- None,
- &[
- "push".to_owned(),
- exe_file.to_str().unwrap().to_owned(),
- self.config.adb_test_dir.clone()
- ],
- Vec::new(),
- None,
- None)
- .expect(&format!("failed to exec `{:?}`", self.config.adb_path));
-
- procsrv::run("",
- &self.config.adb_path,
- None,
- &[
- "forward".to_owned(),
- "tcp:5039".to_owned(),
- "tcp:5039".to_owned()
- ],
- Vec::new(),
- None,
- None)
- .expect(&format!("failed to exec `{:?}`", self.config.adb_path));
+ Command::new(adb_path)
+ .arg("push")
+ .arg(&exe_file)
+ .arg(&self.config.adb_test_dir)
+ .status()
+ .expect(&format!("failed to exec `{:?}`", adb_path));
+
+ Command::new(adb_path)
+ .args(&["forward", "tcp:5039", "tcp:5039"])
+ .status()
+ .expect(&format!("failed to exec `{:?}`", adb_path));
let adb_arg = format!("export LD_LIBRARY_PATH={}; \
gdbserver{} :5039 {}/{}",
.unwrap());
debug!("adb arg: {}", adb_arg);
- let mut process = procsrv::run_background("",
- &self.config.adb_path
- ,
- None,
- &[
- "shell".to_owned(),
- adb_arg.clone()
- ],
- Vec::new(),
- None,
- None)
- .expect(&format!("failed to exec `{:?}`", self.config.adb_path));
+ let mut adb = Command::new(adb_path)
+ .args(&["shell", &adb_arg])
+ .stdout(Stdio::piped())
+ .stderr(Stdio::inherit())
+ .spawn()
+ .expect(&format!("failed to exec `{:?}`", adb_path));
// Wait for the gdbserver to print out "Listening on port ..."
// at which point we know that it's started and then we can
// execute the debugger below.
- let mut stdout = BufReader::new(process.stdout.take().unwrap());
+ let mut stdout = BufReader::new(adb.stdout.take().unwrap());
let mut line = String::new();
loop {
line.truncate(0);
let mut gdb_path = tool_path;
gdb_path.push_str("/bin/gdb");
- let procsrv::Result {
- out,
- err,
- status
- } = procsrv::run("",
- &gdb_path,
- None,
- &debugger_opts,
- Vec::new(),
- None,
- None)
+ let Output {
+ status,
+ stdout,
+ stderr
+ } = Command::new(&gdb_path)
+ .args(&debugger_opts)
+ .output()
.expect(&format!("failed to exec `{:?}`", gdb_path));
let cmdline = {
- let cmdline = self.make_cmdline("",
- &format!("{}-gdb", self.config.target),
- &debugger_opts);
+ let mut gdb = Command::new(&format!("{}-gdb", self.config.target));
+ gdb.args(&debugger_opts);
+ let cmdline = self.make_cmdline(&gdb, "");
logv(self.config, format!("executing {}", cmdline));
cmdline
};
debugger_run_result = ProcRes {
status,
- stdout: out,
- stderr: err,
+ stdout: String::from_utf8(stdout).unwrap(),
+ stderr: String::from_utf8(stderr).unwrap(),
cmdline,
};
- if process.kill().is_err() {
+ if adb.kill().is_err() {
println!("Adb process is already finished.");
}
}
"-nx".to_owned(),
format!("-command={}", debugger_script.to_str().unwrap())];
- let proc_args = ProcArgs {
- prog: self.config.gdb.as_ref().unwrap().to_owned(),
- args: debugger_opts,
- };
-
- let environment = vec![("PYTHONPATH".to_owned(), rust_pp_module_abs_path)];
+ let mut gdb = Command::new(self.config.gdb.as_ref().unwrap());
+ gdb.args(&debugger_opts)
+ .env("PYTHONPATH", rust_pp_module_abs_path);
debugger_run_result =
- self.compose_and_run(proc_args,
- environment,
+ self.compose_and_run(gdb,
self.config.run_lib_path.to_str().unwrap(),
None,
- None,
None);
}
}
}
fn compile_test(&self) -> ProcRes {
- let aux_dir = self.aux_output_dir_name();
- // FIXME (#9639): This needs to handle non-utf8 paths
- let mut extra_args = vec!["-L".to_owned(),
- aux_dir.to_str().unwrap().to_owned()];
+ let mut rustc = self.make_compile_args(
+ &self.testpaths.file, TargetLocation::ThisFile(self.make_exe_name()));
+
+ rustc.arg("-L").arg(&self.aux_output_dir_name());
+
match self.config.mode {
CompileFail | Ui => {
// compile-fail and ui tests tend to have tons of unused code as
// want to actually assert warnings about all this code. Instead
// let's just ignore unused code warnings by defaults and tests
// can turn it back on if needed.
- extra_args.push("-A".to_owned());
- extra_args.push("unused".to_owned());
+ rustc.args(&["-A", "unused"]);
}
_ => {}
}
- let args = self.make_compile_args(extra_args,
- &self.testpaths.file,
- TargetLocation::ThisFile(self.make_exe_name()));
- self.compose_and_run_compiler(args, None)
+
+ self.compose_and_run_compiler(rustc, None)
}
fn document(&self, out_dir: &Path) -> ProcRes {
}
let aux_dir = self.aux_output_dir_name();
- let mut args = vec!["-L".to_owned(),
- aux_dir.to_str().unwrap().to_owned(),
- "-o".to_owned(),
- out_dir.to_str().unwrap().to_owned(),
- self.testpaths.file.to_str().unwrap().to_owned()];
- args.extend(self.props.compile_flags.iter().cloned());
- let args = ProcArgs {
- prog: self.config.rustdoc_path
- .as_ref().expect("--rustdoc-path passed").to_str().unwrap().to_owned(),
- args,
- };
- self.compose_and_run_compiler(args, None)
+
+ let rustdoc_path = self.config.rustdoc_path.as_ref().expect("--rustdoc-path passed");
+ let mut rustdoc = Command::new(rustdoc_path);
+
+ rustdoc.arg("-L").arg(aux_dir)
+ .arg("-o").arg(out_dir)
+ .arg(&self.testpaths.file)
+ .args(&self.props.compile_flags);
+
+ self.compose_and_run_compiler(rustdoc, None)
}
fn exec_compiled_test(&self) -> ProcRes {
- let env = self.props.exec_env.clone();
+ let env = &self.props.exec_env;
match &*self.config.target {
// This is pretty similar to below, we're transforming:
// the process) and then report back the same result.
_ if self.config.remote_test_client.is_some() => {
let aux_dir = self.aux_output_dir_name();
- let mut args = self.make_run_args();
- let mut program = args.prog.clone();
+ let ProcArgs { mut prog, args } = self.make_run_args();
if let Ok(entries) = aux_dir.read_dir() {
for entry in entries {
let entry = entry.unwrap();
if !entry.path().is_file() {
continue
}
- program.push_str(":");
- program.push_str(entry.path().to_str().unwrap());
+ prog.push_str(":");
+ prog.push_str(entry.path().to_str().unwrap());
}
}
- args.args.insert(0, program);
- args.args.insert(0, "run".to_string());
- args.prog = self.config.remote_test_client.clone().unwrap()
- .into_os_string().into_string().unwrap();
- self.compose_and_run(args,
- env,
+ let mut test_client = Command::new(
+ self.config.remote_test_client.as_ref().unwrap());
+ test_client
+ .args(&["run", &prog])
+ .args(args)
+ .envs(env.clone());
+ self.compose_and_run(test_client,
self.config.run_lib_path.to_str().unwrap(),
Some(aux_dir.to_str().unwrap()),
- None,
None)
}
_ => {
let aux_dir = self.aux_output_dir_name();
- let working_dir =
- Some(self.output_base_name()
- .parent().unwrap()
- .to_str().unwrap().to_owned());
- self.compose_and_run(self.make_run_args(),
- env,
+ let ProcArgs { prog, args } = self.make_run_args();
+ let mut program = Command::new(&prog);
+ program.args(args)
+ .current_dir(&self.output_base_name().parent().unwrap())
+ .envs(env.clone());
+ self.compose_and_run(program,
self.config.run_lib_path.to_str().unwrap(),
Some(aux_dir.to_str().unwrap()),
- None,
- working_dir)
+ None)
}
}
}
}
}
- fn compose_and_run_compiler(&self, args: ProcArgs, input: Option<String>) -> ProcRes {
+ fn compose_and_run_compiler(&self, mut rustc: Command, input: Option<String>) -> ProcRes {
if !self.props.aux_builds.is_empty() {
create_dir_all(&self.aux_output_dir_name()).unwrap();
}
let aux_dir = self.aux_output_dir_name();
- // FIXME (#9639): This needs to handle non-utf8 paths
- let extra_link_args = vec!["-L".to_owned(),
- aux_dir.to_str().unwrap().to_owned()];
for rel_ab in &self.props.aux_builds {
let aux_testpaths = self.compute_aux_test_paths(rel_ab);
let aux_props = self.props.from_aux_file(&aux_testpaths.file,
self.revision,
self.config);
- let mut crate_type = if aux_props.no_prefer_dynamic {
- Vec::new()
+ let aux_output = {
+ let f = self.make_lib_name(&self.testpaths.file);
+ let parent = f.parent().unwrap();
+ TargetLocation::ThisDirectory(parent.to_path_buf())
+ };
+ let aux_cx = TestCx {
+ config: self.config,
+ props: &aux_props,
+ testpaths: &aux_testpaths,
+ revision: self.revision
+ };
+ let mut aux_rustc = aux_cx.make_compile_args(&aux_testpaths.file, aux_output);
+
+ let crate_type = if aux_props.no_prefer_dynamic {
+ None
} else if (self.config.target.contains("musl") && !aux_props.force_host) ||
self.config.target.contains("emscripten") {
// We primarily compile all auxiliary libraries as dynamic libraries
// dynamic libraries so we just go back to building a normal library. Note,
// however, that for MUSL if the library is built with `force_host` then
// it's ok to be a dylib as the host should always support dylibs.
- vec!["--crate-type=lib".to_owned()]
+ Some("lib")
} else {
- vec!["--crate-type=dylib".to_owned()]
- };
- crate_type.extend(extra_link_args.clone());
- let aux_output = {
- let f = self.make_lib_name(&self.testpaths.file);
- let parent = f.parent().unwrap();
- TargetLocation::ThisDirectory(parent.to_path_buf())
+ Some("dylib")
};
- let aux_cx = TestCx {
- config: self.config,
- props: &aux_props,
- testpaths: &aux_testpaths,
- revision: self.revision
- };
- let aux_args = aux_cx.make_compile_args(crate_type, &aux_testpaths.file, aux_output);
- let auxres = aux_cx.compose_and_run(aux_args,
- Vec::new(),
+
+ if let Some(crate_type) = crate_type {
+ aux_rustc.args(&["--crate-type", crate_type]);
+ }
+
+ aux_rustc.arg("-L").arg(&aux_dir);
+
+ let auxres = aux_cx.compose_and_run(aux_rustc,
aux_cx.config.compile_lib_path.to_str().unwrap(),
Some(aux_dir.to_str().unwrap()),
- None,
None);
if !auxres.status.success() {
self.fatal_proc_rec(
}
}
- self.compose_and_run(args,
- self.props.rustc_env.clone(),
+ rustc.envs(self.props.rustc_env.clone());
+ self.compose_and_run(rustc,
self.config.compile_lib_path.to_str().unwrap(),
Some(aux_dir.to_str().unwrap()),
- input,
- None)
+ input)
}
fn compose_and_run(&self,
- ProcArgs{ args, prog }: ProcArgs,
- procenv: Vec<(String, String)> ,
+ mut command: Command,
lib_path: &str,
aux_path: Option<&str>,
- input: Option<String>,
- working_dir: Option<String>) -> ProcRes {
- self.program_output(lib_path, prog, aux_path, args, procenv, input, working_dir)
- }
+ input: Option<String>) -> ProcRes {
+ let cmdline =
+ {
+ let cmdline = self.make_cmdline(&command, lib_path);
+ logv(self.config, format!("executing {}", cmdline));
+ cmdline
+ };
- fn make_compile_args(&self,
- extras: Vec<String> ,
- input_file: &Path,
- output_file: TargetLocation)
- -> ProcArgs
- {
- let target = if self.props.force_host {
- &*self.config.host
- } else {
- &*self.config.target
+ command
+ .stdout(Stdio::piped())
+ .stderr(Stdio::piped())
+ .stdin(Stdio::piped());
+
+ // Need to be sure to put both the lib_path and the aux path in the dylib
+ // search path for the child.
+ let mut path = env::split_paths(&env::var_os(dylib_env_var()).unwrap_or(OsString::new()))
+ .collect::<Vec<_>>();
+ if let Some(p) = aux_path {
+ path.insert(0, PathBuf::from(p))
+ }
+ path.insert(0, PathBuf::from(lib_path));
+
+ // Add the new dylib search path var
+ let newpath = env::join_paths(&path).unwrap();
+ command.env(dylib_env_var(), newpath);
+
+ let mut child = command.spawn().expect(&format!("failed to exec `{:?}`", &command));
+ if let Some(input) = input {
+ child.stdin.as_mut().unwrap().write_all(input.as_bytes()).unwrap();
+ }
+ let Output { status, stdout, stderr } = child.wait_with_output().unwrap();
+
+ let result = ProcRes {
+ status,
+ stdout: String::from_utf8(stdout).unwrap(),
+ stderr: String::from_utf8(stderr).unwrap(),
+ cmdline,
};
- // FIXME (#9639): This needs to handle non-utf8 paths
- let mut args = vec![input_file.to_str().unwrap().to_owned(),
- "-L".to_owned(),
- self.config.build_base.to_str().unwrap().to_owned()];
+ self.dump_output(&result.stdout, &result.stderr);
+
+ result
+ }
+
+ fn make_compile_args(&self, input_file: &Path, output_file: TargetLocation) -> Command {
+ let mut rustc = Command::new(&self.config.rustc_path);
+ rustc.arg(input_file)
+ .arg("-L").arg(&self.config.build_base);
// Optionally prevent default --target if specified in test compile-flags.
let custom_target = self.props.compile_flags
.fold(false, |acc, x| acc || x.starts_with("--target"));
if !custom_target {
- args.extend(vec![
- format!("--target={}", target),
- ]);
+ let target = if self.props.force_host {
+ &*self.config.host
+ } else {
+ &*self.config.target
+ };
+
+ rustc.arg(&format!("--target={}", target));
}
if let Some(revision) = self.revision {
- args.extend(vec![
- "--cfg".to_string(),
- revision.to_string(),
- ]);
+ rustc.args(&["--cfg", revision]);
}
if let Some(ref incremental_dir) = self.props.incremental_dir {
- args.extend(vec![
- "-Z".to_string(),
- format!("incremental={}", incremental_dir.display()),
- ]);
+ rustc.args(&["-Z", &format!("incremental={}", incremental_dir.display())]);
}
-
match self.config.mode {
CompileFail |
ParseFail |
// fashion, then you want JSON mode. Old-skool error
// patterns still match the raw compiler output.
if self.props.error_patterns.is_empty() {
- args.extend(["--error-format",
- "json"]
- .iter()
- .map(|s| s.to_string()));
+ rustc.args(&["--error-format", "json"]);
}
}
MirOpt => {
- args.extend(["-Zdump-mir=all",
- "-Zmir-opt-level=3",
- "-Zdump-mir-exclude-pass-number"]
- .iter()
- .map(|s| s.to_string()));
-
+ rustc.args(&[
+ "-Zdump-mir=all",
+ "-Zmir-opt-level=3",
+ "-Zdump-mir-exclude-pass-number"]);
let mir_dump_dir = self.get_mir_dump_dir();
create_dir_all(mir_dump_dir.as_path()).unwrap();
dir_opt.push_str(mir_dump_dir.to_str().unwrap());
debug!("dir_opt: {:?}", dir_opt);
- args.push(dir_opt);
+ rustc.arg(dir_opt);
}
RunPass |
RunFail |
}
}
- args.extend_from_slice(&extras);
if !self.props.no_prefer_dynamic {
- args.push("-C".to_owned());
- args.push("prefer-dynamic".to_owned());
+ rustc.args(&["-C", "prefer-dynamic"]);
}
- let path = match output_file {
+
+ match output_file {
TargetLocation::ThisFile(path) => {
- args.push("-o".to_owned());
- path
+ rustc.arg("-o").arg(path);
}
TargetLocation::ThisDirectory(path) => {
- args.push("--out-dir".to_owned());
- path
+ rustc.arg("--out-dir").arg(path);
}
- };
- args.push(path.to_str().unwrap().to_owned());
+ }
+
if self.props.force_host {
- args.extend(self.split_maybe_args(&self.config.host_rustcflags));
+ rustc.args(self.split_maybe_args(&self.config.host_rustcflags));
} else {
- args.extend(self.split_maybe_args(&self.config.target_rustcflags));
- }
- args.extend(self.props.compile_flags.iter().cloned());
- ProcArgs {
- prog: self.config.rustc_path.to_str().unwrap().to_owned(),
- args,
+ rustc.args(self.split_maybe_args(&self.config.target_rustcflags));
}
+
+ rustc.args(&self.props.compile_flags);
+
+ rustc
}
fn make_lib_name(&self, auxfile: &Path) -> PathBuf {
}
}
- fn program_output(&self,
- lib_path: &str,
- prog: String,
- aux_path: Option<&str>,
- args: Vec<String>,
- env: Vec<(String, String)>,
- input: Option<String>,
- working_dir: Option<String>)
- -> ProcRes {
- let cmdline =
- {
- let cmdline = self.make_cmdline(lib_path,
- &prog,
- &args);
- logv(self.config, format!("executing {}", cmdline));
- cmdline
- };
-
- let procsrv::Result {
- out,
- err,
- status
- } = procsrv::run(lib_path,
- &prog,
- aux_path,
- &args,
- env,
- input,
- working_dir).expect(&format!("failed to exec `{}`", prog));
- self.dump_output(&out, &err);
- ProcRes {
- status,
- stdout: out,
- stderr: err,
- cmdline,
- }
- }
-
- fn make_cmdline(&self, libpath: &str, prog: &str, args: &[String]) -> String {
+ fn make_cmdline(&self, command: &Command, libpath: &str) -> String {
use util;
// Linux and mac don't require adjusting the library search path
if cfg!(unix) {
- format!("{} {}", prog, args.join(" "))
+ format!("{:?}", command)
} else {
// Build the LD_LIBRARY_PATH variable as it would be seen on the command line
// for diagnostic purposes
format!("{}=\"{}\"", util::lib_path_env_var(), util::make_new_path(path))
}
- format!("{} {} {}", lib_path_cmd_prefix(libpath), prog, args.join(" "))
+ format!("{} {:?}", lib_path_cmd_prefix(libpath), command)
}
}
fn compile_test_and_save_ir(&self) -> ProcRes {
let aux_dir = self.aux_output_dir_name();
- // FIXME (#9639): This needs to handle non-utf8 paths
- let mut link_args = vec!["-L".to_owned(),
- aux_dir.to_str().unwrap().to_owned()];
- let llvm_args = vec!["--emit=llvm-ir".to_owned(),];
- link_args.extend(llvm_args);
- let args = self.make_compile_args(link_args,
- &self.testpaths.file,
- TargetLocation::ThisDirectory(
- self.output_base_name().parent()
- .unwrap()
- .to_path_buf()));
- self.compose_and_run_compiler(args, None)
+
+ let output_file = TargetLocation::ThisDirectory(
+ self.output_base_name().parent().unwrap().to_path_buf());
+ let mut rustc = self.make_compile_args(&self.testpaths.file, output_file);
+ rustc.arg("-L").arg(aux_dir)
+ .arg("--emit=llvm-ir");
+
+ self.compose_and_run_compiler(rustc, None)
}
fn check_ir_with_filecheck(&self) -> ProcRes {
let irfile = self.output_base_name().with_extension("ll");
- let prog = self.config.llvm_filecheck.as_ref().unwrap();
- let proc_args = ProcArgs {
- // FIXME (#9639): This needs to handle non-utf8 paths
- prog: prog.to_str().unwrap().to_owned(),
- args: vec![format!("-input-file={}", irfile.to_str().unwrap()),
- self.testpaths.file.to_str().unwrap().to_owned()]
- };
- self.compose_and_run(proc_args, Vec::new(), "", None, None, None)
+ let mut filecheck = Command::new(self.config.llvm_filecheck.as_ref().unwrap());
+ filecheck.arg("--input-file").arg(irfile)
+ .arg(&self.testpaths.file);
+ self.compose_and_run(filecheck, "", None, None)
}
fn run_codegen_test(&self) {
.env("RUSTDOC",
cwd.join(&self.config.rustdoc_path.as_ref().expect("--rustdoc-path passed")))
.env("TMPDIR", &tmpdir)
- .env("LD_LIB_PATH_ENVVAR", procsrv::dylib_env_var())
+ .env("LD_LIB_PATH_ENVVAR", dylib_env_var())
.env("HOST_RPATH_DIR", cwd.join(&self.config.compile_lib_path))
.env("TARGET_RPATH_DIR", cwd.join(&self.config.run_lib_path))
.env("LLVM_COMPONENTS", &self.config.llvm_components)
-Subproject commit 5d4bbd9052fe2af849a7d017b85df98ad002c20f
+Subproject commit 25ffb3a3d7809b4fa112f3e04e926eb539dd5e90