Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Weaken guarantee around advancing underlying iterators in zip #83791

Merged
merged 1 commit into from
Nov 27, 2021

Conversation

the8472
Copy link
Member

@the8472 the8472 commented Apr 2, 2021

The current guarantee (introduced in #52279) is too strong as it prevents adapters from exploiting knowledge about the iterator length and using counted loops for example because they would stop calling next() before it ever returned None. Additionally several nested zip iterators already fail to uphold this.

This does not yet remove any of the specialization code that tries (and sometimes fails) to uphold the guarantee for next()
because removing it would also affect next_back() in more surprising ways.

The intent is to be able to remove for example this branch

} else if A::MAY_HAVE_SIDE_EFFECT && self.index < self.a_len {
let i = self.index;
self.index += 1;
self.len += 1;
// match the base implementation's potential side effects
// SAFETY: we just checked that `i` < `self.a.len()`
unsafe {
self.a.__iterator_get_unchecked(i);
}
None

or this test

#[test]
fn test_zip_nested_sideffectful() {
let mut xs = [0; 6];
let ys = [0; 4];
{
// test that it has the side effect nested inside enumerate
let it = xs.iter_mut().map(|x| *x = 1).enumerate().zip(&ys);
it.count();
}
assert_eq!(&xs, &[1, 1, 1, 1, 1, 0]);
}

Solves #82303 by declaring it a non-issue.

@rust-highfive
Copy link
Collaborator

r? @m-ou-se

(rust-highfive has picked a reviewer for you, use r? to override)

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Apr 2, 2021
@the8472
Copy link
Member Author

the8472 commented Apr 2, 2021

@rustbot label T-libs

@rustbot rustbot added the T-libs-api Relevant to the library API team, which will review and decide on the PR/issue. label Apr 2, 2021
@the8472 the8472 force-pushed the relax-zip-side-effect-guarantee branch from 3df4a98 to 4428053 Compare April 2, 2021 18:34
@the8472
Copy link
Member Author

the8472 commented Apr 2, 2021

#83796 can be used for a crater run and serves as an example what we might get rid off.

@@ -500,8 +500,8 @@ pub trait Iterator {
/// In other words, it zips two iterators together, into a single one.
///
/// If either iterator returns [`None`], [`next`] from the zipped iterator
/// will return [`None`]. If the first iterator returns [`None`], `zip` will
/// short-circuit and `next` will not be called on the second iterator.
/// will return [`None`]. If the zipped iterator has no more elements to return then attempts
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no more elements to return

What would this mean for non-fused iterators? What if both iterators return None at some point, but both start giving Some(..) again some time later? Are you sayingg that the Zip iterator might just stop forever at that point (fusing the iterator), or are you just talking about iterators that we know will give None forever because of our specializations?

Copy link
Member Author

@the8472 the8472 Apr 14, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A hypothetical implementation could query size_hint() of one or both iterators on every call to next() and short-circuit when the upper bound of either is 0. That should be safe and not require any specialization. Whether that could be considered as fusing the iterator would depend on how the non-fused one calculates its size hint.

It's intentionally kept vague to leave more flexibility for optimizations while at the same time telling the users that the underlying iterators' next() might not be called. Previously it only said that the 2nd iterator's might not be called, now it may call neither.

@crlf0710 crlf0710 added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels May 1, 2021
@Dylan-DPC-zz
Copy link

marking this as blocked till #83796 crater run is complete and triaged.

@Dylan-DPC-zz Dylan-DPC-zz added S-waiting-on-crater Status: Waiting on a crater run to be completed. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels May 1, 2021
@crlf0710 crlf0710 added S-waiting-on-crater Status: Waiting on a crater run to be completed. and removed S-waiting-on-crater Status: Waiting on a crater run to be completed. labels May 22, 2021
@crlf0710 crlf0710 added S-waiting-on-crater Status: Waiting on a crater run to be completed. and removed S-waiting-on-crater Status: Waiting on a crater run to be completed. labels Jun 11, 2021
@the8472
Copy link
Member Author

the8472 commented Jun 11, 2021

@rustbot label -S-waiting-on-crater +S-waiting-on-review

The crater run in #83796 completed, I went through the results in #83796 (comment) and wrote my conclusion in #83796 (comment)

Possible routes that can be taken from here:

A)

  1. Accept this PR, which only updates documentation to declare Better documentation for Iter::zip behavior #52279 a non-issue. This would only legalize the current state of TrustedRandomAccess specializations eliding the side-effects of calling zip.next() after a None has been returned. This is a fairly niche side-effect and the crater run didn't turn up anything relying on that even though it actually tested a more aggressive optimization. I.e. this only affects forward iteration.
  2. (optional) Further simplifcation of Zip. In the specialization we could also elide the length-trimming side-effects during backwards iteration when the iterators are not of the same length. This would be a somewhat bigger change, but still around the totally unspecified case of backwards iteration in Zip. The crater run also tested that and didn't find any issues. It would be a change in behavior but not an API break since the API simply didn't specify anything in that regard.
  3. (optional and tangential) Further specializations for the purpose of optimization on the default iterator implementations. This would extend the changes in 1. to all iterators (where applicable)

B)

  1. reject this PR and instead remove most specializations from Zip. This would simplify its implementation and only leave the default implementation which behaves according to the documented behavior. This would also end all the problems surrounding zip. The downside is of course that it would also revert to the performance characteristics of the default implementation
  2. introduce ZipExact ([ER] Iterator::zip_exact #85342) as replacement that is easier to optimize because we can design its contract so that it is easier to optimize and avoid the specialization pitfalls that we have learned from zip.

C)

