Update books
## rust-lang/book
2 commits in 5b6c1ceaa62ecbd6caef08df39b33b3938e99deb..71352deb20727b4dda9ebfe8182709d5bf17dfea
2023-11-09 14:49:45 UTC to 2023-11-09 14:49:16 UTC
- Fixed 'Devtools' link (rust-lang/book#3770)
- Fix mdBook links (rust-lang/book#3769)
## rust-lang/rust-by-example
7 commits in 311b84962016b28c75525c86e7b3f49fd9101a39..a6581246f96837113968c02187db24f742af3908
2023-11-18 21:45:20 UTC to 2023-11-07 22:32:53 UTC
- rename `y` to `_y` to get the correct compile error (rust-lang/rust-by-example#1769)
- fix test name in cargo/test.md (rust-lang/rust-by-example#1768)
- Various minor edits for typo fixes, formatting fixes, and clarifications (rust-lang/rust-by-example#1765)
- Update closures.md to correct a typo (rust-lang/rust-by-example#1763)
- Link to the Bulgarian translation (rust-lang/rust-by-example#1764)
- Fix asm example explanation for `inlateout` usage (22.1 Inline Assembly) (rust-lang/rust-by-example#1766)
- Update index.md: Added descriptions for the 'leftover' points (rust-lang/rust-by-example#1767)
## rust-lang/rustc-dev-guide
3 commits in 77dbe5782b2488af3bb489ad702eaff438f465bf..ddb8b1309f9e905804cea1e248a4572fed6b464b
2023-11-18 21:08:13 UTC to 2023-11-08 14:43:50 UTC
- Add link for unsize.md (rust-lang/rustc-dev-guide#1825)
- Fix typo in contribution walkthrough (rust-lang/rustc-dev-guide#1824)
- Update documentation for coverage tests (rust-lang/rustc-dev-guide#1823)
feat: specialize `SpecFromElem` for `()`
# Description
This PR adds a specialization `SpecFromElem for ()` which allows to significantly reduce `vec![(), N]` time in debug builds (specifically, tests) turning it from observable $O(n)$ to $O(1)$.
# Observing the change
The problem this PR aims to fix explicitly is slow `vec![(), N]` on big `N`s which may appear in tests (see [Background section](#Background) for more details).
The minimal example to see the problem:
```rust
#![feature(test)]
extern crate test;
#[cfg(test)]
mod tests {
const HUGE_SIZE: usize = i32::MAX as usize + 1;
#[bench]
fn bench_vec_literal(b: &mut test::Bencher) {
b.iter(|| vec![(); HUGE_SIZE]);
}
#[bench]
fn bench_vec_repeat(b: &mut test::Bencher) {
b.iter(|| [(); 1].repeat(HUGE_SIZE));
}
}
```
<details><summary>Output</summary>
<p>
```bash
cargo +nightly test -- --report-time -Zunstable-options
Compiling huge-zst-vec-literal-bench v0.1.0 (/home/progrm_jarvis/RustroverProjects/huge-zst-vec-literal-bench)
Finished test [unoptimized + debuginfo] target(s) in 0.31s
Running unittests src/lib.rs (target/debug/deps/huge_zst_vec_literal_bench-e43b1ef287ba8b36)
running 2 tests
test tests::bench_vec_repeat ... ok <0.000s>
test tests::bench_vec_literal ... ok <14.382s>
test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 14.38s
Doc-tests huge-zst-vec-literal-bench
running 0 tests
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
```
</p>
</details>
> [!IMPORTANT]
> This problem is only observable in Debug (unoptimized) builds, while Release (optimized) ones do not observe this problem. It still is worth fixing it, IMO, since the original scenario observes the problem in tests for which optimizations are disabled by default and it seems unreasonable to override this for the whole project while the problem is very local.
# Background
While working on a crate for a custom data format which has an `i32::MAX` limit on its list's sizes, I wrote the following test to ensure that this invariant is upheld:
```rust
#[test]
fn lists_should_have_i32_size() {
assert!(
RawNbtList::try_from(vec![(); i32::MAX as usize]).is_ok(),
"lists should permit the size up to {}",
i32::MAX
);
assert!(
RawNbtList::try_from(vec![(); i32::MAX as usize + 1]).is_err(),
"lists should have the size of at most {}",
i32::MAX
);
}
```
Soon I discovered that this takes $\approx 3--4s$ per assertion on my machine, almost all of which is spent on `vec![..]`.
While this would be logical for a non-ZST vector (which would require actual $O(n)$ allocation), here `()` was used intentionally considering that for ZSTs size-changing operations should anyway be $O(1)$ (at least from allocator perspective). Yet, this "overhead" is logical if we consider that in general case `clone()` (which is used by `Vec` literal) may have a non-trivial implementation and thus each element has to actually be visited (even if they occupy no space).
In my specific case, the following (contextual) equivalent solved the issue:
```rust
#[test]
fn lists_should_have_i32_size() {
assert!(
RawNbtList::try_from([(); 1].repeat(i32::MAX as usize)).is_ok(),
"lists should permit the size up to {}",
i32::MAX
);
assert!(
RawNbtList::try_from([(); 1].repeat(i32::MAX as usize + 1)).is_err(),
"lists should have the size of at most {}",
i32::MAX
);
}
```
which works since `repeat` explicitly uses `T: Copy` and so does not have to think about non-trivial `Clone`.
But it still may be counter-intuitive for users to observe such long time on the "canonical" vec literal thus the PR.
# Generic solution
This change is explicitly non-generic. Initially I considered it possible to implement in generically, but this would require the specialization to have the following type requirements:
- ✅ the type must be a ZST: easily done via
```rust
if core::mem::size_of::<T>() == 0 {
todo!("specialization")
}
```
or
```rust
use core::mem::SizedTypeProperties;
if T::IS_ZST {
todo!("specialization")
}
```
- :white_check_mark`: the type must implement `Copy`: implementable non-conflictable via a separate specialization:
```rust
trait IsCopyZst: Sized {
fn is_copy_zst() -> bool;
}
impl<T> IsCopyZst for T {
fn is_copy_zst() -> bool {
false
}
}
impl<T: Copy> IsCopyZst for T {
fn is_copy_zst() -> bool {
Self::IS_ZST
}
}
```
- ❌ the type should have a trivial `Clone` implementation: since `vec![t; n]` is specified to use `clone()`, we can only use this "performance optimization" when we are guaranteed that `clone()` does nothing except for copying.
The latter is the real blocker for a generic fix since I am unaware of any way to get this information in a compiler-guaranteed way.
While there may be a fix for this (my friend `@CertainLach` has suggested a potential solution by an perma-unstable fn in `Clone` like `is_trivially_cloneable()` defaulting to `false` and only overridable by `rustc` on derive), this is surely out of this PRs scope.
Explicitly unset $CARGO for compiletest
Some UI tests trigger behavior in rustc where it reads $CARGO and changes behavior if it exists. To make the tests work that rely on it not being set, make sure it is not set.
By default, this is not set, but people may do weird hacks that cause it to be set.
closes#118058
Add place.ty() and Ty build from a kind to smir
Add a method to retrieve the type of a place and a few utility functions needed to build the projection type. I decided to return a result to avoid panicking if the user passes invalid inputs, such as wrong list of locals.
r? `@spastorino`
Rollup of 8 pull requests
Successful merges:
- #117327 (Add documentation for some queries)
- #117835 (Note about object lifetime defaults in does not live long enough error)
- #117851 (Uplift `InferConst` to `rustc_type_ir`)
- #117973 (test: Add test for async-move in 2015 Rust proc macro)
- #117992 (Don't require intercrate mode for negative coherence)
- #118010 (Typeck break expr even if break is illegal)
- #118026 (Don't consider regions in `deref_into_dyn_supertrait` lint)
- #118089 (intercrate_ambiguity_causes: handle self ty infer + reservation impls)
r? `@ghost`
`@rustbot` modify labels: rollup
Unify `defined_lib_features` and `lib_features` queries
Extracts part of https://github.com/rust-lang/rust/pull/115623#discussion_r1318929750
I went with also introducing a `FeatureStability` enum, instead of using `Some(span)` to mean stable and `None` to mean unstable.
r? `@cjgillot`
Update cargo
9 commits in 9765a449d9b7341c2b49b88da41c2268ea599720..71cd3a926f0cf41eeaf9f2a7f2194b2aff85b0f6
2023-11-17 20:58:23 +0000 to 2023-11-20 15:30:57 +0000
- Handle $message_type in JSON diagnostics (rust-lang/cargo#13016)
- refactor(toml): Further clean up inheritance (rust-lang/cargo#13000)
- Fix `--check-cfg` invocations with zero features (rust-lang/cargo#13011)
- chore: bump `cargo-credential-*` crates as e58b84d broke stuff (rust-lang/cargo#13010)
- contrib docs: Update now that credential crates are published. (rust-lang/cargo#13006)
- Add more resources to the contrib docs. (rust-lang/cargo#13008)
- Respect `rust-lang/rust`'s `omit-git-hash` (rust-lang/cargo#12968)
- Fix clippy-wrapper test race condition. (rust-lang/cargo#12999)
- fix(resolver): Don't do git fetches when updating workspace members (rust-lang/cargo#12975)
Don't consider regions in `deref_into_dyn_supertrait` lint
I actually wonder if we should just warn on *any* deref impl with a target type that matches a supertrait by *def-id*.
cc #89460
r? types
Typeck break expr even if break is illegal
Fixes#117821
We were returning immediately when encountering an illegal break. However, this caused problems later when the expr that the break was returning was evaluated during writeback. So now we don't return and instead simply set tainted by error. This lets typeck of break expr to occur even though we've encountered an illegal break.
Don't require intercrate mode for negative coherence
Negative coherence needs to be *sound*, but does not need to be *complete*, since it's looking for the *existence* of a negative goal, not the non-existence of a positive goal.
This removes some trivial and annoying ambiguities when a negative impl has region constraints.
r? lcnr idk if this needs an fcp but if it does, pls kick it off
Uplift `InferConst` to `rustc_type_ir`
We need this in `rustc_type_ir` because the canonicalizer must understand the difference between a const vid and an effect vid. In that way, it's not an implementation detail of the representation of an infer const, but just part of the type ir.
If we find out later on that it's better to leave the representation up to the consumer of `rustc_type_ir`, we could abstract `InferConst` (and probably `InferTy` as well) with some traits, but I don't see the benefit of that indirection currently.
Note about object lifetime defaults in does not live long enough error
This is a aspect of Rust that frequently trips up people who are not aware of it yet. This diagnostic attempts to explain what's happening and why the lifetime constraint, that was never mentioned in the source, arose.
The implementation feels a bit questionable, I'm not sure whether there are better ways to do this. There probably are.
fixes#117835
r? types
While a better approach would be to implement it for all ZSTs
which are `Copy` and have trivial `Clone`,
the last property cannot be detected for now.
Signed-off-by: Petr Portnov <me@progrm-jarvis.ru>
Add a test to ensure issue #89699 does not show up again. This test
emits an `async move` closure in a proc macro, which is used in a
test program compiled with edition 2015. We make sure the error message
is nice and shows up properly.
Rollup of 8 pull requests
Successful merges:
- #117828 (Avoid iterating over hashmaps in astconv)
- #117832 (interpret: simplify handling of shifts by no longer trying to handle signed and unsigned shift amounts in the same branch)
- #117891 (Recover `dyn` and `impl` after `for<...>`)
- #117957 (if available use a Child's pidfd for kill/wait)
- #117988 (Handle attempts to have multiple `cfg`d tail expressions)
- #117994 (Ignore but do not assume region obligations from unifying headers in negative coherence)
- #118000 (Make regionck care about placeholders in outlives components)
- #118068 (subtree update cg_gcc 2023/11/17)
r? `@ghost`
`@rustbot` modify labels: rollup
We were earlier returning immediately when encountering an illegal break. However, this caused problems later
when the expr that the break was returning was evaluated during writeback. So now we don't return and instead
simply set tainted by error. This lets typeck of break expr to occur even though we've encountered an illegal break.
Fix insertion of statements to be executed along return edge in inlining
Inlining creates additional statements to be executed along the return
edge: an assignment to the destination, storage end for temporaries.
Previously those statements where inserted directly into a call target,
but this is incorrect when the target has other predecessors.
Avoid the issue by creating a new dedicated block for those statements.
When the block happens to be redundant it will be removed by CFG
simplification that follows inlining.
Fixes#117355
Inlining creates additional statements to be executed along the return
edge: an assignment to the destination, storage end for temporaries.
Previously those statements where inserted directly into a call target,
but this is incorrect when the target has other predecessors.
Avoid the issue by creating a new dedicated block for those statements.
When the block happens to be redundant it will be removed by CFG
simplification that follows inlining.
Fixes#117355