Merge from rustc

This commit is contained in:
Ralf Jung 2023-04-30 22:35:29 +02:00
commit 697d130844
2531 changed files with 30229 additions and 19084 deletions

View File

@ -20,3 +20,6 @@ trim_trailing_whitespace = false
[*.yml]
indent_size = 2
[Makefile]
indent_style = tab

View File

@ -12,3 +12,5 @@ a06baa56b95674fc626b3c3fd680d6a65357fe60
c34fbfaad38cf5829ef5cfe780dc9d58480adeaa
# move tests
cf2dff2b1e3fa55fa5415d524200070d0d7aacfe
# Run rustfmt on bootstrap
b39a1d6f1a30ba29f25d7141038b9a5bf0126e36

View File

@ -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

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -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' }

View File

@ -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

View File

@ -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]

View File

@ -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
}

View File

@ -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));
}

View File

@ -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;
}
}

View File

@ -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",

View File

@ -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)
}
}

View File

@ -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)]

View File

@ -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();

View File

@ -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.

View File

@ -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() }
}

View File

@ -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

View File

@ -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);
}

View File

@ -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" }

View File

@ -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(

View File

@ -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),
// …
// ]
// }

View File

@ -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;

View File

@ -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")

View File

@ -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);
}
}

View File

@ -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" }

View File

@ -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}

View File

@ -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]

View File

@ -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;

View File

@ -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 {

View File

@ -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();

View File

@ -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" }

View File

@ -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;

View File

@ -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" }

View File

@ -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

View File

@ -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,

View File

@ -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;

View File

@ -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;

View File

@ -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()

View File

@ -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,

View File

@ -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: &note_msg,
span,
});
} else {
None
err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Note {
is_partial_move,
ty,
place: &note_msg,
});
};
self.note_type_does_not_implement_copy(&mut err, &note_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,

View File

@ -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,

View File

@ -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 },
})
}
}
}

View File

@ -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,
});
}
}

View File

@ -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)

View File

@ -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];

View File

@ -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()
}
}

View File

@ -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(..)

View File

@ -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);
}
}
}

View File

@ -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 {

View File

@ -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 => {

View File

@ -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: _,

View File

@ -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};

View File

@ -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;

View File

@ -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;

View File

@ -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 },
}

View File

@ -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;

View File

@ -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};

View File

@ -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(..), _) => {}
}
}

View File

@ -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]))
}

View File

@ -0,0 +1,3 @@
mod collect_writes;
pub use collect_writes::FindAssignments;

View File

@ -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" }

View File

@ -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

View File

@ -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;
}

View File

@ -301,6 +301,7 @@ impl<'cx, 'a> Context<'cx, 'a> {
| ExprKind::If(_, _, _)
| ExprKind::IncludedBytes(..)
| ExprKind::InlineAsm(_)
| ExprKind::OffsetOf(_, _)
| ExprKind::Let(_, _, _)
| ExprKind::Lit(_)
| ExprKind::Loop(_, _, _)

View File

@ -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,
}

View File

@ -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(),
});

View File

@ -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,

View 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)
}
}
}

View File

@ -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;
}

View File

@ -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

View 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.

View 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'

View 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);
});

View 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=="
}
}
}

View 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"
}
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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"

View File

@ -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 }

View File

@ -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

View File

@ -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",

View File

@ -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");
}

View File

@ -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(&REGEX_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

View File

@ -18,7 +18,7 @@ extern "C" {
}
#[panic_handler]
fn panic_handler(_: &core::panic::PanicInfo) -> ! {
fn panic_handler(_: &core::panic::PanicInfo<'_>) -> ! {
core::intrinsics::abort();
}

View File

@ -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.

View File

@ -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);
}

View File

@ -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() {

View File

@ -2,7 +2,9 @@
#![feature(type_alias_impl_trait)]
trait T { type Item; }
trait T {
type Item;
}
type Alias<'a> = impl T<Item = &'a ()>;

View File

@ -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());

View File

@ -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;

View File

@ -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 },

View File

@ -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]

View File

@ -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 {

View File

@ -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:

View File

@ -1,3 +1,3 @@
[toolchain]
channel = "nightly-2023-03-15"
channel = "nightly-2023-04-29"
components = ["rust-src", "rustc-dev", "llvm-tools-preview"]

View File

@ -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(

View File

@ -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