Middle ground between A) and B): We could remove the TrustedRandomAccess specialization for next() and next_back() and introduce them only for fold and for_each instead. This way internal iteration would still be optimized while external iteration would take the default implementation.

D)

Somehow extend TrustedRandomAccess to fix this case too? @steffahn hinted at some ideas in #85873 (comment) something a bit more concrete would help to fill in this option

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-crater Status: Waiting on a crater run to be completed. labels Jun 11, 2021
@steffahn
Copy link
Member

steffahn commented Jun 12, 2021

Yeah, I’m working on an approach that’ll need two or three additional methods for TrustedRandomAccess. Which probably means they’ll technically become methods of Iterator the same way that get_unchecked() does… Basically a method to be called before iteration from the back starts, and a method that can be called to emulate the side effects of next() after the iterator is depleted. I haven’t finalized the safety conditions around those, also performance impact will probably be a relevant question.

So the new methods would be just for triggering side effects. Maybe extra const …: bool flags would also help to avoid any (runtime) performance impact in case of no such side effects being present.

Such a proposal would also come with a list of recommendations/requirements around using these methods (not safety requirements) that you’ll need to follow if you want to not mess with an iterator’s order of side effects.

Two or three, because a third method to be called before iteration from the front starts could be added for symmetry and e.g. to make Rev implement TrustedRandomAccess – in case you’re wondering how that works: I’d also disallow the usage of next_back() after get_unchecked. But I haven’t thought this through in detail yet, does this also need a forth method corresponding to next_back on an empty iterator?

I’d expect to be able to provide more details within 2 weeks.

@the8472
Copy link
Member Author

the8472 commented Jun 12, 2021

Interesting. Another idea I want to toss in, it might help to pass the nominal direction of iteration with each call to get_unchecked. This may not be relevant for current issues but it could help with implementing TRA for StepBy.

Which probably means they’ll technically become methods of Iterator the same way that get_unchecked() does…

While technically this is fine it seems aesthetically unpleasing. I wonder if we can somehow bundle this stuff into a helper trait/struct/associated type to separate it more cleanly. Or maybe we should use multiple impl blocks and collect them into a separate file. I think it'll make future improvements easier.

@JohnCSimon JohnCSimon added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jun 27, 2021
@JohnCSimon JohnCSimon added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jul 12, 2021
@the8472
Copy link
Member Author

the8472 commented Aug 9, 2021

Updated, please check if the change is now sufficiently small.

It should still solve #82303 by saying that the 1st iterator is advanced zero or one times without touching the guarantee about the 2nd iterator.

