mirror of
https://git.proxmox.com/git/rustc
synced 2025-08-02 18:10:26 +00:00
New upstream version 1.72.1+dfsg1
This commit is contained in:
parent
49aad94119
commit
fe692bf9c3
1582
Cargo.lock
generated
1582
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,5 @@
|
||||
[workspace]
|
||||
resolver = "1"
|
||||
members = [
|
||||
"compiler/rustc",
|
||||
"library/std",
|
||||
@ -8,6 +9,7 @@ members = [
|
||||
"src/tools/cargotest",
|
||||
"src/tools/clippy",
|
||||
"src/tools/clippy/clippy_dev",
|
||||
"src/tools/clippy/clippy_test_deps",
|
||||
"src/tools/compiletest",
|
||||
"src/tools/error_index_generator",
|
||||
"src/tools/linkchecker",
|
||||
|
42
README.md
42
README.md
@ -22,8 +22,9 @@ Read ["Installation"] from [The Book].
|
||||
|
||||
The Rust build system uses a Python script called `x.py` to build the compiler,
|
||||
which manages the bootstrapping process. It lives at the root of the project.
|
||||
It also uses a file named `config.toml` to determine various configuration settings for the build.
|
||||
You can see a full list of options in `config.example.toml`.
|
||||
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:
|
||||
@ -33,24 +34,14 @@ format:
|
||||
```
|
||||
|
||||
This is how the documentation and examples assume you are running `x.py`.
|
||||
Some alternative ways are:
|
||||
|
||||
```sh
|
||||
# On a Unix shell if you don't have the necessary `python3` command
|
||||
./x <subcommand> [flags]
|
||||
|
||||
# On the Windows Command Prompt (if .py files are configured to run Python)
|
||||
x.py <subcommand> [flags]
|
||||
|
||||
# You can also run Python yourself, e.g.:
|
||||
python x.py <subcommand> [flags]
|
||||
```
|
||||
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
|
||||
[rustcguidebuild]: https://rustc-dev-guide.rust-lang.org/building/how-to-build-and-run.html#what-is-xpy
|
||||
|
||||
### Dependencies
|
||||
|
||||
@ -116,24 +107,26 @@ See [the rustc-dev-guide for more info][sysllvm].
|
||||
|
||||
When complete, `./x.py install` will place several programs into
|
||||
`$PREFIX/bin`: `rustc`, the Rust compiler, and `rustdoc`, the
|
||||
API-documentation tool. By default, it will also include [Cargo], Rust's package manager.
|
||||
You can disable this behavior by passing `--set build.extended=false` to `./configure`.
|
||||
API-documentation tool. By default, it will also include [Cargo], Rust's
|
||||
package manager. You can disable this behavior by passing
|
||||
`--set build.extended=false` to `./configure`.
|
||||
|
||||
[Cargo]: https://github.com/rust-lang/cargo
|
||||
|
||||
#### Configure and Make
|
||||
|
||||
This project provides a configure script and makefile (the latter of which just invokes `x.py`).
|
||||
`./configure` is the recommended way to programatically generate a `config.toml`. `make` is not
|
||||
recommended (we suggest using `x.py` directly), but it is supported and we try not to break it
|
||||
unnecessarily.
|
||||
This project provides a configure script and makefile (the latter of which just
|
||||
invokes `x.py`). `./configure` is the recommended way to programatically
|
||||
generate a `config.toml`. `make` is not recommended (we suggest using `x.py`
|
||||
directly), but it is supported and we try not to break it unnecessarily.
|
||||
|
||||
```sh
|
||||
./configure
|
||||
make && sudo make install
|
||||
```
|
||||
|
||||
`configure` generates a `config.toml` which can also be used with normal `x.py` invocations.
|
||||
`configure` generates a `config.toml` which can also be used with normal `x.py`
|
||||
invocations.
|
||||
|
||||
### Building on Windows
|
||||
|
||||
@ -204,7 +197,7 @@ toolchain.
|
||||
#### 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
|
||||
(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/
|
||||
@ -245,7 +238,8 @@ Windows build triples are:
|
||||
|
||||
The build triple can be specified by either specifying `--build=<triple>` when
|
||||
invoking `x.py` commands, or by creating a `config.toml` file (as described in
|
||||
[Building on a Unix-like system](#building-on-a-unix-like-system)), and passing `--set build.build=<triple>` to `./configure`.
|
||||
[Building on a Unix-like system](#building-on-a-unix-like-system)), and passing
|
||||
`--set build.build=<triple>` to `./configure`.
|
||||
|
||||
## Building Documentation
|
||||
|
||||
|
143
RELEASES.md
143
RELEASES.md
@ -1,3 +1,118 @@
|
||||
Version 1.72.1 (2023-09-14)
|
||||
===========================
|
||||
|
||||
- [Adjust codegen change to improve LLVM codegen](https://github.com/rust-lang/rust/pull/115236)
|
||||
- [rustdoc: Fix self ty params in objects with lifetimes](https://github.com/rust-lang/rust/pull/115276)
|
||||
- [Fix regression in compile times](https://github.com/rust-lang/rust/pull/114948)
|
||||
- Resolve some ICE regressions in the compiler:
|
||||
- [#115215](https://github.com/rust-lang/rust/pull/115215)
|
||||
- [#115559](https://github.com/rust-lang/rust/pull/115559)
|
||||
|
||||
Version 1.72.0 (2023-08-24)
|
||||
==========================
|
||||
|
||||
<a id="1.72.0-Language"></a>
|
||||
|
||||
Language
|
||||
--------
|
||||
|
||||
- [Replace const eval limit by a lint and add an exponential backoff warning](https://github.com/rust-lang/rust/pull/103877/)
|
||||
- [expand: Change how `#![cfg(FALSE)]` behaves on crate root](https://github.com/rust-lang/rust/pull/110141/)
|
||||
- [Stabilize inline asm for LoongArch64](https://github.com/rust-lang/rust/pull/111235/)
|
||||
- [Uplift `clippy::undropped_manually_drops` lint](https://github.com/rust-lang/rust/pull/111530/)
|
||||
- [Uplift `clippy::invalid_utf8_in_unchecked` lint](https://github.com/rust-lang/rust/pull/111543/)
|
||||
- [Uplift `clippy::cast_ref_to_mut` lint](https://github.com/rust-lang/rust/pull/111567/)
|
||||
- [Uplift `clippy::cmp_nan` lint](https://github.com/rust-lang/rust/pull/111818/)
|
||||
- [resolve: Remove artificial import ambiguity errors](https://github.com/rust-lang/rust/pull/112086/)
|
||||
- [Don't require associated types with Self: Sized bounds in `dyn Trait` objects](https://github.com/rust-lang/rust/pull/112319/)
|
||||
|
||||
<a id="1.72.0-Compiler"></a>
|
||||
|
||||
Compiler
|
||||
--------
|
||||
|
||||
- [Remember names of `cfg`-ed out items to mention them in diagnostics](https://github.com/rust-lang/rust/pull/109005/)
|
||||
- [Support for native WASM exceptions](https://github.com/rust-lang/rust/pull/111322/)
|
||||
- [Add support for NetBSD/aarch64-be (big-endian arm64).](https://github.com/rust-lang/rust/pull/111326/)
|
||||
- [Write to stdout if `-` is given as output file](https://github.com/rust-lang/rust/pull/111626/)
|
||||
- [Force all native libraries to be statically linked when linking a static binary](https://github.com/rust-lang/rust/pull/111698/)
|
||||
- [Add Tier 3 support for `loongarch64-unknown-none*`](https://github.com/rust-lang/rust/pull/112310/)
|
||||
- [Prevent `.eh_frame` from being emitted for `-C panic=abort`](https://github.com/rust-lang/rust/pull/112403/)
|
||||
- [Support 128-bit enum variant in debuginfo codegen](https://github.com/rust-lang/rust/pull/112474/)
|
||||
- [compiler: update solaris/illumos to enable tsan support.](https://github.com/rust-lang/rust/pull/112039/)
|
||||
|
||||
Refer to Rust's [platform support page][platform-support-doc]
|
||||
for more information on Rust's tiered platform support.
|
||||
|
||||
<a id="1.72.0-Libraries"></a>
|
||||
|
||||
Libraries
|
||||
---------
|
||||
|
||||
- [Document memory orderings of `thread::{park, unpark}`](https://github.com/rust-lang/rust/pull/99587/)
|
||||
- [io: soften ‘at most one write attempt’ requirement in io::Write::write](https://github.com/rust-lang/rust/pull/107200/)
|
||||
- [Specify behavior of HashSet::insert](https://github.com/rust-lang/rust/pull/107619/)
|
||||
- [Relax implicit `T: Sized` bounds on `BufReader<T>`, `BufWriter<T>` and `LineWriter<T>`](https://github.com/rust-lang/rust/pull/111074/)
|
||||
- [Update runtime guarantee for `select_nth_unstable`](https://github.com/rust-lang/rust/pull/111974/)
|
||||
- [Return `Ok` on kill if process has already exited](https://github.com/rust-lang/rust/pull/112594/)
|
||||
- [Implement PartialOrd for `Vec`s over different allocators](https://github.com/rust-lang/rust/pull/112632/)
|
||||
- [Use 128 bits for TypeId hash](https://github.com/rust-lang/rust/pull/109953/)
|
||||
- [Don't drain-on-drop in DrainFilter impls of various collections.](https://github.com/rust-lang/rust/pull/104455/)
|
||||
- [Make `{Arc,Rc,Weak}::ptr_eq` ignore pointer metadata](https://github.com/rust-lang/rust/pull/106450/)
|
||||
|
||||
<a id="1.72.0-Rustdoc"></a>
|
||||
|
||||
Rustdoc
|
||||
-------
|
||||
|
||||
- [Allow whitespace as path separator like double colon](https://github.com/rust-lang/rust/pull/108537/)
|
||||
- [Add search result item types after their name](https://github.com/rust-lang/rust/pull/110688/)
|
||||
- [Search for slices and arrays by type with `[]`](https://github.com/rust-lang/rust/pull/111958/)
|
||||
- [Clean up type unification and "unboxing"](https://github.com/rust-lang/rust/pull/112233/)
|
||||
|
||||
<a id="1.72.0-Stabilized-APIs"></a>
|
||||
|
||||
Stabilized APIs
|
||||
---------------
|
||||
|
||||
- [`impl<T: Send> Sync for mpsc::Sender<T>`](https://doc.rust-lang.org/nightly/std/sync/mpsc/struct.Sender.html#impl-Sync-for-Sender%3CT%3E)
|
||||
- [`impl TryFrom<&OsStr> for &str`](https://doc.rust-lang.org/nightly/std/primitive.str.html#impl-TryFrom%3C%26'a+OsStr%3E-for-%26'a+str)
|
||||
- [`String::leak`](https://doc.rust-lang.org/nightly/alloc/string/struct.String.html#method.leak)
|
||||
|
||||
These APIs are now stable in const contexts:
|
||||
|
||||
- [`CStr::from_bytes_with_nul`](https://doc.rust-lang.org/nightly/std/ffi/struct.CStr.html#method.from_bytes_with_nul)
|
||||
- [`CStr::to_bytes`](https://doc.rust-lang.org/nightly/std/ffi/struct.CStr.html#method.from_bytes_with_nul)
|
||||
- [`CStr::to_bytes_with_nul`](https://doc.rust-lang.org/nightly/std/ffi/struct.CStr.html#method.from_bytes_with_nul)
|
||||
- [`CStr::to_str`](https://doc.rust-lang.org/nightly/std/ffi/struct.CStr.html#method.from_bytes_with_nul)
|
||||
|
||||
<a id="1.72.0-Cargo"></a>
|
||||
|
||||
Cargo
|
||||
-----
|
||||
|
||||
- Enable `-Zdoctest-in-workspace` by default. When running each documentation
|
||||
test, the working directory is set to the root directory of the package the
|
||||
test belongs to.
|
||||
[docs](https://doc.rust-lang.org/nightly/cargo/commands/cargo-test.html#working-directory-of-tests)
|
||||
[#12221](https://github.com/rust-lang/cargo/pull/12221)
|
||||
[#12288](https://github.com/rust-lang/cargo/pull/12288)
|
||||
- Add support of the "default" keyword to reset previously set `build.jobs`
|
||||
parallelism back to the default.
|
||||
[#12222](https://github.com/rust-lang/cargo/pull/12222)
|
||||
|
||||
<a id="1.72.0-Compatibility-Notes"></a>
|
||||
|
||||
Compatibility Notes
|
||||
-------------------
|
||||
|
||||
- [Alter `Display` for `Ipv6Addr` for IPv4-compatible addresses](https://github.com/rust-lang/rust/pull/112606/)
|
||||
- Cargo changed feature name validation check to a hard error. The warning was
|
||||
added in Rust 1.49. These extended characters aren't allowed on crates.io, so
|
||||
this should only impact users of other registries, or people who don't publish
|
||||
to a registry.
|
||||
[#12291](https://github.com/rust-lang/cargo/pull/12291)
|
||||
|
||||
Version 1.71.1 (2023-08-03)
|
||||
===========================
|
||||
|
||||
@ -102,7 +217,6 @@ Cargo
|
||||
-----
|
||||
- [Allow named debuginfo options in `Cargo.toml`.](https://github.com/rust-lang/cargo/pull/11958/)
|
||||
- [Add `workspace_default_members` to the output of `cargo metadata`.](https://github.com/rust-lang/cargo/pull/11978/)
|
||||
- [`cargo add` now considers `rust-version` when selecting packages.](https://github.com/rust-lang/cargo/pull/12078/)
|
||||
- [Automatically inherit workspace fields when running `cargo new`/`cargo init`.](https://github.com/rust-lang/cargo/pull/12069/)
|
||||
|
||||
<a id="1.71.0-Rustdoc"></a>
|
||||
@ -113,6 +227,11 @@ Rustdoc
|
||||
- [Add a new `rustdoc::unescaped_backticks` lint for broken inline code.](https://github.com/rust-lang/rust/pull/105848/)
|
||||
- [Support strikethrough with single tildes.](https://github.com/rust-lang/rust/pull/111152/) (`~~old~~` vs. `~new~`)
|
||||
|
||||
<a id="1.71.0-Misc"></a>
|
||||
|
||||
Misc
|
||||
----
|
||||
|
||||
<a id="1.71.0-Compatibility-Notes"></a>
|
||||
|
||||
Compatibility Notes
|
||||
@ -136,6 +255,16 @@ Compatibility Notes
|
||||
table. This is considered to be not a use case Cargo would like to support, since it will likely
|
||||
cause problems or lead to confusion.
|
||||
|
||||
<a id="1.71.0-Internal-Changes"></a>
|
||||
|
||||
Internal Changes
|
||||
----------------
|
||||
|
||||
These changes do not affect any public interfaces of Rust, but they represent
|
||||
significant improvements to the performance or internals of rustc and related
|
||||
tools.
|
||||
|
||||
|
||||
Version 1.70.0 (2023-06-01)
|
||||
==========================
|
||||
|
||||
@ -198,7 +327,7 @@ Stabilized APIs
|
||||
- [`Default for std::collections::binary_heap::IntoIter`](https://doc.rust-lang.org/stable/std/collections/binary_heap/struct.IntoIter.html)
|
||||
- [`Default for std::collections::btree_map::{IntoIter, Iter, IterMut}`](https://doc.rust-lang.org/stable/std/collections/btree_map/struct.IntoIter.html)
|
||||
- [`Default for std::collections::btree_map::{IntoKeys, Keys}`](https://doc.rust-lang.org/stable/std/collections/btree_map/struct.IntoKeys.html)
|
||||
- [`Default for std::collections::btree_map::{IntoValues, Values}`](https://doc.rust-lang.org/stable/std/collections/btree_map/struct.IntoKeys.html)
|
||||
- [`Default for std::collections::btree_map::{IntoValues, Values}`](https://doc.rust-lang.org/stable/std/collections/btree_map/struct.IntoValues.html)
|
||||
- [`Default for std::collections::btree_map::Range`](https://doc.rust-lang.org/stable/std/collections/btree_map/struct.Range.html)
|
||||
- [`Default for std::collections::btree_set::{IntoIter, Iter}`](https://doc.rust-lang.org/stable/std/collections/btree_set/struct.IntoIter.html)
|
||||
- [`Default for std::collections::btree_set::Range`](https://doc.rust-lang.org/stable/std/collections/btree_set/struct.Range.html)
|
||||
@ -2613,7 +2742,7 @@ related tools.
|
||||
[`OsStr::to_ascii_lowercase`]: https://doc.rust-lang.org/std/ffi/struct.OsStr.html#method.to_ascii_lowercase
|
||||
[`OsStr::to_ascii_uppercase`]: https://doc.rust-lang.org/std/ffi/struct.OsStr.html#method.to_ascii_uppercase
|
||||
[`Peekable::peek_mut`]: https://doc.rust-lang.org/std/iter/struct.Peekable.html#method.peek_mut
|
||||
[`Rc::decrement_strong_count`]: https://doc.rust-lang.org/std/rc/struct.Rc.html#method.increment_strong_count
|
||||
[`Rc::decrement_strong_count`]: https://doc.rust-lang.org/std/rc/struct.Rc.html#method.decrement_strong_count
|
||||
[`Rc::increment_strong_count`]: https://doc.rust-lang.org/std/rc/struct.Rc.html#method.increment_strong_count
|
||||
[`Vec::extend_from_within`]: https://doc.rust-lang.org/beta/std/vec/struct.Vec.html#method.extend_from_within
|
||||
[`array::from_mut`]: https://doc.rust-lang.org/beta/std/array/fn.from_mut.html
|
||||
@ -2622,7 +2751,7 @@ related tools.
|
||||
[`cmp::max_by`]: https://doc.rust-lang.org/beta/std/cmp/fn.max_by.html
|
||||
[`cmp::min_by_key`]: https://doc.rust-lang.org/beta/std/cmp/fn.min_by_key.html
|
||||
[`cmp::min_by`]: https://doc.rust-lang.org/beta/std/cmp/fn.min_by.html
|
||||
[`f32::is_subnormal`]: https://doc.rust-lang.org/std/primitive.f64.html#method.is_subnormal
|
||||
[`f32::is_subnormal`]: https://doc.rust-lang.org/std/primitive.f32.html#method.is_subnormal
|
||||
[`f64::is_subnormal`]: https://doc.rust-lang.org/std/primitive.f64.html#method.is_subnormal
|
||||
[ietf6943]: https://datatracker.ietf.org/doc/html/rfc6943#section-3.1.1
|
||||
|
||||
@ -2958,7 +3087,7 @@ Internal Only
|
||||
[`sync::OnceState`]: https://doc.rust-lang.org/stable/std/sync/struct.OnceState.html
|
||||
[`panic::panic_any`]: https://doc.rust-lang.org/stable/std/panic/fn.panic_any.html
|
||||
[`slice::strip_prefix`]: https://doc.rust-lang.org/stable/std/primitive.slice.html#method.strip_prefix
|
||||
[`slice::strip_suffix`]: https://doc.rust-lang.org/stable/std/primitive.slice.html#method.strip_prefix
|
||||
[`slice::strip_suffix`]: https://doc.rust-lang.org/stable/std/primitive.slice.html#method.strip_suffix
|
||||
[`Arc::increment_strong_count`]: https://doc.rust-lang.org/nightly/std/sync/struct.Arc.html#method.increment_strong_count
|
||||
[`Arc::decrement_strong_count`]: https://doc.rust-lang.org/nightly/std/sync/struct.Arc.html#method.decrement_strong_count
|
||||
[`slice::fill_with`]: https://doc.rust-lang.org/nightly/std/primitive.slice.html#method.fill_with
|
||||
@ -8028,7 +8157,7 @@ Compatibility Notes
|
||||
[39379]: https://github.com/rust-lang/rust/pull/39379
|
||||
[41105]: https://github.com/rust-lang/rust/issues/41105
|
||||
[`<*const T>::wrapping_offset`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.wrapping_offset
|
||||
[`<*mut T>::wrapping_offset`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.wrapping_offset
|
||||
[`<*mut T>::wrapping_offset`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.wrapping_offset-1
|
||||
[`Duration::checked_add`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.checked_add
|
||||
[`Duration::checked_div`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.checked_div
|
||||
[`Duration::checked_mul`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.checked_mul
|
||||
@ -9006,7 +9135,7 @@ Stabilized APIs
|
||||
* [`f64::to_radians`](https://doc.rust-lang.org/std/primitive.f64.html#method.to_radians)
|
||||
(in libcore - previously stabilized in libstd)
|
||||
* [`Iterator::sum`](https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.sum)
|
||||
* [`Iterator::product`](https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.sum)
|
||||
* [`Iterator::product`](https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.product)
|
||||
* [`Cell::get_mut`](https://doc.rust-lang.org/std/cell/struct.Cell.html#method.get_mut)
|
||||
* [`RefCell::get_mut`](https://doc.rust-lang.org/std/cell/struct.RefCell.html#method.get_mut)
|
||||
|
||||
|
@ -134,7 +134,7 @@ pub trait LayoutCalculator {
|
||||
scalar_valid_range: (Bound<u128>, Bound<u128>),
|
||||
discr_range_of_repr: impl Fn(i128, i128) -> (Integer, bool),
|
||||
discriminants: impl Iterator<Item = (VariantIdx, i128)>,
|
||||
niche_optimize_enum: bool,
|
||||
dont_niche_optimize_enum: bool,
|
||||
always_sized: bool,
|
||||
) -> Option<LayoutS> {
|
||||
let dl = self.current_data_layout();
|
||||
@ -183,10 +183,10 @@ pub trait LayoutCalculator {
|
||||
// (Typechecking will reject discriminant-sizing attrs.)
|
||||
|
||||
let v = present_first;
|
||||
let kind = if is_enum || variants[v].is_empty() {
|
||||
let kind = if is_enum || variants[v].is_empty() || always_sized {
|
||||
StructKind::AlwaysSized
|
||||
} else {
|
||||
if !always_sized { StructKind::MaybeUnsized } else { StructKind::AlwaysSized }
|
||||
StructKind::MaybeUnsized
|
||||
};
|
||||
|
||||
let mut st = self.univariant(dl, &variants[v], repr, kind)?;
|
||||
@ -280,7 +280,7 @@ pub trait LayoutCalculator {
|
||||
}
|
||||
|
||||
let calculate_niche_filling_layout = || -> Option<TmpLayout> {
|
||||
if niche_optimize_enum {
|
||||
if dont_niche_optimize_enum {
|
||||
return None;
|
||||
}
|
||||
|
||||
|
@ -209,7 +209,7 @@ pub enum TargetDataLayoutErrors<'a> {
|
||||
InvalidAddressSpace { addr_space: &'a str, cause: &'a str, err: ParseIntError },
|
||||
InvalidBits { kind: &'a str, bit: &'a str, cause: &'a str, err: ParseIntError },
|
||||
MissingAlignment { cause: &'a str },
|
||||
InvalidAlignment { cause: &'a str, err: String },
|
||||
InvalidAlignment { cause: &'a str, err: AlignFromBytesError },
|
||||
InconsistentTargetArchitecture { dl: &'a str, target: &'a str },
|
||||
InconsistentTargetPointerWidth { pointer_size: u64, target: u32 },
|
||||
InvalidBitsSize { err: String },
|
||||
@ -414,7 +414,9 @@ pub struct Size {
|
||||
// Safety: Ord is implement as just comparing numerical values and numerical values
|
||||
// are not changed by (de-)serialization.
|
||||
#[cfg(feature = "nightly")]
|
||||
unsafe impl StableOrd for Size {}
|
||||
unsafe impl StableOrd for Size {
|
||||
const CAN_USE_UNSTABLE_SORT: bool = true;
|
||||
}
|
||||
|
||||
// This is debug-printed a lot in larger structs, don't waste too much space there
|
||||
impl fmt::Debug for Size {
|
||||
@ -640,30 +642,65 @@ impl fmt::Debug for Align {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum AlignFromBytesError {
|
||||
NotPowerOfTwo(u64),
|
||||
TooLarge(u64),
|
||||
}
|
||||
|
||||
impl AlignFromBytesError {
|
||||
pub fn diag_ident(self) -> &'static str {
|
||||
match self {
|
||||
Self::NotPowerOfTwo(_) => "not_power_of_two",
|
||||
Self::TooLarge(_) => "too_large",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn align(self) -> u64 {
|
||||
let (Self::NotPowerOfTwo(align) | Self::TooLarge(align)) = self;
|
||||
align
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for AlignFromBytesError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt::Display::fmt(self, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for AlignFromBytesError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
AlignFromBytesError::NotPowerOfTwo(align) => write!(f, "`{align}` is not a power of 2"),
|
||||
AlignFromBytesError::TooLarge(align) => write!(f, "`{align}` is too large"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Align {
|
||||
pub const ONE: Align = Align { pow2: 0 };
|
||||
pub const MAX: Align = Align { pow2: 29 };
|
||||
|
||||
#[inline]
|
||||
pub fn from_bits(bits: u64) -> Result<Align, String> {
|
||||
pub fn from_bits(bits: u64) -> Result<Align, AlignFromBytesError> {
|
||||
Align::from_bytes(Size::from_bits(bits).bytes())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn from_bytes(align: u64) -> Result<Align, String> {
|
||||
pub fn from_bytes(align: u64) -> Result<Align, AlignFromBytesError> {
|
||||
// Treat an alignment of 0 bytes like 1-byte alignment.
|
||||
if align == 0 {
|
||||
return Ok(Align::ONE);
|
||||
}
|
||||
|
||||
#[cold]
|
||||
fn not_power_of_2(align: u64) -> String {
|
||||
format!("`{}` is not a power of 2", align)
|
||||
fn not_power_of_2(align: u64) -> AlignFromBytesError {
|
||||
AlignFromBytesError::NotPowerOfTwo(align)
|
||||
}
|
||||
|
||||
#[cold]
|
||||
fn too_large(align: u64) -> String {
|
||||
format!("`{}` is too large", align)
|
||||
fn too_large(align: u64) -> AlignFromBytesError {
|
||||
AlignFromBytesError::TooLarge(align)
|
||||
}
|
||||
|
||||
let tz = align.trailing_zeros();
|
||||
|
@ -67,7 +67,7 @@ struct ArenaChunk<T = u8> {
|
||||
|
||||
unsafe impl<#[may_dangle] T> Drop for ArenaChunk<T> {
|
||||
fn drop(&mut self) {
|
||||
unsafe { Box::from_raw(self.storage.as_mut()) };
|
||||
unsafe { drop(Box::from_raw(self.storage.as_mut())) }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1295,6 +1295,7 @@ impl Expr {
|
||||
ExprKind::Yield(..) => ExprPrecedence::Yield,
|
||||
ExprKind::Yeet(..) => ExprPrecedence::Yeet,
|
||||
ExprKind::FormatArgs(..) => ExprPrecedence::FormatArgs,
|
||||
ExprKind::Become(..) => ExprPrecedence::Become,
|
||||
ExprKind::Err => ExprPrecedence::Err,
|
||||
}
|
||||
}
|
||||
@ -1515,6 +1516,11 @@ pub enum ExprKind {
|
||||
/// with an optional value to be returned.
|
||||
Yeet(Option<P<Expr>>),
|
||||
|
||||
/// A tail call return, with the value to be returned.
|
||||
///
|
||||
/// While `.0` must be a function call, we check this later, after parsing.
|
||||
Become(P<Expr>),
|
||||
|
||||
/// Bytes included via `include_bytes!`
|
||||
/// Added for optimization purposes to avoid the need to escape
|
||||
/// large binary blobs - should always behave like [`ExprKind::Lit`]
|
||||
@ -2646,6 +2652,15 @@ pub struct NormalAttr {
|
||||
pub tokens: Option<LazyAttrTokenStream>,
|
||||
}
|
||||
|
||||
impl NormalAttr {
|
||||
pub fn from_ident(ident: Ident) -> Self {
|
||||
Self {
|
||||
item: AttrItem { path: Path::from_ident(ident), args: AttrArgs::Empty, tokens: None },
|
||||
tokens: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)]
|
||||
pub struct AttrItem {
|
||||
pub path: Path,
|
||||
|
@ -1,3 +1,20 @@
|
||||
//! Definitions shared by macros / syntax extensions and e.g. `rustc_middle`.
|
||||
|
||||
use rustc_span::{def_id::DefId, symbol::Ident};
|
||||
|
||||
use crate::MetaItem;
|
||||
|
||||
pub mod allocator;
|
||||
|
||||
#[derive(Debug, Clone, Encodable, Decodable, HashStable_Generic)]
|
||||
pub struct StrippedCfgItem<ModId = DefId> {
|
||||
pub parent_module: ModId,
|
||||
pub name: Ident,
|
||||
pub cfg: MetaItem,
|
||||
}
|
||||
|
||||
impl<ModId> StrippedCfgItem<ModId> {
|
||||
pub fn map_mod_id<New>(self, f: impl FnOnce(ModId) -> New) -> StrippedCfgItem<New> {
|
||||
StrippedCfgItem { parent_module: f(self.parent_module), name: self.name, cfg: self.cfg }
|
||||
}
|
||||
}
|
||||
|
@ -1457,6 +1457,7 @@ pub fn noop_visit_expr<T: MutVisitor>(
|
||||
ExprKind::Yeet(expr) => {
|
||||
visit_opt(expr, |expr| vis.visit_expr(expr));
|
||||
}
|
||||
ExprKind::Become(expr) => vis.visit_expr(expr),
|
||||
ExprKind::InlineAsm(asm) => vis.visit_inline_asm(asm),
|
||||
ExprKind::FormatArgs(fmt) => vis.visit_format_args(fmt),
|
||||
ExprKind::OffsetOf(container, fields) => {
|
||||
|
@ -11,6 +11,7 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_macros::HashStable_Generic;
|
||||
use rustc_span::symbol::{kw, sym};
|
||||
#[cfg_attr(not(bootstrap), allow(hidden_glob_reexports))]
|
||||
use rustc_span::symbol::{Ident, Symbol};
|
||||
use rustc_span::{self, edition::Edition, Span, DUMMY_SP};
|
||||
use std::borrow::Cow;
|
||||
|
@ -25,7 +25,7 @@ use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
|
||||
use rustc_span::{Span, DUMMY_SP};
|
||||
use smallvec::{smallvec, SmallVec};
|
||||
|
||||
use std::{fmt, iter};
|
||||
use std::{fmt, iter, mem};
|
||||
|
||||
/// When the main Rust parser encounters a syntax-extension invocation, it
|
||||
/// parses the arguments to the invocation as a token tree. This is a very
|
||||
@ -410,8 +410,17 @@ impl TokenStream {
|
||||
t1.next().is_none() && t2.next().is_none()
|
||||
}
|
||||
|
||||
pub fn map_enumerated<F: FnMut(usize, &TokenTree) -> TokenTree>(self, mut f: F) -> TokenStream {
|
||||
TokenStream(Lrc::new(self.0.iter().enumerate().map(|(i, tree)| f(i, tree)).collect()))
|
||||
/// Applies the supplied function to each `TokenTree` and its index in `self`, returning a new `TokenStream`
|
||||
///
|
||||
/// It is equivalent to `TokenStream::new(self.trees().cloned().enumerate().map(|(i, tt)| f(i, tt)).collect())`.
|
||||
pub fn map_enumerated_owned(
|
||||
mut self,
|
||||
mut f: impl FnMut(usize, TokenTree) -> TokenTree,
|
||||
) -> TokenStream {
|
||||
let owned = Lrc::make_mut(&mut self.0); // clone if necessary
|
||||
// rely on vec's in-place optimizations to avoid another allocation
|
||||
*owned = mem::take(owned).into_iter().enumerate().map(|(i, tree)| f(i, tree)).collect();
|
||||
self
|
||||
}
|
||||
|
||||
/// Create a token stream containing a single token with alone spacing.
|
||||
|
@ -245,6 +245,7 @@ pub enum ExprPrecedence {
|
||||
Ret,
|
||||
Yield,
|
||||
Yeet,
|
||||
Become,
|
||||
|
||||
Range,
|
||||
|
||||
@ -298,7 +299,8 @@ impl ExprPrecedence {
|
||||
| ExprPrecedence::Continue
|
||||
| ExprPrecedence::Ret
|
||||
| ExprPrecedence::Yield
|
||||
| ExprPrecedence::Yeet => PREC_JUMP,
|
||||
| ExprPrecedence::Yeet
|
||||
| ExprPrecedence::Become => PREC_JUMP,
|
||||
|
||||
// `Range` claims to have higher precedence than `Assign`, but `x .. x = x` fails to
|
||||
// parse, instead of parsing as `(x .. x) = x`. Giving `Range` a lower precedence
|
||||
|
@ -908,6 +908,7 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {
|
||||
ExprKind::Yeet(optional_expression) => {
|
||||
walk_list!(visitor, visit_expr, optional_expression);
|
||||
}
|
||||
ExprKind::Become(expr) => visitor.visit_expr(expr),
|
||||
ExprKind::MacCall(mac) => visitor.visit_mac_call(mac),
|
||||
ExprKind::Paren(subexpression) => visitor.visit_expr(subexpression),
|
||||
ExprKind::InlineAsm(asm) => visitor.visit_inline_asm(asm),
|
||||
|
@ -44,6 +44,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
| asm::InlineAsmArch::AArch64
|
||||
| asm::InlineAsmArch::RiscV32
|
||||
| asm::InlineAsmArch::RiscV64
|
||||
| asm::InlineAsmArch::LoongArch64
|
||||
);
|
||||
if !is_stable && !self.tcx.features().asm_experimental_arch {
|
||||
feature_err(
|
||||
|
@ -71,9 +71,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
|
||||
let kind = match &e.kind {
|
||||
ExprKind::Array(exprs) => hir::ExprKind::Array(self.lower_exprs(exprs)),
|
||||
ExprKind::ConstBlock(anon_const) => {
|
||||
let anon_const = self.lower_anon_const(anon_const);
|
||||
hir::ExprKind::ConstBlock(anon_const)
|
||||
ExprKind::ConstBlock(c) => {
|
||||
let c = self.with_new_scopes(|this| hir::ConstBlock {
|
||||
def_id: this.local_def_id(c.id),
|
||||
hir_id: this.lower_node_id(c.id),
|
||||
body: this.lower_const_body(c.value.span, Some(&c.value)),
|
||||
});
|
||||
hir::ExprKind::ConstBlock(c)
|
||||
}
|
||||
ExprKind::Repeat(expr, count) => {
|
||||
let expr = self.lower_expr(expr);
|
||||
@ -271,6 +275,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
hir::ExprKind::Ret(e)
|
||||
}
|
||||
ExprKind::Yeet(sub_expr) => self.lower_expr_yeet(e.span, sub_expr.as_deref()),
|
||||
ExprKind::Become(sub_expr) => {
|
||||
let sub_expr = self.lower_expr(sub_expr);
|
||||
hir::ExprKind::Become(sub_expr)
|
||||
}
|
||||
ExprKind::InlineAsm(asm) => {
|
||||
hir::ExprKind::InlineAsm(self.lower_inline_asm(e.span, asm))
|
||||
}
|
||||
@ -665,14 +673,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
self.lower_attrs(
|
||||
inner_hir_id,
|
||||
&[Attribute {
|
||||
kind: AttrKind::Normal(ptr::P(NormalAttr {
|
||||
item: AttrItem {
|
||||
path: Path::from_ident(Ident::new(sym::track_caller, span)),
|
||||
args: AttrArgs::Empty,
|
||||
tokens: None,
|
||||
},
|
||||
tokens: None,
|
||||
})),
|
||||
kind: AttrKind::Normal(ptr::P(NormalAttr::from_ident(Ident::new(sym::track_caller, span)))),
|
||||
id: self.tcx.sess.parse_sess.attr_id_generator.mk_attr_id(),
|
||||
style: AttrStyle::Outer,
|
||||
span: unstable_span,
|
||||
|
@ -223,6 +223,14 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
|
||||
});
|
||||
}
|
||||
|
||||
fn visit_inline_const(&mut self, constant: &'hir ConstBlock) {
|
||||
self.insert(DUMMY_SP, constant.hir_id, Node::ConstBlock(constant));
|
||||
|
||||
self.with_parent(constant.hir_id, |this| {
|
||||
intravisit::walk_inline_const(this, constant);
|
||||
});
|
||||
}
|
||||
|
||||
fn visit_expr(&mut self, expr: &'hir Expr<'hir>) {
|
||||
self.insert(expr.span, expr.hir_id, Node::Expr(expr));
|
||||
|
||||
|
@ -3,6 +3,7 @@ use super::ResolverAstLoweringExt;
|
||||
use super::{AstOwner, ImplTraitContext, ImplTraitPosition};
|
||||
use super::{FnDeclKind, LoweringContext, ParamMode};
|
||||
|
||||
use hir::definitions::DefPathData;
|
||||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::visit::AssocCtxt;
|
||||
use rustc_ast::*;
|
||||
@ -257,10 +258,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
);
|
||||
|
||||
let itctx = ImplTraitContext::Universal;
|
||||
let (generics, decl) = this.lower_generics(generics, id, &itctx, |this| {
|
||||
let ret_id = asyncness.opt_return_id();
|
||||
this.lower_fn_decl(&decl, id, *fn_sig_span, FnDeclKind::Fn, ret_id)
|
||||
});
|
||||
let (generics, decl) =
|
||||
this.lower_generics(generics, header.constness, id, &itctx, |this| {
|
||||
let ret_id = asyncness.opt_return_id();
|
||||
this.lower_fn_decl(&decl, id, *fn_sig_span, FnDeclKind::Fn, ret_id)
|
||||
});
|
||||
let sig = hir::FnSig {
|
||||
decl,
|
||||
header: this.lower_fn_header(*header),
|
||||
@ -295,6 +297,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
add_ty_alias_where_clause(&mut generics, *where_clauses, true);
|
||||
let (generics, ty) = self.lower_generics(
|
||||
&generics,
|
||||
Const::No,
|
||||
id,
|
||||
&ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
||||
|this| match ty {
|
||||
@ -316,6 +319,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
ItemKind::Enum(enum_definition, generics) => {
|
||||
let (generics, variants) = self.lower_generics(
|
||||
generics,
|
||||
Const::No,
|
||||
id,
|
||||
&ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
||||
|this| {
|
||||
@ -329,6 +333,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
ItemKind::Struct(struct_def, generics) => {
|
||||
let (generics, struct_def) = self.lower_generics(
|
||||
generics,
|
||||
Const::No,
|
||||
id,
|
||||
&ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
||||
|this| this.lower_variant_data(hir_id, struct_def),
|
||||
@ -338,6 +343,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
ItemKind::Union(vdata, generics) => {
|
||||
let (generics, vdata) = self.lower_generics(
|
||||
generics,
|
||||
Const::No,
|
||||
id,
|
||||
&ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
||||
|this| this.lower_variant_data(hir_id, vdata),
|
||||
@ -369,7 +375,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
// parent lifetime.
|
||||
let itctx = ImplTraitContext::Universal;
|
||||
let (generics, (trait_ref, lowered_ty)) =
|
||||
self.lower_generics(ast_generics, id, &itctx, |this| {
|
||||
self.lower_generics(ast_generics, *constness, id, &itctx, |this| {
|
||||
let trait_ref = trait_ref.as_ref().map(|trait_ref| {
|
||||
this.lower_trait_ref(
|
||||
trait_ref,
|
||||
@ -410,8 +416,15 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
}))
|
||||
}
|
||||
ItemKind::Trait(box Trait { is_auto, unsafety, generics, bounds, items }) => {
|
||||
// FIXME(const_trait_impl, effects, fee1-dead) this should be simplified if possible
|
||||
let constness = attrs
|
||||
.unwrap_or(&[])
|
||||
.iter()
|
||||
.find(|x| x.has_name(sym::const_trait))
|
||||
.map_or(Const::No, |x| Const::Yes(x.span));
|
||||
let (generics, (unsafety, items, bounds)) = self.lower_generics(
|
||||
generics,
|
||||
constness,
|
||||
id,
|
||||
&ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
||||
|this| {
|
||||
@ -431,6 +444,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
ItemKind::TraitAlias(generics, bounds) => {
|
||||
let (generics, bounds) = self.lower_generics(
|
||||
generics,
|
||||
Const::No,
|
||||
id,
|
||||
&ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
||||
|this| {
|
||||
@ -593,7 +607,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
let fdec = &sig.decl;
|
||||
let itctx = ImplTraitContext::Universal;
|
||||
let (generics, (fn_dec, fn_args)) =
|
||||
self.lower_generics(generics, i.id, &itctx, |this| {
|
||||
self.lower_generics(generics, Const::No, i.id, &itctx, |this| {
|
||||
(
|
||||
// Disallow `impl Trait` in foreign items.
|
||||
this.lower_fn_decl(
|
||||
@ -745,6 +759,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
add_ty_alias_where_clause(&mut generics, *where_clauses, false);
|
||||
let (generics, kind) = self.lower_generics(
|
||||
&generics,
|
||||
Const::No,
|
||||
i.id,
|
||||
&ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
||||
|this| {
|
||||
@ -843,6 +858,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
add_ty_alias_where_clause(&mut generics, *where_clauses, false);
|
||||
self.lower_generics(
|
||||
&generics,
|
||||
Const::No,
|
||||
i.id,
|
||||
&ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
||||
|this| match ty {
|
||||
@ -1201,9 +1217,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
) -> (&'hir hir::Generics<'hir>, hir::FnSig<'hir>) {
|
||||
let header = self.lower_fn_header(sig.header);
|
||||
let itctx = ImplTraitContext::Universal;
|
||||
let (generics, decl) = self.lower_generics(generics, id, &itctx, |this| {
|
||||
this.lower_fn_decl(&sig.decl, id, sig.span, kind, is_async)
|
||||
});
|
||||
let (generics, decl) =
|
||||
self.lower_generics(generics, sig.header.constness, id, &itctx, |this| {
|
||||
this.lower_fn_decl(&sig.decl, id, sig.span, kind, is_async)
|
||||
});
|
||||
(generics, hir::FnSig { header, decl, span: self.lower_span(sig.span) })
|
||||
}
|
||||
|
||||
@ -1275,6 +1292,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
fn lower_generics<T>(
|
||||
&mut self,
|
||||
generics: &Generics,
|
||||
constness: Const,
|
||||
parent_node_id: NodeId,
|
||||
itctx: &ImplTraitContext,
|
||||
f: impl FnOnce(&mut Self) -> T,
|
||||
@ -1372,6 +1390,87 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
let impl_trait_bounds = std::mem::take(&mut self.impl_trait_bounds);
|
||||
predicates.extend(impl_trait_bounds.into_iter());
|
||||
|
||||
// Desugar `~const` bound in generics into an additional `const host: bool` param
|
||||
// if the effects feature is enabled.
|
||||
if let Const::Yes(span) = constness && self.tcx.features().effects
|
||||
// Do not add host param if it already has it (manually specified)
|
||||
&& !params.iter().any(|x| {
|
||||
self.attrs.get(&x.hir_id.local_id).map_or(false, |attrs| {
|
||||
attrs.iter().any(|x| x.has_name(sym::rustc_host))
|
||||
})
|
||||
})
|
||||
{
|
||||
let param_node_id = self.next_node_id();
|
||||
let const_node_id = self.next_node_id();
|
||||
let def_id = self.create_def(self.local_def_id(parent_node_id), param_node_id, DefPathData::TypeNs(sym::host), span);
|
||||
let anon_const: LocalDefId = self.create_def(def_id, const_node_id, DefPathData::AnonConst, span);
|
||||
|
||||
let hir_id = self.next_id();
|
||||
let const_id = self.next_id();
|
||||
let const_expr_id = self.next_id();
|
||||
let bool_id = self.next_id();
|
||||
|
||||
self.children.push((def_id, hir::MaybeOwner::NonOwner(hir_id)));
|
||||
self.children.push((anon_const, hir::MaybeOwner::NonOwner(const_id)));
|
||||
|
||||
let attr_id = self.tcx.sess.parse_sess.attr_id_generator.mk_attr_id();
|
||||
|
||||
let attrs = self.arena.alloc_from_iter([
|
||||
Attribute {
|
||||
kind: AttrKind::Normal(P(NormalAttr::from_ident(Ident::new(sym::rustc_host, span)))),
|
||||
span,
|
||||
id: attr_id,
|
||||
style: AttrStyle::Outer,
|
||||
},
|
||||
]);
|
||||
self.attrs.insert(hir_id.local_id, attrs);
|
||||
|
||||
let const_body = self.lower_body(|this| {
|
||||
(
|
||||
&[],
|
||||
hir::Expr {
|
||||
hir_id: const_expr_id,
|
||||
kind: hir::ExprKind::Lit(
|
||||
this.arena.alloc(hir::Lit { node: LitKind::Bool(true), span }),
|
||||
),
|
||||
span,
|
||||
},
|
||||
)
|
||||
});
|
||||
|
||||
let param = hir::GenericParam {
|
||||
def_id,
|
||||
hir_id,
|
||||
name: hir::ParamName::Plain(Ident { name: sym::host, span }),
|
||||
span,
|
||||
kind: hir::GenericParamKind::Const {
|
||||
ty: self.arena.alloc(self.ty(
|
||||
span,
|
||||
hir::TyKind::Path(hir::QPath::Resolved(
|
||||
None,
|
||||
self.arena.alloc(hir::Path {
|
||||
res: Res::PrimTy(hir::PrimTy::Bool),
|
||||
span,
|
||||
segments: self.arena.alloc_from_iter([hir::PathSegment {
|
||||
ident: Ident { name: sym::bool, span },
|
||||
hir_id: bool_id,
|
||||
res: Res::PrimTy(hir::PrimTy::Bool),
|
||||
args: None,
|
||||
infer_args: false,
|
||||
}]),
|
||||
}),
|
||||
)),
|
||||
)),
|
||||
default: Some(hir::AnonConst { def_id: anon_const, hir_id: const_id, body: const_body }),
|
||||
},
|
||||
colon_span: None,
|
||||
pure_wrt_drop: false,
|
||||
source: hir::GenericParamSource::Generics,
|
||||
};
|
||||
|
||||
params.push(param);
|
||||
}
|
||||
|
||||
let lowered_generics = self.arena.alloc(hir::Generics {
|
||||
params: self.arena.alloc_from_iter(params),
|
||||
predicates: self.arena.alloc_from_iter(predicates),
|
||||
|
@ -1539,9 +1539,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
);
|
||||
debug!(?opaque_ty_def_id);
|
||||
|
||||
// Contains the new lifetime definitions created for the TAIT (if any).
|
||||
let mut collected_lifetimes = Vec::new();
|
||||
|
||||
// If this came from a TAIT (as opposed to a function that returns an RPIT), we only want
|
||||
// to capture the lifetimes that appear in the bounds. So visit the bounds to find out
|
||||
// exactly which ones those are.
|
||||
@ -1558,20 +1555,31 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
};
|
||||
debug!(?lifetimes_to_remap);
|
||||
|
||||
let mut new_remapping = FxHashMap::default();
|
||||
|
||||
// Contains the new lifetime definitions created for the TAIT (if any).
|
||||
// If this opaque type is only capturing a subset of the lifetimes (those that appear in
|
||||
// bounds), then create the new lifetime parameters required and create a mapping from the
|
||||
// old `'a` (on the function) to the new `'a` (on the opaque type).
|
||||
let collected_lifetimes =
|
||||
self.create_lifetime_defs(opaque_ty_def_id, &lifetimes_to_remap, &mut new_remapping);
|
||||
debug!(?collected_lifetimes);
|
||||
debug!(?new_remapping);
|
||||
|
||||
// This creates HIR lifetime arguments as `hir::GenericArg`, in the given example `type
|
||||
// TestReturn<'a, T, 'x> = impl Debug + 'x`, it creates a collection containing `&['x]`.
|
||||
let collected_lifetime_mapping: Vec<_> = collected_lifetimes
|
||||
.iter()
|
||||
.map(|(node_id, lifetime)| {
|
||||
let id = self.next_node_id();
|
||||
let lifetime = self.new_named_lifetime(lifetime.id, id, lifetime.ident);
|
||||
let def_id = self.local_def_id(*node_id);
|
||||
(lifetime, def_id)
|
||||
})
|
||||
.collect();
|
||||
debug!(?collected_lifetime_mapping);
|
||||
|
||||
self.with_hir_id_owner(opaque_ty_node_id, |lctx| {
|
||||
let mut new_remapping = FxHashMap::default();
|
||||
|
||||
// If this opaque type is only capturing a subset of the lifetimes (those that appear
|
||||
// in bounds), then create the new lifetime parameters required and create a mapping
|
||||
// from the old `'a` (on the function) to the new `'a` (on the opaque type).
|
||||
collected_lifetimes = lctx.create_lifetime_defs(
|
||||
opaque_ty_def_id,
|
||||
&lifetimes_to_remap,
|
||||
&mut new_remapping,
|
||||
);
|
||||
debug!(?collected_lifetimes);
|
||||
debug!(?new_remapping);
|
||||
|
||||
// Install the remapping from old to new (if any):
|
||||
lctx.with_remapping(new_remapping, |lctx| {
|
||||
// This creates HIR lifetime definitions as `hir::GenericParam`, in the given
|
||||
@ -1610,6 +1618,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
let hir_bounds = lctx.lower_param_bounds(bounds, itctx);
|
||||
debug!(?hir_bounds);
|
||||
|
||||
let lifetime_mapping = if in_trait {
|
||||
self.arena.alloc_from_iter(
|
||||
collected_lifetime_mapping
|
||||
.iter()
|
||||
.map(|(lifetime, def_id)| (**lifetime, *def_id)),
|
||||
)
|
||||
} else {
|
||||
&mut []
|
||||
};
|
||||
|
||||
let opaque_ty_item = hir::OpaqueTy {
|
||||
generics: self.arena.alloc(hir::Generics {
|
||||
params: lifetime_defs,
|
||||
@ -1620,6 +1638,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
}),
|
||||
bounds: hir_bounds,
|
||||
origin,
|
||||
lifetime_mapping,
|
||||
in_trait,
|
||||
};
|
||||
debug!(?opaque_ty_item);
|
||||
@ -1628,20 +1647,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
})
|
||||
});
|
||||
|
||||
// This creates HIR lifetime arguments as `hir::GenericArg`, in the given example `type
|
||||
// TestReturn<'a, T, 'x> = impl Debug + 'x`, it creates a collection containing `&['x]`.
|
||||
let lifetimes =
|
||||
self.arena.alloc_from_iter(collected_lifetimes.into_iter().map(|(_, lifetime)| {
|
||||
let id = self.next_node_id();
|
||||
let l = self.new_named_lifetime(lifetime.id, id, lifetime.ident);
|
||||
hir::GenericArg::Lifetime(l)
|
||||
}));
|
||||
debug!(?lifetimes);
|
||||
|
||||
// `impl Trait` now just becomes `Foo<'a, 'b, ..>`.
|
||||
hir::TyKind::OpaqueDef(
|
||||
hir::ItemId { owner_id: hir::OwnerId { def_id: opaque_ty_def_id } },
|
||||
lifetimes,
|
||||
self.arena.alloc_from_iter(
|
||||
collected_lifetime_mapping
|
||||
.iter()
|
||||
.map(|(lifetime, _)| hir::GenericArg::Lifetime(*lifetime)),
|
||||
),
|
||||
in_trait,
|
||||
)
|
||||
}
|
||||
@ -1655,7 +1668,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
span: Span,
|
||||
opaque_ty_span: Span,
|
||||
) -> hir::OwnerNode<'hir> {
|
||||
let opaque_ty_item_kind = hir::ItemKind::OpaqueTy(opaque_ty_item);
|
||||
let opaque_ty_item_kind = hir::ItemKind::OpaqueTy(self.arena.alloc(opaque_ty_item));
|
||||
// Generate an `type Foo = impl Trait;` declaration.
|
||||
trace!("registering opaque type with id {:#?}", opaque_ty_id);
|
||||
let opaque_ty_item = hir::Item {
|
||||
@ -1983,7 +1996,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
let lifetime = Lifetime { id: outer_node_id, ident };
|
||||
collected_lifetimes.push((inner_node_id, lifetime, Some(inner_res)));
|
||||
}
|
||||
|
||||
debug!(?collected_lifetimes);
|
||||
|
||||
// We only want to capture the lifetimes that appear in the bounds. So visit the bounds to
|
||||
@ -1993,22 +2005,36 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
let lifetimes_to_remap = lifetime_collector::lifetimes_in_ret_ty(&self.resolver, output);
|
||||
debug!(?lifetimes_to_remap);
|
||||
|
||||
self.with_hir_id_owner(opaque_ty_node_id, |this| {
|
||||
// If this opaque type is only capturing a subset of the lifetimes (those that appear
|
||||
// in bounds), then create the new lifetime parameters required and create a mapping
|
||||
// from the old `'a` (on the function) to the new `'a` (on the opaque type).
|
||||
collected_lifetimes.extend(
|
||||
this.create_lifetime_defs(
|
||||
opaque_ty_def_id,
|
||||
&lifetimes_to_remap,
|
||||
&mut new_remapping,
|
||||
)
|
||||
// If this opaque type is only capturing a subset of the lifetimes (those that appear in
|
||||
// bounds), then create the new lifetime parameters required and create a mapping from the
|
||||
// old `'a` (on the function) to the new `'a` (on the opaque type).
|
||||
collected_lifetimes.extend(
|
||||
self.create_lifetime_defs(opaque_ty_def_id, &lifetimes_to_remap, &mut new_remapping)
|
||||
.into_iter()
|
||||
.map(|(new_node_id, lifetime)| (new_node_id, lifetime, None)),
|
||||
);
|
||||
debug!(?collected_lifetimes);
|
||||
debug!(?new_remapping);
|
||||
);
|
||||
debug!(?collected_lifetimes);
|
||||
debug!(?new_remapping);
|
||||
|
||||
// This creates pairs of HIR lifetimes and def_ids. In the given example `type
|
||||
// TestReturn<'a, T, 'x> = impl Debug + 'x`, it creates a collection containing the
|
||||
// new lifetime of the RPIT 'x and the def_id of the lifetime 'x corresponding to
|
||||
// `TestReturn`.
|
||||
let collected_lifetime_mapping: Vec<_> = collected_lifetimes
|
||||
.iter()
|
||||
.map(|(node_id, lifetime, res)| {
|
||||
let id = self.next_node_id();
|
||||
let res = res.unwrap_or(
|
||||
self.resolver.get_lifetime_res(lifetime.id).unwrap_or(LifetimeRes::Error),
|
||||
);
|
||||
let lifetime = self.new_named_lifetime_with_res(id, lifetime.ident, res);
|
||||
let def_id = self.local_def_id(*node_id);
|
||||
(lifetime, def_id)
|
||||
})
|
||||
.collect();
|
||||
debug!(?collected_lifetime_mapping);
|
||||
|
||||
self.with_hir_id_owner(opaque_ty_node_id, |this| {
|
||||
// Install the remapping from old to new (if any):
|
||||
this.with_remapping(new_remapping, |this| {
|
||||
// We have to be careful to get elision right here. The
|
||||
@ -2063,6 +2089,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
));
|
||||
debug!("lower_async_fn_ret_ty: generic_params={:#?}", generic_params);
|
||||
|
||||
let lifetime_mapping = if in_trait {
|
||||
self.arena.alloc_from_iter(
|
||||
collected_lifetime_mapping
|
||||
.iter()
|
||||
.map(|(lifetime, def_id)| (**lifetime, *def_id)),
|
||||
)
|
||||
} else {
|
||||
&mut []
|
||||
};
|
||||
|
||||
let opaque_ty_item = hir::OpaqueTy {
|
||||
generics: this.arena.alloc(hir::Generics {
|
||||
params: generic_params,
|
||||
@ -2073,6 +2109,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
}),
|
||||
bounds: arena_vec![this; future_bound],
|
||||
origin: hir::OpaqueTyOrigin::AsyncFn(fn_def_id),
|
||||
lifetime_mapping,
|
||||
in_trait,
|
||||
};
|
||||
|
||||
@ -2096,15 +2133,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
//
|
||||
// For the "output" lifetime parameters, we just want to
|
||||
// generate `'_`.
|
||||
let generic_args = self.arena.alloc_from_iter(collected_lifetimes.into_iter().map(
|
||||
|(_, lifetime, res)| {
|
||||
let id = self.next_node_id();
|
||||
let res = res.unwrap_or(
|
||||
self.resolver.get_lifetime_res(lifetime.id).unwrap_or(LifetimeRes::Error),
|
||||
);
|
||||
hir::GenericArg::Lifetime(self.new_named_lifetime_with_res(id, lifetime.ident, res))
|
||||
},
|
||||
));
|
||||
let generic_args = self.arena.alloc_from_iter(
|
||||
collected_lifetime_mapping
|
||||
.iter()
|
||||
.map(|(lifetime, _)| hir::GenericArg::Lifetime(*lifetime)),
|
||||
);
|
||||
|
||||
// Create the `Foo<...>` reference itself. Note that the `type
|
||||
// Foo = impl Trait` is, internally, created as a child of the
|
||||
|
@ -364,7 +364,12 @@ impl<'a> AstValidator<'a> {
|
||||
self.err_handler().emit_err(errors::BoundInContext { span, ctx });
|
||||
}
|
||||
|
||||
fn check_foreign_ty_genericless(&self, generics: &Generics, where_span: Span) {
|
||||
fn check_foreign_ty_genericless(
|
||||
&self,
|
||||
generics: &Generics,
|
||||
before_where_clause: &TyAliasWhereClause,
|
||||
after_where_clause: &TyAliasWhereClause,
|
||||
) {
|
||||
let cannot_have = |span, descr, remove_descr| {
|
||||
self.err_handler().emit_err(errors::ExternTypesCannotHave {
|
||||
span,
|
||||
@ -378,9 +383,14 @@ impl<'a> AstValidator<'a> {
|
||||
cannot_have(generics.span, "generic parameters", "generic parameters");
|
||||
}
|
||||
|
||||
if !generics.where_clause.predicates.is_empty() {
|
||||
cannot_have(where_span, "`where` clauses", "`where` clause");
|
||||
}
|
||||
let check_where_clause = |where_clause: &TyAliasWhereClause| {
|
||||
if let TyAliasWhereClause(true, where_clause_span) = where_clause {
|
||||
cannot_have(*where_clause_span, "`where` clauses", "`where` clause");
|
||||
}
|
||||
};
|
||||
|
||||
check_where_clause(before_where_clause);
|
||||
check_where_clause(after_where_clause);
|
||||
}
|
||||
|
||||
fn check_foreign_kind_bodyless(&self, ident: Ident, kind: &str, body: Option<Span>) {
|
||||
@ -613,13 +623,12 @@ impl<'a> AstValidator<'a> {
|
||||
fn maybe_lint_missing_abi(&mut self, span: Span, id: NodeId) {
|
||||
// FIXME(davidtwco): This is a hack to detect macros which produce spans of the
|
||||
// call site which do not have a macro backtrace. See #61963.
|
||||
let is_macro_callsite = self
|
||||
if self
|
||||
.session
|
||||
.source_map()
|
||||
.span_to_snippet(span)
|
||||
.map(|snippet| snippet.starts_with("#["))
|
||||
.unwrap_or(true);
|
||||
if !is_macro_callsite {
|
||||
.is_ok_and(|snippet| !snippet.starts_with("#["))
|
||||
{
|
||||
self.lint_buffer.buffer_lint_with_diagnostic(
|
||||
MISSING_ABI,
|
||||
id,
|
||||
@ -1039,7 +1048,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
||||
self.check_defaultness(fi.span, *defaultness);
|
||||
self.check_foreign_kind_bodyless(fi.ident, "type", ty.as_ref().map(|b| b.span));
|
||||
self.check_type_no_bounds(bounds, "`extern` blocks");
|
||||
self.check_foreign_ty_genericless(generics, where_clauses.0.1);
|
||||
self.check_foreign_ty_genericless(generics, &where_clauses.0, &where_clauses.1);
|
||||
self.check_foreign_item_ascii_only(fi.ident);
|
||||
}
|
||||
ForeignItemKind::Static(_, _, body) => {
|
||||
|
@ -77,13 +77,6 @@ pub struct ForbiddenLifetimeBound {
|
||||
pub spans: Vec<Span>,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_passes_forbidden_non_lifetime_param)]
|
||||
pub struct ForbiddenNonLifetimeParam {
|
||||
#[primary_span]
|
||||
pub spans: Vec<Span>,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_passes_fn_param_too_many)]
|
||||
pub struct FnParamTooMany {
|
||||
|
@ -2,7 +2,6 @@ use rustc_ast as ast;
|
||||
use rustc_ast::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor};
|
||||
use rustc_ast::{attr, AssocConstraint, AssocConstraintKind, NodeId};
|
||||
use rustc_ast::{PatKind, RangeEnd};
|
||||
use rustc_errors::{Applicability, StashKey};
|
||||
use rustc_feature::{AttributeGate, BuiltinAttribute, Features, GateIssue, BUILTIN_ATTRIBUTE_MAP};
|
||||
use rustc_session::parse::{feature_err, feature_err_issue, feature_warn};
|
||||
use rustc_session::Session;
|
||||
@ -374,55 +373,8 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_stmt(&mut self, stmt: &'a ast::Stmt) {
|
||||
if let ast::StmtKind::Semi(expr) = &stmt.kind
|
||||
&& let ast::ExprKind::Assign(lhs, _, _) = &expr.kind
|
||||
&& let ast::ExprKind::Type(..) = lhs.kind
|
||||
&& self.sess.parse_sess.span_diagnostic.err_count() == 0
|
||||
&& !self.features.type_ascription
|
||||
&& !lhs.span.allows_unstable(sym::type_ascription)
|
||||
{
|
||||
// When we encounter a statement of the form `foo: Ty = val;`, this will emit a type
|
||||
// ascription error, but the likely intention was to write a `let` statement. (#78907).
|
||||
feature_err(
|
||||
&self.sess.parse_sess,
|
||||
sym::type_ascription,
|
||||
lhs.span,
|
||||
"type ascription is experimental",
|
||||
).span_suggestion_verbose(
|
||||
lhs.span.shrink_to_lo(),
|
||||
"you might have meant to introduce a new binding",
|
||||
"let ",
|
||||
Applicability::MachineApplicable,
|
||||
).emit();
|
||||
}
|
||||
visit::walk_stmt(self, stmt);
|
||||
}
|
||||
|
||||
fn visit_expr(&mut self, e: &'a ast::Expr) {
|
||||
match e.kind {
|
||||
ast::ExprKind::Type(..) => {
|
||||
if self.sess.parse_sess.span_diagnostic.err_count() == 0 {
|
||||
// To avoid noise about type ascription in common syntax errors,
|
||||
// only emit if it is the *only* error.
|
||||
gate_feature_post!(
|
||||
&self,
|
||||
type_ascription,
|
||||
e.span,
|
||||
"type ascription is experimental"
|
||||
);
|
||||
} else {
|
||||
// And if it isn't, cancel the early-pass warning.
|
||||
if let Some(err) = self
|
||||
.sess
|
||||
.parse_sess
|
||||
.span_diagnostic
|
||||
.steal_diagnostic(e.span, StashKey::EarlySyntaxWarning)
|
||||
{
|
||||
err.cancel()
|
||||
}
|
||||
}
|
||||
}
|
||||
ast::ExprKind::TryBlock(_) => {
|
||||
gate_feature_post!(&self, try_blocks, e.span, "`try` expression is experimental");
|
||||
}
|
||||
@ -603,6 +555,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session) {
|
||||
gate_all!(dyn_star, "`dyn*` trait objects are experimental");
|
||||
gate_all!(const_closures, "const closures are experimental");
|
||||
gate_all!(builtin_syntax, "`builtin #` syntax is unstable");
|
||||
gate_all!(explicit_tail_calls, "`become` expression is experimental");
|
||||
|
||||
if !visitor.features.negative_bounds {
|
||||
for &span in spans.get(&sym::negative_bounds).iter().copied().flatten() {
|
||||
@ -629,7 +582,6 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session) {
|
||||
gate_all!(box_patterns, "box pattern syntax is experimental");
|
||||
gate_all!(exclusive_range_pattern, "exclusive range pattern syntax is experimental");
|
||||
gate_all!(try_blocks, "`try` blocks are unstable");
|
||||
gate_all!(type_ascription, "type ascription is experimental");
|
||||
|
||||
visit::walk_crate(&mut visitor, krate);
|
||||
}
|
||||
|
@ -32,6 +32,10 @@ pub fn bounds_to_string(bounds: &[ast::GenericBound]) -> String {
|
||||
State::new().bounds_to_string(bounds)
|
||||
}
|
||||
|
||||
pub fn where_bound_predicate_to_string(where_bound_predicate: &ast::WhereBoundPredicate) -> String {
|
||||
State::new().where_bound_predicate_to_string(where_bound_predicate)
|
||||
}
|
||||
|
||||
pub fn pat_to_string(pat: &ast::Pat) -> String {
|
||||
State::new().pat_to_string(pat)
|
||||
}
|
||||
|
@ -824,6 +824,13 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
|
||||
Self::to_string(|s| s.print_type_bounds(bounds))
|
||||
}
|
||||
|
||||
fn where_bound_predicate_to_string(
|
||||
&self,
|
||||
where_bound_predicate: &ast::WhereBoundPredicate,
|
||||
) -> String {
|
||||
Self::to_string(|s| s.print_where_bound_predicate(where_bound_predicate))
|
||||
}
|
||||
|
||||
fn pat_to_string(&self, pat: &ast::Pat) -> String {
|
||||
Self::to_string(|s| s.print_pat(pat))
|
||||
}
|
||||
|
@ -537,6 +537,11 @@ impl<'a> State<'a> {
|
||||
self.print_expr_maybe_paren(expr, parser::PREC_JUMP);
|
||||
}
|
||||
}
|
||||
ast::ExprKind::Become(result) => {
|
||||
self.word("become");
|
||||
self.word(" ");
|
||||
self.print_expr_maybe_paren(result, parser::PREC_JUMP);
|
||||
}
|
||||
ast::ExprKind::InlineAsm(a) => {
|
||||
// FIXME: This should have its own syntax, distinct from a macro invocation.
|
||||
self.word("asm!");
|
||||
|
@ -623,19 +623,8 @@ impl<'a> State<'a> {
|
||||
|
||||
pub fn print_where_predicate(&mut self, predicate: &ast::WherePredicate) {
|
||||
match predicate {
|
||||
ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate {
|
||||
bound_generic_params,
|
||||
bounded_ty,
|
||||
bounds,
|
||||
..
|
||||
}) => {
|
||||
self.print_formal_generic_params(bound_generic_params);
|
||||
self.print_type(bounded_ty);
|
||||
self.word(":");
|
||||
if !bounds.is_empty() {
|
||||
self.nbsp();
|
||||
self.print_type_bounds(bounds);
|
||||
}
|
||||
ast::WherePredicate::BoundPredicate(where_bound_predicate) => {
|
||||
self.print_where_bound_predicate(where_bound_predicate);
|
||||
}
|
||||
ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate {
|
||||
lifetime,
|
||||
@ -658,6 +647,19 @@ impl<'a> State<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn print_where_bound_predicate(
|
||||
&mut self,
|
||||
where_bound_predicate: &ast::WhereBoundPredicate,
|
||||
) {
|
||||
self.print_formal_generic_params(&where_bound_predicate.bound_generic_params);
|
||||
self.print_type(&where_bound_predicate.bounded_ty);
|
||||
self.word(":");
|
||||
if !where_bound_predicate.bounds.is_empty() {
|
||||
self.nbsp();
|
||||
self.print_type_bounds(&where_bound_predicate.bounds);
|
||||
}
|
||||
}
|
||||
|
||||
fn print_use_tree(&mut self, tree: &ast::UseTree) {
|
||||
match &tree.kind {
|
||||
ast::UseTreeKind::Simple(rename) => {
|
||||
|
@ -72,8 +72,11 @@ impl<'tcx> fmt::Display for BorrowData<'tcx> {
|
||||
let kind = match self.kind {
|
||||
mir::BorrowKind::Shared => "",
|
||||
mir::BorrowKind::Shallow => "shallow ",
|
||||
mir::BorrowKind::Unique => "uniq ",
|
||||
mir::BorrowKind::Mut { .. } => "mut ",
|
||||
mir::BorrowKind::Mut { kind: mir::MutBorrowKind::ClosureCapture } => "uniq ",
|
||||
// FIXME: differentiate `TwoPhaseBorrow`
|
||||
mir::BorrowKind::Mut {
|
||||
kind: mir::MutBorrowKind::Default | mir::MutBorrowKind::TwoPhaseBorrow,
|
||||
} => "mut ",
|
||||
};
|
||||
write!(w, "&{:?} {}{:?}", self.region, kind, self.borrowed_place)
|
||||
}
|
||||
|
@ -278,7 +278,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
|
||||
move_from_span: Span,
|
||||
move_from_desc: &str,
|
||||
) -> DiagnosticBuilder<'cx, ErrorGuaranteed> {
|
||||
struct_span_err!(self, move_from_span, E0507, "cannot move out of {}", move_from_desc,)
|
||||
struct_span_err!(self, move_from_span, E0507, "cannot move out of {}", move_from_desc)
|
||||
}
|
||||
|
||||
/// Signal an error due to an attempt to move out of the interior
|
||||
|
@ -4,8 +4,8 @@ use rustc_infer::infer::InferCtxt;
|
||||
use rustc_middle::mir::visit::TyContext;
|
||||
use rustc_middle::mir::visit::Visitor;
|
||||
use rustc_middle::mir::{
|
||||
BasicBlock, BasicBlockData, Body, Local, Location, Place, PlaceRef, ProjectionElem, Rvalue,
|
||||
SourceInfo, Statement, StatementKind, Terminator, TerminatorKind, UserTypeProjection,
|
||||
Body, Local, Location, Place, PlaceRef, ProjectionElem, Rvalue, SourceInfo, Statement,
|
||||
StatementKind, Terminator, TerminatorKind, UserTypeProjection,
|
||||
};
|
||||
use rustc_middle::ty::subst::SubstsRef;
|
||||
use rustc_middle::ty::visit::TypeVisitable;
|
||||
@ -49,10 +49,6 @@ struct ConstraintGeneration<'cg, 'tcx> {
|
||||
}
|
||||
|
||||
impl<'cg, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'tcx> {
|
||||
fn visit_basic_block_data(&mut self, bb: BasicBlock, data: &BasicBlockData<'tcx>) {
|
||||
self.super_basic_block_data(bb, data);
|
||||
}
|
||||
|
||||
/// We sometimes have `substs` within an rvalue, or within a
|
||||
/// call. Make them live at the location where they appear.
|
||||
fn visit_substs(&mut self, substs: &SubstsRef<'tcx>, location: Location) {
|
||||
|
@ -59,7 +59,7 @@ macro_rules! impl_visitable {
|
||||
}
|
||||
|
||||
fn reconstruct_before_statement_effect(
|
||||
&self,
|
||||
&mut self,
|
||||
state: &mut Self::FlowState,
|
||||
stmt: &mir::Statement<'tcx>,
|
||||
loc: Location,
|
||||
@ -69,7 +69,7 @@ macro_rules! impl_visitable {
|
||||
}
|
||||
|
||||
fn reconstruct_statement_effect(
|
||||
&self,
|
||||
&mut self,
|
||||
state: &mut Self::FlowState,
|
||||
stmt: &mir::Statement<'tcx>,
|
||||
loc: Location,
|
||||
@ -79,7 +79,7 @@ macro_rules! impl_visitable {
|
||||
}
|
||||
|
||||
fn reconstruct_before_terminator_effect(
|
||||
&self,
|
||||
&mut self,
|
||||
state: &mut Self::FlowState,
|
||||
term: &mir::Terminator<'tcx>,
|
||||
loc: Location,
|
||||
@ -89,7 +89,7 @@ macro_rules! impl_visitable {
|
||||
}
|
||||
|
||||
fn reconstruct_terminator_effect(
|
||||
&self,
|
||||
&mut self,
|
||||
state: &mut Self::FlowState,
|
||||
term: &mir::Terminator<'tcx>,
|
||||
loc: Location,
|
||||
@ -125,15 +125,9 @@ pub struct Borrows<'a, 'tcx> {
|
||||
borrows_out_of_scope_at_location: FxIndexMap<Location, Vec<BorrowIndex>>,
|
||||
}
|
||||
|
||||
struct StackEntry {
|
||||
bb: mir::BasicBlock,
|
||||
lo: usize,
|
||||
hi: usize,
|
||||
}
|
||||
|
||||
struct OutOfScopePrecomputer<'a, 'tcx> {
|
||||
visited: BitSet<mir::BasicBlock>,
|
||||
visit_stack: Vec<StackEntry>,
|
||||
visit_stack: Vec<mir::BasicBlock>,
|
||||
body: &'a Body<'tcx>,
|
||||
regioncx: &'a RegionInferenceContext<'tcx>,
|
||||
borrows_out_of_scope_at_location: FxIndexMap<Location, Vec<BorrowIndex>>,
|
||||
@ -158,29 +152,50 @@ impl<'tcx> OutOfScopePrecomputer<'_, 'tcx> {
|
||||
borrow_region: RegionVid,
|
||||
first_location: Location,
|
||||
) {
|
||||
// We visit one BB at a time. The complication is that we may start in the
|
||||
// middle of the first BB visited (the one containing `first_location`), in which
|
||||
// case we may have to later on process the first part of that BB if there
|
||||
// is a path back to its start.
|
||||
|
||||
// For visited BBs, we record the index of the first statement processed.
|
||||
// (In fully processed BBs this index is 0.) Note also that we add BBs to
|
||||
// `visited` once they are added to `stack`, before they are actually
|
||||
// processed, because this avoids the need to look them up again on
|
||||
// completion.
|
||||
self.visited.insert(first_location.block);
|
||||
|
||||
let first_block = first_location.block;
|
||||
let mut first_lo = first_location.statement_index;
|
||||
let first_hi = self.body[first_block].statements.len();
|
||||
let first_bb_data = &self.body.basic_blocks[first_block];
|
||||
|
||||
self.visit_stack.push(StackEntry { bb: first_block, lo: first_lo, hi: first_hi });
|
||||
// This is the first block, we only want to visit it from the creation of the borrow at
|
||||
// `first_location`.
|
||||
let first_lo = first_location.statement_index;
|
||||
let first_hi = first_bb_data.statements.len();
|
||||
|
||||
'preorder: while let Some(StackEntry { bb, lo, hi }) = self.visit_stack.pop() {
|
||||
if let Some(kill_stmt) = self.regioncx.first_non_contained_inclusive(
|
||||
borrow_region,
|
||||
first_block,
|
||||
first_lo,
|
||||
first_hi,
|
||||
) {
|
||||
let kill_location = Location { block: first_block, statement_index: kill_stmt };
|
||||
// If region does not contain a point at the location, then add to list and skip
|
||||
// successor locations.
|
||||
debug!("borrow {:?} gets killed at {:?}", borrow_index, kill_location);
|
||||
self.borrows_out_of_scope_at_location
|
||||
.entry(kill_location)
|
||||
.or_default()
|
||||
.push(borrow_index);
|
||||
|
||||
// The borrow is already dead, there is no need to visit other blocks.
|
||||
return;
|
||||
}
|
||||
|
||||
// The borrow is not dead. Add successor BBs to the work list, if necessary.
|
||||
for succ_bb in first_bb_data.terminator().successors() {
|
||||
if self.visited.insert(succ_bb) {
|
||||
self.visit_stack.push(succ_bb);
|
||||
}
|
||||
}
|
||||
|
||||
// We may end up visiting `first_block` again. This is not an issue: we know at this point
|
||||
// that it does not kill the borrow in the `first_lo..=first_hi` range, so checking the
|
||||
// `0..first_lo` range and the `0..first_hi` range give the same result.
|
||||
while let Some(block) = self.visit_stack.pop() {
|
||||
let bb_data = &self.body[block];
|
||||
let num_stmts = bb_data.statements.len();
|
||||
if let Some(kill_stmt) =
|
||||
self.regioncx.first_non_contained_inclusive(borrow_region, bb, lo, hi)
|
||||
self.regioncx.first_non_contained_inclusive(borrow_region, block, 0, num_stmts)
|
||||
{
|
||||
let kill_location = Location { block: bb, statement_index: kill_stmt };
|
||||
let kill_location = Location { block, statement_index: kill_stmt };
|
||||
// If region does not contain a point at the location, then add to list and skip
|
||||
// successor locations.
|
||||
debug!("borrow {:?} gets killed at {:?}", borrow_index, kill_location);
|
||||
@ -188,38 +203,15 @@ impl<'tcx> OutOfScopePrecomputer<'_, 'tcx> {
|
||||
.entry(kill_location)
|
||||
.or_default()
|
||||
.push(borrow_index);
|
||||
continue 'preorder;
|
||||
}
|
||||
|
||||
// If we process the first part of the first basic block (i.e. we encounter that block
|
||||
// for the second time), we no longer have to visit its successors again.
|
||||
if bb == first_block && hi != first_hi {
|
||||
// We killed the borrow, so we do not visit this block's successors.
|
||||
continue;
|
||||
}
|
||||
|
||||
// Add successor BBs to the work list, if necessary.
|
||||
let bb_data = &self.body[bb];
|
||||
debug_assert!(hi == bb_data.statements.len());
|
||||
for succ_bb in bb_data.terminator().successors() {
|
||||
if !self.visited.insert(succ_bb) {
|
||||
if succ_bb == first_block && first_lo > 0 {
|
||||
// `succ_bb` has been seen before. If it wasn't
|
||||
// fully processed, add its first part to `stack`
|
||||
// for processing.
|
||||
self.visit_stack.push(StackEntry { bb: succ_bb, lo: 0, hi: first_lo - 1 });
|
||||
|
||||
// And update this entry with 0, to represent the
|
||||
// whole BB being processed.
|
||||
first_lo = 0;
|
||||
}
|
||||
} else {
|
||||
// succ_bb hasn't been seen before. Add it to
|
||||
// `stack` for processing.
|
||||
self.visit_stack.push(StackEntry {
|
||||
bb: succ_bb,
|
||||
lo: 0,
|
||||
hi: self.body[succ_bb].statements.len(),
|
||||
});
|
||||
if self.visited.insert(succ_bb) {
|
||||
self.visit_stack.push(succ_bb);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -343,7 +335,7 @@ impl<'tcx> rustc_mir_dataflow::GenKillAnalysis<'tcx> for Borrows<'_, 'tcx> {
|
||||
type Idx = BorrowIndex;
|
||||
|
||||
fn before_statement_effect(
|
||||
&self,
|
||||
&mut self,
|
||||
trans: &mut impl GenKill<Self::Idx>,
|
||||
_statement: &mir::Statement<'tcx>,
|
||||
location: Location,
|
||||
@ -352,7 +344,7 @@ impl<'tcx> rustc_mir_dataflow::GenKillAnalysis<'tcx> for Borrows<'_, 'tcx> {
|
||||
}
|
||||
|
||||
fn statement_effect(
|
||||
&self,
|
||||
&mut self,
|
||||
trans: &mut impl GenKill<Self::Idx>,
|
||||
stmt: &mir::Statement<'tcx>,
|
||||
location: Location,
|
||||
@ -400,7 +392,7 @@ impl<'tcx> rustc_mir_dataflow::GenKillAnalysis<'tcx> for Borrows<'_, 'tcx> {
|
||||
}
|
||||
|
||||
fn before_terminator_effect(
|
||||
&self,
|
||||
&mut self,
|
||||
trans: &mut impl GenKill<Self::Idx>,
|
||||
_terminator: &mir::Terminator<'tcx>,
|
||||
location: Location,
|
||||
@ -409,7 +401,7 @@ impl<'tcx> rustc_mir_dataflow::GenKillAnalysis<'tcx> for Borrows<'_, 'tcx> {
|
||||
}
|
||||
|
||||
fn terminator_effect(
|
||||
&self,
|
||||
&mut self,
|
||||
trans: &mut impl GenKill<Self::Idx>,
|
||||
terminator: &mir::Terminator<'tcx>,
|
||||
_location: Location,
|
||||
@ -426,7 +418,7 @@ impl<'tcx> rustc_mir_dataflow::GenKillAnalysis<'tcx> for Borrows<'_, 'tcx> {
|
||||
}
|
||||
|
||||
fn call_return_effect(
|
||||
&self,
|
||||
&mut self,
|
||||
_trans: &mut impl GenKill<Self::Idx>,
|
||||
_block: mir::BasicBlock,
|
||||
_return_places: CallReturnPlaces<'_, 'tcx>,
|
||||
|
@ -180,24 +180,25 @@ trait TypeOpInfo<'tcx> {
|
||||
return;
|
||||
};
|
||||
|
||||
let placeholder_region = tcx.mk_re_placeholder(ty::Placeholder {
|
||||
universe: adjusted_universe.into(),
|
||||
bound: placeholder.bound,
|
||||
});
|
||||
let placeholder_region = ty::Region::new_placeholder(
|
||||
tcx,
|
||||
ty::Placeholder { universe: adjusted_universe.into(), bound: placeholder.bound },
|
||||
);
|
||||
|
||||
let error_region =
|
||||
if let RegionElement::PlaceholderRegion(error_placeholder) = error_element {
|
||||
let adjusted_universe =
|
||||
error_placeholder.universe.as_u32().checked_sub(base_universe.as_u32());
|
||||
adjusted_universe.map(|adjusted| {
|
||||
tcx.mk_re_placeholder(ty::Placeholder {
|
||||
universe: adjusted.into(),
|
||||
bound: error_placeholder.bound,
|
||||
})
|
||||
})
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let error_region = if let RegionElement::PlaceholderRegion(error_placeholder) =
|
||||
error_element
|
||||
{
|
||||
let adjusted_universe =
|
||||
error_placeholder.universe.as_u32().checked_sub(base_universe.as_u32());
|
||||
adjusted_universe.map(|adjusted| {
|
||||
ty::Region::new_placeholder(
|
||||
tcx,
|
||||
ty::Placeholder { universe: adjusted.into(), bound: error_placeholder.bound },
|
||||
)
|
||||
})
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
debug!(?placeholder_region);
|
||||
|
||||
@ -390,7 +391,7 @@ fn try_extract_error_from_fulfill_cx<'tcx>(
|
||||
error_region,
|
||||
®ion_constraints,
|
||||
|vid| ocx.infcx.region_var_origin(vid),
|
||||
|vid| ocx.infcx.universe_of_region(ocx.infcx.tcx.mk_re_var(vid)),
|
||||
|vid| ocx.infcx.universe_of_region(ty::Region::new_var(ocx.infcx.tcx, vid)),
|
||||
)
|
||||
}
|
||||
|
||||
@ -411,7 +412,7 @@ fn try_extract_error_from_region_constraints<'tcx>(
|
||||
}
|
||||
// FIXME: Should this check the universe of the var?
|
||||
Constraint::VarSubReg(vid, sup) if sup == placeholder_region => {
|
||||
Some((infcx.tcx.mk_re_var(vid), cause.clone()))
|
||||
Some((ty::Region::new_var(infcx.tcx, vid), cause.clone()))
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
use std::iter;
|
||||
|
||||
use either::Either;
|
||||
use hir::PatField;
|
||||
use rustc_data_structures::captures::Captures;
|
||||
use rustc_data_structures::fx::FxIndexSet;
|
||||
use rustc_errors::{
|
||||
@ -14,9 +13,10 @@ use rustc_infer::traits::ObligationCause;
|
||||
use rustc_middle::hir::nested_filter::OnlyBodies;
|
||||
use rustc_middle::mir::tcx::PlaceTy;
|
||||
use rustc_middle::mir::{
|
||||
self, AggregateKind, BindingForm, BorrowKind, ClearCrossCrate, ConstraintCategory,
|
||||
FakeReadCause, LocalDecl, LocalInfo, LocalKind, Location, Operand, Place, PlaceRef,
|
||||
ProjectionElem, Rvalue, Statement, StatementKind, Terminator, TerminatorKind, VarBindingForm,
|
||||
self, AggregateKind, BindingForm, BorrowKind, CallSource, ClearCrossCrate, ConstraintCategory,
|
||||
FakeReadCause, LocalDecl, LocalInfo, LocalKind, Location, MutBorrowKind, Operand, Place,
|
||||
PlaceRef, ProjectionElem, Rvalue, Statement, StatementKind, Terminator, TerminatorKind,
|
||||
VarBindingForm,
|
||||
};
|
||||
use rustc_middle::ty::{self, suggest_constraining_type_params, PredicateKind, Ty};
|
||||
use rustc_middle::util::CallKind;
|
||||
@ -27,6 +27,7 @@ use rustc_span::symbol::{kw, sym, Ident};
|
||||
use rustc_span::{BytePos, Span, Symbol};
|
||||
use rustc_trait_selection::infer::InferCtxtExt;
|
||||
use rustc_trait_selection::traits::ObligationCtxt;
|
||||
use std::iter;
|
||||
|
||||
use crate::borrow_set::TwoPhaseActivation;
|
||||
use crate::borrowck_errors;
|
||||
@ -677,8 +678,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
let tcx = self.infcx.tcx;
|
||||
|
||||
// Find out if the predicates show that the type is a Fn or FnMut
|
||||
let find_fn_kind_from_did = |(pred, _): (ty::Predicate<'tcx>, _)| {
|
||||
if let ty::PredicateKind::Clause(ty::Clause::Trait(pred)) = pred.kind().skip_binder()
|
||||
let find_fn_kind_from_did = |(pred, _): (ty::Clause<'tcx>, _)| {
|
||||
if let ty::ClauseKind::Trait(pred) = pred.kind().skip_binder()
|
||||
&& pred.self_ty() == ty
|
||||
{
|
||||
if Some(pred.def_id()) == tcx.lang_items().fn_trait() {
|
||||
@ -704,7 +705,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => tcx
|
||||
.explicit_item_bounds(def_id)
|
||||
.subst_iter_copied(tcx, substs)
|
||||
.find_map(find_fn_kind_from_did),
|
||||
.find_map(|(clause, span)| find_fn_kind_from_did((clause, span))),
|
||||
ty::Closure(_, substs) => match substs.as_closure().kind() {
|
||||
ty::ClosureKind::Fn => Some(hir::Mutability::Not),
|
||||
ty::ClosureKind::FnMut => Some(hir::Mutability::Mut),
|
||||
@ -775,7 +776,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
let predicates: Result<Vec<_>, _> = errors
|
||||
.into_iter()
|
||||
.map(|err| match err.obligation.predicate.kind().skip_binder() {
|
||||
PredicateKind::Clause(ty::Clause::Trait(predicate)) => {
|
||||
PredicateKind::Clause(ty::ClauseKind::Trait(predicate)) => {
|
||||
match predicate.self_ty().kind() {
|
||||
ty::Param(param_ty) => Ok((
|
||||
generics.type_param(param_ty, tcx),
|
||||
@ -926,7 +927,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
// FIXME: supply non-"" `opt_via` when appropriate
|
||||
let first_borrow_desc;
|
||||
let mut err = match (gen_borrow_kind, issued_borrow.kind) {
|
||||
(BorrowKind::Shared, BorrowKind::Mut { .. }) => {
|
||||
(
|
||||
BorrowKind::Shared,
|
||||
BorrowKind::Mut { kind: MutBorrowKind::Default | MutBorrowKind::TwoPhaseBorrow },
|
||||
) => {
|
||||
first_borrow_desc = "mutable ";
|
||||
self.cannot_reborrow_already_borrowed(
|
||||
span,
|
||||
@ -940,7 +944,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
None,
|
||||
)
|
||||
}
|
||||
(BorrowKind::Mut { .. }, BorrowKind::Shared) => {
|
||||
(
|
||||
BorrowKind::Mut { kind: MutBorrowKind::Default | MutBorrowKind::TwoPhaseBorrow },
|
||||
BorrowKind::Shared,
|
||||
) => {
|
||||
first_borrow_desc = "immutable ";
|
||||
let mut err = self.cannot_reborrow_already_borrowed(
|
||||
span,
|
||||
@ -962,7 +969,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
err
|
||||
}
|
||||
|
||||
(BorrowKind::Mut { .. }, BorrowKind::Mut { .. }) => {
|
||||
(
|
||||
BorrowKind::Mut { kind: MutBorrowKind::Default | MutBorrowKind::TwoPhaseBorrow },
|
||||
BorrowKind::Mut { kind: MutBorrowKind::Default | MutBorrowKind::TwoPhaseBorrow },
|
||||
) => {
|
||||
first_borrow_desc = "first ";
|
||||
let mut err = self.cannot_mutably_borrow_multiply(
|
||||
span,
|
||||
@ -972,7 +982,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
&msg_borrow,
|
||||
None,
|
||||
);
|
||||
self.suggest_split_at_mut_if_applicable(
|
||||
self.suggest_slice_method_if_applicable(
|
||||
&mut err,
|
||||
place,
|
||||
issued_borrow.borrowed_place,
|
||||
@ -982,15 +992,23 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
issued_borrow.borrowed_place,
|
||||
&issued_spans,
|
||||
);
|
||||
self.explain_iterator_advancement_in_for_loop_if_applicable(
|
||||
&mut err,
|
||||
span,
|
||||
&issued_spans,
|
||||
);
|
||||
err
|
||||
}
|
||||
|
||||
(BorrowKind::Unique, BorrowKind::Unique) => {
|
||||
(
|
||||
BorrowKind::Mut { kind: MutBorrowKind::ClosureCapture },
|
||||
BorrowKind::Mut { kind: MutBorrowKind::ClosureCapture },
|
||||
) => {
|
||||
first_borrow_desc = "first ";
|
||||
self.cannot_uniquely_borrow_by_two_closures(span, &desc_place, issued_span, None)
|
||||
}
|
||||
|
||||
(BorrowKind::Mut { .. } | BorrowKind::Unique, BorrowKind::Shallow) => {
|
||||
(BorrowKind::Mut { .. }, BorrowKind::Shallow) => {
|
||||
if let Some(immutable_section_description) =
|
||||
self.classify_immutable_section(issued_borrow.assigned_place)
|
||||
{
|
||||
@ -1004,7 +1022,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
borrow_spans.var_subdiag(
|
||||
None,
|
||||
&mut err,
|
||||
Some(BorrowKind::Unique),
|
||||
Some(BorrowKind::Mut { kind: MutBorrowKind::ClosureCapture }),
|
||||
|kind, var_span| {
|
||||
use crate::session_diagnostics::CaptureVarCause::*;
|
||||
match kind {
|
||||
@ -1038,7 +1056,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
(BorrowKind::Unique, _) => {
|
||||
(BorrowKind::Mut { kind: MutBorrowKind::ClosureCapture }, _) => {
|
||||
first_borrow_desc = "first ";
|
||||
self.cannot_uniquely_borrow_by_one_closure(
|
||||
span,
|
||||
@ -1052,7 +1070,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
)
|
||||
}
|
||||
|
||||
(BorrowKind::Shared, BorrowKind::Unique) => {
|
||||
(BorrowKind::Shared, BorrowKind::Mut { kind: MutBorrowKind::ClosureCapture }) => {
|
||||
first_borrow_desc = "first ";
|
||||
self.cannot_reborrow_already_uniquely_borrowed(
|
||||
span,
|
||||
@ -1067,7 +1085,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
)
|
||||
}
|
||||
|
||||
(BorrowKind::Mut { .. }, BorrowKind::Unique) => {
|
||||
(BorrowKind::Mut { .. }, BorrowKind::Mut { kind: MutBorrowKind::ClosureCapture }) => {
|
||||
first_borrow_desc = "first ";
|
||||
self.cannot_reborrow_already_uniquely_borrowed(
|
||||
span,
|
||||
@ -1085,10 +1103,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
(BorrowKind::Shared, BorrowKind::Shared | BorrowKind::Shallow)
|
||||
| (
|
||||
BorrowKind::Shallow,
|
||||
BorrowKind::Mut { .. }
|
||||
| BorrowKind::Unique
|
||||
| BorrowKind::Shared
|
||||
| BorrowKind::Shallow,
|
||||
BorrowKind::Mut { .. } | BorrowKind::Shared | BorrowKind::Shallow,
|
||||
) => unreachable!(),
|
||||
};
|
||||
|
||||
@ -1252,7 +1267,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
);
|
||||
}
|
||||
|
||||
fn suggest_split_at_mut_if_applicable(
|
||||
fn suggest_slice_method_if_applicable(
|
||||
&self,
|
||||
err: &mut Diagnostic,
|
||||
place: Place<'tcx>,
|
||||
@ -1264,7 +1279,75 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
err.help(
|
||||
"consider using `.split_at_mut(position)` or similar method to obtain \
|
||||
two mutable non-overlapping sub-slices",
|
||||
);
|
||||
)
|
||||
.help("consider using `.swap(index_1, index_2)` to swap elements at the specified indices");
|
||||
}
|
||||
}
|
||||
|
||||
/// Suggest using `while let` for call `next` on an iterator in a for loop.
|
||||
///
|
||||
/// For example:
|
||||
/// ```ignore (illustrative)
|
||||
///
|
||||
/// for x in iter {
|
||||
/// ...
|
||||
/// iter.next()
|
||||
/// }
|
||||
/// ```
|
||||
pub(crate) fn explain_iterator_advancement_in_for_loop_if_applicable(
|
||||
&self,
|
||||
err: &mut Diagnostic,
|
||||
span: Span,
|
||||
issued_spans: &UseSpans<'tcx>,
|
||||
) {
|
||||
let issue_span = issued_spans.args_or_use();
|
||||
let tcx = self.infcx.tcx;
|
||||
let hir = tcx.hir();
|
||||
|
||||
let Some(body_id) = hir.get(self.mir_hir_id()).body_id() else { return };
|
||||
let typeck_results = tcx.typeck(self.mir_def_id());
|
||||
|
||||
struct ExprFinder<'hir> {
|
||||
issue_span: Span,
|
||||
expr_span: Span,
|
||||
body_expr: Option<&'hir hir::Expr<'hir>>,
|
||||
loop_bind: Option<Symbol>,
|
||||
}
|
||||
impl<'hir> Visitor<'hir> for ExprFinder<'hir> {
|
||||
fn visit_expr(&mut self, ex: &'hir hir::Expr<'hir>) {
|
||||
if let hir::ExprKind::Loop(hir::Block{ stmts: [stmt, ..], ..}, _, hir::LoopSource::ForLoop, _) = ex.kind &&
|
||||
let hir::StmtKind::Expr(hir::Expr{ kind: hir::ExprKind::Match(call, [_, bind, ..], _), ..}) = stmt.kind &&
|
||||
let hir::ExprKind::Call(path, _args) = call.kind &&
|
||||
let hir::ExprKind::Path(hir::QPath::LangItem(LangItem::IteratorNext, _, _, )) = path.kind &&
|
||||
let hir::PatKind::Struct(path, [field, ..], _) = bind.pat.kind &&
|
||||
let hir::QPath::LangItem(LangItem::OptionSome, _, _) = path &&
|
||||
let PatField { pat: hir::Pat{ kind: hir::PatKind::Binding(_, _, ident, ..), .. }, ..} = field &&
|
||||
self.issue_span.source_equal(call.span) {
|
||||
self.loop_bind = Some(ident.name);
|
||||
}
|
||||
|
||||
if let hir::ExprKind::MethodCall(body_call, _recv, ..) = ex.kind &&
|
||||
body_call.ident.name == sym::next && ex.span.source_equal(self.expr_span) {
|
||||
self.body_expr = Some(ex);
|
||||
}
|
||||
|
||||
hir::intravisit::walk_expr(self, ex);
|
||||
}
|
||||
}
|
||||
let mut finder =
|
||||
ExprFinder { expr_span: span, issue_span, loop_bind: None, body_expr: None };
|
||||
finder.visit_expr(hir.body(body_id).value);
|
||||
|
||||
if let Some(loop_bind) = finder.loop_bind &&
|
||||
let Some(body_expr) = finder.body_expr &&
|
||||
let Some(def_id) = typeck_results.type_dependent_def_id(body_expr.hir_id) &&
|
||||
let Some(trait_did) = tcx.trait_of_item(def_id) &&
|
||||
tcx.is_diagnostic_item(sym::Iterator, trait_did) {
|
||||
err.note(format!(
|
||||
"a for loop advances the iterator for you, the result is stored in `{}`.",
|
||||
loop_bind
|
||||
));
|
||||
err.help("if you want to call `next` on a iterator within the loop, consider using `while let`.");
|
||||
}
|
||||
}
|
||||
|
||||
@ -1720,18 +1803,19 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
(
|
||||
Some(name),
|
||||
BorrowExplanation::UsedLater(LaterUseKind::ClosureCapture, var_or_use_span, _),
|
||||
) => self.report_escaping_closure_capture(
|
||||
borrow_spans,
|
||||
borrow_span,
|
||||
&RegionName {
|
||||
name: self.synthesize_region_name(),
|
||||
source: RegionNameSource::Static,
|
||||
},
|
||||
ConstraintCategory::CallArgument(None),
|
||||
var_or_use_span,
|
||||
&format!("`{}`", name),
|
||||
"block",
|
||||
),
|
||||
) if borrow_spans.for_generator() || borrow_spans.for_closure() => self
|
||||
.report_escaping_closure_capture(
|
||||
borrow_spans,
|
||||
borrow_span,
|
||||
&RegionName {
|
||||
name: self.synthesize_region_name(),
|
||||
source: RegionNameSource::Static,
|
||||
},
|
||||
ConstraintCategory::CallArgument(None),
|
||||
var_or_use_span,
|
||||
&format!("`{}`", name),
|
||||
"block",
|
||||
),
|
||||
(
|
||||
Some(name),
|
||||
BorrowExplanation::MustBeValidFor {
|
||||
@ -1744,7 +1828,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
span,
|
||||
..
|
||||
},
|
||||
) if borrow_spans.for_generator() | borrow_spans.for_closure() => self
|
||||
) if borrow_spans.for_generator() || borrow_spans.for_closure() => self
|
||||
.report_escaping_closure_capture(
|
||||
borrow_spans,
|
||||
borrow_span,
|
||||
@ -2579,7 +2663,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
fn explain_deref_coercion(&mut self, loan: &BorrowData<'tcx>, err: &mut Diagnostic) {
|
||||
let tcx = self.infcx.tcx;
|
||||
if let (
|
||||
Some(Terminator { kind: TerminatorKind::Call { from_hir_call: false, .. }, .. }),
|
||||
Some(Terminator {
|
||||
kind: TerminatorKind::Call { call_source: CallSource::OverloadedOperator, .. },
|
||||
..
|
||||
}),
|
||||
Some((method_did, method_substs)),
|
||||
) = (
|
||||
&self.body[loan.reserve_location.block].terminator,
|
||||
|
@ -6,10 +6,10 @@ use rustc_hir::intravisit::Visitor;
|
||||
use rustc_index::IndexSlice;
|
||||
use rustc_infer::infer::NllRegionVariableOrigin;
|
||||
use rustc_middle::mir::{
|
||||
Body, CastKind, ConstraintCategory, FakeReadCause, Local, LocalInfo, Location, Operand, Place,
|
||||
Rvalue, Statement, StatementKind, TerminatorKind,
|
||||
Body, CallSource, CastKind, ConstraintCategory, FakeReadCause, Local, LocalInfo, Location,
|
||||
Operand, Place, Rvalue, Statement, StatementKind, TerminatorKind,
|
||||
};
|
||||
use rustc_middle::ty::adjustment::PointerCast;
|
||||
use rustc_middle::ty::adjustment::PointerCoercion;
|
||||
use rustc_middle::ty::{self, RegionVid, TyCtxt};
|
||||
use rustc_span::symbol::{kw, Symbol};
|
||||
use rustc_span::{sym, DesugaringKind, Span};
|
||||
@ -494,7 +494,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
} else if self.was_captured_by_trait_object(borrow) {
|
||||
LaterUseKind::TraitCapture
|
||||
} else if location.statement_index == block.statements.len() {
|
||||
if let TerminatorKind::Call { func, from_hir_call: true, .. } =
|
||||
if let TerminatorKind::Call { func, call_source: CallSource::Normal, .. } =
|
||||
&block.terminator().kind
|
||||
{
|
||||
// Just point to the function, to reduce the chance of overlapping spans.
|
||||
@ -584,7 +584,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
},
|
||||
// If we see an unsized cast, then if it is our data we should check
|
||||
// whether it is being cast to a trait object.
|
||||
Rvalue::Cast(CastKind::Pointer(PointerCast::Unsize), operand, ty) => {
|
||||
Rvalue::Cast(
|
||||
CastKind::PointerCoercion(PointerCoercion::Unsize),
|
||||
operand,
|
||||
ty,
|
||||
) => {
|
||||
match operand {
|
||||
Operand::Copy(place) | Operand::Move(place) => {
|
||||
if let Some(from) = place.as_local() {
|
||||
|
@ -13,8 +13,9 @@ use rustc_index::IndexSlice;
|
||||
use rustc_infer::infer::LateBoundRegionConversionTime;
|
||||
use rustc_middle::mir::tcx::PlaceTy;
|
||||
use rustc_middle::mir::{
|
||||
AggregateKind, Constant, FakeReadCause, Local, LocalInfo, LocalKind, Location, Operand, Place,
|
||||
PlaceRef, ProjectionElem, Rvalue, Statement, StatementKind, Terminator, TerminatorKind,
|
||||
AggregateKind, CallSource, Constant, FakeReadCause, Local, LocalInfo, LocalKind, Location,
|
||||
Operand, Place, PlaceRef, ProjectionElem, Rvalue, Statement, StatementKind, Terminator,
|
||||
TerminatorKind,
|
||||
};
|
||||
use rustc_middle::ty::print::Print;
|
||||
use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
|
||||
@ -414,7 +415,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
if !is_terminator {
|
||||
continue;
|
||||
} else if let Some(Terminator {
|
||||
kind: TerminatorKind::Call { func, from_hir_call: false, .. },
|
||||
kind:
|
||||
TerminatorKind::Call {
|
||||
func,
|
||||
call_source: CallSource::OverloadedOperator,
|
||||
..
|
||||
},
|
||||
..
|
||||
}) = &bbd.terminator
|
||||
{
|
||||
@ -622,8 +628,7 @@ impl UseSpans<'_> {
|
||||
err.subdiagnostic(match kind {
|
||||
Some(kd) => match kd {
|
||||
rustc_middle::mir::BorrowKind::Shared
|
||||
| rustc_middle::mir::BorrowKind::Shallow
|
||||
| rustc_middle::mir::BorrowKind::Unique => {
|
||||
| rustc_middle::mir::BorrowKind::Shallow => {
|
||||
CaptureVarKind::Immut { kind_span: capture_kind_span }
|
||||
}
|
||||
|
||||
@ -839,7 +844,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
debug!("move_spans: target_temp = {:?}", target_temp);
|
||||
|
||||
if let Some(Terminator {
|
||||
kind: TerminatorKind::Call { fn_span, from_hir_call, .. }, ..
|
||||
kind: TerminatorKind::Call { fn_span, call_source, .. }, ..
|
||||
}) = &self.body[location.block].terminator
|
||||
{
|
||||
let Some((method_did, method_substs)) =
|
||||
@ -859,7 +864,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
method_did,
|
||||
method_substs,
|
||||
*fn_span,
|
||||
*from_hir_call,
|
||||
call_source.from_hir_call(),
|
||||
Some(self.infcx.tcx.fn_arg_names(method_did)[0]),
|
||||
);
|
||||
|
||||
@ -1045,7 +1050,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
Some(def_id) => type_known_to_meet_bound_modulo_regions(
|
||||
&self.infcx,
|
||||
self.param_env,
|
||||
tcx.mk_imm_ref(tcx.lifetimes.re_erased, ty),
|
||||
Ty::new_imm_ref(tcx, tcx.lifetimes.re_erased, ty),
|
||||
def_id,
|
||||
),
|
||||
_ => false,
|
||||
@ -1141,6 +1146,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
// Avoid pointing to the same function in multiple different
|
||||
// error messages.
|
||||
if span != DUMMY_SP && self.fn_self_span_reported.insert(self_arg.span) {
|
||||
self.explain_iterator_advancement_in_for_loop_if_applicable(
|
||||
err,
|
||||
span,
|
||||
&move_spans,
|
||||
);
|
||||
|
||||
let func = tcx.def_path_str(method_did);
|
||||
err.subdiagnostic(CaptureReasonNote::FuncTakeSelf {
|
||||
func,
|
||||
|
@ -123,13 +123,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||
item_msg = access_place_desc;
|
||||
debug_assert!(self.body.local_decls[ty::CAPTURE_STRUCT_LOCAL].ty.is_ref());
|
||||
debug_assert!(is_closure_or_generator(
|
||||
Place::ty_from(
|
||||
the_place_err.local,
|
||||
the_place_err.projection,
|
||||
self.body,
|
||||
self.infcx.tcx
|
||||
)
|
||||
.ty
|
||||
the_place_err.ty(self.body, self.infcx.tcx).ty
|
||||
));
|
||||
|
||||
reason = if self.is_upvar_field_projection(access_place.as_ref()).is_some() {
|
||||
@ -234,7 +228,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||
borrow_spans.var_subdiag(
|
||||
None,
|
||||
&mut err,
|
||||
Some(mir::BorrowKind::Mut { allow_two_phase_borrow: false }),
|
||||
Some(mir::BorrowKind::Mut { kind: mir::MutBorrowKind::Default }),
|
||||
|_kind, var_span| {
|
||||
let place = self.describe_any_place(access_place.as_ref());
|
||||
crate::session_diagnostics::CaptureVarCause::MutableBorrowUsePlaceClosure {
|
||||
@ -300,7 +294,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||
_,
|
||||
mir::Rvalue::Ref(
|
||||
_,
|
||||
mir::BorrowKind::Mut { allow_two_phase_borrow: false },
|
||||
mir::BorrowKind::Mut { kind: mir::MutBorrowKind::Default },
|
||||
_,
|
||||
),
|
||||
)),
|
||||
@ -416,12 +410,28 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||
_,
|
||||
) = pat.kind
|
||||
{
|
||||
err.span_suggestion(
|
||||
upvar_ident.span,
|
||||
"consider changing this to be mutable",
|
||||
format!("mut {}", upvar_ident.name),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
if upvar_ident.name == kw::SelfLower {
|
||||
for (_, node) in self.infcx.tcx.hir().parent_iter(upvar_hir_id) {
|
||||
if let Some(fn_decl) = node.fn_decl() {
|
||||
if !matches!(fn_decl.implicit_self, hir::ImplicitSelfKind::ImmRef | hir::ImplicitSelfKind::MutRef) {
|
||||
err.span_suggestion(
|
||||
upvar_ident.span,
|
||||
"consider changing this to be mutable",
|
||||
format!("mut {}", upvar_ident.name),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
err.span_suggestion(
|
||||
upvar_ident.span,
|
||||
"consider changing this to be mutable",
|
||||
format!("mut {}", upvar_ident.name),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
let tcx = self.infcx.tcx;
|
||||
|
@ -508,7 +508,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||
let generic_arg = substs[param_index as usize];
|
||||
let identity_substs =
|
||||
InternalSubsts::identity_for_item(self.infcx.tcx, adt.did());
|
||||
let base_ty = self.infcx.tcx.mk_adt(*adt, identity_substs);
|
||||
let base_ty = Ty::new_adt(self.infcx.tcx, *adt, identity_substs);
|
||||
let base_generic_arg = identity_substs[param_index as usize];
|
||||
let adt_desc = adt.descr();
|
||||
|
||||
|
@ -928,7 +928,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
|
||||
|
||||
fn any_param_predicate_mentions(
|
||||
&self,
|
||||
predicates: &[ty::Predicate<'tcx>],
|
||||
clauses: &[ty::Clause<'tcx>],
|
||||
ty: Ty<'tcx>,
|
||||
region: ty::EarlyBoundRegion,
|
||||
) -> bool {
|
||||
@ -937,10 +937,10 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
|
||||
if let ty::GenericArgKind::Type(ty) = arg.unpack()
|
||||
&& let ty::Param(_) = ty.kind()
|
||||
{
|
||||
predicates.iter().any(|pred| {
|
||||
clauses.iter().any(|pred| {
|
||||
match pred.kind().skip_binder() {
|
||||
ty::PredicateKind::Clause(ty::Clause::Trait(data)) if data.self_ty() == ty => {}
|
||||
ty::PredicateKind::Clause(ty::Clause::Projection(data)) if data.projection_ty.self_ty() == ty => {}
|
||||
ty::ClauseKind::Trait(data) if data.self_ty() == ty => {}
|
||||
ty::ClauseKind::Projection(data) if data.projection_ty.self_ty() == ty => {}
|
||||
_ => return false,
|
||||
}
|
||||
tcx.any_free_region_meets(pred, |r| {
|
||||
|
@ -128,7 +128,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> {
|
||||
destination,
|
||||
target: _,
|
||||
unwind: _,
|
||||
from_hir_call: _,
|
||||
call_source: _,
|
||||
fn_span: _,
|
||||
} => {
|
||||
self.consume_operand(location, func);
|
||||
@ -255,7 +255,7 @@ impl<'cx, 'tcx> InvalidationGenerator<'cx, 'tcx> {
|
||||
(Shallow(Some(ArtificialField::ShallowBorrow)), Read(ReadKind::Borrow(bk)))
|
||||
}
|
||||
BorrowKind::Shared => (Deep, Read(ReadKind::Borrow(bk))),
|
||||
BorrowKind::Unique | BorrowKind::Mut { .. } => {
|
||||
BorrowKind::Mut { .. } => {
|
||||
let wk = WriteKind::MutableBorrow(bk);
|
||||
if allow_two_phase_borrow(bk) {
|
||||
(Deep, Reservation(wk))
|
||||
@ -273,7 +273,7 @@ impl<'cx, 'tcx> InvalidationGenerator<'cx, 'tcx> {
|
||||
Mutability::Mut => (
|
||||
Deep,
|
||||
Write(WriteKind::MutableBorrow(BorrowKind::Mut {
|
||||
allow_two_phase_borrow: false,
|
||||
kind: mir::MutBorrowKind::Default,
|
||||
})),
|
||||
),
|
||||
Mutability::Not => (Deep, Read(ReadKind::Borrow(BorrowKind::Shared))),
|
||||
@ -376,14 +376,11 @@ impl<'cx, 'tcx> InvalidationGenerator<'cx, 'tcx> {
|
||||
}
|
||||
|
||||
(Read(_), BorrowKind::Shallow | BorrowKind::Shared)
|
||||
| (
|
||||
Read(ReadKind::Borrow(BorrowKind::Shallow)),
|
||||
BorrowKind::Unique | BorrowKind::Mut { .. },
|
||||
) => {
|
||||
| (Read(ReadKind::Borrow(BorrowKind::Shallow)), BorrowKind::Mut { .. }) => {
|
||||
// Reads don't invalidate shared or shallow borrows
|
||||
}
|
||||
|
||||
(Read(_), BorrowKind::Unique | BorrowKind::Mut { .. }) => {
|
||||
(Read(_), BorrowKind::Mut { .. }) => {
|
||||
// Reading from mere reservations of mutable-borrows is OK.
|
||||
if !is_active(&this.dominators, borrow, location) {
|
||||
// If the borrow isn't active yet, reads don't invalidate it
|
||||
@ -425,7 +422,7 @@ impl<'cx, 'tcx> InvalidationGenerator<'cx, 'tcx> {
|
||||
// only mutable borrows should be 2-phase
|
||||
assert!(match borrow.kind {
|
||||
BorrowKind::Shared | BorrowKind::Shallow => false,
|
||||
BorrowKind::Unique | BorrowKind::Mut { .. } => true,
|
||||
BorrowKind::Mut { .. } => true,
|
||||
});
|
||||
|
||||
self.access_place(
|
||||
|
@ -29,8 +29,8 @@ use rustc_infer::infer::{
|
||||
InferCtxt, NllRegionVariableOrigin, RegionVariableOrigin, TyCtxtInferExt,
|
||||
};
|
||||
use rustc_middle::mir::{
|
||||
traversal, Body, ClearCrossCrate, Local, Location, Mutability, NonDivergingIntrinsic, Operand,
|
||||
Place, PlaceElem, PlaceRef, VarDebugInfoContents,
|
||||
traversal, Body, ClearCrossCrate, Local, Location, MutBorrowKind, Mutability,
|
||||
NonDivergingIntrinsic, Operand, Place, PlaceElem, PlaceRef, VarDebugInfoContents,
|
||||
};
|
||||
use rustc_middle::mir::{AggregateKind, BasicBlock, BorrowCheckResult, BorrowKind};
|
||||
use rustc_middle::mir::{InlineAsmOperand, Terminator, TerminatorKind};
|
||||
@ -222,7 +222,7 @@ fn do_mir_borrowck<'tcx>(
|
||||
|
||||
let (move_data, move_errors): (MoveData<'tcx>, Vec<(Place<'tcx>, MoveError<'tcx>)>) =
|
||||
match MoveData::gather_moves(&body, tcx, param_env) {
|
||||
Ok((_, move_data)) => (move_data, Vec::new()),
|
||||
Ok(move_data) => (move_data, Vec::new()),
|
||||
Err((move_data, move_errors)) => (move_data, move_errors),
|
||||
};
|
||||
let promoted_errors = promoted
|
||||
@ -368,7 +368,7 @@ fn do_mir_borrowck<'tcx>(
|
||||
// Compute and report region errors, if any.
|
||||
mbcx.report_region_errors(nll_errors);
|
||||
|
||||
let results = BorrowckResults {
|
||||
let mut results = BorrowckResults {
|
||||
ever_inits: flow_ever_inits,
|
||||
uninits: flow_uninits,
|
||||
borrows: flow_borrows,
|
||||
@ -379,7 +379,7 @@ fn do_mir_borrowck<'tcx>(
|
||||
rustc_mir_dataflow::visit_results(
|
||||
body,
|
||||
traversal::reverse_postorder(body).map(|(bb, _)| bb),
|
||||
&results,
|
||||
&mut results,
|
||||
&mut mbcx,
|
||||
);
|
||||
|
||||
@ -598,11 +598,12 @@ struct MirBorrowckCtxt<'cx, 'tcx> {
|
||||
// 2. loans made in overlapping scopes do not conflict
|
||||
// 3. assignments do not affect things loaned out as immutable
|
||||
// 4. moves do not affect things loaned out in any way
|
||||
impl<'cx, 'tcx> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtxt<'cx, 'tcx> {
|
||||
impl<'cx, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx, R> for MirBorrowckCtxt<'cx, 'tcx> {
|
||||
type FlowState = Flows<'cx, 'tcx>;
|
||||
|
||||
fn visit_statement_before_primary_effect(
|
||||
&mut self,
|
||||
_results: &R,
|
||||
flow_state: &Flows<'cx, 'tcx>,
|
||||
stmt: &'cx Statement<'tcx>,
|
||||
location: Location,
|
||||
@ -672,6 +673,7 @@ impl<'cx, 'tcx> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtx
|
||||
|
||||
fn visit_terminator_before_primary_effect(
|
||||
&mut self,
|
||||
_results: &R,
|
||||
flow_state: &Flows<'cx, 'tcx>,
|
||||
term: &'cx Terminator<'tcx>,
|
||||
loc: Location,
|
||||
@ -708,7 +710,7 @@ impl<'cx, 'tcx> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtx
|
||||
destination,
|
||||
target: _,
|
||||
unwind: _,
|
||||
from_hir_call: _,
|
||||
call_source: _,
|
||||
fn_span: _,
|
||||
} => {
|
||||
self.consume_operand(loc, (func, span), flow_state);
|
||||
@ -782,6 +784,7 @@ impl<'cx, 'tcx> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtx
|
||||
|
||||
fn visit_terminator_after_primary_effect(
|
||||
&mut self,
|
||||
_results: &R,
|
||||
flow_state: &Flows<'cx, 'tcx>,
|
||||
term: &'cx Terminator<'tcx>,
|
||||
loc: Location,
|
||||
@ -1068,10 +1071,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
}
|
||||
|
||||
(Read(_), BorrowKind::Shared | BorrowKind::Shallow)
|
||||
| (
|
||||
Read(ReadKind::Borrow(BorrowKind::Shallow)),
|
||||
BorrowKind::Unique | BorrowKind::Mut { .. },
|
||||
) => Control::Continue,
|
||||
| (Read(ReadKind::Borrow(BorrowKind::Shallow)), BorrowKind::Mut { .. }) => {
|
||||
Control::Continue
|
||||
}
|
||||
|
||||
(Reservation(_), BorrowKind::Shallow | BorrowKind::Shared) => {
|
||||
// This used to be a future compatibility warning (to be
|
||||
@ -1084,7 +1086,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
Control::Continue
|
||||
}
|
||||
|
||||
(Read(kind), BorrowKind::Unique | BorrowKind::Mut { .. }) => {
|
||||
(Read(kind), BorrowKind::Mut { .. }) => {
|
||||
// Reading from mere reservations of mutable-borrows is OK.
|
||||
if !is_active(this.dominators(), borrow, location) {
|
||||
assert!(allow_two_phase_borrow(borrow.kind));
|
||||
@ -1191,7 +1193,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
(Shallow(Some(ArtificialField::ShallowBorrow)), Read(ReadKind::Borrow(bk)))
|
||||
}
|
||||
BorrowKind::Shared => (Deep, Read(ReadKind::Borrow(bk))),
|
||||
BorrowKind::Unique | BorrowKind::Mut { .. } => {
|
||||
BorrowKind::Mut { .. } => {
|
||||
let wk = WriteKind::MutableBorrow(bk);
|
||||
if allow_two_phase_borrow(bk) {
|
||||
(Deep, Reservation(wk))
|
||||
@ -1228,7 +1230,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
Mutability::Mut => (
|
||||
Deep,
|
||||
Write(WriteKind::MutableBorrow(BorrowKind::Mut {
|
||||
allow_two_phase_borrow: false,
|
||||
kind: MutBorrowKind::Default,
|
||||
})),
|
||||
),
|
||||
Mutability::Not => (Deep, Read(ReadKind::Borrow(BorrowKind::Shared))),
|
||||
@ -1562,7 +1564,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
// only mutable borrows should be 2-phase
|
||||
assert!(match borrow.kind {
|
||||
BorrowKind::Shared | BorrowKind::Shallow => false,
|
||||
BorrowKind::Unique | BorrowKind::Mut { .. } => true,
|
||||
BorrowKind::Mut { .. } => true,
|
||||
});
|
||||
|
||||
self.access_place(
|
||||
@ -1956,16 +1958,15 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
let the_place_err;
|
||||
|
||||
match kind {
|
||||
Reservation(WriteKind::MutableBorrow(
|
||||
borrow_kind @ (BorrowKind::Unique | BorrowKind::Mut { .. }),
|
||||
))
|
||||
| Write(WriteKind::MutableBorrow(
|
||||
borrow_kind @ (BorrowKind::Unique | BorrowKind::Mut { .. }),
|
||||
)) => {
|
||||
let is_local_mutation_allowed = match borrow_kind {
|
||||
BorrowKind::Unique => LocalMutationIsAllowed::Yes,
|
||||
BorrowKind::Mut { .. } => is_local_mutation_allowed,
|
||||
BorrowKind::Shared | BorrowKind::Shallow => unreachable!(),
|
||||
Reservation(WriteKind::MutableBorrow(BorrowKind::Mut { kind: mut_borrow_kind }))
|
||||
| Write(WriteKind::MutableBorrow(BorrowKind::Mut { kind: mut_borrow_kind })) => {
|
||||
let is_local_mutation_allowed = match mut_borrow_kind {
|
||||
// `ClosureCapture` is used for mutable variable with a immutable binding.
|
||||
// This is only behaviour difference between `ClosureCapture` and mutable borrows.
|
||||
MutBorrowKind::ClosureCapture => LocalMutationIsAllowed::Yes,
|
||||
MutBorrowKind::Default | MutBorrowKind::TwoPhaseBorrow => {
|
||||
is_local_mutation_allowed
|
||||
}
|
||||
};
|
||||
match self.is_mutable(place.as_ref(), is_local_mutation_allowed) {
|
||||
Ok(root_place) => {
|
||||
@ -2028,12 +2029,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
return false;
|
||||
}
|
||||
Read(
|
||||
ReadKind::Borrow(
|
||||
BorrowKind::Unique
|
||||
| BorrowKind::Mut { .. }
|
||||
| BorrowKind::Shared
|
||||
| BorrowKind::Shallow,
|
||||
)
|
||||
ReadKind::Borrow(BorrowKind::Mut { .. } | BorrowKind::Shared | BorrowKind::Shallow)
|
||||
| ReadKind::Copy,
|
||||
) => {
|
||||
// Access authorized
|
||||
|
@ -441,7 +441,7 @@ fn for_each_region_constraint<'tcx>(
|
||||
let subject = match req.subject {
|
||||
ClosureOutlivesSubject::Region(subject) => format!("{:?}", subject),
|
||||
ClosureOutlivesSubject::Ty(ty) => {
|
||||
format!("{:?}", ty.instantiate(tcx, |vid| tcx.mk_re_var(vid)))
|
||||
format!("{:?}", ty.instantiate(tcx, |vid| ty::Region::new_var(tcx, vid)))
|
||||
}
|
||||
};
|
||||
with_msg(format!("where {}: {:?}", subject, req.outlived_free_region,))?;
|
||||
|
@ -46,11 +46,9 @@ impl<'tcx> PlaceExt<'tcx> for Place<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
for (i, elem) in self.projection.iter().enumerate() {
|
||||
let proj_base = &self.projection[..i];
|
||||
|
||||
for (i, (proj_base, elem)) in self.iter_projections().enumerate() {
|
||||
if elem == ProjectionElem::Deref {
|
||||
let ty = Place::ty_from(self.local, proj_base, body, tcx).ty;
|
||||
let ty = proj_base.ty(body, tcx).ty;
|
||||
match ty.kind() {
|
||||
ty::Ref(_, _, hir::Mutability::Not) if i == 0 => {
|
||||
// For references to thread-local statics, we do need
|
||||
|
@ -4,7 +4,9 @@ use crate::ArtificialField;
|
||||
use crate::Overlap;
|
||||
use crate::{AccessDepth, Deep, Shallow};
|
||||
use rustc_hir as hir;
|
||||
use rustc_middle::mir::{Body, BorrowKind, Local, Place, PlaceElem, PlaceRef, ProjectionElem};
|
||||
use rustc_middle::mir::{
|
||||
Body, BorrowKind, Local, MutBorrowKind, Place, PlaceElem, PlaceRef, ProjectionElem,
|
||||
};
|
||||
use rustc_middle::ty::{self, TyCtxt};
|
||||
use std::cmp::max;
|
||||
use std::iter;
|
||||
@ -35,7 +37,7 @@ pub fn places_conflict<'tcx>(
|
||||
tcx,
|
||||
body,
|
||||
borrow_place,
|
||||
BorrowKind::Mut { allow_two_phase_borrow: true },
|
||||
BorrowKind::Mut { kind: MutBorrowKind::TwoPhaseBorrow },
|
||||
access_place.as_ref(),
|
||||
AccessDepth::Deep,
|
||||
bias,
|
||||
@ -135,13 +137,11 @@ fn place_components_conflict<'tcx>(
|
||||
}
|
||||
|
||||
// loop invariant: borrow_c is always either equal to access_c or disjoint from it.
|
||||
for (i, (borrow_c, &access_c)) in
|
||||
iter::zip(borrow_place.projection, access_place.projection).enumerate()
|
||||
for ((borrow_place, borrow_c), &access_c) in
|
||||
iter::zip(borrow_place.iter_projections(), access_place.projection)
|
||||
{
|
||||
debug!(?borrow_c, ?access_c);
|
||||
|
||||
let borrow_proj_base = &borrow_place.projection[..i];
|
||||
|
||||
// Borrow and access path both have more components.
|
||||
//
|
||||
// Examples:
|
||||
@ -154,15 +154,7 @@ fn place_components_conflict<'tcx>(
|
||||
// check whether the components being borrowed vs
|
||||
// accessed are disjoint (as in the second example,
|
||||
// but not the first).
|
||||
match place_projection_conflict(
|
||||
tcx,
|
||||
body,
|
||||
borrow_local,
|
||||
borrow_proj_base,
|
||||
borrow_c,
|
||||
access_c,
|
||||
bias,
|
||||
) {
|
||||
match place_projection_conflict(tcx, body, borrow_place, borrow_c, access_c, bias) {
|
||||
Overlap::Arbitrary => {
|
||||
// We have encountered different fields of potentially
|
||||
// the same union - the borrow now partially overlaps.
|
||||
@ -193,8 +185,7 @@ fn place_components_conflict<'tcx>(
|
||||
}
|
||||
|
||||
if borrow_place.projection.len() > access_place.projection.len() {
|
||||
for (i, elem) in borrow_place.projection[access_place.projection.len()..].iter().enumerate()
|
||||
{
|
||||
for (base, elem) in borrow_place.iter_projections().skip(access_place.projection.len()) {
|
||||
// Borrow path is longer than the access path. Examples:
|
||||
//
|
||||
// - borrow of `a.b.c`, access to `a.b`
|
||||
@ -203,8 +194,7 @@ fn place_components_conflict<'tcx>(
|
||||
// our place. This is a conflict if that is a part our
|
||||
// access cares about.
|
||||
|
||||
let proj_base = &borrow_place.projection[..access_place.projection.len() + i];
|
||||
let base_ty = Place::ty_from(borrow_local, proj_base, body, tcx).ty;
|
||||
let base_ty = base.ty(body, tcx).ty;
|
||||
|
||||
match (elem, &base_ty.kind(), access) {
|
||||
(_, _, Shallow(Some(ArtificialField::ArrayLength)))
|
||||
@ -308,8 +298,7 @@ fn place_base_conflict(l1: Local, l2: Local) -> Overlap {
|
||||
fn place_projection_conflict<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
body: &Body<'tcx>,
|
||||
pi1_local: Local,
|
||||
pi1_proj_base: &[PlaceElem<'tcx>],
|
||||
pi1: PlaceRef<'tcx>,
|
||||
pi1_elem: PlaceElem<'tcx>,
|
||||
pi2_elem: PlaceElem<'tcx>,
|
||||
bias: PlaceConflictBias,
|
||||
@ -331,7 +320,7 @@ fn place_projection_conflict<'tcx>(
|
||||
debug!("place_element_conflict: DISJOINT-OR-EQ-FIELD");
|
||||
Overlap::EqualOrDisjoint
|
||||
} else {
|
||||
let ty = Place::ty_from(pi1_local, pi1_proj_base, body, tcx).ty;
|
||||
let ty = pi1.ty(body, tcx).ty;
|
||||
if ty.is_union() {
|
||||
// Different fields of a union, we are basically stuck.
|
||||
debug!("place_element_conflict: STUCK-UNION");
|
||||
|
@ -1139,7 +1139,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
_ => arg.fold_with(self),
|
||||
}
|
||||
});
|
||||
tcx.mk_opaque(def_id, tcx.mk_substs_from_iter(substs))
|
||||
Ty::new_opaque(tcx, def_id, tcx.mk_substs_from_iter(substs))
|
||||
}
|
||||
}
|
||||
|
||||
@ -1158,7 +1158,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
.universal_regions_outlived_by(r_scc)
|
||||
.filter(|&u_r| !self.universal_regions.is_local_free_region(u_r))
|
||||
.find(|&u_r| self.eval_equal(u_r, r_vid))
|
||||
.map(|u_r| tcx.mk_re_var(u_r))
|
||||
.map(|u_r| ty::Region::new_var(tcx, u_r))
|
||||
// In the case of a failure, use `ReErased`. We will eventually
|
||||
// return `None` in this case.
|
||||
.unwrap_or(tcx.lifetimes.re_erased)
|
||||
@ -1355,7 +1355,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
let vid = self.to_region_vid(r);
|
||||
let scc = self.constraint_sccs.scc(vid);
|
||||
let repr = self.scc_representatives[scc];
|
||||
tcx.mk_re_var(repr)
|
||||
ty::Region::new_var(tcx, repr)
|
||||
})
|
||||
}
|
||||
|
||||
@ -1779,7 +1779,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
}
|
||||
|
||||
// If not, report an error.
|
||||
let member_region = infcx.tcx.mk_re_var(member_region_vid);
|
||||
let member_region = ty::Region::new_var(infcx.tcx, member_region_vid);
|
||||
errors_buffer.push(RegionErrorKind::UnexpectedHiddenRegion {
|
||||
span: m_c.definition_span,
|
||||
hidden_ty: m_c.hidden_ty,
|
||||
|
@ -61,7 +61,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
pub(crate) fn infer_opaque_types(
|
||||
&self,
|
||||
infcx: &InferCtxt<'tcx>,
|
||||
opaque_ty_decls: FxIndexMap<OpaqueTypeKey<'tcx>, (OpaqueHiddenType<'tcx>, OpaqueTyOrigin)>,
|
||||
opaque_ty_decls: FxIndexMap<OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>>,
|
||||
) -> FxIndexMap<LocalDefId, OpaqueHiddenType<'tcx>> {
|
||||
let mut result: FxIndexMap<LocalDefId, OpaqueHiddenType<'tcx>> = FxIndexMap::default();
|
||||
|
||||
@ -72,7 +72,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
.collect();
|
||||
debug!(?member_constraints);
|
||||
|
||||
for (opaque_type_key, (concrete_type, origin)) in opaque_ty_decls {
|
||||
for (opaque_type_key, concrete_type) in opaque_ty_decls {
|
||||
let substs = opaque_type_key.substs;
|
||||
debug!(?concrete_type, ?substs);
|
||||
|
||||
@ -92,7 +92,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
}
|
||||
None => {
|
||||
subst_regions.push(vid);
|
||||
infcx.tcx.mk_re_error_with_message(
|
||||
ty::Region::new_error_with_message(
|
||||
infcx.tcx,
|
||||
concrete_type.span,
|
||||
"opaque type with non-universal region substs",
|
||||
)
|
||||
@ -142,7 +143,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
let ty = infcx.infer_opaque_definition_from_instantiation(
|
||||
opaque_type_key,
|
||||
universal_concrete_type,
|
||||
origin,
|
||||
);
|
||||
// Sometimes two opaque types are the same only after we remap the generic parameters
|
||||
// back to the opaque type definition. E.g. we may have `OpaqueType<X, Y>` mapped to `(X, Y)`
|
||||
@ -158,7 +158,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
)
|
||||
.emit()
|
||||
});
|
||||
prev.ty = infcx.tcx.ty_error(guar);
|
||||
prev.ty = Ty::new_error(infcx.tcx, guar);
|
||||
}
|
||||
// Pick a better span if there is one.
|
||||
// FIXME(oli-obk): collect multiple spans for better diagnostics down the road.
|
||||
@ -214,7 +214,6 @@ pub trait InferCtxtExt<'tcx> {
|
||||
&self,
|
||||
opaque_type_key: OpaqueTypeKey<'tcx>,
|
||||
instantiated_ty: OpaqueHiddenType<'tcx>,
|
||||
origin: OpaqueTyOrigin,
|
||||
) -> Ty<'tcx>;
|
||||
}
|
||||
|
||||
@ -247,99 +246,117 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
|
||||
&self,
|
||||
opaque_type_key: OpaqueTypeKey<'tcx>,
|
||||
instantiated_ty: OpaqueHiddenType<'tcx>,
|
||||
origin: OpaqueTyOrigin,
|
||||
) -> Ty<'tcx> {
|
||||
if let Some(e) = self.tainted_by_errors() {
|
||||
return self.tcx.ty_error(e);
|
||||
return Ty::new_error(self.tcx, e);
|
||||
}
|
||||
|
||||
if let Err(guar) =
|
||||
check_opaque_type_parameter_valid(self.tcx, opaque_type_key, instantiated_ty.span)
|
||||
{
|
||||
return Ty::new_error(self.tcx, guar);
|
||||
}
|
||||
|
||||
let definition_ty = instantiated_ty
|
||||
.remap_generic_params_to_declaration_params(opaque_type_key, self.tcx, false)
|
||||
.ty;
|
||||
|
||||
if let Err(guar) = check_opaque_type_parameter_valid(
|
||||
// `definition_ty` does not live in of the current inference context,
|
||||
// so lets make sure that we don't accidentally misuse our current `infcx`.
|
||||
match check_opaque_type_well_formed(
|
||||
self.tcx,
|
||||
opaque_type_key,
|
||||
origin,
|
||||
self.next_trait_solver(),
|
||||
opaque_type_key.def_id,
|
||||
instantiated_ty.span,
|
||||
) {
|
||||
return self.tcx.ty_error(guar);
|
||||
}
|
||||
|
||||
// Only check this for TAIT. RPIT already supports `tests/ui/impl-trait/nested-return-type2.rs`
|
||||
// on stable and we'd break that.
|
||||
let OpaqueTyOrigin::TyAlias { .. } = origin else {
|
||||
return definition_ty;
|
||||
};
|
||||
let def_id = opaque_type_key.def_id;
|
||||
// This logic duplicates most of `check_opaque_meets_bounds`.
|
||||
// FIXME(oli-obk): Also do region checks here and then consider removing `check_opaque_meets_bounds` entirely.
|
||||
let param_env = self.tcx.param_env(def_id);
|
||||
// HACK This bubble is required for this tests to pass:
|
||||
// nested-return-type2-tait2.rs
|
||||
// nested-return-type2-tait3.rs
|
||||
let infcx =
|
||||
self.tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bubble).build();
|
||||
let ocx = ObligationCtxt::new(&infcx);
|
||||
// Require the hidden type to be well-formed with only the generics of the opaque type.
|
||||
// Defining use functions may have more bounds than the opaque type, which is ok, as long as the
|
||||
// hidden type is well formed even without those bounds.
|
||||
let predicate = ty::Binder::dummy(ty::PredicateKind::WellFormed(definition_ty.into()));
|
||||
|
||||
let id_substs = InternalSubsts::identity_for_item(self.tcx, def_id);
|
||||
|
||||
// Require that the hidden type actually fulfills all the bounds of the opaque type, even without
|
||||
// the bounds that the function supplies.
|
||||
let opaque_ty = self.tcx.mk_opaque(def_id.to_def_id(), id_substs);
|
||||
if let Err(err) = ocx.eq(
|
||||
&ObligationCause::misc(instantiated_ty.span, def_id),
|
||||
param_env,
|
||||
opaque_ty,
|
||||
definition_ty,
|
||||
) {
|
||||
Ok(hidden_ty) => hidden_ty,
|
||||
Err(guar) => Ty::new_error(self.tcx, guar),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// This logic duplicates most of `check_opaque_meets_bounds`.
|
||||
/// FIXME(oli-obk): Also do region checks here and then consider removing
|
||||
/// `check_opaque_meets_bounds` entirely.
|
||||
fn check_opaque_type_well_formed<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
next_trait_solver: bool,
|
||||
def_id: LocalDefId,
|
||||
definition_span: Span,
|
||||
definition_ty: Ty<'tcx>,
|
||||
) -> Result<Ty<'tcx>, ErrorGuaranteed> {
|
||||
// Only check this for TAIT. RPIT already supports `tests/ui/impl-trait/nested-return-type2.rs`
|
||||
// on stable and we'd break that.
|
||||
let opaque_ty_hir = tcx.hir().expect_item(def_id);
|
||||
let OpaqueTyOrigin::TyAlias { .. } = opaque_ty_hir.expect_opaque_ty().origin else {
|
||||
return Ok(definition_ty);
|
||||
};
|
||||
let param_env = tcx.param_env(def_id);
|
||||
// HACK This bubble is required for this tests to pass:
|
||||
// nested-return-type2-tait2.rs
|
||||
// nested-return-type2-tait3.rs
|
||||
// FIXME(-Ztrait-solver=next): We probably should use `DefiningAnchor::Error`
|
||||
// and prepopulate this `InferCtxt` with known opaque values, rather than
|
||||
// using the `Bind` anchor here. For now it's fine.
|
||||
let infcx = tcx
|
||||
.infer_ctxt()
|
||||
.with_next_trait_solver(next_trait_solver)
|
||||
.with_opaque_type_inference(if next_trait_solver {
|
||||
DefiningAnchor::Bind(def_id)
|
||||
} else {
|
||||
DefiningAnchor::Bubble
|
||||
})
|
||||
.build();
|
||||
let ocx = ObligationCtxt::new(&infcx);
|
||||
let identity_substs = InternalSubsts::identity_for_item(tcx, def_id);
|
||||
|
||||
// Require that the hidden type actually fulfills all the bounds of the opaque type, even without
|
||||
// the bounds that the function supplies.
|
||||
let opaque_ty = Ty::new_opaque(tcx, def_id.to_def_id(), identity_substs);
|
||||
ocx.eq(&ObligationCause::misc(definition_span, def_id), param_env, opaque_ty, definition_ty)
|
||||
.map_err(|err| {
|
||||
infcx
|
||||
.err_ctxt()
|
||||
.report_mismatched_types(
|
||||
&ObligationCause::misc(instantiated_ty.span, def_id),
|
||||
&ObligationCause::misc(definition_span, def_id),
|
||||
opaque_ty,
|
||||
definition_ty,
|
||||
err,
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
.emit()
|
||||
})?;
|
||||
|
||||
ocx.register_obligation(Obligation::misc(
|
||||
infcx.tcx,
|
||||
instantiated_ty.span,
|
||||
def_id,
|
||||
param_env,
|
||||
predicate,
|
||||
));
|
||||
// Require the hidden type to be well-formed with only the generics of the opaque type.
|
||||
// Defining use functions may have more bounds than the opaque type, which is ok, as long as the
|
||||
// hidden type is well formed even without those bounds.
|
||||
let predicate = ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(
|
||||
definition_ty.into(),
|
||||
)));
|
||||
ocx.register_obligation(Obligation::misc(tcx, definition_span, def_id, param_env, predicate));
|
||||
|
||||
// Check that all obligations are satisfied by the implementation's
|
||||
// version.
|
||||
let errors = ocx.select_all_or_error();
|
||||
// Check that all obligations are satisfied by the implementation's
|
||||
// version.
|
||||
let errors = ocx.select_all_or_error();
|
||||
|
||||
// This is still required for many(half of the tests in ui/type-alias-impl-trait)
|
||||
// tests to pass
|
||||
let _ = infcx.take_opaque_types();
|
||||
// This is still required for many(half of the tests in ui/type-alias-impl-trait)
|
||||
// tests to pass
|
||||
let _ = infcx.take_opaque_types();
|
||||
|
||||
if errors.is_empty() {
|
||||
definition_ty
|
||||
} else {
|
||||
let reported = infcx.err_ctxt().report_fulfillment_errors(&errors);
|
||||
self.tcx.ty_error(reported)
|
||||
}
|
||||
if errors.is_empty() {
|
||||
Ok(definition_ty)
|
||||
} else {
|
||||
Err(infcx.err_ctxt().report_fulfillment_errors(&errors))
|
||||
}
|
||||
}
|
||||
|
||||
fn check_opaque_type_parameter_valid(
|
||||
tcx: TyCtxt<'_>,
|
||||
opaque_type_key: OpaqueTypeKey<'_>,
|
||||
origin: OpaqueTyOrigin,
|
||||
span: Span,
|
||||
) -> Result<(), ErrorGuaranteed> {
|
||||
match origin {
|
||||
let opaque_ty_hir = tcx.hir().expect_item(opaque_type_key.def_id);
|
||||
match opaque_ty_hir.expect_opaque_ty().origin {
|
||||
// No need to check return position impl trait (RPIT)
|
||||
// because for type and const parameters they are correct
|
||||
// by construction: we convert
|
||||
|
@ -89,11 +89,13 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||
category: ConstraintCategory<'tcx>,
|
||||
) {
|
||||
self.prove_predicate(
|
||||
ty::Binder::dummy(ty::PredicateKind::Clause(ty::Clause::Trait(ty::TraitPredicate {
|
||||
trait_ref,
|
||||
constness: ty::BoundConstness::NotConst,
|
||||
polarity: ty::ImplPolarity::Positive,
|
||||
}))),
|
||||
ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::Trait(
|
||||
ty::TraitPredicate {
|
||||
trait_ref,
|
||||
constness: ty::BoundConstness::NotConst,
|
||||
polarity: ty::ImplPolarity::Positive,
|
||||
},
|
||||
))),
|
||||
locations,
|
||||
category,
|
||||
);
|
||||
|
@ -245,7 +245,7 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
|
||||
.and(type_op::normalize::Normalize::new(ty))
|
||||
.fully_perform(self.infcx, span)
|
||||
.unwrap_or_else(|guar| TypeOpOutput {
|
||||
output: self.infcx.tcx.ty_error(guar),
|
||||
output: Ty::new_error(self.infcx.tcx, guar),
|
||||
constraints: None,
|
||||
error_info: None,
|
||||
});
|
||||
|
@ -124,21 +124,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||
// Return types are a bit more complex. They may contain opaque `impl Trait` types.
|
||||
let mir_output_ty = body.local_decls[RETURN_PLACE].ty;
|
||||
let output_span = body.local_decls[RETURN_PLACE].source_info.span;
|
||||
if let Err(terr) = self.eq_types(
|
||||
normalized_output_ty,
|
||||
mir_output_ty,
|
||||
Locations::All(output_span),
|
||||
ConstraintCategory::BoringNoLocation,
|
||||
) {
|
||||
span_mirbug!(
|
||||
self,
|
||||
Location::START,
|
||||
"equate_inputs_and_outputs: `{:?}=={:?}` failed with `{:?}`",
|
||||
normalized_output_ty,
|
||||
mir_output_ty,
|
||||
terr
|
||||
);
|
||||
};
|
||||
self.equate_normalized_input_or_output(normalized_output_ty, mir_output_ty, output_span);
|
||||
}
|
||||
|
||||
#[instrument(skip(self), level = "debug")]
|
||||
|
@ -7,7 +7,6 @@ use std::{fmt, iter, mem};
|
||||
|
||||
use either::Either;
|
||||
|
||||
use hir::OpaqueTyOrigin;
|
||||
use rustc_data_structures::frozen::Frozen;
|
||||
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
|
||||
use rustc_errors::ErrorGuaranteed;
|
||||
@ -28,7 +27,8 @@ use rustc_middle::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor};
|
||||
use rustc_middle::mir::AssertKind;
|
||||
use rustc_middle::mir::*;
|
||||
use rustc_middle::traits::query::NoSolution;
|
||||
use rustc_middle::ty::adjustment::PointerCast;
|
||||
use rustc_middle::traits::ObligationCause;
|
||||
use rustc_middle::ty::adjustment::PointerCoercion;
|
||||
use rustc_middle::ty::cast::CastTy;
|
||||
use rustc_middle::ty::subst::{SubstsRef, UserSubsts};
|
||||
use rustc_middle::ty::visit::TypeVisitableExt;
|
||||
@ -50,7 +50,6 @@ use rustc_mir_dataflow::impls::MaybeInitializedPlaces;
|
||||
use rustc_mir_dataflow::move_paths::MoveData;
|
||||
use rustc_mir_dataflow::ResultsCursor;
|
||||
|
||||
use crate::renumber::RegionCtxt;
|
||||
use crate::session_diagnostics::MoveUnsized;
|
||||
use crate::{
|
||||
borrow_set::BorrowSet,
|
||||
@ -139,7 +138,7 @@ pub(crate) fn type_check<'mir, 'tcx>(
|
||||
upvars: &[Upvar<'tcx>],
|
||||
use_polonius: bool,
|
||||
) -> MirTypeckResults<'tcx> {
|
||||
let implicit_region_bound = infcx.tcx.mk_re_var(universal_regions.fr_fn_body);
|
||||
let implicit_region_bound = ty::Region::new_var(infcx.tcx, universal_regions.fr_fn_body);
|
||||
let mut constraints = MirTypeckRegionConstraints {
|
||||
placeholder_indices: PlaceholderIndices::default(),
|
||||
placeholder_index_to_region: IndexVec::default(),
|
||||
@ -188,10 +187,7 @@ pub(crate) fn type_check<'mir, 'tcx>(
|
||||
|
||||
// FIXME(-Ztrait-solver=next): A bit dubious that we're only registering
|
||||
// predefined opaques in the typeck root.
|
||||
// FIXME(-Ztrait-solver=next): This is also totally wrong for TAITs, since
|
||||
// the HIR typeck map defining usages back to their definition params,
|
||||
// they won't actually match up with the usages in this body...
|
||||
if infcx.tcx.trait_solver_next() && !infcx.tcx.is_typeck_child(body.source.def_id()) {
|
||||
if infcx.next_trait_solver() && !infcx.tcx.is_typeck_child(body.source.def_id()) {
|
||||
checker.register_predefined_opaques_in_new_solver();
|
||||
}
|
||||
|
||||
@ -241,10 +237,10 @@ pub(crate) fn type_check<'mir, 'tcx>(
|
||||
decl.hidden_type.span,
|
||||
format!("could not resolve {:#?}", hidden_type.ty.kind()),
|
||||
);
|
||||
hidden_type.ty = infcx.tcx.ty_error(reported);
|
||||
hidden_type.ty = Ty::new_error(infcx.tcx, reported);
|
||||
}
|
||||
|
||||
(opaque_type_key, (hidden_type, decl.origin))
|
||||
(opaque_type_key, hidden_type)
|
||||
})
|
||||
.collect();
|
||||
|
||||
@ -480,9 +476,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
|
||||
|
||||
fn visit_body(&mut self, body: &Body<'tcx>) {
|
||||
self.sanitize_type(&"return type", body.return_ty());
|
||||
for local_decl in &body.local_decls {
|
||||
self.sanitize_type(local_decl, local_decl.ty);
|
||||
}
|
||||
// The types of local_decls are checked above which is called in super_body.
|
||||
self.super_body(body);
|
||||
}
|
||||
}
|
||||
@ -526,7 +520,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
|
||||
for elem in place.projection.iter() {
|
||||
if place_ty.variant_index.is_none() {
|
||||
if let Err(guar) = place_ty.ty.error_reported() {
|
||||
return PlaceTy::from_ty(self.tcx().ty_error(guar));
|
||||
return PlaceTy::from_ty(Ty::new_error(self.tcx(), guar));
|
||||
}
|
||||
}
|
||||
place_ty = self.sanitize_projection(place_ty, elem, place, location, context);
|
||||
@ -662,7 +656,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
|
||||
PlaceTy::from_ty(match base_ty.kind() {
|
||||
ty::Array(inner, _) => {
|
||||
assert!(!from_end, "array subslices should not use from_end");
|
||||
tcx.mk_array(*inner, to - from)
|
||||
Ty::new_array(tcx, *inner, to - from)
|
||||
}
|
||||
ty::Slice(..) => {
|
||||
assert!(from_end, "slice subslices should use from_end");
|
||||
@ -755,7 +749,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
|
||||
}
|
||||
|
||||
fn error(&mut self) -> Ty<'tcx> {
|
||||
self.tcx().ty_error_misc()
|
||||
Ty::new_misc_error(self.tcx())
|
||||
}
|
||||
|
||||
fn get_ambient_variance(&self, context: PlaceContext) -> ty::Variance {
|
||||
@ -883,8 +877,7 @@ struct BorrowCheckContext<'a, 'tcx> {
|
||||
pub(crate) struct MirTypeckResults<'tcx> {
|
||||
pub(crate) constraints: MirTypeckRegionConstraints<'tcx>,
|
||||
pub(crate) universal_region_relations: Frozen<UniversalRegionRelations<'tcx>>,
|
||||
pub(crate) opaque_type_values:
|
||||
FxIndexMap<OpaqueTypeKey<'tcx>, (OpaqueHiddenType<'tcx>, OpaqueTyOrigin)>,
|
||||
pub(crate) opaque_type_values: FxIndexMap<OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>>,
|
||||
}
|
||||
|
||||
/// A collection of region constraints that must be satisfied for the
|
||||
@ -1042,16 +1035,13 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||
.typeck(self.body.source.def_id().expect_local())
|
||||
.concrete_opaque_types
|
||||
.iter()
|
||||
.map(|(&def_id, &hidden_ty)| {
|
||||
let substs = ty::InternalSubsts::identity_for_item(self.infcx.tcx, def_id);
|
||||
(ty::OpaqueTypeKey { def_id, substs }, hidden_ty)
|
||||
})
|
||||
.map(|(k, v)| (*k, *v))
|
||||
.collect();
|
||||
|
||||
let renumbered_opaques = self.infcx.tcx.fold_regions(opaques, |_, _| {
|
||||
self.infcx.next_nll_region_var(
|
||||
self.infcx.next_nll_region_var_in_universe(
|
||||
NllRegionVariableOrigin::Existential { from_forall: false },
|
||||
|| RegionCtxt::Unknown,
|
||||
ty::UniverseIndex::ROOT,
|
||||
)
|
||||
});
|
||||
|
||||
@ -1061,15 +1051,29 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||
ConstraintCategory::OpaqueType,
|
||||
CustomTypeOp::new(
|
||||
|ocx| {
|
||||
for (key, hidden_ty) in renumbered_opaques {
|
||||
ocx.register_infer_ok_obligations(
|
||||
ocx.infcx.register_hidden_type_in_new_solver(
|
||||
key,
|
||||
param_env,
|
||||
hidden_ty.ty,
|
||||
)?,
|
||||
let mut obligations = Vec::new();
|
||||
for (opaque_type_key, hidden_ty) in renumbered_opaques {
|
||||
let cause = ObligationCause::dummy();
|
||||
ocx.infcx.insert_hidden_type(
|
||||
opaque_type_key,
|
||||
&cause,
|
||||
param_env,
|
||||
hidden_ty.ty,
|
||||
true,
|
||||
&mut obligations,
|
||||
)?;
|
||||
|
||||
ocx.infcx.add_item_bounds_for_hidden_type(
|
||||
opaque_type_key.def_id.to_def_id(),
|
||||
opaque_type_key.substs,
|
||||
cause,
|
||||
param_env,
|
||||
hidden_ty.ty,
|
||||
&mut obligations,
|
||||
);
|
||||
}
|
||||
|
||||
ocx.register_obligations(obligations);
|
||||
Ok(())
|
||||
},
|
||||
"register pre-defined opaques",
|
||||
@ -1366,7 +1370,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||
}
|
||||
// FIXME: check the values
|
||||
}
|
||||
TerminatorKind::Call { func, args, destination, from_hir_call, target, .. } => {
|
||||
TerminatorKind::Call { func, args, destination, call_source, target, .. } => {
|
||||
self.check_operand(func, term_location);
|
||||
for arg in args {
|
||||
self.check_operand(arg, term_location);
|
||||
@ -1415,9 +1419,11 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||
//
|
||||
// See #91068 for an example.
|
||||
self.prove_predicates(
|
||||
sig.inputs_and_output
|
||||
.iter()
|
||||
.map(|ty| ty::Binder::dummy(ty::PredicateKind::WellFormed(ty.into()))),
|
||||
sig.inputs_and_output.iter().map(|ty| {
|
||||
ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(
|
||||
ty.into(),
|
||||
)))
|
||||
}),
|
||||
term_location.to_locations(),
|
||||
ConstraintCategory::Boring,
|
||||
);
|
||||
@ -1440,7 +1446,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||
.add_element(region_vid, term_location);
|
||||
}
|
||||
|
||||
self.check_call_inputs(body, term, &sig, args, term_location, *from_hir_call);
|
||||
self.check_call_inputs(body, term, &sig, args, term_location, *call_source);
|
||||
}
|
||||
TerminatorKind::Assert { cond, msg, .. } => {
|
||||
self.check_operand(cond, term_location);
|
||||
@ -1567,7 +1573,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||
sig: &ty::FnSig<'tcx>,
|
||||
args: &[Operand<'tcx>],
|
||||
term_location: Location,
|
||||
from_hir_call: bool,
|
||||
call_source: CallSource,
|
||||
) {
|
||||
debug!("check_call_inputs({:?}, {:?})", sig, args);
|
||||
if args.len() < sig.inputs().len() || (args.len() > sig.inputs().len() && !sig.c_variadic) {
|
||||
@ -1585,7 +1591,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||
let op_arg_ty = op_arg.ty(body, self.tcx());
|
||||
|
||||
let op_arg_ty = self.normalize(op_arg_ty, term_location);
|
||||
let category = if from_hir_call {
|
||||
let category = if call_source.from_hir_call() {
|
||||
ConstraintCategory::CallArgument(self.infcx.tcx.erase_regions(func_ty))
|
||||
} else {
|
||||
ConstraintCategory::Boring
|
||||
@ -1846,7 +1852,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||
|
||||
let array_ty = rvalue.ty(body.local_decls(), tcx);
|
||||
self.prove_predicate(
|
||||
ty::PredicateKind::WellFormed(array_ty.into()),
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(array_ty.into())),
|
||||
Locations::Single(location),
|
||||
ConstraintCategory::Boring,
|
||||
);
|
||||
@ -1902,7 +1908,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||
self.check_operand(op, location);
|
||||
|
||||
match cast_kind {
|
||||
CastKind::Pointer(PointerCast::ReifyFnPointer) => {
|
||||
CastKind::PointerCoercion(PointerCoercion::ReifyFnPointer) => {
|
||||
let fn_sig = op.ty(body, tcx).fn_sig(tcx);
|
||||
|
||||
// The type that we see in the fcx is like
|
||||
@ -1912,7 +1918,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||
// and hence may contain unnormalized results.
|
||||
let fn_sig = self.normalize(fn_sig, location);
|
||||
|
||||
let ty_fn_ptr_from = tcx.mk_fn_ptr(fn_sig);
|
||||
let ty_fn_ptr_from = Ty::new_fn_ptr(tcx, fn_sig);
|
||||
|
||||
if let Err(terr) = self.eq_types(
|
||||
*ty,
|
||||
@ -1931,12 +1937,13 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
CastKind::Pointer(PointerCast::ClosureFnPointer(unsafety)) => {
|
||||
CastKind::PointerCoercion(PointerCoercion::ClosureFnPointer(unsafety)) => {
|
||||
let sig = match op.ty(body, tcx).kind() {
|
||||
ty::Closure(_, substs) => substs.as_closure().sig(),
|
||||
_ => bug!(),
|
||||
};
|
||||
let ty_fn_ptr_from = tcx.mk_fn_ptr(tcx.signature_unclosure(sig, *unsafety));
|
||||
let ty_fn_ptr_from =
|
||||
Ty::new_fn_ptr(tcx, tcx.signature_unclosure(sig, *unsafety));
|
||||
|
||||
if let Err(terr) = self.eq_types(
|
||||
*ty,
|
||||
@ -1955,7 +1962,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
CastKind::Pointer(PointerCast::UnsafeFnPointer) => {
|
||||
CastKind::PointerCoercion(PointerCoercion::UnsafeFnPointer) => {
|
||||
let fn_sig = op.ty(body, tcx).fn_sig(tcx);
|
||||
|
||||
// The type that we see in the fcx is like
|
||||
@ -1984,7 +1991,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
CastKind::Pointer(PointerCast::Unsize) => {
|
||||
CastKind::PointerCoercion(PointerCoercion::Unsize) => {
|
||||
let &ty = ty;
|
||||
let trait_ref = ty::TraitRef::from_lang_item(
|
||||
tcx,
|
||||
@ -2019,10 +2026,11 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||
ConstraintCategory::Cast,
|
||||
);
|
||||
|
||||
let outlives_predicate =
|
||||
tcx.mk_predicate(Binder::dummy(ty::PredicateKind::Clause(
|
||||
ty::Clause::TypeOutlives(ty::OutlivesPredicate(self_ty, *region)),
|
||||
)));
|
||||
let outlives_predicate = tcx.mk_predicate(Binder::dummy(
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(
|
||||
ty::OutlivesPredicate(self_ty, *region),
|
||||
)),
|
||||
));
|
||||
self.prove_predicate(
|
||||
outlives_predicate,
|
||||
location.to_locations(),
|
||||
@ -2030,7 +2038,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||
);
|
||||
}
|
||||
|
||||
CastKind::Pointer(PointerCast::MutToConstPointer) => {
|
||||
CastKind::PointerCoercion(PointerCoercion::MutToConstPointer) => {
|
||||
let ty::RawPtr(ty::TypeAndMut {
|
||||
ty: ty_from,
|
||||
mutbl: hir::Mutability::Mut,
|
||||
@ -2072,7 +2080,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
CastKind::Pointer(PointerCast::ArrayToPointer) => {
|
||||
CastKind::PointerCoercion(PointerCoercion::ArrayToPointer) => {
|
||||
let ty_from = op.ty(body, tcx);
|
||||
|
||||
let opt_ty_elem_mut = match ty_from.kind() {
|
||||
@ -2495,7 +2503,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||
location, borrow_region, borrowed_place
|
||||
);
|
||||
|
||||
let mut cursor = borrowed_place.projection.as_ref();
|
||||
let tcx = self.infcx.tcx;
|
||||
let field = path_utils::is_upvar_field_projection(
|
||||
tcx,
|
||||
@ -2509,14 +2516,12 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||
ConstraintCategory::Boring
|
||||
};
|
||||
|
||||
while let [proj_base @ .., elem] = cursor {
|
||||
cursor = proj_base;
|
||||
|
||||
for (base, elem) in borrowed_place.as_ref().iter_projections().rev() {
|
||||
debug!("add_reborrow_constraint - iteration {:?}", elem);
|
||||
|
||||
match elem {
|
||||
ProjectionElem::Deref => {
|
||||
let base_ty = Place::ty_from(borrowed_place.local, proj_base, body, tcx).ty;
|
||||
let base_ty = base.ty(body, tcx).ty;
|
||||
|
||||
debug!("add_reborrow_constraint - base_ty = {:?}", base_ty);
|
||||
match base_ty.kind() {
|
||||
|
@ -500,7 +500,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
|
||||
.next_nll_region_var(FR, || RegionCtxt::Free(Symbol::intern("c-variadic")))
|
||||
.as_var();
|
||||
|
||||
let region = self.infcx.tcx.mk_re_var(reg_vid);
|
||||
let region = ty::Region::new_var(self.infcx.tcx, reg_vid);
|
||||
let va_list_ty =
|
||||
self.infcx.tcx.type_of(va_list_did).subst(self.infcx.tcx, &[region.into()]);
|
||||
|
||||
@ -660,7 +660,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
|
||||
var: ty::BoundVar::from_usize(bound_vars.len() - 1),
|
||||
kind: ty::BrEnv,
|
||||
};
|
||||
let env_region = tcx.mk_re_late_bound(ty::INNERMOST, br);
|
||||
let env_region = ty::Region::new_late_bound(tcx, ty::INNERMOST, br);
|
||||
let closure_ty = tcx.closure_env_ty(def_id, substs, env_region).unwrap();
|
||||
|
||||
// The "inputs" of the closure in the
|
||||
@ -685,7 +685,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
|
||||
assert_eq!(self.mir_def.to_def_id(), def_id);
|
||||
let resume_ty = substs.as_generator().resume_ty();
|
||||
let output = substs.as_generator().return_ty();
|
||||
let generator_ty = tcx.mk_generator(def_id, substs, movability);
|
||||
let generator_ty = Ty::new_generator(tcx, def_id, substs, movability);
|
||||
let inputs_and_output =
|
||||
self.infcx.tcx.mk_type_list(&[generator_ty, resume_ty, output]);
|
||||
ty::Binder::dummy(inputs_and_output)
|
||||
@ -778,7 +778,8 @@ impl<'cx, 'tcx> InferCtxtExt<'tcx> for BorrowckInferCtxt<'cx, 'tcx> {
|
||||
{
|
||||
let (value, _map) = self.tcx.replace_late_bound_regions(value, |br| {
|
||||
debug!(?br);
|
||||
let liberated_region = self.tcx.mk_re_free(all_outlive_scope.to_def_id(), br.kind);
|
||||
let liberated_region =
|
||||
ty::Region::new_free(self.tcx, all_outlive_scope.to_def_id(), br.kind);
|
||||
let region_vid = {
|
||||
let name = match br.kind.get_name() {
|
||||
Some(name) => name,
|
||||
@ -889,7 +890,7 @@ impl<'tcx> UniversalRegionIndices<'tcx> {
|
||||
where
|
||||
T: TypeFoldable<TyCtxt<'tcx>>,
|
||||
{
|
||||
tcx.fold_regions(value, |region, _| tcx.mk_re_var(self.to_region_vid(region)))
|
||||
tcx.fold_regions(value, |region, _| ty::Region::new_var(tcx, self.to_region_vid(region)))
|
||||
}
|
||||
}
|
||||
|
||||
@ -929,7 +930,7 @@ fn for_each_late_bound_region_in_item<'tcx>(
|
||||
|
||||
for bound_var in tcx.late_bound_vars(tcx.hir().local_def_id_to_hir_id(mir_def_id)) {
|
||||
let ty::BoundVariableKind::Region(bound_region) = bound_var else { continue; };
|
||||
let liberated_region = tcx.mk_re_free(mir_def_id.to_def_id(), bound_region);
|
||||
let liberated_region = ty::Region::new_free(tcx, mir_def_id.to_def_id(), bound_region);
|
||||
f(liberated_region);
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
builtin_macros_alloc_error_must_be_fn = alloc_error_handler must be a function
|
||||
builtin_macros_alloc_must_statics = allocators must be statics
|
||||
|
||||
builtin_macros_asm_clobber_abi = clobber_abi
|
||||
builtin_macros_asm_clobber_no_reg = asm with `clobber_abi` must specify explicit registers for outputs
|
||||
@ -56,6 +57,9 @@ builtin_macros_bad_derive_target = `derive` may only be applied to `struct`s, `e
|
||||
.label = not applicable here
|
||||
.label2 = not a `struct`, `enum` or `union`
|
||||
|
||||
builtin_macros_bench_sig = functions used as benches must have signature `fn(&mut Bencher) -> impl Termination`
|
||||
|
||||
|
||||
builtin_macros_cannot_derive_union = this trait cannot be derived for unions
|
||||
|
||||
builtin_macros_cfg_accessible_has_args = `cfg_accessible` path cannot accept arguments
|
||||
@ -84,6 +88,7 @@ builtin_macros_concat_bytes_non_u8 = numeric literal is not a `u8`
|
||||
builtin_macros_concat_bytes_oob = numeric literal is out of bounds
|
||||
|
||||
builtin_macros_concat_bytestr = cannot concatenate a byte string literal
|
||||
builtin_macros_concat_c_str_lit = cannot concatenate a C string literal
|
||||
|
||||
builtin_macros_concat_idents_ident_args = `concat_idents!()` requires ident args
|
||||
|
||||
@ -111,6 +116,10 @@ builtin_macros_env_takes_args = `env!()` takes 1 or 2 arguments
|
||||
|
||||
builtin_macros_expected_one_cfg_pattern = expected 1 cfg-pattern
|
||||
|
||||
builtin_macros_expected_register_class_or_explicit_register = expected register class or explicit register
|
||||
|
||||
builtin_macros_export_macro_rules = cannot export macro_rules! macros from a `proc-macro` crate type currently
|
||||
|
||||
builtin_macros_format_duplicate_arg = duplicate argument named `{$ident}`
|
||||
.label1 = previously here
|
||||
.label2 = duplicate argument
|
||||
@ -158,6 +167,8 @@ builtin_macros_format_unused_args = multiple unused formatting arguments
|
||||
|
||||
builtin_macros_global_asm_clobber_abi = `clobber_abi` cannot be used with `global_asm!`
|
||||
|
||||
builtin_macros_invalid_crate_attribute = invalid crate attribute
|
||||
|
||||
builtin_macros_multiple_default_attrs = multiple `#[default]` attributes
|
||||
.note = only one `#[default]` attribute is needed
|
||||
.label = `#[default]` used here
|
||||
@ -177,6 +188,8 @@ builtin_macros_no_default_variant = no default declared
|
||||
.help = make a unit variant default by placing `#[default]` above it
|
||||
.suggestion = make `{$ident}` default
|
||||
|
||||
builtin_macros_non_abi = at least one abi must be provided as an argument to `clobber_abi`
|
||||
|
||||
builtin_macros_non_exhaustive_default = default variant must be exhaustive
|
||||
.label = declared `#[non_exhaustive]` here
|
||||
.help = consider a manual implementation of `Default`
|
||||
@ -184,12 +197,20 @@ builtin_macros_non_exhaustive_default = default variant must be exhaustive
|
||||
builtin_macros_non_unit_default = the `#[default]` attribute may only be used on unit enum variants
|
||||
.help = consider a manual implementation of `Default`
|
||||
|
||||
builtin_macros_proc_macro = `proc-macro` crate types currently cannot export any items other than functions tagged with `#[proc_macro]`, `#[proc_macro_derive]`, or `#[proc_macro_attribute]`
|
||||
|
||||
builtin_macros_requires_cfg_pattern =
|
||||
macro requires a cfg-pattern as an argument
|
||||
.label = cfg-pattern required
|
||||
|
||||
builtin_macros_should_panic = functions using `#[should_panic]` must return `()`
|
||||
|
||||
builtin_macros_sugg = consider using a positional formatting argument instead
|
||||
|
||||
builtin_macros_test_arg_non_lifetime = functions used as tests can not have any non-lifetime generic parameters
|
||||
|
||||
builtin_macros_test_args = functions used as tests can not have any arguments
|
||||
|
||||
builtin_macros_test_bad_fn = {$kind} functions cannot be used for tests
|
||||
.label = `{$kind}` because of this
|
||||
|
||||
@ -198,6 +219,10 @@ builtin_macros_test_case_non_item = `#[test_case]` attribute is only allowed on
|
||||
builtin_macros_test_runner_invalid = `test_runner` argument must be a path
|
||||
builtin_macros_test_runner_nargs = `#![test_runner(..)]` accepts exactly 1 argument
|
||||
|
||||
builtin_macros_tests_not_support = building tests with panic=abort is not supported without `-Zpanic_abort_tests`
|
||||
|
||||
builtin_macros_trace_macros = trace_macros! accepts only `true` or `false`
|
||||
|
||||
builtin_macros_unexpected_lit = expected path to a trait, found literal
|
||||
.label = not a trait
|
||||
.str_lit = try using `#[derive({$sym})]`
|
||||
|
@ -371,24 +371,16 @@ fn parse_clobber_abi<'a>(p: &mut Parser<'a>, args: &mut AsmArgs) -> PResult<'a,
|
||||
p.expect(&token::OpenDelim(Delimiter::Parenthesis))?;
|
||||
|
||||
if p.eat(&token::CloseDelim(Delimiter::Parenthesis)) {
|
||||
let err = p.sess.span_diagnostic.struct_span_err(
|
||||
p.token.span,
|
||||
"at least one abi must be provided as an argument to `clobber_abi`",
|
||||
);
|
||||
return Err(err);
|
||||
return Err(p.sess.span_diagnostic.create_err(errors::NonABI { span: p.token.span }));
|
||||
}
|
||||
|
||||
let mut new_abis = Vec::new();
|
||||
loop {
|
||||
while !p.eat(&token::CloseDelim(Delimiter::Parenthesis)) {
|
||||
match p.parse_str_lit() {
|
||||
Ok(str_lit) => {
|
||||
new_abis.push((str_lit.symbol_unescaped, str_lit.span));
|
||||
}
|
||||
Err(opt_lit) => {
|
||||
// If the non-string literal is a closing paren then it's the end of the list and is fine
|
||||
if p.eat(&token::CloseDelim(Delimiter::Parenthesis)) {
|
||||
break;
|
||||
}
|
||||
let span = opt_lit.map_or(p.token.span, |lit| lit.span);
|
||||
let mut err =
|
||||
p.sess.span_diagnostic.struct_span_err(span, "expected string literal");
|
||||
@ -432,9 +424,9 @@ fn parse_reg<'a>(
|
||||
ast::InlineAsmRegOrRegClass::Reg(symbol)
|
||||
}
|
||||
_ => {
|
||||
return Err(
|
||||
p.struct_span_err(p.token.span, "expected register class or explicit register")
|
||||
);
|
||||
return Err(p.sess.create_err(errors::ExpectedRegisterClassOrExplicitRegister {
|
||||
span: p.token.span,
|
||||
}));
|
||||
}
|
||||
};
|
||||
p.bump();
|
||||
|
@ -320,6 +320,7 @@ impl<'cx, 'a> Context<'cx, 'a> {
|
||||
| ExprKind::Underscore
|
||||
| ExprKind::While(_, _, _)
|
||||
| ExprKind::Yeet(_)
|
||||
| ExprKind::Become(_)
|
||||
| ExprKind::Yield(_) => {}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
//! Attributes injected into the crate root from command line using `-Z crate-attr`.
|
||||
|
||||
use crate::errors;
|
||||
use rustc_ast::attr::mk_attr;
|
||||
use rustc_ast::token;
|
||||
use rustc_ast::{self as ast, AttrItem, AttrStyle};
|
||||
@ -24,7 +25,9 @@ pub fn inject(krate: &mut ast::Crate, parse_sess: &ParseSess, attrs: &[String])
|
||||
};
|
||||
let end_span = parser.token.span;
|
||||
if parser.token != token::Eof {
|
||||
parse_sess.span_diagnostic.span_err(start_span.to(end_span), "invalid crate attribute");
|
||||
parse_sess
|
||||
.span_diagnostic
|
||||
.emit_err(errors::InvalidCrateAttr { span: start_span.to(end_span) });
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -18,7 +18,7 @@ pub fn expand_compile_error<'cx>(
|
||||
reason = "diagnostic message is specified by user"
|
||||
)]
|
||||
#[expect(rustc::untranslatable_diagnostic, reason = "diagnostic message is specified by user")]
|
||||
cx.span_err(sp, var.as_str());
|
||||
cx.span_err(sp, var.to_string());
|
||||
|
||||
DummyResult::any(sp)
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ pub fn expand_concat(
|
||||
accumulator.push_str(&b.to_string());
|
||||
}
|
||||
Ok(ast::LitKind::CStr(..)) => {
|
||||
cx.span_err(e.span, "cannot concatenate a C string literal");
|
||||
cx.emit_err(errors::ConcatCStrLit{ span: e.span});
|
||||
has_errors = true;
|
||||
}
|
||||
Ok(ast::LitKind::Byte(..) | ast::LitKind::ByteStr(..)) => {
|
||||
|
@ -21,7 +21,7 @@ fn invalid_type_err(
|
||||
Ok(ast::LitKind::CStr(_, _)) => {
|
||||
// FIXME(c_str_literals): should concatenation of C string literals
|
||||
// include the null bytes in the end?
|
||||
cx.span_err(span, "cannot concatenate C string literals");
|
||||
cx.emit_err(errors::ConcatCStrLit { span: span });
|
||||
}
|
||||
Ok(ast::LitKind::Char(_)) => {
|
||||
let sugg =
|
||||
|
@ -8,7 +8,7 @@ use rustc_feature::AttributeTemplate;
|
||||
use rustc_parse::validate_attr;
|
||||
use rustc_session::Session;
|
||||
use rustc_span::symbol::{sym, Ident};
|
||||
use rustc_span::Span;
|
||||
use rustc_span::{ErrorGuaranteed, Span};
|
||||
|
||||
pub(crate) struct Expander(pub bool);
|
||||
|
||||
@ -22,7 +22,7 @@ impl MultiItemModifier for Expander {
|
||||
_: bool,
|
||||
) -> ExpandResult<Vec<Annotatable>, Annotatable> {
|
||||
let sess = ecx.sess;
|
||||
if report_bad_target(sess, &item, span) {
|
||||
if report_bad_target(sess, &item, span).is_err() {
|
||||
// We don't want to pass inappropriate targets to derive macros to avoid
|
||||
// follow up errors, all other errors below are recoverable.
|
||||
return ExpandResult::Ready(vec![item]);
|
||||
@ -103,7 +103,11 @@ fn dummy_annotatable() -> Annotatable {
|
||||
})
|
||||
}
|
||||
|
||||
fn report_bad_target(sess: &Session, item: &Annotatable, span: Span) -> bool {
|
||||
fn report_bad_target(
|
||||
sess: &Session,
|
||||
item: &Annotatable,
|
||||
span: Span,
|
||||
) -> Result<(), ErrorGuaranteed> {
|
||||
let item_kind = match item {
|
||||
Annotatable::Item(item) => Some(&item.kind),
|
||||
Annotatable::Stmt(stmt) => match &stmt.kind {
|
||||
@ -116,9 +120,9 @@ fn report_bad_target(sess: &Session, item: &Annotatable, span: Span) -> bool {
|
||||
let bad_target =
|
||||
!matches!(item_kind, Some(ItemKind::Struct(..) | ItemKind::Enum(..) | ItemKind::Union(..)));
|
||||
if bad_target {
|
||||
sess.emit_err(errors::BadDeriveTarget { span, item: item.span() });
|
||||
return Err(sess.emit_err(errors::BadDeriveTarget { span, item: item.span() }));
|
||||
}
|
||||
bad_target
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn report_unexpected_meta_item_lit(sess: &Session, lit: &ast::MetaItemLit) {
|
||||
|
@ -68,7 +68,6 @@ pub fn expand_deriving_clone(
|
||||
_ => cx.span_bug(span, "`#[derive(Clone)]` on trait item or impl item"),
|
||||
}
|
||||
|
||||
let attrs = thin_vec![cx.attr_word(sym::inline, span)];
|
||||
let trait_def = TraitDef {
|
||||
span,
|
||||
path: path_std!(clone::Clone),
|
||||
@ -82,7 +81,7 @@ pub fn expand_deriving_clone(
|
||||
explicit_self: true,
|
||||
nonself_args: Vec::new(),
|
||||
ret_ty: Self_,
|
||||
attributes: attrs,
|
||||
attributes: thin_vec![cx.attr_word(sym::inline, span)],
|
||||
fieldless_variants_strategy: FieldlessVariantsStrategy::Default,
|
||||
combine_substructure: substructure,
|
||||
}],
|
||||
|
@ -18,11 +18,6 @@ pub fn expand_deriving_eq(
|
||||
is_const: bool,
|
||||
) {
|
||||
let span = cx.with_def_site_ctxt(span);
|
||||
let attrs = thin_vec![
|
||||
cx.attr_word(sym::inline, span),
|
||||
cx.attr_nested_word(sym::doc, sym::hidden, span),
|
||||
cx.attr_word(sym::no_coverage, span)
|
||||
];
|
||||
let trait_def = TraitDef {
|
||||
span,
|
||||
path: path_std!(cmp::Eq),
|
||||
@ -36,7 +31,11 @@ pub fn expand_deriving_eq(
|
||||
explicit_self: true,
|
||||
nonself_args: vec![],
|
||||
ret_ty: Unit,
|
||||
attributes: attrs,
|
||||
attributes: thin_vec![
|
||||
cx.attr_word(sym::inline, span),
|
||||
cx.attr_nested_word(sym::doc, sym::hidden, span),
|
||||
cx.attr_word(sym::no_coverage, span)
|
||||
],
|
||||
fieldless_variants_strategy: FieldlessVariantsStrategy::Unify,
|
||||
combine_substructure: combine_substructure(Box::new(|a, b, c| {
|
||||
cs_total_eq_assert(a, b, c)
|
||||
|
@ -15,7 +15,6 @@ pub fn expand_deriving_ord(
|
||||
push: &mut dyn FnMut(Annotatable),
|
||||
is_const: bool,
|
||||
) {
|
||||
let attrs = thin_vec![cx.attr_word(sym::inline, span)];
|
||||
let trait_def = TraitDef {
|
||||
span,
|
||||
path: path_std!(cmp::Ord),
|
||||
@ -29,7 +28,7 @@ pub fn expand_deriving_ord(
|
||||
explicit_self: true,
|
||||
nonself_args: vec![(self_ref(), sym::other)],
|
||||
ret_ty: Path(path_std!(cmp::Ordering)),
|
||||
attributes: attrs,
|
||||
attributes: thin_vec![cx.attr_word(sym::inline, span)],
|
||||
fieldless_variants_strategy: FieldlessVariantsStrategy::Unify,
|
||||
combine_substructure: combine_substructure(Box::new(|a, b, c| cs_cmp(a, b, c))),
|
||||
}],
|
||||
|
@ -82,14 +82,13 @@ pub fn expand_deriving_partial_eq(
|
||||
|
||||
// No need to generate `ne`, the default suffices, and not generating it is
|
||||
// faster.
|
||||
let attrs = thin_vec![cx.attr_word(sym::inline, span)];
|
||||
let methods = vec![MethodDef {
|
||||
name: sym::eq,
|
||||
generics: Bounds::empty(),
|
||||
explicit_self: true,
|
||||
nonself_args: vec![(self_ref(), sym::other)],
|
||||
ret_ty: Path(path_local!(bool)),
|
||||
attributes: attrs,
|
||||
attributes: thin_vec![cx.attr_word(sym::inline, span)],
|
||||
fieldless_variants_strategy: FieldlessVariantsStrategy::Unify,
|
||||
combine_substructure: combine_substructure(Box::new(|a, b, c| cs_eq(a, b, c))),
|
||||
}];
|
||||
|
@ -19,8 +19,6 @@ pub fn expand_deriving_partial_ord(
|
||||
let ret_ty =
|
||||
Path(Path::new_(pathvec_std!(option::Option), vec![Box::new(ordering_ty)], PathKind::Std));
|
||||
|
||||
let attrs = thin_vec![cx.attr_word(sym::inline, span)];
|
||||
|
||||
// Order in which to perform matching
|
||||
let tag_then_data = if let Annotatable::Item(item) = item
|
||||
&& let ItemKind::Enum(def, _) = &item.kind {
|
||||
@ -48,7 +46,7 @@ pub fn expand_deriving_partial_ord(
|
||||
explicit_self: true,
|
||||
nonself_args: vec![(self_ref(), sym::other)],
|
||||
ret_ty,
|
||||
attributes: attrs,
|
||||
attributes: thin_vec![cx.attr_word(sym::inline, span)],
|
||||
fieldless_variants_strategy: FieldlessVariantsStrategy::Unify,
|
||||
combine_substructure: combine_substructure(Box::new(|cx, span, substr| {
|
||||
cs_partial_cmp(cx, span, substr, tag_then_data)
|
||||
|
@ -20,7 +20,6 @@ pub fn expand_deriving_default(
|
||||
) {
|
||||
item.visit_with(&mut DetectNonVariantDefaultAttr { cx });
|
||||
|
||||
let attrs = thin_vec![cx.attr_word(sym::inline, span)];
|
||||
let trait_def = TraitDef {
|
||||
span,
|
||||
path: Path::new(vec![kw::Default, sym::Default]),
|
||||
@ -34,7 +33,7 @@ pub fn expand_deriving_default(
|
||||
explicit_self: false,
|
||||
nonself_args: Vec::new(),
|
||||
ret_ty: Self_,
|
||||
attributes: attrs,
|
||||
attributes: thin_vec![cx.attr_word(sym::inline, span)],
|
||||
fieldless_variants_strategy: FieldlessVariantsStrategy::Default,
|
||||
combine_substructure: combine_substructure(Box::new(|cx, trait_span, substr| {
|
||||
match substr.fields {
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::deriving::generic::ty::*;
|
||||
use crate::deriving::generic::*;
|
||||
use crate::deriving::{path_std, pathvec_std};
|
||||
use rustc_ast::{AttrVec, MetaItem, Mutability};
|
||||
use rustc_ast::{MetaItem, Mutability};
|
||||
use rustc_expand::base::{Annotatable, ExtCtxt};
|
||||
use rustc_span::symbol::sym;
|
||||
use rustc_span::Span;
|
||||
@ -33,7 +33,7 @@ pub fn expand_deriving_hash(
|
||||
explicit_self: true,
|
||||
nonself_args: vec![(Ref(Box::new(Path(arg)), Mutability::Mut), sym::state)],
|
||||
ret_ty: Unit,
|
||||
attributes: AttrVec::new(),
|
||||
attributes: thin_vec![cx.attr_word(sym::inline, span)],
|
||||
fieldless_variants_strategy: FieldlessVariantsStrategy::Unify,
|
||||
combine_substructure: combine_substructure(Box::new(|a, b, c| {
|
||||
hash_substructure(a, b, c)
|
||||
|
@ -87,6 +87,83 @@ pub(crate) struct ConcatBytestr {
|
||||
pub(crate) span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(builtin_macros_concat_c_str_lit)]
|
||||
pub(crate) struct ConcatCStrLit {
|
||||
#[primary_span]
|
||||
pub(crate) span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(builtin_macros_export_macro_rules)]
|
||||
pub(crate) struct ExportMacroRules {
|
||||
#[primary_span]
|
||||
pub(crate) span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(builtin_macros_proc_macro)]
|
||||
pub(crate) struct ProcMacro {
|
||||
#[primary_span]
|
||||
pub(crate) span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(builtin_macros_invalid_crate_attribute)]
|
||||
pub(crate) struct InvalidCrateAttr {
|
||||
#[primary_span]
|
||||
pub(crate) span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(builtin_macros_non_abi)]
|
||||
pub(crate) struct NonABI {
|
||||
#[primary_span]
|
||||
pub(crate) span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(builtin_macros_trace_macros)]
|
||||
pub(crate) struct TraceMacros {
|
||||
#[primary_span]
|
||||
pub(crate) span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(builtin_macros_bench_sig)]
|
||||
pub(crate) struct BenchSig {
|
||||
#[primary_span]
|
||||
pub(crate) span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(builtin_macros_test_arg_non_lifetime)]
|
||||
pub(crate) struct TestArgNonLifetime {
|
||||
#[primary_span]
|
||||
pub(crate) span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(builtin_macros_should_panic)]
|
||||
pub(crate) struct ShouldPanic {
|
||||
#[primary_span]
|
||||
pub(crate) span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(builtin_macros_test_args)]
|
||||
pub(crate) struct TestArgs {
|
||||
#[primary_span]
|
||||
pub(crate) span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(builtin_macros_alloc_must_statics)]
|
||||
pub(crate) struct AllocMustStatics {
|
||||
#[primary_span]
|
||||
pub(crate) span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(builtin_macros_concat_bytes_invalid)]
|
||||
pub(crate) struct ConcatBytesInvalid {
|
||||
@ -201,6 +278,10 @@ pub(crate) struct BadDeriveTarget {
|
||||
pub(crate) item: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(builtin_macros_tests_not_support)]
|
||||
pub(crate) struct TestsNotSupport {}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(builtin_macros_unexpected_lit, code = "E0777")]
|
||||
pub(crate) struct BadDeriveLit {
|
||||
@ -377,7 +458,7 @@ impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for EnvNotDefined {
|
||||
rustc::untranslatable_diagnostic,
|
||||
reason = "cannot translate user-provided messages"
|
||||
)]
|
||||
handler.struct_diagnostic(msg.as_str())
|
||||
handler.struct_diagnostic(msg.to_string())
|
||||
} else {
|
||||
handler.struct_diagnostic(crate::fluent_generated::builtin_macros_env_not_defined)
|
||||
};
|
||||
@ -732,3 +813,10 @@ pub(crate) struct TestRunnerNargs {
|
||||
#[primary_span]
|
||||
pub(crate) span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(builtin_macros_expected_register_class_or_explicit_register)]
|
||||
pub(crate) struct ExpectedRegisterClassOrExplicitRegister {
|
||||
#[primary_span]
|
||||
pub(crate) span: Span,
|
||||
}
|
||||
|
@ -554,9 +554,6 @@ fn report_missing_placeholders(
|
||||
fmt_span: Span,
|
||||
) {
|
||||
let mut diag = if let &[(span, named)] = &unused[..] {
|
||||
//let mut diag = ecx.struct_span_err(span, msg);
|
||||
//diag.span_label(span, msg);
|
||||
//diag
|
||||
ecx.create_err(errors::FormatUnusedArg { span, named })
|
||||
} else {
|
||||
let unused_labels =
|
||||
|
@ -1,5 +1,6 @@
|
||||
use crate::util::check_builtin_macro_attribute;
|
||||
|
||||
use crate::errors;
|
||||
use rustc_ast::expand::allocator::{
|
||||
global_fn_name, AllocatorMethod, AllocatorTy, ALLOCATOR_METHODS,
|
||||
};
|
||||
@ -34,7 +35,7 @@ pub fn expand(
|
||||
{
|
||||
(item, true, ecx.with_def_site_ctxt(ty.span))
|
||||
} else {
|
||||
ecx.sess.parse_sess.span_diagnostic.span_err(item.span(), "allocators must be statics");
|
||||
ecx.sess.parse_sess.span_diagnostic.emit_err(errors::AllocMustStatics{span: item.span()});
|
||||
return vec![orig_item];
|
||||
};
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
use crate::errors;
|
||||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::visit::{self, Visitor};
|
||||
use rustc_ast::{self as ast, attr, NodeId};
|
||||
@ -83,12 +84,7 @@ pub fn inject(
|
||||
impl<'a> CollectProcMacros<'a> {
|
||||
fn check_not_pub_in_root(&self, vis: &ast::Visibility, sp: Span) {
|
||||
if self.is_proc_macro_crate && self.in_root && vis.kind.is_pub() {
|
||||
self.handler.span_err(
|
||||
sp,
|
||||
"`proc-macro` crate types currently cannot export any items other \
|
||||
than functions tagged with `#[proc_macro]`, `#[proc_macro_derive]`, \
|
||||
or `#[proc_macro_attribute]`",
|
||||
);
|
||||
self.handler.emit_err(errors::ProcMacro { span: sp });
|
||||
}
|
||||
}
|
||||
|
||||
@ -157,9 +153,9 @@ impl<'a> Visitor<'a> for CollectProcMacros<'a> {
|
||||
fn visit_item(&mut self, item: &'a ast::Item) {
|
||||
if let ast::ItemKind::MacroDef(..) = item.kind {
|
||||
if self.is_proc_macro_crate && attr::contains_name(&item.attrs, sym::macro_export) {
|
||||
let msg =
|
||||
"cannot export macro_rules! macros from a `proc-macro` crate type currently";
|
||||
self.handler.span_err(self.source_map.guess_head_span(item.span), msg);
|
||||
self.handler.emit_err(errors::ExportMacroRules {
|
||||
span: self.source_map.guess_head_span(item.span),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,12 +3,12 @@ use crate::errors;
|
||||
/// Ideally, this code would be in libtest but for efficiency and error messages it lives here.
|
||||
use crate::util::{check_builtin_macro_attribute, warn_on_duplicate_attribute};
|
||||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::{self as ast, attr};
|
||||
use rustc_ast::{self as ast, attr, GenericParamKind};
|
||||
use rustc_ast_pretty::pprust;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_expand::base::*;
|
||||
use rustc_span::symbol::{sym, Ident, Symbol};
|
||||
use rustc_span::{FileNameDisplayPreference, Span};
|
||||
use rustc_span::{ErrorGuaranteed, FileNameDisplayPreference, Span};
|
||||
use std::iter;
|
||||
use thin_vec::{thin_vec, ThinVec};
|
||||
|
||||
@ -122,23 +122,26 @@ pub fn expand_test_or_bench(
|
||||
let ast::ItemKind::Fn(fn_) = &item.kind else {
|
||||
not_testable_error(cx, attr_sp, Some(&item));
|
||||
return if is_stmt {
|
||||
vec![Annotatable::Stmt(P(ast::Stmt {
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
span: item.span,
|
||||
kind: ast::StmtKind::Item(item),
|
||||
}))]
|
||||
vec![Annotatable::Stmt(P(cx.stmt_item(item.span, item)))]
|
||||
} else {
|
||||
vec![Annotatable::Item(item)]
|
||||
};
|
||||
};
|
||||
|
||||
// has_*_signature will report any errors in the type so compilation
|
||||
// check_*_signature will report any errors in the type so compilation
|
||||
// will fail. We shouldn't try to expand in this case because the errors
|
||||
// would be spurious.
|
||||
if (!is_bench && !has_test_signature(cx, &item))
|
||||
|| (is_bench && !has_bench_signature(cx, &item))
|
||||
{
|
||||
return vec![Annotatable::Item(item)];
|
||||
let check_result = if is_bench {
|
||||
check_bench_signature(cx, &item, &fn_)
|
||||
} else {
|
||||
check_test_signature(cx, &item, &fn_)
|
||||
};
|
||||
if check_result.is_err() {
|
||||
return if is_stmt {
|
||||
vec![Annotatable::Stmt(P(cx.stmt_item(item.span, item)))]
|
||||
} else {
|
||||
vec![Annotatable::Item(item)]
|
||||
};
|
||||
}
|
||||
|
||||
let sp = cx.with_def_site_ctxt(item.span);
|
||||
@ -523,75 +526,57 @@ fn test_type(cx: &ExtCtxt<'_>) -> TestType {
|
||||
}
|
||||
}
|
||||
|
||||
fn has_test_signature(cx: &ExtCtxt<'_>, i: &ast::Item) -> bool {
|
||||
fn check_test_signature(
|
||||
cx: &ExtCtxt<'_>,
|
||||
i: &ast::Item,
|
||||
f: &ast::Fn,
|
||||
) -> Result<(), ErrorGuaranteed> {
|
||||
let has_should_panic_attr = attr::contains_name(&i.attrs, sym::should_panic);
|
||||
let sd = &cx.sess.parse_sess.span_diagnostic;
|
||||
match &i.kind {
|
||||
ast::ItemKind::Fn(box ast::Fn { sig, generics, .. }) => {
|
||||
if let ast::Unsafe::Yes(span) = sig.header.unsafety {
|
||||
sd.emit_err(errors::TestBadFn { span: i.span, cause: span, kind: "unsafe" });
|
||||
return false;
|
||||
}
|
||||
if let ast::Async::Yes { span, .. } = sig.header.asyncness {
|
||||
sd.emit_err(errors::TestBadFn { span: i.span, cause: span, kind: "async" });
|
||||
return false;
|
||||
}
|
||||
|
||||
// If the termination trait is active, the compiler will check that the output
|
||||
// type implements the `Termination` trait as `libtest` enforces that.
|
||||
let has_output = match &sig.decl.output {
|
||||
ast::FnRetTy::Default(..) => false,
|
||||
ast::FnRetTy::Ty(t) if t.kind.is_unit() => false,
|
||||
_ => true,
|
||||
};
|
||||
|
||||
if !sig.decl.inputs.is_empty() {
|
||||
sd.span_err(i.span, "functions used as tests can not have any arguments");
|
||||
return false;
|
||||
}
|
||||
|
||||
match (has_output, has_should_panic_attr) {
|
||||
(true, true) => {
|
||||
sd.span_err(i.span, "functions using `#[should_panic]` must return `()`");
|
||||
false
|
||||
}
|
||||
(true, false) => {
|
||||
if !generics.params.is_empty() {
|
||||
sd.span_err(
|
||||
i.span,
|
||||
"functions used as tests must have signature fn() -> ()",
|
||||
);
|
||||
false
|
||||
} else {
|
||||
true
|
||||
}
|
||||
}
|
||||
(false, _) => true,
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
// should be unreachable because `is_test_fn_item` should catch all non-fn items
|
||||
debug_assert!(false);
|
||||
false
|
||||
}
|
||||
if let ast::Unsafe::Yes(span) = f.sig.header.unsafety {
|
||||
return Err(sd.emit_err(errors::TestBadFn { span: i.span, cause: span, kind: "unsafe" }));
|
||||
}
|
||||
}
|
||||
|
||||
fn has_bench_signature(cx: &ExtCtxt<'_>, i: &ast::Item) -> bool {
|
||||
let has_sig = match &i.kind {
|
||||
// N.B., inadequate check, but we're running
|
||||
// well before resolve, can't get too deep.
|
||||
ast::ItemKind::Fn(box ast::Fn { sig, .. }) => sig.decl.inputs.len() == 1,
|
||||
_ => false,
|
||||
if let ast::Async::Yes { span, .. } = f.sig.header.asyncness {
|
||||
return Err(sd.emit_err(errors::TestBadFn { span: i.span, cause: span, kind: "async" }));
|
||||
}
|
||||
|
||||
// If the termination trait is active, the compiler will check that the output
|
||||
// type implements the `Termination` trait as `libtest` enforces that.
|
||||
let has_output = match &f.sig.decl.output {
|
||||
ast::FnRetTy::Default(..) => false,
|
||||
ast::FnRetTy::Ty(t) if t.kind.is_unit() => false,
|
||||
_ => true,
|
||||
};
|
||||
|
||||
if !has_sig {
|
||||
cx.sess.parse_sess.span_diagnostic.span_err(
|
||||
i.span,
|
||||
"functions used as benches must have \
|
||||
signature `fn(&mut Bencher) -> impl Termination`",
|
||||
);
|
||||
if !f.sig.decl.inputs.is_empty() {
|
||||
return Err(sd.span_err(i.span, "functions used as tests can not have any arguments"));
|
||||
}
|
||||
|
||||
has_sig
|
||||
if has_should_panic_attr && has_output {
|
||||
return Err(sd.span_err(i.span, "functions using `#[should_panic]` must return `()`"));
|
||||
}
|
||||
|
||||
if f.generics.params.iter().any(|param| !matches!(param.kind, GenericParamKind::Lifetime)) {
|
||||
return Err(sd.span_err(
|
||||
i.span,
|
||||
"functions used as tests can not have any non-lifetime generic parameters",
|
||||
));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn check_bench_signature(
|
||||
cx: &ExtCtxt<'_>,
|
||||
i: &ast::Item,
|
||||
f: &ast::Fn,
|
||||
) -> Result<(), ErrorGuaranteed> {
|
||||
// N.B., inadequate check, but we're running
|
||||
// well before resolve, can't get too deep.
|
||||
if f.sig.decl.inputs.len() != 1 {
|
||||
return Err(cx.sess.parse_sess.span_diagnostic.emit_err(errors::BenchSig { span: i.span }));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
@ -63,10 +63,7 @@ pub fn inject(krate: &mut ast::Crate, sess: &Session, resolver: &mut dyn Resolve
|
||||
// Silently allow compiling with panic=abort on these platforms,
|
||||
// but with old behavior (abort if a test fails).
|
||||
} else {
|
||||
span_diagnostic.err(
|
||||
"building tests with panic=abort is not supported \
|
||||
without `-Zpanic_abort_tests`",
|
||||
);
|
||||
span_diagnostic.emit_err(errors::TestsNotSupport {});
|
||||
}
|
||||
PanicStrategy::Unwind
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
use crate::errors;
|
||||
use rustc_ast::tokenstream::{TokenStream, TokenTree};
|
||||
use rustc_expand::base::{self, ExtCtxt};
|
||||
use rustc_span::symbol::kw;
|
||||
@ -20,7 +21,7 @@ pub fn expand_trace_macros(
|
||||
};
|
||||
err |= cursor.next().is_some();
|
||||
if err {
|
||||
cx.span_err(sp, "trace_macros! accepts only `true` or `false`")
|
||||
cx.emit_err(errors::TraceMacros { span: sp });
|
||||
} else {
|
||||
cx.set_trace_macros(value);
|
||||
}
|
||||
|
@ -1,16 +1,16 @@
|
||||
task:
|
||||
name: freebsd
|
||||
freebsd_instance:
|
||||
image: freebsd-13-1-release-amd64
|
||||
image: freebsd-13-2-release-amd64
|
||||
setup_rust_script:
|
||||
- pkg install -y curl git bash
|
||||
- pkg install -y git bash
|
||||
- curl https://sh.rustup.rs -sSf --output rustup.sh
|
||||
- sh rustup.sh --default-toolchain none -y --profile=minimal
|
||||
target_cache:
|
||||
folder: target
|
||||
prepare_script:
|
||||
- . $HOME/.cargo/env
|
||||
- ./y.rs prepare
|
||||
- ./y.sh prepare
|
||||
test_script:
|
||||
- . $HOME/.cargo/env
|
||||
- ./y.rs test
|
||||
- ./y.sh test
|
||||
|
@ -46,12 +46,12 @@ jobs:
|
||||
run: rustup set default-host x86_64-pc-windows-gnu
|
||||
|
||||
- name: Prepare dependencies
|
||||
run: ./y.rs prepare
|
||||
run: ./y.sh prepare
|
||||
|
||||
- name: Build
|
||||
run: ./y.rs build --sysroot none
|
||||
run: ./y.sh build --sysroot none
|
||||
|
||||
- name: Test abi-cafe
|
||||
env:
|
||||
TARGET_TRIPLE: ${{ matrix.env.TARGET_TRIPLE }}
|
||||
run: ./y.rs abi-cafe
|
||||
run: ./y.sh abi-cafe
|
||||
|
@ -19,7 +19,7 @@ jobs:
|
||||
- name: Rustfmt
|
||||
run: |
|
||||
cargo fmt --check
|
||||
rustfmt --check build_system/mod.rs
|
||||
rustfmt --check build_system/main.rs
|
||||
rustfmt --check example/*
|
||||
|
||||
|
||||
@ -91,22 +91,52 @@ jobs:
|
||||
sudo apt-get install -y gcc-s390x-linux-gnu qemu-user
|
||||
|
||||
- name: Prepare dependencies
|
||||
run: ./y.rs prepare
|
||||
|
||||
- name: Build without unstable features
|
||||
env:
|
||||
TARGET_TRIPLE: ${{ matrix.env.TARGET_TRIPLE }}
|
||||
# This is the config rust-lang/rust uses for builds
|
||||
run: ./y.rs build --no-unstable-features
|
||||
run: ./y.sh prepare
|
||||
|
||||
- name: Build
|
||||
run: ./y.rs build --sysroot none
|
||||
run: ./y.sh build --sysroot none
|
||||
|
||||
- name: Test
|
||||
env:
|
||||
TARGET_TRIPLE: ${{ matrix.env.TARGET_TRIPLE }}
|
||||
run: ./y.rs test
|
||||
run: ./y.sh test
|
||||
|
||||
- name: Install LLVM standard library
|
||||
run: rustup target add ${{ matrix.env.TARGET_TRIPLE }}
|
||||
|
||||
# This is roughly config rust-lang/rust uses for testing
|
||||
- name: Test with LLVM sysroot
|
||||
# Skip native x86_64-pc-windows-gnu. It is way too slow and cross-compiled
|
||||
# x86_64-pc-windows-gnu covers at least part of the tests.
|
||||
if: matrix.os != 'windows-latest' || matrix.env.TARGET_TRIPLE != 'x86_64-pc-windows-gnu'
|
||||
env:
|
||||
TARGET_TRIPLE: ${{ matrix.env.TARGET_TRIPLE }}
|
||||
run: ./y.sh test --sysroot llvm --no-unstable-features
|
||||
|
||||
|
||||
# This job doesn't use cg_clif in any way. It checks that all cg_clif tests work with cg_llvm too.
|
||||
test_llvm:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 60
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Prepare dependencies
|
||||
run: ./y.rs prepare
|
||||
|
||||
- name: Disable JIT tests
|
||||
run: |
|
||||
sed -i 's/jit./#jit./' config.txt
|
||||
|
||||
- name: Test
|
||||
env:
|
||||
TARGET_TRIPLE: x86_64-unknown-linux-gnu
|
||||
run: ./y.rs test --use-backend llvm
|
||||
|
||||
bench:
|
||||
runs-on: ubuntu-latest
|
||||
@ -135,13 +165,13 @@ jobs:
|
||||
run: cargo install hyperfine || true
|
||||
|
||||
- name: Prepare dependencies
|
||||
run: ./y.rs prepare
|
||||
run: ./y.sh prepare
|
||||
|
||||
- name: Build
|
||||
run: CI_OPT=1 ./y.rs build --sysroot none
|
||||
run: CI_OPT=1 ./y.sh build --sysroot none
|
||||
|
||||
- name: Benchmark
|
||||
run: CI_OPT=1 ./y.rs bench
|
||||
run: CI_OPT=1 ./y.sh bench
|
||||
|
||||
|
||||
dist:
|
||||
@ -194,13 +224,13 @@ jobs:
|
||||
sudo apt-get install -y gcc-mingw-w64-x86-64 wine-stable
|
||||
|
||||
- name: Prepare dependencies
|
||||
run: ./y.rs prepare
|
||||
run: ./y.sh prepare
|
||||
|
||||
- name: Build backend
|
||||
run: CI_OPT=1 ./y.rs build --sysroot none
|
||||
run: CI_OPT=1 ./y.sh build --sysroot none
|
||||
|
||||
- name: Build sysroot
|
||||
run: CI_OPT=1 ./y.rs build
|
||||
run: CI_OPT=1 ./y.sh build
|
||||
|
||||
- name: Package prebuilt cg_clif
|
||||
run: tar cvfJ cg_clif.tar.xz dist
|
||||
|
@ -18,7 +18,7 @@ jobs:
|
||||
key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }}
|
||||
|
||||
- name: Prepare dependencies
|
||||
run: ./y.rs prepare
|
||||
run: ./y.sh prepare
|
||||
|
||||
- name: Test
|
||||
run: ./scripts/test_bootstrap.sh
|
||||
@ -38,7 +38,7 @@ jobs:
|
||||
key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }}
|
||||
|
||||
- name: Prepare dependencies
|
||||
run: ./y.rs prepare
|
||||
run: ./y.sh prepare
|
||||
|
||||
- name: Test
|
||||
run: ./scripts/test_rustc_tests.sh
|
||||
|
@ -6,9 +6,10 @@
|
||||
"rust-analyzer.imports.granularity.enforce": true,
|
||||
"rust-analyzer.imports.granularity.group": "module",
|
||||
"rust-analyzer.imports.prefix": "crate",
|
||||
"rust-analyzer.cargo.features": ["unstable-features", "__check_build_system_using_ra"],
|
||||
"rust-analyzer.cargo.features": ["unstable-features"],
|
||||
"rust-analyzer.linkedProjects": [
|
||||
"./Cargo.toml",
|
||||
"./build_system/Cargo.toml",
|
||||
{
|
||||
"crates": [
|
||||
{
|
||||
|
136
compiler/rustc_codegen_cranelift/Cargo.lock
generated
136
compiler/rustc_codegen_cranelift/Cargo.lock
generated
@ -19,6 +19,12 @@ version = "1.0.66"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "216261ddc8289130e551ddcd5ce8a064710c0d064a4d2895c67151c92b5443f6"
|
||||
|
||||
[[package]]
|
||||
name = "arbitrary"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2d098ff73c1ca148721f37baad5ea6a465a13f9573aba8641fbbbae8164a54e"
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.1.0"
|
||||
@ -37,12 +43,6 @@ version = "3.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba"
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
@ -51,23 +51,24 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-bforest"
|
||||
version = "0.95.1"
|
||||
version = "0.96.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1277fbfa94bc82c8ec4af2ded3e639d49ca5f7f3c7eeab2c66accd135ece4e70"
|
||||
checksum = "9b6160c0a96253993b79fb7e0983534a4515ecf666120ddf8f92068114997ebc"
|
||||
dependencies = [
|
||||
"cranelift-entity",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-codegen"
|
||||
version = "0.95.1"
|
||||
version = "0.96.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c6e8c31ad3b2270e9aeec38723888fe1b0ace3bea2b06b3f749ccf46661d3220"
|
||||
checksum = "7b38da5f63562e42f3c929d7c76871098e5ad12c8ab44b0659ffc529f22a5b3a"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"cranelift-bforest",
|
||||
"cranelift-codegen-meta",
|
||||
"cranelift-codegen-shared",
|
||||
"cranelift-control",
|
||||
"cranelift-entity",
|
||||
"cranelift-isle",
|
||||
"gimli",
|
||||
@ -80,30 +81,39 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-codegen-meta"
|
||||
version = "0.95.1"
|
||||
version = "0.96.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c8ac5ac30d62b2d66f12651f6b606dbdfd9c2cfd0908de6b387560a277c5c9da"
|
||||
checksum = "011371e213e163b55dd9e8404b3f2d9fa52cd14dc2f3dc5b83e61ffceff126db"
|
||||
dependencies = [
|
||||
"cranelift-codegen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-codegen-shared"
|
||||
version = "0.95.1"
|
||||
version = "0.96.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd82b8b376247834b59ed9bdc0ddeb50f517452827d4a11bccf5937b213748b8"
|
||||
checksum = "1bf97dde7f5ad571161cdd203a2c9c88682ef669830aea3c14ea5d164ef8bb43"
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-control"
|
||||
version = "0.96.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fd9a9254aee733b0f2b68e5eaaf0337ad53cb23252a056c10a35370551be8d40"
|
||||
dependencies = [
|
||||
"arbitrary",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-entity"
|
||||
version = "0.95.1"
|
||||
version = "0.96.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "40099d38061b37e505e63f89bab52199037a72b931ad4868d9089ff7268660b0"
|
||||
checksum = "baf39a33ee39479d1337cd9333f3c09786c5a0ca1ec509edcaf9d1346d5de0e5"
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-frontend"
|
||||
version = "0.95.1"
|
||||
version = "0.96.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "64a25d9d0a0ae3079c463c34115ec59507b4707175454f0eee0891e83e30e82d"
|
||||
checksum = "65e260b92a193a0a2dccc3938f133d9532e7dcfe8d03e36bf8b7d3518c1c1793"
|
||||
dependencies = [
|
||||
"cranelift-codegen",
|
||||
"log",
|
||||
@ -113,18 +123,19 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-isle"
|
||||
version = "0.95.1"
|
||||
version = "0.96.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "80de6a7d0486e4acbd5f9f87ec49912bf4c8fb6aea00087b989685460d4469ba"
|
||||
checksum = "9446c8e1aadfcdacee1a49592bc2c25d1d9bf5484782c163e7f5485c92cd3c1c"
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-jit"
|
||||
version = "0.95.1"
|
||||
version = "0.96.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3ca96b05988aa057eda09a817a6e31915fabd7f476b513123aff08053cd193dd"
|
||||
checksum = "689a6df165d0f860c1e1a3d53c28944e2743c3e9ee4c678cf190fe60ad7a6ef5"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"cranelift-codegen",
|
||||
"cranelift-control",
|
||||
"cranelift-entity",
|
||||
"cranelift-module",
|
||||
"cranelift-native",
|
||||
@ -138,19 +149,20 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-module"
|
||||
version = "0.95.1"
|
||||
version = "0.96.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e5112c0be9cc5da064e0620570d67852f11ce44f2e572a58ecf7f11df73978b8"
|
||||
checksum = "0b1402d6ff1695b429536b2eaa126db560fc94c375ed0e9cfb15051fc07427f7"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"cranelift-codegen",
|
||||
"cranelift-control",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-native"
|
||||
version = "0.95.1"
|
||||
version = "0.96.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bb6b03e0e03801c4b3fd8ce0758a94750c07a44e7944cc0ffbf0d3f2e7c79b00"
|
||||
checksum = "eac916f3c5aff4b817e42fc2e682292b931495b3fe2603d5e3c3cf602d74e344"
|
||||
dependencies = [
|
||||
"cranelift-codegen",
|
||||
"libc",
|
||||
@ -159,12 +171,13 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-object"
|
||||
version = "0.95.1"
|
||||
version = "0.96.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "48ed1b37d0972abe804cb5bf2b35f3a76a276ebbe148e3a726d8e31042790978"
|
||||
checksum = "23860f4cd064017f2108e6bc5d25660a77cd6eea77f1ac0756870a00abb12e93"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"cranelift-codegen",
|
||||
"cranelift-control",
|
||||
"cranelift-module",
|
||||
"log",
|
||||
"object",
|
||||
@ -186,15 +199,6 @@ version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7"
|
||||
|
||||
[[package]]
|
||||
name = "fxhash"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gimli"
|
||||
version = "0.27.2"
|
||||
@ -273,9 +277,9 @@ checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
|
||||
|
||||
[[package]]
|
||||
name = "object"
|
||||
version = "0.30.3"
|
||||
version = "0.30.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ea86265d3d3dcb6a27fc51bd29a4bf387fae9d2986b823079d4986af253eb439"
|
||||
checksum = "03b4680b86d9cfafba8fc491dc9b6df26b68cf40e9e6cd73909194759a63c385"
|
||||
dependencies = [
|
||||
"crc32fast",
|
||||
"hashbrown 0.13.2",
|
||||
@ -291,12 +295,13 @@ checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860"
|
||||
|
||||
[[package]]
|
||||
name = "regalloc2"
|
||||
version = "0.6.1"
|
||||
version = "0.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "80535183cae11b149d618fbd3c37e38d7cda589d82d7769e196ca9a9042d7621"
|
||||
checksum = "d4a52e724646c6c0800fc456ec43b4165d2f91fba88ceaca06d9e0b400023478"
|
||||
dependencies = [
|
||||
"fxhash",
|
||||
"hashbrown 0.13.2",
|
||||
"log",
|
||||
"rustc-hash",
|
||||
"slice-group-by",
|
||||
"smallvec",
|
||||
]
|
||||
@ -313,6 +318,12 @@ dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-hash"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
|
||||
|
||||
[[package]]
|
||||
name = "rustc_codegen_cranelift"
|
||||
version = "0.1.0"
|
||||
@ -327,7 +338,6 @@ dependencies = [
|
||||
"indexmap",
|
||||
"libloading",
|
||||
"object",
|
||||
"once_cell",
|
||||
"smallvec",
|
||||
"target-lexicon",
|
||||
]
|
||||
@ -364,9 +374,9 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
||||
|
||||
[[package]]
|
||||
name = "wasmtime-jit-icache-coherence"
|
||||
version = "8.0.1"
|
||||
version = "9.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aecae978b13f7f67efb23bd827373ace4578f2137ec110bbf6a4a7cde4121bbd"
|
||||
checksum = "7d90933b781e1cef7656baed671c7a90bdba0c1c694e04fdd4124419308f5cbb"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
@ -397,18 +407,18 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.45.0"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0"
|
||||
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
|
||||
dependencies = [
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.42.1"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e2522491fbfcd58cc84d47aeb2958948c4b8982e9a2d8a2a35bbaed431390e7"
|
||||
checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc",
|
||||
@ -421,42 +431,42 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.42.1"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608"
|
||||
checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.42.1"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7"
|
||||
checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.42.1"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640"
|
||||
checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.42.1"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605"
|
||||
checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.42.1"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45"
|
||||
checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.42.1"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463"
|
||||
checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.42.1"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd"
|
||||
checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"
|
||||
|
@ -3,31 +3,23 @@ name = "rustc_codegen_cranelift"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[[bin]]
|
||||
# This is used just to teach rust-analyzer how to check the build system. required-features is used
|
||||
# to disable it for regular builds.
|
||||
name = "y"
|
||||
path = "./y.rs"
|
||||
required-features = ["__check_build_system_using_ra"]
|
||||
|
||||
[lib]
|
||||
crate-type = ["dylib"]
|
||||
|
||||
[dependencies]
|
||||
# These have to be in sync with each other
|
||||
cranelift-codegen = { version = "0.95.1", features = ["unwind", "all-arch"] }
|
||||
cranelift-frontend = { version = "0.95.1" }
|
||||
cranelift-module = { version = "0.95.1" }
|
||||
cranelift-native = { version = "0.95.1" }
|
||||
cranelift-jit = { version = "0.95.1", optional = true }
|
||||
cranelift-object = { version = "0.95.1" }
|
||||
cranelift-codegen = { version = "0.96.1", features = ["unwind", "all-arch"] }
|
||||
cranelift-frontend = { version = "0.96.1" }
|
||||
cranelift-module = { version = "0.96.1" }
|
||||
cranelift-native = { version = "0.96.1" }
|
||||
cranelift-jit = { version = "0.96.1", optional = true }
|
||||
cranelift-object = { version = "0.96.1" }
|
||||
target-lexicon = "0.12.0"
|
||||
gimli = { version = "0.27.2", default-features = false, features = ["write"]}
|
||||
object = { version = "0.30.3", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] }
|
||||
|
||||
indexmap = "1.9.3"
|
||||
libloading = { version = "0.7.3", optional = true }
|
||||
once_cell = "1.10.0"
|
||||
smallvec = "1.8.1"
|
||||
|
||||
[patch.crates-io]
|
||||
@ -46,7 +38,6 @@ smallvec = "1.8.1"
|
||||
unstable-features = ["jit", "inline_asm"]
|
||||
jit = ["cranelift-jit", "libloading"]
|
||||
inline_asm = []
|
||||
__check_build_system_using_ra = []
|
||||
|
||||
[package.metadata.rust-analyzer]
|
||||
rustc_private = true
|
||||
|
@ -10,8 +10,8 @@ If not please open an issue.
|
||||
```bash
|
||||
$ git clone https://github.com/bjorn3/rustc_codegen_cranelift
|
||||
$ cd rustc_codegen_cranelift
|
||||
$ ./y.rs prepare
|
||||
$ ./y.rs build
|
||||
$ ./y.sh prepare
|
||||
$ ./y.sh build
|
||||
```
|
||||
|
||||
To run the test suite replace the last command with:
|
||||
@ -20,9 +20,14 @@ To run the test suite replace the last command with:
|
||||
$ ./test.sh
|
||||
```
|
||||
|
||||
For more docs on how to build and test see [build_system/usage.txt](build_system/usage.txt) or the help message of `./y.rs`.
|
||||
For more docs on how to build and test see [build_system/usage.txt](build_system/usage.txt) or the help message of `./y.sh`.
|
||||
|
||||
## Precompiled builds
|
||||
|
||||
Alternatively you can download a pre built version from the [releases] page.
|
||||
Extract the `dist` directory in the archive anywhere you want.
|
||||
If you want to use `cargo clif build` instead of having to specify the full path to the `cargo-clif` executable, you can add the `bin` subdirectory of the extracted `dist` directory to your `PATH`.
|
||||
(tutorial [for Windows](https://stackoverflow.com/a/44272417), and [for Linux/MacOS](https://unix.stackexchange.com/questions/26047/how-to-correctly-add-a-path-to-path/26059#26059)).
|
||||
|
||||
[releases]: https://github.com/bjorn3/rustc_codegen_cranelift/releases/tag/dev
|
||||
|
||||
@ -30,7 +35,7 @@ Alternatively you can download a pre built version from the [releases] page.
|
||||
|
||||
rustc_codegen_cranelift can be used as a near-drop-in replacement for `cargo build` or `cargo run` for existing projects.
|
||||
|
||||
Assuming `$cg_clif_dir` is the directory you cloned this repo into and you followed the instructions (`y.rs prepare` and `y.rs build` or `test.sh`).
|
||||
Assuming `$cg_clif_dir` is the directory you cloned this repo into and you followed the instructions (`y.sh prepare` and `y.sh build` or `test.sh`).
|
||||
|
||||
In the directory with your project (where you can do the usual `cargo build`), run:
|
||||
|
||||
@ -42,6 +47,32 @@ This will build your project with rustc_codegen_cranelift instead of the usual L
|
||||
|
||||
For additional ways to use rustc_codegen_cranelift like the JIT mode see [usage.md](docs/usage.md).
|
||||
|
||||
## Building and testing with changes in rustc code
|
||||
|
||||
This is useful when changing code in `rustc_codegen_cranelift` as part of changing [main Rust repository](https://github.com/rust-lang/rust/).
|
||||
This can happen, for example, when you are implementing a new compiler intrinsic.
|
||||
|
||||
Instruction below uses `$RustCheckoutDir` as substitute for any folder where you cloned Rust repository.
|
||||
|
||||
You need to do this steps to successfully compile and use the cranelift backend with your changes in rustc code:
|
||||
|
||||
1. `cd $RustCheckoutDir`
|
||||
2. Run `python x.py setup` and choose option for compiler (`b`).
|
||||
3. Build compiler and necessary tools: `python x.py build --stage=2 compiler library/std src/tools/rustdoc src/tools/rustfmt`
|
||||
* (Optional) You can also build cargo by adding `src/tools/cargo` to previous command.
|
||||
4. Copy exectutable files from `./build/host/stage2-tools/<your hostname triple>/release`
|
||||
to `./build/host/stage2/bin/`. Note that you would need to do this every time you rebuilt `rust` repository.
|
||||
5. Copy cargo from another toolchain: `cp $(rustup which cargo) .build/<your hostname triple>/stage2/bin/cargo`
|
||||
* Another option is to build it at step 3 and copy with other executables at step 4.
|
||||
6. Link your new `rustc` to toolchain: `rustup toolchain link stage2 ./build/host/stage2/`.
|
||||
7. (Windows only) compile y.rs: `rustc +stage2 -O y.rs`.
|
||||
8. You need to prefix every `./y.rs` (or `y` if you built `y.rs`) command by `rustup run stage2` to make cg_clif use your local changes in rustc.
|
||||
|
||||
* `rustup run stage2 ./y.rs prepare`
|
||||
* `rustup run stage2 ./y.rs build`
|
||||
* (Optional) run tests: `rustup run stage2 ./y.rs test`
|
||||
9. Now you can use your cg_clif build to compile other Rust programs, e.g. you can open any Rust crate and run commands like `$RustCheckoutDir/compiler/rustc_codegen_cranelift/dist/cargo-clif build --release`.
|
||||
|
||||
## Configuration
|
||||
|
||||
See the documentation on the `BackendConfig` struct in [config.rs](src/config.rs) for all
|
||||
|
@ -1,323 +0,0 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "addr2line"
|
||||
version = "0.19.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"gimli",
|
||||
"rustc-std-workspace-alloc",
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "adler"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "alloc"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.79"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "compiler_builtins"
|
||||
version = "0.1.91"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "571298a3cce7e2afbd3d61abb91a18667d5ab25993ec577a88ee8ac45f00cc3a"
|
||||
dependencies = [
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "core"
|
||||
version = "0.0.0"
|
||||
|
||||
[[package]]
|
||||
name = "dlmalloc"
|
||||
version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "203540e710bfadb90e5e29930baf5d10270cec1f43ab34f46f78b147b2de715a"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"libc",
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fortanix-sgx-abi"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "57cafc2274c10fab234f176b25903ce17e690fca7597090d50880e047a0389c5"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getopts"
|
||||
version = "0.2.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5"
|
||||
dependencies = [
|
||||
"rustc-std-workspace-core",
|
||||
"rustc-std-workspace-std",
|
||||
"unicode-width",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gimli"
|
||||
version = "0.27.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ad0a93d233ebf96623465aad4046a8d3aa4da22d4f4beba5388838c8a434bbb4"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"rustc-std-workspace-alloc",
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.12.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"rustc-std-workspace-alloc",
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"rustc-std-workspace-alloc",
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.142"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6a987beff54b60ffa6d51982e1aa1146bc42f19bd26be28b0586f252fccf5317"
|
||||
dependencies = [
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.6.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa"
|
||||
dependencies = [
|
||||
"adler",
|
||||
"compiler_builtins",
|
||||
"rustc-std-workspace-alloc",
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "object"
|
||||
version = "0.30.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ea86265d3d3dcb6a27fc51bd29a4bf387fae9d2986b823079d4986af253eb439"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"memchr",
|
||||
"rustc-std-workspace-alloc",
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "panic_abort"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"alloc",
|
||||
"cfg-if",
|
||||
"compiler_builtins",
|
||||
"core",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "panic_unwind"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"alloc",
|
||||
"cfg-if",
|
||||
"compiler_builtins",
|
||||
"core",
|
||||
"libc",
|
||||
"unwind",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc_macro"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"core",
|
||||
"std",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-demangle"
|
||||
version = "0.1.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-std-workspace-alloc"
|
||||
version = "1.99.0"
|
||||
dependencies = [
|
||||
"alloc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-std-workspace-core"
|
||||
version = "1.99.0"
|
||||
dependencies = [
|
||||
"core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-std-workspace-std"
|
||||
version = "1.99.0"
|
||||
dependencies = [
|
||||
"std",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "std"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"addr2line",
|
||||
"alloc",
|
||||
"cfg-if",
|
||||
"compiler_builtins",
|
||||
"core",
|
||||
"dlmalloc",
|
||||
"fortanix-sgx-abi",
|
||||
"hashbrown",
|
||||
"hermit-abi",
|
||||
"libc",
|
||||
"miniz_oxide",
|
||||
"object",
|
||||
"panic_abort",
|
||||
"panic_unwind",
|
||||
"rustc-demangle",
|
||||
"std_detect",
|
||||
"unwind",
|
||||
"wasi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "std_detect"
|
||||
version = "0.1.5"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"compiler_builtins",
|
||||
"libc",
|
||||
"rustc-std-workspace-alloc",
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sysroot"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"alloc",
|
||||
"compiler_builtins",
|
||||
"core",
|
||||
"std",
|
||||
"test",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "test"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"core",
|
||||
"getopts",
|
||||
"panic_abort",
|
||||
"panic_unwind",
|
||||
"proc_macro",
|
||||
"std",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-width"
|
||||
version = "0.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"rustc-std-workspace-core",
|
||||
"rustc-std-workspace-std",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unwind"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"cfg-if",
|
||||
"compiler_builtins",
|
||||
"core",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.11.0+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"rustc-std-workspace-alloc",
|
||||
"rustc-std-workspace-core",
|
||||
]
|
@ -1,35 +0,0 @@
|
||||
[package]
|
||||
name = "sysroot"
|
||||
version = "0.0.0"
|
||||
|
||||
[dependencies]
|
||||
core = { path = "./sysroot_src/library/core" }
|
||||
alloc = { path = "./sysroot_src/library/alloc" }
|
||||
std = { path = "./sysroot_src/library/std", features = ["panic_unwind", "backtrace"] }
|
||||
test = { path = "./sysroot_src/library/test" }
|
||||
|
||||
compiler_builtins = { version = "0.1.87", default-features = false, features = ["no-asm"] }
|
||||
|
||||
[patch.crates-io]
|
||||
rustc-std-workspace-core = { path = "./sysroot_src/library/rustc-std-workspace-core" }
|
||||
rustc-std-workspace-alloc = { path = "./sysroot_src/library/rustc-std-workspace-alloc" }
|
||||
rustc-std-workspace-std = { path = "./sysroot_src/library/rustc-std-workspace-std" }
|
||||
|
||||
[profile.dev]
|
||||
lto = "off"
|
||||
|
||||
[profile.release]
|
||||
debug = true
|
||||
incremental = true
|
||||
lto = "off"
|
||||
|
||||
# Mandatory for correctly compiling compiler-builtins
|
||||
[profile.dev.package.compiler_builtins]
|
||||
debug-assertions = false
|
||||
overflow-checks = false
|
||||
codegen-units = 10000
|
||||
|
||||
[profile.release.package.compiler_builtins]
|
||||
debug-assertions = false
|
||||
overflow-checks = false
|
||||
codegen-units = 10000
|
@ -1 +0,0 @@
|
||||
#![no_std]
|
7
compiler/rustc_codegen_cranelift/build_system/Cargo.lock
generated
Normal file
7
compiler/rustc_codegen_cranelift/build_system/Cargo.lock
generated
Normal file
@ -0,0 +1,7 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "y"
|
||||
version = "0.1.0"
|
13
compiler/rustc_codegen_cranelift/build_system/Cargo.toml
Normal file
13
compiler/rustc_codegen_cranelift/build_system/Cargo.toml
Normal file
@ -0,0 +1,13 @@
|
||||
[package]
|
||||
name = "y"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[[bin]]
|
||||
name = "y"
|
||||
path = "main.rs"
|
||||
|
||||
[features]
|
||||
unstable-features = [] # for rust-analyzer
|
||||
|
||||
# Do not add any dependencies
|
@ -1,25 +1,29 @@
|
||||
use std::path::Path;
|
||||
|
||||
use super::build_sysroot;
|
||||
use super::path::Dirs;
|
||||
use super::prepare::GitRepo;
|
||||
use super::utils::{spawn_and_wait, CargoProject, Compiler};
|
||||
use super::SysrootKind;
|
||||
use super::{CodegenBackend, SysrootKind};
|
||||
|
||||
static ABI_CAFE_REPO: GitRepo =
|
||||
GitRepo::github("Gankra", "abi-cafe", "4c6dc8c9c687e2b3a760ff2176ce236872b37212", "abi-cafe");
|
||||
static ABI_CAFE_REPO: GitRepo = GitRepo::github(
|
||||
"Gankra",
|
||||
"abi-cafe",
|
||||
"4c6dc8c9c687e2b3a760ff2176ce236872b37212",
|
||||
"588df6d66abbe105",
|
||||
"abi-cafe",
|
||||
);
|
||||
|
||||
static ABI_CAFE: CargoProject = CargoProject::new(&ABI_CAFE_REPO.source_dir(), "abi_cafe");
|
||||
static ABI_CAFE: CargoProject = CargoProject::new(&ABI_CAFE_REPO.source_dir(), "abi_cafe_target");
|
||||
|
||||
pub(crate) fn run(
|
||||
channel: &str,
|
||||
sysroot_kind: SysrootKind,
|
||||
dirs: &Dirs,
|
||||
cg_clif_dylib: &Path,
|
||||
cg_clif_dylib: &CodegenBackend,
|
||||
rustup_toolchain_name: Option<&str>,
|
||||
bootstrap_host_compiler: &Compiler,
|
||||
) {
|
||||
ABI_CAFE_REPO.fetch(dirs);
|
||||
spawn_and_wait(ABI_CAFE.fetch("cargo", &bootstrap_host_compiler.rustc, dirs));
|
||||
ABI_CAFE_REPO.patch(dirs);
|
||||
|
||||
eprintln!("Building sysroot for abi-cafe");
|
||||
build_sysroot::build_sysroot(
|
||||
@ -28,6 +32,7 @@ pub(crate) fn run(
|
||||
sysroot_kind,
|
||||
cg_clif_dylib,
|
||||
bootstrap_host_compiler,
|
||||
rustup_toolchain_name,
|
||||
bootstrap_host_compiler.triple.clone(),
|
||||
);
|
||||
|
||||
@ -40,7 +45,14 @@ pub(crate) fn run(
|
||||
cmd.arg("--pairs");
|
||||
cmd.args(pairs);
|
||||
cmd.arg("--add-rustc-codegen-backend");
|
||||
cmd.arg(format!("cgclif:{}", cg_clif_dylib.display()));
|
||||
match cg_clif_dylib {
|
||||
CodegenBackend::Local(path) => {
|
||||
cmd.arg(format!("cgclif:{}", path.display()));
|
||||
}
|
||||
CodegenBackend::Builtin(name) => {
|
||||
cmd.arg(format!("cgclif:{name}"));
|
||||
}
|
||||
}
|
||||
cmd.current_dir(ABI_CAFE.source_dir(dirs));
|
||||
|
||||
spawn_and_wait(cmd);
|
||||
|
@ -1,26 +1,19 @@
|
||||
use std::env;
|
||||
use std::fs;
|
||||
use std::path::Path;
|
||||
|
||||
use super::path::{Dirs, RelPath};
|
||||
use super::prepare::GitRepo;
|
||||
use super::rustc_info::get_file_name;
|
||||
use super::utils::{hyperfine_command, spawn_and_wait, CargoProject, Compiler};
|
||||
use super::utils::{hyperfine_command, spawn_and_wait, Compiler};
|
||||
|
||||
static SIMPLE_RAYTRACER_REPO: GitRepo = GitRepo::github(
|
||||
"ebobby",
|
||||
"simple-raytracer",
|
||||
"804a7a21b9e673a482797aa289a18ed480e4d813",
|
||||
"ad6f59a2331a3f56",
|
||||
"<none>",
|
||||
);
|
||||
|
||||
// Use a separate target dir for the initial LLVM build to reduce unnecessary recompiles
|
||||
static SIMPLE_RAYTRACER_LLVM: CargoProject =
|
||||
CargoProject::new(&SIMPLE_RAYTRACER_REPO.source_dir(), "simple_raytracer_llvm");
|
||||
|
||||
static SIMPLE_RAYTRACER: CargoProject =
|
||||
CargoProject::new(&SIMPLE_RAYTRACER_REPO.source_dir(), "simple_raytracer");
|
||||
|
||||
pub(crate) fn benchmark(dirs: &Dirs, bootstrap_host_compiler: &Compiler) {
|
||||
benchmark_simple_raytracer(dirs, bootstrap_host_compiler);
|
||||
}
|
||||
@ -32,35 +25,17 @@ fn benchmark_simple_raytracer(dirs: &Dirs, bootstrap_host_compiler: &Compiler) {
|
||||
std::process::exit(1);
|
||||
}
|
||||
|
||||
if !SIMPLE_RAYTRACER_REPO.source_dir().to_path(dirs).exists() {
|
||||
SIMPLE_RAYTRACER_REPO.fetch(dirs);
|
||||
spawn_and_wait(SIMPLE_RAYTRACER.fetch(
|
||||
&bootstrap_host_compiler.cargo,
|
||||
&bootstrap_host_compiler.rustc,
|
||||
dirs,
|
||||
));
|
||||
}
|
||||
|
||||
eprintln!("[LLVM BUILD] simple-raytracer");
|
||||
let build_cmd = SIMPLE_RAYTRACER_LLVM.build(bootstrap_host_compiler, dirs);
|
||||
spawn_and_wait(build_cmd);
|
||||
fs::copy(
|
||||
SIMPLE_RAYTRACER_LLVM
|
||||
.target_dir(dirs)
|
||||
.join(&bootstrap_host_compiler.triple)
|
||||
.join("debug")
|
||||
.join(get_file_name("main", "bin")),
|
||||
RelPath::BUILD.to_path(dirs).join(get_file_name("raytracer_cg_llvm", "bin")),
|
||||
)
|
||||
.unwrap();
|
||||
SIMPLE_RAYTRACER_REPO.fetch(dirs);
|
||||
SIMPLE_RAYTRACER_REPO.patch(dirs);
|
||||
|
||||
let bench_runs = env::var("BENCH_RUNS").unwrap_or_else(|_| "10".to_string()).parse().unwrap();
|
||||
|
||||
eprintln!("[BENCH COMPILE] ebobby/simple-raytracer");
|
||||
let cargo_clif =
|
||||
RelPath::DIST.to_path(dirs).join(get_file_name("cargo_clif", "bin").replace('_', "-"));
|
||||
let manifest_path = SIMPLE_RAYTRACER.manifest_path(dirs);
|
||||
let target_dir = SIMPLE_RAYTRACER.target_dir(dirs);
|
||||
let cargo_clif = RelPath::DIST
|
||||
.to_path(dirs)
|
||||
.join(get_file_name(&bootstrap_host_compiler.rustc, "cargo_clif", "bin").replace('_', "-"));
|
||||
let manifest_path = SIMPLE_RAYTRACER_REPO.source_dir().to_path(dirs).join("Cargo.toml");
|
||||
let target_dir = RelPath::BUILD.join("simple_raytracer").to_path(dirs);
|
||||
|
||||
let clean_cmd = format!(
|
||||
"RUSTC=rustc cargo clean --manifest-path {manifest_path} --target-dir {target_dir}",
|
||||
@ -68,35 +43,52 @@ fn benchmark_simple_raytracer(dirs: &Dirs, bootstrap_host_compiler: &Compiler) {
|
||||
target_dir = target_dir.display(),
|
||||
);
|
||||
let llvm_build_cmd = format!(
|
||||
"RUSTC=rustc cargo build --manifest-path {manifest_path} --target-dir {target_dir}",
|
||||
"RUSTC=rustc cargo build --manifest-path {manifest_path} --target-dir {target_dir} && (rm build/raytracer_cg_llvm || true) && ln build/simple_raytracer/debug/main build/raytracer_cg_llvm",
|
||||
manifest_path = manifest_path.display(),
|
||||
target_dir = target_dir.display(),
|
||||
);
|
||||
let clif_build_cmd = format!(
|
||||
"RUSTC=rustc {cargo_clif} build --manifest-path {manifest_path} --target-dir {target_dir}",
|
||||
"RUSTC=rustc {cargo_clif} build --manifest-path {manifest_path} --target-dir {target_dir} && (rm build/raytracer_cg_clif || true) && ln build/simple_raytracer/debug/main build/raytracer_cg_clif",
|
||||
cargo_clif = cargo_clif.display(),
|
||||
manifest_path = manifest_path.display(),
|
||||
target_dir = target_dir.display(),
|
||||
);
|
||||
let clif_build_opt_cmd = format!(
|
||||
"RUSTC=rustc {cargo_clif} build --manifest-path {manifest_path} --target-dir {target_dir} --release && (rm build/raytracer_cg_clif_opt || true) && ln build/simple_raytracer/release/main build/raytracer_cg_clif_opt",
|
||||
cargo_clif = cargo_clif.display(),
|
||||
manifest_path = manifest_path.display(),
|
||||
target_dir = target_dir.display(),
|
||||
);
|
||||
|
||||
let bench_compile =
|
||||
hyperfine_command(1, bench_runs, Some(&clean_cmd), &llvm_build_cmd, &clif_build_cmd);
|
||||
let bench_compile = hyperfine_command(
|
||||
1,
|
||||
bench_runs,
|
||||
Some(&clean_cmd),
|
||||
&[&llvm_build_cmd, &clif_build_cmd, &clif_build_opt_cmd],
|
||||
);
|
||||
|
||||
spawn_and_wait(bench_compile);
|
||||
|
||||
eprintln!("[BENCH RUN] ebobby/simple-raytracer");
|
||||
fs::copy(
|
||||
target_dir.join("debug").join(get_file_name("main", "bin")),
|
||||
RelPath::BUILD.to_path(dirs).join(get_file_name("raytracer_cg_clif", "bin")),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let mut bench_run = hyperfine_command(
|
||||
0,
|
||||
bench_runs,
|
||||
None,
|
||||
Path::new(".").join(get_file_name("raytracer_cg_llvm", "bin")).to_str().unwrap(),
|
||||
Path::new(".").join(get_file_name("raytracer_cg_clif", "bin")).to_str().unwrap(),
|
||||
&[
|
||||
Path::new(".")
|
||||
.join(get_file_name(&bootstrap_host_compiler.rustc, "raytracer_cg_llvm", "bin"))
|
||||
.to_str()
|
||||
.unwrap(),
|
||||
Path::new(".")
|
||||
.join(get_file_name(&bootstrap_host_compiler.rustc, "raytracer_cg_clif", "bin"))
|
||||
.to_str()
|
||||
.unwrap(),
|
||||
Path::new(".")
|
||||
.join(get_file_name(&bootstrap_host_compiler.rustc, "raytracer_cg_clif_opt", "bin"))
|
||||
.to_str()
|
||||
.unwrap(),
|
||||
],
|
||||
);
|
||||
bench_run.current_dir(RelPath::BUILD.to_path(dirs));
|
||||
spawn_and_wait(bench_run);
|
||||
|
@ -3,7 +3,7 @@ use std::path::PathBuf;
|
||||
|
||||
use super::path::{Dirs, RelPath};
|
||||
use super::rustc_info::get_file_name;
|
||||
use super::utils::{is_ci, is_ci_opt, CargoProject, Compiler};
|
||||
use super::utils::{is_ci, is_ci_opt, maybe_incremental, CargoProject, Compiler};
|
||||
|
||||
pub(crate) static CG_CLIF: CargoProject = CargoProject::new(&RelPath::SOURCE, "cg_clif");
|
||||
|
||||
@ -14,8 +14,7 @@ pub(crate) fn build_backend(
|
||||
use_unstable_features: bool,
|
||||
) -> PathBuf {
|
||||
let mut cmd = CG_CLIF.build(&bootstrap_host_compiler, dirs);
|
||||
|
||||
cmd.env("CARGO_BUILD_INCREMENTAL", "true"); // Force incr comp even in release mode
|
||||
maybe_incremental(&mut cmd);
|
||||
|
||||
let mut rustflags = env::var("RUSTFLAGS").unwrap_or_default();
|
||||
|
||||
@ -23,11 +22,9 @@ pub(crate) fn build_backend(
|
||||
// Deny warnings on CI
|
||||
rustflags += " -Dwarnings";
|
||||
|
||||
// Disabling incr comp reduces cache size and incr comp doesn't save as much on CI anyway
|
||||
cmd.env("CARGO_BUILD_INCREMENTAL", "false");
|
||||
|
||||
if !is_ci_opt() {
|
||||
cmd.env("CARGO_PROFILE_RELEASE_DEBUG_ASSERTIONS", "true");
|
||||
cmd.env("CARGO_PROFILE_RELEASE_OVERFLOW_CHECKS", "true");
|
||||
}
|
||||
}
|
||||
|
||||
@ -52,5 +49,5 @@ pub(crate) fn build_backend(
|
||||
.target_dir(dirs)
|
||||
.join(&bootstrap_host_compiler.triple)
|
||||
.join(channel)
|
||||
.join(get_file_name("rustc_codegen_cranelift", "dylib"))
|
||||
.join(get_file_name(&bootstrap_host_compiler.rustc, "rustc_codegen_cranelift", "dylib"))
|
||||
}
|
||||
|
@ -1,11 +1,13 @@
|
||||
use std::fs;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process::{self, Command};
|
||||
use std::process::Command;
|
||||
|
||||
use super::path::{Dirs, RelPath};
|
||||
use super::rustc_info::{get_file_name, get_rustc_version, get_toolchain_name};
|
||||
use super::utils::{remove_dir_if_exists, spawn_and_wait, try_hard_link, CargoProject, Compiler};
|
||||
use super::SysrootKind;
|
||||
use super::rustc_info::get_file_name;
|
||||
use super::utils::{
|
||||
maybe_incremental, remove_dir_if_exists, spawn_and_wait, try_hard_link, CargoProject, Compiler,
|
||||
};
|
||||
use super::{CodegenBackend, SysrootKind};
|
||||
|
||||
static DIST_DIR: RelPath = RelPath::DIST;
|
||||
static BIN_DIR: RelPath = RelPath::DIST.join("bin");
|
||||
@ -15,8 +17,9 @@ pub(crate) fn build_sysroot(
|
||||
dirs: &Dirs,
|
||||
channel: &str,
|
||||
sysroot_kind: SysrootKind,
|
||||
cg_clif_dylib_src: &Path,
|
||||
cg_clif_dylib_src: &CodegenBackend,
|
||||
bootstrap_host_compiler: &Compiler,
|
||||
rustup_toolchain_name: Option<&str>,
|
||||
target_triple: String,
|
||||
) -> Compiler {
|
||||
eprintln!("[BUILD] sysroot {:?}", sysroot_kind);
|
||||
@ -27,32 +30,52 @@ pub(crate) fn build_sysroot(
|
||||
|
||||
let is_native = bootstrap_host_compiler.triple == target_triple;
|
||||
|
||||
// Copy the backend
|
||||
let cg_clif_dylib_path = if cfg!(windows) {
|
||||
// Windows doesn't have rpath support, so the cg_clif dylib needs to be next to the
|
||||
// binaries.
|
||||
BIN_DIR
|
||||
} else {
|
||||
LIB_DIR
|
||||
}
|
||||
.to_path(dirs)
|
||||
.join(cg_clif_dylib_src.file_name().unwrap());
|
||||
try_hard_link(cg_clif_dylib_src, &cg_clif_dylib_path);
|
||||
let cg_clif_dylib_path = match cg_clif_dylib_src {
|
||||
CodegenBackend::Local(src_path) => {
|
||||
// Copy the backend
|
||||
let cg_clif_dylib_path = if cfg!(windows) {
|
||||
// Windows doesn't have rpath support, so the cg_clif dylib needs to be next to the
|
||||
// binaries.
|
||||
BIN_DIR
|
||||
} else {
|
||||
LIB_DIR
|
||||
}
|
||||
.to_path(dirs)
|
||||
.join(src_path.file_name().unwrap());
|
||||
try_hard_link(src_path, &cg_clif_dylib_path);
|
||||
CodegenBackend::Local(cg_clif_dylib_path)
|
||||
}
|
||||
CodegenBackend::Builtin(name) => CodegenBackend::Builtin(name.clone()),
|
||||
};
|
||||
|
||||
// Build and copy rustc and cargo wrappers
|
||||
let wrapper_base_name = get_file_name("____", "bin");
|
||||
let toolchain_name = get_toolchain_name();
|
||||
let wrapper_base_name = get_file_name(&bootstrap_host_compiler.rustc, "____", "bin");
|
||||
for wrapper in ["rustc-clif", "rustdoc-clif", "cargo-clif"] {
|
||||
let wrapper_name = wrapper_base_name.replace("____", wrapper);
|
||||
|
||||
let mut build_cargo_wrapper_cmd = Command::new(&bootstrap_host_compiler.rustc);
|
||||
let wrapper_path = DIST_DIR.to_path(dirs).join(&wrapper_name);
|
||||
build_cargo_wrapper_cmd
|
||||
.env("TOOLCHAIN_NAME", toolchain_name.clone())
|
||||
.arg(RelPath::SCRIPTS.to_path(dirs).join(&format!("{wrapper}.rs")))
|
||||
.arg("-o")
|
||||
.arg(&wrapper_path)
|
||||
.arg("-Cstrip=debuginfo");
|
||||
if let Some(rustup_toolchain_name) = &rustup_toolchain_name {
|
||||
build_cargo_wrapper_cmd
|
||||
.env("TOOLCHAIN_NAME", rustup_toolchain_name)
|
||||
.env_remove("CARGO")
|
||||
.env_remove("RUSTC")
|
||||
.env_remove("RUSTDOC");
|
||||
} else {
|
||||
build_cargo_wrapper_cmd
|
||||
.env_remove("TOOLCHAIN_NAME")
|
||||
.env("CARGO", &bootstrap_host_compiler.cargo)
|
||||
.env("RUSTC", &bootstrap_host_compiler.rustc)
|
||||
.env("RUSTDOC", &bootstrap_host_compiler.rustdoc);
|
||||
}
|
||||
if let CodegenBackend::Builtin(name) = cg_clif_dylib_src {
|
||||
build_cargo_wrapper_cmd.env("BUILTIN_BACKEND", name);
|
||||
}
|
||||
spawn_and_wait(build_cargo_wrapper_cmd);
|
||||
try_hard_link(wrapper_path, BIN_DIR.to_path(dirs).join(wrapper_name));
|
||||
}
|
||||
@ -134,12 +157,9 @@ impl SysrootTarget {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) static ORIG_BUILD_SYSROOT: RelPath = RelPath::SOURCE.join("build_sysroot");
|
||||
pub(crate) static BUILD_SYSROOT: RelPath = RelPath::DOWNLOAD.join("sysroot");
|
||||
pub(crate) static SYSROOT_RUSTC_VERSION: RelPath = BUILD_SYSROOT.join("rustc_version");
|
||||
pub(crate) static SYSROOT_SRC: RelPath = BUILD_SYSROOT.join("sysroot_src");
|
||||
pub(crate) static STDLIB_SRC: RelPath = RelPath::BUILD.join("stdlib");
|
||||
pub(crate) static STANDARD_LIBRARY: CargoProject =
|
||||
CargoProject::new(&BUILD_SYSROOT, "build_sysroot");
|
||||
CargoProject::new(&STDLIB_SRC.join("library/sysroot"), "stdlib_target");
|
||||
pub(crate) static RTSTARTUP_SYSROOT: RelPath = RelPath::BUILD.join("rtstartup");
|
||||
|
||||
#[must_use]
|
||||
@ -147,7 +167,7 @@ fn build_sysroot_for_triple(
|
||||
dirs: &Dirs,
|
||||
channel: &str,
|
||||
compiler: Compiler,
|
||||
cg_clif_dylib_path: &Path,
|
||||
cg_clif_dylib_path: &CodegenBackend,
|
||||
sysroot_kind: SysrootKind,
|
||||
) -> SysrootTarget {
|
||||
match sysroot_kind {
|
||||
@ -155,7 +175,7 @@ fn build_sysroot_for_triple(
|
||||
.unwrap_or(SysrootTarget { triple: compiler.triple, libs: vec![] }),
|
||||
SysrootKind::Llvm => build_llvm_sysroot_for_triple(compiler),
|
||||
SysrootKind::Clif => {
|
||||
build_clif_sysroot_for_triple(dirs, channel, compiler, &cg_clif_dylib_path)
|
||||
build_clif_sysroot_for_triple(dirs, channel, compiler, cg_clif_dylib_path)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -199,26 +219,8 @@ fn build_clif_sysroot_for_triple(
|
||||
dirs: &Dirs,
|
||||
channel: &str,
|
||||
mut compiler: Compiler,
|
||||
cg_clif_dylib_path: &Path,
|
||||
cg_clif_dylib_path: &CodegenBackend,
|
||||
) -> SysrootTarget {
|
||||
match fs::read_to_string(SYSROOT_RUSTC_VERSION.to_path(dirs)) {
|
||||
Err(e) => {
|
||||
eprintln!("Failed to get rustc version for patched sysroot source: {}", e);
|
||||
eprintln!("Hint: Try `./y.rs prepare` to patch the sysroot source");
|
||||
process::exit(1);
|
||||
}
|
||||
Ok(source_version) => {
|
||||
let rustc_version = get_rustc_version(&compiler.rustc);
|
||||
if source_version != rustc_version {
|
||||
eprintln!("The patched sysroot source is outdated");
|
||||
eprintln!("Source version: {}", source_version.trim());
|
||||
eprintln!("Rustc version: {}", rustc_version.trim());
|
||||
eprintln!("Hint: Try `./y.rs prepare` to update the patched sysroot source");
|
||||
process::exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut target_libs = SysrootTarget { triple: compiler.triple.clone(), libs: vec![] };
|
||||
|
||||
if let Some(rtstartup_target_libs) = build_rtstartup(dirs, &compiler) {
|
||||
@ -237,19 +239,28 @@ fn build_clif_sysroot_for_triple(
|
||||
|
||||
// Build sysroot
|
||||
let mut rustflags = " -Zforce-unstable-if-unmarked -Cpanic=abort".to_string();
|
||||
rustflags.push_str(&format!(" -Zcodegen-backend={}", cg_clif_dylib_path.to_str().unwrap()));
|
||||
match cg_clif_dylib_path {
|
||||
CodegenBackend::Local(path) => {
|
||||
rustflags.push_str(&format!(" -Zcodegen-backend={}", path.to_str().unwrap()));
|
||||
}
|
||||
CodegenBackend::Builtin(name) => {
|
||||
rustflags.push_str(&format!(" -Zcodegen-backend={name}"));
|
||||
}
|
||||
};
|
||||
// Necessary for MinGW to find rsbegin.o and rsend.o
|
||||
rustflags
|
||||
.push_str(&format!(" --sysroot={}", RTSTARTUP_SYSROOT.to_path(dirs).to_str().unwrap()));
|
||||
.push_str(&format!(" --sysroot {}", RTSTARTUP_SYSROOT.to_path(dirs).to_str().unwrap()));
|
||||
if channel == "release" {
|
||||
rustflags.push_str(" -Zmir-opt-level=3");
|
||||
}
|
||||
compiler.rustflags += &rustflags;
|
||||
let mut build_cmd = STANDARD_LIBRARY.build(&compiler, dirs);
|
||||
maybe_incremental(&mut build_cmd);
|
||||
if channel == "release" {
|
||||
build_cmd.arg("--release");
|
||||
}
|
||||
build_cmd.arg("--locked");
|
||||
build_cmd.arg("--features").arg("compiler-builtins-no-asm backtrace panic-unwind");
|
||||
build_cmd.env("CARGO_PROFILE_RELEASE_DEBUG", "true");
|
||||
build_cmd.env("__CARGO_DEFAULT_LIB_METADATA", "cg_clif");
|
||||
if compiler.triple.contains("apple") {
|
||||
build_cmd.env("CARGO_PROFILE_RELEASE_SPLIT_DEBUGINFO", "packed");
|
||||
@ -272,13 +283,17 @@ fn build_clif_sysroot_for_triple(
|
||||
}
|
||||
|
||||
fn build_rtstartup(dirs: &Dirs, compiler: &Compiler) -> Option<SysrootTarget> {
|
||||
if !super::config::get_bool("keep_sysroot") {
|
||||
super::prepare::prepare_stdlib(dirs, &compiler.rustc);
|
||||
}
|
||||
|
||||
if !compiler.triple.ends_with("windows-gnu") {
|
||||
return None;
|
||||
}
|
||||
|
||||
RTSTARTUP_SYSROOT.ensure_fresh(dirs);
|
||||
|
||||
let rtstartup_src = SYSROOT_SRC.to_path(dirs).join("library").join("rtstartup");
|
||||
let rtstartup_src = STDLIB_SRC.to_path(dirs).join("library").join("rtstartup");
|
||||
let mut target_libs = SysrootTarget { triple: compiler.triple.clone(), libs: vec![] };
|
||||
|
||||
for file in ["rsbegin", "rsend"] {
|
||||
|
272
compiler/rustc_codegen_cranelift/build_system/main.rs
Normal file
272
compiler/rustc_codegen_cranelift/build_system/main.rs
Normal file
@ -0,0 +1,272 @@
|
||||
#![warn(rust_2018_idioms)]
|
||||
#![warn(unused_lifetimes)]
|
||||
#![warn(unreachable_pub)]
|
||||
|
||||
use std::env;
|
||||
use std::path::PathBuf;
|
||||
use std::process;
|
||||
|
||||
use self::utils::{is_ci, is_ci_opt, Compiler};
|
||||
|
||||
mod abi_cafe;
|
||||
mod bench;
|
||||
mod build_backend;
|
||||
mod build_sysroot;
|
||||
mod config;
|
||||
mod path;
|
||||
mod prepare;
|
||||
mod rustc_info;
|
||||
mod tests;
|
||||
mod utils;
|
||||
|
||||
fn usage() {
|
||||
eprintln!("{}", include_str!("usage.txt"));
|
||||
}
|
||||
|
||||
macro_rules! arg_error {
|
||||
($($err:tt)*) => {{
|
||||
eprintln!($($err)*);
|
||||
usage();
|
||||
std::process::exit(1);
|
||||
}};
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Debug)]
|
||||
enum Command {
|
||||
Prepare,
|
||||
Build,
|
||||
Test,
|
||||
AbiCafe,
|
||||
Bench,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
enum SysrootKind {
|
||||
None,
|
||||
Clif,
|
||||
Llvm,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
enum CodegenBackend {
|
||||
Local(PathBuf),
|
||||
Builtin(String),
|
||||
}
|
||||
|
||||
fn main() {
|
||||
if env::var("RUST_BACKTRACE").is_err() {
|
||||
env::set_var("RUST_BACKTRACE", "1");
|
||||
}
|
||||
env::set_var("CG_CLIF_DISABLE_INCR_CACHE", "1");
|
||||
|
||||
if is_ci() {
|
||||
// Disabling incr comp reduces cache size and incr comp doesn't save as much on CI anyway
|
||||
env::set_var("CARGO_BUILD_INCREMENTAL", "false");
|
||||
|
||||
if !is_ci_opt() {
|
||||
// Enable the Cranelift verifier
|
||||
env::set_var("CG_CLIF_ENABLE_VERIFIER", "1");
|
||||
}
|
||||
}
|
||||
|
||||
let mut args = env::args().skip(1);
|
||||
let command = match args.next().as_deref() {
|
||||
Some("prepare") => Command::Prepare,
|
||||
Some("build") => Command::Build,
|
||||
Some("test") => Command::Test,
|
||||
Some("abi-cafe") => Command::AbiCafe,
|
||||
Some("bench") => Command::Bench,
|
||||
Some(flag) if flag.starts_with('-') => arg_error!("Expected command found flag {}", flag),
|
||||
Some(command) => arg_error!("Unknown command {}", command),
|
||||
None => {
|
||||
usage();
|
||||
process::exit(0);
|
||||
}
|
||||
};
|
||||
|
||||
let mut out_dir = PathBuf::from(".");
|
||||
let mut download_dir = None;
|
||||
let mut channel = "release";
|
||||
let mut sysroot_kind = SysrootKind::Clif;
|
||||
let mut use_unstable_features = true;
|
||||
let mut frozen = false;
|
||||
let mut skip_tests = vec![];
|
||||
let mut use_backend = None;
|
||||
while let Some(arg) = args.next().as_deref() {
|
||||
match arg {
|
||||
"--out-dir" => {
|
||||
out_dir = PathBuf::from(args.next().unwrap_or_else(|| {
|
||||
arg_error!("--out-dir requires argument");
|
||||
}));
|
||||
}
|
||||
"--download-dir" => {
|
||||
download_dir = Some(PathBuf::from(args.next().unwrap_or_else(|| {
|
||||
arg_error!("--download-dir requires argument");
|
||||
})));
|
||||
}
|
||||
"--debug" => channel = "debug",
|
||||
"--sysroot" => {
|
||||
sysroot_kind = match args.next().as_deref() {
|
||||
Some("none") => SysrootKind::None,
|
||||
Some("clif") => SysrootKind::Clif,
|
||||
Some("llvm") => SysrootKind::Llvm,
|
||||
Some(arg) => arg_error!("Unknown sysroot kind {}", arg),
|
||||
None => arg_error!("--sysroot requires argument"),
|
||||
}
|
||||
}
|
||||
"--no-unstable-features" => use_unstable_features = false,
|
||||
"--frozen" => frozen = true,
|
||||
"--skip-test" => {
|
||||
// FIXME check that all passed in tests actually exist
|
||||
skip_tests.push(args.next().unwrap_or_else(|| {
|
||||
arg_error!("--skip-test requires argument");
|
||||
}));
|
||||
}
|
||||
"--use-backend" => {
|
||||
use_backend = Some(match args.next() {
|
||||
Some(name) => name,
|
||||
None => arg_error!("--use-backend requires argument"),
|
||||
});
|
||||
}
|
||||
flag if flag.starts_with("-") => arg_error!("Unknown flag {}", flag),
|
||||
arg => arg_error!("Unexpected argument {}", arg),
|
||||
}
|
||||
}
|
||||
|
||||
let current_dir = std::env::current_dir().unwrap();
|
||||
out_dir = current_dir.join(out_dir);
|
||||
|
||||
if command == Command::Prepare {
|
||||
prepare::prepare(&path::Dirs {
|
||||
source_dir: current_dir.clone(),
|
||||
download_dir: download_dir
|
||||
.map(|dir| current_dir.join(dir))
|
||||
.unwrap_or_else(|| out_dir.join("download")),
|
||||
build_dir: PathBuf::from("dummy_do_not_use"),
|
||||
dist_dir: PathBuf::from("dummy_do_not_use"),
|
||||
frozen,
|
||||
});
|
||||
process::exit(0);
|
||||
}
|
||||
|
||||
let rustup_toolchain_name = match (env::var("CARGO"), env::var("RUSTC"), env::var("RUSTDOC")) {
|
||||
(Ok(_), Ok(_), Ok(_)) => None,
|
||||
(Err(_), Err(_), Err(_)) => Some(rustc_info::get_toolchain_name()),
|
||||
_ => {
|
||||
eprintln!("All of CARGO, RUSTC and RUSTDOC need to be set or none must be set");
|
||||
process::exit(1);
|
||||
}
|
||||
};
|
||||
let bootstrap_host_compiler = {
|
||||
let cargo = rustc_info::get_cargo_path();
|
||||
let rustc = rustc_info::get_rustc_path();
|
||||
let rustdoc = rustc_info::get_rustdoc_path();
|
||||
let triple = std::env::var("HOST_TRIPLE")
|
||||
.ok()
|
||||
.or_else(|| config::get_value("host"))
|
||||
.unwrap_or_else(|| rustc_info::get_host_triple(&rustc));
|
||||
Compiler {
|
||||
cargo,
|
||||
rustc,
|
||||
rustdoc,
|
||||
rustflags: String::new(),
|
||||
rustdocflags: String::new(),
|
||||
triple,
|
||||
runner: vec![],
|
||||
}
|
||||
};
|
||||
let target_triple = std::env::var("TARGET_TRIPLE")
|
||||
.ok()
|
||||
.or_else(|| config::get_value("target"))
|
||||
.unwrap_or_else(|| bootstrap_host_compiler.triple.clone());
|
||||
|
||||
let dirs = path::Dirs {
|
||||
source_dir: current_dir.clone(),
|
||||
download_dir: download_dir
|
||||
.map(|dir| current_dir.join(dir))
|
||||
.unwrap_or_else(|| out_dir.join("download")),
|
||||
build_dir: out_dir.join("build"),
|
||||
dist_dir: out_dir.join("dist"),
|
||||
frozen,
|
||||
};
|
||||
|
||||
path::RelPath::BUILD.ensure_exists(&dirs);
|
||||
|
||||
{
|
||||
// Make sure we always explicitly specify the target dir
|
||||
let target =
|
||||
path::RelPath::BUILD.join("target_dir_should_be_set_explicitly").to_path(&dirs);
|
||||
env::set_var("CARGO_TARGET_DIR", &target);
|
||||
let _ = std::fs::remove_file(&target);
|
||||
std::fs::File::create(target).unwrap();
|
||||
}
|
||||
|
||||
env::set_var("RUSTC", "rustc_should_be_set_explicitly");
|
||||
env::set_var("RUSTDOC", "rustdoc_should_be_set_explicitly");
|
||||
|
||||
let cg_clif_dylib = if let Some(name) = use_backend {
|
||||
CodegenBackend::Builtin(name)
|
||||
} else {
|
||||
CodegenBackend::Local(build_backend::build_backend(
|
||||
&dirs,
|
||||
channel,
|
||||
&bootstrap_host_compiler,
|
||||
use_unstable_features,
|
||||
))
|
||||
};
|
||||
match command {
|
||||
Command::Prepare => {
|
||||
// Handled above
|
||||
}
|
||||
Command::Test => {
|
||||
tests::run_tests(
|
||||
&dirs,
|
||||
channel,
|
||||
sysroot_kind,
|
||||
use_unstable_features,
|
||||
&skip_tests.iter().map(|test| &**test).collect::<Vec<_>>(),
|
||||
&cg_clif_dylib,
|
||||
&bootstrap_host_compiler,
|
||||
rustup_toolchain_name.as_deref(),
|
||||
target_triple.clone(),
|
||||
);
|
||||
}
|
||||
Command::AbiCafe => {
|
||||
if bootstrap_host_compiler.triple != target_triple {
|
||||
eprintln!("Abi-cafe doesn't support cross-compilation");
|
||||
process::exit(1);
|
||||
}
|
||||
abi_cafe::run(
|
||||
channel,
|
||||
sysroot_kind,
|
||||
&dirs,
|
||||
&cg_clif_dylib,
|
||||
rustup_toolchain_name.as_deref(),
|
||||
&bootstrap_host_compiler,
|
||||
);
|
||||
}
|
||||
Command::Build => {
|
||||
build_sysroot::build_sysroot(
|
||||
&dirs,
|
||||
channel,
|
||||
sysroot_kind,
|
||||
&cg_clif_dylib,
|
||||
&bootstrap_host_compiler,
|
||||
rustup_toolchain_name.as_deref(),
|
||||
target_triple,
|
||||
);
|
||||
}
|
||||
Command::Bench => {
|
||||
build_sysroot::build_sysroot(
|
||||
&dirs,
|
||||
channel,
|
||||
sysroot_kind,
|
||||
&cg_clif_dylib,
|
||||
&bootstrap_host_compiler,
|
||||
rustup_toolchain_name.as_deref(),
|
||||
target_triple,
|
||||
);
|
||||
bench::benchmark(&dirs, &bootstrap_host_compiler);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,193 +0,0 @@
|
||||
use std::env;
|
||||
use std::path::PathBuf;
|
||||
use std::process;
|
||||
|
||||
use self::utils::{is_ci, is_ci_opt, Compiler};
|
||||
|
||||
mod abi_cafe;
|
||||
mod bench;
|
||||
mod build_backend;
|
||||
mod build_sysroot;
|
||||
mod config;
|
||||
mod path;
|
||||
mod prepare;
|
||||
mod rustc_info;
|
||||
mod tests;
|
||||
mod utils;
|
||||
|
||||
fn usage() {
|
||||
eprintln!("{}", include_str!("usage.txt"));
|
||||
}
|
||||
|
||||
macro_rules! arg_error {
|
||||
($($err:tt)*) => {{
|
||||
eprintln!($($err)*);
|
||||
usage();
|
||||
std::process::exit(1);
|
||||
}};
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Debug)]
|
||||
enum Command {
|
||||
Prepare,
|
||||
Build,
|
||||
Test,
|
||||
AbiCafe,
|
||||
Bench,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub(crate) enum SysrootKind {
|
||||
None,
|
||||
Clif,
|
||||
Llvm,
|
||||
}
|
||||
|
||||
pub(crate) fn main() {
|
||||
if env::var("RUST_BACKTRACE").is_err() {
|
||||
env::set_var("RUST_BACKTRACE", "1");
|
||||
}
|
||||
env::set_var("CG_CLIF_DISABLE_INCR_CACHE", "1");
|
||||
|
||||
if is_ci() {
|
||||
// Disabling incr comp reduces cache size and incr comp doesn't save as much on CI anyway
|
||||
env::set_var("CARGO_BUILD_INCREMENTAL", "false");
|
||||
|
||||
if !is_ci_opt() {
|
||||
// Enable the Cranelift verifier
|
||||
env::set_var("CG_CLIF_ENABLE_VERIFIER", "1");
|
||||
}
|
||||
}
|
||||
|
||||
let mut args = env::args().skip(1);
|
||||
let command = match args.next().as_deref() {
|
||||
Some("prepare") => Command::Prepare,
|
||||
Some("build") => Command::Build,
|
||||
Some("test") => Command::Test,
|
||||
Some("abi-cafe") => Command::AbiCafe,
|
||||
Some("bench") => Command::Bench,
|
||||
Some(flag) if flag.starts_with('-') => arg_error!("Expected command found flag {}", flag),
|
||||
Some(command) => arg_error!("Unknown command {}", command),
|
||||
None => {
|
||||
usage();
|
||||
process::exit(0);
|
||||
}
|
||||
};
|
||||
|
||||
let mut out_dir = PathBuf::from(".");
|
||||
let mut channel = "release";
|
||||
let mut sysroot_kind = SysrootKind::Clif;
|
||||
let mut use_unstable_features = true;
|
||||
while let Some(arg) = args.next().as_deref() {
|
||||
match arg {
|
||||
"--out-dir" => {
|
||||
out_dir = PathBuf::from(args.next().unwrap_or_else(|| {
|
||||
arg_error!("--out-dir requires argument");
|
||||
}))
|
||||
}
|
||||
"--debug" => channel = "debug",
|
||||
"--sysroot" => {
|
||||
sysroot_kind = match args.next().as_deref() {
|
||||
Some("none") => SysrootKind::None,
|
||||
Some("clif") => SysrootKind::Clif,
|
||||
Some("llvm") => SysrootKind::Llvm,
|
||||
Some(arg) => arg_error!("Unknown sysroot kind {}", arg),
|
||||
None => arg_error!("--sysroot requires argument"),
|
||||
}
|
||||
}
|
||||
"--no-unstable-features" => use_unstable_features = false,
|
||||
flag if flag.starts_with("-") => arg_error!("Unknown flag {}", flag),
|
||||
arg => arg_error!("Unexpected argument {}", arg),
|
||||
}
|
||||
}
|
||||
|
||||
let bootstrap_host_compiler = Compiler::bootstrap_with_triple(
|
||||
std::env::var("HOST_TRIPLE")
|
||||
.ok()
|
||||
.or_else(|| config::get_value("host"))
|
||||
.unwrap_or_else(|| rustc_info::get_host_triple()),
|
||||
);
|
||||
let target_triple = std::env::var("TARGET_TRIPLE")
|
||||
.ok()
|
||||
.or_else(|| config::get_value("target"))
|
||||
.unwrap_or_else(|| bootstrap_host_compiler.triple.clone());
|
||||
|
||||
// FIXME allow changing the location of these dirs using cli arguments
|
||||
let current_dir = std::env::current_dir().unwrap();
|
||||
out_dir = current_dir.join(out_dir);
|
||||
let dirs = path::Dirs {
|
||||
source_dir: current_dir.clone(),
|
||||
download_dir: out_dir.join("download"),
|
||||
build_dir: out_dir.join("build"),
|
||||
dist_dir: out_dir.join("dist"),
|
||||
};
|
||||
|
||||
path::RelPath::BUILD.ensure_exists(&dirs);
|
||||
|
||||
{
|
||||
// Make sure we always explicitly specify the target dir
|
||||
let target =
|
||||
path::RelPath::BUILD.join("target_dir_should_be_set_explicitly").to_path(&dirs);
|
||||
env::set_var("CARGO_TARGET_DIR", &target);
|
||||
let _ = std::fs::remove_file(&target);
|
||||
std::fs::File::create(target).unwrap();
|
||||
}
|
||||
|
||||
if command == Command::Prepare {
|
||||
prepare::prepare(&dirs);
|
||||
process::exit(0);
|
||||
}
|
||||
|
||||
env::set_var("RUSTC", "rustc_should_be_set_explicitly");
|
||||
env::set_var("RUSTDOC", "rustdoc_should_be_set_explicitly");
|
||||
|
||||
let cg_clif_dylib = build_backend::build_backend(
|
||||
&dirs,
|
||||
channel,
|
||||
&bootstrap_host_compiler,
|
||||
use_unstable_features,
|
||||
);
|
||||
match command {
|
||||
Command::Prepare => {
|
||||
// Handled above
|
||||
}
|
||||
Command::Test => {
|
||||
tests::run_tests(
|
||||
&dirs,
|
||||
channel,
|
||||
sysroot_kind,
|
||||
&cg_clif_dylib,
|
||||
&bootstrap_host_compiler,
|
||||
target_triple.clone(),
|
||||
);
|
||||
}
|
||||
Command::AbiCafe => {
|
||||
if bootstrap_host_compiler.triple != target_triple {
|
||||
eprintln!("Abi-cafe doesn't support cross-compilation");
|
||||
process::exit(1);
|
||||
}
|
||||
abi_cafe::run(channel, sysroot_kind, &dirs, &cg_clif_dylib, &bootstrap_host_compiler);
|
||||
}
|
||||
Command::Build => {
|
||||
build_sysroot::build_sysroot(
|
||||
&dirs,
|
||||
channel,
|
||||
sysroot_kind,
|
||||
&cg_clif_dylib,
|
||||
&bootstrap_host_compiler,
|
||||
target_triple,
|
||||
);
|
||||
}
|
||||
Command::Bench => {
|
||||
build_sysroot::build_sysroot(
|
||||
&dirs,
|
||||
channel,
|
||||
sysroot_kind,
|
||||
&cg_clif_dylib,
|
||||
&bootstrap_host_compiler,
|
||||
target_triple,
|
||||
);
|
||||
bench::benchmark(&dirs, &bootstrap_host_compiler);
|
||||
}
|
||||
}
|
||||
}
|
@ -9,6 +9,7 @@ pub(crate) struct Dirs {
|
||||
pub(crate) download_dir: PathBuf,
|
||||
pub(crate) build_dir: PathBuf,
|
||||
pub(crate) dist_dir: PathBuf,
|
||||
pub(crate) frozen: bool,
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
|
@ -3,77 +3,60 @@ use std::fs;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process::Command;
|
||||
|
||||
use super::build_sysroot::{BUILD_SYSROOT, ORIG_BUILD_SYSROOT, SYSROOT_RUSTC_VERSION, SYSROOT_SRC};
|
||||
use super::build_sysroot::STDLIB_SRC;
|
||||
use super::path::{Dirs, RelPath};
|
||||
use super::rustc_info::{get_default_sysroot, get_rustc_version};
|
||||
use super::tests::LIBCORE_TESTS_SRC;
|
||||
use super::utils::{copy_dir_recursively, git_command, retry_spawn_and_wait, spawn_and_wait};
|
||||
use super::rustc_info::get_default_sysroot;
|
||||
use super::utils::{
|
||||
copy_dir_recursively, git_command, remove_dir_if_exists, retry_spawn_and_wait, spawn_and_wait,
|
||||
};
|
||||
|
||||
pub(crate) fn prepare(dirs: &Dirs) {
|
||||
RelPath::DOWNLOAD.ensure_fresh(dirs);
|
||||
|
||||
spawn_and_wait(super::build_backend::CG_CLIF.fetch("cargo", "rustc", dirs));
|
||||
|
||||
prepare_stdlib(dirs);
|
||||
spawn_and_wait(super::build_sysroot::STANDARD_LIBRARY.fetch("cargo", "rustc", dirs));
|
||||
|
||||
prepare_coretests(dirs);
|
||||
spawn_and_wait(super::tests::LIBCORE_TESTS.fetch("cargo", "rustc", dirs));
|
||||
|
||||
RelPath::DOWNLOAD.ensure_exists(dirs);
|
||||
super::tests::RAND_REPO.fetch(dirs);
|
||||
spawn_and_wait(super::tests::RAND.fetch("cargo", "rustc", dirs));
|
||||
super::tests::REGEX_REPO.fetch(dirs);
|
||||
spawn_and_wait(super::tests::REGEX.fetch("cargo", "rustc", dirs));
|
||||
super::tests::PORTABLE_SIMD_REPO.fetch(dirs);
|
||||
spawn_and_wait(super::tests::PORTABLE_SIMD.fetch("cargo", "rustc", dirs));
|
||||
}
|
||||
|
||||
fn prepare_stdlib(dirs: &Dirs) {
|
||||
let sysroot_src_orig = get_default_sysroot(Path::new("rustc")).join("lib/rustlib/src/rust");
|
||||
pub(crate) fn prepare_stdlib(dirs: &Dirs, rustc: &Path) {
|
||||
let sysroot_src_orig = get_default_sysroot(rustc).join("lib/rustlib/src/rust");
|
||||
assert!(sysroot_src_orig.exists());
|
||||
|
||||
eprintln!("[COPY] stdlib src");
|
||||
apply_patches(dirs, "stdlib", &sysroot_src_orig, &STDLIB_SRC.to_path(dirs));
|
||||
|
||||
// FIXME ensure builds error out or update the copy if any of the files copied here change
|
||||
BUILD_SYSROOT.ensure_fresh(dirs);
|
||||
copy_dir_recursively(&ORIG_BUILD_SYSROOT.to_path(dirs), &BUILD_SYSROOT.to_path(dirs));
|
||||
std::fs::write(
|
||||
STDLIB_SRC.to_path(dirs).join("Cargo.toml"),
|
||||
r#"
|
||||
[workspace]
|
||||
members = ["./library/sysroot"]
|
||||
|
||||
fs::create_dir_all(SYSROOT_SRC.to_path(dirs).join("library")).unwrap();
|
||||
copy_dir_recursively(
|
||||
&sysroot_src_orig.join("library"),
|
||||
&SYSROOT_SRC.to_path(dirs).join("library"),
|
||||
);
|
||||
[patch.crates-io]
|
||||
rustc-std-workspace-core = { path = "./library/rustc-std-workspace-core" }
|
||||
rustc-std-workspace-alloc = { path = "./library/rustc-std-workspace-alloc" }
|
||||
rustc-std-workspace-std = { path = "./library/rustc-std-workspace-std" }
|
||||
|
||||
let rustc_version = get_rustc_version(Path::new("rustc"));
|
||||
fs::write(SYSROOT_RUSTC_VERSION.to_path(dirs), &rustc_version).unwrap();
|
||||
# Mandatory for correctly compiling compiler-builtins
|
||||
[profile.dev.package.compiler_builtins]
|
||||
debug-assertions = false
|
||||
overflow-checks = false
|
||||
codegen-units = 10000
|
||||
|
||||
eprintln!("[GIT] init");
|
||||
init_git_repo(&SYSROOT_SRC.to_path(dirs));
|
||||
[profile.release.package.compiler_builtins]
|
||||
debug-assertions = false
|
||||
overflow-checks = false
|
||||
codegen-units = 10000
|
||||
"#,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
apply_patches(dirs, "stdlib", &SYSROOT_SRC.to_path(dirs));
|
||||
}
|
||||
|
||||
fn prepare_coretests(dirs: &Dirs) {
|
||||
let sysroot_src_orig = get_default_sysroot(Path::new("rustc")).join("lib/rustlib/src/rust");
|
||||
assert!(sysroot_src_orig.exists());
|
||||
|
||||
eprintln!("[COPY] coretests src");
|
||||
|
||||
fs::create_dir_all(LIBCORE_TESTS_SRC.to_path(dirs)).unwrap();
|
||||
copy_dir_recursively(
|
||||
&sysroot_src_orig.join("library/core/tests"),
|
||||
&LIBCORE_TESTS_SRC.to_path(dirs),
|
||||
);
|
||||
|
||||
eprintln!("[GIT] init");
|
||||
init_git_repo(&LIBCORE_TESTS_SRC.to_path(dirs));
|
||||
|
||||
apply_patches(dirs, "coretests", &LIBCORE_TESTS_SRC.to_path(dirs));
|
||||
let source_lockfile = RelPath::PATCHES.to_path(dirs).join("stdlib-lock.toml");
|
||||
let target_lockfile = STDLIB_SRC.to_path(dirs).join("Cargo.lock");
|
||||
fs::copy(source_lockfile, target_lockfile).unwrap();
|
||||
}
|
||||
|
||||
pub(crate) struct GitRepo {
|
||||
url: GitRepoUrl,
|
||||
rev: &'static str,
|
||||
content_hash: &'static str,
|
||||
patch_name: &'static str,
|
||||
}
|
||||
|
||||
@ -81,35 +64,107 @@ enum GitRepoUrl {
|
||||
Github { user: &'static str, repo: &'static str },
|
||||
}
|
||||
|
||||
// Note: This uses a hasher which is not cryptographically secure. This is fine as the hash is meant
|
||||
// to protect against accidental modification and outdated downloads, not against manipulation.
|
||||
fn hash_file(file: &std::path::Path) -> u64 {
|
||||
let contents = std::fs::read(file).unwrap();
|
||||
#[allow(deprecated)]
|
||||
let mut hasher = std::hash::SipHasher::new();
|
||||
std::hash::Hash::hash(&contents, &mut hasher);
|
||||
std::hash::Hasher::finish(&hasher)
|
||||
}
|
||||
|
||||
fn hash_dir(dir: &std::path::Path) -> u64 {
|
||||
let mut sub_hashes = std::collections::BTreeMap::new();
|
||||
for entry in std::fs::read_dir(dir).unwrap() {
|
||||
let entry = entry.unwrap();
|
||||
if entry.file_type().unwrap().is_dir() {
|
||||
sub_hashes
|
||||
.insert(entry.file_name().to_str().unwrap().to_owned(), hash_dir(&entry.path()));
|
||||
} else {
|
||||
sub_hashes
|
||||
.insert(entry.file_name().to_str().unwrap().to_owned(), hash_file(&entry.path()));
|
||||
}
|
||||
}
|
||||
#[allow(deprecated)]
|
||||
let mut hasher = std::hash::SipHasher::new();
|
||||
std::hash::Hash::hash(&sub_hashes, &mut hasher);
|
||||
std::hash::Hasher::finish(&hasher)
|
||||
}
|
||||
|
||||
impl GitRepo {
|
||||
pub(crate) const fn github(
|
||||
user: &'static str,
|
||||
repo: &'static str,
|
||||
rev: &'static str,
|
||||
content_hash: &'static str,
|
||||
patch_name: &'static str,
|
||||
) -> GitRepo {
|
||||
GitRepo { url: GitRepoUrl::Github { user, repo }, rev, patch_name }
|
||||
GitRepo { url: GitRepoUrl::Github { user, repo }, rev, content_hash, patch_name }
|
||||
}
|
||||
|
||||
fn download_dir(&self, dirs: &Dirs) -> PathBuf {
|
||||
match self.url {
|
||||
GitRepoUrl::Github { user: _, repo } => RelPath::DOWNLOAD.join(repo).to_path(dirs),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) const fn source_dir(&self) -> RelPath {
|
||||
match self.url {
|
||||
GitRepoUrl::Github { user: _, repo } => RelPath::DOWNLOAD.join(repo),
|
||||
GitRepoUrl::Github { user: _, repo } => RelPath::BUILD.join(repo),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn fetch(&self, dirs: &Dirs) {
|
||||
match self.url {
|
||||
GitRepoUrl::Github { user, repo } => {
|
||||
clone_repo_shallow_github(
|
||||
dirs,
|
||||
&self.source_dir().to_path(dirs),
|
||||
user,
|
||||
repo,
|
||||
self.rev,
|
||||
let download_dir = self.download_dir(dirs);
|
||||
|
||||
if download_dir.exists() {
|
||||
let actual_hash = format!("{:016x}", hash_dir(&download_dir));
|
||||
if actual_hash == self.content_hash {
|
||||
println!("[FRESH] {}", download_dir.display());
|
||||
return;
|
||||
} else {
|
||||
println!(
|
||||
"Mismatched content hash for {download_dir}: {actual_hash} != {content_hash}. Downloading again.",
|
||||
download_dir = download_dir.display(),
|
||||
content_hash = self.content_hash,
|
||||
);
|
||||
}
|
||||
}
|
||||
apply_patches(dirs, self.patch_name, &self.source_dir().to_path(dirs));
|
||||
|
||||
match self.url {
|
||||
GitRepoUrl::Github { user, repo } => {
|
||||
clone_repo_shallow_github(dirs, &download_dir, user, repo, self.rev);
|
||||
}
|
||||
}
|
||||
|
||||
let source_lockfile =
|
||||
RelPath::PATCHES.to_path(dirs).join(format!("{}-lock.toml", self.patch_name));
|
||||
let target_lockfile = download_dir.join("Cargo.lock");
|
||||
if source_lockfile.exists() {
|
||||
fs::copy(source_lockfile, target_lockfile).unwrap();
|
||||
} else {
|
||||
assert!(target_lockfile.exists());
|
||||
}
|
||||
|
||||
let actual_hash = format!("{:016x}", hash_dir(&download_dir));
|
||||
if actual_hash != self.content_hash {
|
||||
println!(
|
||||
"Download of {download_dir} failed with mismatched content hash: {actual_hash} != {content_hash}",
|
||||
download_dir = download_dir.display(),
|
||||
content_hash = self.content_hash,
|
||||
);
|
||||
std::process::exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn patch(&self, dirs: &Dirs) {
|
||||
apply_patches(
|
||||
dirs,
|
||||
self.patch_name,
|
||||
&self.download_dir(dirs),
|
||||
&self.source_dir().to_path(dirs),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -126,6 +181,8 @@ fn clone_repo(download_dir: &Path, repo: &str, rev: &str) {
|
||||
let mut checkout_cmd = git_command(download_dir, "checkout");
|
||||
checkout_cmd.arg("-q").arg(rev);
|
||||
spawn_and_wait(checkout_cmd);
|
||||
|
||||
std::fs::remove_dir_all(download_dir.join(".git")).unwrap();
|
||||
}
|
||||
|
||||
fn clone_repo_shallow_github(dirs: &Dirs, download_dir: &Path, user: &str, repo: &str, rev: &str) {
|
||||
@ -173,8 +230,6 @@ fn clone_repo_shallow_github(dirs: &Dirs, download_dir: &Path, user: &str, repo:
|
||||
// Rename unpacked dir to the expected name
|
||||
std::fs::rename(archive_dir, &download_dir).unwrap();
|
||||
|
||||
init_git_repo(&download_dir);
|
||||
|
||||
// Cleanup
|
||||
std::fs::remove_file(archive_file).unwrap();
|
||||
}
|
||||
@ -213,7 +268,22 @@ fn get_patches(dirs: &Dirs, crate_name: &str) -> Vec<PathBuf> {
|
||||
patches
|
||||
}
|
||||
|
||||
fn apply_patches(dirs: &Dirs, crate_name: &str, target_dir: &Path) {
|
||||
pub(crate) fn apply_patches(dirs: &Dirs, crate_name: &str, source_dir: &Path, target_dir: &Path) {
|
||||
// FIXME avoid copy and patch if src, patches and target are unchanged
|
||||
|
||||
eprintln!("[COPY] {crate_name} source");
|
||||
|
||||
remove_dir_if_exists(target_dir);
|
||||
fs::create_dir_all(target_dir).unwrap();
|
||||
if crate_name == "stdlib" {
|
||||
fs::create_dir(target_dir.join("library")).unwrap();
|
||||
copy_dir_recursively(&source_dir.join("library"), &target_dir.join("library"));
|
||||
} else {
|
||||
copy_dir_recursively(source_dir, target_dir);
|
||||
}
|
||||
|
||||
init_git_repo(target_dir);
|
||||
|
||||
if crate_name == "<none>" {
|
||||
return;
|
||||
}
|
||||
|
@ -1,15 +1,9 @@
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process::{Command, Stdio};
|
||||
|
||||
pub(crate) fn get_rustc_version(rustc: &Path) -> String {
|
||||
pub(crate) fn get_host_triple(rustc: &Path) -> String {
|
||||
let version_info =
|
||||
Command::new(rustc).stderr(Stdio::inherit()).args(&["-V"]).output().unwrap().stdout;
|
||||
String::from_utf8(version_info).unwrap()
|
||||
}
|
||||
|
||||
pub(crate) fn get_host_triple() -> String {
|
||||
let version_info =
|
||||
Command::new("rustc").stderr(Stdio::inherit()).args(&["-vV"]).output().unwrap().stdout;
|
||||
Command::new(rustc).stderr(Stdio::inherit()).args(&["-vV"]).output().unwrap().stdout;
|
||||
String::from_utf8(version_info)
|
||||
.unwrap()
|
||||
.lines()
|
||||
@ -34,6 +28,9 @@ pub(crate) fn get_toolchain_name() -> String {
|
||||
}
|
||||
|
||||
pub(crate) fn get_cargo_path() -> PathBuf {
|
||||
if let Ok(cargo) = std::env::var("CARGO") {
|
||||
return PathBuf::from(cargo);
|
||||
}
|
||||
let cargo_path = Command::new("rustup")
|
||||
.stderr(Stdio::inherit())
|
||||
.args(&["which", "cargo"])
|
||||
@ -44,6 +41,9 @@ pub(crate) fn get_cargo_path() -> PathBuf {
|
||||
}
|
||||
|
||||
pub(crate) fn get_rustc_path() -> PathBuf {
|
||||
if let Ok(rustc) = std::env::var("RUSTC") {
|
||||
return PathBuf::from(rustc);
|
||||
}
|
||||
let rustc_path = Command::new("rustup")
|
||||
.stderr(Stdio::inherit())
|
||||
.args(&["which", "rustc"])
|
||||
@ -54,6 +54,9 @@ pub(crate) fn get_rustc_path() -> PathBuf {
|
||||
}
|
||||
|
||||
pub(crate) fn get_rustdoc_path() -> PathBuf {
|
||||
if let Ok(rustdoc) = std::env::var("RUSTDOC") {
|
||||
return PathBuf::from(rustdoc);
|
||||
}
|
||||
let rustc_path = Command::new("rustup")
|
||||
.stderr(Stdio::inherit())
|
||||
.args(&["which", "rustdoc"])
|
||||
@ -73,8 +76,9 @@ pub(crate) fn get_default_sysroot(rustc: &Path) -> PathBuf {
|
||||
Path::new(String::from_utf8(default_sysroot).unwrap().trim()).to_owned()
|
||||
}
|
||||
|
||||
pub(crate) fn get_file_name(crate_name: &str, crate_type: &str) -> String {
|
||||
let file_name = Command::new("rustc")
|
||||
// FIXME call once for each target and pass result around in struct
|
||||
pub(crate) fn get_file_name(rustc: &Path, crate_name: &str, crate_type: &str) -> String {
|
||||
let file_name = Command::new(rustc)
|
||||
.stderr(Stdio::inherit())
|
||||
.args(&[
|
||||
"--crate-name",
|
||||
|
@ -1,13 +1,14 @@
|
||||
use super::build_sysroot;
|
||||
use super::config;
|
||||
use super::path::{Dirs, RelPath};
|
||||
use super::prepare::GitRepo;
|
||||
use super::prepare::{apply_patches, GitRepo};
|
||||
use super::rustc_info::get_default_sysroot;
|
||||
use super::utils::{spawn_and_wait, spawn_and_wait_with_input, CargoProject, Compiler};
|
||||
use super::SysrootKind;
|
||||
use super::{CodegenBackend, SysrootKind};
|
||||
use std::env;
|
||||
use std::ffi::OsStr;
|
||||
use std::fs;
|
||||
use std::path::Path;
|
||||
use std::path::PathBuf;
|
||||
use std::process::Command;
|
||||
|
||||
static BUILD_EXAMPLE_OUT_DIR: RelPath = RelPath::BUILD.join("example");
|
||||
@ -18,7 +19,7 @@ struct TestCase {
|
||||
}
|
||||
|
||||
enum TestCaseCmd {
|
||||
Custom { func: &'static dyn Fn(&TestRunner) },
|
||||
Custom { func: &'static dyn Fn(&TestRunner<'_>) },
|
||||
BuildLib { source: &'static str, crate_types: &'static str },
|
||||
BuildBinAndRun { source: &'static str, args: &'static [&'static str] },
|
||||
JitBin { source: &'static str, args: &'static str },
|
||||
@ -26,7 +27,7 @@ enum TestCaseCmd {
|
||||
|
||||
impl TestCase {
|
||||
// FIXME reduce usage of custom test case commands
|
||||
const fn custom(config: &'static str, func: &'static dyn Fn(&TestRunner)) -> Self {
|
||||
const fn custom(config: &'static str, func: &'static dyn Fn(&TestRunner<'_>)) -> Self {
|
||||
Self { config, cmd: TestCaseCmd::Custom { func } }
|
||||
}
|
||||
|
||||
@ -95,32 +96,45 @@ const BASE_SYSROOT_SUITE: &[TestCase] = &[
|
||||
|
||||
// FIXME(rust-random/rand#1293): Newer rand versions fail to test on Windows. Update once this is
|
||||
// fixed.
|
||||
pub(crate) static RAND_REPO: GitRepo =
|
||||
GitRepo::github("rust-random", "rand", "50b9a447410860af8d6db9a208c3576886955874", "rand");
|
||||
pub(crate) static RAND_REPO: GitRepo = GitRepo::github(
|
||||
"rust-random",
|
||||
"rand",
|
||||
"50b9a447410860af8d6db9a208c3576886955874",
|
||||
"446203b96054891e",
|
||||
"rand",
|
||||
);
|
||||
|
||||
pub(crate) static RAND: CargoProject = CargoProject::new(&RAND_REPO.source_dir(), "rand");
|
||||
pub(crate) static RAND: CargoProject = CargoProject::new(&RAND_REPO.source_dir(), "rand_target");
|
||||
|
||||
pub(crate) static REGEX_REPO: GitRepo =
|
||||
GitRepo::github("rust-lang", "regex", "32fed9429eafba0ae92a64b01796a0c5a75b88c8", "regex");
|
||||
pub(crate) static REGEX_REPO: GitRepo = GitRepo::github(
|
||||
"rust-lang",
|
||||
"regex",
|
||||
"32fed9429eafba0ae92a64b01796a0c5a75b88c8",
|
||||
"fcc4df7c5b902633",
|
||||
"regex",
|
||||
);
|
||||
|
||||
pub(crate) static REGEX: CargoProject = CargoProject::new(®EX_REPO.source_dir(), "regex");
|
||||
pub(crate) static REGEX: CargoProject = CargoProject::new(®EX_REPO.source_dir(), "regex_target");
|
||||
|
||||
pub(crate) static PORTABLE_SIMD_REPO: GitRepo = GitRepo::github(
|
||||
"rust-lang",
|
||||
"portable-simd",
|
||||
"ad8afa8c81273b3b49acbea38cd3bcf17a34cf2b",
|
||||
"800548f8000e31bd",
|
||||
"portable-simd",
|
||||
);
|
||||
|
||||
pub(crate) static PORTABLE_SIMD: CargoProject =
|
||||
CargoProject::new(&PORTABLE_SIMD_REPO.source_dir(), "portable_simd");
|
||||
CargoProject::new(&PORTABLE_SIMD_REPO.source_dir(), "portable-simd_target");
|
||||
|
||||
pub(crate) static LIBCORE_TESTS_SRC: RelPath = RelPath::DOWNLOAD.join("coretests_src");
|
||||
static LIBCORE_TESTS_SRC: RelPath = RelPath::BUILD.join("coretests");
|
||||
|
||||
pub(crate) static LIBCORE_TESTS: CargoProject = CargoProject::new(&LIBCORE_TESTS_SRC, "core_tests");
|
||||
static LIBCORE_TESTS: CargoProject = CargoProject::new(&LIBCORE_TESTS_SRC, "coretests_target");
|
||||
|
||||
const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[
|
||||
TestCase::custom("test.rust-random/rand", &|runner| {
|
||||
RAND_REPO.patch(&runner.dirs);
|
||||
|
||||
RAND.clean(&runner.dirs);
|
||||
|
||||
if runner.is_native {
|
||||
@ -135,6 +149,17 @@ const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[
|
||||
}
|
||||
}),
|
||||
TestCase::custom("test.libcore", &|runner| {
|
||||
apply_patches(
|
||||
&runner.dirs,
|
||||
"coretests",
|
||||
&runner.stdlib_source.join("library/core/tests"),
|
||||
&LIBCORE_TESTS_SRC.to_path(&runner.dirs),
|
||||
);
|
||||
|
||||
let source_lockfile = RelPath::PATCHES.to_path(&runner.dirs).join("coretests-lock.toml");
|
||||
let target_lockfile = LIBCORE_TESTS_SRC.to_path(&runner.dirs).join("Cargo.lock");
|
||||
fs::copy(source_lockfile, target_lockfile).unwrap();
|
||||
|
||||
LIBCORE_TESTS.clean(&runner.dirs);
|
||||
|
||||
if runner.is_native {
|
||||
@ -149,6 +174,8 @@ const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[
|
||||
}
|
||||
}),
|
||||
TestCase::custom("test.regex-shootout-regex-dna", &|runner| {
|
||||
REGEX_REPO.patch(&runner.dirs);
|
||||
|
||||
REGEX.clean(&runner.dirs);
|
||||
|
||||
let mut build_cmd = REGEX.build(&runner.target_compiler, &runner.dirs);
|
||||
@ -181,6 +208,8 @@ const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[
|
||||
}
|
||||
}),
|
||||
TestCase::custom("test.regex", &|runner| {
|
||||
REGEX_REPO.patch(&runner.dirs);
|
||||
|
||||
REGEX.clean(&runner.dirs);
|
||||
|
||||
if runner.is_native {
|
||||
@ -197,6 +226,8 @@ const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[
|
||||
}
|
||||
}),
|
||||
TestCase::custom("test.portable-simd", &|runner| {
|
||||
PORTABLE_SIMD_REPO.patch(&runner.dirs);
|
||||
|
||||
PORTABLE_SIMD.clean(&runner.dirs);
|
||||
|
||||
let mut build_cmd = PORTABLE_SIMD.build(&runner.target_compiler, &runner.dirs);
|
||||
@ -215,24 +246,35 @@ pub(crate) fn run_tests(
|
||||
dirs: &Dirs,
|
||||
channel: &str,
|
||||
sysroot_kind: SysrootKind,
|
||||
cg_clif_dylib: &Path,
|
||||
use_unstable_features: bool,
|
||||
skip_tests: &[&str],
|
||||
cg_clif_dylib: &CodegenBackend,
|
||||
bootstrap_host_compiler: &Compiler,
|
||||
rustup_toolchain_name: Option<&str>,
|
||||
target_triple: String,
|
||||
) {
|
||||
if config::get_bool("testsuite.no_sysroot") {
|
||||
let stdlib_source =
|
||||
get_default_sysroot(&bootstrap_host_compiler.rustc).join("lib/rustlib/src/rust");
|
||||
assert!(stdlib_source.exists());
|
||||
|
||||
if config::get_bool("testsuite.no_sysroot") && !skip_tests.contains(&"testsuite.no_sysroot") {
|
||||
let target_compiler = build_sysroot::build_sysroot(
|
||||
dirs,
|
||||
channel,
|
||||
SysrootKind::None,
|
||||
cg_clif_dylib,
|
||||
bootstrap_host_compiler,
|
||||
rustup_toolchain_name,
|
||||
target_triple.clone(),
|
||||
);
|
||||
|
||||
let runner = TestRunner::new(
|
||||
dirs.clone(),
|
||||
target_compiler,
|
||||
use_unstable_features,
|
||||
skip_tests,
|
||||
bootstrap_host_compiler.triple == target_triple,
|
||||
stdlib_source.clone(),
|
||||
);
|
||||
|
||||
BUILD_EXAMPLE_OUT_DIR.ensure_fresh(dirs);
|
||||
@ -241,23 +283,32 @@ pub(crate) fn run_tests(
|
||||
eprintln!("[SKIP] no_sysroot tests");
|
||||
}
|
||||
|
||||
let run_base_sysroot = config::get_bool("testsuite.base_sysroot");
|
||||
let run_extended_sysroot = config::get_bool("testsuite.extended_sysroot");
|
||||
let run_base_sysroot = config::get_bool("testsuite.base_sysroot")
|
||||
&& !skip_tests.contains(&"testsuite.base_sysroot");
|
||||
let run_extended_sysroot = config::get_bool("testsuite.extended_sysroot")
|
||||
&& !skip_tests.contains(&"testsuite.extended_sysroot");
|
||||
|
||||
if run_base_sysroot || run_extended_sysroot {
|
||||
let target_compiler = build_sysroot::build_sysroot(
|
||||
let mut target_compiler = build_sysroot::build_sysroot(
|
||||
dirs,
|
||||
channel,
|
||||
sysroot_kind,
|
||||
cg_clif_dylib,
|
||||
bootstrap_host_compiler,
|
||||
rustup_toolchain_name,
|
||||
target_triple.clone(),
|
||||
);
|
||||
// Rust's build system denies a couple of lints that trigger on several of the test
|
||||
// projects. Changing the code to fix them is not worth it, so just silence all lints.
|
||||
target_compiler.rustflags += " --cap-lints=allow";
|
||||
|
||||
let runner = TestRunner::new(
|
||||
dirs.clone(),
|
||||
target_compiler,
|
||||
use_unstable_features,
|
||||
skip_tests,
|
||||
bootstrap_host_compiler.triple == target_triple,
|
||||
stdlib_source,
|
||||
);
|
||||
|
||||
if run_base_sysroot {
|
||||
@ -274,15 +325,25 @@ pub(crate) fn run_tests(
|
||||
}
|
||||
}
|
||||
|
||||
struct TestRunner {
|
||||
struct TestRunner<'a> {
|
||||
is_native: bool,
|
||||
jit_supported: bool,
|
||||
use_unstable_features: bool,
|
||||
skip_tests: &'a [&'a str],
|
||||
dirs: Dirs,
|
||||
target_compiler: Compiler,
|
||||
stdlib_source: PathBuf,
|
||||
}
|
||||
|
||||
impl TestRunner {
|
||||
fn new(dirs: Dirs, mut target_compiler: Compiler, is_native: bool) -> Self {
|
||||
impl<'a> TestRunner<'a> {
|
||||
fn new(
|
||||
dirs: Dirs,
|
||||
mut target_compiler: Compiler,
|
||||
use_unstable_features: bool,
|
||||
skip_tests: &'a [&'a str],
|
||||
is_native: bool,
|
||||
stdlib_source: PathBuf,
|
||||
) -> Self {
|
||||
if let Ok(rustflags) = env::var("RUSTFLAGS") {
|
||||
target_compiler.rustflags.push(' ');
|
||||
target_compiler.rustflags.push_str(&rustflags);
|
||||
@ -297,11 +358,20 @@ impl TestRunner {
|
||||
target_compiler.rustflags.push_str(" -Clink-arg=-undefined -Clink-arg=dynamic_lookup");
|
||||
}
|
||||
|
||||
let jit_supported = is_native
|
||||
let jit_supported = use_unstable_features
|
||||
&& is_native
|
||||
&& target_compiler.triple.contains("x86_64")
|
||||
&& !target_compiler.triple.contains("windows");
|
||||
|
||||
Self { is_native, jit_supported, dirs, target_compiler }
|
||||
Self {
|
||||
is_native,
|
||||
jit_supported,
|
||||
use_unstable_features,
|
||||
skip_tests,
|
||||
dirs,
|
||||
target_compiler,
|
||||
stdlib_source,
|
||||
}
|
||||
}
|
||||
|
||||
fn run_testsuite(&self, tests: &[TestCase]) {
|
||||
@ -310,7 +380,10 @@ impl TestRunner {
|
||||
let tag = tag.to_uppercase();
|
||||
let is_jit_test = tag == "JIT";
|
||||
|
||||
if !config::get_bool(config) || (is_jit_test && !self.jit_supported) {
|
||||
if !config::get_bool(config)
|
||||
|| (is_jit_test && !self.jit_supported)
|
||||
|| self.skip_tests.contains(&config)
|
||||
{
|
||||
eprintln!("[{tag}] {testname} (skipped)");
|
||||
continue;
|
||||
} else {
|
||||
@ -320,10 +393,24 @@ impl TestRunner {
|
||||
match *cmd {
|
||||
TestCaseCmd::Custom { func } => func(self),
|
||||
TestCaseCmd::BuildLib { source, crate_types } => {
|
||||
self.run_rustc([source, "--crate-type", crate_types]);
|
||||
if self.use_unstable_features {
|
||||
self.run_rustc([source, "--crate-type", crate_types]);
|
||||
} else {
|
||||
self.run_rustc([
|
||||
source,
|
||||
"--crate-type",
|
||||
crate_types,
|
||||
"--cfg",
|
||||
"no_unstable_features",
|
||||
]);
|
||||
}
|
||||
}
|
||||
TestCaseCmd::BuildBinAndRun { source, args } => {
|
||||
self.run_rustc([source]);
|
||||
if self.use_unstable_features {
|
||||
self.run_rustc([source]);
|
||||
} else {
|
||||
self.run_rustc([source, "--cfg", "no_unstable_features"]);
|
||||
}
|
||||
self.run_out_command(
|
||||
source.split('/').last().unwrap().split('.').next().unwrap(),
|
||||
args,
|
||||
|
@ -1,11 +1,11 @@
|
||||
The build system of cg_clif.
|
||||
|
||||
USAGE:
|
||||
./y.rs prepare [--out-dir DIR]
|
||||
./y.rs build [--debug] [--sysroot none|clif|llvm] [--out-dir DIR] [--no-unstable-features]
|
||||
./y.rs test [--debug] [--sysroot none|clif|llvm] [--out-dir DIR] [--no-unstable-features]
|
||||
./y.rs abi-cafe [--debug] [--sysroot none|clif|llvm] [--out-dir DIR] [--no-unstable-features]
|
||||
./y.rs bench [--debug] [--sysroot none|clif|llvm] [--out-dir DIR] [--no-unstable-features]
|
||||
./y.sh prepare [--out-dir DIR] [--download-dir DIR]
|
||||
./y.sh build [--debug] [--sysroot none|clif|llvm] [--out-dir DIR] [--download-dir DIR] [--no-unstable-features] [--frozen]
|
||||
./y.sh test [--debug] [--sysroot none|clif|llvm] [--out-dir DIR] [--download-dir DIR] [--no-unstable-features] [--frozen] [--skip-test TESTNAME]
|
||||
./y.sh abi-cafe [--debug] [--sysroot none|clif|llvm] [--out-dir DIR] [--download-dir DIR] [--no-unstable-features] [--frozen]
|
||||
./y.sh bench [--debug] [--sysroot none|clif|llvm] [--out-dir DIR] [--download-dir DIR] [--no-unstable-features] [--frozen]
|
||||
|
||||
OPTIONS:
|
||||
--debug
|
||||
@ -22,14 +22,28 @@ OPTIONS:
|
||||
Specify the directory in which the download, build and dist directories are stored.
|
||||
By default this is the working directory.
|
||||
|
||||
--download-dir DIR
|
||||
Specify the directory in which the download directory is stored. Overrides --out-dir.
|
||||
|
||||
--no-unstable-features
|
||||
Some features are not yet ready for production usage. This option will disable these
|
||||
features. This includes the JIT mode and inline assembly support.
|
||||
|
||||
--frozen
|
||||
Require Cargo.lock and cache are up to date
|
||||
|
||||
--skip-test TESTNAME
|
||||
Skip testing the TESTNAME test. The test name format is the same as config.txt.
|
||||
|
||||
--use-backend NAME
|
||||
Use the existing Cranelift (or other) backend of the rustc with which we built.
|
||||
Warning: This is meant for use in rust's CI only!
|
||||
|
||||
REQUIREMENTS:
|
||||
* Rustup: The build system has a hard coded dependency on rustup to install the right nightly
|
||||
version and make sure it is used where necessary.
|
||||
* Git: `./y.rs prepare` uses git for applying patches and on Windows for downloading test repos.
|
||||
* Curl and tar (non-Windows only): Used by `./y.rs prepare` to download a single commit for
|
||||
* Rustup: By default rustup is used to install the right nightly version. If you don't want to
|
||||
use rustup, you can manually install the nightly version indicated by rust-toolchain.toml and
|
||||
point the CARGO, RUSTC and RUSTDOC env vars to the right executables.
|
||||
* Git: `./y.sh prepare` uses git for applying patches and on Windows for downloading test repos.
|
||||
* Curl and tar (non-Windows only): Used by `./y.sh prepare` to download a single commit for
|
||||
repos. Git will be used to clone the whole repo when using Windows.
|
||||
* [Hyperfine](https://github.com/sharkdp/hyperfine/): Used for benchmarking with `./y.rs bench`.
|
||||
* [Hyperfine](https://github.com/sharkdp/hyperfine/): Used for benchmarking with `./y.sh bench`.
|
||||
|
@ -5,7 +5,6 @@ use std::path::{Path, PathBuf};
|
||||
use std::process::{self, Command, Stdio};
|
||||
|
||||
use super::path::{Dirs, RelPath};
|
||||
use super::rustc_info::{get_cargo_path, get_rustc_path, get_rustdoc_path};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub(crate) struct Compiler {
|
||||
@ -19,18 +18,6 @@ pub(crate) struct Compiler {
|
||||
}
|
||||
|
||||
impl Compiler {
|
||||
pub(crate) fn bootstrap_with_triple(triple: String) -> Compiler {
|
||||
Compiler {
|
||||
cargo: get_cargo_path(),
|
||||
rustc: get_rustc_path(),
|
||||
rustdoc: get_rustdoc_path(),
|
||||
rustflags: String::new(),
|
||||
rustdocflags: String::new(),
|
||||
triple,
|
||||
runner: vec![],
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn set_cross_linker_and_runner(&mut self) {
|
||||
match self.triple.as_str() {
|
||||
"aarch64-unknown-linux-gnu" => {
|
||||
@ -95,7 +82,11 @@ impl CargoProject {
|
||||
.arg(self.manifest_path(dirs))
|
||||
.arg("--target-dir")
|
||||
.arg(self.target_dir(dirs))
|
||||
.arg("--frozen");
|
||||
.arg("--locked");
|
||||
|
||||
if dirs.frozen {
|
||||
cmd.arg("--frozen");
|
||||
}
|
||||
|
||||
cmd
|
||||
}
|
||||
@ -120,23 +111,6 @@ impl CargoProject {
|
||||
cmd
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub(crate) fn fetch(
|
||||
&self,
|
||||
cargo: impl AsRef<Path>,
|
||||
rustc: impl AsRef<Path>,
|
||||
dirs: &Dirs,
|
||||
) -> Command {
|
||||
let mut cmd = Command::new(cargo.as_ref());
|
||||
|
||||
cmd.env("RUSTC", rustc.as_ref())
|
||||
.arg("fetch")
|
||||
.arg("--manifest-path")
|
||||
.arg(self.manifest_path(dirs));
|
||||
|
||||
cmd
|
||||
}
|
||||
|
||||
pub(crate) fn clean(&self, dirs: &Dirs) {
|
||||
let _ = fs::remove_dir_all(self.target_dir(dirs));
|
||||
}
|
||||
@ -162,8 +136,7 @@ pub(crate) fn hyperfine_command(
|
||||
warmup: u64,
|
||||
runs: u64,
|
||||
prepare: Option<&str>,
|
||||
a: &str,
|
||||
b: &str,
|
||||
cmds: &[&str],
|
||||
) -> Command {
|
||||
let mut bench = Command::new("hyperfine");
|
||||
|
||||
@ -179,7 +152,7 @@ pub(crate) fn hyperfine_command(
|
||||
bench.arg("--prepare").arg(prepare);
|
||||
}
|
||||
|
||||
bench.arg(a).arg(b);
|
||||
bench.args(cmds);
|
||||
|
||||
bench
|
||||
}
|
||||
@ -285,3 +258,13 @@ pub(crate) fn is_ci() -> bool {
|
||||
pub(crate) fn is_ci_opt() -> bool {
|
||||
env::var("CI_OPT").is_ok()
|
||||
}
|
||||
|
||||
pub(crate) fn maybe_incremental(cmd: &mut Command) {
|
||||
if is_ci() || std::env::var("CARGO_BUILD_INCREMENTAL").map_or(false, |val| val == "false") {
|
||||
// Disabling incr comp reduces cache size and incr comp doesn't save as much on CI anyway
|
||||
cmd.env("CARGO_BUILD_INCREMENTAL", "false");
|
||||
} else {
|
||||
// Force incr comp even in release mode unless in CI or incremental builds are explicitly disabled
|
||||
cmd.env("CARGO_BUILD_INCREMENTAL", "true");
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
|
||||
rm -rf target/ download/ build/ dist/ y.bin y.bin.dSYM y.exe y.pdb
|
||||
rm -rf target/ build_system/target download/ build/ dist/ y.bin y.bin.dSYM y.exe y.pdb
|
||||
|
||||
# Kept for now in case someone updates their checkout of cg_clif before running clean_all.sh
|
||||
# FIXME remove at some point in the future
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
rustc_codegen_cranelift can be used as a near-drop-in replacement for `cargo build` or `cargo run` for existing projects.
|
||||
|
||||
Assuming `$cg_clif_dir` is the directory you cloned this repo into and you followed the instructions (`y.rs prepare` and `y.rs build` or `test.sh`).
|
||||
Assuming `$cg_clif_dir` is the directory you cloned this repo into and you followed the instructions (`y.sh prepare` and `y.sh build` or `test.sh`).
|
||||
|
||||
## Cargo
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
#![feature(start, core_intrinsics, alloc_error_handler)]
|
||||
#![feature(start, core_intrinsics, alloc_error_handler, lang_items)]
|
||||
#![no_std]
|
||||
|
||||
extern crate alloc;
|
||||
@ -27,6 +27,11 @@ fn alloc_error_handler(_: alloc::alloc::Layout) -> ! {
|
||||
core::intrinsics::abort();
|
||||
}
|
||||
|
||||
#[lang = "eh_personality"]
|
||||
fn eh_personality() -> ! {
|
||||
loop {}
|
||||
}
|
||||
|
||||
#[start]
|
||||
fn main(_argc: isize, _argv: *const *const u8) -> isize {
|
||||
let world: Box<&str> = Box::new("Hello World!\0");
|
||||
|
@ -502,6 +502,9 @@ pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
|
||||
drop_in_place(to_drop);
|
||||
}
|
||||
|
||||
#[lang = "unpin"]
|
||||
pub auto trait Unpin {}
|
||||
|
||||
#[lang = "deref"]
|
||||
pub trait Deref {
|
||||
type Target: ?Sized;
|
||||
@ -526,7 +529,7 @@ impl<T: ?Sized, U: ?Sized> CoerceUnsized<Unique<U>> for Unique<T> where T: Unsiz
|
||||
impl<T: ?Sized, U: ?Sized> DispatchFromDyn<Unique<U>> for Unique<T> where T: Unsize<U> {}
|
||||
|
||||
#[lang = "owned_box"]
|
||||
pub struct Box<T: ?Sized>(Unique<T>, ());
|
||||
pub struct Box<T: ?Sized, A = ()>(Unique<T>, A);
|
||||
|
||||
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Box<U>> for Box<T> {}
|
||||
|
||||
@ -541,9 +544,10 @@ impl<T> Box<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ?Sized> Drop for Box<T> {
|
||||
impl<T: ?Sized, A> Drop for Box<T, A> {
|
||||
fn drop(&mut self) {
|
||||
// drop is currently performed by compiler.
|
||||
// inner value is dropped by compiler
|
||||
libc::free(self.0.pointer.0 as *mut u8);
|
||||
}
|
||||
}
|
||||
|
||||
@ -560,11 +564,6 @@ unsafe fn allocate(size: usize, _align: usize) -> *mut u8 {
|
||||
libc::malloc(size)
|
||||
}
|
||||
|
||||
#[lang = "box_free"]
|
||||
unsafe fn box_free<T: ?Sized>(ptr: Unique<T>, _alloc: ()) {
|
||||
libc::free(ptr.pointer.0 as *mut u8);
|
||||
}
|
||||
|
||||
#[lang = "drop"]
|
||||
pub trait Drop {
|
||||
fn drop(&mut self);
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user