mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-26 08:44:35 +00:00
Merge from rustc
This commit is contained in:
commit
697d130844
@ -20,3 +20,6 @@ trim_trailing_whitespace = false
|
||||
|
||||
[*.yml]
|
||||
indent_size = 2
|
||||
|
||||
[Makefile]
|
||||
indent_style = tab
|
||||
|
@ -12,3 +12,5 @@ a06baa56b95674fc626b3c3fd680d6a65357fe60
|
||||
c34fbfaad38cf5829ef5cfe780dc9d58480adeaa
|
||||
# move tests
|
||||
cf2dff2b1e3fa55fa5415d524200070d0d7aacfe
|
||||
# Run rustfmt on bootstrap
|
||||
b39a1d6f1a30ba29f25d7141038b9a5bf0126e36
|
||||
|
@ -12,7 +12,7 @@ Tracking issues are for tracking a feature from implementation to stabilization.
|
||||
Make sure to include the relevant RFC for the feature if it has one.
|
||||
|
||||
If the new feature is small, it may be fine to skip the RFC process. In that
|
||||
case, you can use use `issue = "none"` in your initial implementation PR. The
|
||||
case, you can use `issue = "none"` in your initial implementation PR. The
|
||||
reviewer will ask you to open a tracking issue if they agree your feature can be
|
||||
added without an RFC.
|
||||
-->
|
||||
@ -65,7 +65,7 @@ the rfcbot will ask all the team members to verify they agree with
|
||||
stabilization. Once enough members agree and there are no concerns, the final
|
||||
comment period begins: this issue will be marked as such and will be listed
|
||||
in the next This Week in Rust newsletter. If no blocking concerns are raised in
|
||||
that period of 10 days, a stabilzation PR can be opened by anyone.
|
||||
that period of 10 days, a stabilization PR can be opened by anyone.
|
||||
-->
|
||||
|
||||
### Unresolved Questions
|
||||
|
88
.github/workflows/ci.yml
vendored
88
.github/workflows/ci.yml
vendored
@ -181,70 +181,70 @@ jobs:
|
||||
- ARM64
|
||||
- linux
|
||||
- name: arm-android
|
||||
os: ubuntu-20.04-16core-64gb
|
||||
os: ubuntu-20.04-8core-32gb
|
||||
env: {}
|
||||
- name: armhf-gnu
|
||||
os: ubuntu-20.04-16core-64gb
|
||||
os: ubuntu-20.04-8core-32gb
|
||||
env: {}
|
||||
- name: dist-aarch64-linux
|
||||
os: ubuntu-20.04-16core-64gb
|
||||
os: ubuntu-20.04-8core-32gb
|
||||
env: {}
|
||||
- name: dist-android
|
||||
os: ubuntu-20.04-16core-64gb
|
||||
os: ubuntu-20.04-8core-32gb
|
||||
env: {}
|
||||
- name: dist-arm-linux
|
||||
os: ubuntu-20.04-16core-64gb
|
||||
env: {}
|
||||
- name: dist-armhf-linux
|
||||
os: ubuntu-20.04-16core-64gb
|
||||
os: ubuntu-20.04-8core-32gb
|
||||
env: {}
|
||||
- name: dist-armv7-linux
|
||||
os: ubuntu-20.04-16core-64gb
|
||||
os: ubuntu-20.04-8core-32gb
|
||||
env: {}
|
||||
- name: dist-i586-gnu-i586-i686-musl
|
||||
os: ubuntu-20.04-16core-64gb
|
||||
os: ubuntu-20.04-8core-32gb
|
||||
env: {}
|
||||
- name: dist-i686-linux
|
||||
os: ubuntu-20.04-16core-64gb
|
||||
os: ubuntu-20.04-8core-32gb
|
||||
env: {}
|
||||
- name: dist-mips-linux
|
||||
os: ubuntu-20.04-16core-64gb
|
||||
os: ubuntu-20.04-8core-32gb
|
||||
env: {}
|
||||
- name: dist-mips64-linux
|
||||
os: ubuntu-20.04-16core-64gb
|
||||
os: ubuntu-20.04-8core-32gb
|
||||
env: {}
|
||||
- name: dist-mips64el-linux
|
||||
os: ubuntu-20.04-16core-64gb
|
||||
os: ubuntu-20.04-8core-32gb
|
||||
env: {}
|
||||
- name: dist-mipsel-linux
|
||||
os: ubuntu-20.04-16core-64gb
|
||||
os: ubuntu-20.04-8core-32gb
|
||||
env: {}
|
||||
- name: dist-powerpc-linux
|
||||
os: ubuntu-20.04-16core-64gb
|
||||
os: ubuntu-20.04-8core-32gb
|
||||
env: {}
|
||||
- name: dist-powerpc64-linux
|
||||
os: ubuntu-20.04-16core-64gb
|
||||
os: ubuntu-20.04-8core-32gb
|
||||
env: {}
|
||||
- name: dist-powerpc64le-linux
|
||||
os: ubuntu-20.04-16core-64gb
|
||||
os: ubuntu-20.04-8core-32gb
|
||||
env: {}
|
||||
- name: dist-riscv64-linux
|
||||
os: ubuntu-20.04-16core-64gb
|
||||
os: ubuntu-20.04-8core-32gb
|
||||
env: {}
|
||||
- name: dist-s390x-linux
|
||||
os: ubuntu-20.04-16core-64gb
|
||||
os: ubuntu-20.04-8core-32gb
|
||||
env: {}
|
||||
- name: dist-various-1
|
||||
os: ubuntu-20.04-16core-64gb
|
||||
os: ubuntu-20.04-8core-32gb
|
||||
env: {}
|
||||
- name: dist-various-2
|
||||
os: ubuntu-20.04-16core-64gb
|
||||
os: ubuntu-20.04-8core-32gb
|
||||
env: {}
|
||||
- name: dist-x86_64-freebsd
|
||||
os: ubuntu-20.04-16core-64gb
|
||||
os: ubuntu-20.04-8core-32gb
|
||||
env: {}
|
||||
- name: dist-x86_64-illumos
|
||||
os: ubuntu-20.04-16core-64gb
|
||||
os: ubuntu-20.04-8core-32gb
|
||||
env: {}
|
||||
- name: dist-x86_64-linux
|
||||
os: ubuntu-20.04-16core-64gb
|
||||
@ -254,10 +254,10 @@ jobs:
|
||||
IMAGE: dist-x86_64-linux
|
||||
os: ubuntu-20.04-16core-64gb
|
||||
- name: dist-x86_64-musl
|
||||
os: ubuntu-20.04-16core-64gb
|
||||
os: ubuntu-20.04-8core-32gb
|
||||
env: {}
|
||||
- name: dist-x86_64-netbsd
|
||||
os: ubuntu-20.04-16core-64gb
|
||||
os: ubuntu-20.04-8core-32gb
|
||||
env: {}
|
||||
- name: i686-gnu
|
||||
os: ubuntu-20.04-16core-64gb
|
||||
@ -266,51 +266,55 @@ jobs:
|
||||
os: ubuntu-20.04-16core-64gb
|
||||
env: {}
|
||||
- name: mingw-check
|
||||
os: ubuntu-20.04-16core-64gb
|
||||
os: ubuntu-20.04-8core-32gb
|
||||
env: {}
|
||||
- name: test-various
|
||||
os: ubuntu-20.04-16core-64gb
|
||||
os: ubuntu-20.04-8core-32gb
|
||||
env: {}
|
||||
- name: wasm32
|
||||
os: ubuntu-20.04-16core-64gb
|
||||
os: ubuntu-20.04-8core-32gb
|
||||
env: {}
|
||||
- name: x86_64-gnu
|
||||
os: ubuntu-20.04-16core-64gb
|
||||
os: ubuntu-20.04-8core-32gb
|
||||
env: {}
|
||||
- name: x86_64-gnu-stable
|
||||
env:
|
||||
IMAGE: x86_64-gnu
|
||||
RUST_CI_OVERRIDE_RELEASE_CHANNEL: stable
|
||||
CI_ONLY_WHEN_CHANNEL: nightly
|
||||
os: ubuntu-20.04-16core-64gb
|
||||
os: ubuntu-20.04-8core-32gb
|
||||
- name: x86_64-gnu-aux
|
||||
os: ubuntu-20.04-16core-64gb
|
||||
os: ubuntu-20.04-8core-32gb
|
||||
env: {}
|
||||
- name: x86_64-gnu-debug
|
||||
os: ubuntu-20.04-16core-64gb
|
||||
os: ubuntu-20.04-8core-32gb
|
||||
env: {}
|
||||
- name: x86_64-gnu-distcheck
|
||||
os: ubuntu-20.04-16core-64gb
|
||||
os: ubuntu-20.04-8core-32gb
|
||||
env: {}
|
||||
- name: x86_64-gnu-llvm-16
|
||||
env:
|
||||
RUST_BACKTRACE: 1
|
||||
os: ubuntu-20.04-8core-32gb
|
||||
- name: x86_64-gnu-llvm-15
|
||||
env:
|
||||
RUST_BACKTRACE: 1
|
||||
os: ubuntu-20.04-16core-64gb
|
||||
os: ubuntu-20.04-8core-32gb
|
||||
- name: x86_64-gnu-llvm-14
|
||||
env:
|
||||
RUST_BACKTRACE: 1
|
||||
os: ubuntu-20.04-16core-64gb
|
||||
os: ubuntu-20.04-8core-32gb
|
||||
- name: x86_64-gnu-llvm-14-stage1
|
||||
env:
|
||||
RUST_BACKTRACE: 1
|
||||
os: ubuntu-20.04-16core-64gb
|
||||
os: ubuntu-20.04-8core-32gb
|
||||
- name: x86_64-gnu-nopt
|
||||
os: ubuntu-20.04-16core-64gb
|
||||
os: ubuntu-20.04-8core-32gb
|
||||
env: {}
|
||||
- name: x86_64-gnu-tools
|
||||
env:
|
||||
DEPLOY_TOOLSTATES_JSON: toolstates-linux.json
|
||||
os: ubuntu-20.04-16core-64gb
|
||||
os: ubuntu-20.04-8core-32gb
|
||||
- name: dist-x86_64-apple
|
||||
env:
|
||||
SCRIPT: "./x.py dist bootstrap --include-default-paths --host=x86_64-apple-darwin --target=x86_64-apple-darwin"
|
||||
@ -322,7 +326,7 @@ jobs:
|
||||
NO_DEBUG_ASSERTIONS: 1
|
||||
NO_OVERFLOW_CHECKS: 1
|
||||
DIST_REQUIRE_ALL_TOOLS: 1
|
||||
os: macos-12-xl
|
||||
os: macos-latest
|
||||
- name: dist-apple-various
|
||||
env:
|
||||
SCRIPT: "./x.py dist bootstrap --include-default-paths --host='' --target=aarch64-apple-ios,x86_64-apple-ios,aarch64-apple-ios-sim"
|
||||
@ -333,7 +337,7 @@ jobs:
|
||||
NO_LLVM_ASSERTIONS: 1
|
||||
NO_DEBUG_ASSERTIONS: 1
|
||||
NO_OVERFLOW_CHECKS: 1
|
||||
os: macos-12-xl
|
||||
os: macos-latest
|
||||
- name: dist-x86_64-apple-alt
|
||||
env:
|
||||
SCRIPT: "./x.py dist bootstrap --include-default-paths"
|
||||
@ -344,7 +348,7 @@ jobs:
|
||||
NO_LLVM_ASSERTIONS: 1
|
||||
NO_DEBUG_ASSERTIONS: 1
|
||||
NO_OVERFLOW_CHECKS: 1
|
||||
os: macos-12-xl
|
||||
os: macos-latest
|
||||
- name: x86_64-apple-1
|
||||
env:
|
||||
SCRIPT: "./x.py --stage 2 test --exclude tests/ui --exclude tests/rustdoc --exclude tests/run-make-fulldeps"
|
||||
@ -355,7 +359,7 @@ jobs:
|
||||
NO_LLVM_ASSERTIONS: 1
|
||||
NO_DEBUG_ASSERTIONS: 1
|
||||
NO_OVERFLOW_CHECKS: 1
|
||||
os: macos-12-xl
|
||||
os: macos-latest
|
||||
- name: x86_64-apple-2
|
||||
env:
|
||||
SCRIPT: "./x.py --stage 2 test tests/ui tests/rustdoc tests/run-make-fulldeps"
|
||||
@ -366,7 +370,7 @@ jobs:
|
||||
NO_LLVM_ASSERTIONS: 1
|
||||
NO_DEBUG_ASSERTIONS: 1
|
||||
NO_OVERFLOW_CHECKS: 1
|
||||
os: macos-12-xl
|
||||
os: macos-latest
|
||||
- name: dist-aarch64-apple
|
||||
env:
|
||||
SCRIPT: "./x.py dist bootstrap --include-default-paths --stage 2"
|
||||
@ -381,7 +385,7 @@ jobs:
|
||||
NO_OVERFLOW_CHECKS: 1
|
||||
DIST_REQUIRE_ALL_TOOLS: 1
|
||||
JEMALLOC_SYS_WITH_LG_PAGE: 14
|
||||
os: macos-12-xl
|
||||
os: macos-latest
|
||||
- name: x86_64-msvc-1
|
||||
env:
|
||||
RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-msvc --enable-profiler"
|
||||
|
2142
Cargo.lock
2142
Cargo.lock
File diff suppressed because it is too large
Load Diff
11
Cargo.toml
11
Cargo.toml
@ -22,12 +22,6 @@ members = [
|
||||
"src/tools/remote-test-server",
|
||||
"src/tools/rust-installer",
|
||||
"src/tools/rust-demangler",
|
||||
"src/tools/cargo",
|
||||
"src/tools/cargo/crates/credential/cargo-credential-1password",
|
||||
"src/tools/cargo/crates/credential/cargo-credential-macos-keychain",
|
||||
"src/tools/cargo/crates/credential/cargo-credential-wincred",
|
||||
"src/tools/cargo/crates/mdman",
|
||||
# "src/tools/cargo/crates/resolver-tests",
|
||||
"src/tools/rustdoc",
|
||||
"src/tools/rls",
|
||||
"src/tools/rustfmt",
|
||||
@ -44,6 +38,7 @@ members = [
|
||||
"src/tools/lld-wrapper",
|
||||
"src/tools/collect-license-metadata",
|
||||
"src/tools/generate-copyright",
|
||||
"src/tools/suggest-tests",
|
||||
]
|
||||
|
||||
exclude = [
|
||||
@ -105,10 +100,6 @@ miniz_oxide.debug = 0
|
||||
object.debug = 0
|
||||
|
||||
[patch.crates-io]
|
||||
# See comments in `src/tools/rustc-workspace-hack/README.md` for what's going on
|
||||
# here
|
||||
rustc-workspace-hack = { path = 'src/tools/rustc-workspace-hack' }
|
||||
|
||||
# See comments in `library/rustc-std-workspace-core/README.md` for what's going on
|
||||
# here
|
||||
rustc-std-workspace-core = { path = 'library/rustc-std-workspace-core' }
|
||||
|
51
README.md
51
README.md
@ -22,6 +22,8 @@ Read ["Installation"] from [The Book].
|
||||
|
||||
The Rust build system uses a Python script called `x.py` to build the compiler,
|
||||
which manages the bootstrapping process. It lives at the root of the project.
|
||||
It also uses a file named `config.toml` to determine various configuration settings for the build.
|
||||
You can see a full list of options in `config.example.toml`.
|
||||
|
||||
The `x.py` command can be run directly on most Unix systems in the following
|
||||
format:
|
||||
@ -85,6 +87,8 @@ See [the rustc-dev-guide for more info][sysllvm].
|
||||
|
||||
### Building on a Unix-like system
|
||||
|
||||
#### Build steps
|
||||
|
||||
1. Clone the [source] with `git`:
|
||||
|
||||
```sh
|
||||
@ -96,18 +100,13 @@ See [the rustc-dev-guide for more info][sysllvm].
|
||||
|
||||
2. Configure the build settings:
|
||||
|
||||
The Rust build system uses a file named `config.toml` in the root of the
|
||||
source tree to determine various configuration settings for the build.
|
||||
Set up the defaults intended for distros to get started. You can see a full
|
||||
list of options in `config.example.toml`.
|
||||
|
||||
```sh
|
||||
printf 'profile = "user" \nchangelog-seen = 2 \n' > config.toml
|
||||
./configure
|
||||
```
|
||||
|
||||
If you plan to use `x.py install` to create an installation, it is
|
||||
recommended that you set the `prefix` value in the `[install]` section to a
|
||||
directory.
|
||||
directory: `./configure --set install.prefix=<path>`
|
||||
|
||||
3. Build and install:
|
||||
|
||||
@ -117,12 +116,25 @@ See [the rustc-dev-guide for more info][sysllvm].
|
||||
|
||||
When complete, `./x.py install` will place several programs into
|
||||
`$PREFIX/bin`: `rustc`, the Rust compiler, and `rustdoc`, the
|
||||
API-documentation tool. If you've set `profile = "user"` or
|
||||
`build.extended = true`, it will also include [Cargo], Rust's package
|
||||
manager.
|
||||
API-documentation tool. By default, it will also include [Cargo], Rust's package manager.
|
||||
You can disable this behavior by passing `--set build.extended=false` to `./configure`.
|
||||
|
||||
[Cargo]: https://github.com/rust-lang/cargo
|
||||
|
||||
#### Configure and Make
|
||||
|
||||
This project provides a configure script and makefile (the latter of which just invokes `x.py`).
|
||||
`./configure` is the recommended way to programatically generate a `config.toml`. `make` is not
|
||||
recommended (we suggest using `x.py` directly), but it is supported and we try not to break it
|
||||
unnecessarily.
|
||||
|
||||
```sh
|
||||
./configure
|
||||
make && sudo make install
|
||||
```
|
||||
|
||||
`configure` generates a `config.toml` which can also be used with normal `x.py` invocations.
|
||||
|
||||
### Building on Windows
|
||||
|
||||
On Windows, we suggest using [winget] to install dependencies by running the
|
||||
@ -186,7 +198,7 @@ toolchain.
|
||||
4. Navigate to Rust's source code (or clone it), then build it:
|
||||
|
||||
```sh
|
||||
./x.py build && ./x.py install
|
||||
python x.py setup user && python x.py build && python x.py install
|
||||
```
|
||||
|
||||
#### MSVC
|
||||
@ -204,6 +216,7 @@ With these dependencies installed, you can build the compiler in a `cmd.exe`
|
||||
shell with:
|
||||
|
||||
```sh
|
||||
python x.py setup user
|
||||
python x.py build
|
||||
```
|
||||
|
||||
@ -232,21 +245,7 @@ Windows build triples are:
|
||||
|
||||
The build triple can be specified by either specifying `--build=<triple>` when
|
||||
invoking `x.py` commands, or by creating a `config.toml` file (as described in
|
||||
[Installing from Source](#installing-from-source)), and modifying the `build`
|
||||
option under the `[build]` section.
|
||||
|
||||
### Configure and Make
|
||||
|
||||
While it's not the recommended build system, this project also provides a
|
||||
configure script and makefile (the latter of which just invokes `x.py`).
|
||||
|
||||
```sh
|
||||
./configure
|
||||
make && sudo make install
|
||||
```
|
||||
|
||||
`configure` generates a `config.toml` which can also be used with normal `x.py`
|
||||
invocations.
|
||||
[Building on a Unix-like system](#building-on-a-unix-like-system)), and passing `--set build.build=<triple>` to `./configure`.
|
||||
|
||||
## Building Documentation
|
||||
|
||||
|
116
RELEASES.md
116
RELEASES.md
@ -1,3 +1,109 @@
|
||||
Version 1.69.0 (2023-04-20)
|
||||
==========================
|
||||
|
||||
<a id="1.69.0-Language"></a>
|
||||
|
||||
Language
|
||||
--------
|
||||
|
||||
- [Deriving built-in traits on packed structs works with `Copy` fields.](https://github.com/rust-lang/rust/pull/104429/)
|
||||
- [Stabilize the `cmpxchg16b` target feature on x86 and x86_64.](https://github.com/rust-lang/rust/pull/106774/)
|
||||
- [Improve analysis of trait bounds for associated types.](https://github.com/rust-lang/rust/pull/103695/)
|
||||
- [Allow associated types to be used as union fields.](https://github.com/rust-lang/rust/pull/106938/)
|
||||
- [Allow `Self: Autotrait` bounds on dyn-safe trait methods.](https://github.com/rust-lang/rust/pull/107082/)
|
||||
- [Treat `str` as containing `[u8]` for auto trait purposes.](https://github.com/rust-lang/rust/pull/107941/)
|
||||
|
||||
<a id="1.69.0-Compiler"></a>
|
||||
|
||||
Compiler
|
||||
--------
|
||||
|
||||
- [Upgrade `*-pc-windows-gnu` on CI to mingw-w64 v10 and GCC 12.2.](https://github.com/rust-lang/rust/pull/100178/)
|
||||
- [Rework min_choice algorithm of member constraints.](https://github.com/rust-lang/rust/pull/105300/)
|
||||
- [Support `true` and `false` as boolean flags in compiler arguments.](https://github.com/rust-lang/rust/pull/107043/)
|
||||
- [Default `repr(C)` enums to `c_int` size.](https://github.com/rust-lang/rust/pull/107592/)
|
||||
|
||||
<a id="1.69.0-Libraries"></a>
|
||||
|
||||
Libraries
|
||||
---------
|
||||
|
||||
- [Implement the unstable `DispatchFromDyn` for cell types, allowing downstream experimentation with custom method receivers.](https://github.com/rust-lang/rust/pull/97373/)
|
||||
- [Document that `fmt::Arguments::as_str()` may return `Some(_)` in more cases after optimization, subject to change.](https://github.com/rust-lang/rust/pull/106823/)
|
||||
- [Implement `AsFd` and `AsRawFd` for `Rc`.](https://github.com/rust-lang/rust/pull/107317/)
|
||||
|
||||
<a id="1.69.0-Stabilized-APIs"></a>
|
||||
|
||||
Stabilized APIs
|
||||
---------------
|
||||
|
||||
- [`CStr::from_bytes_until_nul`](https://doc.rust-lang.org/stable/core/ffi/struct.CStr.html#method.from_bytes_until_nul)
|
||||
- [`core::ffi::FromBytesUntilNulError`](https://doc.rust-lang.org/stable/core/ffi/struct.FromBytesUntilNulError.html)
|
||||
|
||||
These APIs are now stable in const contexts:
|
||||
|
||||
- [`SocketAddr::new`](https://doc.rust-lang.org/stable/std/net/enum.SocketAddr.html#method.new)
|
||||
- [`SocketAddr::ip`](https://doc.rust-lang.org/stable/std/net/enum.SocketAddr.html#method.ip)
|
||||
- [`SocketAddr::port`](https://doc.rust-lang.org/stable/std/net/enum.SocketAddr.html#method.port)
|
||||
- [`SocketAddr::is_ipv4`](https://doc.rust-lang.org/stable/std/net/enum.SocketAddr.html#method.is_ipv4)
|
||||
- [`SocketAddr::is_ipv6`](https://doc.rust-lang.org/stable/std/net/enum.SocketAddr.html#method.is_ipv6)
|
||||
- [`SocketAddrV4::new`](https://doc.rust-lang.org/stable/std/net/struct.SocketAddrV4.html#method.new)
|
||||
- [`SocketAddrV4::ip`](https://doc.rust-lang.org/stable/std/net/struct.SocketAddrV4.html#method.ip)
|
||||
- [`SocketAddrV4::port`](https://doc.rust-lang.org/stable/std/net/struct.SocketAddrV4.html#method.port)
|
||||
- [`SocketAddrV6::new`](https://doc.rust-lang.org/stable/std/net/struct.SocketAddrV6.html#method.new)
|
||||
- [`SocketAddrV6::ip`](https://doc.rust-lang.org/stable/std/net/struct.SocketAddrV6.html#method.ip)
|
||||
- [`SocketAddrV6::port`](https://doc.rust-lang.org/stable/std/net/struct.SocketAddrV6.html#method.port)
|
||||
- [`SocketAddrV6::flowinfo`](https://doc.rust-lang.org/stable/std/net/struct.SocketAddrV6.html#method.flowinfo)
|
||||
- [`SocketAddrV6::scope_id`](https://doc.rust-lang.org/stable/std/net/struct.SocketAddrV6.html#method.scope_id)
|
||||
|
||||
<a id="1.69.0-Cargo"></a>
|
||||
|
||||
Cargo
|
||||
-----
|
||||
|
||||
- [Cargo now suggests `cargo fix` or `cargo clippy --fix` when compilation warnings are auto-fixable.](https://github.com/rust-lang/cargo/pull/11558/)
|
||||
- [Cargo now suggests `cargo add` if you try to install a library crate.](https://github.com/rust-lang/cargo/pull/11410/)
|
||||
- [Cargo now sets the `CARGO_BIN_NAME` environment variable also for binary examples.](https://github.com/rust-lang/cargo/pull/11705/)
|
||||
|
||||
<a id="1.69.0-Rustdoc"></a>
|
||||
|
||||
Rustdoc
|
||||
-----
|
||||
|
||||
- [Vertically compact trait bound formatting.](https://github.com/rust-lang/rust/pull/102842/)
|
||||
- [Only include stable lints in `rustdoc::all` group.](https://github.com/rust-lang/rust/pull/106316/)
|
||||
- [Compute maximum Levenshtein distance based on the query.](https://github.com/rust-lang/rust/pull/107141/)
|
||||
- [Remove inconsistently-present sidebar tooltips.](https://github.com/rust-lang/rust/pull/107490/)
|
||||
- [Search by macro when query ends with `!`.](https://github.com/rust-lang/rust/pull/108143/)
|
||||
|
||||
<a id="1.69.0-Compatibility-Notes"></a>
|
||||
|
||||
Compatibility Notes
|
||||
-------------------
|
||||
|
||||
- [The `rust-analysis` component from `rustup` now only contains a warning placeholder.](https://github.com/rust-lang/rust/pull/101841/) This was primarily intended for RLS, and the corresponding `-Zsave-analysis` flag has been removed from the compiler as well.
|
||||
- [Unaligned references to packed fields are now a hard error.](https://github.com/rust-lang/rust/pull/102513/) This has been a warning since 1.53, and denied by default with a future-compatibility warning since 1.62.
|
||||
- [Update the minimum external LLVM to 14.](https://github.com/rust-lang/rust/pull/107573/)
|
||||
- [Cargo now emits errors on invalid characters in a registry token.](https://github.com/rust-lang/cargo/pull/11600/)
|
||||
- [When `default-features` is set to false of a workspace dependency, and an inherited dependency of a member has `default-features = true`, Cargo will enable default features of that dependency.](https://github.com/rust-lang/cargo/pull/11409/)
|
||||
- [Cargo denies `CARGO_HOME` in the `[env]` configuration table. Cargo itself doesn't pick up this value, but recursive calls to cargo would, which was not intended.](https://github.com/rust-lang/cargo/pull/11644/)
|
||||
- [Debuginfo for build dependencies is now off if not explicitly set. This is expected to improve the overall build time.](https://github.com/rust-lang/cargo/pull/11252/)
|
||||
- [The Rust distribution no longer always includes rustdoc](https://github.com/rust-lang/rust/pull/106886)
|
||||
If `tools = [...]` is set in config.toml, we will respect a missing rustdoc in that list. By
|
||||
default rustdoc remains included. To retain the prior behavior explicitly add `"rustdoc"` to the
|
||||
list.
|
||||
|
||||
<a id="1.69.0-Internal-Changes"></a>
|
||||
|
||||
Internal Changes
|
||||
----------------
|
||||
|
||||
These changes do not affect any public interfaces of Rust, but they represent
|
||||
significant improvements to the performance or internals of rustc and related
|
||||
tools.
|
||||
|
||||
- [Move `format_args!()` into AST (and expand it during AST lowering)](https://github.com/rust-lang/rust/pull/106745/)
|
||||
|
||||
Version 1.68.2 (2023-03-28)
|
||||
===========================
|
||||
|
||||
@ -861,7 +967,7 @@ Compatibility Notes
|
||||
- [rustdoc: doctests are now run on unexported `macro_rules!` macros, matching other private items][96630]
|
||||
- [rustdoc: Remove .woff font files][96279]
|
||||
- [Enforce Copy bounds for repeat elements while considering lifetimes][95819]
|
||||
- [Windows: Fix potentinal unsoundness by aborting if `File` reads or writes cannot
|
||||
- [Windows: Fix potential unsoundness by aborting if `File` reads or writes cannot
|
||||
complete synchronously][95469].
|
||||
|
||||
Internal Changes
|
||||
@ -1692,10 +1798,10 @@ Libraries
|
||||
- [impl Default, Copy, Clone for std::io::Sink and std::io::Empty][rust#86744]
|
||||
- [`impl From<[(K, V); N]>` for all collections.][rust#84111]
|
||||
- [Remove `P: Unpin` bound on impl Future for Pin.][rust#81363]
|
||||
- [Treat invalid environment variable names as non-existent.][rust#86183]
|
||||
- [Treat invalid environment variable names as nonexistent.][rust#86183]
|
||||
Previously, the environment functions would panic if given a variable name
|
||||
with an internal null character or equal sign (`=`). Now, these functions will
|
||||
just treat such names as non-existent variables, since the OS cannot represent
|
||||
just treat such names as nonexistent variables, since the OS cannot represent
|
||||
the existence of a variable with such a name.
|
||||
|
||||
Stabilised APIs
|
||||
@ -1888,7 +1994,7 @@ Compatibility Notes
|
||||
kinds of errors could be categorised [into newer more specific `ErrorKind`
|
||||
variants][79965], and that they do not represent a user error.
|
||||
- [Using environment variable names with `process::Command` on Windows now
|
||||
behaves as expected.][85270] Previously using envionment variables with
|
||||
behaves as expected.][85270] Previously using environment variables with
|
||||
`Command` would cause them to be ASCII-uppercased.
|
||||
- [Rustdoc will now warn on using rustdoc lints that aren't prefixed
|
||||
with `rustdoc::`][86849]
|
||||
@ -6265,7 +6371,7 @@ eg. `static MINUTE: Duration = Duration::from_secs(60);`
|
||||
|
||||
Cargo
|
||||
-----
|
||||
- [`cargo new` no longer removes `rust` or `rs` prefixs/suffixs.][cargo/5013]
|
||||
- [`cargo new` no longer removes `rust` or `rs` prefixes/suffixes.][cargo/5013]
|
||||
- [`cargo new` now defaults to creating a binary crate, instead of a
|
||||
library crate.][cargo/5029]
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
use super::*;
|
||||
use std::fmt::Write;
|
||||
use std::{borrow::Borrow, cmp, iter, ops::Bound};
|
||||
|
||||
#[cfg(feature = "randomize")]
|
||||
@ -49,219 +50,60 @@ pub trait LayoutCalculator {
|
||||
repr: &ReprOptions,
|
||||
kind: StructKind,
|
||||
) -> Option<LayoutS> {
|
||||
let pack = repr.pack;
|
||||
let mut align = if pack.is_some() { dl.i8_align } else { dl.aggregate_align };
|
||||
let mut inverse_memory_index: IndexVec<u32, FieldIdx> = fields.indices().collect();
|
||||
let optimize = !repr.inhibit_struct_field_reordering_opt();
|
||||
if optimize {
|
||||
let end =
|
||||
if let StructKind::MaybeUnsized = kind { fields.len() - 1 } else { fields.len() };
|
||||
let optimizing = &mut inverse_memory_index.raw[..end];
|
||||
let effective_field_align = |layout: Layout<'_>| {
|
||||
if let Some(pack) = pack {
|
||||
// return the packed alignment in bytes
|
||||
layout.align().abi.min(pack).bytes()
|
||||
} else {
|
||||
// returns log2(effective-align).
|
||||
// This is ok since `pack` applies to all fields equally.
|
||||
// The calculation assumes that size is an integer multiple of align, except for ZSTs.
|
||||
//
|
||||
// group [u8; 4] with align-4 or [u8; 6] with align-2 fields
|
||||
layout.align().abi.bytes().max(layout.size().bytes()).trailing_zeros() as u64
|
||||
}
|
||||
};
|
||||
let layout = univariant(self, dl, fields, repr, kind, NicheBias::Start);
|
||||
// Enums prefer niches close to the beginning or the end of the variants so that other (smaller)
|
||||
// data-carrying variants can be packed into the space after/before the niche.
|
||||
// If the default field ordering does not give us a niche at the front then we do a second
|
||||
// run and bias niches to the right and then check which one is closer to one of the struct's
|
||||
// edges.
|
||||
if let Some(layout) = &layout {
|
||||
if let Some(niche) = layout.largest_niche {
|
||||
let head_space = niche.offset.bytes();
|
||||
let niche_length = niche.value.size(dl).bytes();
|
||||
let tail_space = layout.size.bytes() - head_space - niche_length;
|
||||
|
||||
// If `-Z randomize-layout` was enabled for the type definition we can shuffle
|
||||
// the field ordering to try and catch some code making assumptions about layouts
|
||||
// we don't guarantee
|
||||
if repr.can_randomize_type_layout() && cfg!(feature = "randomize") {
|
||||
#[cfg(feature = "randomize")]
|
||||
{
|
||||
// `ReprOptions.layout_seed` is a deterministic seed that we can use to
|
||||
// randomize field ordering with
|
||||
let mut rng = Xoshiro128StarStar::seed_from_u64(repr.field_shuffle_seed);
|
||||
// This may end up doing redundant work if the niche is already in the last field
|
||||
// (e.g. a trailing bool) and there is tail padding. But it's non-trivial to get
|
||||
// the unpadded size so we try anyway.
|
||||
if fields.len() > 1 && head_space != 0 && tail_space > 0 {
|
||||
let alt_layout = univariant(self, dl, fields, repr, kind, NicheBias::End)
|
||||
.expect("alt layout should always work");
|
||||
let niche = alt_layout
|
||||
.largest_niche
|
||||
.expect("alt layout should have a niche like the regular one");
|
||||
let alt_head_space = niche.offset.bytes();
|
||||
let alt_niche_len = niche.value.size(dl).bytes();
|
||||
let alt_tail_space = alt_layout.size.bytes() - alt_head_space - alt_niche_len;
|
||||
|
||||
// Shuffle the ordering of the fields
|
||||
optimizing.shuffle(&mut rng);
|
||||
}
|
||||
// Otherwise we just leave things alone and actually optimize the type's fields
|
||||
} else {
|
||||
match kind {
|
||||
StructKind::AlwaysSized | StructKind::MaybeUnsized => {
|
||||
optimizing.sort_by_key(|&x| {
|
||||
// Place ZSTs first to avoid "interesting offsets",
|
||||
// especially with only one or two non-ZST fields.
|
||||
// Then place largest alignments first, largest niches within an alignment group last
|
||||
let f = fields[x];
|
||||
let niche_size = f.largest_niche().map_or(0, |n| n.available(dl));
|
||||
(!f.0.is_zst(), cmp::Reverse(effective_field_align(f)), niche_size)
|
||||
});
|
||||
}
|
||||
debug_assert_eq!(layout.size.bytes(), alt_layout.size.bytes());
|
||||
|
||||
StructKind::Prefixed(..) => {
|
||||
// Sort in ascending alignment so that the layout stays optimal
|
||||
// regardless of the prefix.
|
||||
// And put the largest niche in an alignment group at the end
|
||||
// so it can be used as discriminant in jagged enums
|
||||
optimizing.sort_by_key(|&x| {
|
||||
let f = fields[x];
|
||||
let niche_size = f.largest_niche().map_or(0, |n| n.available(dl));
|
||||
(effective_field_align(f), niche_size)
|
||||
});
|
||||
}
|
||||
}
|
||||
let prefer_alt_layout =
|
||||
alt_head_space > head_space && alt_head_space > tail_space;
|
||||
|
||||
// FIXME(Kixiron): We can always shuffle fields within a given alignment class
|
||||
// regardless of the status of `-Z randomize-layout`
|
||||
}
|
||||
}
|
||||
// inverse_memory_index holds field indices by increasing memory offset.
|
||||
// That is, if field 5 has offset 0, the first element of inverse_memory_index is 5.
|
||||
// We now write field offsets to the corresponding offset slot;
|
||||
// field 5 with offset 0 puts 0 in offsets[5].
|
||||
// At the bottom of this function, we invert `inverse_memory_index` to
|
||||
// produce `memory_index` (see `invert_mapping`).
|
||||
let mut sized = true;
|
||||
let mut offsets = IndexVec::from_elem(Size::ZERO, &fields);
|
||||
let mut offset = Size::ZERO;
|
||||
let mut largest_niche = None;
|
||||
let mut largest_niche_available = 0;
|
||||
if let StructKind::Prefixed(prefix_size, prefix_align) = kind {
|
||||
let prefix_align =
|
||||
if let Some(pack) = pack { prefix_align.min(pack) } else { prefix_align };
|
||||
align = align.max(AbiAndPrefAlign::new(prefix_align));
|
||||
offset = prefix_size.align_to(prefix_align);
|
||||
}
|
||||
for &i in &inverse_memory_index {
|
||||
let field = &fields[i];
|
||||
if !sized {
|
||||
self.delay_bug(&format!(
|
||||
"univariant: field #{} comes after unsized field",
|
||||
offsets.len(),
|
||||
));
|
||||
}
|
||||
debug!(
|
||||
"sz: {}, default_niche_at: {}+{}, default_tail_space: {}, alt_niche_at/head_space: {}+{}, alt_tail: {}, num_fields: {}, better: {}\n\
|
||||
layout: {}\n\
|
||||
alt_layout: {}\n",
|
||||
layout.size.bytes(),
|
||||
head_space,
|
||||
niche_length,
|
||||
tail_space,
|
||||
alt_head_space,
|
||||
alt_niche_len,
|
||||
alt_tail_space,
|
||||
layout.fields.count(),
|
||||
prefer_alt_layout,
|
||||
format_field_niches(&layout, &fields, &dl),
|
||||
format_field_niches(&alt_layout, &fields, &dl),
|
||||
);
|
||||
|
||||
if field.0.is_unsized() {
|
||||
sized = false;
|
||||
}
|
||||
|
||||
// Invariant: offset < dl.obj_size_bound() <= 1<<61
|
||||
let field_align = if let Some(pack) = pack {
|
||||
field.align().min(AbiAndPrefAlign::new(pack))
|
||||
} else {
|
||||
field.align()
|
||||
};
|
||||
offset = offset.align_to(field_align.abi);
|
||||
align = align.max(field_align);
|
||||
|
||||
debug!("univariant offset: {:?} field: {:#?}", offset, field);
|
||||
offsets[i] = offset;
|
||||
|
||||
if let Some(mut niche) = field.largest_niche() {
|
||||
let available = niche.available(dl);
|
||||
if available > largest_niche_available {
|
||||
largest_niche_available = available;
|
||||
niche.offset += offset;
|
||||
largest_niche = Some(niche);
|
||||
}
|
||||
}
|
||||
|
||||
offset = offset.checked_add(field.size(), dl)?;
|
||||
}
|
||||
if let Some(repr_align) = repr.align {
|
||||
align = align.max(AbiAndPrefAlign::new(repr_align));
|
||||
}
|
||||
debug!("univariant min_size: {:?}", offset);
|
||||
let min_size = offset;
|
||||
// As stated above, inverse_memory_index holds field indices by increasing offset.
|
||||
// This makes it an already-sorted view of the offsets vec.
|
||||
// To invert it, consider:
|
||||
// If field 5 has offset 0, offsets[0] is 5, and memory_index[5] should be 0.
|
||||
// Field 5 would be the first element, so memory_index is i:
|
||||
// Note: if we didn't optimize, it's already right.
|
||||
let memory_index = if optimize {
|
||||
inverse_memory_index.invert_bijective_mapping()
|
||||
} else {
|
||||
debug_assert!(inverse_memory_index.iter().copied().eq(fields.indices()));
|
||||
inverse_memory_index.into_iter().map(FieldIdx::as_u32).collect()
|
||||
};
|
||||
let size = min_size.align_to(align.abi);
|
||||
let mut abi = Abi::Aggregate { sized };
|
||||
// Unpack newtype ABIs and find scalar pairs.
|
||||
if sized && size.bytes() > 0 {
|
||||
// All other fields must be ZSTs.
|
||||
let mut non_zst_fields = fields.iter_enumerated().filter(|&(_, f)| !f.0.is_zst());
|
||||
|
||||
match (non_zst_fields.next(), non_zst_fields.next(), non_zst_fields.next()) {
|
||||
// We have exactly one non-ZST field.
|
||||
(Some((i, field)), None, None) => {
|
||||
// Field fills the struct and it has a scalar or scalar pair ABI.
|
||||
if offsets[i].bytes() == 0
|
||||
&& align.abi == field.align().abi
|
||||
&& size == field.size()
|
||||
{
|
||||
match field.abi() {
|
||||
// For plain scalars, or vectors of them, we can't unpack
|
||||
// newtypes for `#[repr(C)]`, as that affects C ABIs.
|
||||
Abi::Scalar(_) | Abi::Vector { .. } if optimize => {
|
||||
abi = field.abi();
|
||||
}
|
||||
// But scalar pairs are Rust-specific and get
|
||||
// treated as aggregates by C ABIs anyway.
|
||||
Abi::ScalarPair(..) => {
|
||||
abi = field.abi();
|
||||
}
|
||||
_ => {}
|
||||
if prefer_alt_layout {
|
||||
return Some(alt_layout);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Two non-ZST fields, and they're both scalars.
|
||||
(Some((i, a)), Some((j, b)), None) => {
|
||||
match (a.abi(), b.abi()) {
|
||||
(Abi::Scalar(a), Abi::Scalar(b)) => {
|
||||
// Order by the memory placement, not source order.
|
||||
let ((i, a), (j, b)) = if offsets[i] < offsets[j] {
|
||||
((i, a), (j, b))
|
||||
} else {
|
||||
((j, b), (i, a))
|
||||
};
|
||||
let pair = self.scalar_pair(a, b);
|
||||
let pair_offsets = match pair.fields {
|
||||
FieldsShape::Arbitrary { ref offsets, ref memory_index } => {
|
||||
assert_eq!(memory_index.raw, [0, 1]);
|
||||
offsets
|
||||
}
|
||||
_ => panic!(),
|
||||
};
|
||||
if offsets[i] == pair_offsets[FieldIdx::from_usize(0)]
|
||||
&& offsets[j] == pair_offsets[FieldIdx::from_usize(1)]
|
||||
&& align == pair.align
|
||||
&& size == pair.size
|
||||
{
|
||||
// We can use `ScalarPair` only when it matches our
|
||||
// already computed layout (including `#[repr(C)]`).
|
||||
abi = pair.abi;
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
if fields.iter().any(|f| f.abi().is_uninhabited()) {
|
||||
abi = Abi::Uninhabited;
|
||||
}
|
||||
Some(LayoutS {
|
||||
variants: Variants::Single { index: FIRST_VARIANT },
|
||||
fields: FieldsShape::Arbitrary { offsets, memory_index },
|
||||
abi,
|
||||
largest_niche,
|
||||
align,
|
||||
size,
|
||||
})
|
||||
layout
|
||||
}
|
||||
|
||||
fn layout_of_never_type(&self) -> LayoutS {
|
||||
@ -461,8 +303,8 @@ pub trait LayoutCalculator {
|
||||
let all_indices = variants.indices();
|
||||
let needs_disc =
|
||||
|index: VariantIdx| index != largest_variant_index && !absent(&variants[index]);
|
||||
let niche_variants = all_indices.clone().find(|v| needs_disc(*v)).unwrap().index()
|
||||
..=all_indices.rev().find(|v| needs_disc(*v)).unwrap().index();
|
||||
let niche_variants = all_indices.clone().find(|v| needs_disc(*v)).unwrap()
|
||||
..=all_indices.rev().find(|v| needs_disc(*v)).unwrap();
|
||||
|
||||
let count = niche_variants.size_hint().1.unwrap() as u128;
|
||||
|
||||
@ -560,8 +402,7 @@ pub trait LayoutCalculator {
|
||||
tag: niche_scalar,
|
||||
tag_encoding: TagEncoding::Niche {
|
||||
untagged_variant: largest_variant_index,
|
||||
niche_variants: (VariantIdx::new(*niche_variants.start())
|
||||
..=VariantIdx::new(*niche_variants.end())),
|
||||
niche_variants,
|
||||
niche_start,
|
||||
},
|
||||
tag_field: 0,
|
||||
@ -934,3 +775,323 @@ pub trait LayoutCalculator {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Determines towards which end of a struct layout optimizations will try to place the best niches.
|
||||
enum NicheBias {
|
||||
Start,
|
||||
End,
|
||||
}
|
||||
|
||||
fn univariant(
|
||||
this: &(impl LayoutCalculator + ?Sized),
|
||||
dl: &TargetDataLayout,
|
||||
fields: &IndexSlice<FieldIdx, Layout<'_>>,
|
||||
repr: &ReprOptions,
|
||||
kind: StructKind,
|
||||
niche_bias: NicheBias,
|
||||
) -> Option<LayoutS> {
|
||||
let pack = repr.pack;
|
||||
let mut align = if pack.is_some() { dl.i8_align } else { dl.aggregate_align };
|
||||
let mut inverse_memory_index: IndexVec<u32, FieldIdx> = fields.indices().collect();
|
||||
let optimize = !repr.inhibit_struct_field_reordering_opt();
|
||||
if optimize && fields.len() > 1 {
|
||||
let end = if let StructKind::MaybeUnsized = kind { fields.len() - 1 } else { fields.len() };
|
||||
let optimizing = &mut inverse_memory_index.raw[..end];
|
||||
|
||||
// If `-Z randomize-layout` was enabled for the type definition we can shuffle
|
||||
// the field ordering to try and catch some code making assumptions about layouts
|
||||
// we don't guarantee
|
||||
if repr.can_randomize_type_layout() && cfg!(feature = "randomize") {
|
||||
#[cfg(feature = "randomize")]
|
||||
{
|
||||
// `ReprOptions.layout_seed` is a deterministic seed that we can use to
|
||||
// randomize field ordering with
|
||||
let mut rng = Xoshiro128StarStar::seed_from_u64(repr.field_shuffle_seed.as_u64());
|
||||
|
||||
// Shuffle the ordering of the fields
|
||||
optimizing.shuffle(&mut rng);
|
||||
}
|
||||
// Otherwise we just leave things alone and actually optimize the type's fields
|
||||
} else {
|
||||
let max_field_align = fields.iter().map(|f| f.align().abi.bytes()).max().unwrap_or(1);
|
||||
let largest_niche_size = fields
|
||||
.iter()
|
||||
.filter_map(|f| f.largest_niche())
|
||||
.map(|n| n.available(dl))
|
||||
.max()
|
||||
.unwrap_or(0);
|
||||
|
||||
// Calculates a sort key to group fields by their alignment or possibly some size-derived
|
||||
// pseudo-alignment.
|
||||
let alignment_group_key = |layout: Layout<'_>| {
|
||||
if let Some(pack) = pack {
|
||||
// return the packed alignment in bytes
|
||||
layout.align().abi.min(pack).bytes()
|
||||
} else {
|
||||
// returns log2(effective-align).
|
||||
// This is ok since `pack` applies to all fields equally.
|
||||
// The calculation assumes that size is an integer multiple of align, except for ZSTs.
|
||||
//
|
||||
let align = layout.align().abi.bytes();
|
||||
let size = layout.size().bytes();
|
||||
let niche_size = layout.largest_niche().map(|n| n.available(dl)).unwrap_or(0);
|
||||
// group [u8; 4] with align-4 or [u8; 6] with align-2 fields
|
||||
let size_as_align = align.max(size).trailing_zeros();
|
||||
let size_as_align = if largest_niche_size > 0 {
|
||||
match niche_bias {
|
||||
// Given `A(u8, [u8; 16])` and `B(bool, [u8; 16])` we want to bump the array
|
||||
// to the front in the first case (for aligned loads) but keep the bool in front
|
||||
// in the second case for its niches.
|
||||
NicheBias::Start => max_field_align.trailing_zeros().min(size_as_align),
|
||||
// When moving niches towards the end of the struct then for
|
||||
// A((u8, u8, u8, bool), (u8, bool, u8)) we want to keep the first tuple
|
||||
// in the align-1 group because its bool can be moved closer to the end.
|
||||
NicheBias::End if niche_size == largest_niche_size => {
|
||||
align.trailing_zeros()
|
||||
}
|
||||
NicheBias::End => size_as_align,
|
||||
}
|
||||
} else {
|
||||
size_as_align
|
||||
};
|
||||
size_as_align as u64
|
||||
}
|
||||
};
|
||||
|
||||
match kind {
|
||||
StructKind::AlwaysSized | StructKind::MaybeUnsized => {
|
||||
// Currently `LayoutS` only exposes a single niche so sorting is usually sufficient
|
||||
// to get one niche into the preferred position. If it ever supported multiple niches
|
||||
// then a more advanced pick-and-pack approach could provide better results.
|
||||
// But even for the single-niche cache it's not optimal. E.g. for
|
||||
// A(u32, (bool, u8), u16) it would be possible to move the bool to the front
|
||||
// but it would require packing the tuple together with the u16 to build a 4-byte
|
||||
// group so that the u32 can be placed after it without padding. This kind
|
||||
// of packing can't be achieved by sorting.
|
||||
optimizing.sort_by_key(|&x| {
|
||||
let f = fields[x];
|
||||
let field_size = f.size().bytes();
|
||||
let niche_size = f.largest_niche().map_or(0, |n| n.available(dl));
|
||||
let niche_size_key = match niche_bias {
|
||||
// large niche first
|
||||
NicheBias::Start => !niche_size,
|
||||
// large niche last
|
||||
NicheBias::End => niche_size,
|
||||
};
|
||||
let inner_niche_offset_key = match niche_bias {
|
||||
NicheBias::Start => f.largest_niche().map_or(0, |n| n.offset.bytes()),
|
||||
NicheBias::End => f.largest_niche().map_or(0, |n| {
|
||||
!(field_size - n.value.size(dl).bytes() - n.offset.bytes())
|
||||
}),
|
||||
};
|
||||
|
||||
(
|
||||
// Place ZSTs first to avoid "interesting offsets", especially with only one
|
||||
// or two non-ZST fields. This helps Scalar/ScalarPair layouts.
|
||||
!f.0.is_zst(),
|
||||
// Then place largest alignments first.
|
||||
cmp::Reverse(alignment_group_key(f)),
|
||||
// Then prioritize niche placement within alignment group according to
|
||||
// `niche_bias_start`.
|
||||
niche_size_key,
|
||||
// Then among fields with equally-sized niches prefer the ones
|
||||
// closer to the start/end of the field.
|
||||
inner_niche_offset_key,
|
||||
)
|
||||
});
|
||||
}
|
||||
|
||||
StructKind::Prefixed(..) => {
|
||||
// Sort in ascending alignment so that the layout stays optimal
|
||||
// regardless of the prefix.
|
||||
// And put the largest niche in an alignment group at the end
|
||||
// so it can be used as discriminant in jagged enums
|
||||
optimizing.sort_by_key(|&x| {
|
||||
let f = fields[x];
|
||||
let niche_size = f.largest_niche().map_or(0, |n| n.available(dl));
|
||||
(alignment_group_key(f), niche_size)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME(Kixiron): We can always shuffle fields within a given alignment class
|
||||
// regardless of the status of `-Z randomize-layout`
|
||||
}
|
||||
}
|
||||
// inverse_memory_index holds field indices by increasing memory offset.
|
||||
// That is, if field 5 has offset 0, the first element of inverse_memory_index is 5.
|
||||
// We now write field offsets to the corresponding offset slot;
|
||||
// field 5 with offset 0 puts 0 in offsets[5].
|
||||
// At the bottom of this function, we invert `inverse_memory_index` to
|
||||
// produce `memory_index` (see `invert_mapping`).
|
||||
let mut sized = true;
|
||||
let mut offsets = IndexVec::from_elem(Size::ZERO, &fields);
|
||||
let mut offset = Size::ZERO;
|
||||
let mut largest_niche = None;
|
||||
let mut largest_niche_available = 0;
|
||||
if let StructKind::Prefixed(prefix_size, prefix_align) = kind {
|
||||
let prefix_align =
|
||||
if let Some(pack) = pack { prefix_align.min(pack) } else { prefix_align };
|
||||
align = align.max(AbiAndPrefAlign::new(prefix_align));
|
||||
offset = prefix_size.align_to(prefix_align);
|
||||
}
|
||||
for &i in &inverse_memory_index {
|
||||
let field = &fields[i];
|
||||
if !sized {
|
||||
this.delay_bug(&format!(
|
||||
"univariant: field #{} comes after unsized field",
|
||||
offsets.len(),
|
||||
));
|
||||
}
|
||||
|
||||
if field.0.is_unsized() {
|
||||
sized = false;
|
||||
}
|
||||
|
||||
// Invariant: offset < dl.obj_size_bound() <= 1<<61
|
||||
let field_align = if let Some(pack) = pack {
|
||||
field.align().min(AbiAndPrefAlign::new(pack))
|
||||
} else {
|
||||
field.align()
|
||||
};
|
||||
offset = offset.align_to(field_align.abi);
|
||||
align = align.max(field_align);
|
||||
|
||||
debug!("univariant offset: {:?} field: {:#?}", offset, field);
|
||||
offsets[i] = offset;
|
||||
|
||||
if let Some(mut niche) = field.largest_niche() {
|
||||
let available = niche.available(dl);
|
||||
// Pick up larger niches.
|
||||
let prefer_new_niche = match niche_bias {
|
||||
NicheBias::Start => available > largest_niche_available,
|
||||
// if there are several niches of the same size then pick the last one
|
||||
NicheBias::End => available >= largest_niche_available,
|
||||
};
|
||||
if prefer_new_niche {
|
||||
largest_niche_available = available;
|
||||
niche.offset += offset;
|
||||
largest_niche = Some(niche);
|
||||
}
|
||||
}
|
||||
|
||||
offset = offset.checked_add(field.size(), dl)?;
|
||||
}
|
||||
if let Some(repr_align) = repr.align {
|
||||
align = align.max(AbiAndPrefAlign::new(repr_align));
|
||||
}
|
||||
debug!("univariant min_size: {:?}", offset);
|
||||
let min_size = offset;
|
||||
// As stated above, inverse_memory_index holds field indices by increasing offset.
|
||||
// This makes it an already-sorted view of the offsets vec.
|
||||
// To invert it, consider:
|
||||
// If field 5 has offset 0, offsets[0] is 5, and memory_index[5] should be 0.
|
||||
// Field 5 would be the first element, so memory_index is i:
|
||||
// Note: if we didn't optimize, it's already right.
|
||||
let memory_index = if optimize {
|
||||
inverse_memory_index.invert_bijective_mapping()
|
||||
} else {
|
||||
debug_assert!(inverse_memory_index.iter().copied().eq(fields.indices()));
|
||||
inverse_memory_index.into_iter().map(FieldIdx::as_u32).collect()
|
||||
};
|
||||
let size = min_size.align_to(align.abi);
|
||||
let mut abi = Abi::Aggregate { sized };
|
||||
// Unpack newtype ABIs and find scalar pairs.
|
||||
if sized && size.bytes() > 0 {
|
||||
// All other fields must be ZSTs.
|
||||
let mut non_zst_fields = fields.iter_enumerated().filter(|&(_, f)| !f.0.is_zst());
|
||||
|
||||
match (non_zst_fields.next(), non_zst_fields.next(), non_zst_fields.next()) {
|
||||
// We have exactly one non-ZST field.
|
||||
(Some((i, field)), None, None) => {
|
||||
// Field fills the struct and it has a scalar or scalar pair ABI.
|
||||
if offsets[i].bytes() == 0 && align.abi == field.align().abi && size == field.size()
|
||||
{
|
||||
match field.abi() {
|
||||
// For plain scalars, or vectors of them, we can't unpack
|
||||
// newtypes for `#[repr(C)]`, as that affects C ABIs.
|
||||
Abi::Scalar(_) | Abi::Vector { .. } if optimize => {
|
||||
abi = field.abi();
|
||||
}
|
||||
// But scalar pairs are Rust-specific and get
|
||||
// treated as aggregates by C ABIs anyway.
|
||||
Abi::ScalarPair(..) => {
|
||||
abi = field.abi();
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Two non-ZST fields, and they're both scalars.
|
||||
(Some((i, a)), Some((j, b)), None) => {
|
||||
match (a.abi(), b.abi()) {
|
||||
(Abi::Scalar(a), Abi::Scalar(b)) => {
|
||||
// Order by the memory placement, not source order.
|
||||
let ((i, a), (j, b)) = if offsets[i] < offsets[j] {
|
||||
((i, a), (j, b))
|
||||
} else {
|
||||
((j, b), (i, a))
|
||||
};
|
||||
let pair = this.scalar_pair(a, b);
|
||||
let pair_offsets = match pair.fields {
|
||||
FieldsShape::Arbitrary { ref offsets, ref memory_index } => {
|
||||
assert_eq!(memory_index.raw, [0, 1]);
|
||||
offsets
|
||||
}
|
||||
_ => panic!(),
|
||||
};
|
||||
if offsets[i] == pair_offsets[FieldIdx::from_usize(0)]
|
||||
&& offsets[j] == pair_offsets[FieldIdx::from_usize(1)]
|
||||
&& align == pair.align
|
||||
&& size == pair.size
|
||||
{
|
||||
// We can use `ScalarPair` only when it matches our
|
||||
// already computed layout (including `#[repr(C)]`).
|
||||
abi = pair.abi;
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
if fields.iter().any(|f| f.abi().is_uninhabited()) {
|
||||
abi = Abi::Uninhabited;
|
||||
}
|
||||
Some(LayoutS {
|
||||
variants: Variants::Single { index: FIRST_VARIANT },
|
||||
fields: FieldsShape::Arbitrary { offsets, memory_index },
|
||||
abi,
|
||||
largest_niche,
|
||||
align,
|
||||
size,
|
||||
})
|
||||
}
|
||||
|
||||
fn format_field_niches(
|
||||
layout: &LayoutS,
|
||||
fields: &IndexSlice<FieldIdx, Layout<'_>>,
|
||||
dl: &TargetDataLayout,
|
||||
) -> String {
|
||||
let mut s = String::new();
|
||||
for i in layout.fields.index_by_increasing_offset() {
|
||||
let offset = layout.fields.offset(i);
|
||||
let f = fields[i.into()];
|
||||
write!(s, "[o{}a{}s{}", offset.bytes(), f.align().abi.bytes(), f.size().bytes()).unwrap();
|
||||
if let Some(n) = f.largest_niche() {
|
||||
write!(
|
||||
s,
|
||||
" n{}b{}s{}",
|
||||
n.offset.bytes(),
|
||||
n.available(dl).ilog2(),
|
||||
n.value.size(dl).bytes()
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
write!(s, "] ").unwrap();
|
||||
}
|
||||
s
|
||||
}
|
||||
|
@ -9,9 +9,10 @@ use std::str::FromStr;
|
||||
|
||||
use bitflags::bitflags;
|
||||
use rustc_data_structures::intern::Interned;
|
||||
use rustc_data_structures::stable_hasher::Hash64;
|
||||
#[cfg(feature = "nightly")]
|
||||
use rustc_data_structures::stable_hasher::StableOrd;
|
||||
use rustc_index::vec::{Idx, IndexSlice, IndexVec};
|
||||
use rustc_index::{IndexSlice, IndexVec};
|
||||
#[cfg(feature = "nightly")]
|
||||
use rustc_macros::HashStable_Generic;
|
||||
#[cfg(feature = "nightly")]
|
||||
@ -77,12 +78,12 @@ pub struct ReprOptions {
|
||||
pub flags: ReprFlags,
|
||||
/// The seed to be used for randomizing a type's layout
|
||||
///
|
||||
/// Note: This could technically be a `[u8; 16]` (a `u128`) which would
|
||||
/// Note: This could technically be a `Hash128` which would
|
||||
/// be the "most accurate" hash as it'd encompass the item and crate
|
||||
/// hash without loss, but it does pay the price of being larger.
|
||||
/// Everything's a tradeoff, a `u64` seed should be sufficient for our
|
||||
/// Everything's a tradeoff, a 64-bit seed should be sufficient for our
|
||||
/// purposes (primarily `-Z randomize-layout`)
|
||||
pub field_shuffle_seed: u64,
|
||||
pub field_shuffle_seed: Hash64,
|
||||
}
|
||||
|
||||
impl ReprOptions {
|
||||
@ -665,15 +666,12 @@ impl Align {
|
||||
format!("`{}` is too large", align)
|
||||
}
|
||||
|
||||
let mut bytes = align;
|
||||
let mut pow2: u8 = 0;
|
||||
while (bytes & 1) == 0 {
|
||||
pow2 += 1;
|
||||
bytes >>= 1;
|
||||
}
|
||||
if bytes != 1 {
|
||||
let tz = align.trailing_zeros();
|
||||
if align != (1 << tz) {
|
||||
return Err(not_power_of_2(align));
|
||||
}
|
||||
|
||||
let pow2 = tz as u8;
|
||||
if pow2 > Self::MAX.pow2 {
|
||||
return Err(too_large(align));
|
||||
}
|
||||
|
@ -20,6 +20,7 @@
|
||||
#![feature(rustc_attrs)]
|
||||
#![cfg_attr(test, feature(test))]
|
||||
#![feature(strict_provenance)]
|
||||
#![deny(unsafe_op_in_unsafe_fn)]
|
||||
#![deny(rustc::untranslatable_diagnostic)]
|
||||
#![deny(rustc::diagnostic_outside_of_impl)]
|
||||
#![allow(clippy::mut_from_ref)] // Arena allocators are one of the places where this pattern is fine.
|
||||
@ -74,21 +75,29 @@ impl<T> ArenaChunk<T> {
|
||||
#[inline]
|
||||
unsafe fn new(capacity: usize) -> ArenaChunk<T> {
|
||||
ArenaChunk {
|
||||
storage: NonNull::new(Box::into_raw(Box::new_uninit_slice(capacity))).unwrap(),
|
||||
storage: NonNull::from(Box::leak(Box::new_uninit_slice(capacity))),
|
||||
entries: 0,
|
||||
}
|
||||
}
|
||||
|
||||
/// Destroys this arena chunk.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The caller must ensure that `len` elements of this chunk have been initialized.
|
||||
#[inline]
|
||||
unsafe fn destroy(&mut self, len: usize) {
|
||||
// The branch on needs_drop() is an -O1 performance optimization.
|
||||
// Without the branch, dropping TypedArena<u8> takes linear time.
|
||||
// Without the branch, dropping TypedArena<T> takes linear time.
|
||||
if mem::needs_drop::<T>() {
|
||||
let slice = &mut *(self.storage.as_mut());
|
||||
// SAFETY: The caller must ensure that `len` elements of this chunk have
|
||||
// been initialized.
|
||||
unsafe {
|
||||
let slice = self.storage.as_mut();
|
||||
ptr::drop_in_place(MaybeUninit::slice_assume_init_mut(&mut slice[..len]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Returns a pointer to the first allocated object.
|
||||
#[inline]
|
||||
@ -104,7 +113,7 @@ impl<T> ArenaChunk<T> {
|
||||
// A pointer as large as possible for zero-sized elements.
|
||||
ptr::invalid_mut(!0)
|
||||
} else {
|
||||
self.start().add((*self.storage.as_ptr()).len())
|
||||
self.start().add(self.storage.len())
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -255,7 +264,9 @@ impl<T> TypedArena<T> {
|
||||
self.ensure_capacity(len);
|
||||
|
||||
let start_ptr = self.ptr.get();
|
||||
self.ptr.set(start_ptr.add(len));
|
||||
// SAFETY: `self.ensure_capacity` makes sure that there is enough space
|
||||
// for `len` elements.
|
||||
unsafe { self.ptr.set(start_ptr.add(len)) };
|
||||
start_ptr
|
||||
}
|
||||
|
||||
@ -288,7 +299,7 @@ impl<T> TypedArena<T> {
|
||||
// If the previous chunk's len is less than HUGE_PAGE
|
||||
// bytes, then this chunk will be least double the previous
|
||||
// chunk's size.
|
||||
new_cap = (*last_chunk.storage.as_ptr()).len().min(HUGE_PAGE / elem_size / 2);
|
||||
new_cap = last_chunk.storage.len().min(HUGE_PAGE / elem_size / 2);
|
||||
new_cap *= 2;
|
||||
} else {
|
||||
new_cap = PAGE / elem_size;
|
||||
@ -396,7 +407,7 @@ impl DroplessArena {
|
||||
// If the previous chunk's len is less than HUGE_PAGE
|
||||
// bytes, then this chunk will be least double the previous
|
||||
// chunk's size.
|
||||
new_cap = (*last_chunk.storage.as_ptr()).len().min(HUGE_PAGE / 2);
|
||||
new_cap = last_chunk.storage.len().min(HUGE_PAGE / 2);
|
||||
new_cap *= 2;
|
||||
} else {
|
||||
new_cap = PAGE;
|
||||
@ -483,6 +494,10 @@ impl DroplessArena {
|
||||
}
|
||||
}
|
||||
|
||||
/// # Safety
|
||||
///
|
||||
/// The caller must ensure that `mem` is valid for writes up to
|
||||
/// `size_of::<T>() * len`.
|
||||
#[inline]
|
||||
unsafe fn write_from_iter<T, I: Iterator<Item = T>>(
|
||||
&self,
|
||||
@ -494,13 +509,18 @@ impl DroplessArena {
|
||||
// Use a manual loop since LLVM manages to optimize it better for
|
||||
// slice iterators
|
||||
loop {
|
||||
let value = iter.next();
|
||||
if i >= len || value.is_none() {
|
||||
// SAFETY: The caller must ensure that `mem` is valid for writes up to
|
||||
// `size_of::<T>() * len`.
|
||||
unsafe {
|
||||
match iter.next() {
|
||||
Some(value) if i < len => mem.add(i).write(value),
|
||||
Some(_) | None => {
|
||||
// We only return as many items as the iterator gave us, even
|
||||
// though it was supposed to give us `len`
|
||||
return slice::from_raw_parts_mut(mem, i);
|
||||
}
|
||||
ptr::write(mem.add(i), value.unwrap());
|
||||
}
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
|
@ -1271,6 +1271,7 @@ impl Expr {
|
||||
ExprKind::Continue(..) => ExprPrecedence::Continue,
|
||||
ExprKind::Ret(..) => ExprPrecedence::Ret,
|
||||
ExprKind::InlineAsm(..) => ExprPrecedence::InlineAsm,
|
||||
ExprKind::OffsetOf(..) => ExprPrecedence::OffsetOf,
|
||||
ExprKind::MacCall(..) => ExprPrecedence::Mac,
|
||||
ExprKind::Struct(..) => ExprPrecedence::Struct,
|
||||
ExprKind::Repeat(..) => ExprPrecedence::Repeat,
|
||||
@ -1298,7 +1299,8 @@ impl Expr {
|
||||
|
||||
/// To a first-order approximation, is this a pattern?
|
||||
pub fn is_approximately_pattern(&self) -> bool {
|
||||
match &self.peel_parens().kind {
|
||||
matches!(
|
||||
&self.peel_parens().kind,
|
||||
ExprKind::Array(_)
|
||||
| ExprKind::Call(_, _)
|
||||
| ExprKind::Tup(_)
|
||||
@ -1306,9 +1308,8 @@ impl Expr {
|
||||
| ExprKind::Range(_, _, _)
|
||||
| ExprKind::Underscore
|
||||
| ExprKind::Path(_, _)
|
||||
| ExprKind::Struct(_) => true,
|
||||
_ => false,
|
||||
}
|
||||
| ExprKind::Struct(_)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1469,6 +1470,9 @@ pub enum ExprKind {
|
||||
/// Output of the `asm!()` macro.
|
||||
InlineAsm(P<InlineAsm>),
|
||||
|
||||
/// Output of the `offset_of!()` macro.
|
||||
OffsetOf(P<Ty>, P<[Ident]>),
|
||||
|
||||
/// A macro invocation; pre-expansion.
|
||||
MacCall(P<MacCall>),
|
||||
|
||||
@ -2972,7 +2976,7 @@ pub enum ItemKind {
|
||||
}
|
||||
|
||||
impl ItemKind {
|
||||
pub fn article(&self) -> &str {
|
||||
pub fn article(&self) -> &'static str {
|
||||
use ItemKind::*;
|
||||
match self {
|
||||
Use(..) | Static(..) | Const(..) | Fn(..) | Mod(..) | GlobalAsm(..) | TyAlias(..)
|
||||
@ -2981,7 +2985,7 @@ impl ItemKind {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn descr(&self) -> &str {
|
||||
pub fn descr(&self) -> &'static str {
|
||||
match self {
|
||||
ItemKind::ExternCrate(..) => "extern crate",
|
||||
ItemKind::Use(..) => "`use` import",
|
||||
|
@ -10,15 +10,10 @@ use crate::tokenstream::{DelimSpan, Spacing, TokenTree};
|
||||
use crate::tokenstream::{LazyAttrTokenStream, TokenStream};
|
||||
use crate::util::comments;
|
||||
use crate::util::literal::escape_string_symbol;
|
||||
use rustc_data_structures::sync::WorkerLocal;
|
||||
use rustc_index::bit_set::GrowableBitSet;
|
||||
use rustc_span::symbol::{sym, Ident, Symbol};
|
||||
use rustc_span::Span;
|
||||
use std::cell::Cell;
|
||||
use std::iter;
|
||||
#[cfg(debug_assertions)]
|
||||
use std::ops::BitXor;
|
||||
#[cfg(debug_assertions)]
|
||||
use std::sync::atomic::{AtomicU32, Ordering};
|
||||
use thin_vec::{thin_vec, ThinVec};
|
||||
|
||||
@ -40,39 +35,16 @@ impl MarkedAttrs {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct AttrIdGenerator(WorkerLocal<Cell<u32>>);
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
static MAX_ATTR_ID: AtomicU32 = AtomicU32::new(u32::MAX);
|
||||
pub struct AttrIdGenerator(AtomicU32);
|
||||
|
||||
impl AttrIdGenerator {
|
||||
pub fn new() -> Self {
|
||||
// We use `(index as u32).reverse_bits()` to initialize the
|
||||
// starting value of AttrId in each worker thread.
|
||||
// The `index` is the index of the worker thread.
|
||||
// This ensures that the AttrId generated in each thread is unique.
|
||||
AttrIdGenerator(WorkerLocal::new(|index| {
|
||||
let index: u32 = index.try_into().unwrap();
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
{
|
||||
let max_id = ((index + 1).next_power_of_two() - 1).bitxor(u32::MAX).reverse_bits();
|
||||
MAX_ATTR_ID.fetch_min(max_id, Ordering::Release);
|
||||
}
|
||||
|
||||
Cell::new(index.reverse_bits())
|
||||
}))
|
||||
AttrIdGenerator(AtomicU32::new(0))
|
||||
}
|
||||
|
||||
pub fn mk_attr_id(&self) -> AttrId {
|
||||
let id = self.0.get();
|
||||
|
||||
// Ensure the assigned attr_id does not overlap the bits
|
||||
// representing the number of threads.
|
||||
#[cfg(debug_assertions)]
|
||||
assert!(id <= MAX_ATTR_ID.load(Ordering::Acquire));
|
||||
|
||||
self.0.set(id + 1);
|
||||
let id = self.0.fetch_add(1, Ordering::Relaxed);
|
||||
assert!(id != u32::MAX);
|
||||
AttrId::from_u32(id)
|
||||
}
|
||||
}
|
||||
|
@ -10,7 +10,6 @@
|
||||
)]
|
||||
#![feature(associated_type_bounds)]
|
||||
#![feature(box_patterns)]
|
||||
#![feature(const_default_impls)]
|
||||
#![feature(const_trait_impl)]
|
||||
#![feature(if_let_guard)]
|
||||
#![feature(let_chains)]
|
||||
|
@ -1456,6 +1456,12 @@ pub fn noop_visit_expr<T: MutVisitor>(
|
||||
}
|
||||
ExprKind::InlineAsm(asm) => vis.visit_inline_asm(asm),
|
||||
ExprKind::FormatArgs(fmt) => vis.visit_format_args(fmt),
|
||||
ExprKind::OffsetOf(container, fields) => {
|
||||
vis.visit_ty(container);
|
||||
for field in fields.iter_mut() {
|
||||
vis.visit_ident(field);
|
||||
}
|
||||
}
|
||||
ExprKind::MacCall(mac) => vis.visit_mac_call(mac),
|
||||
ExprKind::Struct(se) => {
|
||||
let StructExpr { qself, path, fields, rest } = se.deref_mut();
|
||||
|
@ -9,14 +9,14 @@ rustc_index::newtype_index! {
|
||||
///
|
||||
/// [`DefId`]: rustc_span::def_id::DefId
|
||||
#[debug_format = "NodeId({})"]
|
||||
pub struct NodeId {}
|
||||
pub struct NodeId {
|
||||
/// The [`NodeId`] used to represent the root of the crate.
|
||||
const CRATE_NODE_ID = 0;
|
||||
}
|
||||
}
|
||||
|
||||
rustc_data_structures::define_id_collections!(NodeMap, NodeSet, NodeMapEntry, NodeId);
|
||||
|
||||
/// The [`NodeId`] used to represent the root of the crate.
|
||||
pub const CRATE_NODE_ID: NodeId = NodeId::from_u32(0);
|
||||
|
||||
/// When parsing and at the beginning of doing expansions, we initially give all AST nodes
|
||||
/// this dummy AST [`NodeId`]. Then, during a later phase of expansion, we renumber them
|
||||
/// to have small, positive IDs.
|
||||
|
@ -126,7 +126,8 @@ impl<S: Encoder, T: Encodable<S>> Encodable<S> for P<T> {
|
||||
}
|
||||
|
||||
impl<T> P<[T]> {
|
||||
pub const fn new() -> P<[T]> {
|
||||
// FIXME(const-hack) make this const again
|
||||
pub fn new() -> P<[T]> {
|
||||
P { ptr: Box::default() }
|
||||
}
|
||||
|
||||
|
@ -269,6 +269,7 @@ pub enum ExprPrecedence {
|
||||
Index,
|
||||
Try,
|
||||
InlineAsm,
|
||||
OffsetOf,
|
||||
Mac,
|
||||
FormatArgs,
|
||||
|
||||
@ -335,7 +336,8 @@ impl ExprPrecedence {
|
||||
| ExprPrecedence::Try
|
||||
| ExprPrecedence::InlineAsm
|
||||
| ExprPrecedence::Mac
|
||||
| ExprPrecedence::FormatArgs => PREC_POSTFIX,
|
||||
| ExprPrecedence::FormatArgs
|
||||
| ExprPrecedence::OffsetOf => PREC_POSTFIX,
|
||||
|
||||
// Never need parens
|
||||
ExprPrecedence::Array
|
||||
|
@ -909,6 +909,12 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {
|
||||
ExprKind::Paren(subexpression) => visitor.visit_expr(subexpression),
|
||||
ExprKind::InlineAsm(asm) => visitor.visit_inline_asm(asm),
|
||||
ExprKind::FormatArgs(f) => visitor.visit_format_args(f),
|
||||
ExprKind::OffsetOf(container, fields) => {
|
||||
visitor.visit_ty(container);
|
||||
for &field in fields {
|
||||
visitor.visit_ident(field);
|
||||
}
|
||||
}
|
||||
ExprKind::Yield(optional_expression) => {
|
||||
walk_list!(visitor, visit_expr, optional_expression);
|
||||
}
|
||||
|
@ -12,6 +12,7 @@ rustc_ast_pretty = { path = "../rustc_ast_pretty" }
|
||||
rustc_data_structures = { path = "../rustc_data_structures" }
|
||||
rustc_errors = { path = "../rustc_errors" }
|
||||
rustc_hir = { path = "../rustc_hir" }
|
||||
rustc_fluent_macro = { path = "../rustc_fluent_macro" }
|
||||
rustc_index = { path = "../rustc_index" }
|
||||
rustc_middle = { path = "../rustc_middle" }
|
||||
rustc_macros = { path = "../rustc_macros" }
|
||||
|
@ -121,12 +121,16 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
LitKind::Err
|
||||
}
|
||||
};
|
||||
hir::ExprKind::Lit(respan(self.lower_span(e.span), lit_kind))
|
||||
let lit = self.arena.alloc(respan(self.lower_span(e.span), lit_kind));
|
||||
hir::ExprKind::Lit(lit)
|
||||
}
|
||||
ExprKind::IncludedBytes(bytes) => hir::ExprKind::Lit(respan(
|
||||
ExprKind::IncludedBytes(bytes) => {
|
||||
let lit = self.arena.alloc(respan(
|
||||
self.lower_span(e.span),
|
||||
LitKind::ByteStr(bytes.clone(), StrStyle::Cooked),
|
||||
)),
|
||||
));
|
||||
hir::ExprKind::Lit(lit)
|
||||
}
|
||||
ExprKind::Cast(expr, ty) => {
|
||||
let expr = self.lower_expr(expr);
|
||||
let ty =
|
||||
@ -285,6 +289,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
hir::ExprKind::InlineAsm(self.lower_inline_asm(e.span, asm))
|
||||
}
|
||||
ExprKind::FormatArgs(fmt) => self.lower_format_args(e.span, fmt),
|
||||
ExprKind::OffsetOf(container, fields) => hir::ExprKind::OffsetOf(
|
||||
self.lower_ty(
|
||||
container,
|
||||
&mut ImplTraitContext::Disallowed(ImplTraitPosition::OffsetOf),
|
||||
),
|
||||
self.arena.alloc_from_iter(fields.iter().map(|&ident| self.lower_ident(ident))),
|
||||
),
|
||||
ExprKind::Struct(se) => {
|
||||
let rest = match &se.rest {
|
||||
StructRest::Base(e) => Some(self.lower_expr(e)),
|
||||
@ -847,13 +858,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
let awaitee_arm = self.arm(awaitee_pat, loop_expr);
|
||||
|
||||
// `match ::std::future::IntoFuture::into_future(<expr>) { ... }`
|
||||
let into_future_span = self.mark_span_with_reason(
|
||||
DesugaringKind::Await,
|
||||
dot_await_span,
|
||||
self.allow_into_future.clone(),
|
||||
);
|
||||
let into_future_expr = self.expr_call_lang_item_fn(
|
||||
into_future_span,
|
||||
span,
|
||||
hir::LangItem::IntoFutureIntoFuture,
|
||||
arena_vec![self; expr],
|
||||
Some(expr_hir_id),
|
||||
@ -1746,40 +1752,31 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
}
|
||||
|
||||
pub(super) fn expr_usize(&mut self, sp: Span, value: usize) -> hir::Expr<'hir> {
|
||||
self.expr(
|
||||
sp,
|
||||
hir::ExprKind::Lit(hir::Lit {
|
||||
let lit = self.arena.alloc(hir::Lit {
|
||||
span: sp,
|
||||
node: ast::LitKind::Int(
|
||||
value as u128,
|
||||
ast::LitIntType::Unsigned(ast::UintTy::Usize),
|
||||
),
|
||||
}),
|
||||
)
|
||||
node: ast::LitKind::Int(value as u128, ast::LitIntType::Unsigned(ast::UintTy::Usize)),
|
||||
});
|
||||
self.expr(sp, hir::ExprKind::Lit(lit))
|
||||
}
|
||||
|
||||
pub(super) fn expr_u32(&mut self, sp: Span, value: u32) -> hir::Expr<'hir> {
|
||||
self.expr(
|
||||
sp,
|
||||
hir::ExprKind::Lit(hir::Lit {
|
||||
let lit = self.arena.alloc(hir::Lit {
|
||||
span: sp,
|
||||
node: ast::LitKind::Int(value.into(), ast::LitIntType::Unsigned(ast::UintTy::U32)),
|
||||
}),
|
||||
)
|
||||
});
|
||||
self.expr(sp, hir::ExprKind::Lit(lit))
|
||||
}
|
||||
|
||||
pub(super) fn expr_char(&mut self, sp: Span, value: char) -> hir::Expr<'hir> {
|
||||
self.expr(sp, hir::ExprKind::Lit(hir::Lit { span: sp, node: ast::LitKind::Char(value) }))
|
||||
let lit = self.arena.alloc(hir::Lit { span: sp, node: ast::LitKind::Char(value) });
|
||||
self.expr(sp, hir::ExprKind::Lit(lit))
|
||||
}
|
||||
|
||||
pub(super) fn expr_str(&mut self, sp: Span, value: Symbol) -> hir::Expr<'hir> {
|
||||
self.expr(
|
||||
sp,
|
||||
hir::ExprKind::Lit(hir::Lit {
|
||||
span: sp,
|
||||
node: ast::LitKind::Str(value, ast::StrStyle::Cooked),
|
||||
}),
|
||||
)
|
||||
let lit = self
|
||||
.arena
|
||||
.alloc(hir::Lit { span: sp, node: ast::LitKind::Str(value, ast::StrStyle::Cooked) });
|
||||
self.expr(sp, hir::ExprKind::Lit(lit))
|
||||
}
|
||||
|
||||
pub(super) fn expr_call_mut(
|
||||
|
@ -186,7 +186,7 @@ enum ArgumentType {
|
||||
/// Generates:
|
||||
///
|
||||
/// ```text
|
||||
/// <core::fmt::ArgumentV1>::new_…(arg)
|
||||
/// <core::fmt::Argument>::new_…(arg)
|
||||
/// ```
|
||||
fn make_argument<'hir>(
|
||||
ctx: &mut LoweringContext<'_, 'hir>,
|
||||
@ -220,19 +220,19 @@ fn make_argument<'hir>(
|
||||
/// Generates:
|
||||
///
|
||||
/// ```text
|
||||
/// <core::fmt::rt::v1::Count>::Is(…)
|
||||
/// <core::fmt::rt::Count>::Is(…)
|
||||
/// ```
|
||||
///
|
||||
/// or
|
||||
///
|
||||
/// ```text
|
||||
/// <core::fmt::rt::v1::Count>::Param(…)
|
||||
/// <core::fmt::rt::Count>::Param(…)
|
||||
/// ```
|
||||
///
|
||||
/// or
|
||||
///
|
||||
/// ```text
|
||||
/// <core::fmt::rt::v1::Count>::Implied
|
||||
/// <core::fmt::rt::Count>::Implied
|
||||
/// ```
|
||||
fn make_count<'hir>(
|
||||
ctx: &mut LoweringContext<'_, 'hir>,
|
||||
@ -278,13 +278,13 @@ fn make_count<'hir>(
|
||||
/// Generates
|
||||
///
|
||||
/// ```text
|
||||
/// <core::fmt::rt::v1::Argument::new(
|
||||
/// <core::fmt::rt::Placeholder::new(
|
||||
/// …usize, // position
|
||||
/// '…', // fill
|
||||
/// <core::fmt::rt::v1::Alignment>::…, // alignment
|
||||
/// <core::fmt::rt::Alignment>::…, // alignment
|
||||
/// …u32, // flags
|
||||
/// <core::fmt::rt::v1::Count::…>, // width
|
||||
/// <core::fmt::rt::v1::Count::…>, // precision
|
||||
/// <core::fmt::rt::Count::…>, // width
|
||||
/// <core::fmt::rt::Count::…>, // precision
|
||||
/// )
|
||||
/// ```
|
||||
fn make_format_spec<'hir>(
|
||||
@ -327,7 +327,7 @@ fn make_format_spec<'hir>(
|
||||
None => sym::Unknown,
|
||||
},
|
||||
);
|
||||
// This needs to match `FlagV1` in library/core/src/fmt/mod.rs.
|
||||
// This needs to match `Flag` in library/core/src/fmt/rt.rs.
|
||||
let flags: u32 = ((sign == Some(FormatSign::Plus)) as u32)
|
||||
| ((sign == Some(FormatSign::Minus)) as u32) << 1
|
||||
| (alternate as u32) << 2
|
||||
@ -438,7 +438,7 @@ fn expand_format_args<'hir>(
|
||||
// If the args array contains exactly all the original arguments once,
|
||||
// in order, we can use a simple array instead of a `match` construction.
|
||||
// However, if there's a yield point in any argument except the first one,
|
||||
// we don't do this, because an ArgumentV1 cannot be kept across yield points.
|
||||
// we don't do this, because an Argument cannot be kept across yield points.
|
||||
//
|
||||
// This is an optimization, speeding up compilation about 1-2% in some cases.
|
||||
// See https://github.com/rust-lang/rust/pull/106770#issuecomment-1380790609
|
||||
@ -449,9 +449,9 @@ fn expand_format_args<'hir>(
|
||||
let args = if use_simple_array {
|
||||
// Generate:
|
||||
// &[
|
||||
// <core::fmt::ArgumentV1>::new_display(&arg0),
|
||||
// <core::fmt::ArgumentV1>::new_lower_hex(&arg1),
|
||||
// <core::fmt::ArgumentV1>::new_debug(&arg2),
|
||||
// <core::fmt::Argument>::new_display(&arg0),
|
||||
// <core::fmt::Argument>::new_lower_hex(&arg1),
|
||||
// <core::fmt::Argument>::new_debug(&arg2),
|
||||
// …
|
||||
// ]
|
||||
let elements: Vec<_> = arguments
|
||||
@ -477,9 +477,9 @@ fn expand_format_args<'hir>(
|
||||
// Generate:
|
||||
// &match (&arg0, &arg1, &…) {
|
||||
// args => [
|
||||
// <core::fmt::ArgumentV1>::new_display(args.0),
|
||||
// <core::fmt::ArgumentV1>::new_lower_hex(args.1),
|
||||
// <core::fmt::ArgumentV1>::new_debug(args.0),
|
||||
// <core::fmt::Argument>::new_display(args.0),
|
||||
// <core::fmt::Argument>::new_lower_hex(args.1),
|
||||
// <core::fmt::Argument>::new_debug(args.0),
|
||||
// …
|
||||
// ]
|
||||
// }
|
||||
|
@ -5,7 +5,7 @@ use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_hir::definitions;
|
||||
use rustc_hir::intravisit::{self, Visitor};
|
||||
use rustc_hir::*;
|
||||
use rustc_index::vec::{Idx, IndexVec};
|
||||
use rustc_index::{Idx, IndexVec};
|
||||
use rustc_middle::span_bug;
|
||||
use rustc_session::Session;
|
||||
use rustc_span::source_map::SourceMap;
|
||||
|
@ -12,7 +12,7 @@ use rustc_hir as hir;
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID};
|
||||
use rustc_hir::PredicateOrigin;
|
||||
use rustc_index::vec::{Idx, IndexSlice, IndexVec};
|
||||
use rustc_index::{Idx, IndexSlice, IndexVec};
|
||||
use rustc_middle::ty::{ResolverAstLowering, TyCtxt};
|
||||
use rustc_span::edit_distance::find_best_match_for_name;
|
||||
use rustc_span::source_map::DesugaringKind;
|
||||
@ -83,15 +83,14 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> {
|
||||
impl_trait_bounds: Vec::new(),
|
||||
allow_try_trait: Some([sym::try_trait_v2, sym::yeet_desugar_details][..].into()),
|
||||
allow_gen_future: Some([sym::gen_future, sym::closure_track_caller][..].into()),
|
||||
allow_into_future: Some([sym::into_future][..].into()),
|
||||
generics_def_id_map: Default::default(),
|
||||
};
|
||||
lctx.with_hir_id_owner(owner, |lctx| f(lctx));
|
||||
|
||||
for (def_id, info) in lctx.children {
|
||||
self.owners.ensure_contains_elem(def_id, || hir::MaybeOwner::Phantom);
|
||||
debug_assert!(matches!(self.owners[def_id], hir::MaybeOwner::Phantom));
|
||||
self.owners[def_id] = info;
|
||||
let owner = self.owners.ensure_contains_elem(def_id, || hir::MaybeOwner::Phantom);
|
||||
debug_assert!(matches!(owner, hir::MaybeOwner::Phantom));
|
||||
*owner = info;
|
||||
}
|
||||
}
|
||||
|
||||
@ -99,8 +98,8 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> {
|
||||
&mut self,
|
||||
def_id: LocalDefId,
|
||||
) -> hir::MaybeOwner<&'hir hir::OwnerInfo<'hir>> {
|
||||
self.owners.ensure_contains_elem(def_id, || hir::MaybeOwner::Phantom);
|
||||
if let hir::MaybeOwner::Phantom = self.owners[def_id] {
|
||||
let owner = self.owners.ensure_contains_elem(def_id, || hir::MaybeOwner::Phantom);
|
||||
if let hir::MaybeOwner::Phantom = owner {
|
||||
let node = self.ast_index[def_id];
|
||||
match node {
|
||||
AstOwner::NonOwner => {}
|
||||
@ -138,12 +137,10 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> {
|
||||
// Evaluate with the lifetimes in `params` in-scope.
|
||||
// This is used to track which lifetimes have already been defined,
|
||||
// and which need to be replicated when lowering an async fn.
|
||||
match parent_hir.node().expect_item().kind {
|
||||
hir::ItemKind::Impl(hir::Impl { of_trait, .. }) => {
|
||||
lctx.is_in_trait_impl = of_trait.is_some();
|
||||
|
||||
if let hir::ItemKind::Impl(impl_) = parent_hir.node().expect_item().kind {
|
||||
lctx.is_in_trait_impl = impl_.of_trait.is_some();
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
|
||||
match ctxt {
|
||||
AssocCtxt::Trait => hir::OwnerNode::TraitItem(lctx.lower_trait_item(item)),
|
||||
@ -445,7 +442,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
ItemKind::MacroDef(MacroDef { body, macro_rules }) => {
|
||||
let body = P(self.lower_delim_args(body));
|
||||
let macro_kind = self.resolver.decl_macro_kind(self.local_def_id(id));
|
||||
hir::ItemKind::Macro(ast::MacroDef { body, macro_rules: *macro_rules }, macro_kind)
|
||||
let macro_def = self.arena.alloc(ast::MacroDef { body, macro_rules: *macro_rules });
|
||||
hir::ItemKind::Macro(macro_def, macro_kind)
|
||||
}
|
||||
ItemKind::MacCall(..) => {
|
||||
panic!("`TyMac` should have been expanded by now")
|
||||
|
@ -55,13 +55,13 @@ use rustc_data_structures::sync::Lrc;
|
||||
use rustc_errors::{
|
||||
DiagnosticArgFromDisplay, DiagnosticMessage, Handler, StashKey, SubdiagnosticMessage,
|
||||
};
|
||||
use rustc_fluent_macro::fluent_messages;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::{DefKind, LifetimeRes, Namespace, PartialRes, PerNS, Res};
|
||||
use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID};
|
||||
use rustc_hir::definitions::DefPathData;
|
||||
use rustc_hir::{ConstArg, GenericArg, ItemLocalId, ParamName, TraitCandidate};
|
||||
use rustc_index::vec::{Idx, IndexSlice, IndexVec};
|
||||
use rustc_macros::fluent_messages;
|
||||
use rustc_index::{Idx, IndexSlice, IndexVec};
|
||||
use rustc_middle::{
|
||||
span_bug,
|
||||
ty::{ResolverAstLowering, TyCtxt},
|
||||
@ -136,7 +136,6 @@ struct LoweringContext<'a, 'hir> {
|
||||
|
||||
allow_try_trait: Option<Lrc<[Symbol]>>,
|
||||
allow_gen_future: Option<Lrc<[Symbol]>>,
|
||||
allow_into_future: Option<Lrc<[Symbol]>>,
|
||||
|
||||
/// Mapping from generics `def_id`s to TAIT generics `def_id`s.
|
||||
/// For each captured lifetime (e.g., 'a), we create a new lifetime parameter that is a generic
|
||||
@ -283,6 +282,7 @@ enum ImplTraitPosition {
|
||||
FieldTy,
|
||||
Cast,
|
||||
ImplSelf,
|
||||
OffsetOf,
|
||||
}
|
||||
|
||||
impl std::fmt::Display for ImplTraitPosition {
|
||||
@ -313,6 +313,7 @@ impl std::fmt::Display for ImplTraitPosition {
|
||||
ImplTraitPosition::FieldTy => "field types",
|
||||
ImplTraitPosition::Cast => "cast types",
|
||||
ImplTraitPosition::ImplSelf => "impl headers",
|
||||
ImplTraitPosition::OffsetOf => "`offset_of!` params",
|
||||
};
|
||||
|
||||
write!(f, "{name}")
|
||||
@ -332,10 +333,7 @@ enum FnDeclKind {
|
||||
|
||||
impl FnDeclKind {
|
||||
fn param_impl_trait_allowed(&self) -> bool {
|
||||
match self {
|
||||
FnDeclKind::Fn | FnDeclKind::Inherent | FnDeclKind::Impl | FnDeclKind::Trait => true,
|
||||
_ => false,
|
||||
}
|
||||
matches!(self, FnDeclKind::Fn | FnDeclKind::Inherent | FnDeclKind::Impl | FnDeclKind::Trait)
|
||||
}
|
||||
|
||||
fn return_impl_trait_allowed(&self, tcx: TyCtxt<'_>) -> bool {
|
||||
@ -371,8 +369,8 @@ fn index_crate<'a>(
|
||||
krate: &'a Crate,
|
||||
) -> IndexVec<LocalDefId, AstOwner<'a>> {
|
||||
let mut indexer = Indexer { node_id_to_def_id, index: IndexVec::new() };
|
||||
indexer.index.ensure_contains_elem(CRATE_DEF_ID, || AstOwner::NonOwner);
|
||||
indexer.index[CRATE_DEF_ID] = AstOwner::Crate(krate);
|
||||
*indexer.index.ensure_contains_elem(CRATE_DEF_ID, || AstOwner::NonOwner) =
|
||||
AstOwner::Crate(krate);
|
||||
visit::walk_crate(&mut indexer, krate);
|
||||
return indexer.index;
|
||||
|
||||
@ -389,22 +387,21 @@ fn index_crate<'a>(
|
||||
|
||||
fn visit_item(&mut self, item: &'a ast::Item) {
|
||||
let def_id = self.node_id_to_def_id[&item.id];
|
||||
self.index.ensure_contains_elem(def_id, || AstOwner::NonOwner);
|
||||
self.index[def_id] = AstOwner::Item(item);
|
||||
*self.index.ensure_contains_elem(def_id, || AstOwner::NonOwner) = AstOwner::Item(item);
|
||||
visit::walk_item(self, item)
|
||||
}
|
||||
|
||||
fn visit_assoc_item(&mut self, item: &'a ast::AssocItem, ctxt: visit::AssocCtxt) {
|
||||
let def_id = self.node_id_to_def_id[&item.id];
|
||||
self.index.ensure_contains_elem(def_id, || AstOwner::NonOwner);
|
||||
self.index[def_id] = AstOwner::AssocItem(item, ctxt);
|
||||
*self.index.ensure_contains_elem(def_id, || AstOwner::NonOwner) =
|
||||
AstOwner::AssocItem(item, ctxt);
|
||||
visit::walk_assoc_item(self, item, ctxt);
|
||||
}
|
||||
|
||||
fn visit_foreign_item(&mut self, item: &'a ast::ForeignItem) {
|
||||
let def_id = self.node_id_to_def_id[&item.id];
|
||||
self.index.ensure_contains_elem(def_id, || AstOwner::NonOwner);
|
||||
self.index[def_id] = AstOwner::ForeignItem(item);
|
||||
*self.index.ensure_contains_elem(def_id, || AstOwner::NonOwner) =
|
||||
AstOwner::ForeignItem(item);
|
||||
visit::walk_foreign_item(self, item);
|
||||
}
|
||||
}
|
||||
|
@ -12,6 +12,7 @@ rustc_data_structures = { path = "../rustc_data_structures" }
|
||||
rustc_errors = { path = "../rustc_errors" }
|
||||
rustc_feature = { path = "../rustc_feature" }
|
||||
rustc_macros = { path = "../rustc_macros" }
|
||||
rustc_fluent_macro = { path = "../rustc_fluent_macro" }
|
||||
rustc_parse = { path = "../rustc_parse" }
|
||||
rustc_session = { path = "../rustc_session" }
|
||||
rustc_span = { path = "../rustc_span" }
|
||||
|
@ -231,7 +231,7 @@ ast_passes_feature_on_non_nightly = `#![feature]` may not be used on the {$chann
|
||||
.suggestion = remove the attribute
|
||||
.stable_since = the feature `{$name}` has been stable since `{$since}` and no longer requires an attribute to enable
|
||||
|
||||
ast_passes_incompatbile_features = `{$f1}` and `{$f2}` are incompatible, using them at the same time is not allowed
|
||||
ast_passes_incompatible_features = `{$f1}` and `{$f2}` are incompatible, using them at the same time is not allowed
|
||||
.help = remove one of these features
|
||||
|
||||
ast_passes_show_span = {$msg}
|
||||
|
@ -677,7 +677,7 @@ impl AddToDiagnostic for StableFeature {
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_passes_incompatbile_features)]
|
||||
#[diag(ast_passes_incompatible_features)]
|
||||
#[help]
|
||||
pub struct IncompatibleFeatures {
|
||||
#[primary_span]
|
||||
|
@ -13,7 +13,7 @@
|
||||
#![deny(rustc::diagnostic_outside_of_impl)]
|
||||
|
||||
use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
|
||||
use rustc_macros::fluent_messages;
|
||||
use rustc_fluent_macro::fluent_messages;
|
||||
|
||||
pub mod ast_validation;
|
||||
mod errors;
|
||||
|
@ -360,7 +360,7 @@ impl Printer {
|
||||
|
||||
fn check_stack(&mut self, mut depth: usize) {
|
||||
while let Some(&index) = self.scan_stack.back() {
|
||||
let mut entry = &mut self.buf[index];
|
||||
let entry = &mut self.buf[index];
|
||||
match entry.token {
|
||||
Token::Begin(_) => {
|
||||
if depth == 0 {
|
||||
|
@ -549,6 +549,26 @@ impl<'a> State<'a> {
|
||||
self.end();
|
||||
self.pclose();
|
||||
}
|
||||
ast::ExprKind::OffsetOf(container, fields) => {
|
||||
// FIXME: This should have its own syntax, distinct from a macro invocation.
|
||||
self.word("offset_of!");
|
||||
self.popen();
|
||||
self.rbox(0, Inconsistent);
|
||||
self.print_type(container);
|
||||
self.word(",");
|
||||
self.space();
|
||||
|
||||
if let Some((&first, rest)) = fields.split_first() {
|
||||
self.print_ident(first);
|
||||
|
||||
for &field in rest {
|
||||
self.word(".");
|
||||
self.print_ident(field);
|
||||
}
|
||||
}
|
||||
|
||||
self.end();
|
||||
}
|
||||
ast::ExprKind::MacCall(m) => self.print_mac(m),
|
||||
ast::ExprKind::Paren(e) => {
|
||||
self.popen();
|
||||
|
@ -9,6 +9,7 @@ edition = "2021"
|
||||
rustc_ast_pretty = { path = "../rustc_ast_pretty" }
|
||||
rustc_serialize = { path = "../rustc_serialize" }
|
||||
rustc_errors = { path = "../rustc_errors" }
|
||||
rustc_fluent_macro = { path = "../rustc_fluent_macro" }
|
||||
rustc_span = { path = "../rustc_span" }
|
||||
rustc_data_structures = { path = "../rustc_data_structures" }
|
||||
rustc_feature = { path = "../rustc_feature" }
|
||||
|
@ -12,7 +12,7 @@
|
||||
extern crate rustc_macros;
|
||||
|
||||
use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
|
||||
use rustc_macros::fluent_messages;
|
||||
use rustc_fluent_macro::fluent_messages;
|
||||
|
||||
mod builtin;
|
||||
mod session_diagnostics;
|
||||
|
@ -15,12 +15,12 @@ rustc_data_structures = { path = "../rustc_data_structures" }
|
||||
rustc_errors = { path = "../rustc_errors" }
|
||||
rustc_graphviz = { path = "../rustc_graphviz" }
|
||||
rustc_hir = { path = "../rustc_hir" }
|
||||
rustc_fluent_macro = { path = "../rustc_fluent_macro" }
|
||||
rustc_index = { path = "../rustc_index" }
|
||||
rustc_infer = { path = "../rustc_infer" }
|
||||
rustc_lexer = { path = "../rustc_lexer" }
|
||||
rustc_macros = { path = "../rustc_macros" }
|
||||
rustc_middle = { path = "../rustc_middle" }
|
||||
rustc_const_eval = { path = "../rustc_const_eval" }
|
||||
rustc_mir_dataflow = { path = "../rustc_mir_dataflow" }
|
||||
rustc_serialize = { path = "../rustc_serialize" }
|
||||
rustc_session = { path = "../rustc_session" }
|
||||
|
@ -56,18 +56,6 @@ borrowck_returned_lifetime_short =
|
||||
borrowck_used_impl_require_static =
|
||||
the used `impl` has a `'static` requirement
|
||||
|
||||
borrowck_capture_kind_label =
|
||||
capture is {$kind_desc} because of use here
|
||||
|
||||
borrowck_var_borrow_by_use_place_in_generator =
|
||||
borrow occurs due to use of {$place} in closure in generator
|
||||
|
||||
borrowck_var_borrow_by_use_place_in_closure =
|
||||
borrow occurs due to use of {$place} in closure
|
||||
|
||||
borrowck_var_borrow_by_use_place =
|
||||
borrow occurs due to use of {$place}
|
||||
|
||||
borrowck_borrow_due_to_use_generator =
|
||||
borrow occurs due to use in generator
|
||||
|
||||
@ -101,12 +89,63 @@ borrowck_capture_mut =
|
||||
borrowck_capture_move =
|
||||
capture is moved because of use here
|
||||
|
||||
borrowck_var_borrow_by_use_place_in_generator =
|
||||
{$is_single_var ->
|
||||
*[true] borrow occurs
|
||||
[false] borrows occur
|
||||
} due to use of {$place} in generator
|
||||
|
||||
borrowck_var_borrow_by_use_place_in_closure =
|
||||
{$is_single_var ->
|
||||
*[true] borrow occurs
|
||||
[false] borrows occur
|
||||
} due to use of {$place} in closure
|
||||
|
||||
borrowck_var_borrow_by_use_in_generator =
|
||||
borrow occurs due to use in generator
|
||||
|
||||
borrowck_var_borrow_by_use_in_closure =
|
||||
borrow occurs due to use in closure
|
||||
|
||||
borrowck_var_move_by_use_place_in_generator =
|
||||
move occurs due to use of {$place} in generator
|
||||
|
||||
borrowck_var_move_by_use_place_in_closure =
|
||||
move occurs due to use of {$place} in closure
|
||||
|
||||
borrowck_var_move_by_use_in_generator =
|
||||
move occurs due to use in generator
|
||||
|
||||
borrowck_var_move_by_use_in_closure =
|
||||
move occurs due to use in closure
|
||||
|
||||
borrowck_partial_var_move_by_use_in_generator =
|
||||
variable {$is_partial ->
|
||||
[true] partially moved
|
||||
*[false] moved
|
||||
} due to use in generator
|
||||
|
||||
borrowck_partial_var_move_by_use_in_closure =
|
||||
variable {$is_partial ->
|
||||
[true] partially moved
|
||||
*[false] moved
|
||||
} due to use in closure
|
||||
|
||||
borrowck_var_first_borrow_by_use_place_in_generator =
|
||||
first borrow occurs due to use of {$place} in generator
|
||||
|
||||
borrowck_var_first_borrow_by_use_place_in_closure =
|
||||
first borrow occurs due to use of {$place} in closure
|
||||
|
||||
borrowck_var_second_borrow_by_use_place_in_generator =
|
||||
second borrow occurs due to use of {$place} in generator
|
||||
|
||||
borrowck_var_second_borrow_by_use_place_in_closure =
|
||||
second borrow occurs due to use of {$place} in closure
|
||||
|
||||
borrowck_var_mutable_borrow_by_use_place_in_closure =
|
||||
mutable borrow occurs due to use of {$place} in closure
|
||||
|
||||
borrowck_cannot_move_when_borrowed =
|
||||
cannot move out of {$place ->
|
||||
[value] value
|
||||
@ -127,3 +166,90 @@ borrowck_opaque_type_non_generic_param =
|
||||
[true] cannot use static lifetime; use a bound lifetime instead or remove the lifetime parameter from the opaque type
|
||||
*[other] this generic parameter must be used with a generic {$kind} parameter
|
||||
}
|
||||
|
||||
borrowck_moved_due_to_call =
|
||||
{$place_name} {$is_partial ->
|
||||
[true] partially moved
|
||||
*[false] moved
|
||||
} due to this {$is_loop_message ->
|
||||
[true] call, in previous iteration of loop
|
||||
*[false] call
|
||||
}
|
||||
|
||||
borrowck_moved_due_to_usage_in_operator =
|
||||
{$place_name} {$is_partial ->
|
||||
[true] partially moved
|
||||
*[false] moved
|
||||
} due to usage in {$is_loop_message ->
|
||||
[true] operator, in previous iteration of loop
|
||||
*[false] operator
|
||||
}
|
||||
|
||||
borrowck_moved_due_to_implicit_into_iter_call =
|
||||
{$place_name} {$is_partial ->
|
||||
[true] partially moved
|
||||
*[false] moved
|
||||
} due to this implicit call to {$is_loop_message ->
|
||||
[true] `.into_iter()`, in previous iteration of loop
|
||||
*[false] `.into_iter()`
|
||||
}
|
||||
|
||||
borrowck_moved_due_to_method_call =
|
||||
{$place_name} {$is_partial ->
|
||||
[true] partially moved
|
||||
*[false] moved
|
||||
} due to this method {$is_loop_message ->
|
||||
[true] call, in previous iteration of loop
|
||||
*[false] call
|
||||
}
|
||||
|
||||
borrowck_value_moved_here =
|
||||
value {$is_partial ->
|
||||
[true] partially moved
|
||||
*[false] moved
|
||||
} {$is_move_msg ->
|
||||
[true] into closure here
|
||||
*[false] here
|
||||
}{$is_loop_message ->
|
||||
[true] , in previous iteration of loop
|
||||
*[false] {""}
|
||||
}
|
||||
|
||||
borrowck_consider_borrow_type_contents =
|
||||
help: consider calling `.as_ref()` or `.as_mut()` to borrow the type's contents
|
||||
|
||||
borrowck_moved_a_fn_once_in_call =
|
||||
this value implements `FnOnce`, which causes it to be moved when called
|
||||
|
||||
borrowck_calling_operator_moves_lhs =
|
||||
calling this operator moves the left-hand side
|
||||
|
||||
borrowck_func_take_self_moved_place =
|
||||
`{$func}` takes ownership of the receiver `self`, which moves {$place_name}
|
||||
|
||||
borrowck_suggest_iterate_over_slice =
|
||||
consider iterating over a slice of the `{$ty}`'s content to avoid moving into the `for` loop
|
||||
|
||||
borrowck_suggest_create_freash_reborrow =
|
||||
consider reborrowing the `Pin` instead of moving it
|
||||
|
||||
borrowck_value_capture_here =
|
||||
value captured {$is_within ->
|
||||
[true] here by generator
|
||||
*[false] here
|
||||
}
|
||||
|
||||
borrowck_move_out_place_here =
|
||||
{$place} is moved here
|
||||
|
||||
borrowck_closure_invoked_twice =
|
||||
closure cannot be invoked more than once because it moves the variable `{$place_name}` out of its environment
|
||||
|
||||
borrowck_closure_moved_twice =
|
||||
closure cannot be moved more than once as it is not `Copy` due to moving the variable `{$place_name}` out of its environment
|
||||
|
||||
borrowck_ty_no_impl_copy =
|
||||
{$is_partial_move ->
|
||||
[true] partial move
|
||||
*[false] move
|
||||
} occurs because {$place} has type `{$ty}`, which does not implement the `Copy` trait
|
||||
|
@ -469,6 +469,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
|
||||
}
|
||||
|
||||
#[rustc_lint_diagnostics]
|
||||
#[track_caller]
|
||||
pub(crate) fn struct_span_err_with_code<S: Into<MultiSpan>>(
|
||||
&self,
|
||||
sp: S,
|
||||
|
@ -1,5 +1,5 @@
|
||||
use rustc_data_structures::graph;
|
||||
use rustc_index::vec::IndexVec;
|
||||
use rustc_index::IndexVec;
|
||||
use rustc_middle::mir::ConstraintCategory;
|
||||
use rustc_middle::ty::{RegionVid, VarianceDiagInfo};
|
||||
use rustc_span::DUMMY_SP;
|
||||
|
@ -2,7 +2,7 @@
|
||||
#![deny(rustc::diagnostic_outside_of_impl)]
|
||||
|
||||
use rustc_data_structures::graph::scc::Sccs;
|
||||
use rustc_index::vec::{IndexSlice, IndexVec};
|
||||
use rustc_index::{IndexSlice, IndexVec};
|
||||
use rustc_middle::mir::ConstraintCategory;
|
||||
use rustc_middle::ty::{RegionVid, VarianceDiagInfo};
|
||||
use rustc_span::Span;
|
||||
|
@ -3,10 +3,10 @@
|
||||
//! This file provides API for compiler consumers.
|
||||
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_index::vec::IndexSlice;
|
||||
use rustc_index::IndexSlice;
|
||||
use rustc_infer::infer::{DefiningAnchor, TyCtxtInferExt};
|
||||
use rustc_middle::mir::Body;
|
||||
use rustc_middle::ty::{self, TyCtxt};
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
|
||||
pub use super::{
|
||||
facts::{AllFacts as PoloniusInput, RustcFacts},
|
||||
@ -28,12 +28,9 @@ pub use super::{
|
||||
/// that shows how to do this at `tests/run-make/obtain-borrowck/`.
|
||||
///
|
||||
/// * Polonius is highly unstable, so expect regular changes in its signature or other details.
|
||||
pub fn get_body_with_borrowck_facts(
|
||||
tcx: TyCtxt<'_>,
|
||||
def: ty::WithOptConstParam<LocalDefId>,
|
||||
) -> BodyWithBorrowckFacts<'_> {
|
||||
pub fn get_body_with_borrowck_facts(tcx: TyCtxt<'_>, def: LocalDefId) -> BodyWithBorrowckFacts<'_> {
|
||||
let (input_body, promoted) = tcx.mir_promoted(def);
|
||||
let infcx = tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bind(def.did)).build();
|
||||
let infcx = tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bind(def)).build();
|
||||
let input_body: &Body<'_> = &input_body.borrow();
|
||||
let promoted: &IndexSlice<_, _> = &promoted.borrow();
|
||||
*super::do_mir_borrowck(&infcx, input_body, promoted, true).1.unwrap()
|
||||
|
@ -52,12 +52,16 @@ pub fn categorize(context: PlaceContext) -> Option<DefUse> {
|
||||
PlaceContext::NonMutatingUse(NonMutatingUseContext::ShallowBorrow) |
|
||||
PlaceContext::NonMutatingUse(NonMutatingUseContext::UniqueBorrow) |
|
||||
|
||||
// `PlaceMention` and `AscribeUserType` both evaluate the place, which must not
|
||||
// contain dangling references.
|
||||
PlaceContext::NonUse(NonUseContext::PlaceMention) |
|
||||
PlaceContext::NonUse(NonUseContext::AscribeUserTy) |
|
||||
|
||||
PlaceContext::MutatingUse(MutatingUseContext::AddressOf) |
|
||||
PlaceContext::NonMutatingUse(NonMutatingUseContext::AddressOf) |
|
||||
PlaceContext::NonMutatingUse(NonMutatingUseContext::Inspect) |
|
||||
PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) |
|
||||
PlaceContext::NonMutatingUse(NonMutatingUseContext::Move) |
|
||||
PlaceContext::NonUse(NonUseContext::AscribeUserTy) |
|
||||
PlaceContext::MutatingUse(MutatingUseContext::Retag) =>
|
||||
Some(DefUse::Use),
|
||||
|
||||
@ -72,8 +76,6 @@ pub fn categorize(context: PlaceContext) -> Option<DefUse> {
|
||||
PlaceContext::MutatingUse(MutatingUseContext::Drop) =>
|
||||
Some(DefUse::Drop),
|
||||
|
||||
// This statement exists to help unsafeck. It does not require the place to be live.
|
||||
PlaceContext::NonUse(NonUseContext::PlaceMention) => None,
|
||||
// Debug info is neither def nor use.
|
||||
PlaceContext::NonUse(NonUseContext::VarDebugInfo) => None,
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
use std::iter;
|
||||
|
||||
use either::Either;
|
||||
use rustc_const_eval::util::CallKind;
|
||||
use rustc_data_structures::captures::Captures;
|
||||
use rustc_data_structures::fx::FxIndexSet;
|
||||
use rustc_errors::{
|
||||
@ -9,8 +10,8 @@ use rustc_hir as hir;
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
use rustc_hir::intravisit::{walk_block, walk_expr, Visitor};
|
||||
use rustc_hir::{AsyncGeneratorKind, GeneratorKind, LangItem};
|
||||
use rustc_infer::infer::TyCtxtInferExt;
|
||||
use rustc_infer::traits::ObligationCause;
|
||||
use rustc_middle::hir::nested_filter::OnlyBodies;
|
||||
use rustc_middle::mir::tcx::PlaceTy;
|
||||
use rustc_middle::mir::{
|
||||
self, AggregateKind, BindingForm, BorrowKind, ClearCrossCrate, ConstraintCategory,
|
||||
@ -18,20 +19,19 @@ use rustc_middle::mir::{
|
||||
ProjectionElem, Rvalue, Statement, StatementKind, Terminator, TerminatorKind, VarBindingForm,
|
||||
};
|
||||
use rustc_middle::ty::{self, suggest_constraining_type_params, PredicateKind, Ty};
|
||||
use rustc_middle::util::CallKind;
|
||||
use rustc_mir_dataflow::move_paths::{InitKind, MoveOutIndex, MovePathIndex};
|
||||
use rustc_span::def_id::LocalDefId;
|
||||
use rustc_span::hygiene::DesugaringKind;
|
||||
use rustc_span::symbol::{kw, sym};
|
||||
use rustc_span::symbol::{kw, sym, Ident};
|
||||
use rustc_span::{BytePos, Span, Symbol};
|
||||
use rustc_trait_selection::infer::InferCtxtExt;
|
||||
use rustc_trait_selection::traits::ObligationCtxt;
|
||||
|
||||
use crate::borrow_set::TwoPhaseActivation;
|
||||
use crate::borrowck_errors;
|
||||
|
||||
use crate::diagnostics::conflict_errors::StorageDeadOrDrop::LocalStorageDead;
|
||||
use crate::diagnostics::find_all_local_uses;
|
||||
use crate::diagnostics::mutability_errors::mut_borrow_of_mutable_ref;
|
||||
use crate::diagnostics::{find_all_local_uses, CapturedMessageOpt};
|
||||
use crate::{
|
||||
borrow_set::BorrowData, diagnostics::Instance, prefixes::IsPrefixOf,
|
||||
InitializationRequiringAction, MirBorrowckCtxt, PrefixSet, WriteKind,
|
||||
@ -183,13 +183,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
let move_spans = self.move_spans(moved_place.as_ref(), move_out.source);
|
||||
let move_span = move_spans.args_or_use();
|
||||
|
||||
let move_msg = if move_spans.for_closure() { " into closure" } else { "" };
|
||||
let is_move_msg = move_spans.for_closure();
|
||||
|
||||
let loop_message = if location == move_out.source || move_site.traversed_back_edge {
|
||||
", in previous iteration of loop"
|
||||
} else {
|
||||
""
|
||||
};
|
||||
let is_loop_message = location == move_out.source || move_site.traversed_back_edge;
|
||||
|
||||
if location == move_out.source {
|
||||
is_loop_move = true;
|
||||
@ -206,17 +202,21 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
);
|
||||
}
|
||||
|
||||
let msg_opt = CapturedMessageOpt {
|
||||
is_partial_move,
|
||||
is_loop_message,
|
||||
is_move_msg,
|
||||
is_loop_move,
|
||||
maybe_reinitialized_locations_is_empty: maybe_reinitialized_locations
|
||||
.is_empty(),
|
||||
};
|
||||
self.explain_captures(
|
||||
&mut err,
|
||||
span,
|
||||
move_span,
|
||||
move_spans,
|
||||
*moved_place,
|
||||
partially_str,
|
||||
loop_message,
|
||||
move_msg,
|
||||
is_loop_move,
|
||||
maybe_reinitialized_locations.is_empty(),
|
||||
msg_opt,
|
||||
);
|
||||
}
|
||||
seen_spans.insert(move_span);
|
||||
@ -282,12 +282,21 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
}
|
||||
|
||||
if needs_note {
|
||||
let span = if let Some(local) = place.as_local() {
|
||||
Some(self.body.local_decls[local].source_info.span)
|
||||
if let Some(local) = place.as_local() {
|
||||
let span = self.body.local_decls[local].source_info.span;
|
||||
err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label {
|
||||
is_partial_move,
|
||||
ty,
|
||||
place: ¬e_msg,
|
||||
span,
|
||||
});
|
||||
} else {
|
||||
None
|
||||
err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Note {
|
||||
is_partial_move,
|
||||
ty,
|
||||
place: ¬e_msg,
|
||||
});
|
||||
};
|
||||
self.note_type_does_not_implement_copy(&mut err, ¬e_msg, ty, span, partial_str);
|
||||
}
|
||||
|
||||
if let UseSpans::FnSelfUse {
|
||||
@ -633,11 +642,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
let Some(default_trait) = tcx.get_diagnostic_item(sym::Default) else {
|
||||
return false;
|
||||
};
|
||||
// Regions are already solved, so we must use a fresh InferCtxt,
|
||||
// but the type has region variables, so erase those.
|
||||
tcx.infer_ctxt()
|
||||
.build()
|
||||
.type_implements_trait(default_trait, [tcx.erase_regions(ty)], param_env)
|
||||
self.infcx
|
||||
.type_implements_trait(default_trait, [ty], param_env)
|
||||
.must_apply_modulo_regions()
|
||||
};
|
||||
|
||||
@ -696,7 +702,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
.copied()
|
||||
.find_map(find_fn_kind_from_did),
|
||||
ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => tcx
|
||||
.bound_explicit_item_bounds(def_id)
|
||||
.explicit_item_bounds(def_id)
|
||||
.subst_iter_copied(tcx, substs)
|
||||
.find_map(find_fn_kind_from_did),
|
||||
ty::Closure(_, substs) => match substs.as_closure().kind() {
|
||||
@ -730,13 +736,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
fn suggest_cloning(&self, err: &mut Diagnostic, ty: Ty<'tcx>, span: Span) {
|
||||
let tcx = self.infcx.tcx;
|
||||
// Try to find predicates on *generic params* that would allow copying `ty`
|
||||
let infcx = tcx.infer_ctxt().build();
|
||||
|
||||
if let Some(clone_trait_def) = tcx.lang_items().clone_trait()
|
||||
&& infcx
|
||||
&& self.infcx
|
||||
.type_implements_trait(
|
||||
clone_trait_def,
|
||||
[tcx.erase_regions(ty)],
|
||||
[ty],
|
||||
self.param_env,
|
||||
)
|
||||
.must_apply_modulo_regions()
|
||||
@ -760,12 +764,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
.and_then(|def_id| tcx.hir().get_generics(def_id))
|
||||
else { return; };
|
||||
// Try to find predicates on *generic params* that would allow copying `ty`
|
||||
let infcx = tcx.infer_ctxt().build();
|
||||
let ocx = ObligationCtxt::new(&infcx);
|
||||
let ocx = ObligationCtxt::new(&self.infcx);
|
||||
let copy_did = tcx.require_lang_item(LangItem::Copy, Some(span));
|
||||
let cause = ObligationCause::misc(span, self.mir_def_id());
|
||||
|
||||
ocx.register_bound(cause, self.param_env, infcx.tcx.erase_regions(ty), copy_did);
|
||||
ocx.register_bound(cause, self.param_env, ty, copy_did);
|
||||
let errors = ocx.select_all_or_error();
|
||||
|
||||
// Only emit suggestion if all required predicates are on generic
|
||||
@ -827,11 +830,13 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
|
||||
borrow_spans.var_path_only_subdiag(&mut err, crate::InitializationRequiringAction::Borrow);
|
||||
|
||||
move_spans.var_span_label(
|
||||
&mut err,
|
||||
format!("move occurs due to use{}", move_spans.describe()),
|
||||
"moved",
|
||||
);
|
||||
move_spans.var_subdiag(None, &mut err, None, |kind, var_span| {
|
||||
use crate::session_diagnostics::CaptureVarCause::*;
|
||||
match kind {
|
||||
Some(_) => MoveUseInGenerator { var_span },
|
||||
None => MoveUseInClosure { var_span },
|
||||
}
|
||||
});
|
||||
|
||||
self.explain_why_borrow_contains_point(location, borrow, None)
|
||||
.add_explanation_to_diagnostic(
|
||||
@ -868,13 +873,15 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
borrow_span,
|
||||
&self.describe_any_place(borrow.borrowed_place.as_ref()),
|
||||
);
|
||||
borrow_spans.var_subdiag(&mut err, Some(borrow.kind), |kind, var_span| {
|
||||
borrow_spans.var_subdiag(None, &mut err, Some(borrow.kind), |kind, var_span| {
|
||||
use crate::session_diagnostics::CaptureVarCause::*;
|
||||
let place = &borrow.borrowed_place;
|
||||
let desc_place = self.describe_any_place(place.as_ref());
|
||||
match kind {
|
||||
Some(_) => BorrowUsePlaceGenerator { place: desc_place, var_span },
|
||||
None => BorrowUsePlaceClosure { place: desc_place, var_span },
|
||||
Some(_) => {
|
||||
BorrowUsePlaceGenerator { place: desc_place, var_span, is_single_var: true }
|
||||
}
|
||||
None => BorrowUsePlaceClosure { place: desc_place, var_span, is_single_var: true },
|
||||
}
|
||||
});
|
||||
|
||||
@ -946,7 +953,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
&msg_borrow,
|
||||
None,
|
||||
);
|
||||
self.suggest_binding_for_closure_capture_self(
|
||||
self.suggest_binding_for_closure_capture_self(&mut err, &issued_spans);
|
||||
self.suggest_using_closure_argument_instead_of_capture(
|
||||
&mut err,
|
||||
issued_borrow.borrowed_place,
|
||||
&issued_spans,
|
||||
@ -969,6 +977,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
place,
|
||||
issued_borrow.borrowed_place,
|
||||
);
|
||||
self.suggest_using_closure_argument_instead_of_capture(
|
||||
&mut err,
|
||||
issued_borrow.borrowed_place,
|
||||
&issued_spans,
|
||||
);
|
||||
err
|
||||
}
|
||||
|
||||
@ -988,16 +1001,26 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
immutable_section_description,
|
||||
"mutably borrow",
|
||||
);
|
||||
borrow_spans.var_span_label(
|
||||
borrow_spans.var_subdiag(
|
||||
None,
|
||||
&mut err,
|
||||
format!(
|
||||
"borrow occurs due to use of {}{}",
|
||||
desc_place,
|
||||
borrow_spans.describe(),
|
||||
),
|
||||
"immutable",
|
||||
Some(BorrowKind::Unique),
|
||||
|kind, var_span| {
|
||||
use crate::session_diagnostics::CaptureVarCause::*;
|
||||
match kind {
|
||||
Some(_) => BorrowUsePlaceGenerator {
|
||||
place: desc_place,
|
||||
var_span,
|
||||
is_single_var: true,
|
||||
},
|
||||
None => BorrowUsePlaceClosure {
|
||||
place: desc_place,
|
||||
var_span,
|
||||
is_single_var: true,
|
||||
},
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
return err;
|
||||
} else {
|
||||
first_borrow_desc = "immutable ";
|
||||
@ -1070,32 +1093,48 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
};
|
||||
|
||||
if issued_spans == borrow_spans {
|
||||
borrow_spans.var_span_label(
|
||||
&mut err,
|
||||
format!("borrows occur due to use of {}{}", desc_place, borrow_spans.describe(),),
|
||||
gen_borrow_kind.describe_mutability(),
|
||||
);
|
||||
borrow_spans.var_subdiag(None, &mut err, Some(gen_borrow_kind), |kind, var_span| {
|
||||
use crate::session_diagnostics::CaptureVarCause::*;
|
||||
match kind {
|
||||
Some(_) => BorrowUsePlaceGenerator {
|
||||
place: desc_place,
|
||||
var_span,
|
||||
is_single_var: false,
|
||||
},
|
||||
None => {
|
||||
BorrowUsePlaceClosure { place: desc_place, var_span, is_single_var: false }
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
issued_spans.var_subdiag(
|
||||
Some(&self.infcx.tcx.sess.parse_sess.span_diagnostic),
|
||||
&mut err,
|
||||
Some(issued_borrow.kind),
|
||||
|kind, var_span| {
|
||||
use crate::session_diagnostics::CaptureVarCause::*;
|
||||
let borrow_place = &issued_borrow.borrowed_place;
|
||||
let borrow_place_desc = self.describe_any_place(borrow_place.as_ref());
|
||||
issued_spans.var_span_label(
|
||||
&mut err,
|
||||
format!(
|
||||
"first borrow occurs due to use of {}{}",
|
||||
borrow_place_desc,
|
||||
issued_spans.describe(),
|
||||
),
|
||||
issued_borrow.kind.describe_mutability(),
|
||||
match kind {
|
||||
Some(_) => {
|
||||
FirstBorrowUsePlaceGenerator { place: borrow_place_desc, var_span }
|
||||
}
|
||||
None => FirstBorrowUsePlaceClosure { place: borrow_place_desc, var_span },
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
borrow_spans.var_span_label(
|
||||
borrow_spans.var_subdiag(
|
||||
Some(&self.infcx.tcx.sess.parse_sess.span_diagnostic),
|
||||
&mut err,
|
||||
format!(
|
||||
"second borrow occurs due to use of {}{}",
|
||||
desc_place,
|
||||
borrow_spans.describe(),
|
||||
),
|
||||
gen_borrow_kind.describe_mutability(),
|
||||
Some(gen_borrow_kind),
|
||||
|kind, var_span| {
|
||||
use crate::session_diagnostics::CaptureVarCause::*;
|
||||
match kind {
|
||||
Some(_) => SecondBorrowUsePlaceGenerator { place: desc_place, var_span },
|
||||
None => SecondBorrowUsePlaceClosure { place: desc_place, var_span },
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@ -1229,23 +1268,161 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
fn suggest_binding_for_closure_capture_self(
|
||||
/// Suggest using closure argument instead of capture.
|
||||
///
|
||||
/// For example:
|
||||
/// ```ignore (illustrative)
|
||||
/// struct S;
|
||||
///
|
||||
/// impl S {
|
||||
/// fn call(&mut self, f: impl Fn(&mut Self)) { /* ... */ }
|
||||
/// fn x(&self) {}
|
||||
/// }
|
||||
///
|
||||
/// let mut v = S;
|
||||
/// v.call(|this: &mut S| v.x());
|
||||
/// // ^\ ^-- help: try using the closure argument: `this`
|
||||
/// // *-- error: cannot borrow `v` as mutable because it is also borrowed as immutable
|
||||
/// ```
|
||||
fn suggest_using_closure_argument_instead_of_capture(
|
||||
&self,
|
||||
err: &mut Diagnostic,
|
||||
borrowed_place: Place<'tcx>,
|
||||
issued_spans: &UseSpans<'tcx>,
|
||||
) {
|
||||
let &UseSpans::ClosureUse { capture_kind_span, .. } = issued_spans else { return };
|
||||
let tcx = self.infcx.tcx;
|
||||
let hir = tcx.hir();
|
||||
|
||||
// Get the type of the local that we are trying to borrow
|
||||
let local = borrowed_place.local;
|
||||
let local_ty = self.body.local_decls[local].ty;
|
||||
|
||||
// Get the body the error happens in
|
||||
let Some(body_id) = hir.get(self.mir_hir_id()).body_id() else { return };
|
||||
|
||||
let body_expr = hir.body(body_id).value;
|
||||
|
||||
struct ClosureFinder<'hir> {
|
||||
hir: rustc_middle::hir::map::Map<'hir>,
|
||||
borrow_span: Span,
|
||||
res: Option<(&'hir hir::Expr<'hir>, &'hir hir::Closure<'hir>)>,
|
||||
/// The path expression with the `borrow_span` span
|
||||
error_path: Option<(&'hir hir::Expr<'hir>, &'hir hir::QPath<'hir>)>,
|
||||
}
|
||||
impl<'hir> Visitor<'hir> for ClosureFinder<'hir> {
|
||||
type NestedFilter = OnlyBodies;
|
||||
|
||||
fn nested_visit_map(&mut self) -> Self::Map {
|
||||
self.hir
|
||||
}
|
||||
|
||||
fn visit_expr(&mut self, ex: &'hir hir::Expr<'hir>) {
|
||||
if let hir::ExprKind::Path(qpath) = &ex.kind
|
||||
&& ex.span == self.borrow_span
|
||||
{
|
||||
self.error_path = Some((ex, qpath));
|
||||
}
|
||||
|
||||
if let hir::ExprKind::Closure(closure) = ex.kind
|
||||
&& ex.span.contains(self.borrow_span)
|
||||
// To support cases like `|| { v.call(|this| v.get()) }`
|
||||
// FIXME: actually support such cases (need to figure out how to move from the capture place to original local)
|
||||
&& self.res.as_ref().map_or(true, |(prev_res, _)| prev_res.span.contains(ex.span))
|
||||
{
|
||||
self.res = Some((ex, closure));
|
||||
}
|
||||
|
||||
hir::intravisit::walk_expr(self, ex);
|
||||
}
|
||||
}
|
||||
|
||||
// Find the closure that most tightly wraps `capture_kind_span`
|
||||
let mut finder =
|
||||
ClosureFinder { hir, borrow_span: capture_kind_span, res: None, error_path: None };
|
||||
finder.visit_expr(body_expr);
|
||||
let Some((closure_expr, closure)) = finder.res else { return };
|
||||
|
||||
let typeck_results = tcx.typeck(self.mir_def_id());
|
||||
|
||||
// Check that the parent of the closure is a method call,
|
||||
// with receiver matching with local's type (modulo refs)
|
||||
let parent = hir.parent_id(closure_expr.hir_id);
|
||||
if let hir::Node::Expr(parent) = hir.get(parent) {
|
||||
if let hir::ExprKind::MethodCall(_, recv, ..) = parent.kind {
|
||||
let recv_ty = typeck_results.expr_ty(recv);
|
||||
|
||||
if recv_ty.peel_refs() != local_ty {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get closure's arguments
|
||||
let ty::Closure(_, substs) = typeck_results.expr_ty(closure_expr).kind() else { /* hir::Closure can be a generator too */ return };
|
||||
let sig = substs.as_closure().sig();
|
||||
let tupled_params =
|
||||
tcx.erase_late_bound_regions(sig.inputs().iter().next().unwrap().map_bound(|&b| b));
|
||||
let ty::Tuple(params) = tupled_params.kind() else { return };
|
||||
|
||||
// Find the first argument with a matching type, get its name
|
||||
let Some((_, this_name)) = params
|
||||
.iter()
|
||||
.zip(hir.body_param_names(closure.body))
|
||||
.find(|(param_ty, name)|{
|
||||
// FIXME: also support deref for stuff like `Rc` arguments
|
||||
param_ty.peel_refs() == local_ty && name != &Ident::empty()
|
||||
})
|
||||
else { return };
|
||||
|
||||
let spans;
|
||||
if let Some((_path_expr, qpath)) = finder.error_path
|
||||
&& let hir::QPath::Resolved(_, path) = qpath
|
||||
&& let hir::def::Res::Local(local_id) = path.res
|
||||
{
|
||||
// Find all references to the problematic variable in this closure body
|
||||
|
||||
struct VariableUseFinder {
|
||||
local_id: hir::HirId,
|
||||
spans: Vec<Span>,
|
||||
}
|
||||
impl<'hir> Visitor<'hir> for VariableUseFinder {
|
||||
fn visit_expr(&mut self, ex: &'hir hir::Expr<'hir>) {
|
||||
if let hir::ExprKind::Path(qpath) = &ex.kind
|
||||
&& let hir::QPath::Resolved(_, path) = qpath
|
||||
&& let hir::def::Res::Local(local_id) = path.res
|
||||
&& local_id == self.local_id
|
||||
{
|
||||
self.spans.push(ex.span);
|
||||
}
|
||||
|
||||
hir::intravisit::walk_expr(self, ex);
|
||||
}
|
||||
}
|
||||
|
||||
let mut finder = VariableUseFinder { local_id, spans: Vec::new() };
|
||||
finder.visit_expr(hir.body(closure.body).value);
|
||||
|
||||
spans = finder.spans;
|
||||
} else {
|
||||
spans = vec![capture_kind_span];
|
||||
}
|
||||
|
||||
err.multipart_suggestion(
|
||||
"try using the closure argument",
|
||||
iter::zip(spans, iter::repeat(this_name.to_string())).collect(),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
|
||||
fn suggest_binding_for_closure_capture_self(
|
||||
&self,
|
||||
err: &mut Diagnostic,
|
||||
issued_spans: &UseSpans<'tcx>,
|
||||
) {
|
||||
let UseSpans::ClosureUse { capture_kind_span, .. } = issued_spans else { return };
|
||||
let hir = self.infcx.tcx.hir();
|
||||
|
||||
// check whether the borrowed place is capturing `self` by mut reference
|
||||
let local = borrowed_place.local;
|
||||
let Some(_) = self
|
||||
.body
|
||||
.local_decls
|
||||
.get(local)
|
||||
.map(|l| mut_borrow_of_mutable_ref(l, self.local_names[local])) else { return };
|
||||
|
||||
struct ExpressionFinder<'hir> {
|
||||
capture_span: Span,
|
||||
closure_change_spans: Vec<Span>,
|
||||
@ -1731,9 +1908,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
err.span_label(borrow_span, "borrowed value does not live long enough");
|
||||
err.span_label(drop_span, format!("`{}` dropped here while still borrowed", name));
|
||||
|
||||
let within = if borrow_spans.for_generator() { " by generator" } else { "" };
|
||||
|
||||
borrow_spans.args_span_label(&mut err, format!("value captured here{}", within));
|
||||
borrow_spans.args_subdiag(&mut err, |args_span| {
|
||||
crate::session_diagnostics::CaptureArgLabel::Capture {
|
||||
is_within: borrow_spans.for_generator(),
|
||||
args_span,
|
||||
}
|
||||
});
|
||||
|
||||
explanation.add_explanation_to_diagnostic(
|
||||
self.infcx.tcx,
|
||||
@ -1947,9 +2127,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
None,
|
||||
);
|
||||
|
||||
let within = if borrow_spans.for_generator() { " by generator" } else { "" };
|
||||
|
||||
borrow_spans.args_span_label(&mut err, format!("value captured here{}", within));
|
||||
borrow_spans.args_subdiag(&mut err, |args_span| {
|
||||
crate::session_diagnostics::CaptureArgLabel::Capture {
|
||||
is_within: borrow_spans.for_generator(),
|
||||
args_span,
|
||||
}
|
||||
});
|
||||
|
||||
err
|
||||
}
|
||||
@ -2029,7 +2212,6 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
let tcx = self.infcx.tcx;
|
||||
|
||||
let return_ty = self.regioncx.universal_regions().unnormalized_output_ty;
|
||||
let return_ty = tcx.erase_regions(return_ty);
|
||||
|
||||
// to avoid panics
|
||||
if let Some(iter_trait) = tcx.get_diagnostic_item(sym::Iterator)
|
||||
@ -2382,11 +2564,14 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
section,
|
||||
"assign",
|
||||
);
|
||||
loan_spans.var_span_label(
|
||||
&mut err,
|
||||
format!("borrow occurs due to use{}", loan_spans.describe()),
|
||||
loan.kind.describe_mutability(),
|
||||
);
|
||||
|
||||
loan_spans.var_subdiag(None, &mut err, Some(loan.kind), |kind, var_span| {
|
||||
use crate::session_diagnostics::CaptureVarCause::*;
|
||||
match kind {
|
||||
Some(_) => BorrowUseInGenerator { var_span },
|
||||
None => BorrowUseInClosure { var_span },
|
||||
}
|
||||
});
|
||||
|
||||
self.buffer_error(err);
|
||||
|
||||
@ -2396,11 +2581,13 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
|
||||
let mut err = self.cannot_assign_to_borrowed(span, loan_span, &descr_place);
|
||||
|
||||
loan_spans.var_span_label(
|
||||
&mut err,
|
||||
format!("borrow occurs due to use{}", loan_spans.describe()),
|
||||
loan.kind.describe_mutability(),
|
||||
);
|
||||
loan_spans.var_subdiag(None, &mut err, Some(loan.kind), |kind, var_span| {
|
||||
use crate::session_diagnostics::CaptureVarCause::*;
|
||||
match kind {
|
||||
Some(_) => BorrowUseInGenerator { var_span },
|
||||
None => BorrowUseInClosure { var_span },
|
||||
}
|
||||
});
|
||||
|
||||
self.explain_why_borrow_contains_point(location, loan, None).add_explanation_to_diagnostic(
|
||||
self.infcx.tcx,
|
||||
@ -2424,7 +2611,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
Some((method_did, method_substs)),
|
||||
) = (
|
||||
&self.body[loan.reserve_location.block].terminator,
|
||||
rustc_const_eval::util::find_self_call(
|
||||
rustc_middle::util::find_self_call(
|
||||
tcx,
|
||||
self.body,
|
||||
loan.assigned_place.local,
|
||||
|
@ -3,7 +3,7 @@
|
||||
use rustc_errors::{Applicability, Diagnostic};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::intravisit::Visitor;
|
||||
use rustc_index::vec::IndexSlice;
|
||||
use rustc_index::IndexSlice;
|
||||
use rustc_infer::infer::NllRegionVariableOrigin;
|
||||
use rustc_middle::mir::{
|
||||
Body, CastKind, ConstraintCategory, FakeReadCause, Local, LocalInfo, Location, Operand, Place,
|
||||
|
@ -1,13 +1,16 @@
|
||||
//! Borrow checker diagnostics.
|
||||
|
||||
use crate::session_diagnostics::{
|
||||
CaptureArgLabel, CaptureReasonLabel, CaptureReasonNote, CaptureReasonSuggest, CaptureVarCause,
|
||||
CaptureVarKind, CaptureVarPathUseCause, OnClosureNote,
|
||||
};
|
||||
use itertools::Itertools;
|
||||
use rustc_const_eval::util::{call_kind, CallDesugaringKind};
|
||||
use rustc_errors::{Applicability, Diagnostic};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::{CtorKind, Namespace};
|
||||
use rustc_hir::GeneratorKind;
|
||||
use rustc_index::vec::IndexSlice;
|
||||
use rustc_infer::infer::{LateBoundRegionConversionTime, TyCtxtInferExt};
|
||||
use rustc_index::IndexSlice;
|
||||
use rustc_infer::infer::LateBoundRegionConversionTime;
|
||||
use rustc_middle::mir::tcx::PlaceTy;
|
||||
use rustc_middle::mir::{
|
||||
AggregateKind, Constant, FakeReadCause, Local, LocalInfo, LocalKind, Location, Operand, Place,
|
||||
@ -15,6 +18,7 @@ use rustc_middle::mir::{
|
||||
};
|
||||
use rustc_middle::ty::print::Print;
|
||||
use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
|
||||
use rustc_middle::util::{call_kind, CallDesugaringKind};
|
||||
use rustc_mir_dataflow::move_paths::{InitLocation, LookupResult};
|
||||
use rustc_span::def_id::LocalDefId;
|
||||
use rustc_span::{symbol::sym, Span, Symbol, DUMMY_SP};
|
||||
@ -45,7 +49,7 @@ pub(crate) use mutability_errors::AccessKind;
|
||||
pub(crate) use outlives_suggestion::OutlivesSuggestionBuilder;
|
||||
pub(crate) use region_errors::{ErrorConstraintInfo, RegionErrorKind, RegionErrors};
|
||||
pub(crate) use region_name::{RegionName, RegionNameSource};
|
||||
pub(crate) use rustc_const_eval::util::CallKind;
|
||||
pub(crate) use rustc_middle::util::CallKind;
|
||||
|
||||
pub(super) struct DescribePlaceOpt {
|
||||
pub including_downcast: bool,
|
||||
@ -117,13 +121,15 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
if let ty::Closure(did, _) = self.body.local_decls[closure].ty.kind() {
|
||||
let did = did.expect_local();
|
||||
if let Some((span, hir_place)) = self.infcx.tcx.closure_kind_origin(did) {
|
||||
diag.span_note(
|
||||
*span,
|
||||
&format!(
|
||||
"closure cannot be invoked more than once because it moves the \
|
||||
variable `{}` out of its environment",
|
||||
ty::place_to_string_for_capture(self.infcx.tcx, hir_place)
|
||||
diag.eager_subdiagnostic(
|
||||
&self.infcx.tcx.sess.parse_sess.span_diagnostic,
|
||||
OnClosureNote::InvokedTwice {
|
||||
place_name: &ty::place_to_string_for_capture(
|
||||
self.infcx.tcx,
|
||||
hir_place,
|
||||
),
|
||||
span: *span,
|
||||
},
|
||||
);
|
||||
return true;
|
||||
}
|
||||
@ -137,13 +143,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
if let ty::Closure(did, _) = self.body.local_decls[target].ty.kind() {
|
||||
let did = did.expect_local();
|
||||
if let Some((span, hir_place)) = self.infcx.tcx.closure_kind_origin(did) {
|
||||
diag.span_note(
|
||||
*span,
|
||||
&format!(
|
||||
"closure cannot be moved more than once as it is not `Copy` due to \
|
||||
moving the variable `{}` out of its environment",
|
||||
ty::place_to_string_for_capture(self.infcx.tcx, hir_place)
|
||||
),
|
||||
diag.eager_subdiagnostic(
|
||||
&self.infcx.tcx.sess.parse_sess.span_diagnostic,
|
||||
OnClosureNote::MovedTwice {
|
||||
place_name: &ty::place_to_string_for_capture(self.infcx.tcx, hir_place),
|
||||
span: *span,
|
||||
},
|
||||
);
|
||||
return true;
|
||||
}
|
||||
@ -380,25 +385,6 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Add a note that a type does not implement `Copy`
|
||||
pub(super) fn note_type_does_not_implement_copy(
|
||||
&self,
|
||||
err: &mut Diagnostic,
|
||||
place_desc: &str,
|
||||
ty: Ty<'tcx>,
|
||||
span: Option<Span>,
|
||||
move_prefix: &str,
|
||||
) {
|
||||
let message = format!(
|
||||
"{move_prefix}move occurs because {place_desc} has type `{ty}`, which does not implement the `Copy` trait",
|
||||
);
|
||||
if let Some(span) = span {
|
||||
err.span_label(span, message);
|
||||
} else {
|
||||
err.note(&message);
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn borrowed_content_source(
|
||||
&self,
|
||||
deref_base: PlaceRef<'tcx>,
|
||||
@ -582,9 +568,13 @@ impl UseSpans<'_> {
|
||||
}
|
||||
|
||||
/// Add a span label to the arguments of the closure, if it exists.
|
||||
pub(super) fn args_span_label(self, err: &mut Diagnostic, message: impl Into<String>) {
|
||||
pub(super) fn args_subdiag(
|
||||
self,
|
||||
err: &mut Diagnostic,
|
||||
f: impl FnOnce(Span) -> CaptureArgLabel,
|
||||
) {
|
||||
if let UseSpans::ClosureUse { args_span, .. } = self {
|
||||
err.span_label(args_span, message);
|
||||
err.subdiagnostic(f(args_span));
|
||||
}
|
||||
}
|
||||
|
||||
@ -595,8 +585,8 @@ impl UseSpans<'_> {
|
||||
err: &mut Diagnostic,
|
||||
action: crate::InitializationRequiringAction,
|
||||
) {
|
||||
use crate::session_diagnostics::CaptureVarPathUseCause::*;
|
||||
use crate::InitializationRequiringAction::*;
|
||||
use CaptureVarPathUseCause::*;
|
||||
if let UseSpans::ClosureUse { generator_kind, path_span, .. } = self {
|
||||
match generator_kind {
|
||||
Some(_) => {
|
||||
@ -619,34 +609,14 @@ impl UseSpans<'_> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Add a span label to the use of the captured variable, if it exists.
|
||||
pub(super) fn var_span_label(
|
||||
self,
|
||||
err: &mut Diagnostic,
|
||||
message: impl Into<String>,
|
||||
kind_desc: impl Into<String>,
|
||||
) {
|
||||
if let UseSpans::ClosureUse { capture_kind_span, path_span, .. } = self {
|
||||
if capture_kind_span == path_span {
|
||||
err.span_label(capture_kind_span, message);
|
||||
} else {
|
||||
let capture_kind_label =
|
||||
format!("capture is {} because of use here", kind_desc.into());
|
||||
let path_label = message;
|
||||
err.span_label(capture_kind_span, capture_kind_label);
|
||||
err.span_label(path_span, path_label);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Add a subdiagnostic to the use of the captured variable, if it exists.
|
||||
pub(super) fn var_subdiag(
|
||||
self,
|
||||
handler: Option<&rustc_errors::Handler>,
|
||||
err: &mut Diagnostic,
|
||||
kind: Option<rustc_middle::mir::BorrowKind>,
|
||||
f: impl Fn(Option<GeneratorKind>, Span) -> crate::session_diagnostics::CaptureVarCause,
|
||||
f: impl FnOnce(Option<GeneratorKind>, Span) -> CaptureVarCause,
|
||||
) {
|
||||
use crate::session_diagnostics::CaptureVarKind::*;
|
||||
if let UseSpans::ClosureUse { generator_kind, capture_kind_span, path_span, .. } = self {
|
||||
if capture_kind_span != path_span {
|
||||
err.subdiagnostic(match kind {
|
||||
@ -654,17 +624,21 @@ impl UseSpans<'_> {
|
||||
rustc_middle::mir::BorrowKind::Shared
|
||||
| rustc_middle::mir::BorrowKind::Shallow
|
||||
| rustc_middle::mir::BorrowKind::Unique => {
|
||||
Immute { kind_span: capture_kind_span }
|
||||
CaptureVarKind::Immut { kind_span: capture_kind_span }
|
||||
}
|
||||
|
||||
rustc_middle::mir::BorrowKind::Mut { .. } => {
|
||||
Mut { kind_span: capture_kind_span }
|
||||
CaptureVarKind::Mut { kind_span: capture_kind_span }
|
||||
}
|
||||
},
|
||||
None => Move { kind_span: capture_kind_span },
|
||||
None => CaptureVarKind::Move { kind_span: capture_kind_span },
|
||||
});
|
||||
};
|
||||
err.subdiagnostic(f(generator_kind, path_span));
|
||||
let diag = f(generator_kind, path_span);
|
||||
match handler {
|
||||
Some(hd) => err.eager_subdiagnostic(hd, diag),
|
||||
None => err.subdiagnostic(diag),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@ -684,20 +658,6 @@ impl UseSpans<'_> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Describe the span associated with a use of a place.
|
||||
pub(super) fn describe(&self) -> &str {
|
||||
match *self {
|
||||
UseSpans::ClosureUse { generator_kind, .. } => {
|
||||
if generator_kind.is_some() {
|
||||
" in generator"
|
||||
} else {
|
||||
" in closure"
|
||||
}
|
||||
}
|
||||
_ => "",
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn or_else<F>(self, if_other: F) -> Self
|
||||
where
|
||||
F: FnOnce() -> Self,
|
||||
@ -788,6 +748,15 @@ impl<'tcx> BorrowedContentSource<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
///helper struct for explain_captures()
|
||||
struct CapturedMessageOpt {
|
||||
is_partial_move: bool,
|
||||
is_loop_message: bool,
|
||||
is_move_msg: bool,
|
||||
is_loop_move: bool,
|
||||
maybe_reinitialized_locations_is_empty: bool,
|
||||
}
|
||||
|
||||
impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
/// Finds the spans associated to a move or copy of move_place at location.
|
||||
pub(super) fn move_spans(
|
||||
@ -874,7 +843,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
}) = &self.body[location.block].terminator
|
||||
{
|
||||
let Some((method_did, method_substs)) =
|
||||
rustc_const_eval::util::find_self_call(
|
||||
rustc_middle::util::find_self_call(
|
||||
self.infcx.tcx,
|
||||
&self.body,
|
||||
target_temp,
|
||||
@ -1027,12 +996,15 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
move_span: Span,
|
||||
move_spans: UseSpans<'tcx>,
|
||||
moved_place: Place<'tcx>,
|
||||
partially_str: &str,
|
||||
loop_message: &str,
|
||||
move_msg: &str,
|
||||
is_loop_move: bool,
|
||||
maybe_reinitialized_locations_is_empty: bool,
|
||||
msg_opt: CapturedMessageOpt,
|
||||
) {
|
||||
let CapturedMessageOpt {
|
||||
is_partial_move: is_partial,
|
||||
is_loop_message,
|
||||
is_move_msg,
|
||||
is_loop_move,
|
||||
maybe_reinitialized_locations_is_empty,
|
||||
} = msg_opt;
|
||||
if let UseSpans::FnSelfUse { var_span, fn_call_span, fn_span, kind } = move_spans {
|
||||
let place_name = self
|
||||
.describe_place(moved_place.as_ref())
|
||||
@ -1042,30 +1014,26 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
CallKind::FnCall { fn_trait_id, .. }
|
||||
if Some(fn_trait_id) == self.infcx.tcx.lang_items().fn_once_trait() =>
|
||||
{
|
||||
err.span_label(
|
||||
err.subdiagnostic(CaptureReasonLabel::Call {
|
||||
fn_call_span,
|
||||
&format!(
|
||||
"{place_name} {partially_str}moved due to this call{loop_message}",
|
||||
),
|
||||
);
|
||||
err.span_note(
|
||||
var_span,
|
||||
"this value implements `FnOnce`, which causes it to be moved when called",
|
||||
);
|
||||
place_name: &place_name,
|
||||
is_partial,
|
||||
is_loop_message,
|
||||
});
|
||||
err.subdiagnostic(CaptureReasonNote::FnOnceMoveInCall { var_span });
|
||||
}
|
||||
CallKind::Operator { self_arg, .. } => {
|
||||
let self_arg = self_arg.unwrap();
|
||||
err.span_label(
|
||||
err.subdiagnostic(CaptureReasonLabel::OperatorUse {
|
||||
fn_call_span,
|
||||
&format!(
|
||||
"{place_name} {partially_str}moved due to usage in operator{loop_message}",
|
||||
),
|
||||
);
|
||||
place_name: &place_name,
|
||||
is_partial,
|
||||
is_loop_message,
|
||||
});
|
||||
if self.fn_self_span_reported.insert(fn_span) {
|
||||
err.span_note(
|
||||
self_arg.span,
|
||||
"calling this operator moves the left-hand side",
|
||||
);
|
||||
err.subdiagnostic(CaptureReasonNote::LhsMoveByOperator {
|
||||
span: self_arg.span,
|
||||
});
|
||||
}
|
||||
}
|
||||
CallKind::Normal { self_arg, desugaring, method_did, method_substs } => {
|
||||
@ -1074,35 +1042,27 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
if let Some((CallDesugaringKind::ForLoopIntoIter, _)) = desugaring {
|
||||
let ty = moved_place.ty(self.body, tcx).ty;
|
||||
let suggest = match tcx.get_diagnostic_item(sym::IntoIterator) {
|
||||
Some(def_id) => {
|
||||
let infcx = self.infcx.tcx.infer_ctxt().build();
|
||||
type_known_to_meet_bound_modulo_regions(
|
||||
&infcx,
|
||||
Some(def_id) => type_known_to_meet_bound_modulo_regions(
|
||||
&self.infcx,
|
||||
self.param_env,
|
||||
tcx.mk_imm_ref(tcx.lifetimes.re_erased, tcx.erase_regions(ty)),
|
||||
tcx.mk_imm_ref(tcx.lifetimes.re_erased, ty),
|
||||
def_id,
|
||||
)
|
||||
}
|
||||
),
|
||||
_ => false,
|
||||
};
|
||||
if suggest {
|
||||
err.span_suggestion_verbose(
|
||||
move_span.shrink_to_lo(),
|
||||
&format!(
|
||||
"consider iterating over a slice of the `{ty}`'s content to \
|
||||
avoid moving into the `for` loop",
|
||||
),
|
||||
"&",
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
err.subdiagnostic(CaptureReasonSuggest::IterateSlice {
|
||||
ty,
|
||||
span: move_span.shrink_to_lo(),
|
||||
});
|
||||
}
|
||||
|
||||
err.span_label(
|
||||
err.subdiagnostic(CaptureReasonLabel::ImplicitCall {
|
||||
fn_call_span,
|
||||
&format!(
|
||||
"{place_name} {partially_str}moved due to this implicit call to `.into_iter()`{loop_message}",
|
||||
),
|
||||
);
|
||||
place_name: &place_name,
|
||||
is_partial,
|
||||
is_loop_message,
|
||||
});
|
||||
// If the moved place was a `&mut` ref, then we can
|
||||
// suggest to reborrow it where it was moved, so it
|
||||
// will still be valid by the time we get to the usage.
|
||||
@ -1125,34 +1085,30 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
err.span_label(
|
||||
err.subdiagnostic(CaptureReasonLabel::MethodCall {
|
||||
fn_call_span,
|
||||
&format!(
|
||||
"{place_name} {partially_str}moved due to this method call{loop_message}",
|
||||
),
|
||||
);
|
||||
|
||||
let infcx = tcx.infer_ctxt().build();
|
||||
place_name: &place_name,
|
||||
is_partial,
|
||||
is_loop_message,
|
||||
});
|
||||
// Erase and shadow everything that could be passed to the new infcx.
|
||||
let ty = tcx.erase_regions(moved_place.ty(self.body, tcx).ty);
|
||||
let method_substs = tcx.erase_regions(method_substs);
|
||||
let ty = moved_place.ty(self.body, tcx).ty;
|
||||
|
||||
if let ty::Adt(def, substs) = ty.kind()
|
||||
&& Some(def.did()) == tcx.lang_items().pin_type()
|
||||
&& let ty::Ref(_, _, hir::Mutability::Mut) = substs.type_at(0).kind()
|
||||
&& let self_ty = infcx.instantiate_binder_with_fresh_vars(
|
||||
&& let self_ty = self.infcx.instantiate_binder_with_fresh_vars(
|
||||
fn_call_span,
|
||||
LateBoundRegionConversionTime::FnCall,
|
||||
tcx.fn_sig(method_did).subst(tcx, method_substs).input(0),
|
||||
)
|
||||
&& infcx.can_eq(self.param_env, ty, self_ty)
|
||||
&& self.infcx.can_eq(self.param_env, ty, self_ty)
|
||||
{
|
||||
err.span_suggestion_verbose(
|
||||
fn_call_span.shrink_to_lo(),
|
||||
"consider reborrowing the `Pin` instead of moving it",
|
||||
"as_mut().".to_string(),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
err.eager_subdiagnostic(
|
||||
&self.infcx.tcx.sess.parse_sess.span_diagnostic,
|
||||
CaptureReasonSuggest::FreshReborrow {
|
||||
span: fn_call_span.shrink_to_lo(),
|
||||
});
|
||||
}
|
||||
if let Some(clone_trait) = tcx.lang_items().clone_trait()
|
||||
&& let trait_ref = tcx.mk_trait_ref(clone_trait, [ty])
|
||||
@ -1162,7 +1118,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
self.param_env,
|
||||
ty::Binder::dummy(trait_ref),
|
||||
)
|
||||
&& infcx.predicate_must_hold_modulo_regions(&o)
|
||||
&& self.infcx.predicate_must_hold_modulo_regions(&o)
|
||||
{
|
||||
err.span_suggestion_verbose(
|
||||
fn_call_span.shrink_to_lo(),
|
||||
@ -1177,10 +1133,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
// error messages.
|
||||
if span != DUMMY_SP && self.fn_self_span_reported.insert(self_arg.span) {
|
||||
let func = tcx.def_path_str(method_did);
|
||||
err.span_note(
|
||||
self_arg.span,
|
||||
&format!("`{func}` takes ownership of the receiver `self`, which moves {place_name}")
|
||||
);
|
||||
err.subdiagnostic(CaptureReasonNote::FuncTakeSelf {
|
||||
func,
|
||||
place_name,
|
||||
span: self_arg.span,
|
||||
});
|
||||
}
|
||||
let parent_did = tcx.parent(method_did);
|
||||
let parent_self_ty =
|
||||
@ -1194,30 +1151,28 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
matches!(tcx.get_diagnostic_name(def_id), Some(sym::Option | sym::Result))
|
||||
});
|
||||
if is_option_or_result && maybe_reinitialized_locations_is_empty {
|
||||
err.span_label(
|
||||
var_span,
|
||||
"help: consider calling `.as_ref()` or `.as_mut()` to borrow the type's contents",
|
||||
);
|
||||
err.subdiagnostic(CaptureReasonLabel::BorrowContent { var_span });
|
||||
}
|
||||
}
|
||||
// Other desugarings takes &self, which cannot cause a move
|
||||
_ => {}
|
||||
}
|
||||
} else {
|
||||
if move_span != span || !loop_message.is_empty() {
|
||||
err.span_label(
|
||||
if move_span != span || is_loop_message {
|
||||
err.subdiagnostic(CaptureReasonLabel::MovedHere {
|
||||
move_span,
|
||||
format!("value {partially_str}moved{move_msg} here{loop_message}"),
|
||||
);
|
||||
is_partial,
|
||||
is_move_msg,
|
||||
is_loop_message,
|
||||
});
|
||||
}
|
||||
// If the move error occurs due to a loop, don't show
|
||||
// another message for the same span
|
||||
if loop_message.is_empty() {
|
||||
move_spans.var_span_label(
|
||||
err,
|
||||
format!("variable {partially_str}moved due to use{}", move_spans.describe()),
|
||||
"moved",
|
||||
);
|
||||
if !is_loop_message {
|
||||
move_spans.var_subdiag(None, err, None, |kind, var_span| match kind {
|
||||
Some(_) => CaptureVarCause::PartialMoveUseInGenerator { var_span, is_partial },
|
||||
None => CaptureVarCause::PartialMoveUseInClosure { var_span, is_partial },
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ use rustc_mir_dataflow::move_paths::{
|
||||
};
|
||||
use rustc_span::{BytePos, Span};
|
||||
|
||||
use crate::diagnostics::CapturedMessageOpt;
|
||||
use crate::diagnostics::{DescribePlaceOpt, UseSpans};
|
||||
use crate::prefixes::PrefixSet;
|
||||
use crate::MirBorrowckCtxt;
|
||||
@ -397,10 +398,15 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
};
|
||||
let msg_opt = CapturedMessageOpt {
|
||||
is_partial_move: false,
|
||||
is_loop_message: false,
|
||||
is_move_msg: false,
|
||||
is_loop_move: false,
|
||||
maybe_reinitialized_locations_is_empty: true,
|
||||
};
|
||||
if let Some(use_spans) = use_spans {
|
||||
self.explain_captures(
|
||||
&mut err, span, span, use_spans, move_place, "", "", "", false, true,
|
||||
);
|
||||
self.explain_captures(&mut err, span, span, use_spans, move_place, msg_opt);
|
||||
}
|
||||
err
|
||||
}
|
||||
@ -416,13 +422,12 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||
None => "value".to_string(),
|
||||
};
|
||||
|
||||
self.note_type_does_not_implement_copy(
|
||||
err,
|
||||
&place_desc,
|
||||
place_ty,
|
||||
Some(span),
|
||||
"",
|
||||
);
|
||||
err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label {
|
||||
is_partial_move: false,
|
||||
ty: place_ty,
|
||||
place: &place_desc,
|
||||
span,
|
||||
});
|
||||
} else {
|
||||
binds_to.sort();
|
||||
binds_to.dedup();
|
||||
@ -444,9 +449,19 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||
Some(desc) => format!("`{desc}`"),
|
||||
None => "value".to_string(),
|
||||
};
|
||||
self.note_type_does_not_implement_copy(err, &place_desc, place_ty, Some(span), "");
|
||||
err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label {
|
||||
is_partial_move: false,
|
||||
ty: place_ty,
|
||||
place: &place_desc,
|
||||
span,
|
||||
});
|
||||
|
||||
use_spans.args_span_label(err, format!("{place_desc} is moved here"));
|
||||
use_spans.args_subdiag(err, |args_span| {
|
||||
crate::session_diagnostics::CaptureArgLabel::MoveOutPlace {
|
||||
place: place_desc,
|
||||
args_span,
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -534,13 +549,13 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||
}
|
||||
|
||||
if binds_to.len() == 1 {
|
||||
self.note_type_does_not_implement_copy(
|
||||
err,
|
||||
&format!("`{}`", self.local_names[*local].unwrap()),
|
||||
bind_to.ty,
|
||||
Some(binding_span),
|
||||
"",
|
||||
);
|
||||
let place_desc = &format!("`{}`", self.local_names[*local].unwrap());
|
||||
err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label {
|
||||
is_partial_move: false,
|
||||
ty: bind_to.ty,
|
||||
place: &place_desc,
|
||||
span: binding_span,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -15,8 +15,8 @@ use rustc_span::{sym, BytePos, Span};
|
||||
use rustc_target::abi::FieldIdx;
|
||||
|
||||
use crate::diagnostics::BorrowedContentSource;
|
||||
use crate::util::FindAssignments;
|
||||
use crate::MirBorrowckCtxt;
|
||||
use rustc_const_eval::util::collect_writes::FindAssignments;
|
||||
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||
pub(crate) enum AccessKind {
|
||||
@ -231,13 +231,17 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
if suggest {
|
||||
borrow_spans.var_span_label(
|
||||
borrow_spans.var_subdiag(
|
||||
None,
|
||||
&mut err,
|
||||
format!(
|
||||
"mutable borrow occurs due to use of {} in closure",
|
||||
self.describe_any_place(access_place.as_ref()),
|
||||
),
|
||||
"mutable",
|
||||
Some(mir::BorrowKind::Mut { allow_two_phase_borrow: false }),
|
||||
|_kind, var_span| {
|
||||
let place = self.describe_any_place(access_place.as_ref());
|
||||
crate::session_diagnostics::CaptureVarCause::MutableBorrowUsePlaceClosure {
|
||||
place,
|
||||
var_span,
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
borrow_span
|
||||
@ -1143,7 +1147,7 @@ pub fn mut_borrow_of_mutable_ref(local_decl: &LocalDecl<'_>, local_name: Option<
|
||||
// suggest removing the `&mut`.
|
||||
//
|
||||
// Deliberately fall into this case for all implicit self types,
|
||||
// so that we don't fall in to the next case with them.
|
||||
// so that we don't fall into the next case with them.
|
||||
kind == hir::ImplicitSelfKind::MutRef
|
||||
}
|
||||
_ if Some(kw::SelfLower) == local_name => {
|
||||
@ -1231,7 +1235,7 @@ fn suggest_ampmut<'tcx>(
|
||||
}
|
||||
}
|
||||
|
||||
let (suggestability, highlight_span) = match opt_ty_info {
|
||||
let (suggestibility, highlight_span) = match opt_ty_info {
|
||||
// if this is a variable binding with an explicit type,
|
||||
// try to highlight that for the suggestion.
|
||||
Some(ty_span) => (true, ty_span),
|
||||
@ -1252,7 +1256,7 @@ fn suggest_ampmut<'tcx>(
|
||||
let ty_mut = local_decl.ty.builtin_deref(true).unwrap();
|
||||
assert_eq!(ty_mut.mutbl, hir::Mutability::Not);
|
||||
(
|
||||
suggestability,
|
||||
suggestibility,
|
||||
highlight_span,
|
||||
if local_decl.ty.is_ref() {
|
||||
format!("&mut {}", ty_mut.ty)
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
use crate::region_infer::RegionInferenceContext;
|
||||
use crate::Upvar;
|
||||
use rustc_index::vec::{Idx, IndexSlice};
|
||||
use rustc_index::IndexSlice;
|
||||
use rustc_middle::mir::{Body, Local};
|
||||
use rustc_middle::ty::{RegionVid, TyCtxt};
|
||||
use rustc_span::source_map::Span;
|
||||
@ -117,7 +117,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
argument_index: usize,
|
||||
) -> (Option<Symbol>, Span) {
|
||||
let implicit_inputs = self.universal_regions().defining_ty.implicit_inputs();
|
||||
let argument_local = Local::new(implicit_inputs + argument_index + 1);
|
||||
let argument_local = Local::from_usize(implicit_inputs + argument_index + 1);
|
||||
debug!("get_argument_name_and_span_for_region: argument_local={argument_local:?}");
|
||||
|
||||
let argument_name = local_names[argument_local];
|
||||
|
@ -4,7 +4,6 @@ use crate::location::{LocationIndex, LocationTable};
|
||||
use crate::BorrowIndex;
|
||||
use polonius_engine::AllFacts as PoloniusFacts;
|
||||
use polonius_engine::Atom;
|
||||
use rustc_index::vec::Idx;
|
||||
use rustc_middle::mir::Local;
|
||||
use rustc_middle::ty::{RegionVid, TyCtxt};
|
||||
use rustc_mir_dataflow::move_paths::MovePathIndex;
|
||||
@ -93,13 +92,13 @@ impl AllFactsExt for AllFacts {
|
||||
|
||||
impl Atom for BorrowIndex {
|
||||
fn index(self) -> usize {
|
||||
Idx::index(self)
|
||||
self.as_usize()
|
||||
}
|
||||
}
|
||||
|
||||
impl Atom for LocationIndex {
|
||||
fn index(self) -> usize {
|
||||
Idx::index(self)
|
||||
self.as_usize()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -79,7 +79,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> {
|
||||
}
|
||||
// Only relevant for mir typeck
|
||||
StatementKind::AscribeUserType(..)
|
||||
// Only relevant for unsafeck
|
||||
// Only relevant for liveness and unsafeck
|
||||
| StatementKind::PlaceMention(..)
|
||||
// Doesn't have any language semantics
|
||||
| StatementKind::Coverage(..)
|
||||
|
@ -20,14 +20,14 @@ extern crate tracing;
|
||||
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
|
||||
use rustc_data_structures::graph::dominators::Dominators;
|
||||
use rustc_errors::{Diagnostic, DiagnosticBuilder, DiagnosticMessage, SubdiagnosticMessage};
|
||||
use rustc_fluent_macro::fluent_messages;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_index::bit_set::ChunkedBitSet;
|
||||
use rustc_index::vec::{IndexSlice, IndexVec};
|
||||
use rustc_index::{IndexSlice, IndexVec};
|
||||
use rustc_infer::infer::{
|
||||
DefiningAnchor, InferCtxt, NllRegionVariableOrigin, RegionVariableOrigin, TyCtxtInferExt,
|
||||
};
|
||||
use rustc_macros::fluent_messages;
|
||||
use rustc_middle::mir::{
|
||||
traversal, Body, ClearCrossCrate, Local, Location, Mutability, NonDivergingIntrinsic, Operand,
|
||||
Place, PlaceElem, PlaceRef, VarDebugInfoContents,
|
||||
@ -88,6 +88,7 @@ mod session_diagnostics;
|
||||
mod type_check;
|
||||
mod universal_regions;
|
||||
mod used_muts;
|
||||
mod util;
|
||||
|
||||
/// A public API provided for the Rust compiler consumers.
|
||||
pub mod consumers;
|
||||
@ -118,24 +119,12 @@ impl<'tcx> TyCtxtConsts<'tcx> {
|
||||
}
|
||||
|
||||
pub fn provide(providers: &mut Providers) {
|
||||
*providers = Providers {
|
||||
mir_borrowck: |tcx, did| {
|
||||
if let Some(def) = ty::WithOptConstParam::try_lookup(did, tcx) {
|
||||
tcx.mir_borrowck_const_arg(def)
|
||||
} else {
|
||||
mir_borrowck(tcx, ty::WithOptConstParam::unknown(did))
|
||||
}
|
||||
},
|
||||
mir_borrowck_const_arg: |tcx, (did, param_did)| {
|
||||
mir_borrowck(tcx, ty::WithOptConstParam { did, const_param_did: Some(param_did) })
|
||||
},
|
||||
..*providers
|
||||
};
|
||||
*providers = Providers { mir_borrowck, ..*providers };
|
||||
}
|
||||
|
||||
fn mir_borrowck(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> &BorrowCheckResult<'_> {
|
||||
fn mir_borrowck(tcx: TyCtxt<'_>, def: LocalDefId) -> &BorrowCheckResult<'_> {
|
||||
let (input_body, promoted) = tcx.mir_promoted(def);
|
||||
debug!("run query mir_borrowck: {}", tcx.def_path_str(def.did.to_def_id()));
|
||||
debug!("run query mir_borrowck: {}", tcx.def_path_str(def));
|
||||
|
||||
if input_body.borrow().should_skip() {
|
||||
debug!("Skipping borrowck because of injected body");
|
||||
@ -149,7 +138,7 @@ fn mir_borrowck(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> &Bor
|
||||
return tcx.arena.alloc(result);
|
||||
}
|
||||
|
||||
let hir_owner = tcx.hir().local_def_id_to_hir_id(def.did).owner;
|
||||
let hir_owner = tcx.hir().local_def_id_to_hir_id(def).owner;
|
||||
|
||||
let infcx =
|
||||
tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bind(hir_owner.def_id)).build();
|
||||
@ -166,19 +155,19 @@ fn mir_borrowck(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> &Bor
|
||||
/// If `return_body_with_facts` is true, then return the body with non-erased
|
||||
/// region ids on which the borrow checking was performed together with Polonius
|
||||
/// facts.
|
||||
#[instrument(skip(infcx, input_body, input_promoted), fields(id=?input_body.source.with_opt_param().as_local().unwrap()), level = "debug")]
|
||||
#[instrument(skip(infcx, input_body, input_promoted), fields(id=?input_body.source.def_id()), level = "debug")]
|
||||
fn do_mir_borrowck<'tcx>(
|
||||
infcx: &InferCtxt<'tcx>,
|
||||
input_body: &Body<'tcx>,
|
||||
input_promoted: &IndexSlice<Promoted, Body<'tcx>>,
|
||||
return_body_with_facts: bool,
|
||||
) -> (BorrowCheckResult<'tcx>, Option<Box<BodyWithBorrowckFacts<'tcx>>>) {
|
||||
let def = input_body.source.with_opt_param().as_local().unwrap();
|
||||
let def = input_body.source.def_id().expect_local();
|
||||
debug!(?def);
|
||||
|
||||
let tcx = infcx.tcx;
|
||||
let infcx = BorrowckInferCtxt::new(infcx);
|
||||
let param_env = tcx.param_env(def.did);
|
||||
let param_env = tcx.param_env(def);
|
||||
|
||||
let mut local_names = IndexVec::from_elem(None, &input_body.local_decls);
|
||||
for var_debug_info in &input_body.var_debug_info {
|
||||
@ -206,7 +195,7 @@ fn do_mir_borrowck<'tcx>(
|
||||
errors.set_tainted_by_errors(e);
|
||||
}
|
||||
let upvars: Vec<_> = tcx
|
||||
.closure_captures(def.did)
|
||||
.closure_captures(def)
|
||||
.iter()
|
||||
.map(|&captured_place| {
|
||||
let capture = captured_place.info.capture_kind;
|
||||
@ -248,7 +237,7 @@ fn do_mir_borrowck<'tcx>(
|
||||
.iterate_to_fixpoint()
|
||||
.into_results_cursor(&body);
|
||||
|
||||
let locals_are_invalidated_at_exit = tcx.hir().body_owner_kind(def.did).is_fn_or_closure();
|
||||
let locals_are_invalidated_at_exit = tcx.hir().body_owner_kind(def).is_fn_or_closure();
|
||||
let borrow_set =
|
||||
Rc::new(BorrowSet::build(tcx, body, locals_are_invalidated_at_exit, &mdpe.move_data));
|
||||
|
||||
@ -528,7 +517,7 @@ impl<'cx, 'tcx> BorrowckInferCtxt<'cx, 'tcx> {
|
||||
where
|
||||
F: Fn() -> RegionCtxt,
|
||||
{
|
||||
let next_region = self.infcx.next_nll_region_var(origin.clone());
|
||||
let next_region = self.infcx.next_nll_region_var(origin);
|
||||
let vid = next_region.as_var();
|
||||
|
||||
if cfg!(debug_assertions) && !self.inside_canonicalization_ctxt() {
|
||||
@ -676,7 +665,7 @@ impl<'cx, 'tcx> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtx
|
||||
}
|
||||
// Only relevant for mir typeck
|
||||
StatementKind::AscribeUserType(..)
|
||||
// Only relevant for unsafeck
|
||||
// Only relevant for liveness and unsafeck
|
||||
| StatementKind::PlaceMention(..)
|
||||
// Doesn't have any language semantics
|
||||
| StatementKind::Coverage(..)
|
||||
@ -946,6 +935,7 @@ enum InitializationRequiringAction {
|
||||
PartialAssignment,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct RootPlace<'tcx> {
|
||||
place_local: Local,
|
||||
place_projection: &'tcx [PlaceElem<'tcx>],
|
||||
@ -1859,11 +1849,6 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
// is allowed, remove this match arm.
|
||||
ty::Adt(..) | ty::Tuple(..) => {
|
||||
check_parent_of_field(self, location, place_base, span, flow_state);
|
||||
|
||||
// rust-lang/rust#21232, #54499, #54986: during period where we reject
|
||||
// partial initialization, do not complain about unnecessary `mut` on
|
||||
// an attempt to do a partial initialization.
|
||||
self.used_mut.insert(place.local);
|
||||
}
|
||||
|
||||
_ => {}
|
||||
@ -1951,6 +1936,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
(prefix, base, span),
|
||||
mpi,
|
||||
);
|
||||
|
||||
// rust-lang/rust#21232, #54499, #54986: during period where we reject
|
||||
// partial initialization, do not complain about unnecessary `mut` on
|
||||
// an attempt to do a partial initialization.
|
||||
this.used_mut.insert(base.local);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
#![deny(rustc::untranslatable_diagnostic)]
|
||||
#![deny(rustc::diagnostic_outside_of_impl)]
|
||||
use rustc_index::vec::{Idx, IndexVec};
|
||||
use rustc_index::IndexVec;
|
||||
use rustc_middle::mir::{BasicBlock, Body, Location};
|
||||
|
||||
/// Maps between a MIR Location, which identifies a particular
|
||||
@ -50,19 +50,19 @@ impl LocationTable {
|
||||
}
|
||||
|
||||
pub fn all_points(&self) -> impl Iterator<Item = LocationIndex> {
|
||||
(0..self.num_points).map(LocationIndex::new)
|
||||
(0..self.num_points).map(LocationIndex::from_usize)
|
||||
}
|
||||
|
||||
pub fn start_index(&self, location: Location) -> LocationIndex {
|
||||
let Location { block, statement_index } = location;
|
||||
let start_index = self.statements_before_block[block];
|
||||
LocationIndex::new(start_index + statement_index * 2)
|
||||
LocationIndex::from_usize(start_index + statement_index * 2)
|
||||
}
|
||||
|
||||
pub fn mid_index(&self, location: Location) -> LocationIndex {
|
||||
let Location { block, statement_index } = location;
|
||||
let start_index = self.statements_before_block[block];
|
||||
LocationIndex::new(start_index + statement_index * 2 + 1)
|
||||
LocationIndex::from_usize(start_index + statement_index * 2 + 1)
|
||||
}
|
||||
|
||||
pub fn to_location(&self, index: LocationIndex) -> RichLocation {
|
||||
|
@ -2,7 +2,7 @@
|
||||
#![deny(rustc::diagnostic_outside_of_impl)]
|
||||
use rustc_data_structures::captures::Captures;
|
||||
use rustc_data_structures::fx::FxIndexMap;
|
||||
use rustc_index::vec::{IndexSlice, IndexVec};
|
||||
use rustc_index::{IndexSlice, IndexVec};
|
||||
use rustc_middle::infer::MemberConstraint;
|
||||
use rustc_middle::ty::{self, Ty};
|
||||
use rustc_span::Span;
|
||||
@ -221,7 +221,7 @@ fn append_list(
|
||||
) {
|
||||
let mut p = target_list;
|
||||
loop {
|
||||
let mut r = &mut constraints[p];
|
||||
let r = &mut constraints[p];
|
||||
match r.next_constraint {
|
||||
Some(q) => p = q,
|
||||
None => {
|
||||
|
@ -4,11 +4,11 @@
|
||||
|
||||
use rustc_data_structures::fx::FxIndexMap;
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_index::vec::IndexSlice;
|
||||
use rustc_index::IndexSlice;
|
||||
use rustc_middle::mir::{create_dump_file, dump_enabled, dump_mir, PassWhere};
|
||||
use rustc_middle::mir::{
|
||||
BasicBlock, Body, ClosureOutlivesSubject, ClosureRegionRequirements, LocalKind, Location,
|
||||
Promoted,
|
||||
Body, ClosureOutlivesSubject, ClosureRegionRequirements, LocalKind, Location, Promoted,
|
||||
START_BLOCK,
|
||||
};
|
||||
use rustc_middle::ty::{self, OpaqueHiddenType, TyCtxt};
|
||||
use rustc_span::symbol::sym;
|
||||
@ -61,7 +61,7 @@ pub(crate) fn replace_regions_in_mir<'tcx>(
|
||||
body: &mut Body<'tcx>,
|
||||
promoted: &mut IndexSlice<Promoted, Body<'tcx>>,
|
||||
) -> UniversalRegions<'tcx> {
|
||||
let def = body.source.with_opt_param().as_local().unwrap();
|
||||
let def = body.source.def_id().expect_local();
|
||||
|
||||
debug!(?def);
|
||||
|
||||
@ -94,8 +94,8 @@ fn populate_polonius_move_facts(
|
||||
}
|
||||
}
|
||||
|
||||
let fn_entry_start = location_table
|
||||
.start_index(Location { block: BasicBlock::from_u32(0u32), statement_index: 0 });
|
||||
let fn_entry_start =
|
||||
location_table.start_index(Location { block: START_BLOCK, statement_index: 0 });
|
||||
|
||||
// initialized_at
|
||||
for init in move_data.inits.iter() {
|
||||
@ -235,7 +235,7 @@ pub(crate) fn compute_regions<'cx, 'tcx>(
|
||||
// Create the region inference context, taking ownership of the
|
||||
// region inference data that was contained in `infcx`, and the
|
||||
// base constraints generated by the type-check.
|
||||
let var_origins = infcx.take_region_var_origins();
|
||||
let var_origins = infcx.get_region_var_origins();
|
||||
let MirTypeckRegionConstraints {
|
||||
placeholder_indices,
|
||||
placeholder_index_to_region: _,
|
||||
|
@ -7,7 +7,7 @@ use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
|
||||
use rustc_data_structures::graph::scc::Sccs;
|
||||
use rustc_errors::Diagnostic;
|
||||
use rustc_hir::def_id::CRATE_DEF_ID;
|
||||
use rustc_index::vec::{IndexSlice, IndexVec};
|
||||
use rustc_index::{IndexSlice, IndexVec};
|
||||
use rustc_infer::infer::outlives::test_type_match;
|
||||
use rustc_infer::infer::region_constraints::{GenericKind, VarInfos, VerifyBound, VerifyIfEq};
|
||||
use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin, RegionVariableOrigin};
|
||||
|
@ -4,8 +4,8 @@ use rustc_data_structures::fx::FxIndexSet;
|
||||
use rustc_index::bit_set::SparseBitMatrix;
|
||||
use rustc_index::interval::IntervalSet;
|
||||
use rustc_index::interval::SparseIntervalMatrix;
|
||||
use rustc_index::vec::Idx;
|
||||
use rustc_index::vec::IndexVec;
|
||||
use rustc_index::Idx;
|
||||
use rustc_index::IndexVec;
|
||||
use rustc_middle::mir::{BasicBlock, Body, Location};
|
||||
use rustc_middle::ty::{self, RegionVid};
|
||||
use std::fmt::Debug;
|
||||
|
@ -1,7 +1,7 @@
|
||||
#![deny(rustc::untranslatable_diagnostic)]
|
||||
#![deny(rustc::diagnostic_outside_of_impl)]
|
||||
use crate::BorrowckInferCtxt;
|
||||
use rustc_index::vec::IndexSlice;
|
||||
use rustc_index::IndexSlice;
|
||||
use rustc_infer::infer::NllRegionVariableOrigin;
|
||||
use rustc_middle::mir::visit::{MutVisitor, TyContext};
|
||||
use rustc_middle::mir::Constant;
|
||||
|
@ -184,7 +184,7 @@ pub(crate) enum CaptureVarPathUseCause {
|
||||
#[derive(Subdiagnostic)]
|
||||
pub(crate) enum CaptureVarKind {
|
||||
#[label(borrowck_capture_immute)]
|
||||
Immute {
|
||||
Immut {
|
||||
#[primary_span]
|
||||
kind_span: Span,
|
||||
},
|
||||
@ -204,16 +204,80 @@ pub(crate) enum CaptureVarKind {
|
||||
pub(crate) enum CaptureVarCause {
|
||||
#[label(borrowck_var_borrow_by_use_place_in_generator)]
|
||||
BorrowUsePlaceGenerator {
|
||||
is_single_var: bool,
|
||||
place: String,
|
||||
#[primary_span]
|
||||
var_span: Span,
|
||||
},
|
||||
#[label(borrowck_var_borrow_by_use_place_in_closure)]
|
||||
BorrowUsePlaceClosure {
|
||||
is_single_var: bool,
|
||||
place: String,
|
||||
#[primary_span]
|
||||
var_span: Span,
|
||||
},
|
||||
#[label(borrowck_var_borrow_by_use_in_generator)]
|
||||
BorrowUseInGenerator {
|
||||
#[primary_span]
|
||||
var_span: Span,
|
||||
},
|
||||
#[label(borrowck_var_borrow_by_use_in_closure)]
|
||||
BorrowUseInClosure {
|
||||
#[primary_span]
|
||||
var_span: Span,
|
||||
},
|
||||
#[label(borrowck_var_move_by_use_in_generator)]
|
||||
MoveUseInGenerator {
|
||||
#[primary_span]
|
||||
var_span: Span,
|
||||
},
|
||||
#[label(borrowck_var_move_by_use_in_closure)]
|
||||
MoveUseInClosure {
|
||||
#[primary_span]
|
||||
var_span: Span,
|
||||
},
|
||||
#[label(borrowck_var_first_borrow_by_use_place_in_generator)]
|
||||
FirstBorrowUsePlaceGenerator {
|
||||
place: String,
|
||||
#[primary_span]
|
||||
var_span: Span,
|
||||
},
|
||||
#[label(borrowck_var_first_borrow_by_use_place_in_closure)]
|
||||
FirstBorrowUsePlaceClosure {
|
||||
place: String,
|
||||
#[primary_span]
|
||||
var_span: Span,
|
||||
},
|
||||
#[label(borrowck_var_second_borrow_by_use_place_in_generator)]
|
||||
SecondBorrowUsePlaceGenerator {
|
||||
place: String,
|
||||
#[primary_span]
|
||||
var_span: Span,
|
||||
},
|
||||
#[label(borrowck_var_second_borrow_by_use_place_in_closure)]
|
||||
SecondBorrowUsePlaceClosure {
|
||||
place: String,
|
||||
#[primary_span]
|
||||
var_span: Span,
|
||||
},
|
||||
#[label(borrowck_var_mutable_borrow_by_use_place_in_closure)]
|
||||
MutableBorrowUsePlaceClosure {
|
||||
place: String,
|
||||
#[primary_span]
|
||||
var_span: Span,
|
||||
},
|
||||
#[label(borrowck_partial_var_move_by_use_in_generator)]
|
||||
PartialMoveUseInGenerator {
|
||||
#[primary_span]
|
||||
var_span: Span,
|
||||
is_partial: bool,
|
||||
},
|
||||
#[label(borrowck_partial_var_move_by_use_in_closure)]
|
||||
PartialMoveUseInClosure {
|
||||
#[primary_span]
|
||||
var_span: Span,
|
||||
is_partial: bool,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
@ -239,3 +303,144 @@ pub(crate) struct NonGenericOpaqueTypeParam<'a, 'tcx> {
|
||||
#[label]
|
||||
pub param_span: Span,
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
pub(crate) enum CaptureReasonLabel<'a> {
|
||||
#[label(borrowck_moved_due_to_call)]
|
||||
Call {
|
||||
#[primary_span]
|
||||
fn_call_span: Span,
|
||||
place_name: &'a str,
|
||||
is_partial: bool,
|
||||
is_loop_message: bool,
|
||||
},
|
||||
#[label(borrowck_moved_due_to_usage_in_operator)]
|
||||
OperatorUse {
|
||||
#[primary_span]
|
||||
fn_call_span: Span,
|
||||
place_name: &'a str,
|
||||
is_partial: bool,
|
||||
is_loop_message: bool,
|
||||
},
|
||||
#[label(borrowck_moved_due_to_implicit_into_iter_call)]
|
||||
ImplicitCall {
|
||||
#[primary_span]
|
||||
fn_call_span: Span,
|
||||
place_name: &'a str,
|
||||
is_partial: bool,
|
||||
is_loop_message: bool,
|
||||
},
|
||||
#[label(borrowck_moved_due_to_method_call)]
|
||||
MethodCall {
|
||||
#[primary_span]
|
||||
fn_call_span: Span,
|
||||
place_name: &'a str,
|
||||
is_partial: bool,
|
||||
is_loop_message: bool,
|
||||
},
|
||||
#[label(borrowck_value_moved_here)]
|
||||
MovedHere {
|
||||
#[primary_span]
|
||||
move_span: Span,
|
||||
is_partial: bool,
|
||||
is_move_msg: bool,
|
||||
is_loop_message: bool,
|
||||
},
|
||||
#[label(borrowck_consider_borrow_type_contents)]
|
||||
BorrowContent {
|
||||
#[primary_span]
|
||||
var_span: Span,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
pub(crate) enum CaptureReasonNote {
|
||||
#[note(borrowck_moved_a_fn_once_in_call)]
|
||||
FnOnceMoveInCall {
|
||||
#[primary_span]
|
||||
var_span: Span,
|
||||
},
|
||||
#[note(borrowck_calling_operator_moves_lhs)]
|
||||
LhsMoveByOperator {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
},
|
||||
#[note(borrowck_func_take_self_moved_place)]
|
||||
FuncTakeSelf {
|
||||
func: String,
|
||||
place_name: String,
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
pub(crate) enum CaptureReasonSuggest<'tcx> {
|
||||
#[suggestion(
|
||||
borrowck_suggest_iterate_over_slice,
|
||||
applicability = "maybe-incorrect",
|
||||
code = "&",
|
||||
style = "verbose"
|
||||
)]
|
||||
IterateSlice {
|
||||
ty: Ty<'tcx>,
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
},
|
||||
#[suggestion(
|
||||
borrowck_suggest_create_freash_reborrow,
|
||||
applicability = "maybe-incorrect",
|
||||
code = "as_mut().",
|
||||
style = "verbose"
|
||||
)]
|
||||
FreshReborrow {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
pub(crate) enum CaptureArgLabel {
|
||||
#[label(borrowck_value_capture_here)]
|
||||
Capture {
|
||||
is_within: bool,
|
||||
#[primary_span]
|
||||
args_span: Span,
|
||||
},
|
||||
#[label(borrowck_move_out_place_here)]
|
||||
MoveOutPlace {
|
||||
place: String,
|
||||
#[primary_span]
|
||||
args_span: Span,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
pub(crate) enum OnClosureNote<'a> {
|
||||
#[note(borrowck_closure_invoked_twice)]
|
||||
InvokedTwice {
|
||||
place_name: &'a str,
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
},
|
||||
#[note(borrowck_closure_moved_twice)]
|
||||
MovedTwice {
|
||||
place_name: &'a str,
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
pub(crate) enum TypeNoCopy<'a, 'tcx> {
|
||||
#[label(borrowck_ty_no_impl_copy)]
|
||||
Label {
|
||||
is_partial_move: bool,
|
||||
ty: Ty<'tcx>,
|
||||
place: &'a str,
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
},
|
||||
#[note(borrowck_ty_no_impl_copy)]
|
||||
Note { is_partial_move: bool, ty: Ty<'tcx>, place: &'a str },
|
||||
}
|
||||
|
@ -7,7 +7,6 @@
|
||||
//! `RETURN_PLACE` the MIR arguments) are always fully normalized (and
|
||||
//! contain revealed `impl Trait` values).
|
||||
|
||||
use rustc_index::vec::Idx;
|
||||
use rustc_infer::infer::LateBoundRegionConversionTime;
|
||||
use rustc_middle::mir::*;
|
||||
use rustc_middle::ty::{self, Ty};
|
||||
@ -83,7 +82,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||
}
|
||||
|
||||
// In MIR, argument N is stored in local N+1.
|
||||
let local = Local::new(argument_index + 1);
|
||||
let local = Local::from_usize(argument_index + 1);
|
||||
|
||||
let mir_input_ty = body.local_decls[local].ty;
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
use rustc_data_structures::vec_linked_list as vll;
|
||||
use rustc_index::vec::IndexVec;
|
||||
use rustc_index::IndexVec;
|
||||
use rustc_middle::mir::visit::{PlaceContext, Visitor};
|
||||
use rustc_middle::mir::{Body, Local, Location};
|
||||
|
||||
|
@ -14,7 +14,7 @@ use rustc_hir as hir;
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_hir::lang_items::LangItem;
|
||||
use rustc_index::vec::{IndexSlice, IndexVec};
|
||||
use rustc_index::{IndexSlice, IndexVec};
|
||||
use rustc_infer::infer::canonical::QueryRegionConstraints;
|
||||
use rustc_infer::infer::outlives::env::RegionBoundPairs;
|
||||
use rustc_infer::infer::region_constraints::RegionConstraintData;
|
||||
@ -394,7 +394,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
|
||||
self.cx.ascribe_user_type(
|
||||
constant.literal.ty(),
|
||||
UserType::TypeOf(
|
||||
uv.def.did,
|
||||
uv.def,
|
||||
UserSubsts { substs: uv.substs, user_self_ty: None },
|
||||
),
|
||||
locations.span(&self.cx.body),
|
||||
@ -1766,7 +1766,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||
if let Some(uv) = maybe_uneval {
|
||||
if uv.promoted.is_none() {
|
||||
let tcx = self.tcx();
|
||||
let def_id = uv.def.def_id_for_type_of();
|
||||
let def_id = uv.def;
|
||||
if tcx.def_kind(def_id) == DefKind::InlineConst {
|
||||
let def_id = def_id.expect_local();
|
||||
let predicates =
|
||||
@ -2306,7 +2306,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||
Rvalue::AddressOf(..)
|
||||
| Rvalue::ThreadLocalRef(..)
|
||||
| Rvalue::Len(..)
|
||||
| Rvalue::Discriminant(..) => {}
|
||||
| Rvalue::Discriminant(..)
|
||||
| Rvalue::NullaryOp(NullOp::OffsetOf(..), _) => {}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -19,7 +19,7 @@ use rustc_hir as hir;
|
||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||
use rustc_hir::lang_items::LangItem;
|
||||
use rustc_hir::BodyOwnerKind;
|
||||
use rustc_index::vec::{Idx, IndexVec};
|
||||
use rustc_index::IndexVec;
|
||||
use rustc_infer::infer::NllRegionVariableOrigin;
|
||||
use rustc_middle::ty::fold::TypeFoldable;
|
||||
use rustc_middle::ty::{self, InlineConstSubsts, InlineConstSubstsParts, RegionVid, Ty, TyCtxt};
|
||||
@ -226,7 +226,7 @@ impl<'tcx> UniversalRegions<'tcx> {
|
||||
/// known between those regions.
|
||||
pub fn new(
|
||||
infcx: &BorrowckInferCtxt<'_, 'tcx>,
|
||||
mir_def: ty::WithOptConstParam<LocalDefId>,
|
||||
mir_def: LocalDefId,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
) -> Self {
|
||||
UniversalRegionsBuilder { infcx, mir_def, param_env }.build()
|
||||
@ -289,7 +289,7 @@ impl<'tcx> UniversalRegions<'tcx> {
|
||||
/// Returns an iterator over all the RegionVids corresponding to
|
||||
/// universally quantified free regions.
|
||||
pub fn universal_regions(&self) -> impl Iterator<Item = RegionVid> {
|
||||
(FIRST_GLOBAL_INDEX..self.num_universals).map(RegionVid::new)
|
||||
(FIRST_GLOBAL_INDEX..self.num_universals).map(RegionVid::from_usize)
|
||||
}
|
||||
|
||||
/// Returns `true` if `r` is classified as an local region.
|
||||
@ -388,7 +388,7 @@ impl<'tcx> UniversalRegions<'tcx> {
|
||||
|
||||
struct UniversalRegionsBuilder<'cx, 'tcx> {
|
||||
infcx: &'cx BorrowckInferCtxt<'cx, 'tcx>,
|
||||
mir_def: ty::WithOptConstParam<LocalDefId>,
|
||||
mir_def: LocalDefId,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
}
|
||||
|
||||
@ -417,12 +417,12 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
|
||||
let mut indices = self.compute_indices(fr_static, defining_ty);
|
||||
debug!("build: indices={:?}", indices);
|
||||
|
||||
let typeck_root_def_id = self.infcx.tcx.typeck_root_def_id(self.mir_def.did.to_def_id());
|
||||
let typeck_root_def_id = self.infcx.tcx.typeck_root_def_id(self.mir_def.to_def_id());
|
||||
|
||||
// If this is a 'root' body (not a closure/generator/inline const), then
|
||||
// there are no extern regions, so the local regions start at the same
|
||||
// position as the (empty) sub-list of extern regions
|
||||
let first_local_index = if self.mir_def.did.to_def_id() == typeck_root_def_id {
|
||||
let first_local_index = if self.mir_def.to_def_id() == typeck_root_def_id {
|
||||
first_extern_index
|
||||
} else {
|
||||
// If this is a closure, generator, or inline-const, then the late-bound regions from the enclosing
|
||||
@ -433,7 +433,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
|
||||
// }
|
||||
for_each_late_bound_region_in_recursive_scope(
|
||||
self.infcx.tcx,
|
||||
self.infcx.tcx.local_parent(self.mir_def.did),
|
||||
self.infcx.tcx.local_parent(self.mir_def),
|
||||
|r| {
|
||||
debug!(?r);
|
||||
if !indices.indices.contains_key(&r) {
|
||||
@ -462,13 +462,13 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
|
||||
|
||||
let inputs_and_output = self.infcx.replace_bound_regions_with_nll_infer_vars(
|
||||
FR,
|
||||
self.mir_def.did,
|
||||
self.mir_def,
|
||||
bound_inputs_and_output,
|
||||
&mut indices,
|
||||
);
|
||||
// Converse of above, if this is a function/closure then the late-bound regions declared on its
|
||||
// signature are local.
|
||||
for_each_late_bound_region_in_item(self.infcx.tcx, self.mir_def.did, |r| {
|
||||
for_each_late_bound_region_in_item(self.infcx.tcx, self.mir_def, |r| {
|
||||
debug!(?r);
|
||||
if !indices.indices.contains_key(&r) {
|
||||
let region_vid = {
|
||||
@ -492,7 +492,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
|
||||
if self.infcx.tcx.fn_sig(def_id).skip_binder().c_variadic() {
|
||||
let va_list_did = self.infcx.tcx.require_lang_item(
|
||||
LangItem::VaList,
|
||||
Some(self.infcx.tcx.def_span(self.mir_def.did)),
|
||||
Some(self.infcx.tcx.def_span(self.mir_def)),
|
||||
);
|
||||
|
||||
let reg_vid = self
|
||||
@ -544,11 +544,11 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
|
||||
/// see `DefiningTy` for details.
|
||||
fn defining_ty(&self) -> DefiningTy<'tcx> {
|
||||
let tcx = self.infcx.tcx;
|
||||
let typeck_root_def_id = tcx.typeck_root_def_id(self.mir_def.did.to_def_id());
|
||||
let typeck_root_def_id = tcx.typeck_root_def_id(self.mir_def.to_def_id());
|
||||
|
||||
match tcx.hir().body_owner_kind(self.mir_def.did) {
|
||||
match tcx.hir().body_owner_kind(self.mir_def) {
|
||||
BodyOwnerKind::Closure | BodyOwnerKind::Fn => {
|
||||
let defining_ty = tcx.type_of(self.mir_def.def_id_for_type_of()).subst_identity();
|
||||
let defining_ty = tcx.type_of(self.mir_def).subst_identity();
|
||||
|
||||
debug!("defining_ty (pre-replacement): {:?}", defining_ty);
|
||||
|
||||
@ -562,9 +562,9 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
|
||||
}
|
||||
ty::FnDef(def_id, substs) => DefiningTy::FnDef(def_id, substs),
|
||||
_ => span_bug!(
|
||||
tcx.def_span(self.mir_def.did),
|
||||
tcx.def_span(self.mir_def),
|
||||
"expected defining type for `{:?}`: `{:?}`",
|
||||
self.mir_def.did,
|
||||
self.mir_def,
|
||||
defining_ty
|
||||
),
|
||||
}
|
||||
@ -572,10 +572,10 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
|
||||
|
||||
BodyOwnerKind::Const | BodyOwnerKind::Static(..) => {
|
||||
let identity_substs = InternalSubsts::identity_for_item(tcx, typeck_root_def_id);
|
||||
if self.mir_def.did.to_def_id() == typeck_root_def_id {
|
||||
if self.mir_def.to_def_id() == typeck_root_def_id {
|
||||
let substs =
|
||||
self.infcx.replace_free_regions_with_nll_infer_vars(FR, identity_substs);
|
||||
DefiningTy::Const(self.mir_def.did.to_def_id(), substs)
|
||||
DefiningTy::Const(self.mir_def.to_def_id(), substs)
|
||||
} else {
|
||||
// FIXME this line creates a dependency between borrowck and typeck.
|
||||
//
|
||||
@ -587,15 +587,15 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
|
||||
// below), so that `type_of(inline_const_def_id).substs(substs)` uses the
|
||||
// proper type with NLL infer vars.
|
||||
let ty = tcx
|
||||
.typeck(self.mir_def.did)
|
||||
.node_type(tcx.local_def_id_to_hir_id(self.mir_def.did));
|
||||
.typeck(self.mir_def)
|
||||
.node_type(tcx.local_def_id_to_hir_id(self.mir_def));
|
||||
let substs = InlineConstSubsts::new(
|
||||
tcx,
|
||||
InlineConstSubstsParts { parent_substs: identity_substs, ty },
|
||||
)
|
||||
.substs;
|
||||
let substs = self.infcx.replace_free_regions_with_nll_infer_vars(FR, substs);
|
||||
DefiningTy::InlineConst(self.mir_def.did.to_def_id(), substs)
|
||||
DefiningTy::InlineConst(self.mir_def.to_def_id(), substs)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -611,7 +611,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
|
||||
defining_ty: DefiningTy<'tcx>,
|
||||
) -> UniversalRegionIndices<'tcx> {
|
||||
let tcx = self.infcx.tcx;
|
||||
let typeck_root_def_id = tcx.typeck_root_def_id(self.mir_def.did.to_def_id());
|
||||
let typeck_root_def_id = tcx.typeck_root_def_id(self.mir_def.to_def_id());
|
||||
let identity_substs = InternalSubsts::identity_for_item(tcx, typeck_root_def_id);
|
||||
let fr_substs = match defining_ty {
|
||||
DefiningTy::Closure(_, substs)
|
||||
@ -647,7 +647,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
|
||||
let tcx = self.infcx.tcx;
|
||||
match defining_ty {
|
||||
DefiningTy::Closure(def_id, substs) => {
|
||||
assert_eq!(self.mir_def.did.to_def_id(), def_id);
|
||||
assert_eq!(self.mir_def.to_def_id(), def_id);
|
||||
let closure_sig = substs.as_closure().sig();
|
||||
let inputs_and_output = closure_sig.inputs_and_output();
|
||||
let bound_vars = tcx.mk_bound_variable_kinds_from_iter(
|
||||
@ -682,7 +682,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
|
||||
}
|
||||
|
||||
DefiningTy::Generator(def_id, substs, movability) => {
|
||||
assert_eq!(self.mir_def.did.to_def_id(), def_id);
|
||||
assert_eq!(self.mir_def.to_def_id(), def_id);
|
||||
let resume_ty = substs.as_generator().resume_ty();
|
||||
let output = substs.as_generator().return_ty();
|
||||
let generator_ty = tcx.mk_generator(def_id, substs, movability);
|
||||
@ -700,14 +700,14 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
|
||||
DefiningTy::Const(def_id, _) => {
|
||||
// For a constant body, there are no inputs, and one
|
||||
// "output" (the type of the constant).
|
||||
assert_eq!(self.mir_def.did.to_def_id(), def_id);
|
||||
let ty = tcx.type_of(self.mir_def.def_id_for_type_of()).subst_identity();
|
||||
assert_eq!(self.mir_def.to_def_id(), def_id);
|
||||
let ty = tcx.type_of(self.mir_def).subst_identity();
|
||||
let ty = indices.fold_to_region_vids(tcx, ty);
|
||||
ty::Binder::dummy(tcx.mk_type_list(&[ty]))
|
||||
}
|
||||
|
||||
DefiningTy::InlineConst(def_id, substs) => {
|
||||
assert_eq!(self.mir_def.did.to_def_id(), def_id);
|
||||
assert_eq!(self.mir_def.to_def_id(), def_id);
|
||||
let ty = substs.as_inline_const().ty();
|
||||
ty::Binder::dummy(tcx.mk_type_list(&[ty]))
|
||||
}
|
||||
|
3
compiler/rustc_borrowck/src/util/mod.rs
Normal file
3
compiler/rustc_borrowck/src/util/mod.rs
Normal file
@ -0,0 +1,3 @@
|
||||
mod collect_writes;
|
||||
|
||||
pub use collect_writes::FindAssignments;
|
@ -17,6 +17,7 @@ rustc_feature = { path = "../rustc_feature" }
|
||||
rustc_lexer = { path = "../rustc_lexer" }
|
||||
rustc_lint_defs = { path = "../rustc_lint_defs" }
|
||||
rustc_macros = { path = "../rustc_macros" }
|
||||
rustc_fluent_macro = { path = "../rustc_fluent_macro" }
|
||||
rustc_parse_format = { path = "../rustc_parse_format" }
|
||||
rustc_parse = { path = "../rustc_parse" }
|
||||
rustc_session = { path = "../rustc_session" }
|
||||
|
@ -149,3 +149,25 @@ builtin_macros_format_pos_mismatch = {$n} positional {$n ->
|
||||
[one] argument
|
||||
*[more] arguments
|
||||
} in format string, but {$desc}
|
||||
|
||||
builtin_macros_offset_of_expected_field = expected field
|
||||
|
||||
builtin_macros_offset_of_expected_two_args = expected 2 arguments
|
||||
|
||||
builtin_macros_test_case_non_item = `#[test_case]` attribute is only allowed on items
|
||||
|
||||
builtin_macros_test_bad_fn = {$kind} functions cannot be used for tests
|
||||
.label = `{$kind}` because of this
|
||||
|
||||
builtin_macros_asm_explicit_register_name = explicit register arguments cannot have names
|
||||
|
||||
builtin_macros_asm_mutually_exclusive = the `{$opt1}` and `{$opt2}` options are mutually exclusive
|
||||
|
||||
builtin_macros_asm_pure_combine = the `pure` option must be combined with either `nomem` or `readonly`
|
||||
|
||||
builtin_macros_asm_pure_no_output = asm with the `pure` option must have at least one output
|
||||
|
||||
builtin_macros_asm_modifier_invalid = asm template modifier must be a single character
|
||||
|
||||
builtin_macros_test_runner_invalid = `test_runner` argument must be a path
|
||||
builtin_macros_test_runner_nargs = `#![test_runner(..)]` accepts exactly 1 argument
|
||||
|
@ -15,6 +15,8 @@ use rustc_span::{InnerSpan, Span};
|
||||
use rustc_target::asm::InlineAsmArch;
|
||||
use smallvec::smallvec;
|
||||
|
||||
use crate::errors;
|
||||
|
||||
pub struct AsmArgs {
|
||||
pub templates: Vec<P<ast::Expr>>,
|
||||
pub operands: Vec<(ast::InlineAsmOperand, Span)>,
|
||||
@ -205,7 +207,7 @@ pub fn parse_asm_args<'a>(
|
||||
// of the argument available.
|
||||
if explicit_reg {
|
||||
if name.is_some() {
|
||||
diag.struct_span_err(span, "explicit register arguments cannot have names").emit();
|
||||
diag.emit_err(errors::AsmExplicitRegisterName { span });
|
||||
}
|
||||
args.reg_args.insert(slot);
|
||||
} else if let Some(name) = name {
|
||||
@ -240,25 +242,19 @@ pub fn parse_asm_args<'a>(
|
||||
&& args.options.contains(ast::InlineAsmOptions::READONLY)
|
||||
{
|
||||
let spans = args.options_spans.clone();
|
||||
diag.struct_span_err(spans, "the `nomem` and `readonly` options are mutually exclusive")
|
||||
.emit();
|
||||
diag.emit_err(errors::AsmMutuallyExclusive { spans, opt1: "nomem", opt2: "readonly" });
|
||||
}
|
||||
if args.options.contains(ast::InlineAsmOptions::PURE)
|
||||
&& args.options.contains(ast::InlineAsmOptions::NORETURN)
|
||||
{
|
||||
let spans = args.options_spans.clone();
|
||||
diag.struct_span_err(spans, "the `pure` and `noreturn` options are mutually exclusive")
|
||||
.emit();
|
||||
diag.emit_err(errors::AsmMutuallyExclusive { spans, opt1: "pure", opt2: "noreturn" });
|
||||
}
|
||||
if args.options.contains(ast::InlineAsmOptions::PURE)
|
||||
&& !args.options.intersects(ast::InlineAsmOptions::NOMEM | ast::InlineAsmOptions::READONLY)
|
||||
{
|
||||
let spans = args.options_spans.clone();
|
||||
diag.struct_span_err(
|
||||
spans,
|
||||
"the `pure` option must be combined with either `nomem` or `readonly`",
|
||||
)
|
||||
.emit();
|
||||
diag.emit_err(errors::AsmPureCombine { spans });
|
||||
}
|
||||
|
||||
let mut have_real_output = false;
|
||||
@ -285,11 +281,7 @@ pub fn parse_asm_args<'a>(
|
||||
}
|
||||
}
|
||||
if args.options.contains(ast::InlineAsmOptions::PURE) && !have_real_output {
|
||||
diag.struct_span_err(
|
||||
args.options_spans.clone(),
|
||||
"asm with the `pure` option must have at least one output",
|
||||
)
|
||||
.emit();
|
||||
diag.emit_err(errors::AsmPureNoOutput { spans: args.options_spans.clone() });
|
||||
}
|
||||
if args.options.contains(ast::InlineAsmOptions::NORETURN) && !outputs_sp.is_empty() {
|
||||
let err = diag
|
||||
@ -705,11 +697,7 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, args: AsmArgs) -> Option<ast::Inl
|
||||
.ty_span
|
||||
.map(|sp| template_sp.from_inner(InnerSpan::new(sp.start, sp.end)))
|
||||
.unwrap_or(template_sp);
|
||||
ecx.struct_span_err(
|
||||
span,
|
||||
"asm template modifier must be a single character",
|
||||
)
|
||||
.emit();
|
||||
ecx.emit_err(errors::AsmModifierInvalid { span });
|
||||
modifier = None;
|
||||
}
|
||||
|
||||
|
@ -301,6 +301,7 @@ impl<'cx, 'a> Context<'cx, 'a> {
|
||||
| ExprKind::If(_, _, _)
|
||||
| ExprKind::IncludedBytes(..)
|
||||
| ExprKind::InlineAsm(_)
|
||||
| ExprKind::OffsetOf(_, _)
|
||||
| ExprKind::Let(_, _, _)
|
||||
| ExprKind::Lit(_)
|
||||
| ExprKind::Loop(_, _, _)
|
||||
|
@ -551,3 +551,71 @@ pub(crate) struct FormatPositionalMismatch {
|
||||
#[subdiagnostic]
|
||||
pub(crate) highlight: SingleLabelManySpans,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(builtin_macros_test_case_non_item)]
|
||||
pub(crate) struct TestCaseNonItem {
|
||||
#[primary_span]
|
||||
pub(crate) span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(builtin_macros_test_bad_fn)]
|
||||
pub(crate) struct TestBadFn {
|
||||
#[primary_span]
|
||||
pub(crate) span: Span,
|
||||
#[label]
|
||||
pub(crate) cause: Span,
|
||||
pub(crate) kind: &'static str,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(builtin_macros_asm_explicit_register_name)]
|
||||
pub(crate) struct AsmExplicitRegisterName {
|
||||
#[primary_span]
|
||||
pub(crate) span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(builtin_macros_asm_mutually_exclusive)]
|
||||
pub(crate) struct AsmMutuallyExclusive {
|
||||
#[primary_span]
|
||||
pub(crate) spans: Vec<Span>,
|
||||
pub(crate) opt1: &'static str,
|
||||
pub(crate) opt2: &'static str,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(builtin_macros_asm_pure_combine)]
|
||||
pub(crate) struct AsmPureCombine {
|
||||
#[primary_span]
|
||||
pub(crate) spans: Vec<Span>,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(builtin_macros_asm_pure_no_output)]
|
||||
pub(crate) struct AsmPureNoOutput {
|
||||
#[primary_span]
|
||||
pub(crate) spans: Vec<Span>,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(builtin_macros_asm_modifier_invalid)]
|
||||
pub(crate) struct AsmModifierInvalid {
|
||||
#[primary_span]
|
||||
pub(crate) span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(builtin_macros_test_runner_invalid)]
|
||||
pub(crate) struct TestRunnerInvalid {
|
||||
#[primary_span]
|
||||
pub(crate) span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(builtin_macros_test_runner_nargs)]
|
||||
pub(crate) struct TestRunnerNargs {
|
||||
#[primary_span]
|
||||
pub(crate) span: Span,
|
||||
}
|
||||
|
@ -141,13 +141,7 @@ fn parse_args<'a>(ecx: &mut ExtCtxt<'a>, sp: Span, tts: TokenStream) -> PResult<
|
||||
args: args
|
||||
.named_args()
|
||||
.iter()
|
||||
.filter_map(|a| {
|
||||
if let Some(ident) = a.kind.ident() {
|
||||
Some((a, ident))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.filter_map(|a| a.kind.ident().map(|ident| (a, ident)))
|
||||
.map(|(arg, n)| n.span.to(arg.expr.span))
|
||||
.collect(),
|
||||
});
|
||||
|
@ -24,7 +24,7 @@ use crate::deriving::*;
|
||||
use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
|
||||
use rustc_expand::base::{MacroExpanderFn, ResolverExpand, SyntaxExtensionKind};
|
||||
use rustc_expand::proc_macro::BangProcMacro;
|
||||
use rustc_macros::fluent_messages;
|
||||
use rustc_fluent_macro::fluent_messages;
|
||||
use rustc_span::symbol::sym;
|
||||
|
||||
mod alloc_error_handler;
|
||||
@ -45,6 +45,7 @@ mod format;
|
||||
mod format_foreign;
|
||||
mod global_allocator;
|
||||
mod log_syntax;
|
||||
mod offset_of;
|
||||
mod source_util;
|
||||
mod test;
|
||||
mod trace_macros;
|
||||
@ -92,6 +93,7 @@ pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) {
|
||||
line: source_util::expand_line,
|
||||
log_syntax: log_syntax::expand_log_syntax,
|
||||
module_path: source_util::expand_mod,
|
||||
offset_of: offset_of::expand_offset_of,
|
||||
option_env: env::expand_option_env,
|
||||
core_panic: edition_panic::expand_panic,
|
||||
std_panic: edition_panic::expand_panic,
|
||||
|
99
compiler/rustc_builtin_macros/src/offset_of.rs
Normal file
99
compiler/rustc_builtin_macros/src/offset_of.rs
Normal file
@ -0,0 +1,99 @@
|
||||
use rustc_ast as ast;
|
||||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::token;
|
||||
use rustc_ast::tokenstream::TokenStream;
|
||||
use rustc_errors::PResult;
|
||||
use rustc_expand::base::{self, *};
|
||||
use rustc_macros::Diagnostic;
|
||||
use rustc_parse::parser::Parser;
|
||||
use rustc_span::{symbol::Ident, Span};
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(builtin_macros_offset_of_expected_field)]
|
||||
struct ExpectedField {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(builtin_macros_offset_of_expected_two_args)]
|
||||
struct ExpectedTwoArgs {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
}
|
||||
|
||||
fn parse_field<'a>(cx: &ExtCtxt<'a>, p: &mut Parser<'a>) -> PResult<'a, Ident> {
|
||||
let token = p.token.uninterpolate();
|
||||
let field = match token.kind {
|
||||
token::Ident(name, _) => Ident::new(name, token.span),
|
||||
token::Literal(token::Lit { kind: token::Integer, symbol, suffix: None }) => {
|
||||
Ident::new(symbol, token.span)
|
||||
}
|
||||
_ => return Err(cx.create_err(ExpectedField { span: p.token.span })),
|
||||
};
|
||||
|
||||
p.bump();
|
||||
|
||||
Ok(field)
|
||||
}
|
||||
|
||||
fn parse_args<'a>(
|
||||
cx: &mut ExtCtxt<'a>,
|
||||
sp: Span,
|
||||
tts: TokenStream,
|
||||
) -> PResult<'a, (P<ast::Ty>, P<[Ident]>)> {
|
||||
let mut p = cx.new_parser_from_tts(tts);
|
||||
|
||||
let container = p.parse_ty()?;
|
||||
|
||||
p.expect(&token::Comma)?;
|
||||
|
||||
if p.eat(&token::Eof) {
|
||||
return Err(cx.create_err(ExpectedTwoArgs { span: sp }));
|
||||
}
|
||||
|
||||
let mut fields = Vec::new();
|
||||
|
||||
loop {
|
||||
let field = parse_field(cx, &mut p)?;
|
||||
fields.push(field);
|
||||
|
||||
if p.eat(&token::Dot) {
|
||||
continue;
|
||||
}
|
||||
|
||||
p.eat(&token::Comma);
|
||||
|
||||
if !p.eat(&token::Eof) {
|
||||
return Err(cx.create_err(ExpectedTwoArgs { span: sp }));
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
Ok((container, fields.into()))
|
||||
}
|
||||
|
||||
pub fn expand_offset_of<'cx>(
|
||||
cx: &'cx mut ExtCtxt<'_>,
|
||||
sp: Span,
|
||||
tts: TokenStream,
|
||||
) -> Box<dyn base::MacResult + 'cx> {
|
||||
match parse_args(cx, sp, tts) {
|
||||
Ok((container, fields)) => {
|
||||
let expr = P(ast::Expr {
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
kind: ast::ExprKind::OffsetOf(container, fields),
|
||||
span: sp,
|
||||
attrs: ast::AttrVec::new(),
|
||||
tokens: None,
|
||||
});
|
||||
|
||||
MacEager::expr(expr)
|
||||
}
|
||||
Err(mut err) => {
|
||||
err.emit();
|
||||
DummyResult::any(sp)
|
||||
}
|
||||
}
|
||||
}
|
@ -1,3 +1,4 @@
|
||||
use crate::errors;
|
||||
/// The expansion from a test function to the appropriate test struct for libtest
|
||||
/// Ideally, this code would be in libtest but for efficiency and error messages it lives here.
|
||||
use crate::util::{check_builtin_macro_attribute, warn_on_duplicate_attribute};
|
||||
@ -40,12 +41,7 @@ pub fn expand_test_case(
|
||||
unreachable!()
|
||||
},
|
||||
_ => {
|
||||
ecx.struct_span_err(
|
||||
anno_item.span(),
|
||||
"`#[test_case]` attribute is only allowed on items",
|
||||
)
|
||||
.emit();
|
||||
|
||||
ecx.emit_err(errors::TestCaseNonItem { span: anno_item.span() });
|
||||
return vec![];
|
||||
}
|
||||
};
|
||||
@ -533,15 +529,11 @@ fn has_test_signature(cx: &ExtCtxt<'_>, i: &ast::Item) -> bool {
|
||||
match &i.kind {
|
||||
ast::ItemKind::Fn(box ast::Fn { sig, generics, .. }) => {
|
||||
if let ast::Unsafe::Yes(span) = sig.header.unsafety {
|
||||
sd.struct_span_err(i.span, "unsafe functions cannot be used for tests")
|
||||
.span_label(span, "`unsafe` because of this")
|
||||
.emit();
|
||||
sd.emit_err(errors::TestBadFn { span: i.span, cause: span, kind: "unsafe" });
|
||||
return false;
|
||||
}
|
||||
if let ast::Async::Yes { span, .. } = sig.header.asyncness {
|
||||
sd.struct_span_err(i.span, "async functions cannot be used for tests")
|
||||
.span_label(span, "`async` because of this")
|
||||
.emit();
|
||||
sd.emit_err(errors::TestBadFn { span: i.span, cause: span, kind: "async" });
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -19,6 +19,8 @@ use tracing::debug;
|
||||
|
||||
use std::{iter, mem};
|
||||
|
||||
use crate::errors;
|
||||
|
||||
#[derive(Clone)]
|
||||
struct Test {
|
||||
span: Span,
|
||||
@ -385,11 +387,11 @@ fn get_test_runner(sd: &rustc_errors::Handler, krate: &ast::Crate) -> Option<ast
|
||||
[single] => match single.meta_item() {
|
||||
Some(meta_item) if meta_item.is_word() => return Some(meta_item.path.clone()),
|
||||
_ => {
|
||||
sd.struct_span_err(span, "`test_runner` argument must be a path").emit();
|
||||
sd.emit_err(errors::TestRunnerInvalid { span });
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
sd.struct_span_err(span, "`#![test_runner(..)]` accepts exactly 1 argument").emit();
|
||||
sd.emit_err(errors::TestRunnerNargs { span });
|
||||
}
|
||||
}
|
||||
None
|
||||
|
18
compiler/rustc_codegen_cranelift/.github/actions/github-release/README.md
vendored
Normal file
18
compiler/rustc_codegen_cranelift/.github/actions/github-release/README.md
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
# github-release
|
||||
|
||||
An action used to publish GitHub releases for `wasmtime`.
|
||||
|
||||
As of the time of this writing there's a few actions floating around which
|
||||
perform github releases but they all tend to have their set of drawbacks.
|
||||
Additionally nothing handles deleting releases which we need for our rolling
|
||||
`dev` release.
|
||||
|
||||
To handle all this this action rolls-its-own implementation using the
|
||||
actions/toolkit repository and packages published there. These run in a Docker
|
||||
container and take various inputs to orchestrate the release from the build.
|
||||
|
||||
More comments can be found in `main.js`.
|
||||
|
||||
Testing this is really hard. If you want to try though run `npm install` and
|
||||
then `node main.js`. You'll have to configure a bunch of env vars though to get
|
||||
anything reasonably working.
|
13
compiler/rustc_codegen_cranelift/.github/actions/github-release/action.yml
vendored
Normal file
13
compiler/rustc_codegen_cranelift/.github/actions/github-release/action.yml
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
name: 'rustc_codegen_cranelift github releases'
|
||||
description: 'rustc_codegen_cranelift github releases'
|
||||
inputs:
|
||||
token:
|
||||
description: ''
|
||||
required: true
|
||||
files:
|
||||
description: ''
|
||||
required: true
|
||||
runs:
|
||||
using: 'node16'
|
||||
main: 'main.js'
|
162
compiler/rustc_codegen_cranelift/.github/actions/github-release/main.js
vendored
Normal file
162
compiler/rustc_codegen_cranelift/.github/actions/github-release/main.js
vendored
Normal file
@ -0,0 +1,162 @@
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
const core = require('@actions/core');
|
||||
const path = require("path");
|
||||
const fs = require("fs");
|
||||
const github = require('@actions/github');
|
||||
const glob = require('glob');
|
||||
|
||||
function sleep(milliseconds) {
|
||||
return new Promise(resolve => setTimeout(resolve, milliseconds))
|
||||
}
|
||||
|
||||
async function runOnce() {
|
||||
// Load all our inputs and env vars. Note that `getInput` reads from `INPUT_*`
|
||||
const files = core.getInput('files');
|
||||
const token = core.getInput('token');
|
||||
const slug = process.env.GITHUB_REPOSITORY;
|
||||
const owner = slug.split('/')[0];
|
||||
const repo = slug.split('/')[1];
|
||||
const sha = process.env.GITHUB_SHA;
|
||||
let name = 'dev';
|
||||
if (process.env.GITHUB_REF.startsWith('refs/tags/v')) {
|
||||
name = process.env.GITHUB_REF.substring(10);
|
||||
}
|
||||
|
||||
core.info(`files: ${files}`);
|
||||
core.info(`name: ${name}`);
|
||||
core.info(`token: ${token}`);
|
||||
|
||||
const octokit = github.getOctokit(token);
|
||||
|
||||
// For the `dev` release we may need to update the tag to point to the new
|
||||
// commit on this branch. All other names should already have tags associated
|
||||
// with them.
|
||||
if (name == 'dev') {
|
||||
let tag = null;
|
||||
try {
|
||||
tag = await octokit.request("GET /repos/:owner/:repo/git/refs/tags/:name", { owner, repo, name });
|
||||
core.info(`found existing tag`);
|
||||
console.log("tag: ", JSON.stringify(tag.data, null, 2));
|
||||
} catch (e) {
|
||||
// ignore if this tag doesn't exist
|
||||
core.info(`no existing tag found`);
|
||||
}
|
||||
|
||||
if (tag === null || tag.data.object.sha !== sha) {
|
||||
core.info(`updating existing tag or creating new one`);
|
||||
|
||||
try {
|
||||
core.info(`updating dev tag`);
|
||||
await octokit.rest.git.updateRef({
|
||||
owner,
|
||||
repo,
|
||||
ref: 'tags/dev',
|
||||
sha,
|
||||
force: true,
|
||||
});
|
||||
} catch (e) {
|
||||
console.log("ERROR: ", JSON.stringify(e.data, null, 2));
|
||||
core.info(`creating dev tag`);
|
||||
try {
|
||||
await octokit.rest.git.createRef({
|
||||
owner,
|
||||
repo,
|
||||
ref: 'refs/tags/dev',
|
||||
sha,
|
||||
});
|
||||
} catch (e) {
|
||||
// we might race with others, so assume someone else has created the
|
||||
// tag by this point.
|
||||
console.log("failed to create tag: ", JSON.stringify(e.data, null, 2));
|
||||
}
|
||||
}
|
||||
|
||||
console.log("double-checking tag is correct");
|
||||
tag = await octokit.request("GET /repos/:owner/:repo/git/refs/tags/:name", { owner, repo, name });
|
||||
if (tag.data.object.sha !== sha) {
|
||||
console.log("tag: ", JSON.stringify(tag.data, null, 2));
|
||||
throw new Error("tag didn't work");
|
||||
}
|
||||
} else {
|
||||
core.info(`existing tag works`);
|
||||
}
|
||||
}
|
||||
|
||||
// Delete a previous release
|
||||
try {
|
||||
core.info(`fetching release`);
|
||||
let release = await octokit.rest.repos.getReleaseByTag({ owner, repo, tag: name });
|
||||
console.log("found release: ", JSON.stringify(release.data, null, 2));
|
||||
await octokit.rest.repos.deleteRelease({
|
||||
owner,
|
||||
repo,
|
||||
release_id: release.data.id,
|
||||
});
|
||||
console.log("deleted release");
|
||||
} catch (e) {
|
||||
console.log("ERROR: ", JSON.stringify(e, null, 2));
|
||||
}
|
||||
|
||||
console.log("creating a release");
|
||||
let release = await octokit.rest.repos.createRelease({
|
||||
owner,
|
||||
repo,
|
||||
tag_name: name,
|
||||
prerelease: name === 'dev',
|
||||
});
|
||||
|
||||
// Delete all assets from a previous run
|
||||
for (const asset of release.data.assets) {
|
||||
console.log(`deleting prior asset ${asset.id}`);
|
||||
await octokit.rest.repos.deleteReleaseAsset({
|
||||
owner,
|
||||
repo,
|
||||
asset_id: asset.id,
|
||||
});
|
||||
}
|
||||
|
||||
// Upload all the relevant assets for this release as just general blobs.
|
||||
for (const file of glob.sync(files)) {
|
||||
const size = fs.statSync(file).size;
|
||||
const name = path.basename(file);
|
||||
core.info(`upload ${file}`);
|
||||
await octokit.rest.repos.uploadReleaseAsset({
|
||||
data: fs.createReadStream(file),
|
||||
headers: { 'content-length': size, 'content-type': 'application/octet-stream' },
|
||||
name,
|
||||
url: release.data.upload_url,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async function run() {
|
||||
const retries = 10;
|
||||
for (let i = 0; i < retries; i++) {
|
||||
try {
|
||||
await runOnce();
|
||||
break;
|
||||
} catch (e) {
|
||||
if (i === retries - 1)
|
||||
throw e;
|
||||
logError(e);
|
||||
console.log("RETRYING after 10s");
|
||||
await sleep(10000)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function logError(e) {
|
||||
console.log("ERROR: ", e.message);
|
||||
try {
|
||||
console.log(JSON.stringify(e, null, 2));
|
||||
} catch (e) {
|
||||
// ignore json errors for now
|
||||
}
|
||||
console.log(e.stack);
|
||||
}
|
||||
|
||||
run().catch(err => {
|
||||
logError(err);
|
||||
core.setFailed(err.message);
|
||||
});
|
571
compiler/rustc_codegen_cranelift/.github/actions/github-release/package-lock.json
generated
vendored
Normal file
571
compiler/rustc_codegen_cranelift/.github/actions/github-release/package-lock.json
generated
vendored
Normal file
@ -0,0 +1,571 @@
|
||||
{
|
||||
"name": "rustc_codegen_cranelift-github-release",
|
||||
"version": "0.0.0",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "rustc_codegen_cranelift-github-release",
|
||||
"version": "0.0.0",
|
||||
"dependencies": {
|
||||
"@actions/core": "^1.9.1",
|
||||
"@actions/github": "^5.1.0",
|
||||
"glob": "^7.1.5"
|
||||
}
|
||||
},
|
||||
"node_modules/@actions/core": {
|
||||
"version": "1.9.1",
|
||||
"resolved": "https://registry.npmjs.org/@actions/core/-/core-1.9.1.tgz",
|
||||
"integrity": "sha512-5ad+U2YGrmmiw6du20AQW5XuWo7UKN2052FjSV7MX+Wfjf8sCqcsZe62NfgHys4QI4/Y+vQvLKYL8jWtA1ZBTA==",
|
||||
"dependencies": {
|
||||
"@actions/http-client": "^2.0.1",
|
||||
"uuid": "^8.3.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@actions/github": {
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@actions/github/-/github-5.1.0.tgz",
|
||||
"integrity": "sha512-tuI80F7JQIhg77ZTTgUAPpVD7ZnP9oHSPN8xw7LOwtA4vEMbAjWJNbmLBfV7xua7r016GyjzWLuec5cs8f/a8A==",
|
||||
"dependencies": {
|
||||
"@actions/http-client": "^2.0.1",
|
||||
"@octokit/core": "^3.6.0",
|
||||
"@octokit/plugin-paginate-rest": "^2.17.0",
|
||||
"@octokit/plugin-rest-endpoint-methods": "^5.13.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@actions/http-client": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.0.1.tgz",
|
||||
"integrity": "sha512-PIXiMVtz6VvyaRsGY268qvj57hXQEpsYogYOu2nrQhlf+XCGmZstmuZBbAybUl1nQGnvS1k1eEsQ69ZoD7xlSw==",
|
||||
"dependencies": {
|
||||
"tunnel": "^0.0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/auth-token": {
|
||||
"version": "2.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.5.0.tgz",
|
||||
"integrity": "sha512-r5FVUJCOLl19AxiuZD2VRZ/ORjp/4IN98Of6YJoJOkY75CIBuYfmiNHGrDwXr+aLGG55igl9QrxX3hbiXlLb+g==",
|
||||
"dependencies": {
|
||||
"@octokit/types": "^6.0.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/core": {
|
||||
"version": "3.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/core/-/core-3.6.0.tgz",
|
||||
"integrity": "sha512-7RKRKuA4xTjMhY+eG3jthb3hlZCsOwg3rztWh75Xc+ShDWOfDDATWbeZpAHBNRpm4Tv9WgBMOy1zEJYXG6NJ7Q==",
|
||||
"dependencies": {
|
||||
"@octokit/auth-token": "^2.4.4",
|
||||
"@octokit/graphql": "^4.5.8",
|
||||
"@octokit/request": "^5.6.3",
|
||||
"@octokit/request-error": "^2.0.5",
|
||||
"@octokit/types": "^6.0.3",
|
||||
"before-after-hook": "^2.2.0",
|
||||
"universal-user-agent": "^6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/endpoint": {
|
||||
"version": "6.0.12",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.12.tgz",
|
||||
"integrity": "sha512-lF3puPwkQWGfkMClXb4k/eUT/nZKQfxinRWJrdZaJO85Dqwo/G0yOC434Jr2ojwafWJMYqFGFa5ms4jJUgujdA==",
|
||||
"dependencies": {
|
||||
"@octokit/types": "^6.0.3",
|
||||
"is-plain-object": "^5.0.0",
|
||||
"universal-user-agent": "^6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/graphql": {
|
||||
"version": "4.8.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-4.8.0.tgz",
|
||||
"integrity": "sha512-0gv+qLSBLKF0z8TKaSKTsS39scVKF9dbMxJpj3U0vC7wjNWFuIpL/z76Qe2fiuCbDRcJSavkXsVtMS6/dtQQsg==",
|
||||
"dependencies": {
|
||||
"@octokit/request": "^5.6.0",
|
||||
"@octokit/types": "^6.0.3",
|
||||
"universal-user-agent": "^6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/openapi-types": {
|
||||
"version": "12.11.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.11.0.tgz",
|
||||
"integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ=="
|
||||
},
|
||||
"node_modules/@octokit/plugin-paginate-rest": {
|
||||
"version": "2.21.3",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.21.3.tgz",
|
||||
"integrity": "sha512-aCZTEf0y2h3OLbrgKkrfFdjRL6eSOo8komneVQJnYecAxIej7Bafor2xhuDJOIFau4pk0i/P28/XgtbyPF0ZHw==",
|
||||
"dependencies": {
|
||||
"@octokit/types": "^6.40.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@octokit/core": ">=2"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/plugin-rest-endpoint-methods": {
|
||||
"version": "5.16.2",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-5.16.2.tgz",
|
||||
"integrity": "sha512-8QFz29Fg5jDuTPXVtey05BLm7OB+M8fnvE64RNegzX7U+5NUXcOcnpTIK0YfSHBg8gYd0oxIq3IZTe9SfPZiRw==",
|
||||
"dependencies": {
|
||||
"@octokit/types": "^6.39.0",
|
||||
"deprecation": "^2.3.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@octokit/core": ">=3"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/request": {
|
||||
"version": "5.6.3",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.6.3.tgz",
|
||||
"integrity": "sha512-bFJl0I1KVc9jYTe9tdGGpAMPy32dLBXXo1dS/YwSCTL/2nd9XeHsY616RE3HPXDVk+a+dBuzyz5YdlXwcDTr2A==",
|
||||
"dependencies": {
|
||||
"@octokit/endpoint": "^6.0.1",
|
||||
"@octokit/request-error": "^2.1.0",
|
||||
"@octokit/types": "^6.16.1",
|
||||
"is-plain-object": "^5.0.0",
|
||||
"node-fetch": "^2.6.7",
|
||||
"universal-user-agent": "^6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/request-error": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.1.0.tgz",
|
||||
"integrity": "sha512-1VIvgXxs9WHSjicsRwq8PlR2LR2x6DwsJAaFgzdi0JfJoGSO8mYI/cHJQ+9FbN21aa+DrgNLnwObmyeSC8Rmpg==",
|
||||
"dependencies": {
|
||||
"@octokit/types": "^6.0.3",
|
||||
"deprecation": "^2.0.0",
|
||||
"once": "^1.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/types": {
|
||||
"version": "6.41.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.41.0.tgz",
|
||||
"integrity": "sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg==",
|
||||
"dependencies": {
|
||||
"@octokit/openapi-types": "^12.11.0"
|
||||
}
|
||||
},
|
||||
"node_modules/balanced-match": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
|
||||
},
|
||||
"node_modules/before-after-hook": {
|
||||
"version": "2.2.3",
|
||||
"resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz",
|
||||
"integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ=="
|
||||
},
|
||||
"node_modules/brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
||||
"dependencies": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/concat-map": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
|
||||
},
|
||||
"node_modules/deprecation": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz",
|
||||
"integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ=="
|
||||
},
|
||||
"node_modules/fs.realpath": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
||||
"integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="
|
||||
},
|
||||
"node_modules/glob": {
|
||||
"version": "7.2.3",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
|
||||
"integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
|
||||
"dependencies": {
|
||||
"fs.realpath": "^1.0.0",
|
||||
"inflight": "^1.0.4",
|
||||
"inherits": "2",
|
||||
"minimatch": "^3.1.1",
|
||||
"once": "^1.3.0",
|
||||
"path-is-absolute": "^1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/inflight": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
|
||||
"integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
|
||||
"dependencies": {
|
||||
"once": "^1.3.0",
|
||||
"wrappy": "1"
|
||||
}
|
||||
},
|
||||
"node_modules/inherits": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
|
||||
},
|
||||
"node_modules/is-plain-object": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz",
|
||||
"integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/minimatch": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
||||
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
|
||||
"dependencies": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/node-fetch": {
|
||||
"version": "2.6.7",
|
||||
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
|
||||
"integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
|
||||
"dependencies": {
|
||||
"whatwg-url": "^5.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "4.x || >=6.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"encoding": "^0.1.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"encoding": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/once": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
|
||||
"dependencies": {
|
||||
"wrappy": "1"
|
||||
}
|
||||
},
|
||||
"node_modules/path-is-absolute": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
|
||||
"integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/tr46": {
|
||||
"version": "0.0.3",
|
||||
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
|
||||
"integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="
|
||||
},
|
||||
"node_modules/tunnel": {
|
||||
"version": "0.0.6",
|
||||
"resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz",
|
||||
"integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==",
|
||||
"engines": {
|
||||
"node": ">=0.6.11 <=0.7.0 || >=0.7.3"
|
||||
}
|
||||
},
|
||||
"node_modules/universal-user-agent": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz",
|
||||
"integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w=="
|
||||
},
|
||||
"node_modules/uuid": {
|
||||
"version": "8.3.2",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
|
||||
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
|
||||
"bin": {
|
||||
"uuid": "dist/bin/uuid"
|
||||
}
|
||||
},
|
||||
"node_modules/webidl-conversions": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
|
||||
"integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="
|
||||
},
|
||||
"node_modules/whatwg-url": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
|
||||
"integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
|
||||
"dependencies": {
|
||||
"tr46": "~0.0.3",
|
||||
"webidl-conversions": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/wrappy": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"@actions/core": {
|
||||
"version": "1.9.1",
|
||||
"resolved": "https://registry.npmjs.org/@actions/core/-/core-1.9.1.tgz",
|
||||
"integrity": "sha512-5ad+U2YGrmmiw6du20AQW5XuWo7UKN2052FjSV7MX+Wfjf8sCqcsZe62NfgHys4QI4/Y+vQvLKYL8jWtA1ZBTA==",
|
||||
"requires": {
|
||||
"@actions/http-client": "^2.0.1",
|
||||
"uuid": "^8.3.2"
|
||||
}
|
||||
},
|
||||
"@actions/github": {
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@actions/github/-/github-5.1.0.tgz",
|
||||
"integrity": "sha512-tuI80F7JQIhg77ZTTgUAPpVD7ZnP9oHSPN8xw7LOwtA4vEMbAjWJNbmLBfV7xua7r016GyjzWLuec5cs8f/a8A==",
|
||||
"requires": {
|
||||
"@actions/http-client": "^2.0.1",
|
||||
"@octokit/core": "^3.6.0",
|
||||
"@octokit/plugin-paginate-rest": "^2.17.0",
|
||||
"@octokit/plugin-rest-endpoint-methods": "^5.13.0"
|
||||
}
|
||||
},
|
||||
"@actions/http-client": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.0.1.tgz",
|
||||
"integrity": "sha512-PIXiMVtz6VvyaRsGY268qvj57hXQEpsYogYOu2nrQhlf+XCGmZstmuZBbAybUl1nQGnvS1k1eEsQ69ZoD7xlSw==",
|
||||
"requires": {
|
||||
"tunnel": "^0.0.6"
|
||||
}
|
||||
},
|
||||
"@octokit/auth-token": {
|
||||
"version": "2.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.5.0.tgz",
|
||||
"integrity": "sha512-r5FVUJCOLl19AxiuZD2VRZ/ORjp/4IN98Of6YJoJOkY75CIBuYfmiNHGrDwXr+aLGG55igl9QrxX3hbiXlLb+g==",
|
||||
"requires": {
|
||||
"@octokit/types": "^6.0.3"
|
||||
}
|
||||
},
|
||||
"@octokit/core": {
|
||||
"version": "3.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/core/-/core-3.6.0.tgz",
|
||||
"integrity": "sha512-7RKRKuA4xTjMhY+eG3jthb3hlZCsOwg3rztWh75Xc+ShDWOfDDATWbeZpAHBNRpm4Tv9WgBMOy1zEJYXG6NJ7Q==",
|
||||
"requires": {
|
||||
"@octokit/auth-token": "^2.4.4",
|
||||
"@octokit/graphql": "^4.5.8",
|
||||
"@octokit/request": "^5.6.3",
|
||||
"@octokit/request-error": "^2.0.5",
|
||||
"@octokit/types": "^6.0.3",
|
||||
"before-after-hook": "^2.2.0",
|
||||
"universal-user-agent": "^6.0.0"
|
||||
}
|
||||
},
|
||||
"@octokit/endpoint": {
|
||||
"version": "6.0.12",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.12.tgz",
|
||||
"integrity": "sha512-lF3puPwkQWGfkMClXb4k/eUT/nZKQfxinRWJrdZaJO85Dqwo/G0yOC434Jr2ojwafWJMYqFGFa5ms4jJUgujdA==",
|
||||
"requires": {
|
||||
"@octokit/types": "^6.0.3",
|
||||
"is-plain-object": "^5.0.0",
|
||||
"universal-user-agent": "^6.0.0"
|
||||
}
|
||||
},
|
||||
"@octokit/graphql": {
|
||||
"version": "4.8.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-4.8.0.tgz",
|
||||
"integrity": "sha512-0gv+qLSBLKF0z8TKaSKTsS39scVKF9dbMxJpj3U0vC7wjNWFuIpL/z76Qe2fiuCbDRcJSavkXsVtMS6/dtQQsg==",
|
||||
"requires": {
|
||||
"@octokit/request": "^5.6.0",
|
||||
"@octokit/types": "^6.0.3",
|
||||
"universal-user-agent": "^6.0.0"
|
||||
}
|
||||
},
|
||||
"@octokit/openapi-types": {
|
||||
"version": "12.11.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.11.0.tgz",
|
||||
"integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ=="
|
||||
},
|
||||
"@octokit/plugin-paginate-rest": {
|
||||
"version": "2.21.3",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.21.3.tgz",
|
||||
"integrity": "sha512-aCZTEf0y2h3OLbrgKkrfFdjRL6eSOo8komneVQJnYecAxIej7Bafor2xhuDJOIFau4pk0i/P28/XgtbyPF0ZHw==",
|
||||
"requires": {
|
||||
"@octokit/types": "^6.40.0"
|
||||
}
|
||||
},
|
||||
"@octokit/plugin-rest-endpoint-methods": {
|
||||
"version": "5.16.2",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-5.16.2.tgz",
|
||||
"integrity": "sha512-8QFz29Fg5jDuTPXVtey05BLm7OB+M8fnvE64RNegzX7U+5NUXcOcnpTIK0YfSHBg8gYd0oxIq3IZTe9SfPZiRw==",
|
||||
"requires": {
|
||||
"@octokit/types": "^6.39.0",
|
||||
"deprecation": "^2.3.1"
|
||||
}
|
||||
},
|
||||
"@octokit/request": {
|
||||
"version": "5.6.3",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.6.3.tgz",
|
||||
"integrity": "sha512-bFJl0I1KVc9jYTe9tdGGpAMPy32dLBXXo1dS/YwSCTL/2nd9XeHsY616RE3HPXDVk+a+dBuzyz5YdlXwcDTr2A==",
|
||||
"requires": {
|
||||
"@octokit/endpoint": "^6.0.1",
|
||||
"@octokit/request-error": "^2.1.0",
|
||||
"@octokit/types": "^6.16.1",
|
||||
"is-plain-object": "^5.0.0",
|
||||
"node-fetch": "^2.6.7",
|
||||
"universal-user-agent": "^6.0.0"
|
||||
}
|
||||
},
|
||||
"@octokit/request-error": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.1.0.tgz",
|
||||
"integrity": "sha512-1VIvgXxs9WHSjicsRwq8PlR2LR2x6DwsJAaFgzdi0JfJoGSO8mYI/cHJQ+9FbN21aa+DrgNLnwObmyeSC8Rmpg==",
|
||||
"requires": {
|
||||
"@octokit/types": "^6.0.3",
|
||||
"deprecation": "^2.0.0",
|
||||
"once": "^1.4.0"
|
||||
}
|
||||
},
|
||||
"@octokit/types": {
|
||||
"version": "6.41.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.41.0.tgz",
|
||||
"integrity": "sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg==",
|
||||
"requires": {
|
||||
"@octokit/openapi-types": "^12.11.0"
|
||||
}
|
||||
},
|
||||
"balanced-match": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
|
||||
},
|
||||
"before-after-hook": {
|
||||
"version": "2.2.3",
|
||||
"resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz",
|
||||
"integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ=="
|
||||
},
|
||||
"brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
||||
"requires": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
}
|
||||
},
|
||||
"concat-map": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
|
||||
},
|
||||
"deprecation": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz",
|
||||
"integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ=="
|
||||
},
|
||||
"fs.realpath": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
||||
"integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="
|
||||
},
|
||||
"glob": {
|
||||
"version": "7.2.3",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
|
||||
"integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
|
||||
"requires": {
|
||||
"fs.realpath": "^1.0.0",
|
||||
"inflight": "^1.0.4",
|
||||
"inherits": "2",
|
||||
"minimatch": "^3.1.1",
|
||||
"once": "^1.3.0",
|
||||
"path-is-absolute": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"inflight": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
|
||||
"integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
|
||||
"requires": {
|
||||
"once": "^1.3.0",
|
||||
"wrappy": "1"
|
||||
}
|
||||
},
|
||||
"inherits": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
|
||||
},
|
||||
"is-plain-object": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz",
|
||||
"integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q=="
|
||||
},
|
||||
"minimatch": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
||||
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
|
||||
"requires": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
}
|
||||
},
|
||||
"node-fetch": {
|
||||
"version": "2.6.7",
|
||||
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
|
||||
"integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
|
||||
"requires": {
|
||||
"whatwg-url": "^5.0.0"
|
||||
}
|
||||
},
|
||||
"once": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
|
||||
"requires": {
|
||||
"wrappy": "1"
|
||||
}
|
||||
},
|
||||
"path-is-absolute": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
|
||||
"integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg=="
|
||||
},
|
||||
"tr46": {
|
||||
"version": "0.0.3",
|
||||
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
|
||||
"integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="
|
||||
},
|
||||
"tunnel": {
|
||||
"version": "0.0.6",
|
||||
"resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz",
|
||||
"integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg=="
|
||||
},
|
||||
"universal-user-agent": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz",
|
||||
"integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w=="
|
||||
},
|
||||
"uuid": {
|
||||
"version": "8.3.2",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
|
||||
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg=="
|
||||
},
|
||||
"webidl-conversions": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
|
||||
"integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="
|
||||
},
|
||||
"whatwg-url": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
|
||||
"integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
|
||||
"requires": {
|
||||
"tr46": "~0.0.3",
|
||||
"webidl-conversions": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"wrappy": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
|
||||
}
|
||||
}
|
||||
}
|
11
compiler/rustc_codegen_cranelift/.github/actions/github-release/package.json
vendored
Normal file
11
compiler/rustc_codegen_cranelift/.github/actions/github-release/package.json
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
{
|
||||
"name": "rustc_codegen_cranelift-github-release",
|
||||
"version": "0.0.0",
|
||||
"license": "Apache-2.0 WITH LLVM-exception",
|
||||
"main": "main.js",
|
||||
"dependencies": {
|
||||
"@actions/core": "^1.9.1",
|
||||
"@actions/github": "^5.1.0",
|
||||
"glob": "^7.1.5"
|
||||
}
|
||||
}
|
@ -45,13 +45,6 @@ jobs:
|
||||
if: matrix.env.TARGET_TRIPLE == 'x86_64-pc-windows-gnu'
|
||||
run: rustup set default-host x86_64-pc-windows-gnu
|
||||
|
||||
- name: Use sparse cargo registry
|
||||
run: |
|
||||
cat >> ~/.cargo/config.toml <<EOF
|
||||
[unstable]
|
||||
sparse-registry = true
|
||||
EOF
|
||||
|
||||
- name: Prepare dependencies
|
||||
run: ./y.rs prepare
|
||||
|
||||
|
@ -20,6 +20,7 @@ jobs:
|
||||
run: |
|
||||
cargo fmt --check
|
||||
rustfmt --check build_system/mod.rs
|
||||
rustfmt --check example/*
|
||||
|
||||
|
||||
test:
|
||||
@ -89,13 +90,6 @@ jobs:
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y gcc-s390x-linux-gnu qemu-user
|
||||
|
||||
- name: Use sparse cargo registry
|
||||
run: |
|
||||
cat >> ~/.cargo/config.toml <<EOF
|
||||
[unstable]
|
||||
sparse-registry = true
|
||||
EOF
|
||||
|
||||
- name: Prepare dependencies
|
||||
run: ./y.rs prepare
|
||||
|
||||
@ -137,13 +131,6 @@ jobs:
|
||||
path: ~/.cargo/bin
|
||||
key: ${{ runner.os }}-${{ matrix.env.TARGET_TRIPLE }}-cargo-bin-dir-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }}
|
||||
|
||||
- name: Use sparse cargo registry
|
||||
run: |
|
||||
cat >> ~/.cargo/config.toml <<EOF
|
||||
[unstable]
|
||||
sparse-registry = true
|
||||
EOF
|
||||
|
||||
- name: Install hyperfine
|
||||
run: cargo install hyperfine || true
|
||||
|
||||
@ -206,13 +193,6 @@ jobs:
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y gcc-mingw-w64-x86-64 wine-stable
|
||||
|
||||
- name: Use sparse cargo registry
|
||||
run: |
|
||||
cat >> ~/.cargo/config.toml <<EOF
|
||||
[unstable]
|
||||
sparse-registry = true
|
||||
EOF
|
||||
|
||||
- name: Prepare dependencies
|
||||
run: ./y.rs prepare
|
||||
|
||||
@ -238,3 +218,43 @@ jobs:
|
||||
with:
|
||||
name: cg_clif-${{ runner.os }}-cross-x86_64-mingw
|
||||
path: cg_clif.tar.xz
|
||||
|
||||
release:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
if: ${{ github.ref == 'refs/heads/master' }}
|
||||
needs: [rustfmt, test, bench, dist]
|
||||
|
||||
concurrency:
|
||||
group: release-dev
|
||||
cancel-in-progress: true
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Download all built artifacts
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
path: artifacts/
|
||||
|
||||
- run: |
|
||||
ls -R artifacts/
|
||||
mkdir release/
|
||||
pushd artifacts/
|
||||
for dir in *; do
|
||||
mv $dir/cg_clif.tar.xz ../release/$dir.tar.xz
|
||||
rmdir $dir/ # verify $dir is empty
|
||||
done
|
||||
popd
|
||||
rmdir artifacts/ # verify all artifacts are represented in release/
|
||||
ls -R release/
|
||||
|
||||
- run: npm install --production
|
||||
working-directory: .github/actions/github-release
|
||||
|
||||
- name: Publish Release
|
||||
uses: ./.github/actions/github-release
|
||||
with:
|
||||
files: "release/*"
|
||||
token: ${{ github.token }}
|
||||
continue-on-error: true
|
||||
|
@ -6,6 +6,7 @@ on:
|
||||
jobs:
|
||||
bootstrap_rustc:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 60
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
@ -16,20 +17,16 @@ jobs:
|
||||
path: build/cg_clif
|
||||
key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }}
|
||||
|
||||
- name: Use sparse cargo registry
|
||||
run: |
|
||||
cat >> ~/.cargo/config.toml <<EOF
|
||||
[unstable]
|
||||
sparse-registry = true
|
||||
EOF
|
||||
|
||||
- name: Prepare dependencies
|
||||
run: ./y.rs prepare
|
||||
|
||||
- name: Test
|
||||
run: ./scripts/test_bootstrap.sh
|
||||
|
||||
|
||||
rustc_test_suite:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 60
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
@ -40,13 +37,6 @@ jobs:
|
||||
path: build/cg_clif
|
||||
key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }}
|
||||
|
||||
- name: Use sparse cargo registry
|
||||
run: |
|
||||
cat >> ~/.cargo/config.toml <<EOF
|
||||
[unstable]
|
||||
sparse-registry = true
|
||||
EOF
|
||||
|
||||
- name: Prepare dependencies
|
||||
run: ./y.rs prepare
|
||||
|
||||
|
@ -4,11 +4,11 @@ version = 3
|
||||
|
||||
[[package]]
|
||||
name = "ahash"
|
||||
version = "0.7.6"
|
||||
version = "0.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47"
|
||||
checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
"cfg-if",
|
||||
"once_cell",
|
||||
"version_check",
|
||||
]
|
||||
@ -19,12 +19,6 @@ version = "1.0.66"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "216261ddc8289130e551ddcd5ce8a064710c0d064a4d2895c67151c92b5443f6"
|
||||
|
||||
[[package]]
|
||||
name = "arrayvec"
|
||||
version = "0.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6"
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.1.0"
|
||||
@ -57,20 +51,19 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-bforest"
|
||||
version = "0.93.1"
|
||||
version = "0.95.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a7379abaacee0f14abf3204a7606118f0465785252169d186337bcb75030815a"
|
||||
checksum = "1277fbfa94bc82c8ec4af2ded3e639d49ca5f7f3c7eeab2c66accd135ece4e70"
|
||||
dependencies = [
|
||||
"cranelift-entity",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-codegen"
|
||||
version = "0.93.1"
|
||||
version = "0.95.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9489fa336927df749631f1008007ced2871068544f40a202ce6d93fbf2366a7b"
|
||||
checksum = "c6e8c31ad3b2270e9aeec38723888fe1b0ace3bea2b06b3f749ccf46661d3220"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"bumpalo",
|
||||
"cranelift-bforest",
|
||||
"cranelift-codegen-meta",
|
||||
@ -78,7 +71,7 @@ dependencies = [
|
||||
"cranelift-entity",
|
||||
"cranelift-isle",
|
||||
"gimli",
|
||||
"hashbrown",
|
||||
"hashbrown 0.13.2",
|
||||
"log",
|
||||
"regalloc2",
|
||||
"smallvec",
|
||||
@ -87,30 +80,30 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-codegen-meta"
|
||||
version = "0.93.1"
|
||||
version = "0.95.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "05bbb67da91ec721ed57cef2f7c5ef7728e1cd9bde9ffd3ef8601022e73e3239"
|
||||
checksum = "c8ac5ac30d62b2d66f12651f6b606dbdfd9c2cfd0908de6b387560a277c5c9da"
|
||||
dependencies = [
|
||||
"cranelift-codegen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-codegen-shared"
|
||||
version = "0.93.1"
|
||||
version = "0.95.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "418ecb2f36032f6665dc1a5e2060a143dbab41d83b784882e97710e890a7a16d"
|
||||
checksum = "dd82b8b376247834b59ed9bdc0ddeb50f517452827d4a11bccf5937b213748b8"
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-entity"
|
||||
version = "0.93.1"
|
||||
version = "0.95.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7cf583f7b093f291005f9fb1323e2c37f6ee4c7909e39ce016b2e8360d461705"
|
||||
checksum = "40099d38061b37e505e63f89bab52199037a72b931ad4868d9089ff7268660b0"
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-frontend"
|
||||
version = "0.93.0"
|
||||
version = "0.95.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7d361ed0373cf5f086b49c499aa72227b646a64f899f32e34312f97c0fadff75"
|
||||
checksum = "64a25d9d0a0ae3079c463c34115ec59507b4707175454f0eee0891e83e30e82d"
|
||||
dependencies = [
|
||||
"cranelift-codegen",
|
||||
"log",
|
||||
@ -120,15 +113,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-isle"
|
||||
version = "0.93.1"
|
||||
version = "0.95.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "649782a39ce99798dd6b4029e2bb318a2fbeaade1b4fa25330763c10c65bc358"
|
||||
checksum = "80de6a7d0486e4acbd5f9f87ec49912bf4c8fb6aea00087b989685460d4469ba"
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-jit"
|
||||
version = "0.93.0"
|
||||
version = "0.95.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c9909222db472fcc98d9e4e7192fa9d064dac63a3fa657df8c6daae86fb2604"
|
||||
checksum = "3ca96b05988aa057eda09a817a6e31915fabd7f476b513123aff08053cd193dd"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"cranelift-codegen",
|
||||
@ -145,9 +138,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-module"
|
||||
version = "0.93.0"
|
||||
version = "0.95.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "68689b83e52e605ba48652882d3fccc2e2e136abf139eb64ae667888ba0d52f8"
|
||||
checksum = "e5112c0be9cc5da064e0620570d67852f11ce44f2e572a58ecf7f11df73978b8"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"cranelift-codegen",
|
||||
@ -155,9 +148,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-native"
|
||||
version = "0.93.0"
|
||||
version = "0.95.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f98e4e99a353703475d5acb402b9c13482d41d8a4008b352559bd560afb90363"
|
||||
checksum = "bb6b03e0e03801c4b3fd8ce0758a94750c07a44e7944cc0ffbf0d3f2e7c79b00"
|
||||
dependencies = [
|
||||
"cranelift-codegen",
|
||||
"libc",
|
||||
@ -166,9 +159,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-object"
|
||||
version = "0.93.0"
|
||||
version = "0.95.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b7a006ce1d8dd11df67567d8673e5920f3a56441812aed52a007ffce8f1b20e9"
|
||||
checksum = "48ed1b37d0972abe804cb5bf2b35f3a76a276ebbe148e3a726d8e31042790978"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"cranelift-codegen",
|
||||
@ -202,22 +195,11 @@ dependencies = [
|
||||
"byteorder",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"wasi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gimli"
|
||||
version = "0.26.2"
|
||||
version = "0.27.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d"
|
||||
checksum = "ad0a93d233ebf96623465aad4046a8d3aa4da22d4f4beba5388838c8a434bbb4"
|
||||
dependencies = [
|
||||
"fallible-iterator",
|
||||
"indexmap",
|
||||
@ -229,6 +211,12 @@ name = "hashbrown"
|
||||
version = "0.12.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.13.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e"
|
||||
dependencies = [
|
||||
"ahash",
|
||||
]
|
||||
@ -240,7 +228,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"hashbrown",
|
||||
"hashbrown 0.12.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -285,12 +273,12 @@ checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
|
||||
|
||||
[[package]]
|
||||
name = "object"
|
||||
version = "0.29.0"
|
||||
version = "0.30.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "21158b2c33aa6d4561f1c0a6ea283ca92bc54802a93b263e910746d679a7eb53"
|
||||
checksum = "ea86265d3d3dcb6a27fc51bd29a4bf387fae9d2986b823079d4986af253eb439"
|
||||
dependencies = [
|
||||
"crc32fast",
|
||||
"hashbrown",
|
||||
"hashbrown 0.13.2",
|
||||
"indexmap",
|
||||
"memchr",
|
||||
]
|
||||
@ -303,9 +291,9 @@ checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860"
|
||||
|
||||
[[package]]
|
||||
name = "regalloc2"
|
||||
version = "0.5.1"
|
||||
version = "0.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "300d4fbfb40c1c66a78ba3ddd41c1110247cf52f97b87d0f2fc9209bd49b030c"
|
||||
checksum = "80535183cae11b149d618fbd3c37e38d7cda589d82d7769e196ca9a9042d7621"
|
||||
dependencies = [
|
||||
"fxhash",
|
||||
"log",
|
||||
@ -374,17 +362,11 @@ version = "0.9.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.11.0+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||
|
||||
[[package]]
|
||||
name = "wasmtime-jit-icache-coherence"
|
||||
version = "6.0.0"
|
||||
version = "8.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec1fd0f0dd79e7cc0f55b102e320d7c77ab76cd272008a8fd98e25b5777e2636"
|
||||
checksum = "aecae978b13f7f67efb23bd827373ace4578f2137ec110bbf6a4a7cde4121bbd"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
@ -415,9 +397,18 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.42.0"
|
||||
version = "0.45.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7"
|
||||
checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0"
|
||||
dependencies = [
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.42.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e2522491fbfcd58cc84d47aeb2958948c4b8982e9a2d8a2a35bbaed431390e7"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc",
|
||||
@ -430,42 +421,42 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.42.0"
|
||||
version = "0.42.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e"
|
||||
checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.42.0"
|
||||
version = "0.42.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4"
|
||||
checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.42.0"
|
||||
version = "0.42.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7"
|
||||
checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.42.0"
|
||||
version = "0.42.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246"
|
||||
checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.42.0"
|
||||
version = "0.42.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed"
|
||||
checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.42.0"
|
||||
version = "0.42.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028"
|
||||
checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.42.0"
|
||||
version = "0.42.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5"
|
||||
checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd"
|
||||
|
@ -15,15 +15,15 @@ crate-type = ["dylib"]
|
||||
|
||||
[dependencies]
|
||||
# These have to be in sync with each other
|
||||
cranelift-codegen = { version = "0.93", features = ["unwind", "all-arch"] }
|
||||
cranelift-frontend = { version = "0.93" }
|
||||
cranelift-module = { version = "0.93" }
|
||||
cranelift-native = { version = "0.93" }
|
||||
cranelift-jit = { version = "0.93", optional = true }
|
||||
cranelift-object = { version = "0.93" }
|
||||
cranelift-codegen = { version = "0.95.1", features = ["unwind", "all-arch"] }
|
||||
cranelift-frontend = { version = "0.95.1" }
|
||||
cranelift-module = { version = "0.95.1" }
|
||||
cranelift-native = { version = "0.95.1" }
|
||||
cranelift-jit = { version = "0.95.1", optional = true }
|
||||
cranelift-object = { version = "0.95.1" }
|
||||
target-lexicon = "0.12.0"
|
||||
gimli = { version = "0.26.0", default-features = false, features = ["write"]}
|
||||
object = { version = "0.29.0", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] }
|
||||
gimli = { version = "0.27.2", default-features = false, features = ["write"]}
|
||||
object = { version = "0.30.3", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] }
|
||||
|
||||
indexmap = "1.9.3"
|
||||
libloading = { version = "0.7.3", optional = true }
|
||||
|
@ -22,10 +22,9 @@ $ ./test.sh
|
||||
|
||||
For more docs on how to build and test see [build_system/usage.txt](build_system/usage.txt) or the help message of `./y.rs`.
|
||||
|
||||
Alternatively you can download a pre built version from [Github Actions]. It is listed in the artifacts section
|
||||
of workflow runs. Unfortunately due to GHA restrictions you need to be logged in to access it.
|
||||
Alternatively you can download a pre built version from the [releases] page.
|
||||
|
||||
[Github Actions]: https://github.com/bjorn3/rustc_codegen_cranelift/actions?query=branch%3Amaster+event%3Apush+is%3Asuccess
|
||||
[releases]: https://github.com/bjorn3/rustc_codegen_cranelift/releases/tag/dev
|
||||
|
||||
## Usage
|
||||
|
||||
|
@ -4,9 +4,9 @@ version = 3
|
||||
|
||||
[[package]]
|
||||
name = "addr2line"
|
||||
version = "0.17.0"
|
||||
version = "0.19.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b"
|
||||
checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"gimli",
|
||||
@ -50,9 +50,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "compiler_builtins"
|
||||
version = "0.1.89"
|
||||
version = "0.1.91"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9fc9c2080d347a2c316518840ac9194644a9993dfa1e9778ef38979a339f5d8b"
|
||||
checksum = "571298a3cce7e2afbd3d61abb91a18667d5ab25993ec577a88ee8ac45f00cc3a"
|
||||
dependencies = [
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
@ -95,9 +95,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "gimli"
|
||||
version = "0.26.2"
|
||||
version = "0.27.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d"
|
||||
checksum = "ad0a93d233ebf96623465aad4046a8d3aa4da22d4f4beba5388838c8a434bbb4"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"rustc-std-workspace-alloc",
|
||||
@ -128,9 +128,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.140"
|
||||
version = "0.2.142"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c"
|
||||
checksum = "6a987beff54b60ffa6d51982e1aa1146bc42f19bd26be28b0586f252fccf5317"
|
||||
dependencies = [
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
@ -147,9 +147,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.5.4"
|
||||
version = "0.6.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "96590ba8f175222643a85693f33d26e9c8a015f599c216509b1a6894af675d34"
|
||||
checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa"
|
||||
dependencies = [
|
||||
"adler",
|
||||
"compiler_builtins",
|
||||
@ -159,9 +159,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "object"
|
||||
version = "0.29.0"
|
||||
version = "0.30.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "21158b2c33aa6d4561f1c0a6ea283ca92bc54802a93b263e910746d679a7eb53"
|
||||
checksum = "ea86265d3d3dcb6a27fc51bd29a4bf387fae9d2986b823079d4986af253eb439"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"memchr",
|
||||
@ -202,9 +202,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rustc-demangle"
|
||||
version = "0.1.21"
|
||||
version = "0.1.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342"
|
||||
checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"rustc-std-workspace-core",
|
||||
|
@ -43,7 +43,7 @@ pub(crate) enum SysrootKind {
|
||||
Llvm,
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
pub(crate) fn main() {
|
||||
if env::var("RUST_BACKTRACE").is_err() {
|
||||
env::set_var("RUST_BACKTRACE", "1");
|
||||
}
|
||||
|
@ -2,7 +2,6 @@ use super::build_sysroot;
|
||||
use super::config;
|
||||
use super::path::{Dirs, RelPath};
|
||||
use super::prepare::GitRepo;
|
||||
use super::rustc_info::get_host_triple;
|
||||
use super::utils::{spawn_and_wait, spawn_and_wait_with_input, CargoProject, Compiler};
|
||||
use super::SysrootKind;
|
||||
use std::env;
|
||||
@ -102,14 +101,14 @@ pub(crate) static RAND_REPO: GitRepo =
|
||||
pub(crate) static RAND: CargoProject = CargoProject::new(&RAND_REPO.source_dir(), "rand");
|
||||
|
||||
pub(crate) static REGEX_REPO: GitRepo =
|
||||
GitRepo::github("rust-lang", "regex", "a9b2e02352db92ce1f6e5b7ecd41b8bbffbe161a", "regex");
|
||||
GitRepo::github("rust-lang", "regex", "32fed9429eafba0ae92a64b01796a0c5a75b88c8", "regex");
|
||||
|
||||
pub(crate) static REGEX: CargoProject = CargoProject::new(®EX_REPO.source_dir(), "regex");
|
||||
|
||||
pub(crate) static PORTABLE_SIMD_REPO: GitRepo = GitRepo::github(
|
||||
"rust-lang",
|
||||
"portable-simd",
|
||||
"9bd30e77b3a3c699af102ebb3df0f6110f8aa02e",
|
||||
"ad8afa8c81273b3b49acbea38cd3bcf17a34cf2b",
|
||||
"portable-simd",
|
||||
);
|
||||
|
||||
@ -186,7 +185,9 @@ const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[
|
||||
|
||||
if runner.is_native {
|
||||
let mut run_cmd = REGEX.test(&runner.target_compiler, &runner.dirs);
|
||||
run_cmd.args(["--workspace", "--", "-q"]);
|
||||
// regex-capi and regex-debug don't have any tests. Nor do they contain any code
|
||||
// that is useful to test with cg_clif. Skip building them to reduce test time.
|
||||
run_cmd.args(["-p", "regex", "-p", "regex-syntax", "--", "-q"]);
|
||||
spawn_and_wait(run_cmd);
|
||||
} else {
|
||||
eprintln!("Cross-Compiling: Not running tests");
|
||||
@ -228,8 +229,11 @@ pub(crate) fn run_tests(
|
||||
target_triple.clone(),
|
||||
);
|
||||
|
||||
let runner =
|
||||
TestRunner::new(dirs.clone(), target_compiler, get_host_triple() == target_triple);
|
||||
let runner = TestRunner::new(
|
||||
dirs.clone(),
|
||||
target_compiler,
|
||||
bootstrap_host_compiler.triple == target_triple,
|
||||
);
|
||||
|
||||
BUILD_EXAMPLE_OUT_DIR.ensure_fresh(dirs);
|
||||
runner.run_testsuite(NO_SYSROOT_SUITE);
|
||||
@ -250,8 +254,11 @@ pub(crate) fn run_tests(
|
||||
target_triple.clone(),
|
||||
);
|
||||
|
||||
let runner =
|
||||
TestRunner::new(dirs.clone(), target_compiler, get_host_triple() == target_triple);
|
||||
let runner = TestRunner::new(
|
||||
dirs.clone(),
|
||||
target_compiler,
|
||||
bootstrap_host_compiler.triple == target_triple,
|
||||
);
|
||||
|
||||
if run_base_sysroot {
|
||||
runner.run_testsuite(BASE_SYSROOT_SUITE);
|
||||
@ -275,7 +282,7 @@ struct TestRunner {
|
||||
}
|
||||
|
||||
impl TestRunner {
|
||||
pub fn new(dirs: Dirs, mut target_compiler: Compiler, is_native: bool) -> Self {
|
||||
fn new(dirs: Dirs, mut target_compiler: Compiler, is_native: bool) -> Self {
|
||||
if let Ok(rustflags) = env::var("RUSTFLAGS") {
|
||||
target_compiler.rustflags.push(' ');
|
||||
target_compiler.rustflags.push_str(&rustflags);
|
||||
@ -297,7 +304,7 @@ impl TestRunner {
|
||||
Self { is_native, jit_supported, dirs, target_compiler }
|
||||
}
|
||||
|
||||
pub fn run_testsuite(&self, tests: &[TestCase]) {
|
||||
fn run_testsuite(&self, tests: &[TestCase]) {
|
||||
for TestCase { config, cmd } in tests {
|
||||
let (tag, testname) = config.split_once('.').unwrap();
|
||||
let tag = tag.to_uppercase();
|
||||
@ -382,7 +389,7 @@ impl TestRunner {
|
||||
spawn_and_wait(self.rustc_command(args));
|
||||
}
|
||||
|
||||
fn run_out_command<'a>(&self, name: &str, args: &[&str]) {
|
||||
fn run_out_command(&self, name: &str, args: &[&str]) {
|
||||
let mut full_cmd = vec![];
|
||||
|
||||
// Prepend the RUN_WRAPPER's
|
||||
|
@ -18,7 +18,7 @@ extern "C" {
|
||||
}
|
||||
|
||||
#[panic_handler]
|
||||
fn panic_handler(_: &core::panic::PanicInfo) -> ! {
|
||||
fn panic_handler(_: &core::panic::PanicInfo<'_>) -> ! {
|
||||
core::intrinsics::abort();
|
||||
}
|
||||
|
||||
|
@ -3,8 +3,8 @@
|
||||
#![feature(arbitrary_self_types, unsize, coerce_unsized, dispatch_from_dyn)]
|
||||
|
||||
use std::{
|
||||
ops::{Deref, CoerceUnsized, DispatchFromDyn},
|
||||
marker::Unsize,
|
||||
ops::{CoerceUnsized, Deref, DispatchFromDyn},
|
||||
};
|
||||
|
||||
struct Ptr<T: ?Sized>(Box<T>);
|
||||
@ -33,7 +33,6 @@ impl<T: ?Sized> Deref for Wrapper<T> {
|
||||
impl<T: CoerceUnsized<U>, U> CoerceUnsized<Wrapper<U>> for Wrapper<T> {}
|
||||
impl<T: DispatchFromDyn<U>, U> DispatchFromDyn<Wrapper<U>> for Wrapper<T> {}
|
||||
|
||||
|
||||
trait Trait {
|
||||
// This method isn't object-safe yet. Unsized by-value `self` is object-safe (but not callable
|
||||
// without unsized_locals), but wrappers around `Self` currently are not.
|
||||
|
@ -2,7 +2,7 @@
|
||||
#![allow(dead_code)]
|
||||
struct Foo<T: ?Sized> {
|
||||
a: u16,
|
||||
b: T
|
||||
b: T,
|
||||
}
|
||||
|
||||
trait Bar {
|
||||
@ -10,58 +10,57 @@ trait Bar {
|
||||
}
|
||||
|
||||
impl Bar for usize {
|
||||
fn get(&self) -> usize { *self }
|
||||
fn get(&self) -> usize {
|
||||
*self
|
||||
}
|
||||
}
|
||||
|
||||
struct Baz<T: ?Sized> {
|
||||
a: T
|
||||
a: T,
|
||||
}
|
||||
|
||||
struct HasDrop<T: ?Sized> {
|
||||
ptr: Box<usize>,
|
||||
data: T
|
||||
data: T,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
// Test that zero-offset works properly
|
||||
let b : Baz<usize> = Baz { a: 7 };
|
||||
let b: Baz<usize> = Baz { a: 7 };
|
||||
assert_eq!(b.a.get(), 7);
|
||||
let b : &Baz<dyn Bar> = &b;
|
||||
let b: &Baz<dyn Bar> = &b;
|
||||
assert_eq!(b.a.get(), 7);
|
||||
|
||||
// Test that the field is aligned properly
|
||||
let f : Foo<usize> = Foo { a: 0, b: 11 };
|
||||
let f: Foo<usize> = Foo { a: 0, b: 11 };
|
||||
assert_eq!(f.b.get(), 11);
|
||||
let ptr1 : *const u8 = &f.b as *const _ as *const u8;
|
||||
let ptr1: *const u8 = &f.b as *const _ as *const u8;
|
||||
|
||||
let f : &Foo<dyn Bar> = &f;
|
||||
let ptr2 : *const u8 = &f.b as *const _ as *const u8;
|
||||
let f: &Foo<dyn Bar> = &f;
|
||||
let ptr2: *const u8 = &f.b as *const _ as *const u8;
|
||||
assert_eq!(f.b.get(), 11);
|
||||
|
||||
// The pointers should be the same
|
||||
assert_eq!(ptr1, ptr2);
|
||||
|
||||
// Test that nested DSTs work properly
|
||||
let f : Foo<Foo<usize>> = Foo { a: 0, b: Foo { a: 1, b: 17 }};
|
||||
let f: Foo<Foo<usize>> = Foo { a: 0, b: Foo { a: 1, b: 17 } };
|
||||
assert_eq!(f.b.b.get(), 17);
|
||||
let f : &Foo<Foo<dyn Bar>> = &f;
|
||||
let f: &Foo<Foo<dyn Bar>> = &f;
|
||||
assert_eq!(f.b.b.get(), 17);
|
||||
|
||||
// Test that get the pointer via destructuring works
|
||||
|
||||
let f : Foo<usize> = Foo { a: 0, b: 11 };
|
||||
let f : &Foo<dyn Bar> = &f;
|
||||
let f: Foo<usize> = Foo { a: 0, b: 11 };
|
||||
let f: &Foo<dyn Bar> = &f;
|
||||
let &Foo { a: _, b: ref bar } = f;
|
||||
assert_eq!(bar.get(), 11);
|
||||
|
||||
// Make sure that drop flags don't screw things up
|
||||
|
||||
let d : HasDrop<Baz<[i32; 4]>> = HasDrop {
|
||||
ptr: Box::new(0),
|
||||
data: Baz { a: [1,2,3,4] }
|
||||
};
|
||||
assert_eq!([1,2,3,4], d.data.a);
|
||||
let d: HasDrop<Baz<[i32; 4]>> = HasDrop { ptr: Box::new(0), data: Baz { a: [1, 2, 3, 4] } };
|
||||
assert_eq!([1, 2, 3, 4], d.data.a);
|
||||
|
||||
let d : &HasDrop<Baz<[i32]>> = &d;
|
||||
assert_eq!(&[1,2,3,4], &d.data.a);
|
||||
let d: &HasDrop<Baz<[i32]>> = &d;
|
||||
assert_eq!(&[1, 2, 3, 4], &d.data.a);
|
||||
}
|
||||
|
@ -11,11 +11,7 @@ pub fn abc(a: u8) -> u8 {
|
||||
}
|
||||
|
||||
pub fn bcd(b: bool, a: u8) -> u8 {
|
||||
if b {
|
||||
a * 2
|
||||
} else {
|
||||
a * 3
|
||||
}
|
||||
if b { a * 2 } else { a * 3 }
|
||||
}
|
||||
|
||||
pub fn call() {
|
||||
|
@ -2,7 +2,9 @@
|
||||
|
||||
#![feature(type_alias_impl_trait)]
|
||||
|
||||
trait T { type Item; }
|
||||
trait T {
|
||||
type Item;
|
||||
}
|
||||
|
||||
type Alias<'a> = impl T<Item = &'a ()>;
|
||||
|
||||
|
@ -40,10 +40,7 @@ impl<T, const N: usize> ListImpl<T, N> {
|
||||
}
|
||||
}
|
||||
|
||||
pub static A: ListImpl<u128, 3> = ListImpl {
|
||||
len: 3,
|
||||
data: [5, 6, 7],
|
||||
};
|
||||
pub static A: ListImpl<u128, 3> = ListImpl { len: 3, data: [5, 6, 7] };
|
||||
pub static A_REF: &'static List<u128> = A.as_list();
|
||||
pub static A_TAIL_OFFSET: isize = tail_offset(A.as_list());
|
||||
|
||||
|
@ -37,13 +37,13 @@ impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*mut U> for *mut T {}
|
||||
pub trait DispatchFromDyn<T> {}
|
||||
|
||||
// &T -> &U
|
||||
impl<'a, T: ?Sized+Unsize<U>, U: ?Sized> DispatchFromDyn<&'a U> for &'a T {}
|
||||
impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<&'a U> for &'a T {}
|
||||
// &mut T -> &mut U
|
||||
impl<'a, T: ?Sized+Unsize<U>, U: ?Sized> DispatchFromDyn<&'a mut U> for &'a mut T {}
|
||||
impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<&'a mut U> for &'a mut T {}
|
||||
// *const T -> *const U
|
||||
impl<T: ?Sized+Unsize<U>, U: ?Sized> DispatchFromDyn<*const U> for *const T {}
|
||||
impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<*const U> for *const T {}
|
||||
// *mut T -> *mut U
|
||||
impl<T: ?Sized+Unsize<U>, U: ?Sized> DispatchFromDyn<*mut U> for *mut T {}
|
||||
impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<*mut U> for *mut T {}
|
||||
impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<Box<U>> for Box<T> {}
|
||||
|
||||
#[lang = "receiver"]
|
||||
@ -288,7 +288,6 @@ impl PartialEq for u32 {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl PartialEq for u64 {
|
||||
fn eq(&self, other: &u64) -> bool {
|
||||
(*self) == (*other)
|
||||
@ -361,7 +360,7 @@ impl<T: ?Sized> PartialEq for *const T {
|
||||
}
|
||||
}
|
||||
|
||||
impl <T: PartialEq> PartialEq for Option<T> {
|
||||
impl<T: PartialEq> PartialEq for Option<T> {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
match (self, other) {
|
||||
(Some(lhs), Some(rhs)) => *lhs == *rhs,
|
||||
@ -472,7 +471,20 @@ pub fn panic(_msg: &'static str) -> ! {
|
||||
#[track_caller]
|
||||
fn panic_bounds_check(index: usize, len: usize) -> ! {
|
||||
unsafe {
|
||||
libc::printf("index out of bounds: the len is %d but the index is %d\n\0" as *const str as *const i8, len, index);
|
||||
libc::printf(
|
||||
"index out of bounds: the len is %d but the index is %d\n\0" as *const str as *const i8,
|
||||
len,
|
||||
index,
|
||||
);
|
||||
intrinsics::abort();
|
||||
}
|
||||
}
|
||||
|
||||
#[lang = "panic_cannot_unwind"]
|
||||
#[track_caller]
|
||||
fn panic_cannot_unwind() -> ! {
|
||||
unsafe {
|
||||
libc::puts("panic in a function that cannot unwind\n\0" as *const str as *const i8);
|
||||
intrinsics::abort();
|
||||
}
|
||||
}
|
||||
@ -599,7 +611,7 @@ pub mod libc {
|
||||
// functions. legacy_stdio_definitions.lib which provides the printf wrapper functions as normal
|
||||
// symbols to link against.
|
||||
#[cfg_attr(unix, link(name = "c"))]
|
||||
#[cfg_attr(target_env="msvc", link(name="legacy_stdio_definitions"))]
|
||||
#[cfg_attr(target_env = "msvc", link(name = "legacy_stdio_definitions"))]
|
||||
extern "C" {
|
||||
pub fn printf(format: *const i8, ...) -> i32;
|
||||
}
|
||||
@ -638,7 +650,7 @@ impl<T> Index<usize> for [T] {
|
||||
}
|
||||
}
|
||||
|
||||
extern {
|
||||
extern "C" {
|
||||
type VaListImpl;
|
||||
}
|
||||
|
||||
@ -648,23 +660,33 @@ pub struct VaList<'a>(&'a mut VaListImpl);
|
||||
|
||||
#[rustc_builtin_macro]
|
||||
#[rustc_macro_transparency = "semitransparent"]
|
||||
pub macro stringify($($t:tt)*) { /* compiler built-in */ }
|
||||
pub macro stringify($($t:tt)*) {
|
||||
/* compiler built-in */
|
||||
}
|
||||
|
||||
#[rustc_builtin_macro]
|
||||
#[rustc_macro_transparency = "semitransparent"]
|
||||
pub macro file() { /* compiler built-in */ }
|
||||
pub macro file() {
|
||||
/* compiler built-in */
|
||||
}
|
||||
|
||||
#[rustc_builtin_macro]
|
||||
#[rustc_macro_transparency = "semitransparent"]
|
||||
pub macro line() { /* compiler built-in */ }
|
||||
pub macro line() {
|
||||
/* compiler built-in */
|
||||
}
|
||||
|
||||
#[rustc_builtin_macro]
|
||||
#[rustc_macro_transparency = "semitransparent"]
|
||||
pub macro cfg() { /* compiler built-in */ }
|
||||
pub macro cfg() {
|
||||
/* compiler built-in */
|
||||
}
|
||||
|
||||
#[rustc_builtin_macro]
|
||||
#[rustc_macro_transparency = "semitransparent"]
|
||||
pub macro global_asm() { /* compiler built-in */ }
|
||||
pub macro global_asm() {
|
||||
/* compiler built-in */
|
||||
}
|
||||
|
||||
pub static A_STATIC: u8 = 42;
|
||||
|
||||
@ -676,7 +698,7 @@ struct PanicLocation {
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
#[cfg(not(windows))]
|
||||
#[cfg(not(all(windows, target_env = "gnu")))]
|
||||
pub fn get_tls() -> u8 {
|
||||
#[thread_local]
|
||||
static A: u8 = 42;
|
||||
|
@ -319,7 +319,7 @@ fn main() {
|
||||
|
||||
from_decimal_string();
|
||||
|
||||
#[cfg(not(any(jit, windows)))]
|
||||
#[cfg(all(not(jit), not(all(windows, target_env = "gnu"))))]
|
||||
test_tls();
|
||||
|
||||
#[cfg(all(not(jit), target_arch = "x86_64", any(target_os = "linux", target_os = "darwin")))]
|
||||
@ -524,6 +524,7 @@ pub enum E1 {
|
||||
// Computing the discriminant used to be done using the niche type (here `u8`,
|
||||
// from the `bool` field of `V1`), overflowing for variants with large enough
|
||||
// indices (`V3` and `V4`), causing them to be interpreted as other variants.
|
||||
#[rustfmt::skip]
|
||||
pub enum E2<X> {
|
||||
V1 { f: bool },
|
||||
|
||||
|
@ -3,15 +3,15 @@
|
||||
|
||||
#[cfg_attr(unix, link(name = "c"))]
|
||||
#[cfg_attr(target_env = "msvc", link(name = "msvcrt"))]
|
||||
extern {}
|
||||
extern "C" {}
|
||||
|
||||
#[panic_handler]
|
||||
fn panic_handler(_: &core::panic::PanicInfo) -> ! {
|
||||
fn panic_handler(_: &core::panic::PanicInfo<'_>) -> ! {
|
||||
core::intrinsics::abort();
|
||||
}
|
||||
|
||||
#[lang="eh_personality"]
|
||||
fn eh_personality(){}
|
||||
#[lang = "eh_personality"]
|
||||
fn eh_personality() {}
|
||||
|
||||
// Required for rustc_codegen_llvm
|
||||
#[no_mangle]
|
||||
|
@ -1,4 +1,4 @@
|
||||
#![feature(core_intrinsics, generators, generator_trait, is_sorted)]
|
||||
#![feature(core_intrinsics, generators, generator_trait, is_sorted, repr_simd)]
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
use std::arch::x86_64::*;
|
||||
@ -56,7 +56,10 @@ fn main() {
|
||||
|
||||
assert_eq!(0b0000000000000000000000000010000010000000000000000000000000000000_0000000000100000000000000000000000001000000000000100000000000000u128.leading_zeros(), 26);
|
||||
assert_eq!(0b0000000000000000000000000010000000000000000000000000000000000000_0000000000000000000000000000000000001000000000000000000010000000u128.trailing_zeros(), 7);
|
||||
assert_eq!(core::intrinsics::saturating_sub(0, -170141183460469231731687303715884105728i128), 170141183460469231731687303715884105727i128);
|
||||
assert_eq!(
|
||||
core::intrinsics::saturating_sub(0, -170141183460469231731687303715884105728i128),
|
||||
170141183460469231731687303715884105727i128
|
||||
);
|
||||
|
||||
std::hint::black_box(std::hint::black_box(7571400400375753350092698930310845914i128) * 10);
|
||||
assert!(0i128.checked_div(2i128).is_some());
|
||||
@ -113,7 +116,9 @@ fn main() {
|
||||
|
||||
Box::pin(move |mut _task_context| {
|
||||
yield ();
|
||||
}).as_mut().resume(0);
|
||||
})
|
||||
.as_mut()
|
||||
.resume(0);
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
enum Nums {
|
||||
@ -148,12 +153,20 @@ fn main() {
|
||||
|
||||
enum Never {}
|
||||
}
|
||||
|
||||
foo(I64X2(0, 0));
|
||||
}
|
||||
|
||||
fn panic(_: u128) {
|
||||
panic!();
|
||||
}
|
||||
|
||||
#[repr(simd)]
|
||||
struct I64X2(i64, i64);
|
||||
|
||||
#[allow(improper_ctypes_definitions)]
|
||||
extern "C" fn foo(_a: I64X2) {}
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
#[target_feature(enable = "sse2")]
|
||||
unsafe fn test_simd() {
|
||||
@ -168,7 +181,10 @@ unsafe fn test_simd() {
|
||||
let (zero0, zero1) = std::mem::transmute::<_, (u64, u64)>(x);
|
||||
assert_eq!((zero0, zero1), (0, 0));
|
||||
assert_eq!(std::mem::transmute::<_, [u16; 8]>(or), [7, 7, 7, 7, 7, 7, 7, 7]);
|
||||
assert_eq!(std::mem::transmute::<_, [u16; 8]>(cmp_eq), [0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff]);
|
||||
assert_eq!(
|
||||
std::mem::transmute::<_, [u16; 8]>(cmp_eq),
|
||||
[0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff]
|
||||
);
|
||||
assert_eq!(std::mem::transmute::<_, [u16; 8]>(cmp_lt), [0, 0, 0, 0, 0, 0, 0, 0]);
|
||||
|
||||
test_mm_slli_si128();
|
||||
@ -182,6 +198,7 @@ unsafe fn test_simd() {
|
||||
test_mm_extract_epi8();
|
||||
test_mm_insert_epi16();
|
||||
|
||||
#[rustfmt::skip]
|
||||
let mask1 = _mm_movemask_epi8(dbg!(_mm_setr_epi8(255u8 as i8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)));
|
||||
assert_eq!(mask1, 1);
|
||||
}
|
||||
@ -343,7 +360,7 @@ fn test_checked_mul() {
|
||||
#[derive(PartialEq)]
|
||||
enum LoopState {
|
||||
Continue(()),
|
||||
Break(())
|
||||
Break(()),
|
||||
}
|
||||
|
||||
pub enum Instruction {
|
||||
|
@ -19,7 +19,9 @@ macro_rules! n {
|
||||
// This macro has an unused variable so that it can be repeated base on the
|
||||
// number of times a repeated variable (`$e` in `z`) occurs.
|
||||
macro_rules! zed {
|
||||
($e:expr) => { Z }
|
||||
($e:expr) => {
|
||||
Z
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! z {
|
||||
@ -32,12 +34,14 @@ macro_rules! z {
|
||||
macro_rules! compare_evaluation {
|
||||
($e:expr, $t:ty $(,)?) => {{
|
||||
const CONST_EVAL: $t = $e;
|
||||
const fn const_eval() -> $t { $e }
|
||||
const fn const_eval() -> $t {
|
||||
$e
|
||||
}
|
||||
static CONST_EVAL2: $t = const_eval();
|
||||
let runtime_eval = $e;
|
||||
assert_eq!(CONST_EVAL, runtime_eval);
|
||||
assert_eq!(CONST_EVAL2, runtime_eval);
|
||||
}}
|
||||
}};
|
||||
}
|
||||
|
||||
// Repeat `$test`, substituting the given macro variables with the given
|
||||
@ -65,6 +69,7 @@ macro_rules! repeat {
|
||||
}
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
fn main() {
|
||||
repeat! {
|
||||
($arr $Ty); n, N; z, Z:
|
||||
|
@ -1,3 +1,3 @@
|
||||
[toolchain]
|
||||
channel = "nightly-2023-03-15"
|
||||
channel = "nightly-2023-04-29"
|
||||
components = ["rust-src", "rustc-dev", "llvm-tools-preview"]
|
||||
|
@ -64,7 +64,7 @@ fn main() {
|
||||
};
|
||||
|
||||
#[cfg(unix)]
|
||||
Command::new("cargo").args(args).exec();
|
||||
panic!("Failed to spawn cargo: {}", Command::new("cargo").args(args).exec());
|
||||
|
||||
#[cfg(not(unix))]
|
||||
std::process::exit(
|
||||
|
@ -15,22 +15,24 @@ fn main() {
|
||||
env::consts::DLL_PREFIX.to_string() + "rustc_codegen_cranelift" + env::consts::DLL_SUFFIX,
|
||||
);
|
||||
|
||||
let mut args = std::env::args_os().skip(1).collect::<Vec<_>>();
|
||||
let passed_args = std::env::args_os().skip(1).collect::<Vec<_>>();
|
||||
let mut args = vec![];
|
||||
args.push(OsString::from("-Cpanic=abort"));
|
||||
args.push(OsString::from("-Zpanic-abort-tests"));
|
||||
let mut codegen_backend_arg = OsString::from("-Zcodegen-backend=");
|
||||
codegen_backend_arg.push(cg_clif_dylib_path);
|
||||
args.push(codegen_backend_arg);
|
||||
if !args.contains(&OsString::from("--sysroot")) {
|
||||
if !passed_args.contains(&OsString::from("--sysroot")) {
|
||||
args.push(OsString::from("--sysroot"));
|
||||
args.push(OsString::from(sysroot.to_str().unwrap()));
|
||||
}
|
||||
args.extend(passed_args);
|
||||
|
||||
// Ensure that the right toolchain is used
|
||||
env::set_var("RUSTUP_TOOLCHAIN", env!("TOOLCHAIN_NAME"));
|
||||
|
||||
#[cfg(unix)]
|
||||
Command::new("rustc").args(args).exec();
|
||||
panic!("Failed to spawn rustc: {}", Command::new("rustc").args(args).exec());
|
||||
|
||||
#[cfg(not(unix))]
|
||||
std::process::exit(
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user