/// will return [`None`].
/// If the zipped iterator has no more elements to return then each further attempt to advance
/// it will advance the first iterator zero or one times and not call [`next`] on the second
/// iterator.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the zipped iterator has no more elements to return[,] then each further attempt to advance it will […] not call next on the second iterator.

This is not correct. This only applies to the case where the first iterator has no more elements. If the first iterator is non-empty but the second one is empty, of course next will (or at least can) be called on the second iterator.

Copy link
Member Author

@the8472 the8472 Aug 10, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, how about?

    /// If the zipped iterator has no more elements to return then each further attempt to advance
    /// it will first try to advance the first iterator at most one time and if it still yielded an item
    /// try to advance the second iterator at most one time.

The current guarantee is too strong as it would prevent adapters
from exploiting knowledge about the iterator length and using counted
loops for example because they would stop calling `next()` before
it ever returned `None`. Additionally several nested zip iterators
already fail to uphold this.

This doesn't remove any of the specialization code that tries
(and sometimes fails) to uphold the guarantee for `next()`
because removing it would also affect `next_back()`
in more surprising ways.
@the8472 the8472 force-pushed the relax-zip-side-effect-guarantee branch from 4c1028f to 2ff677d Compare August 16, 2021 22:44
@apiraino apiraino removed the to-announce Announce this issue on triage meeting label Aug 19, 2021
@JohnCSimon JohnCSimon added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Sep 6, 2021
@JohnCSimon JohnCSimon added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Sep 27, 2021
@JohnCSimon JohnCSimon added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Oct 19, 2021
@JohnCSimon JohnCSimon added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Nov 8, 2021
@dtolnay
Copy link
Member

dtolnay commented Nov 26, 2021

@bors r+ rollup

@bors
Copy link
Contributor

bors commented Nov 26, 2021

📌 Commit 2ff677d has been approved by dtolnay

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Nov 26, 2021
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this pull request Nov 27, 2021
…ntee, r=dtolnay

Weaken guarantee around advancing underlying iterators in zip

