Auto merge of #3267 - rust-lang:rustup-2024-01-14, r=saethlin
Automatic Rustup
This commit is contained in:
commit
0c8e1e6f44
837 changed files with 4241 additions and 1345 deletions
|
|
@ -18,6 +18,7 @@ Files: compiler/*
|
|||
configure
|
||||
CONTRIBUTING.md
|
||||
COPYRIGHT
|
||||
INSTALL.md
|
||||
LICENSE-APACHE
|
||||
LICENSE-MIT
|
||||
README.md
|
||||
|
|
@ -51,7 +52,7 @@ Copyright: 2019 The Crossbeam Project Developers
|
|||
The Rust Project Developers (see https://thanks.rust-lang.org)
|
||||
License: MIT OR Apache-2.0
|
||||
|
||||
Files: library/std/src/sys/unix/locks/fuchsia_mutex.rs
|
||||
Files: library/std/src/sys/pal/unix/locks/fuchsia_mutex.rs
|
||||
Copyright: 2016 The Fuchsia Authors
|
||||
The Rust Project Developers (see https://thanks.rust-lang.org)
|
||||
License: BSD-2-Clause AND (MIT OR Apache-2.0)
|
||||
|
|
|
|||
253
INSTALL.md
Normal file
253
INSTALL.md
Normal file
|
|
@ -0,0 +1,253 @@
|
|||
# Installing from Source
|
||||
|
||||
**Note: This document describes _building_ Rust _from source_.
|
||||
This is _not recommended_ if you don't know what you're doing.
|
||||
If you just want to install Rust, check out the [README.md](README.md) instead.**
|
||||
|
||||
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:
|
||||
|
||||
```sh
|
||||
./x.py <subcommand> [flags]
|
||||
```
|
||||
|
||||
This is how the documentation and examples assume you are running `x.py`.
|
||||
See the [rustc dev guide][rustcguidebuild] if this does not work on your
|
||||
platform.
|
||||
|
||||
More information about `x.py` can be found by running it with the `--help` flag
|
||||
or reading the [rustc dev guide][rustcguidebuild].
|
||||
|
||||
[gettingstarted]: https://rustc-dev-guide.rust-lang.org/getting-started.html
|
||||
[rustcguidebuild]: https://rustc-dev-guide.rust-lang.org/building/how-to-build-and-run.html#what-is-xpy
|
||||
|
||||
## Dependencies
|
||||
|
||||
Make sure you have installed the dependencies:
|
||||
|
||||
* `python` 3 or 2.7
|
||||
* `git`
|
||||
* A C compiler (when building for the host, `cc` is enough; cross-compiling may
|
||||
need additional compilers)
|
||||
* `curl` (not needed on Windows)
|
||||
* `pkg-config` if you are compiling on Linux and targeting Linux
|
||||
* `libiconv` (already included with glibc on Debian-based distros)
|
||||
|
||||
To build Cargo, you'll also need OpenSSL (`libssl-dev` or `openssl-devel` on
|
||||
most Unix distros).
|
||||
|
||||
If building LLVM from source, you'll need additional tools:
|
||||
|
||||
* `g++`, `clang++`, or MSVC with versions listed on
|
||||
[LLVM's documentation](https://llvm.org/docs/GettingStarted.html#host-c-toolchain-both-compiler-and-standard-library)
|
||||
* `ninja`, or GNU `make` 3.81 or later (Ninja is recommended, especially on
|
||||
Windows)
|
||||
* `cmake` 3.13.4 or later
|
||||
* `libstdc++-static` may be required on some Linux distributions such as Fedora
|
||||
and Ubuntu
|
||||
|
||||
On tier 1 or tier 2 with host tools platforms, you can also choose to download
|
||||
LLVM by setting `llvm.download-ci-llvm = true`.
|
||||
Otherwise, you'll need LLVM installed and `llvm-config` in your path.
|
||||
See [the rustc-dev-guide for more info][sysllvm].
|
||||
|
||||
[sysllvm]: https://rustc-dev-guide.rust-lang.org/building/new-target.html#using-pre-built-llvm
|
||||
|
||||
|
||||
## Building on a Unix-like system
|
||||
|
||||
### Build steps
|
||||
|
||||
1. Clone the [source] with `git`:
|
||||
|
||||
```sh
|
||||
git clone https://github.com/rust-lang/rust.git
|
||||
cd rust
|
||||
```
|
||||
|
||||
[source]: https://github.com/rust-lang/rust
|
||||
|
||||
2. Configure the build settings:
|
||||
|
||||
```sh
|
||||
./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: `./configure --set install.prefix=<path>`
|
||||
|
||||
3. Build and install:
|
||||
|
||||
```sh
|
||||
./x.py build && ./x.py install
|
||||
```
|
||||
|
||||
When complete, `./x.py install` will place several programs into
|
||||
`$PREFIX/bin`: `rustc`, the Rust compiler, and `rustdoc`, the
|
||||
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 programmatically
|
||||
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
|
||||
following in a terminal:
|
||||
|
||||
```powershell
|
||||
winget install -e Python.Python.3
|
||||
winget install -e Kitware.CMake
|
||||
winget install -e Git.Git
|
||||
```
|
||||
|
||||
Then edit your system's `PATH` variable and add: `C:\Program Files\CMake\bin`.
|
||||
See
|
||||
[this guide on editing the system `PATH`](https://www.java.com/en/download/help/path.html)
|
||||
from the Java documentation.
|
||||
|
||||
[winget]: https://github.com/microsoft/winget-cli
|
||||
|
||||
There are two prominent ABIs in use on Windows: the native (MSVC) ABI used by
|
||||
Visual Studio and the GNU ABI used by the GCC toolchain. Which version of Rust
|
||||
you need depends largely on what C/C++ libraries you want to interoperate with.
|
||||
Use the MSVC build of Rust to interop with software produced by Visual Studio
|
||||
and the GNU build to interop with GNU software built using the MinGW/MSYS2
|
||||
toolchain.
|
||||
|
||||
### MinGW
|
||||
|
||||
[MSYS2][msys2] can be used to easily build Rust on Windows:
|
||||
|
||||
[msys2]: https://www.msys2.org/
|
||||
|
||||
1. Download the latest [MSYS2 installer][msys2] and go through the installer.
|
||||
|
||||
2. Run `mingw32_shell.bat` or `mingw64_shell.bat` from the MSYS2 installation
|
||||
directory (e.g. `C:\msys64`), depending on whether you want 32-bit or 64-bit
|
||||
Rust. (As of the latest version of MSYS2 you have to run `msys2_shell.cmd
|
||||
-mingw32` or `msys2_shell.cmd -mingw64` from the command line instead.)
|
||||
|
||||
3. From this terminal, install the required tools:
|
||||
|
||||
```sh
|
||||
# Update package mirrors (may be needed if you have a fresh install of MSYS2)
|
||||
pacman -Sy pacman-mirrors
|
||||
|
||||
# Install build tools needed for Rust. If you're building a 32-bit compiler,
|
||||
# then replace "x86_64" below with "i686". If you've already got Git, Python,
|
||||
# or CMake installed and in PATH you can remove them from this list.
|
||||
# Note that it is important that you do **not** use the 'python2', 'cmake',
|
||||
# and 'ninja' packages from the 'msys2' subsystem.
|
||||
# The build has historically been known to fail with these packages.
|
||||
pacman -S git \
|
||||
make \
|
||||
diffutils \
|
||||
tar \
|
||||
mingw-w64-x86_64-python \
|
||||
mingw-w64-x86_64-cmake \
|
||||
mingw-w64-x86_64-gcc \
|
||||
mingw-w64-x86_64-ninja
|
||||
```
|
||||
|
||||
4. Navigate to Rust's source code (or clone it), then build it:
|
||||
|
||||
```sh
|
||||
python x.py setup user && python x.py build && python x.py install
|
||||
```
|
||||
|
||||
### MSVC
|
||||
|
||||
MSVC builds of Rust additionally require an installation of Visual Studio 2017
|
||||
(or later) so `rustc` can use its linker. The simplest way is to get
|
||||
[Visual Studio], check the "C++ build tools" and "Windows 10 SDK" workload.
|
||||
|
||||
[Visual Studio]: https://visualstudio.microsoft.com/downloads/
|
||||
|
||||
(If you're installing CMake yourself, be careful that "C++ CMake tools for
|
||||
Windows" doesn't get included under "Individual components".)
|
||||
|
||||
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
|
||||
```
|
||||
|
||||
Right now, building Rust only works with some known versions of Visual Studio.
|
||||
If you have a more recent version installed and the build system doesn't
|
||||
understand, you may need to force rustbuild to use an older version.
|
||||
This can be done by manually calling the appropriate vcvars file before running
|
||||
the bootstrap.
|
||||
|
||||
```batch
|
||||
CALL "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat"
|
||||
python x.py build
|
||||
```
|
||||
|
||||
### Specifying an ABI
|
||||
|
||||
Each specific ABI can also be used from either environment (for example, using
|
||||
the GNU ABI in PowerShell) by using an explicit build triple. The available
|
||||
Windows build triples are:
|
||||
- GNU ABI (using GCC)
|
||||
- `i686-pc-windows-gnu`
|
||||
- `x86_64-pc-windows-gnu`
|
||||
- The MSVC ABI
|
||||
- `i686-pc-windows-msvc`
|
||||
- `x86_64-pc-windows-msvc`
|
||||
|
||||
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
|
||||
[Building on a Unix-like system](#building-on-a-unix-like-system)), and passing
|
||||
`--set build.build=<triple>` to `./configure`.
|
||||
|
||||
## Building Documentation
|
||||
|
||||
If you'd like to build the documentation, it's almost the same:
|
||||
|
||||
```sh
|
||||
./x.py doc
|
||||
```
|
||||
|
||||
The generated documentation will appear under `doc` in the `build` directory for
|
||||
the ABI used. That is, if the ABI was `x86_64-pc-windows-msvc`, the directory
|
||||
will be `build\x86_64-pc-windows-msvc\doc`.
|
||||
|
||||
## Notes
|
||||
|
||||
Since the Rust compiler is written in Rust, it must be built by a precompiled
|
||||
"snapshot" version of itself (made in an earlier stage of development).
|
||||
As such, source builds require an Internet connection to fetch snapshots, and an
|
||||
OS that can execute the available snapshot binaries.
|
||||
|
||||
See https://doc.rust-lang.org/nightly/rustc/platform-support.html for a list of
|
||||
supported platforms.
|
||||
Only "host tools" platforms have a pre-compiled snapshot binary available; to
|
||||
compile for a platform without host tools you must cross-compile.
|
||||
|
||||
You may find that other platforms work, but these are our officially supported
|
||||
build environments that are most likely to work.
|
||||
253
README.md
253
README.md
|
|
@ -15,9 +15,6 @@ If you wish to _contribute_ to the compiler, you should read
|
|||
<summary>Table of Contents</summary>
|
||||
|
||||
- [Quick Start](#quick-start)
|
||||
- [Installing from Source](#installing-from-source)
|
||||
- [Building Documentation](#building-documentation)
|
||||
- [Notes](#notes)
|
||||
- [Getting Help](#getting-help)
|
||||
- [Contributing](#contributing)
|
||||
- [License](#license)
|
||||
|
|
@ -32,255 +29,9 @@ Read ["Installation"] from [The Book].
|
|||
["Installation"]: https://doc.rust-lang.org/book/ch01-01-installation.html
|
||||
[The Book]: https://doc.rust-lang.org/book/index.html
|
||||
|
||||
## Installing from Source
|
||||
## Installing from source
|
||||
|
||||
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:
|
||||
|
||||
```sh
|
||||
./x.py <subcommand> [flags]
|
||||
```
|
||||
|
||||
This is how the documentation and examples assume you are running `x.py`.
|
||||
See the [rustc dev guide][rustcguidebuild] if this does not work on your
|
||||
platform.
|
||||
|
||||
More information about `x.py` can be found by running it with the `--help` flag
|
||||
or reading the [rustc dev guide][rustcguidebuild].
|
||||
|
||||
[gettingstarted]: https://rustc-dev-guide.rust-lang.org/getting-started.html
|
||||
[rustcguidebuild]: https://rustc-dev-guide.rust-lang.org/building/how-to-build-and-run.html#what-is-xpy
|
||||
|
||||
### Dependencies
|
||||
|
||||
Make sure you have installed the dependencies:
|
||||
|
||||
* `python` 3 or 2.7
|
||||
* `git`
|
||||
* A C compiler (when building for the host, `cc` is enough; cross-compiling may
|
||||
need additional compilers)
|
||||
* `curl` (not needed on Windows)
|
||||
* `pkg-config` if you are compiling on Linux and targeting Linux
|
||||
* `libiconv` (already included with glibc on Debian-based distros)
|
||||
|
||||
To build Cargo, you'll also need OpenSSL (`libssl-dev` or `openssl-devel` on
|
||||
most Unix distros).
|
||||
|
||||
If building LLVM from source, you'll need additional tools:
|
||||
|
||||
* `g++`, `clang++`, or MSVC with versions listed on
|
||||
[LLVM's documentation](https://llvm.org/docs/GettingStarted.html#host-c-toolchain-both-compiler-and-standard-library)
|
||||
* `ninja`, or GNU `make` 3.81 or later (Ninja is recommended, especially on
|
||||
Windows)
|
||||
* `cmake` 3.13.4 or later
|
||||
* `libstdc++-static` may be required on some Linux distributions such as Fedora
|
||||
and Ubuntu
|
||||
|
||||
On tier 1 or tier 2 with host tools platforms, you can also choose to download
|
||||
LLVM by setting `llvm.download-ci-llvm = true`.
|
||||
Otherwise, you'll need LLVM installed and `llvm-config` in your path.
|
||||
See [the rustc-dev-guide for more info][sysllvm].
|
||||
|
||||
[sysllvm]: https://rustc-dev-guide.rust-lang.org/building/new-target.html#using-pre-built-llvm
|
||||
|
||||
|
||||
### Building on a Unix-like system
|
||||
|
||||
#### Build steps
|
||||
|
||||
1. Clone the [source] with `git`:
|
||||
|
||||
```sh
|
||||
git clone https://github.com/rust-lang/rust.git
|
||||
cd rust
|
||||
```
|
||||
|
||||
[source]: https://github.com/rust-lang/rust
|
||||
|
||||
2. Configure the build settings:
|
||||
|
||||
```sh
|
||||
./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: `./configure --set install.prefix=<path>`
|
||||
|
||||
3. Build and install:
|
||||
|
||||
```sh
|
||||
./x.py build && ./x.py install
|
||||
```
|
||||
|
||||
When complete, `./x.py install` will place several programs into
|
||||
`$PREFIX/bin`: `rustc`, the Rust compiler, and `rustdoc`, the
|
||||
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 programmatically
|
||||
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
|
||||
following in a terminal:
|
||||
|
||||
```powershell
|
||||
winget install -e Python.Python.3
|
||||
winget install -e Kitware.CMake
|
||||
winget install -e Git.Git
|
||||
```
|
||||
|
||||
Then edit your system's `PATH` variable and add: `C:\Program Files\CMake\bin`.
|
||||
See
|
||||
[this guide on editing the system `PATH`](https://www.java.com/en/download/help/path.html)
|
||||
from the Java documentation.
|
||||
|
||||
[winget]: https://github.com/microsoft/winget-cli
|
||||
|
||||
There are two prominent ABIs in use on Windows: the native (MSVC) ABI used by
|
||||
Visual Studio and the GNU ABI used by the GCC toolchain. Which version of Rust
|
||||
you need depends largely on what C/C++ libraries you want to interoperate with.
|
||||
Use the MSVC build of Rust to interop with software produced by Visual Studio
|
||||
and the GNU build to interop with GNU software built using the MinGW/MSYS2
|
||||
toolchain.
|
||||
|
||||
#### MinGW
|
||||
|
||||
[MSYS2][msys2] can be used to easily build Rust on Windows:
|
||||
|
||||
[msys2]: https://www.msys2.org/
|
||||
|
||||
1. Download the latest [MSYS2 installer][msys2] and go through the installer.
|
||||
|
||||
2. Run `mingw32_shell.bat` or `mingw64_shell.bat` from the MSYS2 installation
|
||||
directory (e.g. `C:\msys64`), depending on whether you want 32-bit or 64-bit
|
||||
Rust. (As of the latest version of MSYS2 you have to run `msys2_shell.cmd
|
||||
-mingw32` or `msys2_shell.cmd -mingw64` from the command line instead.)
|
||||
|
||||
3. From this terminal, install the required tools:
|
||||
|
||||
```sh
|
||||
# Update package mirrors (may be needed if you have a fresh install of MSYS2)
|
||||
pacman -Sy pacman-mirrors
|
||||
|
||||
# Install build tools needed for Rust. If you're building a 32-bit compiler,
|
||||
# then replace "x86_64" below with "i686". If you've already got Git, Python,
|
||||
# or CMake installed and in PATH you can remove them from this list.
|
||||
# Note that it is important that you do **not** use the 'python2', 'cmake',
|
||||
# and 'ninja' packages from the 'msys2' subsystem.
|
||||
# The build has historically been known to fail with these packages.
|
||||
pacman -S git \
|
||||
make \
|
||||
diffutils \
|
||||
tar \
|
||||
mingw-w64-x86_64-python \
|
||||
mingw-w64-x86_64-cmake \
|
||||
mingw-w64-x86_64-gcc \
|
||||
mingw-w64-x86_64-ninja
|
||||
```
|
||||
|
||||
4. Navigate to Rust's source code (or clone it), then build it:
|
||||
|
||||
```sh
|
||||
python x.py setup user && python x.py build && python x.py install
|
||||
```
|
||||
|
||||
#### MSVC
|
||||
|
||||
MSVC builds of Rust additionally require an installation of Visual Studio 2017
|
||||
(or later) so `rustc` can use its linker. The simplest way is to get
|
||||
[Visual Studio], check the "C++ build tools" and "Windows 10 SDK" workload.
|
||||
|
||||
[Visual Studio]: https://visualstudio.microsoft.com/downloads/
|
||||
|
||||
(If you're installing CMake yourself, be careful that "C++ CMake tools for
|
||||
Windows" doesn't get included under "Individual components".)
|
||||
|
||||
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
|
||||
```
|
||||
|
||||
Right now, building Rust only works with some known versions of Visual Studio.
|
||||
If you have a more recent version installed and the build system doesn't
|
||||
understand, you may need to force rustbuild to use an older version.
|
||||
This can be done by manually calling the appropriate vcvars file before running
|
||||
the bootstrap.
|
||||
|
||||
```batch
|
||||
CALL "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat"
|
||||
python x.py build
|
||||
```
|
||||
|
||||
#### Specifying an ABI
|
||||
|
||||
Each specific ABI can also be used from either environment (for example, using
|
||||
the GNU ABI in PowerShell) by using an explicit build triple. The available
|
||||
Windows build triples are:
|
||||
- GNU ABI (using GCC)
|
||||
- `i686-pc-windows-gnu`
|
||||
- `x86_64-pc-windows-gnu`
|
||||
- The MSVC ABI
|
||||
- `i686-pc-windows-msvc`
|
||||
- `x86_64-pc-windows-msvc`
|
||||
|
||||
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
|
||||
[Building on a Unix-like system](#building-on-a-unix-like-system)), and passing
|
||||
`--set build.build=<triple>` to `./configure`.
|
||||
|
||||
## Building Documentation
|
||||
|
||||
If you'd like to build the documentation, it's almost the same:
|
||||
|
||||
```sh
|
||||
./x.py doc
|
||||
```
|
||||
|
||||
The generated documentation will appear under `doc` in the `build` directory for
|
||||
the ABI used. That is, if the ABI was `x86_64-pc-windows-msvc`, the directory
|
||||
will be `build\x86_64-pc-windows-msvc\doc`.
|
||||
|
||||
## Notes
|
||||
|
||||
Since the Rust compiler is written in Rust, it must be built by a precompiled
|
||||
"snapshot" version of itself (made in an earlier stage of development).
|
||||
As such, source builds require an Internet connection to fetch snapshots, and an
|
||||
OS that can execute the available snapshot binaries.
|
||||
|
||||
See https://doc.rust-lang.org/nightly/rustc/platform-support.html for a list of
|
||||
supported platforms.
|
||||
Only "host tools" platforms have a pre-compiled snapshot binary available; to
|
||||
compile for a platform without host tools you must cross-compile.
|
||||
|
||||
You may find that other platforms work, but these are our officially supported
|
||||
build environments that are most likely to work.
|
||||
If you really want to install from source (though this is not recommended), see [INSTALL.md](INSTALL.md).
|
||||
|
||||
## Getting Help
|
||||
|
||||
|
|
|
|||
|
|
@ -2873,6 +2873,7 @@ impl Item {
|
|||
| ItemKind::ForeignMod(_)
|
||||
| ItemKind::GlobalAsm(_)
|
||||
| ItemKind::MacCall(_)
|
||||
| ItemKind::Delegation(_)
|
||||
| ItemKind::MacroDef(_) => None,
|
||||
ItemKind::Static(_) => None,
|
||||
ItemKind::Const(i) => Some(&i.generics),
|
||||
|
|
@ -3019,6 +3020,15 @@ pub struct Fn {
|
|||
pub body: Option<P<Block>>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Encodable, Decodable, Debug)]
|
||||
pub struct Delegation {
|
||||
/// Path resolution id.
|
||||
pub id: NodeId,
|
||||
pub qself: Option<P<QSelf>>,
|
||||
pub path: Path,
|
||||
pub body: Option<P<Block>>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Encodable, Decodable, Debug)]
|
||||
pub struct StaticItem {
|
||||
pub ty: P<Ty>,
|
||||
|
|
@ -3104,6 +3114,11 @@ pub enum ItemKind {
|
|||
|
||||
/// A macro definition.
|
||||
MacroDef(MacroDef),
|
||||
|
||||
/// A delegation item (`reuse`).
|
||||
///
|
||||
/// E.g. `reuse <Type as Trait>::name { target_expr_template }`.
|
||||
Delegation(Box<Delegation>),
|
||||
}
|
||||
|
||||
impl ItemKind {
|
||||
|
|
@ -3111,7 +3126,8 @@ impl ItemKind {
|
|||
use ItemKind::*;
|
||||
match self {
|
||||
Use(..) | Static(..) | Const(..) | Fn(..) | Mod(..) | GlobalAsm(..) | TyAlias(..)
|
||||
| Struct(..) | Union(..) | Trait(..) | TraitAlias(..) | MacroDef(..) => "a",
|
||||
| Struct(..) | Union(..) | Trait(..) | TraitAlias(..) | MacroDef(..)
|
||||
| Delegation(..) => "a",
|
||||
ExternCrate(..) | ForeignMod(..) | MacCall(..) | Enum(..) | Impl { .. } => "an",
|
||||
}
|
||||
}
|
||||
|
|
@ -3135,6 +3151,7 @@ impl ItemKind {
|
|||
ItemKind::MacCall(..) => "item macro invocation",
|
||||
ItemKind::MacroDef(..) => "macro definition",
|
||||
ItemKind::Impl { .. } => "implementation",
|
||||
ItemKind::Delegation(..) => "delegated function",
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -3176,6 +3193,8 @@ pub enum AssocItemKind {
|
|||
Type(Box<TyAlias>),
|
||||
/// A macro expanding to associated items.
|
||||
MacCall(P<MacCall>),
|
||||
/// An associated delegation item.
|
||||
Delegation(Box<Delegation>),
|
||||
}
|
||||
|
||||
impl AssocItemKind {
|
||||
|
|
@ -3184,7 +3203,7 @@ impl AssocItemKind {
|
|||
Self::Const(box ConstItem { defaultness, .. })
|
||||
| Self::Fn(box Fn { defaultness, .. })
|
||||
| Self::Type(box TyAlias { defaultness, .. }) => defaultness,
|
||||
Self::MacCall(..) => Defaultness::Final,
|
||||
Self::MacCall(..) | Self::Delegation(..) => Defaultness::Final,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3196,6 +3215,7 @@ impl From<AssocItemKind> for ItemKind {
|
|||
AssocItemKind::Fn(fn_kind) => ItemKind::Fn(fn_kind),
|
||||
AssocItemKind::Type(ty_alias_kind) => ItemKind::TyAlias(ty_alias_kind),
|
||||
AssocItemKind::MacCall(a) => ItemKind::MacCall(a),
|
||||
AssocItemKind::Delegation(delegation) => ItemKind::Delegation(delegation),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3209,6 +3229,7 @@ impl TryFrom<ItemKind> for AssocItemKind {
|
|||
ItemKind::Fn(fn_kind) => AssocItemKind::Fn(fn_kind),
|
||||
ItemKind::TyAlias(ty_kind) => AssocItemKind::Type(ty_kind),
|
||||
ItemKind::MacCall(a) => AssocItemKind::MacCall(a),
|
||||
ItemKind::Delegation(d) => AssocItemKind::Delegation(d),
|
||||
_ => return Err(item_kind),
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1117,6 +1117,14 @@ pub fn noop_visit_item_kind<T: MutVisitor>(kind: &mut ItemKind, vis: &mut T) {
|
|||
}
|
||||
ItemKind::MacCall(m) => vis.visit_mac_call(m),
|
||||
ItemKind::MacroDef(def) => vis.visit_macro_def(def),
|
||||
ItemKind::Delegation(box Delegation { id, qself, path, body }) => {
|
||||
vis.visit_id(id);
|
||||
vis.visit_qself(qself);
|
||||
vis.visit_path(path);
|
||||
if let Some(body) = body {
|
||||
vis.visit_block(body);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1155,6 +1163,14 @@ pub fn noop_flat_map_assoc_item<T: MutVisitor>(
|
|||
visit_opt(ty, |ty| visitor.visit_ty(ty));
|
||||
}
|
||||
AssocItemKind::MacCall(mac) => visitor.visit_mac_call(mac),
|
||||
AssocItemKind::Delegation(box Delegation { id, qself, path, body }) => {
|
||||
visitor.visit_id(id);
|
||||
visitor.visit_qself(qself);
|
||||
visitor.visit_path(path);
|
||||
if let Some(body) = body {
|
||||
visitor.visit_block(body);
|
||||
}
|
||||
}
|
||||
}
|
||||
visitor.visit_span(span);
|
||||
visit_lazy_tts(tokens, visitor);
|
||||
|
|
|
|||
|
|
@ -375,6 +375,15 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) {
|
|||
}
|
||||
ItemKind::MacCall(mac) => visitor.visit_mac_call(mac),
|
||||
ItemKind::MacroDef(ts) => visitor.visit_mac_def(ts, item.id),
|
||||
ItemKind::Delegation(box Delegation { id: _, qself, path, body }) => {
|
||||
if let Some(qself) = qself {
|
||||
visitor.visit_ty(&qself.ty);
|
||||
}
|
||||
walk_path(visitor, path);
|
||||
if let Some(body) = body {
|
||||
visitor.visit_block(body);
|
||||
}
|
||||
}
|
||||
}
|
||||
walk_list!(visitor, visit_attribute, &item.attrs);
|
||||
}
|
||||
|
|
@ -704,6 +713,15 @@ pub fn walk_assoc_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a AssocItem,
|
|||
AssocItemKind::MacCall(mac) => {
|
||||
visitor.visit_mac_call(mac);
|
||||
}
|
||||
AssocItemKind::Delegation(box Delegation { id: _, qself, path, body }) => {
|
||||
if let Some(qself) = qself {
|
||||
visitor.visit_ty(&qself.ty);
|
||||
}
|
||||
walk_path(visitor, path);
|
||||
if let Some(body) = body {
|
||||
visitor.visit_block(body);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
);
|
||||
if !is_stable && !self.tcx.features().asm_experimental_arch {
|
||||
feature_err(
|
||||
&self.tcx.sess.parse_sess,
|
||||
&self.tcx.sess,
|
||||
sym::asm_experimental_arch,
|
||||
sp,
|
||||
"inline assembly is not stable yet on this architecture",
|
||||
|
|
@ -63,13 +63,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
self.dcx().emit_err(AttSyntaxOnlyX86 { span: sp });
|
||||
}
|
||||
if asm.options.contains(InlineAsmOptions::MAY_UNWIND) && !self.tcx.features().asm_unwind {
|
||||
feature_err(
|
||||
&self.tcx.sess.parse_sess,
|
||||
sym::asm_unwind,
|
||||
sp,
|
||||
"the `may_unwind` option is unstable",
|
||||
)
|
||||
.emit();
|
||||
feature_err(&self.tcx.sess, sym::asm_unwind, sp, "the `may_unwind` option is unstable")
|
||||
.emit();
|
||||
}
|
||||
|
||||
let mut clobber_abis = FxIndexMap::default();
|
||||
|
|
@ -183,7 +178,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
InlineAsmOperand::Const { anon_const } => {
|
||||
if !self.tcx.features().asm_const {
|
||||
feature_err(
|
||||
&sess.parse_sess,
|
||||
sess,
|
||||
sym::asm_const,
|
||||
*op_sp,
|
||||
"const operands for inline assembly are unstable",
|
||||
|
|
|
|||
348
compiler/rustc_ast_lowering/src/delegation.rs
Normal file
348
compiler/rustc_ast_lowering/src/delegation.rs
Normal file
|
|
@ -0,0 +1,348 @@
|
|||
//! This module implements expansion of delegation items with early resolved paths.
|
||||
//! It includes a delegation to a free functions:
|
||||
//!
|
||||
//! ```ignore (illustrative)
|
||||
//! reuse module::name { target_expr_template }
|
||||
//! ```
|
||||
//!
|
||||
//! And delegation to a trait methods:
|
||||
//!
|
||||
//! ```ignore (illustrative)
|
||||
//! reuse <Type as Trait>::name { target_expr_template }
|
||||
//! ```
|
||||
//!
|
||||
//! After expansion for both cases we get:
|
||||
//!
|
||||
//! ```ignore (illustrative)
|
||||
//! fn name(
|
||||
//! arg0: InferDelegation(sig_id, Input(0)),
|
||||
//! arg1: InferDelegation(sig_id, Input(1)),
|
||||
//! ...,
|
||||
//! argN: InferDelegation(sig_id, Input(N)),
|
||||
//! ) -> InferDelegation(sig_id, Output) {
|
||||
//! callee_path(target_expr_template(arg0), arg1, ..., argN)
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! Where `callee_path` is a path in delegation item e.g. `<Type as Trait>::name`.
|
||||
//! `sig_id` is a id of item from which the signature is inherited. It may be a delegation
|
||||
//! item id (`item_id`) in case of impl trait or path resolution id (`path_id`) otherwise.
|
||||
//!
|
||||
//! Since we do not have a proper way to obtain function type information by path resolution
|
||||
//! in AST, we mark each function parameter type as `InferDelegation` and inherit it in `AstConv`.
|
||||
//!
|
||||
//! Similarly generics, predicates and header are set to the "default" values.
|
||||
//! In case of discrepancy with callee function the `NotSupportedDelegation` error will
|
||||
//! also be emitted in `AstConv`.
|
||||
|
||||
use crate::{ImplTraitPosition, ResolverAstLoweringExt};
|
||||
|
||||
use super::{ImplTraitContext, LoweringContext, ParamMode};
|
||||
|
||||
use ast::visit::Visitor;
|
||||
use hir::def::{DefKind, PartialRes, Res};
|
||||
use hir::{BodyId, HirId};
|
||||
use rustc_ast as ast;
|
||||
use rustc_ast::*;
|
||||
use rustc_errors::ErrorGuaranteed;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_middle::span_bug;
|
||||
use rustc_middle::ty::ResolverAstLowering;
|
||||
use rustc_span::{symbol::Ident, Span};
|
||||
use rustc_target::spec::abi;
|
||||
use std::iter;
|
||||
|
||||
pub(crate) struct DelegationResults<'hir> {
|
||||
pub body_id: hir::BodyId,
|
||||
pub sig: hir::FnSig<'hir>,
|
||||
pub generics: &'hir hir::Generics<'hir>,
|
||||
}
|
||||
|
||||
impl<'hir> LoweringContext<'_, 'hir> {
|
||||
pub(crate) fn delegation_has_self(&self, item_id: NodeId, path_id: NodeId, span: Span) -> bool {
|
||||
let sig_id = self.get_delegation_sig_id(item_id, path_id, span);
|
||||
let Ok(sig_id) = sig_id else {
|
||||
return false;
|
||||
};
|
||||
if let Some(local_sig_id) = sig_id.as_local() {
|
||||
self.resolver.has_self.contains(&local_sig_id)
|
||||
} else {
|
||||
match self.tcx.def_kind(sig_id) {
|
||||
DefKind::Fn => false,
|
||||
DefKind::AssocFn => self.tcx.associated_item(sig_id).fn_has_self_parameter,
|
||||
_ => span_bug!(span, "unexpected DefKind for delegation item"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn lower_delegation(
|
||||
&mut self,
|
||||
delegation: &Delegation,
|
||||
item_id: NodeId,
|
||||
) -> DelegationResults<'hir> {
|
||||
let span = delegation.path.segments.last().unwrap().ident.span;
|
||||
let sig_id = self.get_delegation_sig_id(item_id, delegation.id, span);
|
||||
match sig_id {
|
||||
Ok(sig_id) => {
|
||||
let decl = self.lower_delegation_decl(sig_id, span);
|
||||
let sig = self.lower_delegation_sig(span, decl);
|
||||
let body_id = self.lower_delegation_body(sig.decl, delegation);
|
||||
|
||||
let generics = self.lower_delegation_generics(span);
|
||||
DelegationResults { body_id, sig, generics }
|
||||
}
|
||||
Err(err) => self.generate_delegation_error(err, span),
|
||||
}
|
||||
}
|
||||
|
||||
fn get_delegation_sig_id(
|
||||
&self,
|
||||
item_id: NodeId,
|
||||
path_id: NodeId,
|
||||
span: Span,
|
||||
) -> Result<DefId, ErrorGuaranteed> {
|
||||
let sig_id = if self.is_in_trait_impl { item_id } else { path_id };
|
||||
let sig_id = self
|
||||
.resolver
|
||||
.get_partial_res(sig_id)
|
||||
.map(|r| r.expect_full_res().opt_def_id())
|
||||
.unwrap_or(None);
|
||||
|
||||
sig_id.ok_or_else(|| {
|
||||
self.tcx
|
||||
.dcx()
|
||||
.span_delayed_bug(span, "LoweringContext: couldn't resolve delegation item")
|
||||
})
|
||||
}
|
||||
|
||||
fn lower_delegation_generics(&mut self, span: Span) -> &'hir hir::Generics<'hir> {
|
||||
self.arena.alloc(hir::Generics {
|
||||
params: &[],
|
||||
predicates: &[],
|
||||
has_where_clause_predicates: false,
|
||||
where_clause_span: span,
|
||||
span: span,
|
||||
})
|
||||
}
|
||||
|
||||
fn lower_delegation_decl(
|
||||
&mut self,
|
||||
sig_id: DefId,
|
||||
param_span: Span,
|
||||
) -> &'hir hir::FnDecl<'hir> {
|
||||
let args_count = if let Some(local_sig_id) = sig_id.as_local() {
|
||||
// Map may be filled incorrectly due to recursive delegation.
|
||||
// Error will be emmited later in astconv.
|
||||
self.resolver.fn_parameter_counts.get(&local_sig_id).cloned().unwrap_or_default()
|
||||
} else {
|
||||
self.tcx.fn_arg_names(sig_id).len()
|
||||
};
|
||||
let inputs = self.arena.alloc_from_iter((0..args_count).into_iter().map(|arg| hir::Ty {
|
||||
hir_id: self.next_id(),
|
||||
kind: hir::TyKind::InferDelegation(sig_id, hir::InferDelegationKind::Input(arg)),
|
||||
span: self.lower_span(param_span),
|
||||
}));
|
||||
|
||||
let output = self.arena.alloc(hir::Ty {
|
||||
hir_id: self.next_id(),
|
||||
kind: hir::TyKind::InferDelegation(sig_id, hir::InferDelegationKind::Output),
|
||||
span: self.lower_span(param_span),
|
||||
});
|
||||
|
||||
self.arena.alloc(hir::FnDecl {
|
||||
inputs,
|
||||
output: hir::FnRetTy::Return(output),
|
||||
c_variadic: false,
|
||||
lifetime_elision_allowed: true,
|
||||
implicit_self: hir::ImplicitSelfKind::None,
|
||||
})
|
||||
}
|
||||
|
||||
fn lower_delegation_sig(
|
||||
&mut self,
|
||||
span: Span,
|
||||
decl: &'hir hir::FnDecl<'hir>,
|
||||
) -> hir::FnSig<'hir> {
|
||||
hir::FnSig {
|
||||
decl,
|
||||
header: hir::FnHeader {
|
||||
unsafety: hir::Unsafety::Normal,
|
||||
constness: hir::Constness::NotConst,
|
||||
asyncness: hir::IsAsync::NotAsync,
|
||||
abi: abi::Abi::Rust,
|
||||
},
|
||||
span: self.lower_span(span),
|
||||
}
|
||||
}
|
||||
|
||||
fn generate_param(&mut self, ty: &'hir hir::Ty<'hir>) -> (hir::Param<'hir>, NodeId) {
|
||||
let pat_node_id = self.next_node_id();
|
||||
let pat_id = self.lower_node_id(pat_node_id);
|
||||
let pat = self.arena.alloc(hir::Pat {
|
||||
hir_id: pat_id,
|
||||
kind: hir::PatKind::Binding(hir::BindingAnnotation::NONE, pat_id, Ident::empty(), None),
|
||||
span: ty.span,
|
||||
default_binding_modes: false,
|
||||
});
|
||||
|
||||
(hir::Param { hir_id: self.next_id(), pat, ty_span: ty.span, span: ty.span }, pat_node_id)
|
||||
}
|
||||
|
||||
fn generate_arg(&mut self, ty: &'hir hir::Ty<'hir>, param_id: HirId) -> hir::Expr<'hir> {
|
||||
let segments = self.arena.alloc_from_iter(iter::once(hir::PathSegment {
|
||||
ident: Ident::empty(),
|
||||
hir_id: self.next_id(),
|
||||
res: Res::Local(param_id),
|
||||
args: None,
|
||||
infer_args: false,
|
||||
}));
|
||||
|
||||
let path =
|
||||
self.arena.alloc(hir::Path { span: ty.span, res: Res::Local(param_id), segments });
|
||||
|
||||
hir::Expr {
|
||||
hir_id: self.next_id(),
|
||||
kind: hir::ExprKind::Path(hir::QPath::Resolved(None, path)),
|
||||
span: ty.span,
|
||||
}
|
||||
}
|
||||
|
||||
fn lower_delegation_body(
|
||||
&mut self,
|
||||
decl: &'hir hir::FnDecl<'hir>,
|
||||
delegation: &Delegation,
|
||||
) -> BodyId {
|
||||
let path = self.lower_qpath(
|
||||
delegation.id,
|
||||
&delegation.qself,
|
||||
&delegation.path,
|
||||
ParamMode::Optional,
|
||||
&ImplTraitContext::Disallowed(ImplTraitPosition::Path),
|
||||
None,
|
||||
);
|
||||
let block = delegation.body.as_deref();
|
||||
|
||||
self.lower_body(|this| {
|
||||
let mut parameters: Vec<hir::Param<'_>> = Vec::new();
|
||||
let mut args: Vec<hir::Expr<'hir>> = Vec::new();
|
||||
|
||||
for (idx, param_ty) in decl.inputs.iter().enumerate() {
|
||||
let (param, pat_node_id) = this.generate_param(param_ty);
|
||||
parameters.push(param);
|
||||
|
||||
let arg = if let Some(block) = block
|
||||
&& idx == 0
|
||||
{
|
||||
let mut self_resolver = SelfResolver {
|
||||
resolver: this.resolver,
|
||||
path_id: delegation.id,
|
||||
self_param_id: pat_node_id,
|
||||
};
|
||||
self_resolver.visit_block(block);
|
||||
let block = this.lower_block(block, false);
|
||||
hir::Expr {
|
||||
hir_id: this.next_id(),
|
||||
kind: hir::ExprKind::Block(block, None),
|
||||
span: block.span,
|
||||
}
|
||||
} else {
|
||||
let pat_hir_id = this.lower_node_id(pat_node_id);
|
||||
this.generate_arg(param_ty, pat_hir_id)
|
||||
};
|
||||
args.push(arg);
|
||||
}
|
||||
|
||||
let args = self.arena.alloc_from_iter(args);
|
||||
let final_expr = this.generate_call(path, args);
|
||||
(this.arena.alloc_from_iter(parameters), final_expr)
|
||||
})
|
||||
}
|
||||
|
||||
fn generate_call(
|
||||
&mut self,
|
||||
path: hir::QPath<'hir>,
|
||||
args: &'hir [hir::Expr<'hir>],
|
||||
) -> hir::Expr<'hir> {
|
||||
let callee = self.arena.alloc(hir::Expr {
|
||||
hir_id: self.next_id(),
|
||||
kind: hir::ExprKind::Path(path),
|
||||
span: path.span(),
|
||||
});
|
||||
|
||||
let expr = self.arena.alloc(hir::Expr {
|
||||
hir_id: self.next_id(),
|
||||
kind: hir::ExprKind::Call(callee, args),
|
||||
span: path.span(),
|
||||
});
|
||||
|
||||
let block = self.arena.alloc(hir::Block {
|
||||
stmts: &[],
|
||||
expr: Some(expr),
|
||||
hir_id: self.next_id(),
|
||||
rules: hir::BlockCheckMode::DefaultBlock,
|
||||
span: path.span(),
|
||||
targeted_by_break: false,
|
||||
});
|
||||
|
||||
hir::Expr {
|
||||
hir_id: self.next_id(),
|
||||
kind: hir::ExprKind::Block(block, None),
|
||||
span: path.span(),
|
||||
}
|
||||
}
|
||||
|
||||
fn generate_delegation_error(
|
||||
&mut self,
|
||||
err: ErrorGuaranteed,
|
||||
span: Span,
|
||||
) -> DelegationResults<'hir> {
|
||||
let generics = self.lower_delegation_generics(span);
|
||||
|
||||
let decl = self.arena.alloc(hir::FnDecl {
|
||||
inputs: &[],
|
||||
output: hir::FnRetTy::DefaultReturn(span),
|
||||
c_variadic: false,
|
||||
lifetime_elision_allowed: true,
|
||||
implicit_self: hir::ImplicitSelfKind::None,
|
||||
});
|
||||
|
||||
let sig = self.lower_delegation_sig(span, decl);
|
||||
let body_id = self.lower_body(|this| {
|
||||
let expr =
|
||||
hir::Expr { hir_id: this.next_id(), kind: hir::ExprKind::Err(err), span: span };
|
||||
(&[], expr)
|
||||
});
|
||||
DelegationResults { generics, body_id, sig }
|
||||
}
|
||||
}
|
||||
|
||||
struct SelfResolver<'a> {
|
||||
resolver: &'a mut ResolverAstLowering,
|
||||
path_id: NodeId,
|
||||
self_param_id: NodeId,
|
||||
}
|
||||
|
||||
impl<'a> SelfResolver<'a> {
|
||||
fn try_replace_id(&mut self, id: NodeId) {
|
||||
if let Some(res) = self.resolver.partial_res_map.get(&id)
|
||||
&& let Some(Res::Local(sig_id)) = res.full_res()
|
||||
&& sig_id == self.path_id
|
||||
{
|
||||
let new_res = PartialRes::new(Res::Local(self.self_param_id));
|
||||
self.resolver.partial_res_map.insert(id, new_res);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast, 'a> Visitor<'ast> for SelfResolver<'a> {
|
||||
fn visit_path(&mut self, path: &'ast Path, id: NodeId) {
|
||||
self.try_replace_id(id);
|
||||
visit::walk_path(self, path);
|
||||
}
|
||||
|
||||
fn visit_path_segment(&mut self, seg: &'ast PathSegment) {
|
||||
self.try_replace_id(seg.id);
|
||||
visit::walk_path_segment(self, seg);
|
||||
}
|
||||
}
|
||||
|
|
@ -1512,7 +1512,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
Some(hir::CoroutineKind::Coroutine(_)) => {
|
||||
if !self.tcx.features().coroutines {
|
||||
rustc_session::parse::feature_err(
|
||||
&self.tcx.sess.parse_sess,
|
||||
&self.tcx.sess,
|
||||
sym::coroutines,
|
||||
span,
|
||||
"yield syntax is experimental",
|
||||
|
|
@ -1524,7 +1524,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
None => {
|
||||
if !self.tcx.features().coroutines {
|
||||
rustc_session::parse::feature_err(
|
||||
&self.tcx.sess.parse_sess,
|
||||
&self.tcx.sess,
|
||||
sym::coroutines,
|
||||
span,
|
||||
"yield syntax is experimental",
|
||||
|
|
|
|||
|
|
@ -441,6 +441,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
let macro_def = self.arena.alloc(ast::MacroDef { body, macro_rules: *macro_rules });
|
||||
hir::ItemKind::Macro(macro_def, macro_kind)
|
||||
}
|
||||
ItemKind::Delegation(box delegation) => {
|
||||
let delegation_results = self.lower_delegation(delegation, id);
|
||||
hir::ItemKind::Fn(
|
||||
delegation_results.sig,
|
||||
delegation_results.generics,
|
||||
delegation_results.body_id,
|
||||
)
|
||||
}
|
||||
ItemKind::MacCall(..) => {
|
||||
panic!("`TyMac` should have been expanded by now")
|
||||
}
|
||||
|
|
@ -805,6 +813,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
);
|
||||
(generics, kind, ty.is_some())
|
||||
}
|
||||
AssocItemKind::Delegation(box delegation) => {
|
||||
let delegation_results = self.lower_delegation(delegation, i.id);
|
||||
let item_kind = hir::TraitItemKind::Fn(
|
||||
delegation_results.sig,
|
||||
hir::TraitFn::Provided(delegation_results.body_id),
|
||||
);
|
||||
(delegation_results.generics, item_kind, true)
|
||||
}
|
||||
AssocItemKind::MacCall(..) => panic!("macro item shouldn't exist at this point"),
|
||||
};
|
||||
|
||||
|
|
@ -826,6 +842,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
AssocItemKind::Fn(box Fn { sig, .. }) => {
|
||||
hir::AssocItemKind::Fn { has_self: sig.decl.has_self() }
|
||||
}
|
||||
AssocItemKind::Delegation(box delegation) => hir::AssocItemKind::Fn {
|
||||
has_self: self.delegation_has_self(i.id, delegation.id, i.span),
|
||||
},
|
||||
AssocItemKind::MacCall(..) => unimplemented!(),
|
||||
};
|
||||
let id = hir::TraitItemId { owner_id: hir::OwnerId { def_id: self.local_def_id(i.id) } };
|
||||
|
|
@ -908,6 +927,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
},
|
||||
)
|
||||
}
|
||||
AssocItemKind::Delegation(box delegation) => {
|
||||
let delegation_results = self.lower_delegation(delegation, i.id);
|
||||
(
|
||||
delegation_results.generics,
|
||||
hir::ImplItemKind::Fn(delegation_results.sig, delegation_results.body_id),
|
||||
)
|
||||
}
|
||||
AssocItemKind::MacCall(..) => panic!("`TyMac` should have been expanded by now"),
|
||||
};
|
||||
|
||||
|
|
@ -924,6 +950,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
}
|
||||
|
||||
fn lower_impl_item_ref(&mut self, i: &AssocItem) -> hir::ImplItemRef {
|
||||
let trait_item_def_id = self
|
||||
.resolver
|
||||
.get_partial_res(i.id)
|
||||
.map(|r| r.expect_full_res().opt_def_id())
|
||||
.unwrap_or(None);
|
||||
self.is_in_trait_impl = trait_item_def_id.is_some();
|
||||
|
||||
hir::ImplItemRef {
|
||||
id: hir::ImplItemId { owner_id: hir::OwnerId { def_id: self.local_def_id(i.id) } },
|
||||
ident: self.lower_ident(i.ident),
|
||||
|
|
@ -934,12 +967,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
AssocItemKind::Fn(box Fn { sig, .. }) => {
|
||||
hir::AssocItemKind::Fn { has_self: sig.decl.has_self() }
|
||||
}
|
||||
AssocItemKind::Delegation(box delegation) => hir::AssocItemKind::Fn {
|
||||
has_self: self.delegation_has_self(i.id, delegation.id, i.span),
|
||||
},
|
||||
AssocItemKind::MacCall(..) => unimplemented!(),
|
||||
},
|
||||
trait_item_def_id: self
|
||||
.resolver
|
||||
.get_partial_res(i.id)
|
||||
.map(|r| r.expect_full_res().def_id()),
|
||||
trait_item_def_id,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -77,6 +77,7 @@ macro_rules! arena_vec {
|
|||
|
||||
mod asm;
|
||||
mod block;
|
||||
mod delegation;
|
||||
mod errors;
|
||||
mod expr;
|
||||
mod format;
|
||||
|
|
@ -1042,7 +1043,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
{
|
||||
add_feature_diagnostics(
|
||||
&mut err,
|
||||
&self.tcx.sess.parse_sess,
|
||||
&self.tcx.sess,
|
||||
sym::return_type_notation,
|
||||
);
|
||||
}
|
||||
|
|
@ -2309,7 +2310,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
hir::ArrayLen::Infer(self.lower_node_id(c.id), self.lower_span(c.value.span))
|
||||
} else {
|
||||
feature_err(
|
||||
&self.tcx.sess.parse_sess,
|
||||
&self.tcx.sess,
|
||||
sym::generic_arg_infer,
|
||||
c.value.span,
|
||||
"using `_` for array lengths is unstable",
|
||||
|
|
|
|||
|
|
@ -232,6 +232,9 @@ ast_passes_tilde_const_disallowed = `~const` is not allowed here
|
|||
.trait = this trait is not a `#[const_trait]`, so it cannot have `~const` trait bounds
|
||||
.trait_impl = this impl is not `const`, so it cannot have `~const` trait bounds
|
||||
.impl = inherent impls cannot have `~const` trait bounds
|
||||
.trait_assoc_ty = associated types in non-`#[const_trait]` traits cannot have `~const` trait bounds
|
||||
.trait_impl_assoc_ty = associated types in non-const impls cannot have `~const` trait bounds
|
||||
.inherent_assoc_ty = inherent associated types cannot have `~const` trait bounds
|
||||
.object = trait objects cannot have `~const` trait bounds
|
||||
.item = this item cannot have `~const` trait bounds
|
||||
|
||||
|
|
|
|||
|
|
@ -37,12 +37,17 @@ enum SelfSemantic {
|
|||
}
|
||||
|
||||
/// What is the context that prevents using `~const`?
|
||||
// FIXME(effects): Consider getting rid of this in favor of `errors::TildeConstReason`, they're
|
||||
// almost identical. This gets rid of an abstraction layer which might be considered bad.
|
||||
enum DisallowTildeConstContext<'a> {
|
||||
TraitObject,
|
||||
Fn(FnKind<'a>),
|
||||
Trait(Span),
|
||||
TraitImpl(Span),
|
||||
Impl(Span),
|
||||
TraitAssocTy(Span),
|
||||
TraitImplAssocTy(Span),
|
||||
InherentAssocTy(Span),
|
||||
Item,
|
||||
}
|
||||
|
||||
|
|
@ -316,6 +321,7 @@ impl<'a> AstValidator<'a> {
|
|||
constness: Const::No,
|
||||
polarity: ImplPolarity::Positive,
|
||||
trait_ref,
|
||||
..
|
||||
} = parent
|
||||
{
|
||||
Some(trait_ref.path.span.shrink_to_lo())
|
||||
|
|
@ -1286,6 +1292,15 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||
// suggestion for moving such bounds to the assoc const fns if available.
|
||||
errors::TildeConstReason::Impl { span }
|
||||
}
|
||||
&DisallowTildeConstContext::TraitAssocTy(span) => {
|
||||
errors::TildeConstReason::TraitAssocTy { span }
|
||||
}
|
||||
&DisallowTildeConstContext::TraitImplAssocTy(span) => {
|
||||
errors::TildeConstReason::TraitImplAssocTy { span }
|
||||
}
|
||||
&DisallowTildeConstContext::InherentAssocTy(span) => {
|
||||
errors::TildeConstReason::InherentAssocTy { span }
|
||||
}
|
||||
DisallowTildeConstContext::TraitObject => {
|
||||
errors::TildeConstReason::TraitObject
|
||||
}
|
||||
|
|
@ -1483,13 +1498,12 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||
self.check_item_named(item.ident, "const");
|
||||
}
|
||||
|
||||
let parent_is_const =
|
||||
self.outer_trait_or_trait_impl.as_ref().and_then(TraitOrTraitImpl::constness).is_some();
|
||||
|
||||
match &item.kind {
|
||||
AssocItemKind::Fn(box Fn { sig, generics, body, .. })
|
||||
if self
|
||||
.outer_trait_or_trait_impl
|
||||
.as_ref()
|
||||
.and_then(TraitOrTraitImpl::constness)
|
||||
.is_some()
|
||||
if parent_is_const
|
||||
|| ctxt == AssocCtxt::Trait
|
||||
|| matches!(sig.header.constness, Const::Yes(_)) =>
|
||||
{
|
||||
|
|
@ -1505,6 +1519,20 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||
);
|
||||
self.visit_fn(kind, item.span, item.id);
|
||||
}
|
||||
AssocItemKind::Type(_) => {
|
||||
let disallowed = (!parent_is_const).then(|| match self.outer_trait_or_trait_impl {
|
||||
Some(TraitOrTraitImpl::Trait { .. }) => {
|
||||
DisallowTildeConstContext::TraitAssocTy(item.span)
|
||||
}
|
||||
Some(TraitOrTraitImpl::TraitImpl { .. }) => {
|
||||
DisallowTildeConstContext::TraitImplAssocTy(item.span)
|
||||
}
|
||||
None => DisallowTildeConstContext::InherentAssocTy(item.span),
|
||||
});
|
||||
self.with_tilde_const(disallowed, |this| {
|
||||
this.with_in_trait_impl(None, |this| visit::walk_assoc_item(this, item, ctxt))
|
||||
})
|
||||
}
|
||||
_ => self.with_in_trait_impl(None, |this| visit::walk_assoc_item(this, item, ctxt)),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -565,6 +565,8 @@ pub struct ConstBoundTraitObject {
|
|||
pub span: Span,
|
||||
}
|
||||
|
||||
// FIXME(effects): Consider making the note/reason the message of the diagnostic.
|
||||
// FIXME(effects): Provide structured suggestions (e.g., add `const` / `#[const_trait]` here).
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_passes_tilde_const_disallowed)]
|
||||
pub struct TildeConstDisallowed {
|
||||
|
|
@ -598,6 +600,21 @@ pub enum TildeConstReason {
|
|||
#[primary_span]
|
||||
span: Span,
|
||||
},
|
||||
#[note(ast_passes_trait_assoc_ty)]
|
||||
TraitAssocTy {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
},
|
||||
#[note(ast_passes_trait_impl_assoc_ty)]
|
||||
TraitImplAssocTy {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
},
|
||||
#[note(ast_passes_inherent_assoc_ty)]
|
||||
InherentAssocTy {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
},
|
||||
#[note(ast_passes_object)]
|
||||
TraitObject,
|
||||
#[note(ast_passes_item)]
|
||||
|
|
|
|||
|
|
@ -17,14 +17,12 @@ use crate::errors;
|
|||
macro_rules! gate {
|
||||
($visitor:expr, $feature:ident, $span:expr, $explain:expr) => {{
|
||||
if !$visitor.features.$feature && !$span.allows_unstable(sym::$feature) {
|
||||
feature_err(&$visitor.sess.parse_sess, sym::$feature, $span, $explain).emit();
|
||||
feature_err(&$visitor.sess, sym::$feature, $span, $explain).emit();
|
||||
}
|
||||
}};
|
||||
($visitor:expr, $feature:ident, $span:expr, $explain:expr, $help:expr) => {{
|
||||
if !$visitor.features.$feature && !$span.allows_unstable(sym::$feature) {
|
||||
feature_err(&$visitor.sess.parse_sess, sym::$feature, $span, $explain)
|
||||
.with_help($help)
|
||||
.emit();
|
||||
feature_err(&$visitor.sess, sym::$feature, $span, $explain).with_help($help).emit();
|
||||
}
|
||||
}};
|
||||
}
|
||||
|
|
@ -33,7 +31,7 @@ macro_rules! gate {
|
|||
macro_rules! gate_alt {
|
||||
($visitor:expr, $has_feature:expr, $name:expr, $span:expr, $explain:expr) => {{
|
||||
if !$has_feature && !$span.allows_unstable($name) {
|
||||
feature_err(&$visitor.sess.parse_sess, $name, $span, $explain).emit();
|
||||
feature_err(&$visitor.sess, $name, $span, $explain).emit();
|
||||
}
|
||||
}};
|
||||
}
|
||||
|
|
@ -45,7 +43,7 @@ macro_rules! gate_multi {
|
|||
let spans: Vec<_> =
|
||||
$spans.filter(|span| !span.allows_unstable(sym::$feature)).collect();
|
||||
if !spans.is_empty() {
|
||||
feature_err(&$visitor.sess.parse_sess, sym::$feature, spans, $explain).emit();
|
||||
feature_err(&$visitor.sess, sym::$feature, spans, $explain).emit();
|
||||
}
|
||||
}
|
||||
}};
|
||||
|
|
@ -55,7 +53,7 @@ macro_rules! gate_multi {
|
|||
macro_rules! gate_legacy {
|
||||
($visitor:expr, $feature:ident, $span:expr, $explain:expr) => {{
|
||||
if !$visitor.features.$feature && !$span.allows_unstable(sym::$feature) {
|
||||
feature_warn(&$visitor.sess.parse_sess, sym::$feature, $span, $explain);
|
||||
feature_warn(&$visitor.sess, sym::$feature, $span, $explain);
|
||||
}
|
||||
}};
|
||||
}
|
||||
|
|
@ -91,14 +89,7 @@ impl<'a> PostExpansionVisitor<'a> {
|
|||
match abi::is_enabled(self.features, span, symbol_unescaped.as_str()) {
|
||||
Ok(()) => (),
|
||||
Err(abi::AbiDisabled::Unstable { feature, explain }) => {
|
||||
feature_err_issue(
|
||||
&self.sess.parse_sess,
|
||||
feature,
|
||||
span,
|
||||
GateIssue::Language,
|
||||
explain,
|
||||
)
|
||||
.emit();
|
||||
feature_err_issue(&self.sess, feature, span, GateIssue::Language, explain).emit();
|
||||
}
|
||||
Err(abi::AbiDisabled::Unrecognized) => {
|
||||
if self.sess.opts.pretty.map_or(true, |ppm| ppm.needs_hir()) {
|
||||
|
|
@ -556,6 +547,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
|
|||
gate_all!(explicit_tail_calls, "`become` expression is experimental");
|
||||
gate_all!(generic_const_items, "generic const items are experimental");
|
||||
gate_all!(unnamed_fields, "unnamed fields are not yet fully implemented");
|
||||
gate_all!(fn_delegation, "functions delegation is not yet fully implemented");
|
||||
|
||||
if !visitor.features.never_patterns {
|
||||
if let Some(spans) = spans.get(&sym::never_patterns) {
|
||||
|
|
@ -570,13 +562,8 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
|
|||
if let Ok(snippet) = sm.span_to_snippet(span)
|
||||
&& snippet == "!"
|
||||
{
|
||||
feature_err(
|
||||
&sess.parse_sess,
|
||||
sym::never_patterns,
|
||||
span,
|
||||
"`!` patterns are experimental",
|
||||
)
|
||||
.emit();
|
||||
feature_err(sess, sym::never_patterns, span, "`!` patterns are experimental")
|
||||
.emit();
|
||||
} else {
|
||||
let suggestion = span.shrink_to_hi();
|
||||
sess.dcx().emit_err(errors::MatchArmWithNoBody { span, suggestion });
|
||||
|
|
|
|||
|
|
@ -376,6 +376,9 @@ impl<'a> State<'a> {
|
|||
state.print_visibility(&item.vis)
|
||||
});
|
||||
}
|
||||
ast::ItemKind::Delegation(box delegation) => {
|
||||
self.print_delegation(delegation, &item.vis, &item.attrs)
|
||||
}
|
||||
}
|
||||
self.ann.post(self, AnnNode::Item(item))
|
||||
}
|
||||
|
|
@ -554,10 +557,38 @@ impl<'a> State<'a> {
|
|||
self.word(";");
|
||||
}
|
||||
}
|
||||
ast::AssocItemKind::Delegation(box delegation) => {
|
||||
self.print_delegation(delegation, vis, &item.attrs)
|
||||
}
|
||||
}
|
||||
self.ann.post(self, AnnNode::SubItem(id))
|
||||
}
|
||||
|
||||
pub(crate) fn print_delegation(
|
||||
&mut self,
|
||||
delegation: &ast::Delegation,
|
||||
vis: &ast::Visibility,
|
||||
attrs: &[ast::Attribute],
|
||||
) {
|
||||
if delegation.body.is_some() {
|
||||
self.head("");
|
||||
}
|
||||
self.print_visibility(vis);
|
||||
self.word_space("reuse");
|
||||
|
||||
if let Some(qself) = &delegation.qself {
|
||||
self.print_qpath(&delegation.path, qself, false);
|
||||
} else {
|
||||
self.print_path(&delegation.path, false, 0);
|
||||
}
|
||||
if let Some(body) = &delegation.body {
|
||||
self.nbsp();
|
||||
self.print_block_with_attrs(body, attrs);
|
||||
} else {
|
||||
self.word(";");
|
||||
}
|
||||
}
|
||||
|
||||
fn print_fn_full(
|
||||
&mut self,
|
||||
sig: &ast::FnSig,
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ use rustc_macros::HashStable_Generic;
|
|||
use rustc_session::config::ExpectedValues;
|
||||
use rustc_session::lint::builtin::UNEXPECTED_CFGS;
|
||||
use rustc_session::lint::BuiltinLintDiagnostics;
|
||||
use rustc_session::parse::{feature_err, ParseSess};
|
||||
use rustc_session::parse::feature_err;
|
||||
use rustc_session::{RustcVersion, Session};
|
||||
use rustc_span::hygiene::Transparency;
|
||||
use rustc_span::{symbol::sym, symbol::Symbol, Span};
|
||||
|
|
@ -518,15 +518,15 @@ pub struct Condition {
|
|||
/// Tests if a cfg-pattern matches the cfg set
|
||||
pub fn cfg_matches(
|
||||
cfg: &ast::MetaItem,
|
||||
sess: &ParseSess,
|
||||
sess: &Session,
|
||||
lint_node_id: NodeId,
|
||||
features: Option<&Features>,
|
||||
) -> bool {
|
||||
eval_condition(cfg, sess, features, &mut |cfg| {
|
||||
try_gate_cfg(cfg.name, cfg.span, sess, features);
|
||||
match sess.check_config.expecteds.get(&cfg.name) {
|
||||
match sess.parse_sess.check_config.expecteds.get(&cfg.name) {
|
||||
Some(ExpectedValues::Some(values)) if !values.contains(&cfg.value) => {
|
||||
sess.buffer_lint_with_diagnostic(
|
||||
sess.parse_sess.buffer_lint_with_diagnostic(
|
||||
UNEXPECTED_CFGS,
|
||||
cfg.span,
|
||||
lint_node_id,
|
||||
|
|
@ -541,8 +541,8 @@ pub fn cfg_matches(
|
|||
),
|
||||
);
|
||||
}
|
||||
None if sess.check_config.exhaustive_names => {
|
||||
sess.buffer_lint_with_diagnostic(
|
||||
None if sess.parse_sess.check_config.exhaustive_names => {
|
||||
sess.parse_sess.buffer_lint_with_diagnostic(
|
||||
UNEXPECTED_CFGS,
|
||||
cfg.span,
|
||||
lint_node_id,
|
||||
|
|
@ -555,18 +555,18 @@ pub fn cfg_matches(
|
|||
}
|
||||
_ => { /* not unexpected */ }
|
||||
}
|
||||
sess.config.contains(&(cfg.name, cfg.value))
|
||||
sess.parse_sess.config.contains(&(cfg.name, cfg.value))
|
||||
})
|
||||
}
|
||||
|
||||
fn try_gate_cfg(name: Symbol, span: Span, sess: &ParseSess, features: Option<&Features>) {
|
||||
fn try_gate_cfg(name: Symbol, span: Span, sess: &Session, features: Option<&Features>) {
|
||||
let gate = find_gated_cfg(|sym| sym == name);
|
||||
if let (Some(feats), Some(gated_cfg)) = (features, gate) {
|
||||
gate_cfg(gated_cfg, span, sess, feats);
|
||||
}
|
||||
}
|
||||
|
||||
fn gate_cfg(gated_cfg: &GatedCfg, cfg_span: Span, sess: &ParseSess, features: &Features) {
|
||||
fn gate_cfg(gated_cfg: &GatedCfg, cfg_span: Span, sess: &Session, features: &Features) {
|
||||
let (cfg, feature, has_feature) = gated_cfg;
|
||||
if !has_feature(features) && !cfg_span.allows_unstable(*feature) {
|
||||
let explain = format!("`cfg({cfg})` is experimental and subject to change");
|
||||
|
|
@ -594,11 +594,11 @@ fn parse_version(s: Symbol) -> Option<RustcVersion> {
|
|||
/// evaluate individual items.
|
||||
pub fn eval_condition(
|
||||
cfg: &ast::MetaItem,
|
||||
sess: &ParseSess,
|
||||
sess: &Session,
|
||||
features: Option<&Features>,
|
||||
eval: &mut impl FnMut(Condition) -> bool,
|
||||
) -> bool {
|
||||
let dcx = &sess.dcx;
|
||||
let dcx = &sess.parse_sess.dcx;
|
||||
match &cfg.kind {
|
||||
ast::MetaItemKind::List(mis) if cfg.name_or_empty() == sym::version => {
|
||||
try_gate_cfg(sym::version, cfg.span, sess, features);
|
||||
|
|
@ -626,7 +626,7 @@ pub fn eval_condition(
|
|||
};
|
||||
|
||||
// See https://github.com/rust-lang/rust/issues/64796#issuecomment-640851454 for details
|
||||
if sess.assume_incomplete_release {
|
||||
if sess.parse_sess.assume_incomplete_release {
|
||||
RustcVersion::CURRENT > min_version
|
||||
} else {
|
||||
RustcVersion::CURRENT >= min_version
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ pub fn expand_cfg(
|
|||
Ok(cfg) => {
|
||||
let matches_cfg = attr::cfg_matches(
|
||||
&cfg,
|
||||
&cx.sess.parse_sess,
|
||||
&cx.sess,
|
||||
cx.current_expansion.lint_node_id,
|
||||
Some(cx.ecfg.features),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -107,7 +107,7 @@ pub fn expand_include<'cx>(
|
|||
return DummyResult::any(sp);
|
||||
};
|
||||
// The file will be added to the code map by the parser
|
||||
let file = match resolve_path(&cx.sess.parse_sess, file.as_str(), sp) {
|
||||
let file = match resolve_path(&cx.sess, file.as_str(), sp) {
|
||||
Ok(f) => f,
|
||||
Err(err) => {
|
||||
err.emit();
|
||||
|
|
@ -179,7 +179,7 @@ pub fn expand_include_str(
|
|||
let Some(file) = get_single_str_from_tts(cx, sp, tts, "include_str!") else {
|
||||
return DummyResult::any(sp);
|
||||
};
|
||||
let file = match resolve_path(&cx.sess.parse_sess, file.as_str(), sp) {
|
||||
let file = match resolve_path(&cx.sess, file.as_str(), sp) {
|
||||
Ok(f) => f,
|
||||
Err(err) => {
|
||||
err.emit();
|
||||
|
|
@ -213,7 +213,7 @@ pub fn expand_include_bytes(
|
|||
let Some(file) = get_single_str_from_tts(cx, sp, tts, "include_bytes!") else {
|
||||
return DummyResult::any(sp);
|
||||
};
|
||||
let file = match resolve_path(&cx.sess.parse_sess, file.as_str(), sp) {
|
||||
let file = match resolve_path(&cx.sess, file.as_str(), sp) {
|
||||
Ok(f) => f,
|
||||
Err(err) => {
|
||||
err.emit();
|
||||
|
|
|
|||
|
|
@ -267,9 +267,12 @@ impl CguReuseTracker {
|
|||
|
||||
fn check_expected_reuse(&self, sess: &Session) {
|
||||
if let Some(ref data) = self.data {
|
||||
for (cgu_name, &(ref cgu_user_name, ref error_span, expected_reuse, comparison_kind)) in
|
||||
&data.expected_reuse
|
||||
{
|
||||
let mut keys = data.expected_reuse.keys().collect::<Vec<_>>();
|
||||
keys.sort_unstable();
|
||||
for cgu_name in keys {
|
||||
let &(ref cgu_user_name, ref error_span, expected_reuse, comparison_kind) =
|
||||
data.expected_reuse.get(cgu_name).unwrap();
|
||||
|
||||
if let Some(&actual_reuse) = data.actual_reuse.get(cgu_name) {
|
||||
let (error, at_least) = match comparison_kind {
|
||||
ComparisonKind::Exact => (expected_reuse != actual_reuse, false),
|
||||
|
|
|
|||
|
|
@ -554,6 +554,11 @@ fn link_staticlib<'a>(
|
|||
archive_builder_builder
|
||||
.extract_bundled_libs(path, tempdir.as_ref(), &relevant_libs)
|
||||
.unwrap_or_else(|e| sess.dcx().emit_fatal(e));
|
||||
|
||||
// We sort the libraries below
|
||||
#[allow(rustc::potential_query_instability)]
|
||||
let mut relevant_libs: Vec<Symbol> = relevant_libs.into_iter().collect();
|
||||
relevant_libs.sort_unstable();
|
||||
for filename in relevant_libs {
|
||||
let joined = tempdir.as_ref().join(filename.as_str());
|
||||
let path = joined.as_path();
|
||||
|
|
@ -2201,14 +2206,19 @@ fn linker_with_args<'a>(
|
|||
.iter()
|
||||
.find(|(ty, _)| *ty == crate_type)
|
||||
.expect("failed to find crate type in dependency format list");
|
||||
let native_libraries_from_nonstatics = codegen_results
|
||||
|
||||
// We sort the libraries below
|
||||
#[allow(rustc::potential_query_instability)]
|
||||
let mut native_libraries_from_nonstatics = codegen_results
|
||||
.crate_info
|
||||
.native_libraries
|
||||
.iter()
|
||||
.filter_map(|(cnum, libraries)| {
|
||||
(dependency_linkage[cnum.as_usize() - 1] != Linkage::Static).then_some(libraries)
|
||||
})
|
||||
.flatten();
|
||||
.flatten()
|
||||
.collect::<Vec<_>>();
|
||||
native_libraries_from_nonstatics.sort_unstable_by(|a, b| a.name.as_str().cmp(b.name.as_str()));
|
||||
for (raw_dylib_name, raw_dylib_imports) in
|
||||
collate_raw_dylibs(sess, native_libraries_from_nonstatics)?
|
||||
{
|
||||
|
|
@ -2860,7 +2870,7 @@ fn add_dynamic_crate(cmd: &mut dyn Linker, sess: &Session, cratepath: &Path) {
|
|||
|
||||
fn relevant_lib(sess: &Session, lib: &NativeLib) -> bool {
|
||||
match lib.cfg {
|
||||
Some(ref cfg) => rustc_attr::cfg_matches(cfg, &sess.parse_sess, CRATE_NODE_ID, None),
|
||||
Some(ref cfg) => rustc_attr::cfg_matches(cfg, sess, CRATE_NODE_ID, None),
|
||||
None => true,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -319,6 +319,8 @@ fn exported_symbols_provider_local(
|
|||
|
||||
let (_, cgus) = tcx.collect_and_partition_mono_items(());
|
||||
|
||||
// The symbols created in this loop are sorted below it
|
||||
#[allow(rustc::potential_query_instability)]
|
||||
for (mono_item, data) in cgus.iter().flat_map(|cgu| cgu.items().iter()) {
|
||||
if data.linkage != Linkage::External {
|
||||
// We can only re-use things with external linkage, otherwise
|
||||
|
|
|
|||
|
|
@ -912,17 +912,22 @@ impl CrateInfo {
|
|||
})
|
||||
.collect();
|
||||
let prefix = if target.is_like_windows && target.arch == "x86" { "_" } else { "" };
|
||||
|
||||
// This loop only adds new items to values of the hash map, so the order in which we
|
||||
// iterate over the values is not important.
|
||||
#[allow(rustc::potential_query_instability)]
|
||||
info.linked_symbols
|
||||
.iter_mut()
|
||||
.filter(|(crate_type, _)| {
|
||||
!matches!(crate_type, CrateType::Rlib | CrateType::Staticlib)
|
||||
})
|
||||
.for_each(|(_, linked_symbols)| {
|
||||
linked_symbols.extend(
|
||||
missing_weak_lang_items
|
||||
.iter()
|
||||
.map(|item| (format!("{prefix}{item}"), SymbolExportKind::Text)),
|
||||
);
|
||||
let mut symbols = missing_weak_lang_items
|
||||
.iter()
|
||||
.map(|item| (format!("{prefix}{item}"), SymbolExportKind::Text))
|
||||
.collect::<Vec<_>>();
|
||||
symbols.sort_unstable_by(|a, b| a.0.cmp(&b.0));
|
||||
linked_symbols.extend(symbols);
|
||||
if tcx.allocator_kind(()).is_some() {
|
||||
// At least one crate needs a global allocator. This crate may be placed
|
||||
// after the crate that defines it in the linker order, in which case some
|
||||
|
|
|
|||
|
|
@ -155,7 +155,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
|
|||
Some([item]) if item.has_name(sym::linker) => {
|
||||
if !tcx.features().used_with_arg {
|
||||
feature_err(
|
||||
&tcx.sess.parse_sess,
|
||||
&tcx.sess,
|
||||
sym::used_with_arg,
|
||||
attr.span,
|
||||
"`#[used(linker)]` is currently unstable",
|
||||
|
|
@ -167,7 +167,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
|
|||
Some([item]) if item.has_name(sym::compiler) => {
|
||||
if !tcx.features().used_with_arg {
|
||||
feature_err(
|
||||
&tcx.sess.parse_sess,
|
||||
&tcx.sess,
|
||||
sym::used_with_arg,
|
||||
attr.span,
|
||||
"`#[used(compiler)]` is currently unstable",
|
||||
|
|
@ -251,7 +251,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
|
|||
&& !attr.span.allows_unstable(sym::closure_track_caller)
|
||||
{
|
||||
feature_err(
|
||||
&tcx.sess.parse_sess,
|
||||
&tcx.sess,
|
||||
sym::closure_track_caller,
|
||||
attr.span,
|
||||
"`#[track_caller]` on closures is currently unstable",
|
||||
|
|
@ -304,7 +304,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
|
|||
// `#[target_feature]` on `main` and `start`.
|
||||
} else if !tcx.features().target_feature_11 {
|
||||
feature_err(
|
||||
&tcx.sess.parse_sess,
|
||||
&tcx.sess,
|
||||
sym::target_feature_11,
|
||||
attr.span,
|
||||
"`#[target_feature(..)]` can only be applied to `unsafe` functions",
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@
|
|||
#![feature(strict_provenance)]
|
||||
#![feature(try_blocks)]
|
||||
#![recursion_limit = "256"]
|
||||
#![allow(rustc::potential_query_instability)]
|
||||
|
||||
//! This crate contains codegen code that is used by all codegen backends (LLVM and others).
|
||||
//! The backend-agnostic functions of this crate use functions defined in various traits that
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ pub fn from_target_feature(
|
|||
};
|
||||
if !allowed {
|
||||
feature_err(
|
||||
&tcx.sess.parse_sess,
|
||||
&tcx.sess,
|
||||
feature_gate.unwrap(),
|
||||
item.span(),
|
||||
format!("the target feature `{feature}` is currently unstable"),
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ impl<'tcx> NonConstOp<'tcx> for FloatingPointOp {
|
|||
|
||||
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
|
||||
feature_err(
|
||||
&ccx.tcx.sess.parse_sess,
|
||||
&ccx.tcx.sess,
|
||||
sym::const_fn_floating_point_arithmetic,
|
||||
span,
|
||||
format!("floating point arithmetic is not allowed in {}s", ccx.const_kind()),
|
||||
|
|
@ -553,7 +553,7 @@ impl<'tcx> NonConstOp<'tcx> for RawMutPtrDeref {
|
|||
|
||||
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
|
||||
feature_err(
|
||||
&ccx.tcx.sess.parse_sess,
|
||||
&ccx.tcx.sess,
|
||||
sym::const_mut_refs,
|
||||
span,
|
||||
format!("dereferencing raw mutable pointers in {}s is unstable", ccx.const_kind(),),
|
||||
|
|
@ -624,7 +624,7 @@ pub mod ty {
|
|||
|
||||
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
|
||||
feature_err(
|
||||
&ccx.tcx.sess.parse_sess,
|
||||
&ccx.tcx.sess,
|
||||
sym::const_mut_refs,
|
||||
span,
|
||||
format!("mutable references are not allowed in {}s", ccx.const_kind()),
|
||||
|
|
|
|||
|
|
@ -865,10 +865,6 @@ impl DiagCtxt {
|
|||
/// directly).
|
||||
#[track_caller]
|
||||
pub fn delayed_bug(&self, msg: impl Into<DiagnosticMessage>) -> ErrorGuaranteed {
|
||||
let treat_next_err_as_bug = self.inner.borrow().treat_next_err_as_bug();
|
||||
if treat_next_err_as_bug {
|
||||
self.bug(msg);
|
||||
}
|
||||
DiagnosticBuilder::<ErrorGuaranteed>::new(self, DelayedBug(DelayedBugKind::Normal), msg)
|
||||
.emit()
|
||||
}
|
||||
|
|
@ -883,10 +879,6 @@ impl DiagCtxt {
|
|||
sp: impl Into<MultiSpan>,
|
||||
msg: impl Into<DiagnosticMessage>,
|
||||
) -> ErrorGuaranteed {
|
||||
let treat_next_err_as_bug = self.inner.borrow().treat_next_err_as_bug();
|
||||
if treat_next_err_as_bug {
|
||||
self.span_bug(sp, msg);
|
||||
}
|
||||
DiagnosticBuilder::<ErrorGuaranteed>::new(self, DelayedBug(DelayedBugKind::Normal), msg)
|
||||
.with_span(sp)
|
||||
.emit()
|
||||
|
|
@ -1259,10 +1251,6 @@ impl DiagCtxtInner {
|
|||
}
|
||||
|
||||
fn emit_diagnostic(&mut self, mut diagnostic: Diagnostic) -> Option<ErrorGuaranteed> {
|
||||
if matches!(diagnostic.level, Error | Fatal) && self.treat_next_err_as_bug() {
|
||||
diagnostic.level = Bug;
|
||||
}
|
||||
|
||||
// The `LintExpectationId` can be stable or unstable depending on when it was created.
|
||||
// Diagnostics created before the definition of `HirId`s are unstable and can not yet
|
||||
// be stored. Instead, they are buffered until the `LintExpectationId` is replaced by
|
||||
|
|
@ -1298,6 +1286,12 @@ impl DiagCtxtInner {
|
|||
_ => {}
|
||||
}
|
||||
|
||||
// This must come after the possible promotion of `DelayedBug` to
|
||||
// `Error` above.
|
||||
if matches!(diagnostic.level, Error | Fatal) && self.treat_next_err_as_bug() {
|
||||
diagnostic.level = Bug;
|
||||
}
|
||||
|
||||
if diagnostic.has_future_breakage() {
|
||||
// Future breakages aren't emitted if they're Level::Allow,
|
||||
// but they still need to be constructed and stashed below,
|
||||
|
|
@ -1387,20 +1381,14 @@ impl DiagCtxtInner {
|
|||
}
|
||||
|
||||
fn treat_err_as_bug(&self) -> bool {
|
||||
self.flags.treat_err_as_bug.is_some_and(|c| {
|
||||
self.err_count + self.lint_err_count + self.delayed_bug_count() >= c.get()
|
||||
})
|
||||
self.flags.treat_err_as_bug.is_some_and(|c| self.err_count + self.lint_err_count >= c.get())
|
||||
}
|
||||
|
||||
// Use this one before incrementing `err_count`.
|
||||
fn treat_next_err_as_bug(&self) -> bool {
|
||||
self.flags.treat_err_as_bug.is_some_and(|c| {
|
||||
self.err_count + self.lint_err_count + self.delayed_bug_count() + 1 >= c.get()
|
||||
})
|
||||
}
|
||||
|
||||
fn delayed_bug_count(&self) -> usize {
|
||||
self.span_delayed_bugs.len() + self.good_path_delayed_bugs.len()
|
||||
self.flags
|
||||
.treat_err_as_bug
|
||||
.is_some_and(|c| self.err_count + self.lint_err_count + 1 >= c.get())
|
||||
}
|
||||
|
||||
fn has_errors(&self) -> bool {
|
||||
|
|
@ -1412,7 +1400,7 @@ impl DiagCtxtInner {
|
|||
}
|
||||
|
||||
fn flush_delayed(&mut self, kind: DelayedBugKind) {
|
||||
let (bugs, explanation) = match kind {
|
||||
let (bugs, note1) = match kind {
|
||||
DelayedBugKind::Normal => (
|
||||
std::mem::take(&mut self.span_delayed_bugs),
|
||||
"no errors encountered even though `span_delayed_bug` issued",
|
||||
|
|
@ -1422,6 +1410,7 @@ impl DiagCtxtInner {
|
|||
"no warnings or errors encountered even though `good_path_delayed_bugs` issued",
|
||||
),
|
||||
};
|
||||
let note2 = "those delayed bugs will now be shown as internal compiler errors";
|
||||
|
||||
if bugs.is_empty() {
|
||||
return;
|
||||
|
|
@ -1447,8 +1436,11 @@ impl DiagCtxtInner {
|
|||
|
||||
if i == 0 {
|
||||
// Put the overall explanation before the `DelayedBug`s, to
|
||||
// frame them better (e.g. separate warnings from them).
|
||||
self.emit_diagnostic(Diagnostic::new(Bug, explanation));
|
||||
// frame them better (e.g. separate warnings from them). Also,
|
||||
// make it a note so it doesn't count as an error, because that
|
||||
// could trigger `-Ztreat-err-as-bug`, which we don't want.
|
||||
self.emit_diagnostic(Diagnostic::new(Note, note1));
|
||||
self.emit_diagnostic(Diagnostic::new(Note, note2));
|
||||
}
|
||||
|
||||
let mut bug =
|
||||
|
|
@ -1474,22 +1466,12 @@ impl DiagCtxtInner {
|
|||
|
||||
fn panic_if_treat_err_as_bug(&self) {
|
||||
if self.treat_err_as_bug() {
|
||||
match (
|
||||
self.err_count + self.lint_err_count,
|
||||
self.delayed_bug_count(),
|
||||
self.flags.treat_err_as_bug.map(|c| c.get()).unwrap(),
|
||||
) {
|
||||
(1, 0, 1) => panic!("aborting due to `-Z treat-err-as-bug=1`"),
|
||||
(0, 1, 1) => panic!("aborting due delayed bug with `-Z treat-err-as-bug=1`"),
|
||||
(count, delayed_count, val) => {
|
||||
if delayed_count > 0 {
|
||||
panic!(
|
||||
"aborting after {count} errors and {delayed_count} delayed bugs due to `-Z treat-err-as-bug={val}`",
|
||||
)
|
||||
} else {
|
||||
panic!("aborting after {count} errors due to `-Z treat-err-as-bug={val}`")
|
||||
}
|
||||
}
|
||||
let n = self.flags.treat_err_as_bug.map(|c| c.get()).unwrap();
|
||||
assert_eq!(n, self.err_count + self.lint_err_count);
|
||||
if n == 1 {
|
||||
panic!("aborting due to `-Z treat-err-as-bug=1`");
|
||||
} else {
|
||||
panic!("aborting after {n} errors due to `-Z treat-err-as-bug={n}`");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1150,7 +1150,7 @@ impl<'a> ExtCtxt<'a> {
|
|||
///
|
||||
/// This unifies the logic used for resolving `include_X!`.
|
||||
pub fn resolve_path(
|
||||
parse_sess: &ParseSess,
|
||||
parse_sess: &Session,
|
||||
path: impl Into<PathBuf>,
|
||||
span: Span,
|
||||
) -> PResult<'_, PathBuf> {
|
||||
|
|
@ -1166,7 +1166,7 @@ pub fn resolve_path(
|
|||
.expect("attempting to resolve a file path in an external file"),
|
||||
FileName::DocTest(path, _) => path,
|
||||
other => {
|
||||
return Err(parse_sess.dcx.create_err(errors::ResolveRelativePath {
|
||||
return Err(parse_sess.dcx().create_err(errors::ResolveRelativePath {
|
||||
span,
|
||||
path: parse_sess.source_map().filename_for_diagnostics(&other).to_string(),
|
||||
}));
|
||||
|
|
@ -1390,7 +1390,7 @@ pub fn parse_macro_name_and_helper_attrs(
|
|||
/// asserts in old versions of those crates and their wide use in the ecosystem.
|
||||
/// See issue #73345 for more details.
|
||||
/// FIXME(#73933): Remove this eventually.
|
||||
fn pretty_printing_compatibility_hack(item: &Item, sess: &ParseSess) -> bool {
|
||||
fn pretty_printing_compatibility_hack(item: &Item, sess: &Session) -> bool {
|
||||
let name = item.ident.name;
|
||||
if name == sym::ProceduralMasqueradeDummyType {
|
||||
if let ast::ItemKind::Enum(enum_def, _) = &item.kind {
|
||||
|
|
@ -1418,7 +1418,7 @@ fn pretty_printing_compatibility_hack(item: &Item, sess: &ParseSess) -> bool {
|
|||
};
|
||||
|
||||
if crate_matches {
|
||||
sess.buffer_lint_with_diagnostic(
|
||||
sess.parse_sess.buffer_lint_with_diagnostic(
|
||||
PROC_MACRO_BACK_COMPAT,
|
||||
item.ident.span,
|
||||
ast::CRATE_NODE_ID,
|
||||
|
|
@ -1439,7 +1439,7 @@ fn pretty_printing_compatibility_hack(item: &Item, sess: &ParseSess) -> bool {
|
|||
false
|
||||
}
|
||||
|
||||
pub(crate) fn ann_pretty_printing_compatibility_hack(ann: &Annotatable, sess: &ParseSess) -> bool {
|
||||
pub(crate) fn ann_pretty_printing_compatibility_hack(ann: &Annotatable, sess: &Session) -> bool {
|
||||
let item = match ann {
|
||||
Annotatable::Item(item) => item,
|
||||
Annotatable::Stmt(stmt) => match &stmt.kind {
|
||||
|
|
@ -1451,7 +1451,7 @@ pub(crate) fn ann_pretty_printing_compatibility_hack(ann: &Annotatable, sess: &P
|
|||
pretty_printing_compatibility_hack(item, sess)
|
||||
}
|
||||
|
||||
pub(crate) fn nt_pretty_printing_compatibility_hack(nt: &Nonterminal, sess: &ParseSess) -> bool {
|
||||
pub(crate) fn nt_pretty_printing_compatibility_hack(nt: &Nonterminal, sess: &Session) -> bool {
|
||||
let item = match nt {
|
||||
Nonterminal::NtItem(item) => item,
|
||||
Nonterminal::NtStmt(stmt) => match &stmt.kind {
|
||||
|
|
|
|||
|
|
@ -256,12 +256,7 @@ impl<'a> StripUnconfigured<'a> {
|
|||
);
|
||||
}
|
||||
|
||||
if !attr::cfg_matches(
|
||||
&cfg_predicate,
|
||||
&self.sess.parse_sess,
|
||||
self.lint_node_id,
|
||||
self.features,
|
||||
) {
|
||||
if !attr::cfg_matches(&cfg_predicate, &self.sess, self.lint_node_id, self.features) {
|
||||
return vec![];
|
||||
}
|
||||
|
||||
|
|
@ -369,12 +364,7 @@ impl<'a> StripUnconfigured<'a> {
|
|||
};
|
||||
(
|
||||
parse_cfg(&meta_item, self.sess).map_or(true, |meta_item| {
|
||||
attr::cfg_matches(
|
||||
meta_item,
|
||||
&self.sess.parse_sess,
|
||||
self.lint_node_id,
|
||||
self.features,
|
||||
)
|
||||
attr::cfg_matches(meta_item, &self.sess, self.lint_node_id, self.features)
|
||||
}),
|
||||
Some(meta_item),
|
||||
)
|
||||
|
|
@ -385,7 +375,7 @@ impl<'a> StripUnconfigured<'a> {
|
|||
pub(crate) fn maybe_emit_expr_attr_err(&self, attr: &Attribute) {
|
||||
if self.features.is_some_and(|features| !features.stmt_expr_attributes) {
|
||||
let mut err = feature_err(
|
||||
&self.sess.parse_sess,
|
||||
&self.sess,
|
||||
sym::stmt_expr_attributes,
|
||||
attr.span,
|
||||
"attributes on expressions are experimental",
|
||||
|
|
|
|||
|
|
@ -30,8 +30,8 @@ use rustc_parse::parser::{
|
|||
use rustc_parse::validate_attr;
|
||||
use rustc_session::lint::builtin::{UNUSED_ATTRIBUTES, UNUSED_DOC_COMMENTS};
|
||||
use rustc_session::lint::BuiltinLintDiagnostics;
|
||||
use rustc_session::parse::{feature_err, ParseSess};
|
||||
use rustc_session::Limit;
|
||||
use rustc_session::parse::feature_err;
|
||||
use rustc_session::{Limit, Session};
|
||||
use rustc_span::symbol::{sym, Ident};
|
||||
use rustc_span::{FileName, LocalExpnId, Span};
|
||||
|
||||
|
|
@ -800,7 +800,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
|||
return;
|
||||
}
|
||||
feature_err(
|
||||
&self.cx.sess.parse_sess,
|
||||
&self.cx.sess,
|
||||
sym::proc_macro_hygiene,
|
||||
span,
|
||||
format!("custom attributes cannot be applied to {kind}"),
|
||||
|
|
@ -810,7 +810,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
|||
|
||||
fn gate_proc_macro_input(&self, annotatable: &Annotatable) {
|
||||
struct GateProcMacroInput<'a> {
|
||||
parse_sess: &'a ParseSess,
|
||||
sess: &'a Session,
|
||||
}
|
||||
|
||||
impl<'ast, 'a> Visitor<'ast> for GateProcMacroInput<'a> {
|
||||
|
|
@ -820,7 +820,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
|||
if !matches!(mod_kind, ModKind::Loaded(_, Inline::Yes, _)) =>
|
||||
{
|
||||
feature_err(
|
||||
self.parse_sess,
|
||||
self.sess,
|
||||
sym::proc_macro_hygiene,
|
||||
item.span,
|
||||
"non-inline modules in proc macro input are unstable",
|
||||
|
|
@ -835,8 +835,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
|||
}
|
||||
|
||||
if !self.cx.ecfg.features.proc_macro_hygiene {
|
||||
annotatable
|
||||
.visit_with(&mut GateProcMacroInput { parse_sess: &self.cx.sess.parse_sess });
|
||||
annotatable.visit_with(&mut GateProcMacroInput { sess: &self.cx.sess });
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -477,14 +477,14 @@ pub fn compile_declarative_macro(
|
|||
let tt = mbe::quoted::parse(
|
||||
&TokenStream::new(vec![tt.clone()]),
|
||||
true,
|
||||
&sess.parse_sess,
|
||||
sess,
|
||||
def.id,
|
||||
features,
|
||||
edition,
|
||||
)
|
||||
.pop()
|
||||
.unwrap();
|
||||
valid &= check_lhs_nt_follows(&sess.parse_sess, def, &tt);
|
||||
valid &= check_lhs_nt_follows(sess, def, &tt);
|
||||
return tt;
|
||||
}
|
||||
sess.dcx().span_bug(def.span, "wrong-structured lhs")
|
||||
|
|
@ -501,7 +501,7 @@ pub fn compile_declarative_macro(
|
|||
return mbe::quoted::parse(
|
||||
&TokenStream::new(vec![tt.clone()]),
|
||||
false,
|
||||
&sess.parse_sess,
|
||||
sess,
|
||||
def.id,
|
||||
features,
|
||||
edition,
|
||||
|
|
@ -516,12 +516,12 @@ pub fn compile_declarative_macro(
|
|||
};
|
||||
|
||||
for rhs in &rhses {
|
||||
valid &= check_rhs(&sess.parse_sess, rhs);
|
||||
valid &= check_rhs(sess, rhs);
|
||||
}
|
||||
|
||||
// don't abort iteration early, so that errors for multiple lhses can be reported
|
||||
for lhs in &lhses {
|
||||
valid &= check_lhs_no_empty_seq(&sess.parse_sess, slice::from_ref(lhs));
|
||||
valid &= check_lhs_no_empty_seq(sess, slice::from_ref(lhs));
|
||||
}
|
||||
|
||||
valid &= macro_check::check_meta_variables(&sess.parse_sess, def.id, def.span, &lhses, &rhses);
|
||||
|
|
@ -588,21 +588,21 @@ pub fn compile_declarative_macro(
|
|||
(mk_syn_ext(expander), rule_spans)
|
||||
}
|
||||
|
||||
fn check_lhs_nt_follows(sess: &ParseSess, def: &ast::Item, lhs: &mbe::TokenTree) -> bool {
|
||||
fn check_lhs_nt_follows(sess: &Session, def: &ast::Item, lhs: &mbe::TokenTree) -> bool {
|
||||
// lhs is going to be like TokenTree::Delimited(...), where the
|
||||
// entire lhs is those tts. Or, it can be a "bare sequence", not wrapped in parens.
|
||||
if let mbe::TokenTree::Delimited(.., delimited) = lhs {
|
||||
check_matcher(sess, def, &delimited.tts)
|
||||
} else {
|
||||
let msg = "invalid macro matcher; matchers must be contained in balanced delimiters";
|
||||
sess.dcx.span_err(lhs.span(), msg);
|
||||
sess.dcx().span_err(lhs.span(), msg);
|
||||
false
|
||||
}
|
||||
// we don't abort on errors on rejection, the driver will do that for us
|
||||
// after parsing/expansion. we can report every error in every macro this way.
|
||||
}
|
||||
|
||||
fn is_empty_token_tree(sess: &ParseSess, seq: &mbe::SequenceRepetition) -> bool {
|
||||
fn is_empty_token_tree(sess: &Session, seq: &mbe::SequenceRepetition) -> bool {
|
||||
if seq.separator.is_some() {
|
||||
false
|
||||
} else {
|
||||
|
|
@ -621,7 +621,7 @@ fn is_empty_token_tree(sess: &ParseSess, seq: &mbe::SequenceRepetition) -> bool
|
|||
iter.next();
|
||||
}
|
||||
let span = t.span.to(now.span);
|
||||
sess.dcx.span_note(span, "doc comments are ignored in matcher position");
|
||||
sess.dcx().span_note(span, "doc comments are ignored in matcher position");
|
||||
}
|
||||
mbe::TokenTree::Sequence(_, sub_seq)
|
||||
if (sub_seq.kleene.op == mbe::KleeneOp::ZeroOrMore
|
||||
|
|
@ -635,7 +635,7 @@ fn is_empty_token_tree(sess: &ParseSess, seq: &mbe::SequenceRepetition) -> bool
|
|||
|
||||
/// Checks that the lhs contains no repetition which could match an empty token
|
||||
/// tree, because then the matcher would hang indefinitely.
|
||||
fn check_lhs_no_empty_seq(sess: &ParseSess, tts: &[mbe::TokenTree]) -> bool {
|
||||
fn check_lhs_no_empty_seq(sess: &Session, tts: &[mbe::TokenTree]) -> bool {
|
||||
use mbe::TokenTree;
|
||||
for tt in tts {
|
||||
match tt {
|
||||
|
|
@ -651,7 +651,7 @@ fn check_lhs_no_empty_seq(sess: &ParseSess, tts: &[mbe::TokenTree]) -> bool {
|
|||
TokenTree::Sequence(span, seq) => {
|
||||
if is_empty_token_tree(sess, seq) {
|
||||
let sp = span.entire();
|
||||
sess.dcx.span_err(sp, "repetition matches empty token tree");
|
||||
sess.dcx().span_err(sp, "repetition matches empty token tree");
|
||||
return false;
|
||||
}
|
||||
if !check_lhs_no_empty_seq(sess, &seq.tts) {
|
||||
|
|
@ -664,22 +664,22 @@ fn check_lhs_no_empty_seq(sess: &ParseSess, tts: &[mbe::TokenTree]) -> bool {
|
|||
true
|
||||
}
|
||||
|
||||
fn check_rhs(sess: &ParseSess, rhs: &mbe::TokenTree) -> bool {
|
||||
fn check_rhs(sess: &Session, rhs: &mbe::TokenTree) -> bool {
|
||||
match *rhs {
|
||||
mbe::TokenTree::Delimited(..) => return true,
|
||||
_ => {
|
||||
sess.dcx.span_err(rhs.span(), "macro rhs must be delimited");
|
||||
sess.dcx().span_err(rhs.span(), "macro rhs must be delimited");
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
fn check_matcher(sess: &ParseSess, def: &ast::Item, matcher: &[mbe::TokenTree]) -> bool {
|
||||
fn check_matcher(sess: &Session, def: &ast::Item, matcher: &[mbe::TokenTree]) -> bool {
|
||||
let first_sets = FirstSets::new(matcher);
|
||||
let empty_suffix = TokenSet::empty();
|
||||
let err = sess.dcx.err_count();
|
||||
let err = sess.dcx().err_count();
|
||||
check_matcher_core(sess, def, &first_sets, matcher, &empty_suffix);
|
||||
err == sess.dcx.err_count()
|
||||
err == sess.dcx().err_count()
|
||||
}
|
||||
|
||||
fn has_compile_error_macro(rhs: &mbe::TokenTree) -> bool {
|
||||
|
|
@ -1014,7 +1014,7 @@ impl<'tt> TokenSet<'tt> {
|
|||
// Requires that `first_sets` is pre-computed for `matcher`;
|
||||
// see `FirstSets::new`.
|
||||
fn check_matcher_core<'tt>(
|
||||
sess: &ParseSess,
|
||||
sess: &Session,
|
||||
def: &ast::Item,
|
||||
first_sets: &FirstSets<'tt>,
|
||||
matcher: &'tt [mbe::TokenTree],
|
||||
|
|
@ -1139,7 +1139,7 @@ fn check_matcher_core<'tt>(
|
|||
name,
|
||||
Some(NonterminalKind::PatParam { inferred: false }),
|
||||
));
|
||||
sess.buffer_lint_with_diagnostic(
|
||||
sess.parse_sess.buffer_lint_with_diagnostic(
|
||||
RUST_2021_INCOMPATIBLE_OR_PATTERNS,
|
||||
span,
|
||||
ast::CRATE_NODE_ID,
|
||||
|
|
@ -1158,7 +1158,7 @@ fn check_matcher_core<'tt>(
|
|||
};
|
||||
|
||||
let sp = next_token.span();
|
||||
let mut err = sess.dcx.struct_span_err(
|
||||
let mut err = sess.dcx().struct_span_err(
|
||||
sp,
|
||||
format!(
|
||||
"`${name}:{frag}` {may_be} followed by `{next}`, which \
|
||||
|
|
@ -1172,7 +1172,7 @@ fn check_matcher_core<'tt>(
|
|||
err.span_label(sp, format!("not allowed after `{kind}` fragments"));
|
||||
|
||||
if kind == NonterminalKind::PatWithOr
|
||||
&& sess.edition.at_least_rust_2021()
|
||||
&& sess.parse_sess.edition.at_least_rust_2021()
|
||||
&& next_token.is_token(&BinOp(token::BinOpToken::Or))
|
||||
{
|
||||
let suggestion = quoted_tt_to_string(&TokenTree::MetaVarDecl(
|
||||
|
|
|
|||
|
|
@ -5,7 +5,8 @@ use rustc_ast::token::{self, Delimiter, Token};
|
|||
use rustc_ast::{tokenstream, NodeId};
|
||||
use rustc_ast_pretty::pprust;
|
||||
use rustc_feature::Features;
|
||||
use rustc_session::parse::{feature_err, ParseSess};
|
||||
use rustc_session::parse::feature_err;
|
||||
use rustc_session::Session;
|
||||
use rustc_span::symbol::{kw, sym, Ident};
|
||||
|
||||
use rustc_span::edition::Edition;
|
||||
|
|
@ -38,7 +39,7 @@ const VALID_FRAGMENT_NAMES_MSG: &str = "valid fragment specifiers are \
|
|||
pub(super) fn parse(
|
||||
input: &tokenstream::TokenStream,
|
||||
parsing_patterns: bool,
|
||||
sess: &ParseSess,
|
||||
sess: &Session,
|
||||
node_id: NodeId,
|
||||
features: &Features,
|
||||
edition: Edition,
|
||||
|
|
@ -84,7 +85,7 @@ pub(super) fn parse(
|
|||
"invalid fragment specifier `{}`",
|
||||
frag.name
|
||||
);
|
||||
sess.dcx
|
||||
sess.dcx()
|
||||
.struct_span_err(span, msg)
|
||||
.with_help(VALID_FRAGMENT_NAMES_MSG)
|
||||
.emit();
|
||||
|
|
@ -113,7 +114,7 @@ pub(super) fn parse(
|
|||
}
|
||||
|
||||
/// Asks for the `macro_metavar_expr` feature if it is not already declared
|
||||
fn maybe_emit_macro_metavar_expr_feature(features: &Features, sess: &ParseSess, span: Span) {
|
||||
fn maybe_emit_macro_metavar_expr_feature(features: &Features, sess: &Session, span: Span) {
|
||||
if !features.macro_metavar_expr {
|
||||
let msg = "meta-variable expressions are unstable";
|
||||
feature_err(sess, sym::macro_metavar_expr, span, msg).emit();
|
||||
|
|
@ -138,7 +139,7 @@ fn parse_tree<'a>(
|
|||
tree: &'a tokenstream::TokenTree,
|
||||
outer_trees: &mut impl Iterator<Item = &'a tokenstream::TokenTree>,
|
||||
parsing_patterns: bool,
|
||||
sess: &ParseSess,
|
||||
sess: &Session,
|
||||
node_id: NodeId,
|
||||
features: &Features,
|
||||
edition: Edition,
|
||||
|
|
@ -174,7 +175,8 @@ fn parse_tree<'a>(
|
|||
// The delimiter is `{`. This indicates the beginning
|
||||
// of a meta-variable expression (e.g. `${count(ident)}`).
|
||||
// Try to parse the meta-variable expression.
|
||||
match MetaVarExpr::parse(tts, delim_span.entire(), sess) {
|
||||
match MetaVarExpr::parse(tts, delim_span.entire(), &sess.parse_sess)
|
||||
{
|
||||
Err(err) => {
|
||||
err.emit();
|
||||
// Returns early the same read `$` to avoid spanning
|
||||
|
|
@ -195,7 +197,7 @@ fn parse_tree<'a>(
|
|||
_ => {
|
||||
let tok = pprust::token_kind_to_string(&token::OpenDelim(delim));
|
||||
let msg = format!("expected `(` or `{{`, found `{tok}`");
|
||||
sess.dcx.span_err(delim_span.entire(), msg);
|
||||
sess.dcx().span_err(delim_span.entire(), msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -244,7 +246,7 @@ fn parse_tree<'a>(
|
|||
Some(tokenstream::TokenTree::Token(token, _)) => {
|
||||
let msg =
|
||||
format!("expected identifier, found `{}`", pprust::token_to_string(token),);
|
||||
sess.dcx.span_err(token.span, msg);
|
||||
sess.dcx().span_err(token.span, msg);
|
||||
TokenTree::MetaVar(token.span, Ident::empty())
|
||||
}
|
||||
|
||||
|
|
@ -313,7 +315,7 @@ fn parse_kleene_op<'a>(
|
|||
fn parse_sep_and_kleene_op<'a>(
|
||||
input: &mut impl Iterator<Item = &'a tokenstream::TokenTree>,
|
||||
span: Span,
|
||||
sess: &ParseSess,
|
||||
sess: &Session,
|
||||
) -> (Option<Token>, KleeneToken) {
|
||||
// We basically look at two token trees here, denoted as #1 and #2 below
|
||||
let span = match parse_kleene_op(input, span) {
|
||||
|
|
@ -325,7 +327,7 @@ fn parse_sep_and_kleene_op<'a>(
|
|||
// #2 is the `?` Kleene op, which does not take a separator (error)
|
||||
Ok(Ok((KleeneOp::ZeroOrOne, span))) => {
|
||||
// Error!
|
||||
sess.dcx.span_err(
|
||||
sess.dcx().span_err(
|
||||
token.span,
|
||||
"the `?` macro repetition operator does not take a separator",
|
||||
);
|
||||
|
|
@ -346,7 +348,7 @@ fn parse_sep_and_kleene_op<'a>(
|
|||
};
|
||||
|
||||
// If we ever get to this point, we have experienced an "unexpected token" error
|
||||
sess.dcx.span_err(span, "expected one of: `*`, `+`, or `?`");
|
||||
sess.dcx().span_err(span, "expected one of: `*`, `+`, or `?`");
|
||||
|
||||
// Return a dummy
|
||||
(None, KleeneToken::new(KleeneOp::ZeroOrMore, span))
|
||||
|
|
@ -355,9 +357,10 @@ fn parse_sep_and_kleene_op<'a>(
|
|||
// `$$` or a meta-variable is the lhs of a macro but shouldn't.
|
||||
//
|
||||
// For example, `macro_rules! foo { ( ${length()} ) => {} }`
|
||||
fn span_dollar_dollar_or_metavar_in_the_lhs_err(sess: &ParseSess, token: &Token) {
|
||||
sess.dcx.span_err(token.span, format!("unexpected token: {}", pprust::token_to_string(token)));
|
||||
sess.dcx.span_note(
|
||||
fn span_dollar_dollar_or_metavar_in_the_lhs_err(sess: &Session, token: &Token) {
|
||||
sess.dcx()
|
||||
.span_err(token.span, format!("unexpected token: {}", pprust::token_to_string(token)));
|
||||
sess.dcx().span_note(
|
||||
token.span,
|
||||
"`$$` and meta-variable expressions are not allowed inside macro parameter definitions",
|
||||
);
|
||||
|
|
|
|||
|
|
@ -119,7 +119,7 @@ impl MultiItemModifier for DeriveProcMacro {
|
|||
// We need special handling for statement items
|
||||
// (e.g. `fn foo() { #[derive(Debug)] struct Bar; }`)
|
||||
let is_stmt = matches!(item, Annotatable::Stmt(..));
|
||||
let hack = crate::base::ann_pretty_printing_compatibility_hack(&item, &ecx.sess.parse_sess);
|
||||
let hack = crate::base::ann_pretty_printing_compatibility_hack(&item, &ecx.sess);
|
||||
let input = if hack {
|
||||
let nt = match item {
|
||||
Annotatable::Item(item) => token::NtItem(item),
|
||||
|
|
|
|||
|
|
@ -258,7 +258,7 @@ impl FromInternal<(TokenStream, &mut Rustc<'_, '_>)> for Vec<TokenTree<TokenStre
|
|||
// represented as a delimited group.
|
||||
// FIXME: It needs to be removed, but there are some
|
||||
// compatibility issues (see #73345).
|
||||
if crate::base::nt_pretty_printing_compatibility_hack(&nt.0, rustc.sess()) {
|
||||
if crate::base::nt_pretty_printing_compatibility_hack(&nt.0, rustc.ecx.sess) {
|
||||
trees.extend(Self::from_internal((stream, rustc)));
|
||||
} else {
|
||||
trees.push(TokenTree::Group(Group {
|
||||
|
|
|
|||
|
|
@ -2571,9 +2571,17 @@ pub enum OpaqueTyOrigin {
|
|||
},
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, HashStable_Generic)]
|
||||
pub enum InferDelegationKind {
|
||||
Input(usize),
|
||||
Output,
|
||||
}
|
||||
|
||||
/// The various kinds of types recognized by the compiler.
|
||||
#[derive(Debug, Clone, Copy, HashStable_Generic)]
|
||||
pub enum TyKind<'hir> {
|
||||
/// Actual type should be inherited from `DefId` signature
|
||||
InferDelegation(DefId, InferDelegationKind),
|
||||
/// A variable length slice (i.e., `[T]`).
|
||||
Slice(&'hir Ty<'hir>),
|
||||
/// A fixed length array (i.e., `[T; n]`).
|
||||
|
|
|
|||
|
|
@ -856,7 +856,7 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v>) {
|
|||
visitor.visit_lifetime(lifetime);
|
||||
}
|
||||
TyKind::Typeof(ref expression) => visitor.visit_anon_const(expression),
|
||||
TyKind::Infer | TyKind::Err(_) => {}
|
||||
TyKind::Infer | TyKind::InferDelegation(..) | TyKind::Err(_) => {}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -263,6 +263,10 @@ hir_analysis_must_implement_not_function_span_note = required by this annotation
|
|||
|
||||
hir_analysis_must_implement_one_of_attribute = the `#[rustc_must_implement_one_of]` attribute must be used with at least 2 args
|
||||
|
||||
hir_analysis_not_supported_delegation =
|
||||
{$descr} is not supported yet
|
||||
.label = callee defined here
|
||||
|
||||
hir_analysis_only_current_traits_arbitrary = only traits defined in the current crate can be implemented for arbitrary types
|
||||
|
||||
hir_analysis_only_current_traits_foreign = this is not defined in the current crate because this is a foreign trait
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
if trait_segment.args().parenthesized == hir::GenericArgsParentheses::ParenSugar {
|
||||
// For now, require that parenthetical notation be used only with `Fn()` etc.
|
||||
feature_err(
|
||||
&self.tcx().sess.parse_sess,
|
||||
&self.tcx().sess,
|
||||
sym::unboxed_closures,
|
||||
span,
|
||||
"parenthetical notation is only stable when used with `Fn`-family traits",
|
||||
|
|
@ -75,7 +75,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
if trait_segment.args().parenthesized != hir::GenericArgsParentheses::ParenSugar {
|
||||
// For now, require that parenthetical notation be used only with `Fn()` etc.
|
||||
let mut err = feature_err(
|
||||
&sess.parse_sess,
|
||||
sess,
|
||||
sym::unboxed_closures,
|
||||
span,
|
||||
"the precise format of `Fn`-family traits' type parameters is subject to change",
|
||||
|
|
|
|||
|
|
@ -29,10 +29,9 @@ use rustc_hir::{GenericArg, GenericArgs, OpaqueTyOrigin};
|
|||
use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
|
||||
use rustc_infer::traits::ObligationCause;
|
||||
use rustc_middle::middle::stability::AllowUnstable;
|
||||
use rustc_middle::ty::GenericParamDefKind;
|
||||
use rustc_middle::ty::{
|
||||
self, Const, GenericArgKind, GenericArgsRef, IsSuggestable, ParamEnv, Ty, TyCtxt,
|
||||
TypeVisitableExt,
|
||||
self, Const, GenericArgKind, GenericArgsRef, GenericParamDefKind, IsSuggestable, ParamEnv, Ty,
|
||||
TyCtxt, TypeVisitableExt,
|
||||
};
|
||||
use rustc_session::lint::builtin::AMBIGUOUS_ASSOCIATED_ITEMS;
|
||||
use rustc_span::edit_distance::find_best_match_for_name;
|
||||
|
|
@ -2322,6 +2321,114 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
self.ast_ty_to_ty_inner(ast_ty, false, true)
|
||||
}
|
||||
|
||||
fn check_delegation_constraints(&self, sig_id: DefId, span: Span, emit: bool) -> bool {
|
||||
let mut error_occured = false;
|
||||
let sig_span = self.tcx().def_span(sig_id);
|
||||
let mut try_emit = |descr| {
|
||||
if emit {
|
||||
self.tcx().dcx().emit_err(crate::errors::NotSupportedDelegation {
|
||||
span,
|
||||
descr,
|
||||
callee_span: sig_span,
|
||||
});
|
||||
}
|
||||
error_occured = true;
|
||||
};
|
||||
|
||||
if let Some(node) = self.tcx().hir().get_if_local(sig_id)
|
||||
&& let Some(decl) = node.fn_decl()
|
||||
&& let hir::FnRetTy::Return(ty) = decl.output
|
||||
&& let hir::TyKind::InferDelegation(_, _) = ty.kind
|
||||
{
|
||||
try_emit("recursive delegation");
|
||||
}
|
||||
|
||||
let sig = self.tcx().fn_sig(sig_id).instantiate_identity();
|
||||
if sig.output().has_opaque_types() {
|
||||
try_emit("delegation to a function with opaque type");
|
||||
}
|
||||
|
||||
let sig_generics = self.tcx().generics_of(sig_id);
|
||||
let parent = self.tcx().parent(self.item_def_id());
|
||||
let parent_generics = self.tcx().generics_of(parent);
|
||||
|
||||
let parent_is_trait = (self.tcx().def_kind(parent) == DefKind::Trait) as usize;
|
||||
let sig_has_self = sig_generics.has_self as usize;
|
||||
|
||||
if sig_generics.count() > sig_has_self || parent_generics.count() > parent_is_trait {
|
||||
try_emit("delegation with early bound generics");
|
||||
}
|
||||
|
||||
if self.tcx().asyncness(sig_id) == ty::Asyncness::Yes {
|
||||
try_emit("delegation to async functions");
|
||||
}
|
||||
|
||||
if self.tcx().constness(sig_id) == hir::Constness::Const {
|
||||
try_emit("delegation to const functions");
|
||||
}
|
||||
|
||||
if sig.c_variadic() {
|
||||
try_emit("delegation to variadic functions");
|
||||
// variadic functions are also `unsafe` and `extern "C"`.
|
||||
// Do not emit same error multiple times.
|
||||
return error_occured;
|
||||
}
|
||||
|
||||
if let hir::Unsafety::Unsafe = sig.unsafety() {
|
||||
try_emit("delegation to unsafe functions");
|
||||
}
|
||||
|
||||
if abi::Abi::Rust != sig.abi() {
|
||||
try_emit("delegation to non Rust ABI functions");
|
||||
}
|
||||
|
||||
error_occured
|
||||
}
|
||||
|
||||
fn ty_from_delegation(
|
||||
&self,
|
||||
sig_id: DefId,
|
||||
idx: hir::InferDelegationKind,
|
||||
span: Span,
|
||||
) -> Ty<'tcx> {
|
||||
if self.check_delegation_constraints(sig_id, span, idx == hir::InferDelegationKind::Output)
|
||||
{
|
||||
let e = self.tcx().dcx().span_delayed_bug(span, "not supported delegation case");
|
||||
self.set_tainted_by_errors(e);
|
||||
return Ty::new_error(self.tcx(), e);
|
||||
};
|
||||
let sig = self.tcx().fn_sig(sig_id);
|
||||
let sig_generics = self.tcx().generics_of(sig_id);
|
||||
|
||||
let parent = self.tcx().parent(self.item_def_id());
|
||||
let parent_def_kind = self.tcx().def_kind(parent);
|
||||
|
||||
let sig = if let DefKind::Impl { .. } = parent_def_kind
|
||||
&& sig_generics.has_self
|
||||
{
|
||||
// Generic params can't be here except the trait self type.
|
||||
// They are not supported yet.
|
||||
assert_eq!(sig_generics.count(), 1);
|
||||
assert_eq!(self.tcx().generics_of(parent).count(), 0);
|
||||
|
||||
let self_ty = self.tcx().type_of(parent).instantiate_identity();
|
||||
let generic_self_ty = ty::GenericArg::from(self_ty);
|
||||
let substs = self.tcx().mk_args_from_iter(std::iter::once(generic_self_ty));
|
||||
sig.instantiate(self.tcx(), substs)
|
||||
} else {
|
||||
sig.instantiate_identity()
|
||||
};
|
||||
|
||||
// Bound vars are also inherited from `sig_id`. They will be
|
||||
// rebinded later in `ty_of_fn`.
|
||||
let sig = sig.skip_binder();
|
||||
|
||||
match idx {
|
||||
hir::InferDelegationKind::Input(id) => sig.inputs()[id],
|
||||
hir::InferDelegationKind::Output => sig.output(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Turns a `hir::Ty` into a `Ty`. For diagnostics' purposes we keep track of whether trait
|
||||
/// objects are borrowed like `&dyn Trait` to avoid emitting redundant errors.
|
||||
#[instrument(level = "debug", skip(self), ret)]
|
||||
|
|
@ -2329,6 +2436,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
let tcx = self.tcx();
|
||||
|
||||
let result_ty = match &ast_ty.kind {
|
||||
hir::TyKind::InferDelegation(sig_id, idx) => {
|
||||
self.ty_from_delegation(*sig_id, *idx, ast_ty.span)
|
||||
}
|
||||
hir::TyKind::Slice(ty) => Ty::new_slice(tcx, self.ast_ty_to_ty(ty)),
|
||||
hir::TyKind::Ptr(mt) => {
|
||||
Ty::new_ptr(tcx, ty::TypeAndMut { ty: self.ast_ty_to_ty(mt.ty), mutbl: mt.mutbl })
|
||||
|
|
@ -2520,7 +2630,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
hir_ty: Option<&hir::Ty<'_>>,
|
||||
) -> ty::PolyFnSig<'tcx> {
|
||||
let tcx = self.tcx();
|
||||
let bound_vars = tcx.late_bound_vars(hir_id);
|
||||
let bound_vars = if let hir::FnRetTy::Return(ret_ty) = decl.output
|
||||
&& let hir::TyKind::InferDelegation(sig_id, _) = ret_ty.kind
|
||||
{
|
||||
tcx.fn_sig(sig_id).skip_binder().bound_vars()
|
||||
} else {
|
||||
tcx.late_bound_vars(hir_id)
|
||||
};
|
||||
debug!(?bound_vars);
|
||||
|
||||
// We proactively collect all the inferred type params to emit a single error per fn def.
|
||||
|
|
@ -2543,7 +2659,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
self.suggest_trait_fn_ty_for_impl_fn_infer(hir_id, Some(i))
|
||||
{
|
||||
infer_replacements.push((a.span, suggested_ty.to_string()));
|
||||
return suggested_ty;
|
||||
return Ty::new_error_with_message(
|
||||
self.tcx(),
|
||||
a.span,
|
||||
suggested_ty.to_string(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2561,7 +2681,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
self.suggest_trait_fn_ty_for_impl_fn_infer(hir_id, None)
|
||||
{
|
||||
infer_replacements.push((output.span, suggested_ty.to_string()));
|
||||
suggested_ty
|
||||
Ty::new_error_with_message(self.tcx(), output.span, suggested_ty.to_string())
|
||||
} else {
|
||||
visitor.visit_ty(output);
|
||||
self.ast_ty_to_ty(output)
|
||||
|
|
|
|||
|
|
@ -996,7 +996,7 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>)
|
|||
|
||||
if adt.is_union() && !tcx.features().transparent_unions {
|
||||
feature_err(
|
||||
&tcx.sess.parse_sess,
|
||||
&tcx.sess,
|
||||
sym::transparent_unions,
|
||||
tcx.def_span(adt.did()),
|
||||
"transparent unions are unstable",
|
||||
|
|
@ -1128,7 +1128,7 @@ fn check_enum(tcx: TyCtxt<'_>, def_id: LocalDefId) {
|
|||
if repr_type_ty == tcx.types.i128 || repr_type_ty == tcx.types.u128 {
|
||||
if !tcx.features().repr128 {
|
||||
feature_err(
|
||||
&tcx.sess.parse_sess,
|
||||
&tcx.sess,
|
||||
sym::repr128,
|
||||
tcx.def_span(def_id),
|
||||
"repr with 128-bit type is unstable",
|
||||
|
|
|
|||
|
|
@ -293,7 +293,7 @@ fn default_body_is_unstable(
|
|||
|
||||
rustc_session::parse::add_feature_diagnostics_for_issue(
|
||||
&mut err,
|
||||
&tcx.sess.parse_sess,
|
||||
&tcx.sess,
|
||||
feature,
|
||||
rustc_feature::GateIssue::Library(issue),
|
||||
false,
|
||||
|
|
|
|||
|
|
@ -1591,7 +1591,7 @@ fn check_method_receiver<'tcx>(
|
|||
return Err(if receiver_is_valid(wfcx, span, receiver_ty, self_ty, true) {
|
||||
// Report error; would have worked with `arbitrary_self_types`.
|
||||
feature_err(
|
||||
&tcx.sess.parse_sess,
|
||||
&tcx.sess,
|
||||
sym::arbitrary_self_types,
|
||||
span,
|
||||
format!(
|
||||
|
|
|
|||
|
|
@ -1189,12 +1189,13 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
|
|||
&& !self.tcx.asyncness(lifetime_ref.hir_id.owner.def_id).is_async()
|
||||
&& !self.tcx.features().anonymous_lifetime_in_impl_trait
|
||||
{
|
||||
let mut diag = rustc_session::parse::feature_err(
|
||||
&self.tcx.sess.parse_sess,
|
||||
sym::anonymous_lifetime_in_impl_trait,
|
||||
lifetime_ref.ident.span,
|
||||
"anonymous lifetimes in `impl Trait` are unstable",
|
||||
);
|
||||
let mut diag: rustc_errors::DiagnosticBuilder<'_> =
|
||||
rustc_session::parse::feature_err(
|
||||
&self.tcx.sess,
|
||||
sym::anonymous_lifetime_in_impl_trait,
|
||||
lifetime_ref.ident.span,
|
||||
"anonymous lifetimes in `impl Trait` are unstable",
|
||||
);
|
||||
|
||||
if let Some(generics) =
|
||||
self.tcx.hir().get_generics(lifetime_ref.hir_id.owner.def_id)
|
||||
|
|
|
|||
|
|
@ -639,7 +639,7 @@ fn check_feature_inherent_assoc_ty(tcx: TyCtxt<'_>, span: Span) {
|
|||
use rustc_session::parse::feature_err;
|
||||
use rustc_span::symbol::sym;
|
||||
feature_err(
|
||||
&tcx.sess.parse_sess,
|
||||
&tcx.sess,
|
||||
sym::inherent_associated_types,
|
||||
span,
|
||||
"inherent associated types are unstable",
|
||||
|
|
|
|||
|
|
@ -1501,3 +1501,13 @@ pub enum RefOfMutStaticSugg {
|
|||
var: String,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_analysis_not_supported_delegation)]
|
||||
pub struct NotSupportedDelegation<'a> {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub descr: &'a str,
|
||||
#[label]
|
||||
pub callee_span: Span,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -116,7 +116,8 @@ use rustc_hir::def::DefKind;
|
|||
rustc_fluent_macro::fluent_messages! { "../messages.ftl" }
|
||||
|
||||
fn require_c_abi_if_c_variadic(tcx: TyCtxt<'_>, decl: &hir::FnDecl<'_>, abi: Abi, span: Span) {
|
||||
const CONVENTIONS_UNSTABLE: &str = "`C`, `cdecl`, `aapcs`, `win64`, `sysv64` or `efiapi`";
|
||||
const CONVENTIONS_UNSTABLE: &str =
|
||||
"`C`, `cdecl`, `system`, `aapcs`, `win64`, `sysv64` or `efiapi`";
|
||||
const CONVENTIONS_STABLE: &str = "`C` or `cdecl`";
|
||||
const UNSTABLE_EXPLAIN: &str =
|
||||
"using calling conventions other than `C` or `cdecl` for varargs functions is unstable";
|
||||
|
|
@ -133,13 +134,8 @@ fn require_c_abi_if_c_variadic(tcx: TyCtxt<'_>, decl: &hir::FnDecl<'_>, abi: Abi
|
|||
// Using this ABI would be ok, if the feature for additional ABI support was enabled.
|
||||
// Return CONVENTIONS_STABLE, because we want the other error to look the same.
|
||||
(false, true) => {
|
||||
feature_err(
|
||||
&tcx.sess.parse_sess,
|
||||
sym::extended_varargs_abi_support,
|
||||
span,
|
||||
UNSTABLE_EXPLAIN,
|
||||
)
|
||||
.emit();
|
||||
feature_err(&tcx.sess, sym::extended_varargs_abi_support, span, UNSTABLE_EXPLAIN)
|
||||
.emit();
|
||||
CONVENTIONS_STABLE
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -320,7 +320,7 @@ impl<'a> State<'a> {
|
|||
self.word("/*ERROR*/");
|
||||
self.pclose();
|
||||
}
|
||||
hir::TyKind::Infer => {
|
||||
hir::TyKind::Infer | hir::TyKind::InferDelegation(..) => {
|
||||
self.word("_");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -704,7 +704,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
|
|||
|
||||
if has_unsized_tuple_coercion && !self.tcx.features().unsized_tuple_coercion {
|
||||
feature_err(
|
||||
&self.tcx.sess.parse_sess,
|
||||
&self.tcx.sess,
|
||||
sym::unsized_tuple_coercion,
|
||||
self.cause.span,
|
||||
"unsized tuple coercion is not stable enough for use and is subject to change",
|
||||
|
|
|
|||
|
|
@ -1865,7 +1865,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
(ty::Adt(adt, _), ty::Adt(base_adt, _)) if adt == base_adt);
|
||||
if self.tcx.sess.is_nightly_build() && same_adt {
|
||||
feature_err(
|
||||
&self.tcx.sess.parse_sess,
|
||||
&self.tcx.sess,
|
||||
sym::type_changing_struct_update,
|
||||
base_expr.span,
|
||||
"type changing struct updating is experimental",
|
||||
|
|
@ -3262,7 +3262,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
|
||||
if !self.tcx.features().offset_of_enum {
|
||||
rustc_session::parse::feature_err(
|
||||
&self.tcx.sess.parse_sess,
|
||||
&self.tcx.sess,
|
||||
sym::offset_of_enum,
|
||||
ident.span,
|
||||
"using enums in offset_of is experimental",
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
selection_cache: self.selection_cache.clone(),
|
||||
evaluation_cache: self.evaluation_cache.clone(),
|
||||
reported_trait_errors: self.reported_trait_errors.clone(),
|
||||
reported_closure_mismatch: self.reported_closure_mismatch.clone(),
|
||||
reported_signature_mismatch: self.reported_signature_mismatch.clone(),
|
||||
tainted_by_errors: self.tainted_by_errors.clone(),
|
||||
err_count_on_creation: self.err_count_on_creation,
|
||||
universe: self.universe.clone(),
|
||||
|
|
|
|||
|
|
@ -278,7 +278,7 @@ pub struct InferCtxt<'tcx> {
|
|||
/// avoid reporting the same error twice.
|
||||
pub reported_trait_errors: RefCell<FxIndexMap<Span, Vec<ty::Predicate<'tcx>>>>,
|
||||
|
||||
pub reported_closure_mismatch: RefCell<FxHashSet<(Span, Option<Span>)>>,
|
||||
pub reported_signature_mismatch: RefCell<FxHashSet<(Span, Option<Span>)>>,
|
||||
|
||||
/// When an error occurs, we want to avoid reporting "derived"
|
||||
/// errors that are due to this original failure. Normally, we
|
||||
|
|
@ -702,7 +702,7 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
|
|||
selection_cache: Default::default(),
|
||||
evaluation_cache: Default::default(),
|
||||
reported_trait_errors: Default::default(),
|
||||
reported_closure_mismatch: Default::default(),
|
||||
reported_signature_mismatch: Default::default(),
|
||||
tainted_by_errors: Cell::new(None),
|
||||
err_count_on_creation: tcx.dcx().err_count(),
|
||||
universe: Cell::new(ty::UniverseIndex::ROOT),
|
||||
|
|
|
|||
|
|
@ -202,8 +202,15 @@ pub(crate) fn parse_check_cfg(dcx: &DiagCtxt, specs: Vec<String>) -> CheckCfg {
|
|||
if !args.is_empty() {
|
||||
error!("`any()` must be empty");
|
||||
}
|
||||
} else if arg.has_name(sym::none)
|
||||
&& let Some(args) = arg.meta_item_list()
|
||||
{
|
||||
values.insert(None);
|
||||
if !args.is_empty() {
|
||||
error!("`none()` must be empty");
|
||||
}
|
||||
} else {
|
||||
error!("`values()` arguments must be string literals or `any()`");
|
||||
error!("`values()` arguments must be string literals, `none()` or `any()`");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -1306,10 +1306,7 @@ impl<'tcx> LateLintPass<'tcx> for UngatedAsyncFnTrackCaller {
|
|||
cx.emit_spanned_lint(
|
||||
UNGATED_ASYNC_FN_TRACK_CALLER,
|
||||
attr.span,
|
||||
BuiltinUngatedAsyncFnTrackCaller {
|
||||
label: span,
|
||||
parse_sess: &cx.tcx.sess.parse_sess,
|
||||
},
|
||||
BuiltinUngatedAsyncFnTrackCaller { label: span, session: &cx.tcx.sess },
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -786,7 +786,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
|
|||
if let ast::LitKind::Str(rationale, _) = name_value.kind {
|
||||
if !self.features.lint_reasons {
|
||||
feature_err(
|
||||
&self.sess.parse_sess,
|
||||
&self.sess,
|
||||
sym::lint_reasons,
|
||||
item.span,
|
||||
"lint reasons are experimental",
|
||||
|
|
@ -1074,7 +1074,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
|
|||
lint.note(fluent::lint_note);
|
||||
rustc_session::parse::add_feature_diagnostics_for_issue(
|
||||
lint,
|
||||
&self.sess.parse_sess,
|
||||
&self.sess,
|
||||
feature,
|
||||
GateIssue::Language,
|
||||
lint_from_cli,
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ use rustc_macros::{LintDiagnostic, Subdiagnostic};
|
|||
use rustc_middle::ty::{
|
||||
inhabitedness::InhabitedPredicate, Clause, PolyExistentialTraitRef, Ty, TyCtxt,
|
||||
};
|
||||
use rustc_session::parse::ParseSess;
|
||||
use rustc_session::Session;
|
||||
use rustc_span::{edition::Edition, sym, symbol::Ident, Span, Symbol};
|
||||
|
||||
use crate::{
|
||||
|
|
@ -235,7 +235,7 @@ pub struct BuiltinUnstableFeatures;
|
|||
// lint_ungated_async_fn_track_caller
|
||||
pub struct BuiltinUngatedAsyncFnTrackCaller<'a> {
|
||||
pub label: Span,
|
||||
pub parse_sess: &'a ParseSess,
|
||||
pub session: &'a Session,
|
||||
}
|
||||
|
||||
impl<'a> DecorateLint<'a, ()> for BuiltinUngatedAsyncFnTrackCaller<'_> {
|
||||
|
|
@ -243,7 +243,7 @@ impl<'a> DecorateLint<'a, ()> for BuiltinUngatedAsyncFnTrackCaller<'_> {
|
|||
diag.span_label(self.label, fluent::lint_label);
|
||||
rustc_session::parse::add_feature_diagnostics(
|
||||
diag,
|
||||
self.parse_sess,
|
||||
self.session,
|
||||
sym::async_fn_track_caller,
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ pub(crate) fn collect(tcx: TyCtxt<'_>, LocalCrate: LocalCrate) -> Vec<NativeLib>
|
|||
|
||||
pub(crate) fn relevant_lib(sess: &Session, lib: &NativeLib) -> bool {
|
||||
match lib.cfg {
|
||||
Some(ref cfg) => attr::cfg_matches(cfg, &sess.parse_sess, CRATE_NODE_ID, None),
|
||||
Some(ref cfg) => attr::cfg_matches(cfg, sess, CRATE_NODE_ID, None),
|
||||
None => true,
|
||||
}
|
||||
}
|
||||
|
|
@ -163,7 +163,7 @@ impl<'tcx> Collector<'tcx> {
|
|||
"link-arg" => {
|
||||
if !features.link_arg_attribute {
|
||||
feature_err(
|
||||
&sess.parse_sess,
|
||||
sess,
|
||||
sym::link_arg_attribute,
|
||||
span,
|
||||
"link kind `link-arg` is unstable",
|
||||
|
|
@ -206,13 +206,8 @@ impl<'tcx> Collector<'tcx> {
|
|||
continue;
|
||||
};
|
||||
if !features.link_cfg {
|
||||
feature_err(
|
||||
&sess.parse_sess,
|
||||
sym::link_cfg,
|
||||
item.span(),
|
||||
"link cfg is unstable",
|
||||
)
|
||||
.emit();
|
||||
feature_err(sess, sym::link_cfg, item.span(), "link cfg is unstable")
|
||||
.emit();
|
||||
}
|
||||
cfg = Some(link_cfg.clone());
|
||||
}
|
||||
|
|
@ -277,7 +272,7 @@ impl<'tcx> Collector<'tcx> {
|
|||
macro report_unstable_modifier($feature: ident) {
|
||||
if !features.$feature {
|
||||
feature_err(
|
||||
&sess.parse_sess,
|
||||
sess,
|
||||
sym::$feature,
|
||||
span,
|
||||
format!("linking modifier `{modifier}` is unstable"),
|
||||
|
|
@ -520,11 +515,23 @@ impl<'tcx> Collector<'tcx> {
|
|||
) -> DllImport {
|
||||
let span = self.tcx.def_span(item);
|
||||
|
||||
// this logic is similar to `Target::adjust_abi` (in rustc_target/src/spec/mod.rs) but errors on unsupported inputs
|
||||
let calling_convention = if self.tcx.sess.target.arch == "x86" {
|
||||
match abi {
|
||||
Abi::C { .. } | Abi::Cdecl { .. } => DllCallingConvention::C,
|
||||
Abi::Stdcall { .. } | Abi::System { .. } => {
|
||||
DllCallingConvention::Stdcall(self.i686_arg_list_size(item))
|
||||
Abi::Stdcall { .. } => DllCallingConvention::Stdcall(self.i686_arg_list_size(item)),
|
||||
// On Windows, `extern "system"` behaves like msvc's `__stdcall`.
|
||||
// `__stdcall` only applies on x86 and on non-variadic functions:
|
||||
// https://learn.microsoft.com/en-us/cpp/cpp/stdcall?view=msvc-170
|
||||
Abi::System { .. } => {
|
||||
let c_variadic =
|
||||
self.tcx.type_of(item).instantiate_identity().fn_sig(self.tcx).c_variadic();
|
||||
|
||||
if c_variadic {
|
||||
DllCallingConvention::C
|
||||
} else {
|
||||
DllCallingConvention::Stdcall(self.i686_arg_list_size(item))
|
||||
}
|
||||
}
|
||||
Abi::Fastcall { .. } => {
|
||||
DllCallingConvention::Fastcall(self.i686_arg_list_size(item))
|
||||
|
|
|
|||
|
|
@ -116,8 +116,7 @@ pub fn report_unstable(
|
|||
if is_soft {
|
||||
soft_handler(SOFT_UNSTABLE, span, msg)
|
||||
} else {
|
||||
let mut err =
|
||||
feature_err_issue(&sess.parse_sess, feature, span, GateIssue::Library(issue), msg);
|
||||
let mut err = feature_err_issue(sess, feature, span, GateIssue::Library(issue), msg);
|
||||
if let Some((inner_types, msg, sugg, applicability)) = suggestion {
|
||||
err.span_suggestion(inner_types, msg, sugg, applicability);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -611,9 +611,6 @@ pub enum SelectionError<'tcx> {
|
|||
NotConstEvaluatable(NotConstEvaluatable),
|
||||
/// Exceeded the recursion depth during type projection.
|
||||
Overflow(OverflowError),
|
||||
/// Signaling that an error has already been emitted, to avoid
|
||||
/// multiple errors being shown.
|
||||
ErrorReporting,
|
||||
/// Computing an opaque type's hidden type caused an error (e.g. a cycle error).
|
||||
/// We can thus not know whether the hidden type implements an auto trait, so
|
||||
/// we should not presume anything about it.
|
||||
|
|
|
|||
|
|
@ -302,7 +302,6 @@ impl EvaluationResult {
|
|||
pub enum OverflowError {
|
||||
Error(ErrorGuaranteed),
|
||||
Canonical,
|
||||
ErrorReporting,
|
||||
}
|
||||
|
||||
impl From<ErrorGuaranteed> for OverflowError {
|
||||
|
|
@ -318,7 +317,6 @@ impl<'tcx> From<OverflowError> for SelectionError<'tcx> {
|
|||
match overflow_error {
|
||||
OverflowError::Error(e) => SelectionError::Overflow(OverflowError::Error(e)),
|
||||
OverflowError::Canonical => SelectionError::Overflow(OverflowError::Canonical),
|
||||
OverflowError::ErrorReporting => SelectionError::ErrorReporting,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ use rustc_data_structures::unord::UnordMap;
|
|||
use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed, StashKey};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::{CtorKind, CtorOf, DefKind, DocLinkResMap, LifetimeRes, Res};
|
||||
use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LocalDefIdMap};
|
||||
use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LocalDefIdMap, LocalDefIdSet};
|
||||
use rustc_index::IndexVec;
|
||||
use rustc_macros::HashStable;
|
||||
use rustc_query_system::ich::StableHashingContext;
|
||||
|
|
@ -202,6 +202,10 @@ pub struct ResolverAstLowering {
|
|||
|
||||
/// Lints that were emitted by the resolver and early lints.
|
||||
pub lint_buffer: Steal<LintBuffer>,
|
||||
|
||||
/// Information about functions signatures for delegation items expansion
|
||||
pub has_self: LocalDefIdSet,
|
||||
pub fn_parameter_counts: LocalDefIdMap<usize>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
|
|
|
|||
|
|
@ -252,6 +252,8 @@ impl<'a> Parser<'a> {
|
|||
{
|
||||
// IMPL ITEM
|
||||
self.parse_item_impl(attrs, def_())?
|
||||
} else if self.is_reuse_path_item() {
|
||||
self.parse_item_delegation()?
|
||||
} else if self.check_keyword(kw::Mod)
|
||||
|| self.check_keyword(kw::Unsafe) && self.is_keyword_ahead(1, &[kw::Mod])
|
||||
{
|
||||
|
|
@ -349,11 +351,18 @@ impl<'a> Parser<'a> {
|
|||
/// When parsing a statement, would the start of a path be an item?
|
||||
pub(super) fn is_path_start_item(&mut self) -> bool {
|
||||
self.is_kw_followed_by_ident(kw::Union) // no: `union::b`, yes: `union U { .. }`
|
||||
|| self.is_reuse_path_item()
|
||||
|| self.check_auto_or_unsafe_trait_item() // no: `auto::b`, yes: `auto trait X { .. }`
|
||||
|| self.is_async_fn() // no(2015): `async::b`, yes: `async fn`
|
||||
|| matches!(self.is_macro_rules_item(), IsMacroRulesItem::Yes{..}) // no: `macro_rules::b`, yes: `macro_rules! mac`
|
||||
}
|
||||
|
||||
fn is_reuse_path_item(&mut self) -> bool {
|
||||
// no: `reuse ::path` for compatibility reasons with macro invocations
|
||||
self.token.is_keyword(kw::Reuse)
|
||||
&& self.look_ahead(1, |t| t.is_path_start() && t.kind != token::ModSep)
|
||||
}
|
||||
|
||||
/// Are we sure this could not possibly be a macro invocation?
|
||||
fn isnt_macro_invocation(&mut self) -> bool {
|
||||
self.check_ident() && self.look_ahead(1, |t| *t != token::Not && *t != token::ModSep)
|
||||
|
|
@ -655,6 +664,33 @@ impl<'a> Parser<'a> {
|
|||
Ok((Ident::empty(), item_kind))
|
||||
}
|
||||
|
||||
fn parse_item_delegation(&mut self) -> PResult<'a, ItemInfo> {
|
||||
let span = self.token.span;
|
||||
self.expect_keyword(kw::Reuse)?;
|
||||
|
||||
let (qself, path) = if self.eat_lt() {
|
||||
let (qself, path) = self.parse_qpath(PathStyle::Expr)?;
|
||||
(Some(qself), path)
|
||||
} else {
|
||||
(None, self.parse_path(PathStyle::Expr)?)
|
||||
};
|
||||
|
||||
let body = if self.check(&token::OpenDelim(Delimiter::Brace)) {
|
||||
Some(self.parse_block()?)
|
||||
} else {
|
||||
self.expect(&token::Semi)?;
|
||||
None
|
||||
};
|
||||
let span = span.to(self.prev_token.span);
|
||||
self.sess.gated_spans.gate(sym::fn_delegation, span);
|
||||
|
||||
let ident = path.segments.last().map(|seg| seg.ident).unwrap_or(Ident::empty());
|
||||
Ok((
|
||||
ident,
|
||||
ItemKind::Delegation(Box::new(Delegation { id: DUMMY_NODE_ID, qself, path, body })),
|
||||
))
|
||||
}
|
||||
|
||||
fn parse_item_list<T>(
|
||||
&mut self,
|
||||
attrs: &mut AttrVec,
|
||||
|
|
|
|||
|
|
@ -1170,7 +1170,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
sym::rust_logo => {
|
||||
if !self.tcx.features().rustdoc_internals {
|
||||
feature_err(
|
||||
&self.tcx.sess.parse_sess,
|
||||
&self.tcx.sess,
|
||||
sym::rustdoc_internals,
|
||||
meta.span(),
|
||||
"the `#[doc(rust_logo)]` attribute is used for Rust branding",
|
||||
|
|
@ -1815,7 +1815,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
(target, self.tcx.features().fn_align)
|
||||
{
|
||||
feature_err(
|
||||
&self.tcx.sess.parse_sess,
|
||||
&self.tcx.sess,
|
||||
sym::fn_align,
|
||||
hint.span(),
|
||||
"`repr(align)` attributes on functions are unstable",
|
||||
|
|
|
|||
|
|
@ -147,7 +147,7 @@ impl<'tcx> CheckConstVisitor<'tcx> {
|
|||
[missing_primary, ref missing_secondary @ ..] => {
|
||||
let msg =
|
||||
format!("{} is not allowed in a `{}`", expr.name(), const_kind.keyword_name());
|
||||
let mut err = feature_err(&tcx.sess.parse_sess, *missing_primary, span, msg);
|
||||
let mut err = feature_err(&tcx.sess, *missing_primary, span, msg);
|
||||
|
||||
// If multiple feature gates would be required to enable this expression, include
|
||||
// them as help messages. Don't emit a separate error for each missing feature gate.
|
||||
|
|
|
|||
|
|
@ -45,14 +45,13 @@ impl DebuggerVisualizerCollector<'_> {
|
|||
}
|
||||
};
|
||||
|
||||
let file =
|
||||
match resolve_path(&self.sess.parse_sess, visualizer_path.as_str(), attr.span) {
|
||||
Ok(file) => file,
|
||||
Err(err) => {
|
||||
err.emit();
|
||||
return;
|
||||
}
|
||||
};
|
||||
let file = match resolve_path(&self.sess, visualizer_path.as_str(), attr.span) {
|
||||
Ok(file) => file,
|
||||
Err(err) => {
|
||||
err.emit();
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
match std::fs::read(&file) {
|
||||
Ok(contents) => {
|
||||
|
|
|
|||
|
|
@ -135,7 +135,7 @@ fn configure_main(tcx: TyCtxt<'_>, visitor: &EntryContext<'_>) -> Option<(DefId,
|
|||
if main_def.is_import && !tcx.features().imported_main {
|
||||
let span = main_def.span;
|
||||
feature_err(
|
||||
&tcx.sess.parse_sess,
|
||||
&tcx.sess,
|
||||
sym::imported_main,
|
||||
span,
|
||||
"using an imported function as entry point `main` is experimental",
|
||||
|
|
|
|||
|
|
@ -341,6 +341,7 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> {
|
|||
record_variants!(
|
||||
(self, t, t.kind, Id::Node(t.hir_id), hir, Ty, TyKind),
|
||||
[
|
||||
InferDelegation,
|
||||
Slice,
|
||||
Array,
|
||||
Ptr,
|
||||
|
|
@ -521,7 +522,8 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> {
|
|||
TraitAlias,
|
||||
Impl,
|
||||
MacCall,
|
||||
MacroDef
|
||||
MacroDef,
|
||||
Delegation
|
||||
]
|
||||
);
|
||||
ast_visit::walk_item(self, i)
|
||||
|
|
@ -645,7 +647,7 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> {
|
|||
fn visit_assoc_item(&mut self, i: &'v ast::AssocItem, ctxt: ast_visit::AssocCtxt) {
|
||||
record_variants!(
|
||||
(self, i, i.kind, Id::None, ast, AssocItem, AssocItemKind),
|
||||
[Const, Fn, Type, MacCall]
|
||||
[Const, Fn, Type, MacCall, Delegation]
|
||||
);
|
||||
ast_visit::walk_assoc_item(self, i, ctxt);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -271,7 +271,7 @@ impl<'ast, 'tcx> visit::Visitor<'ast> for LanguageItemCollector<'ast, 'tcx> {
|
|||
ast::ItemKind::Use(_) => Target::Use,
|
||||
ast::ItemKind::Static(_) => Target::Static,
|
||||
ast::ItemKind::Const(_) => Target::Const,
|
||||
ast::ItemKind::Fn(_) => Target::Fn,
|
||||
ast::ItemKind::Fn(_) | ast::ItemKind::Delegation(..) => Target::Fn,
|
||||
ast::ItemKind::Mod(_, _) => Target::Mod,
|
||||
ast::ItemKind::ForeignMod(_) => Target::ForeignFn,
|
||||
ast::ItemKind::GlobalAsm(_) => Target::GlobalAsm,
|
||||
|
|
@ -315,24 +315,29 @@ impl<'ast, 'tcx> visit::Visitor<'ast> for LanguageItemCollector<'ast, 'tcx> {
|
|||
|
||||
fn visit_assoc_item(&mut self, i: &'ast ast::AssocItem, ctxt: visit::AssocCtxt) {
|
||||
let (target, generics) = match &i.kind {
|
||||
ast::AssocItemKind::Fn(fun) => (
|
||||
match &self.parent_item.unwrap().kind {
|
||||
ast::ItemKind::Impl(i) => {
|
||||
if i.of_trait.is_some() {
|
||||
Target::Method(MethodKind::Trait { body: fun.body.is_some() })
|
||||
} else {
|
||||
Target::Method(MethodKind::Inherent)
|
||||
ast::AssocItemKind::Fn(..) | ast::AssocItemKind::Delegation(..) => {
|
||||
let (body, generics) = if let ast::AssocItemKind::Fn(fun) = &i.kind {
|
||||
(fun.body.is_some(), Some(&fun.generics))
|
||||
} else {
|
||||
(true, None)
|
||||
};
|
||||
(
|
||||
match &self.parent_item.unwrap().kind {
|
||||
ast::ItemKind::Impl(i) => {
|
||||
if i.of_trait.is_some() {
|
||||
Target::Method(MethodKind::Trait { body })
|
||||
} else {
|
||||
Target::Method(MethodKind::Inherent)
|
||||
}
|
||||
}
|
||||
}
|
||||
ast::ItemKind::Trait(_) => {
|
||||
Target::Method(MethodKind::Trait { body: fun.body.is_some() })
|
||||
}
|
||||
_ => unreachable!(),
|
||||
},
|
||||
&fun.generics,
|
||||
),
|
||||
ast::AssocItemKind::Const(ct) => (Target::AssocConst, &ct.generics),
|
||||
ast::AssocItemKind::Type(ty) => (Target::AssocTy, &ty.generics),
|
||||
ast::ItemKind::Trait(_) => Target::Method(MethodKind::Trait { body }),
|
||||
_ => unreachable!(),
|
||||
},
|
||||
generics,
|
||||
)
|
||||
}
|
||||
ast::AssocItemKind::Const(ct) => (Target::AssocConst, Some(&ct.generics)),
|
||||
ast::AssocItemKind::Type(ty) => (Target::AssocTy, Some(&ty.generics)),
|
||||
ast::AssocItemKind::MacCall(_) => unreachable!("macros should have been expanded"),
|
||||
};
|
||||
|
||||
|
|
@ -341,7 +346,7 @@ impl<'ast, 'tcx> visit::Visitor<'ast> for LanguageItemCollector<'ast, 'tcx> {
|
|||
self.resolver.node_id_to_def_id[&i.id],
|
||||
&i.attrs,
|
||||
i.span,
|
||||
Some(generics),
|
||||
generics,
|
||||
);
|
||||
|
||||
visit::walk_assoc_item(self, i, ctxt);
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ use crate::{Resolver, ResolverArenas, Segment, ToNameBinding, VisResolutionError
|
|||
|
||||
use rustc_ast::visit::{self, AssocCtxt, Visitor};
|
||||
use rustc_ast::{self as ast, AssocItem, AssocItemKind, MetaItemKind, StmtKind};
|
||||
use rustc_ast::{Block, Fn, ForeignItem, ForeignItemKind, Impl, Item, ItemKind, NodeId};
|
||||
use rustc_ast::{Block, ForeignItem, ForeignItemKind, Impl, Item, ItemKind, NodeId};
|
||||
use rustc_attr as attr;
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_errors::{struct_span_code_err, Applicability};
|
||||
|
|
@ -686,10 +686,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
|
|||
}
|
||||
|
||||
// These items live in the value namespace.
|
||||
ItemKind::Static(..) => {
|
||||
self.r.define(parent, ident, ValueNS, (res, vis, sp, expansion));
|
||||
}
|
||||
ItemKind::Const(..) => {
|
||||
ItemKind::Const(..) | ItemKind::Delegation(..) | ItemKind::Static(..) => {
|
||||
self.r.define(parent, ident, ValueNS, (res, vis, sp, expansion));
|
||||
}
|
||||
ItemKind::Fn(..) => {
|
||||
|
|
@ -701,11 +698,11 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
|
|||
}
|
||||
|
||||
// These items live in the type namespace.
|
||||
ItemKind::TyAlias(..) => {
|
||||
ItemKind::TyAlias(..) | ItemKind::TraitAlias(..) => {
|
||||
self.r.define(parent, ident, TypeNS, (res, vis, sp, expansion));
|
||||
}
|
||||
|
||||
ItemKind::Enum(_, _) => {
|
||||
ItemKind::Enum(_, _) | ItemKind::Trait(..) => {
|
||||
let module = self.r.new_module(
|
||||
Some(parent),
|
||||
ModuleKind::Def(def_kind, def_id, ident.name),
|
||||
|
|
@ -717,10 +714,6 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
|
|||
self.parent_scope.module = module;
|
||||
}
|
||||
|
||||
ItemKind::TraitAlias(..) => {
|
||||
self.r.define(parent, ident, TypeNS, (res, vis, sp, expansion));
|
||||
}
|
||||
|
||||
// These items live in both the type and value namespaces.
|
||||
ItemKind::Struct(ref vdata, _) => {
|
||||
// Define a name in the type namespace.
|
||||
|
|
@ -778,19 +771,6 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
|
|||
self.insert_field_visibilities_local(def_id, vdata);
|
||||
}
|
||||
|
||||
ItemKind::Trait(..) => {
|
||||
// Add all the items within to a new module.
|
||||
let module = self.r.new_module(
|
||||
Some(parent),
|
||||
ModuleKind::Def(def_kind, def_id, ident.name),
|
||||
expansion.to_expn_id(),
|
||||
item.span,
|
||||
parent.no_implicit_prelude,
|
||||
);
|
||||
self.r.define(parent, ident, TypeNS, (module, vis, sp, expansion));
|
||||
self.parent_scope.module = module;
|
||||
}
|
||||
|
||||
// These items do not add names to modules.
|
||||
ItemKind::Impl(box Impl { of_trait: Some(..), .. }) => {
|
||||
self.r.trait_impl_items.insert(local_def_id);
|
||||
|
|
@ -1358,13 +1338,9 @@ impl<'a, 'b, 'tcx> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b, 'tcx> {
|
|||
|
||||
if ctxt == AssocCtxt::Trait {
|
||||
let ns = match item.kind {
|
||||
AssocItemKind::Const(..) => ValueNS,
|
||||
AssocItemKind::Fn(box Fn { ref sig, .. }) => {
|
||||
if sig.decl.has_self() {
|
||||
self.r.has_self.insert(local_def_id);
|
||||
}
|
||||
ValueNS
|
||||
}
|
||||
AssocItemKind::Const(..)
|
||||
| AssocItemKind::Delegation(..)
|
||||
| AssocItemKind::Fn(..) => ValueNS,
|
||||
AssocItemKind::Type(..) => TypeNS,
|
||||
AssocItemKind::MacCall(_) => bug!(), // handled above
|
||||
};
|
||||
|
|
|
|||
|
|
@ -111,7 +111,7 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> {
|
|||
ItemKind::TyAlias(..) => DefKind::TyAlias,
|
||||
ItemKind::Static(s) => DefKind::Static(s.mutability),
|
||||
ItemKind::Const(..) => DefKind::Const,
|
||||
ItemKind::Fn(..) => DefKind::Fn,
|
||||
ItemKind::Fn(..) | ItemKind::Delegation(..) => DefKind::Fn,
|
||||
ItemKind::MacroDef(..) => {
|
||||
let macro_data = self.resolver.compile_macro(i, self.resolver.tcx.sess.edition());
|
||||
let macro_kind = macro_data.ext.macro_kind();
|
||||
|
|
@ -259,7 +259,7 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> {
|
|||
|
||||
fn visit_assoc_item(&mut self, i: &'a AssocItem, ctxt: visit::AssocCtxt) {
|
||||
let def_kind = match &i.kind {
|
||||
AssocItemKind::Fn(..) => DefKind::AssocFn,
|
||||
AssocItemKind::Fn(..) | AssocItemKind::Delegation(..) => DefKind::AssocFn,
|
||||
AssocItemKind::Const(..) => DefKind::AssocConst,
|
||||
AssocItemKind::Type(..) => DefKind::AssocTy,
|
||||
AssocItemKind::MacCall(..) => return self.visit_macro_invoc(i.id),
|
||||
|
|
|
|||
|
|
@ -786,7 +786,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||
ResolutionError::SelfImportOnlyInImportListWithNonEmptyPrefix => {
|
||||
self.dcx().create_err(errs::SelfImportOnlyInImportListWithNonEmptyPrefix { span })
|
||||
}
|
||||
ResolutionError::FailedToResolve { last_segment, label, suggestion, module } => {
|
||||
ResolutionError::FailedToResolve { segment, label, suggestion, module } => {
|
||||
let mut err =
|
||||
struct_span_code_err!(self.dcx(), span, E0433, "failed to resolve: {}", &label);
|
||||
err.span_label(span, label);
|
||||
|
|
@ -801,9 +801,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||
|
||||
if let Some(ModuleOrUniformRoot::Module(module)) = module
|
||||
&& let Some(module) = module.opt_def_id()
|
||||
&& let Some(last_segment) = last_segment
|
||||
&& let Some(segment) = segment
|
||||
{
|
||||
self.find_cfg_stripped(&mut err, &last_segment, module);
|
||||
self.find_cfg_stripped(&mut err, &segment, module);
|
||||
}
|
||||
|
||||
err
|
||||
|
|
@ -981,12 +981,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||
}
|
||||
VisResolutionError::FailedToResolve(span, label, suggestion) => self.into_struct_error(
|
||||
span,
|
||||
ResolutionError::FailedToResolve {
|
||||
last_segment: None,
|
||||
label,
|
||||
suggestion,
|
||||
module: None,
|
||||
},
|
||||
ResolutionError::FailedToResolve { segment: None, label, suggestion, module: None },
|
||||
),
|
||||
VisResolutionError::ExpectedFound(span, path_str, res) => {
|
||||
self.dcx().create_err(errs::ExpectedFound { span, res, path_str })
|
||||
|
|
@ -2450,7 +2445,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||
pub(crate) fn find_cfg_stripped(
|
||||
&mut self,
|
||||
err: &mut Diagnostic,
|
||||
last_segment: &Symbol,
|
||||
segment: &Symbol,
|
||||
module: DefId,
|
||||
) {
|
||||
let local_items;
|
||||
|
|
@ -2469,7 +2464,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||
};
|
||||
|
||||
for &StrippedCfgItem { parent_module, name, ref cfg } in symbols {
|
||||
if parent_module != module || name.name != *last_segment {
|
||||
if parent_module != module || name.name != *segment {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -277,7 +277,8 @@ impl<'r, 'ast, 'tcx> Visitor<'ast> for EffectiveVisibilitiesVisitor<'ast, 'r, 't
|
|||
| ast::ItemKind::TraitAlias(..)
|
||||
| ast::ItemKind::MacroDef(..)
|
||||
| ast::ItemKind::ForeignMod(..)
|
||||
| ast::ItemKind::Fn(..) => return,
|
||||
| ast::ItemKind::Fn(..)
|
||||
| ast::ItemKind::Delegation(..) => return,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1381,13 +1381,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||
continue;
|
||||
}
|
||||
}
|
||||
return PathResult::failed(
|
||||
ident.span,
|
||||
false,
|
||||
finalize.is_some(),
|
||||
module,
|
||||
|| ("there are too many leading `super` keywords".to_string(), None),
|
||||
);
|
||||
return PathResult::failed(ident, false, finalize.is_some(), module, || {
|
||||
("there are too many leading `super` keywords".to_string(), None)
|
||||
});
|
||||
}
|
||||
if segment_idx == 0 {
|
||||
if name == kw::SelfLower {
|
||||
|
|
@ -1419,7 +1415,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||
|
||||
// Report special messages for path segment keywords in wrong positions.
|
||||
if ident.is_path_segment_keyword() && segment_idx != 0 {
|
||||
return PathResult::failed(ident.span, false, finalize.is_some(), module, || {
|
||||
return PathResult::failed(ident, false, finalize.is_some(), module, || {
|
||||
let name_str = if name == kw::PathRoot {
|
||||
"crate root".to_string()
|
||||
} else {
|
||||
|
|
@ -1515,7 +1511,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||
));
|
||||
} else {
|
||||
return PathResult::failed(
|
||||
ident.span,
|
||||
ident,
|
||||
is_last,
|
||||
finalize.is_some(),
|
||||
module,
|
||||
|
|
@ -1541,24 +1537,18 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
return PathResult::failed(
|
||||
ident.span,
|
||||
is_last,
|
||||
finalize.is_some(),
|
||||
module,
|
||||
|| {
|
||||
self.report_path_resolution_error(
|
||||
path,
|
||||
opt_ns,
|
||||
parent_scope,
|
||||
ribs,
|
||||
ignore_binding,
|
||||
module,
|
||||
segment_idx,
|
||||
ident,
|
||||
)
|
||||
},
|
||||
);
|
||||
return PathResult::failed(ident, is_last, finalize.is_some(), module, || {
|
||||
self.report_path_resolution_error(
|
||||
path,
|
||||
opt_ns,
|
||||
parent_scope,
|
||||
ribs,
|
||||
ignore_binding,
|
||||
module,
|
||||
segment_idx,
|
||||
ident,
|
||||
)
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -886,6 +886,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||
PathResult::Failed {
|
||||
is_error_from_last_segment: false,
|
||||
span,
|
||||
segment_name,
|
||||
label,
|
||||
suggestion,
|
||||
module,
|
||||
|
|
@ -895,7 +896,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||
self.report_error(
|
||||
span,
|
||||
ResolutionError::FailedToResolve {
|
||||
last_segment: None,
|
||||
segment: Some(segment_name),
|
||||
label,
|
||||
suggestion,
|
||||
module,
|
||||
|
|
|
|||
|
|
@ -394,13 +394,18 @@ pub(crate) enum PathSource<'a> {
|
|||
TupleStruct(Span, &'a [Span]),
|
||||
// `m::A::B` in `<T as m::A>::B::C`.
|
||||
TraitItem(Namespace),
|
||||
// Paths in delegation item
|
||||
Delegation,
|
||||
}
|
||||
|
||||
impl<'a> PathSource<'a> {
|
||||
fn namespace(self) -> Namespace {
|
||||
match self {
|
||||
PathSource::Type | PathSource::Trait(_) | PathSource::Struct => TypeNS,
|
||||
PathSource::Expr(..) | PathSource::Pat | PathSource::TupleStruct(..) => ValueNS,
|
||||
PathSource::Expr(..)
|
||||
| PathSource::Pat
|
||||
| PathSource::TupleStruct(..)
|
||||
| PathSource::Delegation => ValueNS,
|
||||
PathSource::TraitItem(ns) => ns,
|
||||
}
|
||||
}
|
||||
|
|
@ -412,7 +417,7 @@ impl<'a> PathSource<'a> {
|
|||
| PathSource::Pat
|
||||
| PathSource::Struct
|
||||
| PathSource::TupleStruct(..) => true,
|
||||
PathSource::Trait(_) | PathSource::TraitItem(..) => false,
|
||||
PathSource::Trait(_) | PathSource::TraitItem(..) | PathSource::Delegation => false,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -454,6 +459,7 @@ impl<'a> PathSource<'a> {
|
|||
},
|
||||
_ => "value",
|
||||
},
|
||||
PathSource::Delegation => "function",
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -521,6 +527,7 @@ impl<'a> PathSource<'a> {
|
|||
Res::Def(DefKind::AssocTy, _) if ns == TypeNS => true,
|
||||
_ => false,
|
||||
},
|
||||
PathSource::Delegation => matches!(res, Res::Def(DefKind::Fn | DefKind::AssocFn, _)),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -533,8 +540,8 @@ impl<'a> PathSource<'a> {
|
|||
(PathSource::Type, false) => error_code!(E0412),
|
||||
(PathSource::Struct, true) => error_code!(E0574),
|
||||
(PathSource::Struct, false) => error_code!(E0422),
|
||||
(PathSource::Expr(..), true) => error_code!(E0423),
|
||||
(PathSource::Expr(..), false) => error_code!(E0425),
|
||||
(PathSource::Expr(..), true) | (PathSource::Delegation, true) => error_code!(E0423),
|
||||
(PathSource::Expr(..), false) | (PathSource::Delegation, false) => error_code!(E0425),
|
||||
(PathSource::Pat | PathSource::TupleStruct(..), true) => error_code!(E0532),
|
||||
(PathSource::Pat | PathSource::TupleStruct(..), false) => error_code!(E0531),
|
||||
(PathSource::TraitItem(..), true) => error_code!(E0575),
|
||||
|
|
@ -1805,7 +1812,8 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
|
|||
PathSource::Expr(..)
|
||||
| PathSource::Pat
|
||||
| PathSource::Struct
|
||||
| PathSource::TupleStruct(..) => true,
|
||||
| PathSource::TupleStruct(..)
|
||||
| PathSource::Delegation => true,
|
||||
};
|
||||
if inferred {
|
||||
// Do not create a parameter for patterns and expressions: type checking can infer
|
||||
|
|
@ -2514,6 +2522,10 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
|
|||
visit::walk_item(self, item);
|
||||
}
|
||||
|
||||
ItemKind::Delegation(ref delegation) => {
|
||||
self.resolve_delegation(delegation);
|
||||
}
|
||||
|
||||
ItemKind::ExternCrate(..) => {}
|
||||
|
||||
ItemKind::MacCall(_) => panic!("unexpanded macro in resolve!"),
|
||||
|
|
@ -2790,6 +2802,9 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
|
|||
AssocItemKind::Fn(box Fn { generics, .. }) => {
|
||||
walk_assoc_item(self, generics, LifetimeBinderKind::Function, item);
|
||||
}
|
||||
AssocItemKind::Delegation(delegation) => {
|
||||
self.resolve_delegation(delegation);
|
||||
}
|
||||
AssocItemKind::Type(box TyAlias { generics, .. }) => self
|
||||
.with_lifetime_rib(LifetimeRibKind::AnonymousReportError, |this| {
|
||||
walk_assoc_item(this, generics, LifetimeBinderKind::Item, item)
|
||||
|
|
@ -3036,6 +3051,19 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
|
|||
},
|
||||
);
|
||||
}
|
||||
AssocItemKind::Delegation(box delegation) => {
|
||||
debug!("resolve_implementation AssocItemKind::Delegation");
|
||||
self.check_trait_item(
|
||||
item.id,
|
||||
item.ident,
|
||||
&item.kind,
|
||||
ValueNS,
|
||||
item.span,
|
||||
seen_trait_items,
|
||||
|i, s, c| MethodNotMemberOfTrait(i, s, c),
|
||||
);
|
||||
self.resolve_delegation(delegation);
|
||||
}
|
||||
AssocItemKind::MacCall(_) => {
|
||||
panic!("unexpanded macro in resolve!")
|
||||
}
|
||||
|
|
@ -3123,7 +3151,8 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
|
|||
match (def_kind, kind) {
|
||||
(DefKind::AssocTy, AssocItemKind::Type(..))
|
||||
| (DefKind::AssocFn, AssocItemKind::Fn(..))
|
||||
| (DefKind::AssocConst, AssocItemKind::Const(..)) => {
|
||||
| (DefKind::AssocConst, AssocItemKind::Const(..))
|
||||
| (DefKind::AssocFn, AssocItemKind::Delegation(..)) => {
|
||||
self.r.record_partial_res(id, PartialRes::new(res));
|
||||
return;
|
||||
}
|
||||
|
|
@ -3136,6 +3165,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
|
|||
AssocItemKind::Const(..) => (rustc_errors::error_code!(E0323), "const"),
|
||||
AssocItemKind::Fn(..) => (rustc_errors::error_code!(E0324), "method"),
|
||||
AssocItemKind::Type(..) => (rustc_errors::error_code!(E0325), "type"),
|
||||
AssocItemKind::Delegation(..) => (rustc_errors::error_code!(E0324), "method"),
|
||||
AssocItemKind::MacCall(..) => span_bug!(span, "unexpanded macro"),
|
||||
};
|
||||
let trait_path = path_names_to_string(path);
|
||||
|
|
@ -3159,6 +3189,32 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
|
|||
})
|
||||
}
|
||||
|
||||
fn resolve_delegation(&mut self, delegation: &'ast Delegation) {
|
||||
self.smart_resolve_path(
|
||||
delegation.id,
|
||||
&delegation.qself,
|
||||
&delegation.path,
|
||||
PathSource::Delegation,
|
||||
);
|
||||
if let Some(qself) = &delegation.qself {
|
||||
self.visit_ty(&qself.ty);
|
||||
}
|
||||
self.visit_path(&delegation.path, delegation.id);
|
||||
if let Some(body) = &delegation.body {
|
||||
// `PatBoundCtx` is not necessary in this context
|
||||
let mut bindings = smallvec![(PatBoundCtx::Product, Default::default())];
|
||||
|
||||
let span = delegation.path.segments.last().unwrap().ident.span;
|
||||
self.fresh_binding(
|
||||
Ident::new(kw::SelfLower, span),
|
||||
delegation.id,
|
||||
PatternSource::FnParam,
|
||||
&mut bindings,
|
||||
);
|
||||
self.visit_block(body);
|
||||
}
|
||||
}
|
||||
|
||||
fn resolve_params(&mut self, params: &'ast [Param]) {
|
||||
let mut bindings = smallvec![(PatBoundCtx::Product, Default::default())];
|
||||
self.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Infer), |this| {
|
||||
|
|
@ -3998,11 +4054,12 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
|
|||
label,
|
||||
suggestion,
|
||||
module,
|
||||
segment_name,
|
||||
} => {
|
||||
return Err(respan(
|
||||
span,
|
||||
ResolutionError::FailedToResolve {
|
||||
last_segment: None,
|
||||
segment: Some(segment_name),
|
||||
label,
|
||||
suggestion,
|
||||
module,
|
||||
|
|
@ -4551,13 +4608,24 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
struct LifetimeCountVisitor<'a, 'b, 'tcx> {
|
||||
/// Walks the whole crate in DFS order, visiting each item, counting the declared number of
|
||||
/// lifetime generic parameters and function parameters.
|
||||
struct ItemInfoCollector<'a, 'b, 'tcx> {
|
||||
r: &'b mut Resolver<'a, 'tcx>,
|
||||
}
|
||||
|
||||
/// Walks the whole crate in DFS order, visiting each item, counting the declared number of
|
||||
/// lifetime generic parameters.
|
||||
impl<'ast> Visitor<'ast> for LifetimeCountVisitor<'_, '_, '_> {
|
||||
impl ItemInfoCollector<'_, '_, '_> {
|
||||
fn collect_fn_info(&mut self, sig: &FnSig, id: NodeId) {
|
||||
let def_id = self.r.local_def_id(id);
|
||||
self.r.fn_parameter_counts.insert(def_id, sig.decl.inputs.len());
|
||||
|
||||
if sig.decl.has_self() {
|
||||
self.r.has_self.insert(def_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> Visitor<'ast> for ItemInfoCollector<'_, '_, '_> {
|
||||
fn visit_item(&mut self, item: &'ast Item) {
|
||||
match &item.kind {
|
||||
ItemKind::TyAlias(box TyAlias { ref generics, .. })
|
||||
|
|
@ -4569,6 +4637,10 @@ impl<'ast> Visitor<'ast> for LifetimeCountVisitor<'_, '_, '_> {
|
|||
| ItemKind::Impl(box Impl { ref generics, .. })
|
||||
| ItemKind::Trait(box Trait { ref generics, .. })
|
||||
| ItemKind::TraitAlias(ref generics, _) => {
|
||||
if let ItemKind::Fn(box Fn { ref sig, .. }) = &item.kind {
|
||||
self.collect_fn_info(sig, item.id);
|
||||
}
|
||||
|
||||
let def_id = self.r.local_def_id(item.id);
|
||||
let count = generics
|
||||
.params
|
||||
|
|
@ -4586,14 +4658,27 @@ impl<'ast> Visitor<'ast> for LifetimeCountVisitor<'_, '_, '_> {
|
|||
| ItemKind::MacroDef(..)
|
||||
| ItemKind::GlobalAsm(..)
|
||||
| ItemKind::MacCall(..) => {}
|
||||
ItemKind::Delegation(..) => {
|
||||
// Delegated functions have lifetimes, their count is not necessarily zero.
|
||||
// But skipping the delegation items here doesn't mean that the count will be considered zero,
|
||||
// it means there will be a panic when retrieving the count,
|
||||
// but for delegation items we are never actually retrieving that count in practice.
|
||||
}
|
||||
}
|
||||
visit::walk_item(self, item)
|
||||
}
|
||||
|
||||
fn visit_assoc_item(&mut self, item: &'ast AssocItem, ctxt: AssocCtxt) {
|
||||
if let AssocItemKind::Fn(box Fn { ref sig, .. }) = &item.kind {
|
||||
self.collect_fn_info(sig, item.id);
|
||||
}
|
||||
visit::walk_assoc_item(self, item, ctxt);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
pub(crate) fn late_resolve_crate(&mut self, krate: &Crate) {
|
||||
visit::walk_crate(&mut LifetimeCountVisitor { r: self }, krate);
|
||||
visit::walk_crate(&mut ItemInfoCollector { r: self }, krate);
|
||||
let mut late_resolution_visitor = LateResolutionVisitor::new(self);
|
||||
late_resolution_visitor.resolve_doc_links(&krate.attrs, MaybeExported::Ok(CRATE_NODE_ID));
|
||||
visit::walk_crate(&mut late_resolution_visitor, krate);
|
||||
|
|
|
|||
|
|
@ -656,7 +656,10 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
|
|||
let typo_sugg = self
|
||||
.lookup_typo_candidate(path, following_seg, source.namespace(), is_expected)
|
||||
.to_opt_suggestion();
|
||||
if path.len() == 1 && self.self_type_is_available() {
|
||||
if path.len() == 1
|
||||
&& !matches!(source, PathSource::Delegation)
|
||||
&& self.self_type_is_available()
|
||||
{
|
||||
if let Some(candidate) =
|
||||
self.lookup_assoc_candidate(ident, ns, is_expected, source.is_call())
|
||||
{
|
||||
|
|
@ -1899,6 +1902,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
|
|||
(AssocItemKind::Const(..), Res::Def(DefKind::AssocConst, _)) => true,
|
||||
(AssocItemKind::Fn(_), Res::Def(DefKind::AssocFn, _)) => true,
|
||||
(AssocItemKind::Type(..), Res::Def(DefKind::AssocTy, _)) => true,
|
||||
(AssocItemKind::Delegation(_), Res::Def(DefKind::AssocFn, _)) => true,
|
||||
_ => false,
|
||||
})
|
||||
.map(|(key, _)| key.ident.name)
|
||||
|
|
@ -1960,6 +1964,12 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
|
|||
}
|
||||
ast::AssocItemKind::Fn(..) => AssocSuggestion::AssocFn { called },
|
||||
ast::AssocItemKind::Type(..) => AssocSuggestion::AssocType,
|
||||
ast::AssocItemKind::Delegation(..)
|
||||
if self.r.has_self.contains(&self.r.local_def_id(assoc_item.id)) =>
|
||||
{
|
||||
AssocSuggestion::MethodWithSelf { called }
|
||||
}
|
||||
ast::AssocItemKind::Delegation(..) => AssocSuggestion::AssocFn { called },
|
||||
ast::AssocItemKind::MacCall(_) => continue,
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -213,7 +213,7 @@ enum ResolutionError<'a> {
|
|||
SelfImportOnlyInImportListWithNonEmptyPrefix,
|
||||
/// Error E0433: failed to resolve.
|
||||
FailedToResolve {
|
||||
last_segment: Option<Symbol>,
|
||||
segment: Option<Symbol>,
|
||||
label: String,
|
||||
suggestion: Option<Suggestion>,
|
||||
module: Option<ModuleOrUniformRoot<'a>>,
|
||||
|
|
@ -396,12 +396,14 @@ enum PathResult<'a> {
|
|||
suggestion: Option<Suggestion>,
|
||||
is_error_from_last_segment: bool,
|
||||
module: Option<ModuleOrUniformRoot<'a>>,
|
||||
/// The segment name of target
|
||||
segment_name: Symbol,
|
||||
},
|
||||
}
|
||||
|
||||
impl<'a> PathResult<'a> {
|
||||
fn failed(
|
||||
span: Span,
|
||||
ident: Ident,
|
||||
is_error_from_last_segment: bool,
|
||||
finalize: bool,
|
||||
module: Option<ModuleOrUniformRoot<'a>>,
|
||||
|
|
@ -409,7 +411,14 @@ impl<'a> PathResult<'a> {
|
|||
) -> PathResult<'a> {
|
||||
let (label, suggestion) =
|
||||
if finalize { label_and_suggestion() } else { (String::new(), None) };
|
||||
PathResult::Failed { span, label, suggestion, is_error_from_last_segment, module }
|
||||
PathResult::Failed {
|
||||
span: ident.span,
|
||||
segment_name: ident.name,
|
||||
label,
|
||||
suggestion,
|
||||
is_error_from_last_segment,
|
||||
module,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1101,6 +1110,8 @@ pub struct Resolver<'a, 'tcx> {
|
|||
legacy_const_generic_args: FxHashMap<DefId, Option<Vec<usize>>>,
|
||||
/// Amount of lifetime parameters for each item in the crate.
|
||||
item_generics_num_lifetimes: FxHashMap<LocalDefId, usize>,
|
||||
/// Amount of parameters for each function in the crate.
|
||||
fn_parameter_counts: LocalDefIdMap<usize>,
|
||||
|
||||
main_def: Option<MainDefinition>,
|
||||
trait_impls: FxIndexMap<DefId, Vec<LocalDefId>>,
|
||||
|
|
@ -1439,6 +1450,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||
doc_link_resolutions: Default::default(),
|
||||
doc_link_traits_in_scope: Default::default(),
|
||||
all_macro_rules: Default::default(),
|
||||
fn_parameter_counts: Default::default(),
|
||||
};
|
||||
|
||||
let root_parent_scope = ParentScope::module(graph_root, &resolver);
|
||||
|
|
@ -1542,6 +1554,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||
trait_map: self.trait_map,
|
||||
lifetime_elision_allowed: self.lifetime_elision_allowed,
|
||||
lint_buffer: Steal::new(self.lint_buffer),
|
||||
has_self: self.has_self,
|
||||
fn_parameter_counts: self.fn_parameter_counts,
|
||||
};
|
||||
ResolverOutputs { global_ctxt, ast_lowering }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -594,13 +594,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||
if soft_custom_inner_attributes_gate {
|
||||
self.tcx.sess.parse_sess.buffer_lint(SOFT_UNSTABLE, path.span, node_id, msg);
|
||||
} else {
|
||||
feature_err(
|
||||
&self.tcx.sess.parse_sess,
|
||||
sym::custom_inner_attributes,
|
||||
path.span,
|
||||
msg,
|
||||
)
|
||||
.emit();
|
||||
feature_err(&self.tcx.sess, sym::custom_inner_attributes, path.span, msg).emit();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -779,7 +773,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||
self.report_error(
|
||||
span,
|
||||
ResolutionError::FailedToResolve {
|
||||
last_segment: path.last().map(|segment| segment.ident.name),
|
||||
segment: path.last().map(|segment| segment.ident.name),
|
||||
label,
|
||||
suggestion,
|
||||
module,
|
||||
|
|
|
|||
|
|
@ -24,6 +24,9 @@ session_feature_diagnostic_for_issue =
|
|||
session_feature_diagnostic_help =
|
||||
add `#![feature({$feature})]` to the crate attributes to enable
|
||||
|
||||
session_feature_suggest_upgrade_compiler =
|
||||
this compiler was built on {$date}; consider upgrading it if it is out of date
|
||||
|
||||
session_file_is_not_writeable = output file {$file} is not writeable -- check its permissions
|
||||
|
||||
session_file_write_fail = failed to write `{$path}` due to error `{$err}`
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
//! NOTE: Keep these constants in sync with `library/std/src/sys/unix/mod.rs`!
|
||||
//! NOTE: Keep these constants in sync with `library/std/src/sys/pal/unix/mod.rs`!
|
||||
|
||||
/// The default value if `#[unix_sigpipe]` is not specified. This resolves
|
||||
/// to `SIG_IGN` in `library/std/src/sys/unix/mod.rs`.
|
||||
/// to `SIG_IGN` in `library/std/src/sys/pal/unix/mod.rs`.
|
||||
///
|
||||
/// Note that `SIG_IGN` has been the Rust default since 2014. See
|
||||
/// <https://github.com/rust-lang/rust/issues/62569>.
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
use std::num::NonZeroU32;
|
||||
|
||||
use crate::parse::ParseSess;
|
||||
use rustc_ast::token;
|
||||
use rustc_ast::util::literal::LitError;
|
||||
use rustc_errors::{
|
||||
|
|
@ -10,6 +9,8 @@ use rustc_macros::Diagnostic;
|
|||
use rustc_span::{BytePos, Span, Symbol};
|
||||
use rustc_target::spec::{SplitDebuginfo, StackProtector, TargetTriple};
|
||||
|
||||
use crate::parse::ParseSess;
|
||||
|
||||
pub struct FeatureGateError {
|
||||
pub span: MultiSpan,
|
||||
pub explain: DiagnosticMessage,
|
||||
|
|
@ -30,6 +31,24 @@ pub struct FeatureDiagnosticForIssue {
|
|||
pub n: NonZeroU32,
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
#[note(session_feature_suggest_upgrade_compiler)]
|
||||
pub struct SuggestUpgradeCompiler {
|
||||
date: &'static str,
|
||||
}
|
||||
|
||||
impl SuggestUpgradeCompiler {
|
||||
pub fn ui_testing() -> Self {
|
||||
Self { date: "YYYY-MM-DD" }
|
||||
}
|
||||
|
||||
pub fn new() -> Option<Self> {
|
||||
let date = option_env!("CFG_VER_DATE")?;
|
||||
|
||||
Some(Self { date })
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
#[help(session_feature_diagnostic_help)]
|
||||
pub struct FeatureDiagnosticHelp {
|
||||
|
|
|
|||
|
|
@ -4,10 +4,12 @@
|
|||
use crate::config::{Cfg, CheckCfg};
|
||||
use crate::errors::{
|
||||
CliFeatureDiagnosticHelp, FeatureDiagnosticForIssue, FeatureDiagnosticHelp, FeatureGateError,
|
||||
SuggestUpgradeCompiler,
|
||||
};
|
||||
use crate::lint::{
|
||||
builtin::UNSTABLE_SYNTAX_PRE_EXPANSION, BufferedEarlyLint, BuiltinLintDiagnostics, Lint, LintId,
|
||||
};
|
||||
use crate::Session;
|
||||
use rustc_ast::node_id::NodeId;
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
use rustc_data_structures::sync::{AppendOnlyVec, Lock, Lrc};
|
||||
|
|
@ -75,11 +77,12 @@ impl SymbolGallery {
|
|||
}
|
||||
}
|
||||
|
||||
// todo: this function now accepts `Session` instead of `ParseSess` and should be relocated
|
||||
/// Construct a diagnostic for a language feature error due to the given `span`.
|
||||
/// The `feature`'s `Symbol` is the one you used in `unstable.rs` and `rustc_span::symbols`.
|
||||
#[track_caller]
|
||||
pub fn feature_err(
|
||||
sess: &ParseSess,
|
||||
sess: &Session,
|
||||
feature: Symbol,
|
||||
span: impl Into<MultiSpan>,
|
||||
explain: impl Into<DiagnosticMessage>,
|
||||
|
|
@ -93,7 +96,7 @@ pub fn feature_err(
|
|||
/// Almost always, you want to use this for a language feature. If so, prefer `feature_err`.
|
||||
#[track_caller]
|
||||
pub fn feature_err_issue(
|
||||
sess: &ParseSess,
|
||||
sess: &Session,
|
||||
feature: Symbol,
|
||||
span: impl Into<MultiSpan>,
|
||||
issue: GateIssue,
|
||||
|
|
@ -103,12 +106,14 @@ pub fn feature_err_issue(
|
|||
|
||||
// Cancel an earlier warning for this same error, if it exists.
|
||||
if let Some(span) = span.primary_span() {
|
||||
if let Some(err) = sess.dcx.steal_diagnostic(span, StashKey::EarlySyntaxWarning) {
|
||||
if let Some(err) = sess.parse_sess.dcx.steal_diagnostic(span, StashKey::EarlySyntaxWarning)
|
||||
{
|
||||
err.cancel()
|
||||
}
|
||||
}
|
||||
|
||||
let mut err = sess.dcx.create_err(FeatureGateError { span, explain: explain.into() });
|
||||
let mut err =
|
||||
sess.parse_sess.dcx.create_err(FeatureGateError { span, explain: explain.into() });
|
||||
add_feature_diagnostics_for_issue(&mut err, sess, feature, issue, false);
|
||||
err
|
||||
}
|
||||
|
|
@ -117,7 +122,7 @@ pub fn feature_err_issue(
|
|||
///
|
||||
/// This diagnostic is only a warning and *does not cause compilation to fail*.
|
||||
#[track_caller]
|
||||
pub fn feature_warn(sess: &ParseSess, feature: Symbol, span: Span, explain: &'static str) {
|
||||
pub fn feature_warn(sess: &Session, feature: Symbol, span: Span, explain: &'static str) {
|
||||
feature_warn_issue(sess, feature, span, GateIssue::Language, explain);
|
||||
}
|
||||
|
||||
|
|
@ -131,13 +136,13 @@ pub fn feature_warn(sess: &ParseSess, feature: Symbol, span: Span, explain: &'st
|
|||
#[allow(rustc::untranslatable_diagnostic)]
|
||||
#[track_caller]
|
||||
pub fn feature_warn_issue(
|
||||
sess: &ParseSess,
|
||||
sess: &Session,
|
||||
feature: Symbol,
|
||||
span: Span,
|
||||
issue: GateIssue,
|
||||
explain: &'static str,
|
||||
) {
|
||||
let mut err = sess.dcx.struct_span_warn(span, explain);
|
||||
let mut err = sess.parse_sess.dcx.struct_span_warn(span, explain);
|
||||
add_feature_diagnostics_for_issue(&mut err, sess, feature, issue, false);
|
||||
|
||||
// Decorate this as a future-incompatibility lint as in rustc_middle::lint::struct_lint_level
|
||||
|
|
@ -152,7 +157,7 @@ pub fn feature_warn_issue(
|
|||
}
|
||||
|
||||
/// Adds the diagnostics for a feature to an existing error.
|
||||
pub fn add_feature_diagnostics(err: &mut Diagnostic, sess: &ParseSess, feature: Symbol) {
|
||||
pub fn add_feature_diagnostics(err: &mut Diagnostic, sess: &Session, feature: Symbol) {
|
||||
add_feature_diagnostics_for_issue(err, sess, feature, GateIssue::Language, false);
|
||||
}
|
||||
|
||||
|
|
@ -163,7 +168,7 @@ pub fn add_feature_diagnostics(err: &mut Diagnostic, sess: &ParseSess, feature:
|
|||
/// `add_feature_diagnostics`.
|
||||
pub fn add_feature_diagnostics_for_issue(
|
||||
err: &mut Diagnostic,
|
||||
sess: &ParseSess,
|
||||
sess: &Session,
|
||||
feature: Symbol,
|
||||
issue: GateIssue,
|
||||
feature_from_cli: bool,
|
||||
|
|
@ -173,12 +178,18 @@ pub fn add_feature_diagnostics_for_issue(
|
|||
}
|
||||
|
||||
// #23973: do not suggest `#![feature(...)]` if we are in beta/stable
|
||||
if sess.unstable_features.is_nightly_build() {
|
||||
if sess.parse_sess.unstable_features.is_nightly_build() {
|
||||
if feature_from_cli {
|
||||
err.subdiagnostic(CliFeatureDiagnosticHelp { feature });
|
||||
} else {
|
||||
err.subdiagnostic(FeatureDiagnosticHelp { feature });
|
||||
}
|
||||
|
||||
if sess.opts.unstable_opts.ui_testing {
|
||||
err.subdiagnostic(SuggestUpgradeCompiler::ui_testing());
|
||||
} else if let Some(suggestion) = SuggestUpgradeCompiler::new() {
|
||||
err.subdiagnostic(suggestion);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -318,7 +318,7 @@ impl Session {
|
|||
if err.code.is_none() {
|
||||
err.code(error_code!(E0658));
|
||||
}
|
||||
add_feature_diagnostics(&mut err, &self.parse_sess, feature);
|
||||
add_feature_diagnostics(&mut err, self, feature);
|
||||
err
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -102,6 +102,7 @@ symbols! {
|
|||
Gen: "gen",
|
||||
MacroRules: "macro_rules",
|
||||
Raw: "raw",
|
||||
Reuse: "reuse",
|
||||
Union: "union",
|
||||
Yeet: "yeet",
|
||||
}
|
||||
|
|
|
|||
|
|
@ -840,7 +840,7 @@ impl<'a, Ty> FnAbi<'a, Ty> {
|
|||
"sparc" => sparc::compute_abi_info(cx, self),
|
||||
"sparc64" => sparc64::compute_abi_info(cx, self),
|
||||
"nvptx64" => {
|
||||
if cx.target_spec().adjust_abi(abi) == spec::abi::Abi::PtxKernel {
|
||||
if cx.target_spec().adjust_abi(abi, self.c_variadic) == spec::abi::Abi::PtxKernel {
|
||||
nvptx64::compute_ptx_kernel_abi_info(cx, self)
|
||||
} else {
|
||||
nvptx64::compute_abi_info(self)
|
||||
|
|
@ -849,7 +849,7 @@ impl<'a, Ty> FnAbi<'a, Ty> {
|
|||
"hexagon" => hexagon::compute_abi_info(self),
|
||||
"riscv32" | "riscv64" => riscv::compute_abi_info(cx, self),
|
||||
"wasm32" | "wasm64" => {
|
||||
if cx.target_spec().adjust_abi(abi) == spec::abi::Abi::Wasm {
|
||||
if cx.target_spec().adjust_abi(abi, self.c_variadic) == spec::abi::Abi::Wasm {
|
||||
wasm::compute_wasm_abi_info(self)
|
||||
} else {
|
||||
wasm::compute_c_abi_info(cx, self)
|
||||
|
|
|
|||
|
|
@ -70,15 +70,16 @@ impl Abi {
|
|||
// * C and Cdecl obviously support varargs.
|
||||
// * C can be based on Aapcs, SysV64 or Win64, so they must support varargs.
|
||||
// * EfiApi is based on Win64 or C, so it also supports it.
|
||||
// * System falls back to C for functions with varargs.
|
||||
//
|
||||
// * Stdcall does not, because it would be impossible for the callee to clean
|
||||
// up the arguments. (callee doesn't know how many arguments are there)
|
||||
// * Same for Fastcall, Vectorcall and Thiscall.
|
||||
// * System can become Stdcall, so is also a no-no.
|
||||
// * Other calling conventions are related to hardware or the compiler itself.
|
||||
match self {
|
||||
Self::C { .. }
|
||||
| Self::Cdecl { .. }
|
||||
| Self::System { .. }
|
||||
| Self::Aapcs { .. }
|
||||
| Self::Win64 { .. }
|
||||
| Self::SysV64 { .. }
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ pub fn opts() -> TargetOptions {
|
|||
// While we support ELF TLS, rust requires a way to register
|
||||
// cleanup handlers (in C, this would be something along the lines of:
|
||||
// void register_callback(void (*fn)(void *), void *arg);
|
||||
// (see src/libstd/sys/unix/fast_thread_local.rs) that is currently
|
||||
// (see src/libstd/sys/pal/unix/fast_thread_local.rs) that is currently
|
||||
// missing in illumos. For now at least, we must fallback to using
|
||||
// pthread_{get,set}specific.
|
||||
//has_thread_local: true,
|
||||
|
|
|
|||
|
|
@ -2401,10 +2401,14 @@ impl DerefMut for Target {
|
|||
|
||||
impl Target {
|
||||
/// Given a function ABI, turn it into the correct ABI for this target.
|
||||
pub fn adjust_abi(&self, abi: Abi) -> Abi {
|
||||
pub fn adjust_abi(&self, abi: Abi, c_variadic: bool) -> Abi {
|
||||
match abi {
|
||||
Abi::C { .. } => self.default_adjusted_cabi.unwrap_or(abi),
|
||||
Abi::System { unwind } if self.is_like_windows && self.arch == "x86" => {
|
||||
|
||||
// On Windows, `extern "system"` behaves like msvc's `__stdcall`.
|
||||
// `__stdcall` only applies on x86 and on non-variadic functions:
|
||||
// https://learn.microsoft.com/en-us/cpp/cpp/stdcall?view=msvc-170
|
||||
Abi::System { unwind } if self.is_like_windows && self.arch == "x86" && !c_variadic => {
|
||||
Abi::Stdcall { unwind }
|
||||
}
|
||||
Abi::System { unwind } => Abi::C { unwind },
|
||||
|
|
|
|||
|
|
@ -408,7 +408,7 @@ impl<'tcx> OnUnimplementedDirective {
|
|||
.ok_or_else(|| tcx.dcx().emit_err(EmptyOnClauseInOnUnimplemented { span }))?
|
||||
.meta_item()
|
||||
.ok_or_else(|| tcx.dcx().emit_err(InvalidOnClauseInOnUnimplemented { span }))?;
|
||||
attr::eval_condition(cond, &tcx.sess.parse_sess, Some(tcx.features()), &mut |cfg| {
|
||||
attr::eval_condition(cond, &tcx.sess, Some(tcx.features()), &mut |cfg| {
|
||||
if let Some(value) = cfg.value
|
||||
&& let Err(guar) = parse_value(value, cfg.span)
|
||||
{
|
||||
|
|
@ -682,31 +682,22 @@ impl<'tcx> OnUnimplementedDirective {
|
|||
|
||||
for command in self.subcommands.iter().chain(Some(self)).rev() {
|
||||
if let Some(ref condition) = command.condition
|
||||
&& !attr::eval_condition(
|
||||
condition,
|
||||
&tcx.sess.parse_sess,
|
||||
Some(tcx.features()),
|
||||
&mut |cfg| {
|
||||
let value = cfg.value.map(|v| {
|
||||
// `with_no_visible_paths` is also used when generating the options,
|
||||
// so we need to match it here.
|
||||
ty::print::with_no_visible_paths!(
|
||||
OnUnimplementedFormatString {
|
||||
symbol: v,
|
||||
span: cfg.span,
|
||||
is_diagnostic_namespace_variant: false
|
||||
}
|
||||
.format(
|
||||
tcx,
|
||||
trait_ref,
|
||||
&options_map
|
||||
)
|
||||
)
|
||||
});
|
||||
&& !attr::eval_condition(condition, &tcx.sess, Some(tcx.features()), &mut |cfg| {
|
||||
let value = cfg.value.map(|v| {
|
||||
// `with_no_visible_paths` is also used when generating the options,
|
||||
// so we need to match it here.
|
||||
ty::print::with_no_visible_paths!(
|
||||
OnUnimplementedFormatString {
|
||||
symbol: v,
|
||||
span: cfg.span,
|
||||
is_diagnostic_namespace_variant: false
|
||||
}
|
||||
.format(tcx, trait_ref, &options_map)
|
||||
)
|
||||
});
|
||||
|
||||
options.contains(&(cfg.name, value))
|
||||
},
|
||||
)
|
||||
options.contains(&(cfg.name, value))
|
||||
})
|
||||
{
|
||||
debug!("evaluate: skipping {:?} due to condition", command);
|
||||
continue;
|
||||
|
|
|
|||
|
|
@ -947,9 +947,6 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
Overflow(_) => {
|
||||
bug!("overflow should be handled before the `report_selection_error` path");
|
||||
}
|
||||
SelectionError::ErrorReporting => {
|
||||
bug!("ErrorReporting Overflow should not reach `report_selection_err` call")
|
||||
}
|
||||
};
|
||||
|
||||
self.note_obligation_cause(&mut err, &obligation);
|
||||
|
|
@ -3459,14 +3456,12 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
let found_node = found_did.and_then(|did| self.tcx.hir().get_if_local(did));
|
||||
let found_span = found_did.and_then(|did| self.tcx.hir().span_if_local(did));
|
||||
|
||||
if self.reported_closure_mismatch.borrow().contains(&(span, found_span)) {
|
||||
if !self.reported_signature_mismatch.borrow_mut().insert((span, found_span)) {
|
||||
// We check closures twice, with obligations flowing in different directions,
|
||||
// but we want to complain about them only once.
|
||||
return None;
|
||||
}
|
||||
|
||||
self.reported_closure_mismatch.borrow_mut().insert((span, found_span));
|
||||
|
||||
let mut not_tupled = false;
|
||||
|
||||
let found = match found_trait_ref.skip_binder().args.type_at(1).kind() {
|
||||
|
|
|
|||
|
|
@ -116,11 +116,9 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
|
|||
r,
|
||||
)
|
||||
}
|
||||
OverflowError::ErrorReporting => EvaluationResult::EvaluatedToErr,
|
||||
OverflowError::Error(_) => EvaluationResult::EvaluatedToErr,
|
||||
})
|
||||
}
|
||||
Err(OverflowError::ErrorReporting) => EvaluationResult::EvaluatedToErr,
|
||||
Err(OverflowError::Error(_)) => EvaluationResult::EvaluatedToErr,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,9 +14,9 @@ use super::util;
|
|||
use super::util::closure_trait_ref_and_return_type;
|
||||
use super::wf;
|
||||
use super::{
|
||||
ErrorReporting, ImplDerivedObligation, ImplDerivedObligationCause, Normalized, Obligation,
|
||||
ObligationCause, ObligationCauseCode, Overflow, PolyTraitObligation, PredicateObligation,
|
||||
Selection, SelectionError, SelectionResult, TraitQueryMode,
|
||||
ImplDerivedObligation, ImplDerivedObligationCause, Normalized, Obligation, ObligationCause,
|
||||
ObligationCauseCode, Overflow, PolyTraitObligation, PredicateObligation, Selection,
|
||||
SelectionError, SelectionResult, TraitQueryMode,
|
||||
};
|
||||
|
||||
use crate::infer::{InferCtxt, InferOk, TypeFreshener};
|
||||
|
|
@ -496,7 +496,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
}
|
||||
Ok(_) => Ok(None),
|
||||
Err(OverflowError::Canonical) => Err(Overflow(OverflowError::Canonical)),
|
||||
Err(OverflowError::ErrorReporting) => Err(ErrorReporting),
|
||||
Err(OverflowError::Error(e)) => Err(Overflow(OverflowError::Error(e))),
|
||||
})
|
||||
.flat_map(Result::transpose)
|
||||
|
|
@ -1233,7 +1232,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
Ok(Some(c)) => self.evaluate_candidate(stack, &c),
|
||||
Ok(None) => Ok(EvaluatedToAmbig),
|
||||
Err(Overflow(OverflowError::Canonical)) => Err(OverflowError::Canonical),
|
||||
Err(ErrorReporting) => Err(OverflowError::ErrorReporting),
|
||||
Err(..) => Ok(EvaluatedToErr),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -228,9 +228,9 @@ fn fn_sig_for_fn_abi<'tcx>(
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn conv_from_spec_abi(tcx: TyCtxt<'_>, abi: SpecAbi) -> Conv {
|
||||
fn conv_from_spec_abi(tcx: TyCtxt<'_>, abi: SpecAbi, c_variadic: bool) -> Conv {
|
||||
use rustc_target::spec::abi::Abi::*;
|
||||
match tcx.sess.target.adjust_abi(abi) {
|
||||
match tcx.sess.target.adjust_abi(abi, c_variadic) {
|
||||
RustIntrinsic | PlatformIntrinsic | Rust | RustCall => Conv::Rust,
|
||||
|
||||
// This is intentionally not using `Conv::Cold`, as that has to preserve
|
||||
|
|
@ -488,7 +488,7 @@ fn fn_abi_new_uncached<'tcx>(
|
|||
) -> Result<&'tcx FnAbi<'tcx, Ty<'tcx>>, &'tcx FnAbiError<'tcx>> {
|
||||
let sig = cx.tcx.normalize_erasing_late_bound_regions(cx.param_env, sig);
|
||||
|
||||
let conv = conv_from_spec_abi(cx.tcx(), sig.abi);
|
||||
let conv = conv_from_spec_abi(cx.tcx(), sig.abi, sig.c_variadic);
|
||||
|
||||
let mut inputs = sig.inputs();
|
||||
let extra_args = if sig.abi == RustCall {
|
||||
|
|
|
|||
|
|
@ -1605,9 +1605,9 @@ mod prim_ref {}
|
|||
/// type in the function pointer to the type at the function declaration, and the return value is
|
||||
/// [`transmute`d][mem::transmute] from the type in the declaration to the type in the
|
||||
/// pointer. All the usual caveats and concerns around transmutation apply; for instance, if the
|
||||
/// function expects a `NonNullI32` and the function pointer uses the ABI-compatible type
|
||||
/// `Option<NonNullI32>`, and the value used for the argument is `None`, then this call is Undefined
|
||||
/// Behavior since transmuting `None::<NonNullI32>` to `NonNullI32` violates the non-null
|
||||
/// function expects a `NonZeroI32` and the function pointer uses the ABI-compatible type
|
||||
/// `Option<NonZeroI32>`, and the value used for the argument is `None`, then this call is Undefined
|
||||
/// Behavior since transmuting `None::<NonZeroI32>` to `NonZeroI32` violates the non-zero
|
||||
/// requirement.
|
||||
///
|
||||
/// #### Requirements concerning target features
|
||||
|
|
|
|||
|
|
@ -329,12 +329,14 @@ impl Waker {
|
|||
Waker { waker }
|
||||
}
|
||||
|
||||
/// Creates a new `Waker` that does nothing when `wake` is called.
|
||||
/// Returns a reference to a `Waker` that does nothing when used.
|
||||
///
|
||||
/// This is mostly useful for writing tests that need a [`Context`] to poll
|
||||
/// some futures, but are not expecting those futures to wake the waker or
|
||||
/// do not need to do anything specific if it happens.
|
||||
///
|
||||
/// If an owned `Waker` is needed, `clone()` this one.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
|
|
@ -343,8 +345,7 @@ impl Waker {
|
|||
/// use std::future::Future;
|
||||
/// use std::task;
|
||||
///
|
||||
/// let waker = task::Waker::noop();
|
||||
/// let mut cx = task::Context::from_waker(&waker);
|
||||
/// let mut cx = task::Context::from_waker(task::Waker::noop());
|
||||
///
|
||||
/// let mut future = Box::pin(async { 10 });
|
||||
/// assert_eq!(future.as_mut().poll(&mut cx), task::Poll::Ready(10));
|
||||
|
|
@ -352,7 +353,12 @@ impl Waker {
|
|||
#[inline]
|
||||
#[must_use]
|
||||
#[unstable(feature = "noop_waker", issue = "98286")]
|
||||
pub const fn noop() -> Waker {
|
||||
pub const fn noop() -> &'static Waker {
|
||||
// Ideally all this data would be explicitly `static` because it is used by reference and
|
||||
// only ever needs one copy. But `const fn`s (and `const` items) cannot refer to statics,
|
||||
// even though their values can be promoted to static. (That might change; see #119618.)
|
||||
// An alternative would be a `pub static NOOP: &Waker`, but associated static items are not
|
||||
// currently allowed either, and making it non-associated would be unergonomic.
|
||||
const VTABLE: RawWakerVTable = RawWakerVTable::new(
|
||||
// Cloning just returns a new no-op raw waker
|
||||
|_| RAW,
|
||||
|
|
@ -364,8 +370,9 @@ impl Waker {
|
|||
|_| {},
|
||||
);
|
||||
const RAW: RawWaker = RawWaker::new(ptr::null(), &VTABLE);
|
||||
const WAKER_REF: &Waker = &Waker { waker: RAW };
|
||||
|
||||
Waker { waker: RAW }
|
||||
WAKER_REF
|
||||
}
|
||||
|
||||
/// Get a reference to the underlying [`RawWaker`].
|
||||
|
|
|
|||
|
|
@ -1,124 +1,10 @@
|
|||
//! Platform-dependent platform abstraction.
|
||||
//!
|
||||
//! The `std::sys` module is the abstracted interface through which
|
||||
//! `std` talks to the underlying operating system. It has different
|
||||
//! implementations for different operating system families, today
|
||||
//! just Unix and Windows, and initial support for Redox.
|
||||
//!
|
||||
//! The centralization of platform-specific code in this module is
|
||||
//! enforced by the "platform abstraction layer" tidy script in
|
||||
//! `tools/tidy/src/pal.rs`.
|
||||
//!
|
||||
//! This module is closely related to the platform-independent system
|
||||
//! integration code in `std::sys_common`. See that module's
|
||||
//! documentation for details.
|
||||
//!
|
||||
//! In the future it would be desirable for the independent
|
||||
//! implementations of this module to be extracted to their own crates
|
||||
//! that `std` can link to, thus enabling their implementation
|
||||
//! out-of-tree via crate replacement. Though due to the complex
|
||||
//! inter-dependencies within `std` that will be a challenging goal to
|
||||
//! achieve.
|
||||
/// The PAL (platform abstraction layer) contains platform-specific abstractions
|
||||
/// for implementing the features in the other submodules, e.g. UNIX file
|
||||
/// descriptors.
|
||||
mod pal;
|
||||
|
||||
#![allow(missing_debug_implementations)]
|
||||
|
||||
pub mod common;
|
||||
mod personality;
|
||||
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(unix)] {
|
||||
mod unix;
|
||||
pub use self::unix::*;
|
||||
} else if #[cfg(windows)] {
|
||||
mod windows;
|
||||
pub use self::windows::*;
|
||||
} else if #[cfg(target_os = "solid_asp3")] {
|
||||
mod solid;
|
||||
pub use self::solid::*;
|
||||
} else if #[cfg(target_os = "hermit")] {
|
||||
mod hermit;
|
||||
pub use self::hermit::*;
|
||||
} else if #[cfg(target_os = "wasi")] {
|
||||
mod wasi;
|
||||
pub use self::wasi::*;
|
||||
} else if #[cfg(target_family = "wasm")] {
|
||||
mod wasm;
|
||||
pub use self::wasm::*;
|
||||
} else if #[cfg(target_os = "xous")] {
|
||||
mod xous;
|
||||
pub use self::xous::*;
|
||||
} else if #[cfg(target_os = "uefi")] {
|
||||
mod uefi;
|
||||
pub use self::uefi::*;
|
||||
} else if #[cfg(all(target_vendor = "fortanix", target_env = "sgx"))] {
|
||||
mod sgx;
|
||||
pub use self::sgx::*;
|
||||
} else if #[cfg(target_os = "teeos")] {
|
||||
mod teeos;
|
||||
pub use self::teeos::*;
|
||||
} else {
|
||||
mod unsupported;
|
||||
pub use self::unsupported::*;
|
||||
}
|
||||
}
|
||||
|
||||
cfg_if::cfg_if! {
|
||||
// Fuchsia components default to full backtrace.
|
||||
if #[cfg(target_os = "fuchsia")] {
|
||||
pub const FULL_BACKTRACE_DEFAULT: bool = true;
|
||||
} else {
|
||||
pub const FULL_BACKTRACE_DEFAULT: bool = false;
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(test))]
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(target_os = "android")] {
|
||||
pub use self::android::log2f32;
|
||||
pub use self::android::log2f64;
|
||||
} else {
|
||||
#[inline]
|
||||
pub fn log2f32(n: f32) -> f32 {
|
||||
unsafe { crate::intrinsics::log2f32(n) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn log2f64(n: f64) -> f64 {
|
||||
unsafe { crate::intrinsics::log2f64(n) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Solaris/Illumos requires a wrapper around log, log2, and log10 functions
|
||||
// because of their non-standard behavior (e.g., log(-n) returns -Inf instead
|
||||
// of expected NaN).
|
||||
#[cfg(not(test))]
|
||||
#[cfg(any(target_os = "solaris", target_os = "illumos"))]
|
||||
#[inline]
|
||||
pub fn log_wrapper<F: Fn(f64) -> f64>(n: f64, log_fn: F) -> f64 {
|
||||
if n.is_finite() {
|
||||
if n > 0.0 {
|
||||
log_fn(n)
|
||||
} else if n == 0.0 {
|
||||
f64::NEG_INFINITY // log(0) = -Inf
|
||||
} else {
|
||||
f64::NAN // log(-n) = NaN
|
||||
}
|
||||
} else if n.is_nan() {
|
||||
n // log(NaN) = NaN
|
||||
} else if n > 0.0 {
|
||||
n // log(Inf) = Inf
|
||||
} else {
|
||||
f64::NAN // log(-Inf) = NaN
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(test))]
|
||||
#[cfg(not(any(target_os = "solaris", target_os = "illumos")))]
|
||||
#[inline]
|
||||
pub fn log_wrapper<F: Fn(f64) -> f64>(n: f64, log_fn: F) -> f64 {
|
||||
log_fn(n)
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "uefi"))]
|
||||
pub type RawOsError = i32;
|
||||
// FIXME(117276): remove this, move feature implementations into individual
|
||||
// submodules.
|
||||
pub use pal::*;
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue