Auto merge of #148179 - cuviper:stable-next, r=cuviper

[stable] Prepare Rust 1.91.0 release

- [beta-1.91] Add more context to the temporary lifetime extension FCW rust-lang/rust#148174
- rustdoc-search: JavaScript optimization based on Firefox Profiler output rust-lang/rust#146484
- rustdoc-search: use the same ID for entry and path to same item rust-lang/rust#147045
- rustdoc-search: stringdex update with more packing rust-lang/rust#147002
- rustdoc-search: stringdex 0.0.2 rust-lang/rust#147660
- [beta] Clippy beta backport rust-lang/rust#148029
- 1.91.0 release notes rust-lang/rust#148013

r? cuviper
This commit is contained in:
bors 2025-10-27 20:35:19 +00:00
commit 40c4f6dfcd
16 changed files with 1061 additions and 220 deletions

View file

@ -5216,9 +5216,9 @@ dependencies = [
[[package]]
name = "stringdex"
version = "0.0.1-alpha9"
version = "0.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7081029913fd7d591c0112182aba8c98ae886b4f12edb208130496cd17dc3c15"
checksum = "18b3bd4f10d15ef859c40291769f0d85209de6b0f1c30713ff9cdf45ac43ea36"
dependencies = [
"stacker",
]

View file

@ -1,3 +1,340 @@
Version 1.91.0 (2025-10-30)
==========================
<a id="1.91.0-Language"></a>
Language
--------
- [Lower pattern bindings in the order they're written and base drop order on primary bindings' order](https://github.com/rust-lang/rust/pull/143764)
- [Stabilize declaration of C-style variadic functions for `sysv64`, `win64`, `efiapi`, and `aapcs` ABIs](https://github.com/rust-lang/rust/pull/144066).
This brings these ABIs in line with the C ABI: variadic functions can be declared in extern blocks but not defined.
- [Add `dangling_pointers_from_locals` lint to warn against dangling pointers from local variables](https://github.com/rust-lang/rust/pull/144322)
- [Upgrade `semicolon_in_expressions_from_macros` from warn to deny](https://github.com/rust-lang/rust/pull/144369)
- [Stabilize LoongArch32 inline assembly](https://github.com/rust-lang/rust/pull/144402)
- [Add warn-by-default `integer_to_ptr_transmutes` lint against integer-to-pointer transmutes](https://github.com/rust-lang/rust/pull/144531)
- [Stabilize `sse4a` and `tbm` target features](https://github.com/rust-lang/rust/pull/144542)
- [Add `target_env = "macabi"` and `target_env = "sim"` cfgs](https://github.com/rust-lang/rust/pull/139451) as replacements for the `target_abi` cfgs with the same values.
<a id="1.91.0-Compiler"></a>
Compiler
--------
- [Don't warn on never-to-any `as` casts as unreachable](https://github.com/rust-lang/rust/pull/144804)
<a id="1.91.0-Platform-Support"></a>
Platform Support
----------------
- [Promote `aarch64-pc-windows-gnullvm` and `x86_64-pc-windows-gnullvm` to Tier 2 with host tools.](https://github.com/rust-lang/rust/pull/143031)
Note: llvm-tools and MSI installers are missing but will be added in future releases.
- [Promote `aarch64-pc-windows-msvc` to Tier 1](https://github.com/rust-lang/rust/pull/145682)
Refer to Rust's [platform support page][platform-support-doc]
for more information on Rust's tiered platform support.
[platform-support-doc]: https://doc.rust-lang.org/rustc/platform-support.html
<a id="1.91.0-Libraries"></a>
Libraries
---------
- [Print thread ID in panic message](https://github.com/rust-lang/rust/pull/115746)
- [Fix overly restrictive lifetime in `core::panic::Location::file` return type](https://github.com/rust-lang/rust/pull/132087)
- [Guarantee parameter order for `_by()` variants of `min` / `max`/ `minmax` in `std::cmp`](https://github.com/rust-lang/rust/pull/139357)
- [Document assumptions about `Clone` and `Eq` traits](https://github.com/rust-lang/rust/pull/144330/)
- [`std::thread`: Return error if setting thread stack size fails](https://github.com/rust-lang/rust/pull/144210)
This used to panic within the standard library.
<a id="1.91.0-Stabilized-APIs"></a>
Stabilized APIs
---------------
- [`Path::file_prefix`](https://doc.rust-lang.org/stable/std/path/struct.Path.html#method.file_prefix)
- [`AtomicPtr::fetch_ptr_add`](https://doc.rust-lang.org/stable/std/sync/atomic/struct.AtomicPtr.html#method.fetch_ptr_add)
- [`AtomicPtr::fetch_ptr_sub`](https://doc.rust-lang.org/stable/std/sync/atomic/struct.AtomicPtr.html#method.fetch_ptr_sub)
- [`AtomicPtr::fetch_byte_add`](https://doc.rust-lang.org/stable/std/sync/atomic/struct.AtomicPtr.html#method.fetch_byte_add)
- [`AtomicPtr::fetch_byte_sub`](https://doc.rust-lang.org/stable/std/sync/atomic/struct.AtomicPtr.html#method.fetch_byte_sub)
- [`AtomicPtr::fetch_or`](https://doc.rust-lang.org/stable/std/sync/atomic/struct.AtomicPtr.html#method.fetch_or)
- [`AtomicPtr::fetch_and`](https://doc.rust-lang.org/stable/std/sync/atomic/struct.AtomicPtr.html#method.fetch_and)
- [`AtomicPtr::fetch_xor`](https://doc.rust-lang.org/stable/std/sync/atomic/struct.AtomicPtr.html#method.fetch_xor)
- [`{integer}::strict_add`](https://doc.rust-lang.org/stable/std/primitive.u32.html#method.strict_add)
- [`{integer}::strict_sub`](https://doc.rust-lang.org/stable/std/primitive.u32.html#method.strict_sub)
- [`{integer}::strict_mul`](https://doc.rust-lang.org/stable/std/primitive.u32.html#method.strict_mul)
- [`{integer}::strict_div`](https://doc.rust-lang.org/stable/std/primitive.i32.html#method.strict_div)
- [`{integer}::strict_div_euclid`](https://doc.rust-lang.org/stable/std/primitive.i32.html#method.strict_div_euclid)
- [`{integer}::strict_rem`](https://doc.rust-lang.org/stable/std/primitive.i32.html#method.strict_rem)
- [`{integer}::strict_rem_euclid`](https://doc.rust-lang.org/stable/std/primitive.i32.html#method.strict_rem_euclid)
- [`{integer}::strict_neg`](https://doc.rust-lang.org/stable/std/primitive.u32.html#method.strict_neg)
- [`{integer}::strict_shl`](https://doc.rust-lang.org/stable/std/primitive.u32.html#method.strict_shl)
- [`{integer}::strict_shr`](https://doc.rust-lang.org/stable/std/primitive.u32.html#method.strict_shr)
- [`{integer}::strict_pow`](https://doc.rust-lang.org/stable/std/primitive.u32.html#method.strict_pow)
- [`i{N}::strict_add_unsigned`](https://doc.rust-lang.org/stable/std/primitive.i32.html#method.strict_add_unsigned)
- [`i{N}::strict_sub_unsigned`](https://doc.rust-lang.org/stable/std/primitive.i32.html#method.strict_sub_unsigned)
- [`i{N}::strict_abs`](https://doc.rust-lang.org/stable/std/primitive.i32.html#method.strict_abs)
- [`u{N}::strict_add_signed`](https://doc.rust-lang.org/stable/std/primitive.u32.html#method.strict_add_signed)
- [`u{N}::strict_sub_signed`](https://doc.rust-lang.org/stable/std/primitive.u32.html#method.strict_sub_signed)
- [`PanicHookInfo::payload_as_str`](https://doc.rust-lang.org/stable/std/panic/struct.PanicHookInfo.html#method.payload_as_str)
- [`core::iter::chain`](https://doc.rust-lang.org/stable/core/iter/fn.chain.html)
- [`u{N}::checked_signed_diff`](https://doc.rust-lang.org/stable/std/primitive.u16.html#method.checked_signed_diff)
- [`core::array::repeat`](https://doc.rust-lang.org/stable/core/array/fn.repeat.html)
- [`PathBuf::add_extension`](https://doc.rust-lang.org/stable/std/path/struct.PathBuf.html#method.add_extension)
- [`PathBuf::with_added_extension`](https://doc.rust-lang.org/stable/std/path/struct.PathBuf.html#method.with_added_extension)
- [`Duration::from_mins`](https://doc.rust-lang.org/stable/std/time/struct.Duration.html#method.from_mins)
- [`Duration::from_hours`](https://doc.rust-lang.org/stable/std/time/struct.Duration.html#method.from_hours)
- [`impl PartialEq<str> for PathBuf`](https://doc.rust-lang.org/stable/std/path/struct.PathBuf.html#impl-PartialEq%3Cstr%3E-for-PathBuf)
- [`impl PartialEq<String> for PathBuf`](https://doc.rust-lang.org/stable/std/path/struct.PathBuf.html#impl-PartialEq%3CString%3E-for-PathBuf)
- [`impl PartialEq<str> for Path`](https://doc.rust-lang.org/stable/std/path/struct.Path.html#impl-PartialEq%3Cstr%3E-for-Path)
- [`impl PartialEq<String> for Path`](https://doc.rust-lang.org/stable/std/path/struct.Path.html#impl-PartialEq%3CString%3E-for-Path)
- [`impl PartialEq<PathBuf> for String`](https://doc.rust-lang.org/stable/std/string/struct.String.html#impl-PartialEq%3CPathBuf%3E-for-String)
- [`impl PartialEq<Path> for String`](https://doc.rust-lang.org/stable/std/string/struct.String.html#impl-PartialEq%3CPath%3E-for-String)
- [`impl PartialEq<PathBuf> for str`](https://doc.rust-lang.org/stable/std/primitive.str.html#impl-PartialEq%3CPathBuf%3E-for-str)
- [`impl PartialEq<Path> for str`](https://doc.rust-lang.org/stable/std/primitive.str.html#impl-PartialEq%3CPath%3E-for-str)
- [`Ipv4Addr::from_octets`](https://doc.rust-lang.org/stable/std/net/struct.Ipv4Addr.html#method.from_octets)
- [`Ipv6Addr::from_octets`](https://doc.rust-lang.org/stable/std/net/struct.Ipv6Addr.html#method.from_octets)
- [`Ipv6Addr::from_segments`](https://doc.rust-lang.org/stable/std/net/struct.Ipv6Addr.html#method.from_segments)
- [`impl<T> Default for Pin<Box<T>> where Box<T>: Default, T: ?Sized`](https://doc.rust-lang.org/stable/std/default/trait.Default.html#impl-Default-for-Pin%3CBox%3CT%3E%3E)
- [`impl<T> Default for Pin<Rc<T>> where Rc<T>: Default, T: ?Sized`](https://doc.rust-lang.org/stable/std/default/trait.Default.html#impl-Default-for-Pin%3CRc%3CT%3E%3E)
- [`impl<T> Default for Pin<Arc<T>> where Arc<T>: Default, T: ?Sized`](https://doc.rust-lang.org/stable/std/default/trait.Default.html#impl-Default-for-Pin%3CArc%3CT%3E%3E)
- [`Cell::as_array_of_cells`](https://doc.rust-lang.org/stable/std/cell/struct.Cell.html#method.as_array_of_cells)
- [`u{N}::carrying_add`](https://doc.rust-lang.org/stable/std/primitive.u64.html#method.carrying_add)
- [`u{N}::borrowing_sub`](https://doc.rust-lang.org/stable/std/primitive.u64.html#method.borrowing_sub)
- [`u{N}::carrying_mul`](https://doc.rust-lang.org/stable/std/primitive.u64.html#method.carrying_mul)
- [`u{N}::carrying_mul_add`](https://doc.rust-lang.org/stable/std/primitive.u64.html#method.carrying_mul_add)
- [`BTreeMap::extract_if`](https://doc.rust-lang.org/stable/std/collections/struct.BTreeMap.html#method.extract_if)
- [`BTreeSet::extract_if`](https://doc.rust-lang.org/stable/std/collections/struct.BTreeSet.html#method.extract_if)
- [`impl Debug for windows::ffi::EncodeWide<'_>`](https://doc.rust-lang.org/stable/std/os/windows/ffi/struct.EncodeWide.html#impl-Debug-for-EncodeWide%3C'_%3E)
- [`str::ceil_char_boundary`](https://doc.rust-lang.org/stable/std/primitive.str.html#method.ceil_char_boundary)
- [`str::floor_char_boundary`](https://doc.rust-lang.org/stable/std/primitive.str.html#method.floor_char_boundary)
- [`impl Sum for Saturating<u{N}>`](https://doc.rust-lang.org/stable/std/num/struct.Saturating.html#impl-Sum-for-Saturating%3Cu32%3E)
- [`impl Sum<&Self> for Saturating<u{N}>`](https://doc.rust-lang.org/stable/std/num/struct.Saturating.html#impl-Sum%3C%26Saturating%3Cu32%3E%3E-for-Saturating%3Cu32%3E)
- [`impl Product for Saturating<u{N}>`](https://doc.rust-lang.org/stable/std/num/struct.Saturating.html#impl-Product-for-Saturating%3Cu32%3E)
- [`impl Product<&Self> for Saturating<u{N}>`](https://doc.rust-lang.org/stable/std/num/struct.Saturating.html#impl-Product%3C%26Saturating%3Cu32%3E%3E-for-Saturating%3Cu32%3E)
These previously stable APIs are now stable in const contexts:
- [`<[T; N]>::each_ref`](https://doc.rust-lang.org/stable/std/primitive.array.html#method.each_ref)
- [`<[T; N]>::each_mut`](https://doc.rust-lang.org/stable/std/primitive.array.html#method.each_mut)
- [`OsString::new`](https://doc.rust-lang.org/stable/std/ffi/struct.OsString.html#method.new)
- [`PathBuf::new`](https://doc.rust-lang.org/stable/std/path/struct.PathBuf.html#method.new)
- [`TypeId::of`](https://doc.rust-lang.org/stable/std/any/struct.TypeId.html#method.of)
- [`ptr::with_exposed_provenance`](https://doc.rust-lang.org/stable/std/ptr/fn.with_exposed_provenance.html)
- [`ptr::with_exposed_provenance_mut`](https://doc.rust-lang.org/stable/std/ptr/fn.with_exposed_provenance_mut.html)
<a id="1.91.0-Cargo"></a>
Cargo
-----
- 🎉 Stabilize `build.build-dir`.
This config sets the directory where intermediate build artifacts are stored.
These artifacts are produced by Cargo and rustc during the build process.
End users usually won't need to interact with them, and the layout inside
`build-dir` is an implementation detail that may change without notice.
([config doc](https://doc.rust-lang.org/stable/cargo/reference/config.html#buildbuild-dir))
([build cache doc](https://doc.rust-lang.org/stable/cargo/reference/build-cache.html))
[#15833](https://github.com/rust-lang/cargo/pull/15833)
[#15840](https://github.com/rust-lang/cargo/pull/15840)
- The `--target` flag and the `build.target` configuration can now take literal
`"host-tuple"` string, which will internally be substituted by the host
machine's target triple.
[#15838](https://github.com/rust-lang/cargo/pull/15838)
[#16003](https://github.com/rust-lang/cargo/pull/16003)
[#16032](https://github.com/rust-lang/cargo/pull/16032)
<a id="1.91.0-Rustdoc"></a>
Rustdoc
-----
- [In search results, rank doc aliases lower than non-alias items with the same name](https://github.com/rust-lang/rust/pull/145100)
- [Raw pointers now work in type-based search like references](https://github.com/rust-lang/rust/pull/145731). This means you can now search for things like `*const u8 ->`, and additionally functions that take or return raw pointers will now display their signature properly in search results.
<a id="1.91.0-Compatibility-Notes"></a>
Compatibility Notes
-------------------
- [Always require coroutine captures to be drop-live](https://github.com/rust-lang/rust/pull/144156)
- [Apple: Always pass SDK root when linking with `cc`, and pass it via `SDKROOT` env var](https://github.com/rust-lang/rust/pull/131477). This should fix linking issues with `rustc` running inside Xcode. Libraries in `/usr/local/lib` may no longer be linked automatically, if you develop or use a crate that relies on this, you should explicitly set `cargo::rustc-link-search=/usr/local/lib` in a `build.rs` script.
- [Relaxed bounds in associated type bound position like in `TraitRef<AssocTy: ?Sized>` are now correctly forbidden](https://github.com/rust-lang/rust/pull/135331)
- [Add unstable `#[sanitize(xyz = "on|off")]` built-in attribute that shadows procedural macros with the same name](https://github.com/rust-lang/rust/pull/142681)
- [Fix the drop checker being more permissive for bindings declared with let-else](https://github.com/rust-lang/rust/pull/143028)
- [Be more strict when parsing attributes, erroring on many invalid attributes](https://github.com/rust-lang/rust/pull/144689)
- [Error on invalid `#[should_panic]` attributes](https://github.com/rust-lang/rust/pull/143808)
- [Error on invalid `#[link]` attributes](https://github.com/rust-lang/rust/pull/143193)
- [Mark all deprecation lints in name resolution as deny-by-default and also report in dependencies](https://github.com/rust-lang/rust/pull/143929)
- The lint `semicolon_in_expressions_from_macros`, for `macro_rules!` macros in expression position that expand to end in a semicolon (`;`), is now deny-by-default. It was already warn-by-default, and a future compatibility warning (FCW) that warned even in dependencies. This lint will become a hard error in the future.
- [Trait impl modifiers (e.g., `unsafe`, `!`, `default`) in inherent impls are no longer syntactically valid](https://github.com/rust-lang/rust/pull/144386)
- [Start reporting future breakage for `ill_formed_attribute_input` in dependencies](https://github.com/rust-lang/rust/pull/144544)
- [Restrict the scope of temporaries created by the macros `pin!`, `format_args!`, `write!`, and `writeln!` in `if let` scrutinees in Rust Edition 2024.](https://github.com/rust-lang/rust/pull/145342) This applies [Rust Edition 2024's `if let` temporary scope rules](https://doc.rust-lang.org/edition-guide/rust-2024/temporary-if-let-scope.html) to these temporaries, which previously could live past the `if` expression regardless of Edition.
- [Invalid numeric literal suffixes in tuple indexing, tuple struct indexing, and struct field name positions are now correctly rejected](https://github.com/rust-lang/rust/pull/145463)
- [Closures marked with the keyword `static` are now syntactically invalid](https://github.com/rust-lang/rust/pull/145604)
- [Shebangs inside `--cfg` and `--check-cfg` arguments are no longer allowed](https://github.com/rust-lang/rust/pull/146211)
- [Add future incompatibility lint for temporary lifetime shortening in Rust 1.92](https://github.com/rust-lang/rust/pull/147056)
Cargo compatibility notes:
- `cargo publish` no longer keeps `.crate` tarballs as final build artifacts
when `build.build-dir` is set. These tarballs were previously included due to
an oversight and are now treated as intermediate artifacts.
To get `.crate` tarballs as final artifacts, use `cargo package`.
In a future version, this change will apply regardless of `build.build-dir`.
[#15910](https://github.com/rust-lang/cargo/pull/15910)
- Adjust Cargo messages to match rustc diagnostic style.
This changes some of the terminal colors used by Cargo messages.
[#15928](https://github.com/rust-lang/cargo/pull/15928)
- Tools and projects relying on the
[internal details of Cargo's `build-dir`](https://doc.rust-lang.org/cargo/reference/build-cache.html)
may not work for users changing their `build-dir` layout.
For those doing so, we'd recommend proactively testing these cases
particularly as we are considering changing the default location of the `build-dir` in the future
([cargo#16147](https://github.com/rust-lang/cargo/issues/16147)).
If you can't migrate off of Cargo's internal details,
we'd like to learn more about your use case as we prepare to change the layout of the `build-dir`
([cargo#15010](https://github.com/rust-lang/cargo/issues/15010)).
<a id="1.91.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.
- [Update to LLVM 21](https://github.com/rust-lang/rust/pull/143684)
Version 1.90.0 (2025-09-18)
===========================
<a id="1.90-Language"></a>
Language
--------
- [Split up the `unknown_or_malformed_diagnostic_attributes` lint](https://github.com/rust-lang/rust/pull/140717). This lint has been split up into four finer-grained lints, with `unknown_or_malformed_diagnostic_attributes` now being the lint group that contains these lints:
1. `unknown_diagnostic_attributes`: unknown to the current compiler
2. `misplaced_diagnostic_attributes`: placed on the wrong item
3. `malformed_diagnostic_attributes`: malformed attribute syntax or options
4. `malformed_diagnostic_format_literals`: malformed format string literal
- [Allow constants whose final value has references to mutable/external memory, but reject such constants as patterns](https://github.com/rust-lang/rust/pull/140942)
- [Allow volatile access to non-Rust memory, including address 0](https://github.com/rust-lang/rust/pull/141260)
<a id="1.90-Compiler"></a>
Compiler
--------
- [Use `lld` by default on `x86_64-unknown-linux-gnu`](https://github.com/rust-lang/rust/pull/140525).
- [Tier 3 `musl` targets now link dynamically by default](https://github.com/rust-lang/rust/pull/144410). Affected targets:
- `mips64-unknown-linux-muslabi64`
- `powerpc64-unknown-linux-musl`
- `powerpc-unknown-linux-musl`
- `powerpc-unknown-linux-muslspe`
- `riscv32gc-unknown-linux-musl`
- `s390x-unknown-linux-musl`
- `thumbv7neon-unknown-linux-musleabihf`
<a id="1.90-Platform-Support"></a>
Platform Support
----------------
- [Demote `x86_64-apple-darwin` to Tier 2 with host tools](https://github.com/rust-lang/rust/pull/145252)
Refer to Rust's [platform support page][platform-support-doc]
for more information on Rust's tiered platform support.
[platform-support-doc]: https://doc.rust-lang.org/rustc/platform-support.html
<a id="1.90-Libraries"></a>
Libraries
---------
- [Stabilize `u*::{checked,overflowing,saturating,wrapping}_sub_signed`](https://github.com/rust-lang/rust/issues/126043)
- [Allow comparisons between `CStr`, `CString`, and `Cow<CStr>`](https://github.com/rust-lang/rust/pull/137268)
- [Remove some unsized tuple impls since unsized tuples can't be constructed](https://github.com/rust-lang/rust/pull/138340)
- [Set `MSG_NOSIGNAL` for `UnixStream`](https://github.com/rust-lang/rust/pull/140005)
- [`proc_macro::Ident::new` now supports `$crate`.](https://github.com/rust-lang/rust/pull/141996)
- [Guarantee the pointer returned from `Thread::into_raw` has at least 8 bytes of alignment](https://github.com/rust-lang/rust/pull/143859)
<a id="1.90-Stabilized-APIs"></a>
Stabilized APIs
---------------
- [`u{n}::checked_sub_signed`](https://doc.rust-lang.org/stable/std/primitive.usize.html#method.checked_sub_signed)
- [`u{n}::overflowing_sub_signed`](https://doc.rust-lang.org/stable/std/primitive.usize.html#method.overflowing_sub_signed)
- [`u{n}::saturating_sub_signed`](https://doc.rust-lang.org/stable/std/primitive.usize.html#method.saturating_sub_signed)
- [`u{n}::wrapping_sub_signed`](https://doc.rust-lang.org/stable/std/primitive.usize.html#method.wrapping_sub_signed)
- [`impl Copy for IntErrorKind`](https://doc.rust-lang.org/stable/std/num/enum.IntErrorKind.html#impl-Copy-for-IntErrorKind)
- [`impl Hash for IntErrorKind`](https://doc.rust-lang.org/stable/std/num/enum.IntErrorKind.html#impl-Hash-for-IntErrorKind)
- [`impl PartialEq<&CStr> for CStr`](https://doc.rust-lang.org/stable/std/ffi/struct.CStr.html#impl-PartialEq%3C%26CStr%3E-for-CStr)
- [`impl PartialEq<CString> for CStr`](https://doc.rust-lang.org/stable/std/ffi/struct.CStr.html#impl-PartialEq%3CCString%3E-for-CStr)
- [`impl PartialEq<Cow<CStr>> for CStr`](https://doc.rust-lang.org/stable/std/ffi/struct.CStr.html#impl-PartialEq%3CCow%3C'_,+CStr%3E%3E-for-CStr)
- [`impl PartialEq<&CStr> for CString`](https://doc.rust-lang.org/stable/std/ffi/struct.CString.html#impl-PartialEq%3C%26CStr%3E-for-CString)
- [`impl PartialEq<CStr> for CString`](https://doc.rust-lang.org/stable/std/ffi/struct.CString.html#impl-PartialEq%3CCStr%3E-for-CString)
- [`impl PartialEq<Cow<CStr>> for CString`](https://doc.rust-lang.org/stable/std/ffi/struct.CString.html#impl-PartialEq%3CCow%3C'_,+CStr%3E%3E-for-CString)
- [`impl PartialEq<&CStr> for Cow<CStr>`](https://doc.rust-lang.org/stable/std/borrow/enum.Cow.html#impl-PartialEq%3C%26CStr%3E-for-Cow%3C'_,+CStr%3E)
- [`impl PartialEq<CStr> for Cow<CStr>`](https://doc.rust-lang.org/stable/std/borrow/enum.Cow.html#impl-PartialEq%3CCStr%3E-for-Cow%3C'_,+CStr%3E)
- [`impl PartialEq<CString> for Cow<CStr>`](https://doc.rust-lang.org/stable/std/borrow/enum.Cow.html#impl-PartialEq%3CCString%3E-for-Cow%3C'_,+CStr%3E)
These previously stable APIs are now stable in const contexts:
- [`<[T]>::reverse`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.reverse)
- [`f32::floor`](https://doc.rust-lang.org/stable/std/primitive.f32.html#method.floor)
- [`f32::ceil`](https://doc.rust-lang.org/stable/std/primitive.f32.html#method.ceil)
- [`f32::trunc`](https://doc.rust-lang.org/stable/std/primitive.f32.html#method.trunc)
- [`f32::fract`](https://doc.rust-lang.org/stable/std/primitive.f32.html#method.fract)
- [`f32::round`](https://doc.rust-lang.org/stable/std/primitive.f32.html#method.round)
- [`f32::round_ties_even`](https://doc.rust-lang.org/stable/std/primitive.f32.html#method.round_ties_even)
- [`f64::floor`](https://doc.rust-lang.org/stable/std/primitive.f64.html#method.floor)
- [`f64::ceil`](https://doc.rust-lang.org/stable/std/primitive.f64.html#method.ceil)
- [`f64::trunc`](https://doc.rust-lang.org/stable/std/primitive.f64.html#method.trunc)
- [`f64::fract`](https://doc.rust-lang.org/stable/std/primitive.f64.html#method.fract)
- [`f64::round`](https://doc.rust-lang.org/stable/std/primitive.f64.html#method.round)
- [`f64::round_ties_even`](https://doc.rust-lang.org/stable/std/primitive.f64.html#method.round_ties_even)
<a id="1.90-Cargo"></a>
Cargo
-----
- [Add `http.proxy-cainfo` config for proxy certs](https://github.com/rust-lang/cargo/pull/15374/)
- [Use `gix` for `cargo package`](https://github.com/rust-lang/cargo/pull/15534/)
- [feat(publish): Stabilize multi-package publishing](https://github.com/rust-lang/cargo/pull/15636/)
<a id="1.90-Rustdoc"></a>
Rustdoc
-----
- [Add ways to collapse all impl blocks](https://github.com/rust-lang/rust/pull/141663). Previously the "Summary" button and "-" keyboard shortcut would never collapse `impl` blocks, now they do when shift is held
- [Display unsafe attributes with `unsafe()` wrappers](https://github.com/rust-lang/rust/pull/143662)
<a id="1.90-Compatibility-Notes"></a>
Compatibility Notes
-------------------
- [Use `lld` by default on `x86_64-unknown-linux-gnu`](https://github.com/rust-lang/rust/pull/140525).
See also <https://blog.rust-lang.org/2025/09/01/rust-lld-on-1.90.0-stable/>.
- [Make `core::iter::Fuse`'s `Default` impl construct `I::default()` internally as promised in the docs instead of always being empty](https://github.com/rust-lang/rust/pull/140985)
- [Set `MSG_NOSIGNAL` for `UnixStream`](https://github.com/rust-lang/rust/pull/140005)
This may change program behavior but results in the same behavior as other primitives (e.g., stdout, network sockets).
Programs relying on signals to terminate them should update handling of sockets to handle errors on write by exiting.
- [On Unix `std::env::home_dir` will use the fallback if the `HOME` environment variable is empty](https://github.com/rust-lang/rust/pull/141840)
- We now [reject unsupported `extern "{abi}"`s consistently in all positions](https://github.com/rust-lang/rust/pull/142134). This primarily affects the use of implementing traits on an `extern "{abi}"` function pointer, like `extern "stdcall" fn()`, on a platform that doesn't support that, like aarch64-unknown-linux-gnu. Direct usage of these unsupported ABI strings by declaring or defining functions was already rejected, so this is only a change for consistency.
- [const-eval: error when initializing a static writes to that static](https://github.com/rust-lang/rust/pull/143084)
- [Check that the `proc_macro_derive` macro has correct arguments when applied to the crate root](https://github.com/rust-lang/rust/pull/143607)
Version 1.89.0 (2025-08-07)
==========================

View file

@ -1607,6 +1607,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
tcx.node_span_lint(MACRO_EXTENDED_TEMPORARY_SCOPES, lint_root, labels, |diag| {
diag.primary_message("temporary lifetime will be shortened in Rust 1.92");
diag.note("consider using a `let` binding to create a longer lived value");
diag.note("some temporaries were previously incorrectly lifetime-extended since Rust 1.89 in formatting macros, and since Rust 1.88 in `pin!()`");
});
}
}

View file

@ -1 +1 @@
beta
stable

View file

@ -21,7 +21,7 @@ rustdoc-json-types = { path = "../rustdoc-json-types" }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
smallvec = "1.8.1"
stringdex = { version = "0.0.1-alpha9" }
stringdex = "=0.0.2"
tempfile = "3"
threadpool = "1.8.1"
tracing = "0.1"

View file

@ -239,6 +239,34 @@ impl SerializedSearchIndex {
self.alias_pointers.push(alias_pointer);
index
}
/// Add potential search result to the database and return the row ID.
///
/// The returned ID can be used to attach more data to the search result.
fn add_entry(&mut self, name: Symbol, entry_data: EntryData, desc: String) -> usize {
let fqp = if let Some(module_path_index) = entry_data.module_path {
let mut fqp = self.path_data[module_path_index].as_ref().unwrap().module_path.clone();
fqp.push(Symbol::intern(&self.names[module_path_index]));
fqp.push(name);
fqp
} else {
vec![name]
};
// If a path with the same name already exists, but no entry does,
// we can fill in the entry without having to allocate a new row ID.
//
// Because paths and entries both share the same index, using the same
// ID saves space by making the tree smaller.
if let Some(&other_path) = self.crate_paths_index.get(&(entry_data.ty, fqp))
&& self.entry_data[other_path].is_none()
&& self.descs[other_path].is_empty()
{
self.entry_data[other_path] = Some(entry_data);
self.descs[other_path] = desc;
other_path
} else {
self.push(name.as_str().to_string(), None, Some(entry_data), desc, None, None, None)
}
}
fn push_path(&mut self, name: String, path_data: PathData) -> usize {
self.push(name, Some(path_data), None, String::new(), None, None, None)
}
@ -1513,10 +1541,9 @@ pub(crate) fn build_index(
.as_ref()
.map(|path| serialized_index.get_id_by_module_path(path));
let new_entry_id = serialized_index.push(
item.name.as_str().to_string(),
None,
Some(EntryData {
let new_entry_id = serialized_index.add_entry(
item.name,
EntryData {
ty: item.ty,
parent: item.parent_idx,
module_path,
@ -1535,11 +1562,8 @@ pub(crate) fn build_index(
None
},
krate: crate_idx,
}),
},
item.desc.to_string(),
None, // filled in after all the types have been indexed
None,
None,
);
// Aliases

View file

@ -348,7 +348,7 @@ declare namespace rustdoc {
returned: rustdoc.QueryElement[],
is_alias: boolean,
alias?: string,
original?: rustdoc.Rlow,
item: rustdoc.Row,
}
/**
@ -533,4 +533,27 @@ declare namespace rustdoc {
* Generated by `render_call_locations` in `render/mod.rs`.
*/
type ScrapedLoc = [[number, number], string, string]
/**
* Each of these identifiers are used specially by
* type-driven search. Most of them are lang items
* in the compiler.
*/
type TypeNameIds = {
"typeNameIdOfOutput": number,
"typeNameIdOfFnPtr": number,
"typeNameIdOfFn": number,
"typeNameIdOfFnMut": number,
"typeNameIdOfFnOnce": number,
"typeNameIdOfArray": number,
"typeNameIdOfSlice": number,
"typeNameIdOfArrayOrSlice": number,
"typeNameIdOfTuple": number,
"typeNameIdOfUnit": number,
"typeNameIdOfTupleOrUnit": number,
"typeNameIdOfReference": number,
"typeNameIdOfPointer": number,
"typeNameIdOfHof": number,
"typeNameIdOfNever": number,
};
}

View file

@ -1190,17 +1190,6 @@ class DocSearch {
this.rootPath = rootPath;
this.database = database;
this.typeNameIdOfOutput = -1;
this.typeNameIdOfArray = -1;
this.typeNameIdOfSlice = -1;
this.typeNameIdOfArrayOrSlice = -1;
this.typeNameIdOfTuple = -1;
this.typeNameIdOfUnit = -1;
this.typeNameIdOfTupleOrUnit = -1;
this.typeNameIdOfReference = -1;
this.typeNameIdOfPointer = -1;
this.typeNameIdOfHof = -1;
this.utf8decoder = new TextDecoder();
/** @type {Map<number|null, rustdoc.FunctionType>} */
@ -1208,14 +1197,49 @@ class DocSearch {
}
/**
* Load search index. If you do not call this function, `execQuery`
* will never fulfill.
* Load type name ID set.
*
* Each of these identifiers are used specially by
* type-driven search. Most of them are lang items
* in the compiler.
*
* Use this function, which caches the result, and not
* getTypeNameIdsAsync, which is an internal implementation
* detail for this.
*
* @return {Promise<rustdoc.TypeNameIds>|rustdoc.TypeNameIds}
*/
async buildIndex() {
getTypeNameIds() {
if (this.typeNameIds) {
return this.typeNameIds;
}
const nn = this.database.getData("normalizedName");
if (!nn) {
return;
return {
typeNameIdOfOutput: -1,
typeNameIdOfFnPtr: -1,
typeNameIdOfFn: -1,
typeNameIdOfFnMut: -1,
typeNameIdOfFnOnce: -1,
typeNameIdOfArray: -1,
typeNameIdOfSlice: -1,
typeNameIdOfArrayOrSlice: -1,
typeNameIdOfTuple: -1,
typeNameIdOfUnit: -1,
typeNameIdOfTupleOrUnit: -1,
typeNameIdOfReference: -1,
typeNameIdOfPointer: -1,
typeNameIdOfHof: -1,
typeNameIdOfNever: -1,
};
}
return this.getTypeNameIdsAsync(nn);
}
/**
* @param {stringdex.DataColumn} nn
* @returns {Promise<rustdoc.TypeNameIds>}
*/
async getTypeNameIdsAsync(nn) {
// Each of these identifiers are used specially by
// type-driven search.
const [
@ -1274,21 +1298,39 @@ class DocSearch {
}
return -1;
};
this.typeNameIdOfOutput = await first(output, TY_ASSOCTYPE, "");
this.typeNameIdOfFnPtr = await first(fn, TY_PRIMITIVE, "");
this.typeNameIdOfFn = await first(fn, TY_TRAIT, "core::ops");
this.typeNameIdOfFnMut = await first(fnMut, TY_TRAIT, "core::ops");
this.typeNameIdOfFnOnce = await first(fnOnce, TY_TRAIT, "core::ops");
this.typeNameIdOfArray = await first(array, TY_PRIMITIVE, "");
this.typeNameIdOfSlice = await first(slice, TY_PRIMITIVE, "");
this.typeNameIdOfArrayOrSlice = await first(arrayOrSlice, TY_PRIMITIVE, "");
this.typeNameIdOfTuple = await first(tuple, TY_PRIMITIVE, "");
this.typeNameIdOfUnit = await first(unit, TY_PRIMITIVE, "");
this.typeNameIdOfTupleOrUnit = await first(tupleOrUnit, TY_PRIMITIVE, "");
this.typeNameIdOfReference = await first(reference, TY_PRIMITIVE, "");
this.typeNameIdOfPointer = await first(pointer, TY_PRIMITIVE, "");
this.typeNameIdOfHof = await first(hof, TY_PRIMITIVE, "");
this.typeNameIdOfNever = await first(never, TY_PRIMITIVE, "");
const typeNameIdOfOutput = await first(output, TY_ASSOCTYPE, "");
const typeNameIdOfFnPtr = await first(fn, TY_PRIMITIVE, "");
const typeNameIdOfFn = await first(fn, TY_TRAIT, "core::ops");
const typeNameIdOfFnMut = await first(fnMut, TY_TRAIT, "core::ops");
const typeNameIdOfFnOnce = await first(fnOnce, TY_TRAIT, "core::ops");
const typeNameIdOfArray = await first(array, TY_PRIMITIVE, "");
const typeNameIdOfSlice = await first(slice, TY_PRIMITIVE, "");
const typeNameIdOfArrayOrSlice = await first(arrayOrSlice, TY_PRIMITIVE, "");
const typeNameIdOfTuple = await first(tuple, TY_PRIMITIVE, "");
const typeNameIdOfUnit = await first(unit, TY_PRIMITIVE, "");
const typeNameIdOfTupleOrUnit = await first(tupleOrUnit, TY_PRIMITIVE, "");
const typeNameIdOfReference = await first(reference, TY_PRIMITIVE, "");
const typeNameIdOfPointer = await first(pointer, TY_PRIMITIVE, "");
const typeNameIdOfHof = await first(hof, TY_PRIMITIVE, "");
const typeNameIdOfNever = await first(never, TY_PRIMITIVE, "");
this.typeNameIds = {
typeNameIdOfOutput,
typeNameIdOfFnPtr,
typeNameIdOfFn,
typeNameIdOfFnMut,
typeNameIdOfFnOnce,
typeNameIdOfArray,
typeNameIdOfSlice,
typeNameIdOfArrayOrSlice,
typeNameIdOfTuple,
typeNameIdOfUnit,
typeNameIdOfTupleOrUnit,
typeNameIdOfReference,
typeNameIdOfPointer,
typeNameIdOfHof,
typeNameIdOfNever,
};
return this.typeNameIds;
}
/**
@ -1758,12 +1800,8 @@ class DocSearch {
const l = crateNames.length;
const names = [];
for (let i = 0; i < l; ++i) {
names.push(crateNames.at(i).then(name => {
if (name === undefined) {
return "";
}
return this.utf8decoder.decode(name);
}));
const name = await crateNames.at(i);
names.push(name === undefined ? "" : this.utf8decoder.decode(name));
}
return Promise.all(names);
}
@ -1820,6 +1858,9 @@ class DocSearch {
modulePathData,
exactModuleName,
exactModulePathData,
parentName,
parentPath,
crate,
] = await Promise.all([
entry && entry.modulePath !== null ? this.getName(entry.modulePath) : null,
entry && entry.modulePath !== null ? this.getPathData(entry.modulePath) : null,
@ -1829,6 +1870,13 @@ class DocSearch {
entry && entry.exactModulePath !== null ?
this.getPathData(entry.exactModulePath) :
null,
entry && entry.parent !== null ?
this.getName(entry.parent) :
null,
entry && entry.parent !== null ?
this.getPathData(entry.parent) :
null,
entry ? nonnull(await this.getName(entry.krate)) : "",
]);
const name = name_ === null ? "" : name_;
const normalizedName = (name.indexOf("_") === -1 ?
@ -1838,12 +1886,9 @@ class DocSearch {
(modulePathData.modulePath === "" ?
moduleName :
`${modulePathData.modulePath}::${moduleName}`);
const [parentName, parentPath] = entry !== null && entry.parent !== null ?
await Promise.all([this.getName(entry.parent), this.getPathData(entry.parent)]) :
[null, null];
return {
id,
crate: entry ? nonnull(await this.getName(entry.krate)) : "",
crate,
ty: entry ? entry.ty : nonnull(path).ty,
name,
normalizedName,
@ -2148,6 +2193,7 @@ class DocSearch {
* @returns {Promise<rustdoc.DisplayTypeSignature>}
*/
const formatDisplayTypeSignature = async(obj, typeInfo, elems, returned) => {
const typeNameIds = await this.getTypeNameIds();
const objType = obj.type;
if (!objType) {
return {type: [], mappedNames: new Map(), whereClause: new Map()};
@ -2173,10 +2219,12 @@ class DocSearch {
return true;
},
0,
typeNameIds,
);
return !!fnOutput;
},
0,
typeNameIds,
);
} else {
const highlighted = unifyFunctionTypes(
@ -2189,6 +2237,7 @@ class DocSearch {
return true;
},
0,
typeNameIds,
);
if (typeInfo === "elems") {
fnInputs = highlighted;
@ -2268,7 +2317,7 @@ class DocSearch {
* @returns {Promise<void>}
*/
const writeHof = async(fnType, result) => {
const hofOutput = fnType.bindings.get(this.typeNameIdOfOutput) || [];
const hofOutput = fnType.bindings.get(typeNameIds.typeNameIdOfOutput) || [];
const hofInputs = fnType.generics;
pushText(fnType, result);
pushText({name: " (", highlighted: false}, result);
@ -2309,11 +2358,14 @@ class DocSearch {
* @returns {Promise<boolean>}
*/
const writeSpecialPrimitive = async(fnType, result) => {
if (fnType.id === this.typeNameIdOfArray || fnType.id === this.typeNameIdOfSlice ||
fnType.id === this.typeNameIdOfTuple || fnType.id === this.typeNameIdOfUnit) {
if (fnType.id === typeNameIds.typeNameIdOfArray ||
fnType.id === typeNameIds.typeNameIdOfSlice ||
fnType.id === typeNameIds.typeNameIdOfTuple ||
fnType.id === typeNameIds.typeNameIdOfUnit
) {
const [ob, sb] =
fnType.id === this.typeNameIdOfArray ||
fnType.id === this.typeNameIdOfSlice ?
fnType.id === typeNameIds.typeNameIdOfArray ||
fnType.id === typeNameIds.typeNameIdOfSlice ?
["[", "]"] :
["(", ")"];
pushText({ name: ob, highlighted: fnType.highlighted }, result);
@ -2325,7 +2377,7 @@ class DocSearch {
);
pushText({ name: sb, highlighted: fnType.highlighted }, result);
return true;
} else if (fnType.id === this.typeNameIdOfReference) {
} else if (fnType.id === typeNameIds.typeNameIdOfReference) {
pushText({ name: "&", highlighted: fnType.highlighted }, result);
let prevHighlighted = false;
await onEachBtwnAsync(
@ -2341,7 +2393,7 @@ class DocSearch {
}, result),
);
return true;
} else if (fnType.id === this.typeNameIdOfPointer) {
} else if (fnType.id === typeNameIds.typeNameIdOfPointer) {
pushText({ name: "*", highlighted: fnType.highlighted }, result);
if (fnType.generics.length < 2) {
pushText({ name: "const ", highlighted: fnType.highlighted }, result);
@ -2361,14 +2413,14 @@ class DocSearch {
);
return true;
} else if (
fnType.id === this.typeNameIdOfFn ||
fnType.id === this.typeNameIdOfFnMut ||
fnType.id === this.typeNameIdOfFnOnce ||
fnType.id === this.typeNameIdOfFnPtr
fnType.id === typeNameIds.typeNameIdOfFn ||
fnType.id === typeNameIds.typeNameIdOfFnMut ||
fnType.id === typeNameIds.typeNameIdOfFnOnce ||
fnType.id === typeNameIds.typeNameIdOfFnPtr
) {
await writeHof(fnType, result);
return true;
} else if (fnType.id === this.typeNameIdOfNever) {
} else if (fnType.id === typeNameIds.typeNameIdOfNever) {
pushText({ name: "!", highlighted: fnType.highlighted }, result);
return true;
}
@ -2426,10 +2478,10 @@ class DocSearch {
return;
}
} else if (fnType.ty === TY_TRAIT && (
fnType.id === this.typeNameIdOfFn ||
fnType.id === this.typeNameIdOfFnMut ||
fnType.id === this.typeNameIdOfFnOnce ||
fnType.id === this.typeNameIdOfFnPtr
fnType.id === typeNameIds.typeNameIdOfFn ||
fnType.id === typeNameIds.typeNameIdOfFnMut ||
fnType.id === typeNameIds.typeNameIdOfFnOnce ||
fnType.id === typeNameIds.typeNameIdOfFnPtr
)) {
await writeHof(fnType, result);
return;
@ -2540,7 +2592,7 @@ class DocSearch {
* Add extra data to result objects, and filter items that have been
* marked for removal.
*
* @param {[rustdoc.PlainResultObject, rustdoc.Row][]} results
* @param {rustdoc.PlainResultObject[]} results
* @param {"sig"|"elems"|"returned"|null} typeInfo
* @param {Set<string>} duplicates
* @returns {rustdoc.ResultObject[]}
@ -2548,7 +2600,8 @@ class DocSearch {
const transformResults = (results, typeInfo, duplicates) => {
const out = [];
for (const [result, item] of results) {
for (const result of results) {
const item = result.item;
if (item.id !== -1) {
const res = buildHrefAndPath(item);
// many of these properties don't strictly need to be
@ -2633,7 +2686,7 @@ class DocSearch {
const normalizedUserQuery = parsedQuery.userQuery.toLowerCase();
const isMixedCase = normalizedUserQuery !== userQuery;
/**
* @type {[rustdoc.PlainResultObject, rustdoc.Row][]}
* @type {rustdoc.PlainResultObject[]}
*/
const result_list = [];
for (const result of results.values()) {
@ -2641,23 +2694,22 @@ class DocSearch {
continue;
}
/**
* @type {rustdoc.Row?}
* @type {rustdoc.Row}
*/
const item = await this.getRow(result.id, typeInfo !== null);
if (!item) {
continue;
}
const item = result.item;
if (filterCrates !== null && item.crate !== filterCrates) {
continue;
}
if (item) {
result_list.push([result, item]);
result_list.push(result);
} else {
continue;
}
}
result_list.sort(([aaa, aai], [bbb, bbi]) => {
result_list.sort((aaa, bbb) => {
const aai = aaa.item;
const bbi = bbb.item;
/** @type {number} */
let a;
/** @type {number} */
@ -2804,6 +2856,7 @@ class DocSearch {
* @param {number} unboxingDepth
* - Limit checks that Ty matches Vec<Ty>,
* but not Vec<ParamEnvAnd<WithInfcx<ConstTy<Interner<Ty=Ty>>>>>
* @param {rustdoc.TypeNameIds} typeNameIds
*
* @return {rustdoc.HighlightedFunctionType[]|null}
* - Returns highlighted results if a match, null otherwise.
@ -2815,6 +2868,7 @@ class DocSearch {
mgensIn,
solutionCb,
unboxingDepth,
typeNameIds,
) {
if (unboxingDepth >= UNBOXING_LIMIT) {
return null;
@ -2837,7 +2891,12 @@ class DocSearch {
&& queryElems[0].bindings.size === 0) {
const queryElem = queryElems[0];
for (const [i, fnType] of fnTypesIn.entries()) {
if (!unifyFunctionTypeIsMatchCandidate(fnType, queryElem, mgens)) {
if (!unifyFunctionTypeIsMatchCandidate(
fnType,
queryElem,
mgens,
typeNameIds,
)) {
continue;
}
if (fnType.id !== null &&
@ -2873,6 +2932,7 @@ class DocSearch {
mgens ? new Map(mgens) : null,
solutionCb,
unboxingDepth,
typeNameIds,
) || fnType.generics,
});
return highlighted;
@ -2885,6 +2945,7 @@ class DocSearch {
whereClause,
mgens,
unboxingDepth + 1,
typeNameIds,
)) {
continue;
}
@ -2898,6 +2959,7 @@ class DocSearch {
mgens,
solutionCb,
unboxingDepth + 1,
typeNameIds,
);
if (highlightedGenerics) {
const highlighted = [...fnTypesIn];
@ -2916,6 +2978,7 @@ class DocSearch {
mgens ? new Map(mgens) : null,
solutionCb,
unboxingDepth + 1,
typeNameIds,
);
if (highlightedGenerics) {
const highlighted = [...fnTypesIn];
@ -2960,7 +3023,12 @@ class DocSearch {
let queryElemsTmp = null;
for (let i = flast; i >= 0; i -= 1) {
const fnType = fnTypes[i];
if (!unifyFunctionTypeIsMatchCandidate(fnType, queryElem, mgens)) {
if (!unifyFunctionTypeIsMatchCandidate(
fnType,
queryElem,
mgens,
typeNameIds,
)) {
continue;
}
let mgensScratch;
@ -3004,6 +3072,7 @@ class DocSearch {
whereClause,
mgensScratch,
unboxingDepth,
typeNameIds,
);
if (!solution) {
return false;
@ -3017,6 +3086,7 @@ class DocSearch {
simplifiedMgens,
solutionCb,
unboxingDepth,
typeNameIds,
);
if (unifiedGenerics !== null) {
unifiedGenericsMgens = simplifiedMgens;
@ -3026,6 +3096,7 @@ class DocSearch {
return false;
},
unboxingDepth,
typeNameIds,
);
if (passesUnification) {
passesUnification.length = fl;
@ -3042,6 +3113,7 @@ class DocSearch {
unifiedGenericsMgens,
solutionCb,
unboxingDepth,
typeNameIds,
// @ts-expect-error
) : unifiedGenerics.splice(0, v.length)];
})),
@ -3061,6 +3133,7 @@ class DocSearch {
whereClause,
mgens,
unboxingDepth + 1,
typeNameIds,
)) {
continue;
}
@ -3077,6 +3150,7 @@ class DocSearch {
mgens,
solutionCb,
unboxingDepth + 1,
typeNameIds,
);
if (passesUnification) {
const highlightedGenerics = passesUnification.slice(
@ -3117,6 +3191,7 @@ class DocSearch {
* @param {number} unboxingDepth
* - Limit checks that Ty matches Vec<Ty>,
* but not Vec<ParamEnvAnd<WithInfcx<ConstTy<Interner<Ty=Ty>>>>>
* @param {rustdoc.TypeNameIds} typeNameIds
*
* @return {rustdoc.HighlightedFunctionType[]|null}
* - Returns highlighted results if a match, null otherwise.
@ -3128,6 +3203,7 @@ class DocSearch {
mgensIn,
solutionCb,
unboxingDepth,
typeNameIds,
) {
if (unboxingDepth >= UNBOXING_LIMIT) {
return null;
@ -3145,7 +3221,12 @@ class DocSearch {
}
const fnType = fnTypesIn[0];
const queryElem = queryElems[0];
if (unifyFunctionTypeIsMatchCandidate(fnType, queryElem, mgens)) {
if (unifyFunctionTypeIsMatchCandidate(
fnType,
queryElem,
mgens,
typeNameIds,
)) {
if (fnType.id !== null &&
fnType.id < 0 &&
queryElem.id !== null &&
@ -3163,6 +3244,7 @@ class DocSearch {
mgensScratch,
solutionCb,
unboxingDepth,
typeNameIds,
);
if (fnTypesRemaining) {
const highlighted = [fnType, ...fnTypesRemaining];
@ -3189,6 +3271,7 @@ class DocSearch {
whereClause,
mgensScratch,
unboxingDepth,
typeNameIds,
);
if (!solution) {
return false;
@ -3202,6 +3285,7 @@ class DocSearch {
simplifiedMgens,
solutionCb,
unboxingDepth,
typeNameIds,
);
if (unifiedGenerics !== null) {
return true;
@ -3209,6 +3293,7 @@ class DocSearch {
}
},
unboxingDepth,
typeNameIds,
);
if (fnTypesRemaining) {
const highlighted = [fnType, ...fnTypesRemaining];
@ -3227,6 +3312,7 @@ class DocSearch {
whereClause,
mgens,
unboxingDepth + 1,
typeNameIds,
)) {
let highlightedRemaining;
if (fnType.id !== null && fnType.id < 0) {
@ -3248,6 +3334,7 @@ class DocSearch {
mgensScratch,
solutionCb,
unboxingDepth,
typeNameIds,
);
if (hl) {
highlightedRemaining = hl;
@ -3255,6 +3342,7 @@ class DocSearch {
return hl;
},
unboxingDepth + 1,
typeNameIds,
);
if (highlightedGenerics) {
return [Object.assign({
@ -3282,6 +3370,7 @@ class DocSearch {
mgensScratch,
solutionCb,
unboxingDepth,
typeNameIds,
);
if (hl) {
highlightedRemaining = hl;
@ -3289,6 +3378,7 @@ class DocSearch {
return hl;
},
unboxingDepth + 1,
typeNameIds,
);
if (highlightedGenerics) {
return [Object.assign({}, fnType, {
@ -3314,10 +3404,11 @@ class DocSearch {
*
* @param {rustdoc.FunctionType} fnType
* @param {rustdoc.QueryElement} queryElem
* @param {rustdoc.TypeNameIds} typeNameIds
* @param {Map<number,number>|null} mgensIn - Map query generics to function generics.
* @returns {boolean}
*/
const unifyFunctionTypeIsMatchCandidate = (fnType, queryElem, mgensIn) => {
const unifyFunctionTypeIsMatchCandidate = (fnType, queryElem, mgensIn, typeNameIds) => {
// type filters look like `trait:Read` or `enum:Result`
if (!typePassesFilter(queryElem.typeFilter, fnType.ty)) {
return false;
@ -3336,21 +3427,23 @@ class DocSearch {
} else {
// For these special cases, matching code need added to the inverted index.
// search_index.rs -> convert_render_type does this
if (queryElem.id === this.typeNameIdOfArrayOrSlice &&
(fnType.id === this.typeNameIdOfSlice || fnType.id === this.typeNameIdOfArray)
if (queryElem.id === typeNameIds.typeNameIdOfArrayOrSlice &&
(fnType.id === typeNameIds.typeNameIdOfSlice ||
fnType.id === typeNameIds.typeNameIdOfArray)
) {
// [] matches primitive:array or primitive:slice
// if it matches, then we're fine, and this is an appropriate match candidate
} else if (queryElem.id === this.typeNameIdOfTupleOrUnit &&
(fnType.id === this.typeNameIdOfTuple || fnType.id === this.typeNameIdOfUnit)
} else if (queryElem.id === typeNameIds.typeNameIdOfTupleOrUnit &&
(fnType.id === typeNameIds.typeNameIdOfTuple ||
fnType.id === typeNameIds.typeNameIdOfUnit)
) {
// () matches primitive:tuple or primitive:unit
// if it matches, then we're fine, and this is an appropriate match candidate
} else if (queryElem.id === this.typeNameIdOfHof && (
fnType.id === this.typeNameIdOfFn ||
fnType.id === this.typeNameIdOfFnMut ||
fnType.id === this.typeNameIdOfFnOnce ||
fnType.id === this.typeNameIdOfFnPtr
} else if (queryElem.id === typeNameIds.typeNameIdOfHof && (
fnType.id === typeNameIds.typeNameIdOfFn ||
fnType.id === typeNameIds.typeNameIdOfFnMut ||
fnType.id === typeNameIds.typeNameIdOfFnOnce ||
fnType.id === typeNameIds.typeNameIdOfFnPtr
)) {
// -> matches fn, fnonce, and fnmut
// if it matches, then we're fine, and this is an appropriate match candidate
@ -3414,6 +3507,7 @@ class DocSearch {
* @param {Map<number,number>|null} mgensIn - Map query generics to function generics.
* Never modified.
* @param {number} unboxingDepth
* @param {rustdoc.TypeNameIds} typeNameIds
* @returns {false|{
* mgens: [Map<number,number>|null], simplifiedGenerics: rustdoc.FunctionType[]
* }}
@ -3424,6 +3518,7 @@ class DocSearch {
whereClause,
mgensIn,
unboxingDepth,
typeNameIds,
) {
if (fnType.bindings.size < queryElem.bindings.size) {
return false;
@ -3455,6 +3550,7 @@ class DocSearch {
return false;
},
unboxingDepth,
typeNameIds,
);
return newSolutions;
});
@ -3486,6 +3582,7 @@ class DocSearch {
* @param {rustdoc.FunctionType[][]} whereClause - Trait bounds for generic items.
* @param {Map<number,number>|null} mgens - Map query generics to function generics.
* @param {number} unboxingDepth
* @param {rustdoc.TypeNameIds} typeNameIds
* @returns {boolean}
*/
function unifyFunctionTypeIsUnboxCandidate(
@ -3494,6 +3591,7 @@ class DocSearch {
whereClause,
mgens,
unboxingDepth,
typeNameIds,
) {
if (unboxingDepth >= UNBOXING_LIMIT) {
return false;
@ -3512,6 +3610,7 @@ class DocSearch {
whereClause,
mgens,
unboxingDepth,
typeNameIds,
);
} else if (fnType.unboxFlag &&
(fnType.generics.length > 0 || fnType.bindings.size > 0)) {
@ -3525,6 +3624,7 @@ class DocSearch {
whereClause,
mgens,
unboxingDepth,
typeNameIds,
);
}
return false;
@ -3537,14 +3637,15 @@ class DocSearch {
* @param {rustdoc.QueryElement[]} elems
* @param {rustdoc.FunctionType[]} list - A list of function types.
* @param {rustdoc.FunctionType[][]} where_clause - Trait bounds for generic items.
* @param {rustdoc.TypeNameIds} typeNameIds
*/
function containsTypeFromQuery(elems, list, where_clause) {
function containsTypeFromQuery(elems, list, where_clause, typeNameIds) {
if (!list) return false;
for (const ty of elems) {
if (ty.id !== null && ty.id < 0) {
continue;
}
if (checkIfInList(list, ty, where_clause, null, 0)) {
if (checkIfInList(list, ty, where_clause, null, 0, typeNameIds)) {
return true;
}
}
@ -3560,12 +3661,13 @@ class DocSearch {
* @param {rustdoc.FunctionType[][]} whereClause - Trait bounds for generic items.
* @param {Map<number,number>|null} mgens - Map functions generics to query generics.
* @param {number} unboxingDepth
* @param {rustdoc.TypeNameIds} typeNameIds
*
* @return {boolean} - Returns true if found, false otherwise.
*/
function checkIfInList(list, elem, whereClause, mgens, unboxingDepth) {
function checkIfInList(list, elem, whereClause, mgens, unboxingDepth, typeNameIds) {
for (const entry of list) {
if (checkType(entry, elem, whereClause, mgens, unboxingDepth)) {
if (checkType(entry, elem, whereClause, mgens, unboxingDepth, typeNameIds)) {
return true;
}
}
@ -3580,11 +3682,12 @@ class DocSearch {
* @param {rustdoc.QueryElement} elem - The element from the parsed query.
* @param {rustdoc.FunctionType[][]} whereClause - Trait bounds for generic items.
* @param {Map<number,number>|null} mgens - Map query generics to function generics.
* @param {number} unboxingDepth
* @param {rustdoc.TypeNameIds} typeNameIds
*
* @return {boolean} - Returns true if the type matches, false otherwise.
*/
// @ts-expect-error
const checkType = (row, elem, whereClause, mgens, unboxingDepth) => {
const checkType = (row, elem, whereClause, mgens, unboxingDepth, typeNameIds) => {
if (unboxingDepth >= UNBOXING_LIMIT) {
return false;
}
@ -3593,9 +3696,9 @@ class DocSearch {
row.generics.length === 0 && elem.generics.length === 0 &&
row.bindings.size === 0 && elem.bindings.size === 0 &&
// special case
elem.id !== this.typeNameIdOfArrayOrSlice &&
elem.id !== this.typeNameIdOfHof &&
elem.id !== this.typeNameIdOfTupleOrUnit
elem.id !== typeNameIds.typeNameIdOfArrayOrSlice &&
elem.id !== typeNameIds.typeNameIdOfHof &&
elem.id !== typeNameIds.typeNameIdOfTupleOrUnit
) {
return row.id === elem.id && typePassesFilter(elem.typeFilter, row.ty);
} else {
@ -3607,6 +3710,7 @@ class DocSearch {
mgens,
() => true,
unboxingDepth,
typeNameIds,
);
}
};
@ -3673,7 +3777,10 @@ class DocSearch {
/**
* Compute an "edit distance" that ignores missing path elements.
* @param {string[]} contains search query path
* @param {rustdoc.Row} row indexed item
* @param {{
* modulePath: string,
* parent: { path: rustdoc.PathData, name: string}?,
* }} row indexed item
* @returns {null|number} edit distance
*/
function checkRowPath(contains, row) {
@ -3752,7 +3859,7 @@ class DocSearch {
is_alias: true,
elems: [], // only used in type-based queries
returned: [], // only used in type-based queries
original: await this.getRow(alias, false),
item: nonnull(await this.getRow(alias, false)),
};
};
/**
@ -3834,6 +3941,7 @@ class DocSearch {
elems: [], // only used in type-based queries
returned: [], // only used in type-based queries
is_alias: false,
item: row,
} : null;
} else {
return {
@ -3848,6 +3956,7 @@ class DocSearch {
elems: [], // only used in type-based queries
returned: [], // only used in type-based queries
is_alias: false,
item: row,
};
}
};
@ -4359,9 +4468,10 @@ class DocSearch {
};
// finally, we can do the actual unification loop
const [allInputs, allOutput] = await Promise.all([
const [allInputs, allOutput, typeNameIds] = await Promise.all([
unpackPostingsListAll(inputs, "invertedFunctionInputsIndex"),
unpackPostingsListAll(output, "invertedFunctionOutputIndex"),
this.getTypeNameIds(),
]);
let checkCounter = 0;
/**
@ -4430,12 +4540,18 @@ class DocSearch {
mgens,
checkTypeMgensForConflict,
0, // unboxing depth
typeNameIds,
);
},
0, // unboxing depth
typeNameIds,
)) {
return null;
}
const item = await this.getRow(id, true);
if (!item) {
return null;
}
const result = {
id,
dist: fnData.elemCount,
@ -4444,8 +4560,9 @@ class DocSearch {
elems: inputs,
returned: output,
is_alias: false,
item,
};
const entry = await this.getEntryData(id);
const entry = item.entry;
if ((entry && !isFnLikeTy(entry.ty)) ||
(isReturnTypeQuery &&
functionSignature &&
@ -4453,6 +4570,7 @@ class DocSearch {
output,
functionSignature.inputs,
functionSignature.where_clause,
typeNameIds,
)
)
) {
@ -5273,7 +5391,6 @@ if (ROOT_PATH === null) {
const database = await Stringdex.loadDatabase(hooks);
if (typeof window !== "undefined") {
docSearch = new DocSearch(ROOT_PATH, database);
await docSearch.buildIndex();
onEachLazy(document.querySelectorAll(
".search-form.loading",
), form => {
@ -5286,7 +5403,6 @@ if (typeof window !== "undefined") {
}
} else if (typeof exports !== "undefined") {
docSearch = new DocSearch(ROOT_PATH, database);
await docSearch.buildIndex();
return { docSearch, DocSearch };
}
};

View file

@ -29,7 +29,7 @@ declare namespace stringdex {
*/
interface DataColumn {
isEmpty(id: number): boolean;
at(id: number): Promise<Uint8Array|undefined>;
at(id: number): Promise<Uint8Array>|Uint8Array|undefined;
search(name: Uint8Array|string): Promise<Trie?>;
searchLev(name: Uint8Array|string): AsyncGenerator<Trie>;
length: number,

View file

@ -1108,22 +1108,39 @@ function loadDatabase(hooks) {
const id2 = id1 + ((nodeid[4] << 8) | nodeid[5]);
leaves = RoaringBitmap.makeSingleton(id1)
.union(RoaringBitmap.makeSingleton(id2));
} else if (!isWhole && (nodeid[0] & 0xf0) === 0x80) {
const id1 = ((nodeid[0] & 0x0f) << 16) | (nodeid[1] << 8) | nodeid[2];
const id2 = id1 + ((nodeid[3] << 4) | ((nodeid[4] >> 4) & 0x0f));
const id3 = id2 + (((nodeid[4] & 0x0f) << 8) | nodeid[5]);
leaves = RoaringBitmap.makeSingleton(id1)
.union(RoaringBitmap.makeSingleton(id2))
.union(RoaringBitmap.makeSingleton(id3));
} else {
leaves = RoaringBitmap.makeSingleton(
(nodeid[2] << 24) | (nodeid[3] << 16) |
(nodeid[4] << 8) | nodeid[5],
);
}
const data = (nodeid[0] & 0x20) !== 0 ?
Uint8Array.of(((nodeid[0] & 0x0f) << 4) | (nodeid[1] >> 4)) :
EMPTY_UINT8;
newPromise = Promise.resolve(new PrefixSearchTree(
EMPTY_SEARCH_TREE_BRANCHES,
EMPTY_SEARCH_TREE_BRANCHES,
data,
isWhole ? leaves : EMPTY_BITMAP,
isWhole ? EMPTY_BITMAP : leaves,
));
if (isWhole) {
const data = (nodeid[0] & 0x20) !== 0 ?
Uint8Array.of(((nodeid[0] & 0x0f) << 4) | (nodeid[1] >> 4)) :
EMPTY_UINT8;
newPromise = Promise.resolve(new PrefixSearchTree(
EMPTY_SEARCH_TREE_BRANCHES,
EMPTY_SEARCH_TREE_BRANCHES,
data,
leaves,
EMPTY_BITMAP,
));
} else {
const data = (nodeid[0] & 0xf0) === 0x80 ? 0 : (
((nodeid[0] & 0x0f) << 4) | (nodeid[1] >> 4));
newPromise = Promise.resolve(new SuffixSearchTree(
EMPTY_SEARCH_TREE_BRANCHES,
data,
leaves,
));
}
} else {
const hashHex = makeHexFromUint8Array(nodeid);
newPromise = new Promise((resolve, reject) => {
@ -1430,7 +1447,7 @@ function loadDatabase(hooks) {
makeSearchTreeBranchesAlphaBitmapClass(LONG_ALPHABITMAP_CHARS, 4);
/**
* @typedef {PrefixSearchTree|SuffixSearchTree} SearchTree
* @typedef {PrefixSearchTree|SuffixSearchTree|InlineNeighborsTree} SearchTree
* @typedef {PrefixTrie|SuffixTrie} Trie
*/
@ -1658,9 +1675,12 @@ function loadDatabase(hooks) {
yield leaves;
}
}
/** @type {HashTable<[number, SearchTree][]>} */
/** @type {HashTable<[number, PrefixSearchTree|SuffixSearchTree][]>} */
const subnodes = new HashTable();
for await (const node of current_layer) {
for await (const nodeEncoded of current_layer) {
const node = nodeEncoded instanceof InlineNeighborsTree ?
nodeEncoded.decode() :
nodeEncoded;
const branches = node.branches;
const l = branches.subtrees.length;
for (let i = 0; i < l; ++i) {
@ -1724,7 +1744,10 @@ function loadDatabase(hooks) {
// we then yield the smallest ones (can't yield bigger ones
// if we want to do them in order)
for (const {node, len} of current_layer) {
const tree = await node;
const treeEncoded = await node;
const tree = treeEncoded instanceof InlineNeighborsTree ?
treeEncoded.decode() :
treeEncoded;
if (!(tree instanceof PrefixSearchTree)) {
continue;
}
@ -1787,7 +1810,10 @@ function loadDatabase(hooks) {
/** @type {HashTable<{byte: number, tree: PrefixSearchTree, len: number}[]>} */
const subnodes = new HashTable();
for await (const {node, len} of current_layer) {
const tree = await node;
const treeEncoded = await node;
const tree = treeEncoded instanceof InlineNeighborsTree ?
treeEncoded.decode() :
treeEncoded;
if (!(tree instanceof PrefixSearchTree)) {
continue;
}
@ -2149,9 +2175,12 @@ function loadDatabase(hooks) {
yield leaves;
}
}
/** @type {HashTable<[number, SearchTree][]>} */
/** @type {HashTable<[number, PrefixSearchTree|SuffixSearchTree][]>} */
const subnodes = new HashTable();
for await (const node of current_layer) {
for await (const nodeEncoded of current_layer) {
const node = nodeEncoded instanceof InlineNeighborsTree ?
nodeEncoded.decode() :
nodeEncoded;
const branches = node.branches;
const l = branches.subtrees.length;
for (let i = 0; i < l; ++i) {
@ -2247,6 +2276,174 @@ function loadDatabase(hooks) {
}
}
/**
* Represents a subtree where all transitive leaves
* have a shared 16bit prefix and there are no sub-branches.
*/
class InlineNeighborsTree {
/**
* @param {Uint8Array} encoded
* @param {number} start
*/
constructor(
encoded,
start,
) {
this.encoded = encoded;
this.start = start;
}
/**
* @return {PrefixSearchTree|SuffixSearchTree}
*/
decode() {
let i = this.start;
const encoded = this.encoded;
const has_branches = (encoded[i] & 0x04) !== 0;
/** @type {boolean} */
const is_suffixes_only = (encoded[i] & 0x01) !== 0;
let leaves_count = ((encoded[i] >> 4) & 0x0f) + 1;
i += 1;
let branch_count = 0;
if (has_branches) {
branch_count = encoded[i] + 1;
i += 1;
}
const dlen = encoded[i] & 0x3f;
if ((encoded[i] & 0x80) !== 0) {
leaves_count = 0;
}
i += 1;
let data = EMPTY_UINT8;
if (!is_suffixes_only && dlen !== 0) {
data = encoded.subarray(i, i + dlen);
i += dlen;
}
const leaf_value_upper = encoded[i] | (encoded[i + 1] << 8);
i += 2;
/** @type {Promise<SearchTree>[]} */
const branch_nodes = [];
for (let j = 0; j < branch_count; j += 1) {
const branch_dlen = encoded[i] & 0x0f;
const branch_leaves_count = ((encoded[i] >> 4) & 0x0f) + 1;
i += 1;
let branch_data = EMPTY_UINT8;
if (!is_suffixes_only && branch_dlen !== 0) {
branch_data = encoded.subarray(i, i + branch_dlen);
i += branch_dlen;
}
const branch_leaves = new RoaringBitmap(null);
branch_leaves.keysAndCardinalities = Uint8Array.of(
leaf_value_upper & 0xff,
(leaf_value_upper >> 8) & 0xff,
(branch_leaves_count - 1) & 0xff,
((branch_leaves_count - 1) >> 8) & 0xff,
);
branch_leaves.containers = [
new RoaringBitmapArray(
branch_leaves_count,
encoded.subarray(i, i + (branch_leaves_count * 2)),
),
];
i += branch_leaves_count * 2;
branch_nodes.push(Promise.resolve(
is_suffixes_only ?
new SuffixSearchTree(
EMPTY_SEARCH_TREE_BRANCHES,
branch_dlen,
branch_leaves,
) :
new PrefixSearchTree(
EMPTY_SEARCH_TREE_BRANCHES,
EMPTY_SEARCH_TREE_BRANCHES,
branch_data,
branch_leaves,
EMPTY_BITMAP,
),
));
}
/** @type {SearchTreeBranchesArray<SearchTree>} */
const branches = branch_count === 0 ?
EMPTY_SEARCH_TREE_BRANCHES :
new SearchTreeBranchesArray(
encoded.subarray(i, i + branch_count),
EMPTY_UINT8,
);
i += branch_count;
branches.subtrees = branch_nodes;
let leaves = EMPTY_BITMAP;
if (leaves_count !== 0) {
leaves = new RoaringBitmap(null);
leaves.keysAndCardinalities = Uint8Array.of(
leaf_value_upper & 0xff,
(leaf_value_upper >> 8) & 0xff,
(leaves_count - 1) & 0xff,
((leaves_count - 1) >> 8) & 0xff,
);
leaves.containers = [
new RoaringBitmapArray(
leaves_count,
encoded.subarray(i, i + (leaves_count * 2)),
),
];
i += leaves_count * 2;
}
return is_suffixes_only ?
new SuffixSearchTree(
branches,
dlen,
leaves,
) :
new PrefixSearchTree(
branches,
branches,
data,
leaves,
EMPTY_BITMAP,
);
}
/**
* Returns the Trie for the root node.
*
* A Trie pointer refers to a single node in a logical decompressed search tree
* (the real search tree is compressed).
*
* @param {DataColumn} dataColumn
* @param {Uint8ArraySearchPattern} searchPattern
* @return {Trie}
*/
trie(dataColumn, searchPattern) {
const tree = this.decode();
return tree instanceof SuffixSearchTree ?
new SuffixTrie(tree, 0, dataColumn, searchPattern) :
new PrefixTrie(tree, 0, dataColumn, searchPattern);
}
/**
* Return the trie representing `name`
* @param {Uint8Array|string} name
* @param {DataColumn} dataColumn
* @returns {Promise<Trie?>}
*/
search(name, dataColumn) {
return this.decode().search(name, dataColumn);
}
/**
* @param {Uint8Array|string} name
* @param {DataColumn} dataColumn
* @returns {AsyncGenerator<Trie>}
*/
searchLev(name, dataColumn) {
return this.decode().searchLev(name, dataColumn);
}
/** @returns {RoaringBitmap} */
getCurrentLeaves() {
return this.decode().getCurrentLeaves();
}
}
class DataColumn {
/**
* Construct the wrapper object for a data column.
@ -2261,7 +2458,7 @@ function loadDatabase(hooks) {
this.hashes = hashes;
this.emptyset = emptyset;
this.name = name;
/** @type {{"hash": Uint8Array, "data": Promise<Uint8Array[]>?, "end": number}[]} */
/** @type {{"hash": Uint8Array, "data": Uint8Array[]?, "end": number}[]} */
this.buckets = [];
this.bucket_keys = [];
const l = counts.length;
@ -2295,65 +2492,76 @@ function loadDatabase(hooks) {
/**
* Look up a cell by row ID.
* @param {number} id
* @returns {Promise<Uint8Array|undefined>}
* @returns {Promise<Uint8Array>|Uint8Array|undefined}
*/
async at(id) {
at(id) {
if (this.emptyset.contains(id)) {
return Promise.resolve(EMPTY_UINT8);
return EMPTY_UINT8;
} else {
let idx = -1;
while (this.bucket_keys[idx + 1] <= id) {
idx += 1;
}
if (idx === -1 || idx >= this.bucket_keys.length) {
return Promise.resolve(undefined);
return undefined;
} else {
const start = this.bucket_keys[idx];
const {hash, end} = this.buckets[idx];
let data = this.buckets[idx].data;
const bucket = this.buckets[idx];
const data = this.buckets[idx].data;
if (data === null) {
const dataSansEmptysetOrig = await registry.dataLoadByNameAndHash(
this.name,
hash,
);
// After the `await` resolves, another task might fill
// in the data. If so, we should use that.
data = this.buckets[idx].data;
if (data !== null) {
return (await data)[id - start];
}
const dataSansEmptyset = [...dataSansEmptysetOrig];
/** @type {(Uint8Array[])|null} */
let dataWithEmptyset = null;
let pos = start;
let insertCount = 0;
while (pos < end) {
if (this.emptyset.contains(pos)) {
if (dataWithEmptyset === null) {
dataWithEmptyset = dataSansEmptyset.splice(0, insertCount);
} else if (insertCount !== 0) {
dataWithEmptyset.push(
...dataSansEmptyset.splice(0, insertCount),
);
}
insertCount = 0;
dataWithEmptyset.push(EMPTY_UINT8);
} else {
insertCount += 1;
}
pos += 1;
}
data = Promise.resolve(
dataWithEmptyset === null ?
dataSansEmptyset :
dataWithEmptyset.concat(dataSansEmptyset),
);
this.buckets[idx].data = data;
return this.atAsyncFetch(id, start, bucket);
} else {
return data[id - start];
}
return (await data)[id - start];
}
}
}
/**
* Look up a cell by row ID.
* @param {number} id
* @param {number} start
* @param {{hash: Uint8Array, data: Uint8Array[] | null, end: number}} bucket
* @returns {Promise<Uint8Array>}
*/
async atAsyncFetch(id, start, bucket) {
const {hash, end} = bucket;
const dataSansEmptysetOrig = await registry.dataLoadByNameAndHash(
this.name,
hash,
);
// After the `await` resolves, another task might fill
// in the data. If so, we should use that.
let data = bucket.data;
if (data !== null) {
return data[id - start];
}
const dataSansEmptyset = [...dataSansEmptysetOrig];
/** @type {(Uint8Array[])|null} */
let dataWithEmptyset = null;
let pos = start;
let insertCount = 0;
while (pos < end) {
if (this.emptyset.contains(pos)) {
if (dataWithEmptyset === null) {
dataWithEmptyset = dataSansEmptyset.splice(0, insertCount);
} else if (insertCount !== 0) {
dataWithEmptyset.push(
...dataSansEmptyset.splice(0, insertCount),
);
}
insertCount = 0;
dataWithEmptyset.push(EMPTY_UINT8);
} else {
insertCount += 1;
}
pos += 1;
}
data = dataWithEmptyset === null ?
dataSansEmptyset :
dataWithEmptyset.concat(dataSansEmptyset);
bucket.data = data;
return data[id - start];
}
/**
* Search by exact substring
* @param {Uint8Array|string} name
@ -2737,19 +2945,37 @@ function loadDatabase(hooks) {
// because that's the canonical, hashed version of the data
let compression_tag = input[i];
const is_pure_suffixes_only_node = (compression_tag & 0x01) !== 0;
if (compression_tag > 1) {
// compressed node
const is_long_compressed = (compression_tag & 0x04) !== 0;
const is_data_compressed = (compression_tag & 0x08) !== 0;
const is_long_compressed = (compression_tag & 0x04) !== 0;
const is_data_compressed = (compression_tag & 0x08) !== 0;
i += 1;
if (is_long_compressed) {
compression_tag |= input[i] << 8;
i += 1;
if (is_long_compressed) {
compression_tag |= input[i] << 8;
i += 1;
compression_tag |= input[i] << 16;
i += 1;
}
let dlen = input[i];
}
/** @type {number} */
let dlen;
/** @type {number} */
let no_leaves_flag;
/** @type {number} */
let inline_neighbors_flag;
if (is_data_compressed && is_pure_suffixes_only_node) {
dlen = 0;
no_leaves_flag = 0x80;
inline_neighbors_flag = 0;
} else {
dlen = input[i] & 0x3F;
no_leaves_flag = input[i] & 0x80;
inline_neighbors_flag = input[i] & 0x40;
i += 1;
}
if (inline_neighbors_flag !== 0) {
// node with packed leaves and common 16bit prefix
const leaves_count = no_leaves_flag !== 0 ?
0 :
((compression_tag >> 4) & 0x0f) + 1;
const branch_count = is_long_compressed ?
((compression_tag >> 8) & 0xff) + 1 :
0;
if (is_data_compressed) {
data = data_history[data_history.length - dlen - 1];
dlen = data.length;
@ -2761,6 +2987,72 @@ function loadDatabase(hooks) {
new Uint8Array(input.buffer, i + input.byteOffset, dlen);
i += dlen;
}
const branches_start = i;
// leaf_value_upper
i += 2;
// branch_nodes
for (let j = 0; j < branch_count; j += 1) {
const branch_dlen = input[i] & 0x0f;
const branch_leaves_count = ((input[i] >> 4) & 0x0f) + 1;
i += 1;
if (!is_pure_suffixes_only_node) {
i += branch_dlen;
}
i += branch_leaves_count * 2;
}
// branch keys
i += branch_count;
// leaves
i += leaves_count * 2;
if (is_data_compressed) {
const clen = (
1 + // first compression header byte
(is_long_compressed ? 1 : 0) + // branch count
1 + // data length and other flags
dlen + // data
(i - branches_start) // branches and leaves
);
const canonical = new Uint8Array(clen);
let ci = 0;
canonical[ci] = input[start] ^ 0x08;
ci += 1;
if (is_long_compressed) {
canonical[ci] = input[start + ci];
ci += 1;
}
canonical[ci] = dlen | no_leaves_flag | 0x40;
ci += 1;
for (let j = 0; j < dlen; j += 1) {
canonical[ci] = data[j];
ci += 1;
}
for (let j = branches_start; j < i; j += 1) {
canonical[ci] = input[j];
ci += 1;
}
tree = new InlineNeighborsTree(canonical, 0);
siphashOfBytes(canonical, 0, 0, 0, 0, hash);
} else {
tree = new InlineNeighborsTree(input, start);
siphashOfBytes(new Uint8Array(
input.buffer,
start + input.byteOffset,
i - start,
), 0, 0, 0, 0, hash);
}
} else if (compression_tag > 1) {
// compressed node
if (is_pure_suffixes_only_node) {
data = EMPTY_UINT8;
} else if (is_data_compressed) {
data = data_history[data_history.length - dlen - 1];
dlen = data.length;
} else {
data = dlen === 0 ?
EMPTY_UINT8 :
new Uint8Array(input.buffer, i + input.byteOffset, dlen);
i += dlen;
}
const coffset = i;
const {
cpbranches,
@ -2775,29 +3067,42 @@ function loadDatabase(hooks) {
let whole;
let suffix;
if (is_pure_suffixes_only_node) {
suffix = input[i] === 0 ?
EMPTY_BITMAP1 :
new RoaringBitmap(input, i);
i += suffix.consumed_len_bytes;
if (no_leaves_flag) {
whole = EMPTY_BITMAP;
suffix = EMPTY_BITMAP;
} else {
suffix = input[i] === 0 ?
EMPTY_BITMAP1 :
new RoaringBitmap(input, i);
i += suffix.consumed_len_bytes;
}
tree = new SuffixSearchTree(
branches,
dlen,
suffix,
);
const clen = (
3 + // lengths of children and data
// lengths of children and data
(is_data_compressed ? 2 : 3) +
// branches
csnodes.length +
csbranches.length +
// leaves
suffix.consumed_len_bytes
);
if (canonical.length < clen) {
canonical = new Uint8Array(clen);
}
let ci = 0;
canonical[ci] = 1;
ci += 1;
canonical[ci] = dlen;
ci += 1;
if (is_data_compressed) {
canonical[ci] = 0x09;
ci += 1;
} else {
canonical[ci] = 1;
ci += 1;
canonical[ci] = dlen | no_leaves_flag;
ci += 1;
}
canonical[ci] = input[coffset]; // suffix child count
ci += 1;
canonical.set(csnodes, ci);
@ -2810,10 +3115,9 @@ function loadDatabase(hooks) {
}
siphashOfBytes(canonical.subarray(0, clen), 0, 0, 0, 0, hash);
} else {
if (input[i] === 0xff) {
if (no_leaves_flag) {
whole = EMPTY_BITMAP;
suffix = EMPTY_BITMAP1;
i += 1;
suffix = EMPTY_BITMAP;
} else {
whole = input[i] === 0 ?
EMPTY_BITMAP1 :
@ -2845,7 +3149,7 @@ function loadDatabase(hooks) {
let ci = 0;
canonical[ci] = 0;
ci += 1;
canonical[ci] = dlen;
canonical[ci] = dlen | no_leaves_flag;
ci += 1;
canonical.set(data, ci);
ci += data.length;
@ -2867,11 +3171,8 @@ function loadDatabase(hooks) {
}
siphashOfBytes(canonical.subarray(0, clen), 0, 0, 0, 0, hash);
}
hash[2] &= 0x7f;
} else {
// uncompressed node
const dlen = input [i + 1];
i += 2;
if (dlen === 0 || is_pure_suffixes_only_node) {
data = EMPTY_UINT8;
} else {
@ -2886,16 +3187,15 @@ function loadDatabase(hooks) {
i += branches_consumed_len_bytes;
let whole;
let suffix;
if (is_pure_suffixes_only_node) {
if (no_leaves_flag) {
whole = EMPTY_BITMAP;
suffix = EMPTY_BITMAP;
} else if (is_pure_suffixes_only_node) {
whole = EMPTY_BITMAP;
suffix = input[i] === 0 ?
EMPTY_BITMAP1 :
new RoaringBitmap(input, i);
i += suffix.consumed_len_bytes;
} else if (input[i] === 0xff) {
whole = EMPTY_BITMAP;
suffix = EMPTY_BITMAP;
i += 1;
} else {
whole = input[i] === 0 ?
EMPTY_BITMAP1 :
@ -2911,7 +3211,6 @@ function loadDatabase(hooks) {
start + input.byteOffset,
i - start,
), 0, 0, 0, 0, hash);
hash[2] &= 0x7f;
tree = is_pure_suffixes_only_node ?
new SuffixSearchTree(
branches,
@ -2926,30 +3225,33 @@ function loadDatabase(hooks) {
suffix,
);
}
hash[2] &= 0x7f;
hash_history.push({hash: truncatedHash.slice(), used: false});
if (data.length !== 0) {
data_history.push(data);
}
const tree_branch_nodeids = tree.branches.nodeids;
const tree_branch_subtrees = tree.branches.subtrees;
let j = 0;
let lb = tree.branches.subtrees.length;
while (j < lb) {
// node id with a 1 in its most significant bit is inlined, and, so
// it won't be in the stash
if ((tree_branch_nodeids[j * 6] & 0x80) === 0) {
const subtree = stash.getWithOffsetKey(tree_branch_nodeids, j * 6);
if (subtree !== undefined) {
tree_branch_subtrees[j] = Promise.resolve(subtree);
if (!(tree instanceof InlineNeighborsTree)) {
const tree_branch_nodeids = tree.branches.nodeids;
const tree_branch_subtrees = tree.branches.subtrees;
let j = 0;
const lb = tree.branches.subtrees.length;
while (j < lb) {
// node id with a 1 in its most significant bit is inlined, and, so
// it won't be in the stash
if ((tree_branch_nodeids[j * 6] & 0x80) === 0) {
const subtree = stash.getWithOffsetKey(tree_branch_nodeids, j * 6);
if (subtree !== undefined) {
tree_branch_subtrees[j] = Promise.resolve(subtree);
}
}
j += 1;
}
j += 1;
}
if (tree instanceof PrefixSearchTree) {
const tree_mhp_branch_nodeids = tree.might_have_prefix_branches.nodeids;
const tree_mhp_branch_subtrees = tree.might_have_prefix_branches.subtrees;
j = 0;
lb = tree.might_have_prefix_branches.subtrees.length;
let j = 0;
const lb = tree.might_have_prefix_branches.subtrees.length;
while (j < lb) {
// node id with a 1 in its most significant bit is inlined, and, so
// it won't be in the stash

View file

@ -371,9 +371,9 @@ fn parse_len_output<'tcx>(cx: &LateContext<'tcx>, sig: FnSig<'tcx>) -> Option<Le
match *sig.output().kind() {
ty::Int(_) | ty::Uint(_) => Some(LenOutput::Integral),
ty::Adt(adt, subs) if subs.type_at(0).is_integral() => match cx.tcx.get_diagnostic_name(adt.did()) {
Some(sym::Option) => Some(LenOutput::Option(adt.did())),
Some(sym::Result) => Some(LenOutput::Result(adt.did())),
ty::Adt(adt, subs) => match cx.tcx.get_diagnostic_name(adt.did()) {
Some(sym::Option) => subs.type_at(0).is_integral().then(|| LenOutput::Option(adt.did())),
Some(sym::Result) => subs.type_at(0).is_integral().then(|| LenOutput::Result(adt.did())),
_ => None,
},
_ => None,

View file

@ -0,0 +1,11 @@
//@check-pass
#![warn(clippy::len_zero)]
pub struct S1;
pub struct S2;
impl S1 {
pub fn len(&self) -> S2 {
S2
}
}

View file

@ -9,6 +9,7 @@ LL | println!("{:?}{}", (), { format_args!("{:?}", ()) });
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see <https://doc.rust-lang.org/rustc/lints/listing/warn-by-default.html#macro-extended-temporary-scopes>
= note: consider using a `let` binding to create a longer lived value
= note: some temporaries were previously incorrectly lifetime-extended since Rust 1.89 in formatting macros, and since Rust 1.88 in `pin!()`
= note: `#[warn(macro_extended_temporary_scopes)]` (part of `#[warn(future_incompatible)]`) on by default
warning: 1 warning emitted

View file

@ -9,6 +9,7 @@ LL | println!("{:?}{:?}", (), if cond() { &format!("") } else { "" });
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see <https://doc.rust-lang.org/rustc/lints/listing/warn-by-default.html#macro-extended-temporary-scopes>
= note: consider using a `let` binding to create a longer lived value
= note: some temporaries were previously incorrectly lifetime-extended since Rust 1.89 in formatting macros, and since Rust 1.88 in `pin!()`
= note: `#[warn(macro_extended_temporary_scopes)]` (part of `#[warn(future_incompatible)]`) on by default
= note: this warning originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info)
@ -23,6 +24,7 @@ LL | println!("{:?}{:?}", (), if cond() { &"".to_string() } else { "" });
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see <https://doc.rust-lang.org/rustc/lints/listing/warn-by-default.html#macro-extended-temporary-scopes>
= note: consider using a `let` binding to create a longer lived value
= note: some temporaries were previously incorrectly lifetime-extended since Rust 1.89 in formatting macros, and since Rust 1.88 in `pin!()`
warning: temporary lifetime will be shortened in Rust 1.92
--> $DIR/macro-extended-temporary-scopes.rs:39:43
@ -35,6 +37,7 @@ LL | println!("{:?}{:?}", (), if cond() { &("string".to_owned() + "string")
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see <https://doc.rust-lang.org/rustc/lints/listing/warn-by-default.html#macro-extended-temporary-scopes>
= note: consider using a `let` binding to create a longer lived value
= note: some temporaries were previously incorrectly lifetime-extended since Rust 1.89 in formatting macros, and since Rust 1.88 in `pin!()`
warning: temporary lifetime will be shortened in Rust 1.92
--> $DIR/macro-extended-temporary-scopes.rs:58:17
@ -48,6 +51,7 @@ LL | }
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see <https://doc.rust-lang.org/rustc/lints/listing/warn-by-default.html#macro-extended-temporary-scopes>
= note: consider using a `let` binding to create a longer lived value
= note: some temporaries were previously incorrectly lifetime-extended since Rust 1.89 in formatting macros, and since Rust 1.88 in `pin!()`
warning: temporary lifetime will be shortened in Rust 1.92
--> $DIR/macro-extended-temporary-scopes.rs:54:14
@ -61,6 +65,7 @@ LL | } else {
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see <https://doc.rust-lang.org/rustc/lints/listing/warn-by-default.html#macro-extended-temporary-scopes>
= note: consider using a `let` binding to create a longer lived value
= note: some temporaries were previously incorrectly lifetime-extended since Rust 1.89 in formatting macros, and since Rust 1.88 in `pin!()`
warning: temporary lifetime will be shortened in Rust 1.92
--> $DIR/macro-extended-temporary-scopes.rs:50:14
@ -74,6 +79,7 @@ LL | } else if cond() {
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see <https://doc.rust-lang.org/rustc/lints/listing/warn-by-default.html#macro-extended-temporary-scopes>
= note: consider using a `let` binding to create a longer lived value
= note: some temporaries were previously incorrectly lifetime-extended since Rust 1.89 in formatting macros, and since Rust 1.88 in `pin!()`
warning: temporary lifetime will be shortened in Rust 1.92
--> $DIR/macro-extended-temporary-scopes.rs:46:14
@ -87,6 +93,7 @@ LL | } else if cond() {
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see <https://doc.rust-lang.org/rustc/lints/listing/warn-by-default.html#macro-extended-temporary-scopes>
= note: consider using a `let` binding to create a longer lived value
= note: some temporaries were previously incorrectly lifetime-extended since Rust 1.89 in formatting macros, and since Rust 1.88 in `pin!()`
warning: 7 warnings emitted

View file

@ -9,6 +9,7 @@ LL | println!("{:?}{:?}", { &temp() }, ());
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see <https://doc.rust-lang.org/rustc/lints/listing/warn-by-default.html#macro-extended-temporary-scopes>
= note: consider using a `let` binding to create a longer lived value
= note: some temporaries were previously incorrectly lifetime-extended since Rust 1.89 in formatting macros, and since Rust 1.88 in `pin!()`
= note: `#[warn(macro_extended_temporary_scopes)]` (part of `#[warn(future_incompatible)]`) on by default
warning: temporary lifetime will be shortened in Rust 1.92
@ -22,6 +23,7 @@ LL | println!("{:?}{:?}", (), if cond() { &format!("") } else { "" });
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see <https://doc.rust-lang.org/rustc/lints/listing/warn-by-default.html#macro-extended-temporary-scopes>
= note: consider using a `let` binding to create a longer lived value
= note: some temporaries were previously incorrectly lifetime-extended since Rust 1.89 in formatting macros, and since Rust 1.88 in `pin!()`
= note: this warning originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info)
warning: temporary lifetime will be shortened in Rust 1.92
@ -35,6 +37,7 @@ LL | println!("{:?}{:?}", (), if cond() { &"".to_string() } else { "" });
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see <https://doc.rust-lang.org/rustc/lints/listing/warn-by-default.html#macro-extended-temporary-scopes>
= note: consider using a `let` binding to create a longer lived value
= note: some temporaries were previously incorrectly lifetime-extended since Rust 1.89 in formatting macros, and since Rust 1.88 in `pin!()`
warning: temporary lifetime will be shortened in Rust 1.92
--> $DIR/macro-extended-temporary-scopes.rs:39:43
@ -47,6 +50,7 @@ LL | println!("{:?}{:?}", (), if cond() { &("string".to_owned() + "string")
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see <https://doc.rust-lang.org/rustc/lints/listing/warn-by-default.html#macro-extended-temporary-scopes>
= note: consider using a `let` binding to create a longer lived value
= note: some temporaries were previously incorrectly lifetime-extended since Rust 1.89 in formatting macros, and since Rust 1.88 in `pin!()`
warning: temporary lifetime will be shortened in Rust 1.92
--> $DIR/macro-extended-temporary-scopes.rs:58:17
@ -60,6 +64,7 @@ LL | }
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see <https://doc.rust-lang.org/rustc/lints/listing/warn-by-default.html#macro-extended-temporary-scopes>
= note: consider using a `let` binding to create a longer lived value
= note: some temporaries were previously incorrectly lifetime-extended since Rust 1.89 in formatting macros, and since Rust 1.88 in `pin!()`
warning: temporary lifetime will be shortened in Rust 1.92
--> $DIR/macro-extended-temporary-scopes.rs:54:14
@ -73,6 +78,7 @@ LL | } else {
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see <https://doc.rust-lang.org/rustc/lints/listing/warn-by-default.html#macro-extended-temporary-scopes>
= note: consider using a `let` binding to create a longer lived value
= note: some temporaries were previously incorrectly lifetime-extended since Rust 1.89 in formatting macros, and since Rust 1.88 in `pin!()`
warning: temporary lifetime will be shortened in Rust 1.92
--> $DIR/macro-extended-temporary-scopes.rs:50:14
@ -86,6 +92,7 @@ LL | } else if cond() {
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see <https://doc.rust-lang.org/rustc/lints/listing/warn-by-default.html#macro-extended-temporary-scopes>
= note: consider using a `let` binding to create a longer lived value
= note: some temporaries were previously incorrectly lifetime-extended since Rust 1.89 in formatting macros, and since Rust 1.88 in `pin!()`
warning: temporary lifetime will be shortened in Rust 1.92
--> $DIR/macro-extended-temporary-scopes.rs:46:14
@ -99,6 +106,7 @@ LL | } else if cond() {
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see <https://doc.rust-lang.org/rustc/lints/listing/warn-by-default.html#macro-extended-temporary-scopes>
= note: consider using a `let` binding to create a longer lived value
= note: some temporaries were previously incorrectly lifetime-extended since Rust 1.89 in formatting macros, and since Rust 1.88 in `pin!()`
warning: temporary lifetime will be shortened in Rust 1.92
--> $DIR/macro-extended-temporary-scopes.rs:65:18
@ -111,6 +119,7 @@ LL | pin!(pin!({ &temp() }));
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see <https://doc.rust-lang.org/rustc/lints/listing/warn-by-default.html#macro-extended-temporary-scopes>
= note: consider using a `let` binding to create a longer lived value
= note: some temporaries were previously incorrectly lifetime-extended since Rust 1.89 in formatting macros, and since Rust 1.88 in `pin!()`
warning: temporary lifetime will be shortened in Rust 1.92
--> $DIR/macro-extended-temporary-scopes.rs:96:13
@ -123,6 +132,7 @@ LL | pin!({ &(1 / 0) });
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see <https://doc.rust-lang.org/rustc/lints/listing/warn-by-default.html#macro-extended-temporary-scopes>
= note: consider using a `let` binding to create a longer lived value
= note: some temporaries were previously incorrectly lifetime-extended since Rust 1.89 in formatting macros, and since Rust 1.88 in `pin!()`
warning: temporary lifetime will be shortened in Rust 1.92
--> $DIR/macro-extended-temporary-scopes.rs:99:17
@ -135,6 +145,7 @@ LL | pin!({ &mut [()] });
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see <https://doc.rust-lang.org/rustc/lints/listing/warn-by-default.html#macro-extended-temporary-scopes>
= note: consider using a `let` binding to create a longer lived value
= note: some temporaries were previously incorrectly lifetime-extended since Rust 1.89 in formatting macros, and since Rust 1.88 in `pin!()`
warning: temporary lifetime will be shortened in Rust 1.92
--> $DIR/macro-extended-temporary-scopes.rs:102:13
@ -147,6 +158,7 @@ LL | pin!({ &Some(String::new()) });
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see <https://doc.rust-lang.org/rustc/lints/listing/warn-by-default.html#macro-extended-temporary-scopes>
= note: consider using a `let` binding to create a longer lived value
= note: some temporaries were previously incorrectly lifetime-extended since Rust 1.89 in formatting macros, and since Rust 1.88 in `pin!()`
warning: temporary lifetime will be shortened in Rust 1.92
--> $DIR/macro-extended-temporary-scopes.rs:105:13
@ -159,6 +171,7 @@ LL | pin!({ &(|| ())() });
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see <https://doc.rust-lang.org/rustc/lints/listing/warn-by-default.html#macro-extended-temporary-scopes>
= note: consider using a `let` binding to create a longer lived value
= note: some temporaries were previously incorrectly lifetime-extended since Rust 1.89 in formatting macros, and since Rust 1.88 in `pin!()`
warning: temporary lifetime will be shortened in Rust 1.92
--> $DIR/macro-extended-temporary-scopes.rs:108:13
@ -171,6 +184,7 @@ LL | pin!({ &|| &local });
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see <https://doc.rust-lang.org/rustc/lints/listing/warn-by-default.html#macro-extended-temporary-scopes>
= note: consider using a `let` binding to create a longer lived value
= note: some temporaries were previously incorrectly lifetime-extended since Rust 1.89 in formatting macros, and since Rust 1.88 in `pin!()`
warning: temporary lifetime will be shortened in Rust 1.92
--> $DIR/macro-extended-temporary-scopes.rs:111:13
@ -183,6 +197,7 @@ LL | pin!({ &CONST_STRING });
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see <https://doc.rust-lang.org/rustc/lints/listing/warn-by-default.html#macro-extended-temporary-scopes>
= note: consider using a `let` binding to create a longer lived value
= note: some temporaries were previously incorrectly lifetime-extended since Rust 1.89 in formatting macros, and since Rust 1.88 in `pin!()`
warning: 15 warnings emitted

View file

@ -10,6 +10,7 @@ LL | wrap!(String::new())
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see <https://doc.rust-lang.org/rustc/lints/listing/warn-by-default.html#macro-extended-temporary-scopes>
= note: consider using a `let` binding to create a longer lived value
= note: some temporaries were previously incorrectly lifetime-extended since Rust 1.89 in formatting macros, and since Rust 1.88 in `pin!()`
= note: `#[warn(macro_extended_temporary_scopes)]` (part of `#[warn(future_incompatible)]`) on by default
warning: temporary lifetime will be shortened in Rust 1.92
@ -27,6 +28,7 @@ LL | print_with_internal_wrap!();
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see <https://doc.rust-lang.org/rustc/lints/listing/warn-by-default.html#macro-extended-temporary-scopes>
= note: consider using a `let` binding to create a longer lived value
= note: some temporaries were previously incorrectly lifetime-extended since Rust 1.89 in formatting macros, and since Rust 1.88 in `pin!()`
= note: this warning originates in the macro `print_with_internal_wrap` (in Nightly builds, run with -Z macro-backtrace for more info)
warning: temporary lifetime will be shortened in Rust 1.92
@ -41,6 +43,7 @@ LL | external_macros::wrap!(String::new())
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see <https://doc.rust-lang.org/rustc/lints/listing/warn-by-default.html#macro-extended-temporary-scopes>
= note: consider using a `let` binding to create a longer lived value
= note: some temporaries were previously incorrectly lifetime-extended since Rust 1.89 in formatting macros, and since Rust 1.88 in `pin!()`
warning: temporary lifetime will be shortened in Rust 1.92
--> $DIR/user-defined-macros.rs:52:5
@ -54,6 +57,7 @@ LL | external_macros::print_with_internal_wrap!();
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see <https://doc.rust-lang.org/rustc/lints/listing/warn-by-default.html#macro-extended-temporary-scopes>
= note: consider using a `let` binding to create a longer lived value
= note: some temporaries were previously incorrectly lifetime-extended since Rust 1.89 in formatting macros, and since Rust 1.88 in `pin!()`
= note: this warning originates in the macro `external_macros::print_with_internal_wrap` (in Nightly builds, run with -Z macro-backtrace for more info)
warning: 4 warnings emitted