The current guarantee (introduced in rust-lang#52279) is too strong as it prevents adapters from exploiting knowledge about the iterator length and using counted loops for example because they would stop calling `next()` before it ever returned `None`. Additionally several nested zip iterators already fail to uphold this.

This does not yet remove any of the specialization code that tries (and sometimes fails) to uphold the guarantee for `next()`
because removing it would also affect `next_back()` in more surprising ways.

The intent is to be able to remove for example this branch

https://github.com/rust-lang/rust/blob/36bcf4069717b9dff90270d13b53a3b130329960/library/core/src/iter/adapters/zip.rs#L234-L243

or this test

https://github.com/rust-lang/rust/blob/36bcf4069717b9dff90270d13b53a3b130329960/library/core/tests/iter/adapters/zip.rs#L177-L188

Solves rust-lang#82303 by declaring it a non-issue.
This was referenced Nov 27, 2021
bors added a commit to rust-lang-ci/rust that referenced this pull request Nov 27, 2021
…askrgr

Rollup of 6 pull requests

Successful merges:

 - rust-lang#83791 (Weaken guarantee around advancing underlying iterators in zip)
 - rust-lang#90995 (Document non-guarantees for Hash)
 - rust-lang#91057 (Expand `available_parallelism` docs in anticipation of cgroup quota support)
 - rust-lang#91062 (rustdoc: Consolidate static-file replacement mechanism)
 - rust-lang#91208 (Account for incorrect `where T::Assoc = Ty` bound)
 - rust-lang#91266 (Use non-generic inner function for pointer formatting)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
@bors bors merged commit 14ef447 into rust-lang:master Nov 27, 2021
@rustbot rustbot added this to the 1.59.0 milestone Nov 27, 2021
wip-sync pushed a commit to NetBSD/pkgsrc-wip that referenced this pull request Mar 2, 2022
Pkgsrc changes:
 * Bump available bootstraps to 1.58.1.
 * Adjust one patch (and checksum) so that it still applies.

Upstream changes:

Version 1.59.0 (2022-02-24)
==========================

Language
--------

- [Stabilize default arguments for const generics][90207]
- [Stabilize destructuring assignment][90521]
- [Relax private in public lint on generic bounds and where clauses
  of trait impls][90586]
- [Stabilize asm! and global_asm! for x86, x86_64, ARM, Aarch64,
  and RISC-V][91728]

Compiler
--------

- [Stabilize new symbol mangling format, leaving it opt-in
  (-Csymbol-mangling-version=v0)][90128]
- [Emit LLVM optimization remarks when enabled with `-Cremark`][90833]
- [Fix sparc64 ABI for aggregates with floating point members][91003]
- [Warn when a `#[test]`-like built-in attribute macro is present
  multiple times.][91172]
- [Add support for riscv64gc-unknown-freebsd][91284]
- [Stabilize `-Z emit-future-incompat` as `--json future-incompat`][91535]
- [Soft disable incremental compilation][94124]

This release disables incremental compilation, unless the user has explicitly
opted in via the newly added RUSTC_FORCE_INCREMENTAL=1 environment variable.
This is due to a known and relatively frequently occurring bug in incremental
compilation, which causes builds to issue internal compiler errors. This
particular bug is already fixed on nightly, but that fix has not yet rolled out
to stable and is deemed too risky for a direct stable backport.

As always, we encourage users to test with nightly and report bugs so that we
can track failures and fix issues earlier.

See [94124] for more details.

[94124]: rust-lang/rust#94124

Libraries
---------

- [Remove unnecessary bounds for some Hash{Map,Set} methods][91593]

Stabilized APIs
---------------

- [`std::thread::available_parallelism`][available_parallelism]
- [`Result::copied`][result-copied]
- [`Result::cloned`][result-cloned]
- [`arch::asm!`][asm]
- [`arch::global_asm!`][global_asm]
- [`ops::ControlFlow::is_break`][is_break]
- [`ops::ControlFlow::is_continue`][is_continue]
- [`TryFrom<char> for u8`][try_from_char_u8]
- [`char::TryFromCharError`][try_from_char_err]
  implementing `Clone`, `Debug`, `Display`, `PartialEq`, `Copy`, `Eq`, `Error`
- [`iter::zip`][zip]
- [`NonZeroU8::is_power_of_two`][is_power_of_two8]
- [`NonZeroU16::is_power_of_two`][is_power_of_two16]
- [`NonZeroU32::is_power_of_two`][is_power_of_two32]
- [`NonZeroU64::is_power_of_two`][is_power_of_two64]
- [`NonZeroU128::is_power_of_two`][is_power_of_two128]
- [`DoubleEndedIterator for ToLowercase`][lowercase]
- [`DoubleEndedIterator for ToUppercase`][uppercase]
- [`TryFrom<&mut [T]> for [T; N]`][tryfrom_ref_arr]
- [`UnwindSafe for Once`][unwindsafe_once]
- [`RefUnwindSafe for Once`][refunwindsafe_once]
- [armv8 neon intrinsics for aarch64][stdarch/1266]

Const-stable:

- [`mem::MaybeUninit::as_ptr`][muninit_ptr]
- [`mem::MaybeUninit::assume_init`][muninit_init]
- [`mem::MaybeUninit::assume_init_ref`][muninit_init_ref]
- [`ffi::CStr::from_bytes_with_nul_unchecked`][cstr_from_bytes]

Cargo
-----

- [Stabilize the `strip` profile option][cargo/10088]
- [Stabilize future-incompat-report][cargo/10165]
- [Support abbreviating `--release` as `-r`][cargo/10133]
- [Support `term.quiet` configuration][cargo/10152]
- [Remove `--host` from cargo {publish,search,login}][cargo/10145]

Compatibility Notes
-------------------

- [Refactor weak symbols in std::sys::unix][90846]
  This may add new, versioned, symbols when building with a newer glibc, as the
  standard library uses weak linkage rather than dynamically attempting to load
  certain symbols at runtime.
- [Deprecate crate_type and crate_name nested inside `#![cfg_attr]`][83744]
  This adds a future compatibility lint to supporting the use of cfg_attr
  wrapping either crate_type or crate_name specification within Rust files;
  it is recommended that users migrate to setting the equivalent command line
  flags.
- [Remove effect of `#[no_link]` attribute on name resolution][92034]
  This may expose new names, leading to conflicts with preexisting names in a
  given namespace and a compilation failure.
- [Cargo will document libraries before binaries.][cargo/10172]
- [Respect doc=false in dependencies, not just the root crate][cargo/10201]
- [Weaken guarantee around advancing underlying iterators in zip][83791]
- [Make split_inclusive() on an empty slice yield an empty output][89825]
- [Update std::env::temp_dir to use GetTempPath2 on Windows when
  available.][89999]
- [unreachable! was updated to match other formatting macro behavior
  on Rust 2021][92137]

Internal Changes
----------------

These changes provide no direct user facing benefits, but represent significant
improvements to the internals and overall performance of rustc
and related tools.

- [Fix many cases of normalization-related ICEs][91255]
- [Replace dominators algorithm with simple Lengauer-Tarjan][85013]
- [Store liveness in interval sets for region inference][90637]

- [Remove `in_band_lifetimes` from the compiler and standard library,
  in preparation for removing this unstable feature.][91867]

[91867]: rust-lang/rust#91867
[83744]: rust-lang/rust#83744
[83791]: rust-lang/rust#83791
[85013]: rust-lang/rust#85013
[89825]: rust-lang/rust#89825
[89999]: rust-lang/rust#89999
[90128]: rust-lang/rust#90128
[90207]: rust-lang/rust#90207
[90521]: rust-lang/rust#90521
[90586]: rust-lang/rust#90586
[90637]: rust-lang/rust#90637
[90833]: rust-lang/rust#90833
[90846]: rust-lang/rust#90846
[91003]: rust-lang/rust#91003
[91172]: rust-lang/rust#91172
[91255]: rust-lang/rust#91255
[91284]: rust-lang/rust#91284
[91535]: rust-lang/rust#91535
[91593]: rust-lang/rust#91593
[91728]: rust-lang/rust#91728
[91878]: rust-lang/rust#91878
[91896]: rust-lang/rust#91896
[91926]: rust-lang/rust#91926
[91984]: rust-lang/rust#91984
[92020]: rust-lang/rust#92020
[92034]: rust-lang/rust#92034
[92483]: rust-lang/rust#92483
[cargo/10088]: rust-lang/cargo#10088
[cargo/10133]: rust-lang/cargo#10133
[cargo/10145]: rust-lang/cargo#10145
[cargo/10152]: rust-lang/cargo#10152
[cargo/10165]: rust-lang/cargo#10165
[cargo/10172]: rust-lang/cargo#10172
[cargo/10201]: rust-lang/cargo#10201
[cargo/10269]: rust-lang/cargo#10269

[cstr_from_bytes]: https://doc.rust-lang.org/stable/std/ffi/struct.CStr.html#method.from_bytes_with_nul_unchecked
[muninit_ptr]: https://doc.rust-lang.org/stable/std/mem/union.MaybeUninit.html#method.as_ptr
[muninit_init]: https://doc.rust-lang.org/stable/std/mem/union.MaybeUninit.html#method.assume_init
[muninit_init_ref]: https://doc.rust-lang.org/stable/std/mem/union.MaybeUninit.html#method.assume_init_ref
[unwindsafe_once]: https://doc.rust-lang.org/stable/std/sync/struct.Once.html#impl-UnwindSafe
[refunwindsafe_once]: https://doc.rust-lang.org/stable/std/sync/struct.Once.html#impl-RefUnwindSafe
[tryfrom_ref_arr]: https://doc.rust-lang.org/stable/std/convert/trait.TryFrom.html#impl-TryFrom%3C%26%27_%20mut%20%5BT%5D%3E
[lowercase]: https://doc.rust-lang.org/stable/std/char/struct.ToLowercase.html#impl-DoubleEndedIterator
[uppercase]: https://doc.rust-lang.org/stable/std/char/struct.ToUppercase.html#impl-DoubleEndedIterator
[try_from_char_err]: https://doc.rust-lang.org/stable/std/char/struct.TryFromCharError.html
[available_parallelism]: https://doc.rust-lang.org/stable/std/thread/fn.available_parallelism.html
[result-copied]: https://doc.rust-lang.org/stable/std/result/enum.Result.html#method.copied
[result-cloned]: https://doc.rust-lang.org/stable/std/result/enum.Result.html#method.cloned
[asm]: https://doc.rust-lang.org/stable/core/arch/macro.asm.html
[global_asm]: https://doc.rust-lang.org/stable/core/arch/macro.global_asm.html
[is_break]: https://doc.rust-lang.org/stable/std/ops/enum.ControlFlow.html#method.is_break
[is_continue]: https://doc.rust-lang.org/stable/std/ops/enum.ControlFlow.html#method.is_continue
[try_from_char_u8]: https://doc.rust-lang.org/stable/std/primitive.char.html#impl-TryFrom%3Cchar%3E
[zip]: https://doc.rust-lang.org/stable/std/iter/fn.zip.html
[is_power_of_two8]: https://doc.rust-lang.org/stable/core/num/struct.NonZeroU8.html#method.is_power_of_two
[is_power_of_two16]: https://doc.rust-lang.org/stable/core/num/struct.NonZeroU16.html#method.is_power_of_two
[is_power_of_two32]: https://doc.rust-lang.org/stable/core/num/struct.NonZeroU32.html#method.is_power_of_two
[is_power_of_two64]: https://doc.rust-lang.org/stable/core/num/struct.NonZeroU64.html#method.is_power_of_two
[is_power_of_two128]: https://doc.rust-lang.org/stable/core/num/struct.NonZeroU128.html#method.is_power_of_two
[stdarch/1266]: rust-lang/stdarch#1266
netbsd-srcmastr pushed a commit to NetBSD/pkgsrc that referenced this pull request Apr 15, 2022
Pkgsrc changes:
 * Bump available bootstraps to 1.58.1.
 * Adjust one patch (and checksum) so that it still applies.

Upstream changes:

Version 1.59.0 (2022-02-24)
==========================

Language
--------

- [Stabilize default arguments for const generics][90207]
- [Stabilize destructuring assignment][90521]
- [Relax private in public lint on generic bounds and where clauses
  of trait impls][90586]
- [Stabilize asm! and global_asm! for x86, x86_64, ARM, Aarch64,
  and RISC-V][91728]

Compiler
--------

- [Stabilize new symbol mangling format, leaving it opt-in
  (-Csymbol-mangling-version=v0)][90128]
- [Emit LLVM optimization remarks when enabled with `-Cremark`][90833]
- [Fix sparc64 ABI for aggregates with floating point members][91003]
- [Warn when a `#[test]`-like built-in attribute macro is present
  multiple times.][91172]
- [Add support for riscv64gc-unknown-freebsd][91284]
- [Stabilize `-Z emit-future-incompat` as `--json future-incompat`][91535]
- [Soft disable incremental compilation][94124]

This release disables incremental compilation, unless the user has explicitly
opted in via the newly added RUSTC_FORCE_INCREMENTAL=1 environment variable.
This is due to a known and relatively frequently occurring bug in incremental
compilation, which causes builds to issue internal compiler errors. This
particular bug is already fixed on nightly, but that fix has not yet rolled out
to stable and is deemed too risky for a direct stable backport.

As always, we encourage users to test with nightly and report bugs so that we
can track failures and fix issues earlier.

See [94124] for more details.

[94124]: rust-lang/rust#94124

Libraries
---------

- [Remove unnecessary bounds for some Hash{Map,Set} methods][91593]

Stabilized APIs
---------------

- [`std::thread::available_parallelism`][available_parallelism]
- [`Result::copied`][result-copied]
- [`Result::cloned`][result-cloned]
- [`arch::asm!`][asm]
- [`arch::global_asm!`][global_asm]
- [`ops::ControlFlow::is_break`][is_break]
- [`ops::ControlFlow::is_continue`][is_continue]
- [`TryFrom<char> for u8`][try_from_char_u8]
- [`char::TryFromCharError`][try_from_char_err]
  implementing `Clone`, `Debug`, `Display`, `PartialEq`, `Copy`, `Eq`, `Error`
- [`iter::zip`][zip]
- [`NonZeroU8::is_power_of_two`][is_power_of_two8]
- [`NonZeroU16::is_power_of_two`][is_power_of_two16]
- [`NonZeroU32::is_power_of_two`][is_power_of_two32]
- [`NonZeroU64::is_power_of_two`][is_power_of_two64]
- [`NonZeroU128::is_power_of_two`][is_power_of_two128]
- [`DoubleEndedIterator for ToLowercase`][lowercase]
- [`DoubleEndedIterator for ToUppercase`][uppercase]
- [`TryFrom<&mut [T]> for [T; N]`][tryfrom_ref_arr]
- [`UnwindSafe for Once`][unwindsafe_once]
- [`RefUnwindSafe for Once`][refunwindsafe_once]
- [armv8 neon intrinsics for aarch64][stdarch/1266]

Const-stable:

- [`mem::MaybeUninit::as_ptr`][muninit_ptr]
- [`mem::MaybeUninit::assume_init`][muninit_init]
- [`mem::MaybeUninit::assume_init_ref`][muninit_init_ref]
- [`ffi::CStr::from_bytes_with_nul_unchecked`][cstr_from_bytes]

Cargo
-----

- [Stabilize the `strip` profile option][cargo/10088]
- [Stabilize future-incompat-report][cargo/10165]
- [Support abbreviating `--release` as `-r`][cargo/10133]
- [Support `term.quiet` configuration][cargo/10152]
- [Remove `--host` from cargo {publish,search,login}][cargo/10145]

Compatibility Notes
-------------------

- [Refactor weak symbols in std::sys::unix][90846]
  This may add new, versioned, symbols when building with a newer glibc, as the
  standard library uses weak linkage rather than dynamically attempting to load
  certain symbols at runtime.
- [Deprecate crate_type and crate_name nested inside `#![cfg_attr]`][83744]
  This adds a future compatibility lint to supporting the use of cfg_attr
  wrapping either crate_type or crate_name specification within Rust files;
  it is recommended that users migrate to setting the equivalent command line
  flags.
- [Remove effect of `#[no_link]` attribute on name resolution][92034]
  This may expose new names, leading to conflicts with preexisting names in a
  given namespace and a compilation failure.
- [Cargo will document libraries before binaries.][cargo/10172]
- [Respect doc=false in dependencies, not just the root crate][cargo/10201]
- [Weaken guarantee around advancing underlying iterators in zip][83791]
- [Make split_inclusive() on an empty slice yield an empty output][89825]
- [Update std::env::temp_dir to use GetTempPath2 on Windows when
  available.][89999]
- [unreachable! was updated to match other formatting macro behavior
  on Rust 2021][92137]

Internal Changes
----------------

These changes provide no direct user facing benefits, but represent significant
improvements to the internals and overall performance of rustc
and related tools.

- [Fix many cases of normalization-related ICEs][91255]
- [Replace dominators algorithm with simple Lengauer-Tarjan][85013]
- [Store liveness in interval sets for region inference][90637]

- [Remove `in_band_lifetimes` from the compiler and standard library,
  in preparation for removing this unstable feature.][91867]

[91867]: rust-lang/rust#91867
[83744]: rust-lang/rust#83744
[83791]: rust-lang/rust#83791
[85013]: rust-lang/rust#85013
[89825]: rust-lang/rust#89825
[89999]: rust-lang/rust#89999
[90128]: rust-lang/rust#90128
[90207]: rust-lang/rust#90207
[90521]: rust-lang/rust#90521
[90586]: rust-lang/rust#90586
[90637]: rust-lang/rust#90637
[90833]: rust-lang/rust#90833
[90846]: rust-lang/rust#90846
[91003]: rust-lang/rust#91003
[91172]: rust-lang/rust#91172
[91255]: rust-lang/rust#91255
[91284]: rust-lang/rust#91284
[91535]: rust-lang/rust#91535
[91593]: rust-lang/rust#91593
[91728]: rust-lang/rust#91728
[91878]: rust-lang/rust#91878
[91896]: rust-lang/rust#91896
[91926]: rust-lang/rust#91926
[91984]: rust-lang/rust#91984
[92020]: rust-lang/rust#92020
[92034]: rust-lang/rust#92034
[92483]: rust-lang/rust#92483
[cargo/10088]: rust-lang/cargo#10088
[cargo/10133]: rust-lang/cargo#10133
[cargo/10145]: rust-lang/cargo#10145
[cargo/10152]: rust-lang/cargo#10152
[cargo/10165]: rust-lang/cargo#10165
[cargo/10172]: rust-lang/cargo#10172
[cargo/10201]: rust-lang/cargo#10201
[cargo/10269]: rust-lang/cargo#10269

[cstr_from_bytes]: https://doc.rust-lang.org/stable/std/ffi/struct.CStr.html#method.from_bytes_with_nul_unchecked
[muninit_ptr]: https://doc.rust-lang.org/stable/std/mem/union.MaybeUninit.html#method.as_ptr
[muninit_init]: https://doc.rust-lang.org/stable/std/mem/union.MaybeUninit.html#method.assume_init
[muninit_init_ref]: https://doc.rust-lang.org/stable/std/mem/union.MaybeUninit.html#method.assume_init_ref
[unwindsafe_once]: https://doc.rust-lang.org/stable/std/sync/struct.Once.html#impl-UnwindSafe
[refunwindsafe_once]: https://doc.rust-lang.org/stable/std/sync/struct.Once.html#impl-RefUnwindSafe
[tryfrom_ref_arr]: https://doc.rust-lang.org/stable/std/convert/trait.TryFrom.html#impl-TryFrom%3C%26%27_%20mut%20%5BT%5D%3E
[lowercase]: https://doc.rust-lang.org/stable/std/char/struct.ToLowercase.html#impl-DoubleEndedIterator
[uppercase]: https://doc.rust-lang.org/stable/std/char/struct.ToUppercase.html#impl-DoubleEndedIterator
[try_from_char_err]: https://doc.rust-lang.org/stable/std/char/struct.TryFromCharError.html
[available_parallelism]: https://doc.rust-lang.org/stable/std/thread/fn.available_parallelism.html
[result-copied]: https://doc.rust-lang.org/stable/std/result/enum.Result.html#method.copied
[result-cloned]: https://doc.rust-lang.org/stable/std/result/enum.Result.html#method.cloned
[asm]: https://doc.rust-lang.org/stable/core/arch/macro.asm.html
[global_asm]: https://doc.rust-lang.org/stable/core/arch/macro.global_asm.html
[is_break]: https://doc.rust-lang.org/stable/std/ops/enum.ControlFlow.html#method.is_break
[is_continue]: https://doc.rust-lang.org/stable/std/ops/enum.ControlFlow.html#method.is_continue
[try_from_char_u8]: https://doc.rust-lang.org/stable/std/primitive.char.html#impl-TryFrom%3Cchar%3E
[zip]: https://doc.rust-lang.org/stable/std/iter/fn.zip.html
[is_power_of_two8]: https://doc.rust-lang.org/stable/core/num/struct.NonZeroU8.html#method.is_power_of_two
[is_power_of_two16]: https://doc.rust-lang.org/stable/core/num/struct.NonZeroU16.html#method.is_power_of_two
[is_power_of_two32]: https://doc.rust-lang.org/stable/core/num/struct.NonZeroU32.html#method.is_power_of_two
[is_power_of_two64]: https://doc.rust-lang.org/stable/core/num/struct.NonZeroU64.html#method.is_power_of_two
[is_power_of_two128]: https://doc.rust-lang.org/stable/core/num/struct.NonZeroU128.html#method.is_power_of_two
[stdarch/1266]: rust-lang/stdarch#1266
@dtolnay dtolnay self-assigned this Mar 24, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
disposition-merge This issue / PR is in PFCP or FCP with a disposition to merge it. finished-final-comment-period The final comment period is finished for this PR / Issue. S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.