diff --git a/RELEASES.md b/RELEASES.md index 54465621b734b..3707f170a5736 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,3 +1,235 @@ +Version 1.83.0 (2024-11-28) +========================== + + + +Language +-------- +- [Stabilize `&mut`, `*mut`, `&Cell`, and `*const Cell` in const.](https://github.com/rust-lang/rust/pull/129195) +- [Allow creating references to statics in `const` initializers.](https://github.com/rust-lang/rust/pull/129759) +- [Implement raw lifetimes and labels (`'r#ident`).](https://github.com/rust-lang/rust/pull/126452) +- [Define behavior when atomic and non-atomic reads race.](https://github.com/rust-lang/rust/pull/128778) +- [Non-exhaustive structs may now be empty.](https://github.com/rust-lang/rust/pull/128934) +- [Disallow implicit coercions from places of type `!`](https://github.com/rust-lang/rust/pull/129392) +- [`const extern` functions can now be defined for other calling conventions.](https://github.com/rust-lang/rust/pull/129753) +- [Stabilize `expr_2021` macro fragment specifier in all editions.](https://github.com/rust-lang/rust/pull/129972) +- [The `non_local_definitions` lint now fires on less code and warns by default.](https://github.com/rust-lang/rust/pull/127117) + + + + +Compiler +-------- +- [Deprecate unsound `-Csoft-float` flag.](https://github.com/rust-lang/rust/pull/129897) +- Add many new tier 3 targets: + - [`aarch64_unknown_nto_qnx700`](https://github.com/rust-lang/rust/pull/127897) + - [`arm64e-apple-tvos`](https://github.com/rust-lang/rust/pull/130614) + - [`armv7-rtems-eabihf`](https://github.com/rust-lang/rust/pull/127021) + - [`loongarch64-unknown-linux-ohos`](https://github.com/rust-lang/rust/pull/130750) + - [`riscv32-wrs-vxworks` and `riscv64-wrs-vxworks`](https://github.com/rust-lang/rust/pull/130549) + - [`riscv32{e|em|emc}-unknown-none-elf`](https://github.com/rust-lang/rust/pull/130555) + - [`x86_64-unknown-hurd-gnu`](https://github.com/rust-lang/rust/pull/128345) + - [`x86_64-unknown-trusty`](https://github.com/rust-lang/rust/pull/130453) + +Refer to Rust's [platform support page][platform-support-doc] +for more information on Rust's tiered platform support. + + + + +Libraries +--------- +- [Implement `PartialEq` for `ExitCode`.](https://github.com/rust-lang/rust/pull/127633) +- [Document that `catch_unwind` can deal with foreign exceptions without UB, although the exact behavior is unspecified.](https://github.com/rust-lang/rust/pull/128321) +- [Implement `Default` for `HashMap`/`HashSet` iterators that don't already have it.](https://github.com/rust-lang/rust/pull/128711) +- [Bump Unicode to version 16.0.0.](https://github.com/rust-lang/rust/pull/130183) +- [Change documentation of `ptr::add`/`sub` to not claim equivalence with `offset`.](https://github.com/rust-lang/rust/pull/130229). + + + + +Stabilized APIs +--------------- + +- [`BufRead::skip_until`](https://doc.rust-lang.org/stable/std/io/trait.BufRead.html#method.skip_until) +- [`ControlFlow::break_value`](https://doc.rust-lang.org/stable/core/ops/enum.ControlFlow.html#method.break_value) +- [`ControlFlow::continue_value`](https://doc.rust-lang.org/stable/core/ops/enum.ControlFlow.html#method.continue_value) +- [`ControlFlow::map_break`](https://doc.rust-lang.org/stable/core/ops/enum.ControlFlow.html#method.map_break) +- [`ControlFlow::map_continue`](https://doc.rust-lang.org/stable/core/ops/enum.ControlFlow.html#method.map_continue) +- [`DebugList::finish_non_exhaustive`](https://doc.rust-lang.org/stable/core/fmt/struct.DebugList.html#method.finish_non_exhaustive) +- [`DebugMap::finish_non_exhaustive`](https://doc.rust-lang.org/stable/core/fmt/struct.DebugMap.html#method.finish_non_exhaustive) +- [`DebugSet::finish_non_exhaustive`](https://doc.rust-lang.org/stable/core/fmt/struct.DebugSet.html#method.finish_non_exhaustive) +- [`DebugTuple::finish_non_exhaustive`](https://doc.rust-lang.org/stable/core/fmt/struct.DebugTuple.html#method.finish_non_exhaustive) +- [`ErrorKind::ArgumentListTooLong`](https://doc.rust-lang.org/stable/std/io/enum.ErrorKind.html#variant.ArgumentListTooLong) +- [`ErrorKind::Deadlock`](https://doc.rust-lang.org/stable/std/io/enum.ErrorKind.html#variant.Deadlock) +- [`ErrorKind::DirectoryNotEmpty`](https://doc.rust-lang.org/stable/std/io/enum.ErrorKind.html#variant.DirectoryNotEmpty) +- [`ErrorKind::ExecutableFileBusy`](https://doc.rust-lang.org/stable/std/io/enum.ErrorKind.html#variant.ExecutableFileBusy) +- [`ErrorKind::FileTooLarge`](https://doc.rust-lang.org/stable/std/io/enum.ErrorKind.html#variant.FileTooLarge) +- [`ErrorKind::HostUnreachable`](https://doc.rust-lang.org/stable/std/io/enum.ErrorKind.html#variant.HostUnreachable) +- [`ErrorKind::IsADirectory`](https://doc.rust-lang.org/stable/std/io/enum.ErrorKind.html#variant.IsADirectory) +- [`ErrorKind::NetworkDown`](https://doc.rust-lang.org/stable/std/io/enum.ErrorKind.html#variant.NetworkDown) +- [`ErrorKind::NetworkUnreachable`](https://doc.rust-lang.org/stable/std/io/enum.ErrorKind.html#variant.NetworkUnreachable) +- [`ErrorKind::NotADirectory`](https://doc.rust-lang.org/stable/std/io/enum.ErrorKind.html#variant.NotADirectory) +- [`ErrorKind::NotSeekable`](https://doc.rust-lang.org/stable/std/io/enum.ErrorKind.html#variant.NotSeekable) +- [`ErrorKind::ReadOnlyFilesystem`](https://doc.rust-lang.org/stable/std/io/enum.ErrorKind.html#variant.ReadOnlyFilesystem) +- [`ErrorKind::ResourceBusy`](https://doc.rust-lang.org/stable/std/io/enum.ErrorKind.html#variant.ResourceBusy) +- [`ErrorKind::StaleNetworkFileHandle`](https://doc.rust-lang.org/stable/std/io/enum.ErrorKind.html#variant.StaleNetworkFileHandle) +- [`ErrorKind::StorageFull`](https://doc.rust-lang.org/stable/std/io/enum.ErrorKind.html#variant.StorageFull) +- [`ErrorKind::TooManyLinks`](https://doc.rust-lang.org/stable/std/io/enum.ErrorKind.html#variant.TooManyLinks) +- [`Option::get_or_insert_default`](https://doc.rust-lang.org/stable/core/option/enum.Option.html#method.get_or_insert_default) +- [`Waker::data`](https://doc.rust-lang.org/stable/core/task/struct.Waker.html#method.data) +- [`Waker::new`](https://doc.rust-lang.org/stable/core/task/struct.Waker.html#method.new) +- [`Waker::vtable`](https://doc.rust-lang.org/stable/core/task/struct.Waker.html#method.vtable) +- [`char::MIN`](https://doc.rust-lang.org/stable/core/primitive.char.html#associatedconstant.MIN) +- [`hash_map::Entry::insert_entry`](https://doc.rust-lang.org/stable/std/collections/hash_map/enum.Entry.html#method.insert_entry) +- [`hash_map::VacantEntry::insert_entry`](https://doc.rust-lang.org/stable/std/collections/hash_map/struct.VacantEntry.html#method.insert_entry) + +These APIs are now stable in const contexts: + +- [`Cell::into_inner`](https://doc.rust-lang.org/stable/core/cell/struct.Cell.html#method.into_inner) +- [`Duration::as_secs_f32`](https://doc.rust-lang.org/stable/core/time/struct.Duration.html#method.as_secs_f32) +- [`Duration::as_secs_f64`](https://doc.rust-lang.org/stable/core/time/struct.Duration.html#method.as_secs_f64) +- [`Duration::div_duration_f32`](https://doc.rust-lang.org/stable/core/time/struct.Duration.html#method.div_duration_f32) +- [`Duration::div_duration_f64`](https://doc.rust-lang.org/stable/core/time/struct.Duration.html#method.div_duration_f64) +- [`MaybeUninit::as_mut_ptr`](https://doc.rust-lang.org/stable/core/mem/union.MaybeUninit.html#method.as_mut_ptr) +- [`NonNull::as_mut`](https://doc.rust-lang.org/stable/core/ptr/struct.NonNull.html#method.as_mut) +- [`NonNull::copy_from`](https://doc.rust-lang.org/stable/core/ptr/struct.NonNull.html#method.copy_from) +- [`NonNull::copy_from_nonoverlapping`](https://doc.rust-lang.org/stable/core/ptr/struct.NonNull.html#method.copy_from_nonoverlapping) +- [`NonNull::copy_to`](https://doc.rust-lang.org/stable/core/ptr/struct.NonNull.html#method.copy_to) +- [`NonNull::copy_to_nonoverlapping`](https://doc.rust-lang.org/stable/core/ptr/struct.NonNull.html#method.copy_to_nonoverlapping) +- [`NonNull::slice_from_raw_parts`](https://doc.rust-lang.org/stable/core/ptr/struct.NonNull.html#method.slice_from_raw_parts) +- [`NonNull::write`](https://doc.rust-lang.org/stable/core/ptr/struct.NonNull.html#method.write) +- [`NonNull::write_bytes`](https://doc.rust-lang.org/stable/core/ptr/struct.NonNull.html#method.write_bytes) +- [`NonNull::write_unaligned`](https://doc.rust-lang.org/stable/core/ptr/struct.NonNull.html#method.write_unaligned) +- [`OnceCell::into_inner`](https://doc.rust-lang.org/stable/core/cell/struct.OnceCell.html#method.into_inner) +- [`Option::as_mut`](https://doc.rust-lang.org/stable/core/option/enum.Option.html#method.as_mut) +- [`Option::expect`](https://doc.rust-lang.org/stable/core/option/enum.Option.html#method.expect) +- [`Option::replace`](https://doc.rust-lang.org/stable/core/option/enum.Option.html#method.replace) +- [`Option::take`](https://doc.rust-lang.org/stable/core/option/enum.Option.html#method.take) +- [`Option::unwrap`](https://doc.rust-lang.org/stable/core/option/enum.Option.html#method.unwrap) +- [`Option::unwrap_unchecked`](https://doc.rust-lang.org/stable/core/option/enum.Option.html#method.unwrap_unchecked) +- [`Option::<&_>::copied`](https://doc.rust-lang.org/stable/core/option/enum.Option.html#method.copied) +- [`Option::<&mut _>::copied`](https://doc.rust-lang.org/stable/core/option/enum.Option.html#method.copied-1) +- [`Option::>::flatten`](https://doc.rust-lang.org/stable/core/option/enum.Option.html#method.flatten) +- [`Option::>::transpose`](https://doc.rust-lang.org/stable/core/option/enum.Option.html#method.transpose) +- [`RefCell::into_inner`](https://doc.rust-lang.org/stable/core/cell/struct.RefCell.html#method.into_inner) +- [`Result::as_mut`](https://doc.rust-lang.org/stable/core/result/enum.Result.html#method.as_mut) +- [`Result::<&_, _>::copied`](https://doc.rust-lang.org/stable/core/result/enum.Result.html#method.copied) +- [`Result::<&mut _, _>::copied`](https://doc.rust-lang.org/stable/core/result/enum.Result.html#method.copied-1) +- [`Result::, _>::transpose`](https://doc.rust-lang.org/stable/core/result/enum.Result.html#method.transpose) +- [`UnsafeCell::get_mut`](https://doc.rust-lang.org/stable/core/cell/struct.UnsafeCell.html#method.get_mut) +- [`UnsafeCell::into_inner`](https://doc.rust-lang.org/stable/core/cell/struct.UnsafeCell.html#method.into_inner) +- [`array::from_mut`](https://doc.rust-lang.org/stable/core/array/fn.from_mut.html) +- [`char::encode_utf8`](https://doc.rust-lang.org/stable/core/primitive.char.html#method.encode_utf8) +- [`{float}::classify`](https://doc.rust-lang.org/stable/core/primitive.f64.html#method.classify) +- [`{float}::is_finite`](https://doc.rust-lang.org/stable/core/primitive.f64.html#method.is_finite) +- [`{float}::is_infinite`](https://doc.rust-lang.org/stable/core/primitive.f64.html#method.is_infinite) +- [`{float}::is_nan`](https://doc.rust-lang.org/stable/core/primitive.f64.html#method.is_nan) +- [`{float}::is_normal`](https://doc.rust-lang.org/stable/core/primitive.f64.html#method.is_normal) +- [`{float}::is_sign_negative`](https://doc.rust-lang.org/stable/core/primitive.f64.html#method.is_sign_negative) +- [`{float}::is_sign_positive`](https://doc.rust-lang.org/stable/core/primitive.f64.html#method.is_sign_positive) +- [`{float}::is_subnormal`](https://doc.rust-lang.org/stable/core/primitive.f64.html#method.is_subnormal) +- [`{float}::from_bits`](https://doc.rust-lang.org/stable/core/primitive.f64.html#method.from_bits) +- [`{float}::from_be_bytes`](https://doc.rust-lang.org/stable/core/primitive.f64.html#method.from_be_bytes) +- [`{float}::from_le_bytes`](https://doc.rust-lang.org/stable/core/primitive.f64.html#method.from_le_bytes) +- [`{float}::from_ne_bytes`](https://doc.rust-lang.org/stable/core/primitive.f64.html#method.from_ne_bytes) +- [`{float}::to_bits`](https://doc.rust-lang.org/stable/core/primitive.f64.html#method.to_bits) +- [`{float}::to_be_bytes`](https://doc.rust-lang.org/stable/core/primitive.f64.html#method.to_be_bytes) +- [`{float}::to_le_bytes`](https://doc.rust-lang.org/stable/core/primitive.f64.html#method.to_le_bytes) +- [`{float}::to_ne_bytes`](https://doc.rust-lang.org/stable/core/primitive.f64.html#method.to_ne_bytes) +- [`mem::replace`](https://doc.rust-lang.org/stable/core/mem/fn.replace.html) +- [`ptr::replace`](https://doc.rust-lang.org/stable/core/ptr/fn.replace.html) +- [`ptr::slice_from_raw_parts_mut`](https://doc.rust-lang.org/stable/core/ptr/fn.slice_from_raw_parts_mut.html) +- [`ptr::write`](https://doc.rust-lang.org/stable/core/ptr/fn.write.html) +- [`ptr::write_unaligned`](https://doc.rust-lang.org/stable/core/ptr/fn.write_unaligned.html) +- [`<*const _>::copy_to`](https://doc.rust-lang.org/stable/core/primitive.pointer.html#method.copy_to) +- [`<*const _>::copy_to_nonoverlapping`](https://doc.rust-lang.org/stable/core/primitive.pointer.html#method.copy_to_nonoverlapping) +- [`<*mut _>::copy_from`](https://doc.rust-lang.org/stable/core/primitive.pointer.html#method.copy_from) +- [`<*mut _>::copy_from_nonoverlapping`](https://doc.rust-lang.org/stable/core/primitive.pointer.html#method.copy_from_nonoverlapping) +- [`<*mut _>::copy_to`](https://doc.rust-lang.org/stable/core/primitive.pointer.html#method.copy_to-1) +- [`<*mut _>::copy_to_nonoverlapping`](https://doc.rust-lang.org/stable/core/primitive.pointer.html#method.copy_to_nonoverlapping-1) +- [`<*mut _>::write`](https://doc.rust-lang.org/stable/core/primitive.pointer.html#method.write) +- [`<*mut _>::write_bytes`](https://doc.rust-lang.org/stable/core/primitive.pointer.html#method.write_bytes) +- [`<*mut _>::write_unaligned`](https://doc.rust-lang.org/stable/core/primitive.pointer.html#method.write_unaligned) +- [`slice::from_mut`](https://doc.rust-lang.org/stable/core/slice/fn.from_mut.html) +- [`slice::from_raw_parts_mut`](https://doc.rust-lang.org/stable/core/slice/fn.from_raw_parts_mut.html) +- [`<[_]>::first_mut`](https://doc.rust-lang.org/stable/core/primitive.slice.html#method.first_mut) +- [`<[_]>::last_mut`](https://doc.rust-lang.org/stable/core/primitive.slice.html#method.last_mut) +- [`<[_]>::first_chunk_mut`](https://doc.rust-lang.org/stable/core/primitive.slice.html#method.first_chunk_mut) +- [`<[_]>::last_chunk_mut`](https://doc.rust-lang.org/stable/core/primitive.slice.html#method.last_chunk_mut) +- [`<[_]>::split_at_mut`](https://doc.rust-lang.org/stable/core/primitive.slice.html#method.split_at_mut) +- [`<[_]>::split_at_mut_checked`](https://doc.rust-lang.org/stable/core/primitive.slice.html#method.split_at_mut_checked) +- [`<[_]>::split_at_mut_unchecked`](https://doc.rust-lang.org/stable/core/primitive.slice.html#method.split_at_mut_unchecked) +- [`<[_]>::split_first_mut`](https://doc.rust-lang.org/stable/core/primitive.slice.html#method.split_first_mut) +- [`<[_]>::split_last_mut`](https://doc.rust-lang.org/stable/core/primitive.slice.html#method.split_last_mut) +- [`<[_]>::split_first_chunk_mut`](https://doc.rust-lang.org/stable/core/primitive.slice.html#method.split_first_chunk_mut) +- [`<[_]>::split_last_chunk_mut`](https://doc.rust-lang.org/stable/core/primitive.slice.html#method.split_last_chunk_mut) +- [`str::as_bytes_mut`](https://doc.rust-lang.org/stable/core/primitive.str.html#method.as_bytes_mut) +- [`str::as_mut_ptr`](https://doc.rust-lang.org/stable/core/primitive.str.html#method.as_mut_ptr) +- [`str::from_utf8_unchecked_mut`](https://doc.rust-lang.org/stable/core/str/fn.from_utf8_unchecked_mut.html) + + + + +Cargo +----- +- [Introduced a new `CARGO_MANIFEST_PATH` environment variable, similar to `CARGO_MANIFEST_DIR` but pointing directly to the manifest file.](https://github.com/rust-lang/cargo/pull/14404/) +- [Added `package.autolib` to the manifest, allowing `[lib]` auto-discovery to be disabled.](https://github.com/rust-lang/cargo/pull/14591/) +- [Declare support level for each crate in Cargo's Charter / crate docs.](https://github.com/rust-lang/cargo/pull/14600/) +- [Declare new Intentional Artifacts as 'small' changes.](https://github.com/rust-lang/cargo/pull/14599/) + + + + +Rustdoc +------- + +- [The sidebar / hamburger menu table of contents now includes the `# headers` from the main item's doc comment](https://github.com/rust-lang/rust/pull/120736). This is similar to a third-party feature provided by the rustdoc-search-enhancements browser extension. + + + + +Compatibility Notes +------------------- +- [Warn against function pointers using unsupported ABI strings.](https://github.com/rust-lang/rust/pull/128784) +- [Check well-formedness of the source type's signature in fn pointer casts.](https://github.com/rust-lang/rust/pull/129021) This partly closes a soundness hole that comes when casting a function item to function pointer +- [Use equality instead of subtyping when resolving type dependent paths.](https://github.com/rust-lang/rust/pull/129073) +- Linking on macOS now correctly includes Rust's default deployment target. Due to a linker bug, you might have to pass `MACOSX_DEPLOYMENT_TARGET` or fix your `#[link]` attributes to point to the correct frameworks. See . +- [Rust will now correctly raise an error for `repr(Rust)` written on non-`struct`/`enum`/`union` items, since it previous did not have any effect.](https://github.com/rust-lang/rust/pull/129422) +- The future incompatibility lint `deprecated_cfg_attr_crate_type_name` [has been made into a hard error](https://github.com/rust-lang/rust/pull/129670). It was used to deny usage of `#![crate_type]` and `#![crate_name]` attributes in `#![cfg_attr]`, which required a hack in the compiler to be able to change the used crate type and crate name after cfg expansion. + Users can use `--crate-type` instead of `#![cfg_attr(..., crate_type = "...")]` and `--crate-name` instead of `#![cfg_attr(..., crate_name = "...")]` when running `rustc`/`cargo rustc` on the command line. + Use of those two attributes outside of `#![cfg_attr]` continue to be fully supported. +- Until now, paths into the sysroot were always prefixed with `/rustc/$hash` in diagnostics, codegen, backtrace, e.g. + ``` + thread 'main' panicked at 'hello world', map-panic.rs:2:50 + stack backtrace: + 0: std::panicking::begin_panic + at /rustc/a55dd71d5fb0ec5a6a3a9e8c27b2127ba491ce52/library/std/src/panicking.rs:616:12 + 1: map_panic::main::{{closure}} + at ./map-panic.rs:2:50 + 2: core::option::Option::map + at /rustc/a55dd71d5fb0ec5a6a3a9e8c27b2127ba491ce52/library/core/src/option.rs:929:29 + 3: map_panic::main + at ./map-panic.rs:2:30 + 4: core::ops::function::FnOnce::call_once + at /rustc/a55dd71d5fb0ec5a6a3a9e8c27b2127ba491ce52/library/core/src/ops/function.rs:248:5 + note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace. + ``` + [RFC 3127 said](https://rust-lang.github.io/rfcs/3127-trim-paths.html#changing-handling-of-sysroot-path-in-rustc) + > We want to change this behaviour such that, when `rust-src` source files can be discovered, the virtual path is discarded and therefore the local path will be embedded, unless there is a `--remap-path-prefix` that causes this local path to be remapped in the usual way. + + [#129687](https://github.com/rust-lang/rust/pull/129687) implements this behaviour, when `rust-src` is present at compile time, `rustc` replaces `/rustc/$hash` with a real path into the local `rust-src` component with best effort. + To sanitize this, users must explicitly supply `--remap-path-prefix==foo` or not have the `rust-src` component installed. + - The allow-by-default `missing_docs` lint used to disable itself when invoked through `rustc --test`/`cargo test`, resulting in `#[expect(missing_docs)]` emitting false positives due to the expectation being wrongly unfulfilled. This behavior [has now been removed](https://github.com/rust-lang/rust/pull/130025), which allows `#[expect(missing_docs)]` to be fulfilled in all scenarios, but will also report new `missing_docs` diagnostics for publicly reachable `#[cfg(test)]` items, [integration test](https://doc.rust-lang.org/cargo/reference/cargo-targets.html#integration-tests) crate-level documentation, and publicly reachable items in integration tests. +- [The `armv8r-none-eabihf` target now uses the Armv8-R required set of floating-point features.](https://github.com/rust-lang/rust/pull/130295) +- [Fix a soundness bug where rustc wouldn't detect unconstrained higher-ranked lifetimes in a `dyn Trait`'s associated types that occur due to supertraits.](https://github.com/rust-lang/rust/pull/130367) +- [Update the minimum external LLVM version to 18.](https://github.com/rust-lang/rust/pull/130487) +- [Remove `aarch64-fuchsia` and `x86_64-fuchsia` target aliases in favor of `aarch64-unknown-fuchsia` and `x86_64-unknown-fuchsia` respectively.](https://github.com/rust-lang/rust/pull/130657) +- [The ABI-level exception class of a Rust panic is now encoded with native-endian bytes, so it is legible in hex dumps.](https://github.com/rust-lang/rust/pull/130897) +- [Visual Studio 2013 is no longer supported for MSVC targets.](https://github.com/rust-lang/rust/pull/131070) +- [The sysroot no longer contains the `std` dynamic library in its top-level `lib/` dir.](https://github.com/rust-lang/rust/pull/131188) + + Version 1.82.0 (2024-10-17) ========================== @@ -125,7 +357,7 @@ These APIs are now stable in const contexts: - [`std::task::Waker::from_raw`](https://doc.rust-lang.org/nightly/std/task/struct.Waker.html#method.from_raw) - [`std::task::Context::from_waker`](https://doc.rust-lang.org/nightly/std/task/struct.Context.html#method.from_waker) - [`std::task::Context::waker`](https://doc.rust-lang.org/nightly/std/task/struct.Context.html#method.waker) -- [`$integer::from_str_radix`](https://doc.rust-lang.org/nightly/std/primitive.u32.html#method.from_str_radix) +- [`{integer}::from_str_radix`](https://doc.rust-lang.org/nightly/std/primitive.u32.html#method.from_str_radix) - [`std::num::ParseIntError::kind`](https://doc.rust-lang.org/nightly/std/num/struct.ParseIntError.html#method.kind) diff --git a/compiler/rustc_borrowck/src/type_check/canonical.rs b/compiler/rustc_borrowck/src/type_check/canonical.rs index 68b843d4d0d7a..585d0eabf5b97 100644 --- a/compiler/rustc_borrowck/src/type_check/canonical.rs +++ b/compiler/rustc_borrowck/src/type_check/canonical.rs @@ -7,6 +7,7 @@ use rustc_middle::mir::ConstraintCategory; use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, Upcast}; use rustc_span::Span; use rustc_span::def_id::DefId; +use rustc_trait_selection::solve::NoSolution; use rustc_trait_selection::traits::ObligationCause; use rustc_trait_selection::traits::query::type_op::custom::CustomTypeOp; use rustc_trait_selection::traits::query::type_op::{self, TypeOpOutput}; @@ -177,6 +178,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { if self.infcx.next_trait_solver() { let body = self.body; let param_env = self.infcx.param_env; + // FIXME: Make this into a real type op? self.fully_perform_op( location.to_locations(), ConstraintCategory::Boring, @@ -213,6 +215,40 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } } + #[instrument(skip(self), level = "debug")] + pub(super) fn structurally_resolve( + &mut self, + ty: Ty<'tcx>, + location: impl NormalizeLocation, + ) -> Ty<'tcx> { + if self.infcx.next_trait_solver() { + let body = self.body; + let param_env = self.infcx.param_env; + // FIXME: Make this into a real type op? + self.fully_perform_op( + location.to_locations(), + ConstraintCategory::Boring, + CustomTypeOp::new( + |ocx| { + ocx.structurally_normalize( + &ObligationCause::misc( + location.to_locations().span(body), + body.source.def_id().expect_local(), + ), + param_env, + ty, + ) + .map_err(|_| NoSolution) + }, + "normalizing struct tail", + ), + ) + .unwrap_or_else(|guar| Ty::new_error(self.tcx(), guar)) + } else { + self.normalize(ty, location) + } + } + #[instrument(skip(self), level = "debug")] pub(super) fn ascribe_user_type( &mut self, diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 3a7ed711f681e..b4763acbefa0a 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -1064,7 +1064,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { let tcx = self.infcx.tcx; for proj in &user_ty.projs { - if let ty::Alias(ty::Opaque, ..) = curr_projected_ty.ty.kind() { + if !self.infcx.next_trait_solver() + && let ty::Alias(ty::Opaque, ..) = curr_projected_ty.ty.kind() + { // There is nothing that we can compare here if we go through an opaque type. // We're always in its defining scope as we can otherwise not project through // it, so we're constraining it anyways. @@ -1075,7 +1077,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { proj, |this, field, ()| { let ty = this.field_ty(tcx, field); - self.normalize(ty, locations) + self.structurally_resolve(ty, locations) }, |_, _| unreachable!(), ); diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index 2891b48a154cc..06dee6bda5409 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -523,8 +523,9 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( let impl_sig = ocx.normalize( &misc_cause, param_env, - tcx.liberate_late_bound_regions( - impl_m.def_id, + infcx.instantiate_binder_with_fresh_vars( + return_span, + infer::HigherRankedType, tcx.fn_sig(impl_m.def_id).instantiate_identity(), ), ); @@ -536,10 +537,9 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( // them with inference variables. // We will use these inference variables to collect the hidden types of RPITITs. let mut collector = ImplTraitInTraitCollector::new(&ocx, return_span, param_env, impl_m_def_id); - let unnormalized_trait_sig = infcx - .instantiate_binder_with_fresh_vars( - return_span, - infer::HigherRankedType, + let unnormalized_trait_sig = tcx + .liberate_late_bound_regions( + impl_m.def_id, tcx.fn_sig(trait_m.def_id).instantiate(tcx, trait_to_impl_args), ) .fold_with(&mut collector); @@ -702,8 +702,8 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( let mut remapped_types = DefIdMap::default(); for (def_id, (ty, args)) in collected_types { - match infcx.fully_resolve((ty, args)) { - Ok((ty, args)) => { + match infcx.fully_resolve(ty) { + Ok(ty) => { // `ty` contains free regions that we created earlier while liberating the // trait fn signature. However, projection normalization expects `ty` to // contains `def_id`'s early-bound regions. @@ -883,33 +883,27 @@ impl<'tcx> ty::FallibleTypeFolder> for RemapHiddenTyRegions<'tcx> { self.tcx } - fn try_fold_ty(&mut self, t: Ty<'tcx>) -> Result, Self::Error> { - if let ty::Alias(ty::Opaque, ty::AliasTy { args, def_id, .. }) = *t.kind() { - let mut mapped_args = Vec::with_capacity(args.len()); - for (arg, v) in std::iter::zip(args, self.tcx.variances_of(def_id)) { - mapped_args.push(match (arg.unpack(), v) { - // Skip uncaptured opaque args - (ty::GenericArgKind::Lifetime(_), ty::Bivariant) => arg, - _ => arg.try_fold_with(self)?, - }); - } - Ok(Ty::new_opaque(self.tcx, def_id, self.tcx.mk_args(&mapped_args))) - } else { - t.try_super_fold_with(self) - } - } - fn try_fold_region( &mut self, region: ty::Region<'tcx>, ) -> Result, Self::Error> { match region.kind() { - // Remap late-bound regions from the function. + // Never remap bound regions or `'static` + ty::ReBound(..) | ty::ReStatic | ty::ReError(_) => return Ok(region), + // We always remap liberated late-bound regions from the function. ty::ReLateParam(_) => {} // Remap early-bound regions as long as they don't come from the `impl` itself, // in which case we don't really need to renumber them. - ty::ReEarlyParam(ebr) if ebr.index as usize >= self.num_impl_args => {} - _ => return Ok(region), + ty::ReEarlyParam(ebr) => { + if ebr.index as usize >= self.num_impl_args { + // Remap + } else { + return Ok(region); + } + } + ty::ReVar(_) | ty::RePlaceholder(_) | ty::ReErased => unreachable!( + "should not have leaked vars or placeholders into hidden type of RPITIT" + ), } let e = if let Some(id_region) = self.map.get(®ion) { diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index 640729576fcc6..5aaad3636a2a3 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -1642,6 +1642,28 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { } } + // FIXME(-Znext-solver): See the linked issue below. + // + // + // In the new solver, check the well-formedness of the return type. + // This emulates, in a way, the predicates that fall out of + // normalizing the return type in the old solver. + // + // We alternatively could check the predicates of the method itself hold, + // but we intentionally do not do this in the old solver b/c of cycles, + // and doing it in the new solver would be stronger. This should be fixed + // in the future, since it likely leads to much better method winnowing. + if let Some(xform_ret_ty) = xform_ret_ty + && self.infcx.next_trait_solver() + { + ocx.register_obligation(traits::Obligation::new( + self.tcx, + cause.clone(), + self.param_env, + ty::ClauseKind::WellFormed(xform_ret_ty.into()), + )); + } + // Evaluate those obligations to see if they might possibly hold. for error in ocx.select_where_possible() { result = ProbeResult::NoMatch; diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs index a9ca5dbe50941..a5826137181db 100644 --- a/compiler/rustc_span/src/hygiene.rs +++ b/compiler/rustc_span/src/hygiene.rs @@ -26,6 +26,7 @@ use std::cell::RefCell; use std::collections::hash_map::Entry; +use std::collections::hash_set::Entry as SetEntry; use std::fmt; use std::hash::Hash; @@ -1270,7 +1271,7 @@ pub struct HygieneDecodeContext { inner: Lock, /// A set of serialized `SyntaxContext` ids that are currently being decoded on each thread. - local_in_progress: WorkerLocal>>, + local_in_progress: WorkerLocal>>, } /// Register an expansion which has been decoded from the on-disk-cache for the local crate. @@ -1364,14 +1365,14 @@ pub fn decode_syntax_context SyntaxContext match inner.decoding.entry(raw_id) { Entry::Occupied(ctxt_entry) => { match context.local_in_progress.borrow_mut().entry(raw_id) { - Entry::Occupied(..) => { + SetEntry::Occupied(..) => { // We're decoding this already on the current thread. Return here // and let the function higher up the stack finish decoding to handle // recursive cases. return *ctxt_entry.get(); } - Entry::Vacant(entry) => { - entry.insert(()); + SetEntry::Vacant(entry) => { + entry.insert(); // Some other thread is current decoding this. Race with it. *ctxt_entry.get() @@ -1380,7 +1381,7 @@ pub fn decode_syntax_context SyntaxContext } Entry::Vacant(entry) => { // We are the first thread to start decoding. Mark the current thread as being progress. - context.local_in_progress.borrow_mut().insert(raw_id, ()); + context.local_in_progress.borrow_mut().insert(raw_id); // Allocate and store SyntaxContext id *before* calling the decoder function, // as the SyntaxContextData may reference itself. diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index 1481e1cbd918a..57c645bfaba56 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -22,6 +22,7 @@ #![feature(array_windows)] #![feature(cfg_match)] #![feature(core_io_borrowed_buf)] +#![feature(hash_set_entry)] #![feature(if_let_guard)] #![feature(let_chains)] #![feature(min_specialization)] diff --git a/compiler/rustc_traits/src/codegen.rs b/compiler/rustc_traits/src/codegen.rs index 57225df0819d8..e5276e6d51585 100644 --- a/compiler/rustc_traits/src/codegen.rs +++ b/compiler/rustc_traits/src/codegen.rs @@ -74,12 +74,21 @@ pub(crate) fn codegen_select_candidate<'tcx>( } let impl_source = infcx.resolve_vars_if_possible(impl_source); - let impl_source = infcx.tcx.erase_regions(impl_source); - if impl_source.has_infer() { - // Unused lifetimes on an impl get replaced with inference vars, but never resolved, - // causing the return value of a query to contain inference vars. We do not have a concept - // for this and will in fact ICE in stable hashing of the return value. So bail out instead. - infcx.tcx.dcx().has_errors().unwrap(); + let impl_source = tcx.erase_regions(impl_source); + if impl_source.has_non_region_infer() { + // Unused generic types or consts on an impl get replaced with inference vars, + // but never resolved, causing the return value of a query to contain inference + // vars. We do not have a concept for this and will in fact ICE in stable hashing + // of the return value. So bail out instead. + match impl_source { + ImplSource::UserDefined(impl_) => { + tcx.dcx().span_delayed_bug( + tcx.def_span(impl_.impl_def_id), + "this impl has unconstrained generic parameters", + ); + } + _ => unreachable!(), + } return Err(CodegenObligationError::FulfillmentError); } diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs index 67fbda34bb935..95c1eb460cd94 100644 --- a/library/core/src/array/mod.rs +++ b/library/core/src/array/mod.rs @@ -214,8 +214,8 @@ impl BorrowMut<[T]> for [T; N] { } } -/// Tries to create an array `[T; N]` by copying from a slice `&[T]`. Succeeds if -/// `slice.len() == N`. +/// Tries to create an array `[T; N]` by copying from a slice `&[T]`. +/// Succeeds if `slice.len() == N`. /// /// ``` /// let bytes: [u8; 3] = [1, 0, 2]; @@ -282,13 +282,7 @@ impl<'a, T, const N: usize> TryFrom<&'a [T]> for &'a [T; N] { #[inline] fn try_from(slice: &'a [T]) -> Result<&'a [T; N], TryFromSliceError> { - if slice.len() == N { - let ptr = slice.as_ptr() as *const [T; N]; - // SAFETY: ok because we just checked that the length fits - unsafe { Ok(&*ptr) } - } else { - Err(TryFromSliceError(())) - } + slice.as_array().ok_or(TryFromSliceError(())) } } @@ -310,13 +304,7 @@ impl<'a, T, const N: usize> TryFrom<&'a mut [T]> for &'a mut [T; N] { #[inline] fn try_from(slice: &'a mut [T]) -> Result<&'a mut [T; N], TryFromSliceError> { - if slice.len() == N { - let ptr = slice.as_mut_ptr() as *mut [T; N]; - // SAFETY: ok because we just checked that the length fits - unsafe { Ok(&mut *ptr) } - } else { - Err(TryFromSliceError(())) - } + slice.as_mut_array().ok_or(TryFromSliceError(())) } } diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index a178d10125477..1089d415eca94 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -144,6 +144,7 @@ #![feature(ptr_alignment_type)] #![feature(ptr_metadata)] #![feature(set_ptr_value)] +#![feature(slice_as_array)] #![feature(slice_as_chunks)] #![feature(slice_ptr_get)] #![feature(str_internals)] diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index 0dbe819acb1b9..27516789f867c 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -1526,6 +1526,22 @@ impl *const [T] { self as *const T } + /// Gets a raw pointer to the underlying array. + /// + /// If `N` is not exactly equal to the length of `self`, then this method returns `None`. + #[unstable(feature = "slice_as_array", issue = "133508")] + #[rustc_const_unstable(feature = "slice_as_array", issue = "133508")] + #[inline] + #[must_use] + pub const fn as_array(self) -> Option<*const [T; N]> { + if self.len() == N { + let me = self.as_ptr() as *const [T; N]; + Some(me) + } else { + None + } + } + /// Returns a raw pointer to an element or subslice, without doing bounds /// checking. /// diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index f0204bd0f773d..e637edd745918 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -1760,6 +1760,22 @@ impl *mut [T] { self.len() == 0 } + /// Gets a raw, mutable pointer to the underlying array. + /// + /// If `N` is not exactly equal to the length of `self`, then this method returns `None`. + #[unstable(feature = "slice_as_array", issue = "133508")] + #[rustc_const_unstable(feature = "slice_as_array", issue = "133508")] + #[inline] + #[must_use] + pub const fn as_mut_array(self) -> Option<*mut [T; N]> { + if self.len() == N { + let me = self.as_mut_ptr() as *mut [T; N]; + Some(me) + } else { + None + } + } + /// Divides one mutable raw slice into two at an index. /// /// The first will contain all indices from `[0, mid)` (excluding diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index b3defba5a9823..ee91479bb1a9d 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -855,6 +855,44 @@ impl [T] { start..end } + /// Gets a reference to the underlying array. + /// + /// If `N` is not exactly equal to slice's the length of `self`, then this method returns `None`. + #[unstable(feature = "slice_as_array", issue = "133508")] + #[rustc_const_unstable(feature = "slice_as_array", issue = "133508")] + #[inline] + #[must_use] + pub const fn as_array(&self) -> Option<&[T; N]> { + if self.len() == N { + let ptr = self.as_ptr() as *const [T; N]; + + // SAFETY: The underlying array of a slice can be reinterpreted as an actual array `[T; N]` if `N` is not greater than the slice's length. + let me = unsafe { &*ptr }; + Some(me) + } else { + None + } + } + + /// Gets a mutable reference to the slice's underlying array. + /// + /// If `N` is not exactly equal to the length of `self`, then this method returns `None`. + #[unstable(feature = "slice_as_array", issue = "133508")] + #[rustc_const_unstable(feature = "slice_as_array", issue = "133508")] + #[inline] + #[must_use] + pub const fn as_mut_array(&mut self) -> Option<&mut [T; N]> { + if self.len() == N { + let ptr = self.as_mut_ptr() as *mut [T; N]; + + // SAFETY: The underlying array of a slice can be reinterpreted as an actual array `[T; N]` if `N` is not greater than the slice's length. + let me = unsafe { &mut *ptr }; + Some(me) + } else { + None + } + } + /// Swaps two elements in the slice. /// /// If `a` equals to `b`, it's guaranteed that elements won't change value. diff --git a/library/std/src/os/unix/fs.rs b/library/std/src/os/unix/fs.rs index ba6481f052cdf..04a45fd035a55 100644 --- a/library/std/src/os/unix/fs.rs +++ b/library/std/src/os/unix/fs.rs @@ -987,6 +987,11 @@ impl DirBuilderExt for fs::DirBuilder { /// Changing the group typically requires either being the owner and a member of the group, or /// having privileges. /// +/// Be aware that changing owner clears the `suid` and `sgid` permission bits in most cases +/// according to POSIX, usually even if the user is root. The sgid is not cleared when +/// the file is non-group-executable. See: +/// This call may also clear file capabilities, if there was any. +/// /// If called on a symbolic link, this will change the owner and group of the link target. To /// change the owner and group of the link itself, see [`lchown`]. /// diff --git a/library/std/src/sys/cmath.rs b/library/std/src/sys/cmath.rs index 2997e908fa1b2..ee36127cfdf1e 100644 --- a/library/std/src/sys/cmath.rs +++ b/library/std/src/sys/cmath.rs @@ -26,6 +26,7 @@ extern "C" { pub fn tgamma(n: f64) -> f64; pub fn tgammaf(n: f32) -> f32; pub fn lgamma_r(n: f64, s: &mut i32) -> f64; + #[cfg(not(target_os = "aix"))] pub fn lgammaf_r(n: f32, s: &mut i32) -> f32; pub fn acosf128(n: f128) -> f128; @@ -56,6 +57,13 @@ extern "C" { }} } +// On AIX, we don't have lgammaf_r only the f64 version, so we can +// use the f64 version lgamma_r +#[cfg(target_os = "aix")] +pub unsafe fn lgammaf_r(n: f32, s: &mut i32) -> f32 { + lgamma_r(n.into(), s) as f32 +} + // On 32-bit x86 MSVC these functions aren't defined, so we just define shims // which promote everything to f64, perform the calculation, and then demote // back to f32. While not precisely correct should be "correct enough" for now. diff --git a/src/bootstrap/src/core/builder/mod.rs b/src/bootstrap/src/core/builder/mod.rs index e6902bb8cee5f..945a7b7366f4d 100644 --- a/src/bootstrap/src/core/builder/mod.rs +++ b/src/bootstrap/src/core/builder/mod.rs @@ -1523,15 +1523,19 @@ impl<'a> Builder<'a> { pub(crate) fn maybe_open_in_browser(&self, path: impl AsRef) { if self.was_invoked_explicitly::(Kind::Doc) { self.open_in_browser(path); + } else { + self.info(&format!("Doc path: {}", path.as_ref().display())); } } pub(crate) fn open_in_browser(&self, path: impl AsRef) { + let path = path.as_ref(); + if self.config.dry_run() || !self.config.cmd.open() { + self.info(&format!("Doc path: {}", path.display())); return; } - let path = path.as_ref(); self.info(&format!("Opening doc {}", path.display())); if let Err(err) = opener::open(path) { self.info(&format!("{err}\n")); diff --git a/src/librustdoc/clean/cfg.rs b/src/librustdoc/clean/cfg.rs index 9255242611afc..0dfb8a52ebabd 100644 --- a/src/librustdoc/clean/cfg.rs +++ b/src/librustdoc/clean/cfg.rs @@ -391,7 +391,7 @@ fn write_with_opt_paren( Ok(()) } -impl<'a> fmt::Display for Display<'a> { +impl fmt::Display for Display<'_> { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { match *self.0 { Cfg::Not(ref child) => match **child { diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 5ddd6188c2d86..d81c47886d2d5 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -367,7 +367,7 @@ pub(crate) fn build_impls( let tcx = cx.tcx; // for each implementation of an item represented by `did`, build the clean::Item for that impl - for &did in tcx.inherent_impls(did).into_iter() { + for &did in tcx.inherent_impls(did).iter() { cx.with_param_env(did, |cx| { build_impl(cx, did, attrs, ret); }); @@ -382,7 +382,7 @@ pub(crate) fn build_impls( if tcx.has_attr(did, sym::rustc_has_incoherent_inherent_impls) { let type_ = if tcx.is_trait(did) { SimplifiedType::Trait(did) } else { SimplifiedType::Adt(did) }; - for &did in tcx.incoherent_impls(type_).into_iter() { + for &did in tcx.incoherent_impls(type_).iter() { cx.with_param_env(did, |cx| { build_impl(cx, did, attrs, ret); }); diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 97a2c33101261..093f216accbe4 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2509,16 +2509,14 @@ fn clean_generic_args<'tcx>( let args = generic_args .args .iter() - .filter_map(|arg| { - Some(match arg { - hir::GenericArg::Lifetime(lt) if !lt.is_anonymous() => { - GenericArg::Lifetime(clean_lifetime(lt, cx)) - } - hir::GenericArg::Lifetime(_) => GenericArg::Lifetime(Lifetime::elided()), - hir::GenericArg::Type(ty) => GenericArg::Type(clean_ty(ty, cx)), - hir::GenericArg::Const(ct) => GenericArg::Const(Box::new(clean_const(ct, cx))), - hir::GenericArg::Infer(_inf) => GenericArg::Infer, - }) + .map(|arg| match arg { + hir::GenericArg::Lifetime(lt) if !lt.is_anonymous() => { + GenericArg::Lifetime(clean_lifetime(lt, cx)) + } + hir::GenericArg::Lifetime(_) => GenericArg::Lifetime(Lifetime::elided()), + hir::GenericArg::Type(ty) => GenericArg::Type(clean_ty(ty, cx)), + hir::GenericArg::Const(ct) => GenericArg::Const(Box::new(clean_const(ct, cx))), + hir::GenericArg::Infer(_inf) => GenericArg::Infer, }) .collect::>() .into(); diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index a10a6a92bf57e..01d2661f73ede 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -264,17 +264,19 @@ impl ExternalCrate { // rendering by delegating everything to a hash map. let as_primitive = |res: Res| { let Res::Def(DefKind::Mod, def_id) = res else { return None }; - tcx.get_attrs(def_id, sym::rustc_doc_primitive).find_map(|attr| { - let attr_value = attr.value_str().expect("syntax should already be validated"); - let Some(prim) = PrimitiveType::from_symbol(attr_value) else { - span_bug!( - attr.span, - "primitive `{attr_value}` is not a member of `PrimitiveType`" - ); - }; + tcx.get_attrs(def_id, sym::rustc_doc_primitive) + .map(|attr| { + let attr_value = attr.value_str().expect("syntax should already be validated"); + let Some(prim) = PrimitiveType::from_symbol(attr_value) else { + span_bug!( + attr.span, + "primitive `{attr_value}` is not a member of `PrimitiveType`" + ); + }; - Some((def_id, prim)) - }) + (def_id, prim) + }) + .next() }; if root.is_local() { @@ -339,7 +341,7 @@ pub(crate) struct ItemInner { impl std::ops::Deref for Item { type Target = ItemInner; fn deref(&self) -> &ItemInner { - &*self.inner + &self.inner } } @@ -412,7 +414,7 @@ impl Item { pub(crate) fn span(&self, tcx: TyCtxt<'_>) -> Option { let kind = match &self.kind { - ItemKind::StrippedItem(k) => &*k, + ItemKind::StrippedItem(k) => k, _ => &self.kind, }; match kind { @@ -1870,7 +1872,7 @@ impl PrimitiveType { .get(self) .into_iter() .flatten() - .flat_map(move |&simp| tcx.incoherent_impls(simp).into_iter()) + .flat_map(move |&simp| tcx.incoherent_impls(simp).iter()) .copied() } @@ -1878,7 +1880,7 @@ impl PrimitiveType { Self::simplified_types() .values() .flatten() - .flat_map(move |&simp| tcx.incoherent_impls(simp).into_iter()) + .flat_map(move |&simp| tcx.incoherent_impls(simp).iter()) .copied() } diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index 5071ed1c47faa..34c91e33db700 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -178,7 +178,7 @@ impl fmt::Debug for Options { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { struct FmtExterns<'a>(&'a Externs); - impl<'a> fmt::Debug for FmtExterns<'a> { + impl fmt::Debug for FmtExterns<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_map().entries(self.0.iter()).finish() } @@ -508,7 +508,7 @@ impl Options { }; let parts_out_dir = - match matches.opt_str("parts-out-dir").map(|p| PathToParts::from_flag(p)).transpose() { + match matches.opt_str("parts-out-dir").map(PathToParts::from_flag).transpose() { Ok(parts_out_dir) => parts_out_dir, Err(e) => dcx.fatal(e), }; diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index 25e576e9e63aa..da1316a19cc33 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -700,7 +700,7 @@ impl IndividualTestOptions { fn new(options: &RustdocOptions, test_id: &Option, test_path: PathBuf) -> Self { let outdir = if let Some(ref path) = options.persist_doctests { let mut path = path.clone(); - path.push(&test_id.as_deref().unwrap_or("")); + path.push(test_id.as_deref().unwrap_or("")); if let Err(err) = std::fs::create_dir_all(&path) { eprintln!("Couldn't create directory for doctest executables: {err}"); diff --git a/src/librustdoc/doctest/rust.rs b/src/librustdoc/doctest/rust.rs index 27d0be133fea8..dc68f48f635b3 100644 --- a/src/librustdoc/doctest/rust.rs +++ b/src/librustdoc/doctest/rust.rs @@ -88,7 +88,7 @@ impl<'tcx> HirCollector<'tcx> { } } -impl<'tcx> HirCollector<'tcx> { +impl HirCollector<'_> { fn visit_testable( &mut self, name: String, diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs index ff0d537b19f75..e387eb010bebd 100644 --- a/src/librustdoc/formats/cache.rs +++ b/src/librustdoc/formats/cache.rs @@ -203,7 +203,7 @@ impl Cache { } } -impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> { +impl DocFolder for CacheBuilder<'_, '_> { fn fold_item(&mut self, item: clean::Item) -> Option { if item.item_id.is_local() { debug!( diff --git a/src/librustdoc/html/escape.rs b/src/librustdoc/html/escape.rs index 31a2701f06a54..48771571f8ff4 100644 --- a/src/librustdoc/html/escape.rs +++ b/src/librustdoc/html/escape.rs @@ -11,7 +11,7 @@ use unicode_segmentation::UnicodeSegmentation; /// string when passed to a format string. pub(crate) struct Escape<'a>(pub &'a str); -impl<'a> fmt::Display for Escape<'a> { +impl fmt::Display for Escape<'_> { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { // Because the internet is always right, turns out there's not that many // characters to escape: http://stackoverflow.com/questions/7381974 @@ -49,7 +49,7 @@ impl<'a> fmt::Display for Escape<'a> { /// difference, use [`Escape`]. pub(crate) struct EscapeBodyText<'a>(pub &'a str); -impl<'a> fmt::Display for EscapeBodyText<'a> { +impl fmt::Display for EscapeBodyText<'_> { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { // Because the internet is always right, turns out there's not that many // characters to escape: http://stackoverflow.com/questions/7381974 @@ -86,7 +86,7 @@ impl<'a> fmt::Display for EscapeBodyText<'a> { /// difference, use [`Escape`]. pub(crate) struct EscapeBodyTextWithWbr<'a>(pub &'a str); -impl<'a> fmt::Display for EscapeBodyTextWithWbr<'a> { +impl fmt::Display for EscapeBodyTextWithWbr<'_> { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { let EscapeBodyTextWithWbr(text) = *self; if text.len() < 8 { diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 46bc2915d0a3f..0a563b1df2620 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -9,6 +9,7 @@ use std::borrow::Cow; use std::cell::Cell; +use std::cmp::Ordering; use std::fmt::{self, Display, Write}; use std::iter::{self, once}; @@ -785,16 +786,20 @@ pub(crate) fn href_relative_parts<'fqp>( ); } } - // e.g. linking to std::sync::atomic from std::sync - if relative_to_fqp.len() < fqp.len() { - Box::new(fqp[relative_to_fqp.len()..fqp.len()].iter().copied()) - // e.g. linking to std::sync from std::sync::atomic - } else if fqp.len() < relative_to_fqp.len() { - let dissimilar_part_count = relative_to_fqp.len() - fqp.len(); - Box::new(iter::repeat(sym::dotdot).take(dissimilar_part_count)) - // linking to the same module - } else { - Box::new(iter::empty()) + match relative_to_fqp.len().cmp(&fqp.len()) { + Ordering::Less => { + // e.g. linking to std::sync::atomic from std::sync + Box::new(fqp[relative_to_fqp.len()..fqp.len()].iter().copied()) + } + Ordering::Greater => { + // e.g. linking to std::sync from std::sync::atomic + let dissimilar_part_count = relative_to_fqp.len() - fqp.len(); + Box::new(iter::repeat(sym::dotdot).take(dissimilar_part_count)) + } + Ordering::Equal => { + // linking to the same module + Box::new(iter::empty()) + } } } @@ -1384,7 +1389,7 @@ impl clean::Impl { write!(f, ">")?; } } else { - fmt_type(&type_, f, use_absolute, cx)?; + fmt_type(type_, f, use_absolute, cx)?; } Ok(()) } @@ -1531,14 +1536,14 @@ impl clean::FnDecl { (None, Some(last_i)) if i != last_i => write!(f, ", ")?, (None, Some(_)) => (), (Some(n), Some(last_i)) if i != last_i => write!(f, ",\n{}", Indent(n + 4))?, - (Some(_), Some(_)) => write!(f, ",\n")?, + (Some(_), Some(_)) => writeln!(f, ",")?, } } if self.c_variadic { match line_wrapping_indent { None => write!(f, ", ...")?, - Some(n) => write!(f, "{}...\n", Indent(n + 4))?, + Some(n) => writeln!(f, "{}...", Indent(n + 4))?, }; } diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs index b2fc1a47f78fb..48a537ad5e7ad 100644 --- a/src/librustdoc/html/highlight.rs +++ b/src/librustdoc/html/highlight.rs @@ -144,7 +144,7 @@ struct TokenHandler<'a, 'tcx, F: Write> { href_context: Option>, } -impl<'a, 'tcx, F: Write> TokenHandler<'a, 'tcx, F> { +impl TokenHandler<'_, '_, F> { fn handle_exit_span(&mut self) { // We can't get the last `closing_tags` element using `pop()` because `closing_tags` is // being used in `write_pending_elems`. @@ -207,7 +207,7 @@ impl<'a, 'tcx, F: Write> TokenHandler<'a, 'tcx, F> { } } -impl<'a, 'tcx, F: Write> Drop for TokenHandler<'a, 'tcx, F> { +impl Drop for TokenHandler<'_, '_, F> { /// When leaving, we need to flush all pending data to not have missing content. fn drop(&mut self) { if self.pending_exit_span.is_some() { @@ -1017,7 +1017,7 @@ fn string_without_closing_tag( .ok() .map(|(url, _, _)| url), LinkFromSrc::Doc(def_id) => { - format::href_with_root_path(*def_id, context, Some(&href_context.root_path)) + format::href_with_root_path(*def_id, context, Some(href_context.root_path)) .ok() .map(|(doc_link, _, _)| doc_link) } diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs index 31ccfeb38738c..b4bc0b80d6c66 100644 --- a/src/librustdoc/html/layout.rs +++ b/src/librustdoc/html/layout.rs @@ -33,7 +33,7 @@ pub(crate) struct Page<'a> { pub(crate) rust_logo: bool, } -impl<'a> Page<'a> { +impl Page<'_> { pub(crate) fn get_static_root_path(&self) -> String { match self.static_root_path { Some(s) => s.to_string(), diff --git a/src/librustdoc/html/length_limit.rs b/src/librustdoc/html/length_limit.rs index 8562e103dc17e..fdb1ddc1f5311 100644 --- a/src/librustdoc/html/length_limit.rs +++ b/src/librustdoc/html/length_limit.rs @@ -77,7 +77,7 @@ impl HtmlWithLimit { /// This function will panic if called with a non-alphabetic `tag_name`. pub(super) fn open_tag(&mut self, tag_name: &'static str) { assert!( - tag_name.chars().all(|c| ('a'..='z').contains(&c)), + tag_name.chars().all(|c: char| c.is_ascii_lowercase()), "tag_name contained non-alphabetic chars: {tag_name:?}", ); self.queued_tags.push(tag_name); @@ -85,16 +85,15 @@ impl HtmlWithLimit { /// Close the most recently opened HTML tag. pub(super) fn close_tag(&mut self) { - match self.unclosed_tags.pop() { + if let Some(tag_name) = self.unclosed_tags.pop() { // Close the most recently opened tag. - Some(tag_name) => write!(self.buf, "").unwrap(), - // There are valid cases where `close_tag()` is called without - // there being any tags to close. For example, this occurs when - // a tag is opened after the length limit is exceeded; - // `flush_queue()` will never be called, and thus, the tag will - // not end up being added to `unclosed_tags`. - None => {} + write!(self.buf, "").unwrap() } + // There are valid cases where `close_tag()` is called without + // there being any tags to close. For example, this occurs when + // a tag is opened after the length limit is exceeded; + // `flush_queue()` will never be called, and thus, the tag will + // not end up being added to `unclosed_tags`. } /// Write all queued tags and add them to the `unclosed_tags` list. diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index 1d42ec8eec7cb..b6829d5457ba7 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -499,7 +499,7 @@ struct HeadingLinks<'a, 'b, 'ids, I> { heading_offset: HeadingOffset, } -impl<'a, 'b, 'ids, I> HeadingLinks<'a, 'b, 'ids, I> { +impl<'b, 'ids, I> HeadingLinks<'_, 'b, 'ids, I> { fn new( iter: I, toc: Option<&'b mut TocBuilder>, @@ -510,9 +510,7 @@ impl<'a, 'b, 'ids, I> HeadingLinks<'a, 'b, 'ids, I> { } } -impl<'a, 'b, 'ids, I: Iterator>> Iterator - for HeadingLinks<'a, 'b, 'ids, I> -{ +impl<'a, I: Iterator>> Iterator for HeadingLinks<'a, '_, '_, I> { type Item = SpannedEvent<'a>; fn next(&mut self) -> Option { @@ -908,7 +906,7 @@ impl<'a, 'tcx> TagIterator<'a, 'tcx> { } fn parse_string(&mut self, start: usize) -> Option { - while let Some((pos, c)) = self.inner.next() { + for (pos, c) in self.inner.by_ref() { if c == '"' { return Some(Indices { start: start + 1, end: pos }); } @@ -1032,7 +1030,7 @@ impl<'a, 'tcx> TagIterator<'a, 'tcx> { /// Returns `false` if an error was emitted. fn skip_paren_block(&mut self) -> bool { - while let Some((_, c)) = self.inner.next() { + for (_, c) in self.inner.by_ref() { if c == ')' { return true; } @@ -1074,9 +1072,8 @@ impl<'a, 'tcx> TagIterator<'a, 'tcx> { return Some(LangStringToken::LangToken(&self.data[start..pos])); } return self.next(); - } else if pos == start && is_leading_char(c) { - continue; - } else if pos != start && is_bareword_char(c) { + } else if (pos == start && is_leading_char(c)) || (pos != start && is_bareword_char(c)) + { continue; } else { self.emit_error(format!("unexpected character `{c}`")); @@ -1088,7 +1085,7 @@ impl<'a, 'tcx> TagIterator<'a, 'tcx> { } } -impl<'a, 'tcx> Iterator for TagIterator<'a, 'tcx> { +impl<'a> Iterator for TagIterator<'a, '_> { type Item = LangStringToken<'a>; fn next(&mut self) -> Option { @@ -1324,7 +1321,7 @@ impl Markdown<'_> { let mut replacer = |broken_link: BrokenLink<'_>| { links .iter() - .find(|link| &*link.original_text == &*broken_link.reference) + .find(|link| *link.original_text == *broken_link.reference) .map(|link| (link.href.as_str().into(), link.tooltip.as_str().into())) }; @@ -1358,7 +1355,7 @@ impl MarkdownWithToc<'_> { let mut replacer = |broken_link: BrokenLink<'_>| { links .iter() - .find(|link| &*link.original_text == &*broken_link.reference) + .find(|link| *link.original_text == *broken_link.reference) .map(|link| (link.href.as_str().into(), link.tooltip.as_str().into())) }; @@ -1428,7 +1425,7 @@ impl MarkdownSummaryLine<'_> { let mut replacer = |broken_link: BrokenLink<'_>| { links .iter() - .find(|link| &*link.original_text == &*broken_link.reference) + .find(|link| *link.original_text == *broken_link.reference) .map(|link| (link.href.as_str().into(), link.tooltip.as_str().into())) }; @@ -1475,7 +1472,7 @@ fn markdown_summary_with_limit( let mut replacer = |broken_link: BrokenLink<'_>| { link_names .iter() - .find(|link| &*link.original_text == &*broken_link.reference) + .find(|link| *link.original_text == *broken_link.reference) .map(|link| (link.href.as_str().into(), link.tooltip.as_str().into())) }; @@ -1556,7 +1553,7 @@ pub(crate) fn plain_text_summary(md: &str, link_names: &[RenderedLink]) -> Strin let mut replacer = |broken_link: BrokenLink<'_>| { link_names .iter() - .find(|link| &*link.original_text == &*broken_link.reference) + .find(|link| *link.original_text == *broken_link.reference) .map(|link| (link.href.as_str().into(), link.tooltip.as_str().into())) }; @@ -1751,7 +1748,7 @@ pub(crate) fn markdown_links<'md, R>( }; let mut broken_link_callback = |link: BrokenLink<'md>| Some((link.reference, "".into())); - let mut event_iter = Parser::new_with_broken_link_callback( + let event_iter = Parser::new_with_broken_link_callback( md, main_body_opts(), Some(&mut broken_link_callback), @@ -1759,7 +1756,7 @@ pub(crate) fn markdown_links<'md, R>( .into_offset_iter(); let mut links = Vec::new(); - while let Some((event, span)) = event_iter.next() { + for (event, span) in event_iter { match event { Event::Start(Tag::Link { link_type, dest_url, .. }) if may_be_doc_link(link_type) => { let range = match link_type { @@ -1821,7 +1818,7 @@ pub(crate) fn rust_code_blocks(md: &str, extra_info: &ExtraInfo<'_>) -> Vec>> Footnotes<'a, 'b, I> { } } -impl<'a, 'b, I: Iterator>> Iterator for Footnotes<'a, 'b, I> { +impl<'a, I: Iterator>> Iterator for Footnotes<'a, '_, I> { type Item = SpannedEvent<'a>; fn next(&mut self) -> Option { diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs index 5f255c18ec6aa..3a8144621747c 100644 --- a/src/librustdoc/html/render/context.rs +++ b/src/librustdoc/html/render/context.rs @@ -200,7 +200,7 @@ impl<'tcx> Context<'tcx> { }; title.push_str(" - Rust"); let tyname = it.type_(); - let desc = plain_text_summary(&it.doc_value(), &it.link_names(&self.cache())); + let desc = plain_text_summary(&it.doc_value(), &it.link_names(self.cache())); let desc = if !desc.is_empty() { desc } else if it.is_crate() { @@ -739,7 +739,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { &shared.layout, &page, "", - scrape_examples_help(&*shared), + scrape_examples_help(&shared), &shared.style_files, ); shared.fs.write(scrape_examples_help_file, v)?; @@ -779,7 +779,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { self.render_redirect_pages = item.is_stripped(); } let item_name = item.name.unwrap(); - self.dst.push(&*item_name.as_str()); + self.dst.push(item_name.as_str()); self.current.push(item_name); info!("Recursing into {}", self.dst.display()); @@ -812,7 +812,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { unreachable!() }; let items = self.build_sidebar_items(module); - let js_dst = self.dst.join(&format!("sidebar-items{}.js", self.shared.resource_suffix)); + let js_dst = self.dst.join(format!("sidebar-items{}.js", self.shared.resource_suffix)); let v = format!("window.SIDEBAR_ITEMS = {};", serde_json::to_string(&items).unwrap()); self.shared.fs.write(js_dst, v)?; } diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index f11356b44d885..7c5048cd164b7 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -151,13 +151,13 @@ impl RenderType { string.push('{'); write_optional_id(self.id, string); string.push('{'); - for generic in &self.generics.as_deref().unwrap_or_default()[..] { + for generic in self.generics.as_deref().unwrap_or_default() { generic.write_to_string(string); } string.push('}'); if self.bindings.is_some() { string.push('{'); - for binding in &self.bindings.as_deref().unwrap_or_default()[..] { + for binding in self.bindings.as_deref().unwrap_or_default() { string.push('{'); binding.0.write_to_string(string); string.push('{'); @@ -1963,7 +1963,7 @@ fn render_impl( w, "
{}
", Markdown { - content: &*dox, + content: dox, links: &i.impl_item.links(cx), ids: &mut cx.id_map, error_codes: cx.shared.codes, @@ -2093,9 +2093,7 @@ pub(crate) fn small_url_encode(s: String) -> String { // and https://url.spec.whatwg.org/#urlencoded-parsing // and https://url.spec.whatwg.org/#url-code-points fn dont_escape(c: u8) -> bool { - (b'a' <= c && c <= b'z') - || (b'A' <= c && c <= b'Z') - || (b'0' <= c && c <= b'9') + c.is_ascii_alphanumeric() || c == b'-' || c == b'_' || c == b'.' @@ -2150,7 +2148,7 @@ pub(crate) fn small_url_encode(s: String) -> String { } } -fn get_id_for_impl<'tcx>(tcx: TyCtxt<'tcx>, impl_id: ItemId) -> String { +fn get_id_for_impl(tcx: TyCtxt<'_>, impl_id: ItemId) -> String { use rustc_middle::ty::print::with_forced_trimmed_paths; let (type_, trait_) = match impl_id { ItemId::Auto { trait_, for_ } => { @@ -2381,7 +2379,7 @@ fn collect_paths_for_type(first_ty: clean::Type, cache: &Cache) -> Vec { let fqp = cache.exact_paths.get(&did).or_else(get_extern); if let Some(path) = fqp { - out.push(join_with_double_colon(&path)); + out.push(join_with_double_colon(path)); } }; @@ -2462,8 +2460,8 @@ fn render_call_locations(mut w: W, cx: &mut Context<'_>, item: &c }; // Generate the HTML for a single example, being the title and code block - let write_example = |mut w: &mut W, (path, call_data): (&PathBuf, &CallData)| -> bool { - let contents = match fs::read_to_string(&path) { + let write_example = |w: &mut W, (path, call_data): (&PathBuf, &CallData)| -> bool { + let contents = match fs::read_to_string(path) { Ok(contents) => contents, Err(err) => { let span = item.span(tcx).map_or(DUMMY_SP, |span| span.inner()); @@ -2532,7 +2530,7 @@ fn render_call_locations(mut w: W, cx: &mut Context<'_>, item: &c decoration_info.insert("highlight", byte_ranges); sources::print_src( - &mut w, + w, contents_subset, file_span, cx, @@ -2581,7 +2579,7 @@ fn render_call_locations(mut w: W, cx: &mut Context<'_>, item: &c // An example may fail to write if its source can't be read for some reason, so this method // continues iterating until a write succeeds let write_and_skip_failure = |w: &mut W, it: &mut Peekable<_>| { - while let Some(example) = it.next() { + for example in it.by_ref() { if write_example(&mut *w, example) { break; } diff --git a/src/librustdoc/html/render/ordered_json.rs b/src/librustdoc/html/render/ordered_json.rs index 7abe40eef3bdb..d1dddfebc83a2 100644 --- a/src/librustdoc/html/render/ordered_json.rs +++ b/src/librustdoc/html/render/ordered_json.rs @@ -23,7 +23,7 @@ impl OrderedJson { pub(crate) fn array_sorted, I: IntoIterator>(items: I) -> Self { let items = items .into_iter() - .sorted_unstable_by(|a, b| a.borrow().cmp(&b.borrow())) + .sorted_unstable_by(|a, b| a.borrow().cmp(b.borrow())) .format_with(",", |item, f| f(item.borrow())); Self(format!("[{}]", items)) } diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index d247e90d298db..dc205252507c5 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -751,7 +751,7 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean: } if !required_methods.is_empty() { - write!(w, " // Required method{}\n", pluralize(required_methods.len())); + writeln!(w, " // Required method{}", pluralize(required_methods.len())); } for (pos, m) in required_methods.iter().enumerate() { render_assoc_item( @@ -773,7 +773,7 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean: } if !provided_methods.is_empty() { - write!(w, " // Provided method{}\n", pluralize(provided_methods.len())); + writeln!(w, " // Provided method{}", pluralize(provided_methods.len())); } for (pos, m) in provided_methods.iter().enumerate() { render_assoc_item( @@ -940,7 +940,7 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean: "Dyn Compatibility", "dyn-compatibility", None, - &format!( + format!( "

This trait is not \ dyn compatible.

\

In older versions of Rust, dyn compatibility was called \"object safety\", \ @@ -1225,14 +1225,14 @@ fn item_type_alias(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &c w, cx, Some(&t.generics), - &variants, + variants, variants_count, has_stripped_entries, *is_non_exhaustive, enum_def_id, ) }); - item_variants(w, cx, it, &variants, enum_def_id); + item_variants(w, cx, it, variants, enum_def_id); } clean::TypeAliasInnerType::Union { fields } => { wrap_item(w, |w| { @@ -1824,7 +1824,7 @@ fn item_constant( name = it.name.unwrap(), generics = generics.print(cx), typ = ty.print(cx), - where_clause = print_where_clause(&generics, cx, 0, Ending::NoNewline), + where_clause = print_where_clause(generics, cx, 0, Ending::NoNewline), ); // FIXME: The code below now prints @@ -2194,7 +2194,7 @@ fn render_union<'a, 'cx: 'a>( f.write_str(" ")?; } - write!(f, "{{\n")?; + writeln!(f, "{{")?; let count_fields = fields.iter().filter(|field| matches!(field.kind, clean::StructFieldItem(..))).count(); let toggle = should_hide_fields(count_fields); @@ -2204,9 +2204,9 @@ fn render_union<'a, 'cx: 'a>( for field in fields { if let clean::StructFieldItem(ref ty) = field.kind { - write!( + writeln!( f, - " {}{}: {},\n", + " {}{}: {},", visibility_print_with_space(field, cx), field.name.unwrap(), ty.print(cx) @@ -2215,7 +2215,7 @@ fn render_union<'a, 'cx: 'a>( } if it.has_stripped_entries().unwrap() { - write!(f, " /* private fields */\n")?; + writeln!(f, " /* private fields */")?; } if toggle { toggle_close(&mut f); @@ -2355,7 +2355,7 @@ fn document_non_exhaustive_header(item: &clean::Item) -> &str { if item.is_non_exhaustive() { " (Non-exhaustive)" } else { "" } } -fn document_non_exhaustive<'a>(item: &'a clean::Item) -> impl fmt::Display + 'a { +fn document_non_exhaustive(item: &clean::Item) -> impl fmt::Display + '_ { display_fn(|f| { if item.is_non_exhaustive() { write!( diff --git a/src/librustdoc/html/render/search_index.rs b/src/librustdoc/html/render/search_index.rs index f91fdfa1fb5f5..cfb62c3ca1640 100644 --- a/src/librustdoc/html/render/search_index.rs +++ b/src/librustdoc/html/render/search_index.rs @@ -55,10 +55,10 @@ pub(crate) struct SerializedSearchIndex { const DESC_INDEX_SHARD_LEN: usize = 128 * 1024; /// Builds the search index from the collected metadata -pub(crate) fn build_index<'tcx>( +pub(crate) fn build_index( krate: &clean::Crate, cache: &mut Cache, - tcx: TyCtxt<'tcx>, + tcx: TyCtxt<'_>, ) -> SerializedSearchIndex { // Maps from ID to position in the `crate_paths` array. let mut itemid_to_pathid = FxHashMap::default(); @@ -126,7 +126,7 @@ pub(crate) fn build_index<'tcx>( let mut lastpathid = 0isize; // First, on function signatures - let mut search_index = std::mem::replace(&mut cache.search_index, Vec::new()); + let mut search_index = std::mem::take(&mut cache.search_index); for item in search_index.iter_mut() { fn insert_into_map( map: &mut FxHashMap, @@ -194,7 +194,7 @@ pub(crate) fn build_index<'tcx>( { let exact_fqp = exact_paths .get(&defid) - .or_else(|| external_paths.get(&defid).map(|&(ref fqp, _)| fqp)) + .or_else(|| external_paths.get(&defid).map(|(fqp, _)| fqp)) // Re-exports only count if the name is exactly the same. // This is a size optimization, since it means we only need // to store the name once (and the path is re-used for everything @@ -298,7 +298,7 @@ pub(crate) fn build_index<'tcx>( true }); } - let Some(id) = ty.id.clone() else { + let Some(id) = ty.id else { assert!(ty.generics.is_some()); return; }; @@ -372,7 +372,7 @@ pub(crate) fn build_index<'tcx>( if let Some(&(ref fqp, short)) = paths.get(&defid) { let exact_fqp = exact_paths .get(&defid) - .or_else(|| external_paths.get(&defid).map(|&(ref fqp, _)| fqp)) + .or_else(|| external_paths.get(&defid).map(|(fqp, _)| fqp)) .filter(|exact_fqp| { exact_fqp.last() == Some(&item.name) && *exact_fqp != fqp }); @@ -397,7 +397,7 @@ pub(crate) fn build_index<'tcx>( // Their parent carries the exact fqp instead. let exact_fqp = exact_paths .get(&defid) - .or_else(|| external_paths.get(&defid).map(|&(ref fqp, _)| fqp)); + .or_else(|| external_paths.get(&defid).map(|(fqp, _)| fqp)); item.exact_path = exact_fqp.and_then(|fqp| { // Re-exports only count if the name is exactly the same. // This is a size optimization, since it means we only need @@ -426,7 +426,7 @@ pub(crate) fn build_index<'tcx>( } // Omit the parent path if it is same to that of the prior item. - if lastpath == &item.path { + if lastpath == item.path { item.path.clear(); } else { lastpath = &item.path; @@ -512,7 +512,7 @@ pub(crate) fn build_index<'tcx>( } } - impl<'a> Serialize for CrateData<'a> { + impl Serialize for CrateData<'_> { fn serialize(&self, serializer: S) -> Result where S: Serializer, @@ -640,7 +640,7 @@ pub(crate) fn build_index<'tcx>( let mut last_name = None; for (index, item) in self.items.iter().enumerate() { let n = item.ty as u8; - let c = char::try_from(n + b'A').expect("item types must fit in ASCII"); + let c = char::from(n + b'A'); assert!(c <= 'z', "item types must fit within ASCII printables"); types.push(c); @@ -741,22 +741,22 @@ pub(crate) fn build_index<'tcx>( let mut len: usize = 0; let mut item_index: u32 = 0; for desc in std::iter::once(&crate_doc).chain(crate_items.iter().map(|item| &item.desc)) { - if desc == "" { + if desc.is_empty() { empty_desc.push(item_index); item_index += 1; continue; } if set.len() >= DESC_INDEX_SHARD_LEN { - result.push((len, std::mem::replace(&mut set, String::new()))); + result.push((len, std::mem::take(&mut set))); len = 0; } else if len != 0 { set.push('\n'); } - set.push_str(&desc); + set.push_str(desc); len += 1; item_index += 1; } - result.push((len, std::mem::replace(&mut set, String::new()))); + result.push((len, std::mem::take(&mut set))); (empty_desc, result) }; @@ -792,9 +792,9 @@ pub(crate) fn build_index<'tcx>( SerializedSearchIndex { index, desc } } -pub(crate) fn get_function_type_for_search<'tcx>( +pub(crate) fn get_function_type_for_search( item: &clean::Item, - tcx: TyCtxt<'tcx>, + tcx: TyCtxt<'_>, impl_generics: Option<&(clean::Type, clean::Generics)>, parent: Option, cache: &Cache, @@ -861,7 +861,7 @@ fn get_index_type_id( match *clean_type { clean::Type::Path { ref path, .. } => Some(RenderTypeId::DefId(path.def_id())), clean::DynTrait(ref bounds, _) => { - bounds.get(0).map(|b| RenderTypeId::DefId(b.trait_.def_id())) + bounds.first().map(|b| RenderTypeId::DefId(b.trait_.def_id())) } clean::Primitive(p) => Some(RenderTypeId::Primitive(p)), clean::BorrowedRef { .. } => Some(RenderTypeId::Primitive(clean::PrimitiveType::Reference)), @@ -953,7 +953,7 @@ fn simplify_fn_type<'a, 'tcx>( WherePredicate::BoundPredicate { ty, .. } => *ty == *arg, _ => false, }) { - let bounds = where_pred.get_bounds().unwrap_or_else(|| &[]); + let bounds = where_pred.get_bounds().unwrap_or(&[]); for bound in bounds.iter() { if let Some(path) = bound.get_trait_path() { let ty = Type::Path { path }; @@ -1043,7 +1043,7 @@ fn simplify_fn_type<'a, 'tcx>( simplify_fn_type( self_, generics, - &ty, + ty, tcx, recurse + 1, &mut ty_generics, @@ -1058,7 +1058,7 @@ fn simplify_fn_type<'a, 'tcx>( simplify_fn_type( self_, generics, - &ty, + ty, tcx, recurse + 1, &mut ty_generics, @@ -1074,7 +1074,7 @@ fn simplify_fn_type<'a, 'tcx>( simplify_fn_type( self_, generics, - &ty, + ty, tcx, recurse + 1, &mut ty_generics, @@ -1117,7 +1117,7 @@ fn simplify_fn_type<'a, 'tcx>( ); let ty_bindings = vec![(RenderTypeId::AssociatedType(sym::Output), ty_output)]; res.push(RenderType { - id: get_index_type_id(&arg, rgen), + id: get_index_type_id(arg, rgen), bindings: Some(ty_bindings), generics: Some(ty_generics), }); @@ -1134,7 +1134,7 @@ fn simplify_fn_type<'a, 'tcx>( simplify_fn_type( self_, generics, - &type_, + type_, tcx, recurse + 1, &mut ty_generics, @@ -1249,7 +1249,7 @@ fn simplify_fn_type<'a, 'tcx>( } } } - let id = get_index_type_id(&arg, rgen); + let id = get_index_type_id(arg, rgen); if id.is_some() || !ty_generics.is_empty() { res.push(RenderType { id, @@ -1261,11 +1261,11 @@ fn simplify_fn_type<'a, 'tcx>( } } -fn simplify_fn_constraint<'a, 'tcx>( +fn simplify_fn_constraint<'a>( self_: Option<&'a Type>, generics: &Generics, constraint: &'a clean::AssocItemConstraint, - tcx: TyCtxt<'tcx>, + tcx: TyCtxt<'_>, recurse: usize, res: &mut Vec<(RenderTypeId, Vec)>, rgen: &mut FxIndexMap)>, @@ -1347,9 +1347,9 @@ fn simplify_fn_constraint<'a, 'tcx>( /// /// i.e. `fn foo>(x: u32, y: B)` will return /// `[u32, Display, Option]`. -fn get_fn_inputs_and_outputs<'tcx>( +fn get_fn_inputs_and_outputs( func: &Function, - tcx: TyCtxt<'tcx>, + tcx: TyCtxt<'_>, impl_or_trait_generics: Option<&(clean::Type, clean::Generics)>, cache: &Cache, ) -> (Vec, Vec, Vec, Vec>) { diff --git a/src/librustdoc/html/render/search_index/encode.rs b/src/librustdoc/html/render/search_index/encode.rs index 8d715814faad7..8816ea650593b 100644 --- a/src/librustdoc/html/render/search_index/encode.rs +++ b/src/librustdoc/html/render/search_index/encode.rs @@ -25,7 +25,7 @@ pub(crate) fn write_vlqhex_to_string(n: i32, string: &mut String) { break; } shift = shift.wrapping_sub(4); - mask = mask >> 4; + mask >>= 4; } // now write the rest while shift < 32 { @@ -33,7 +33,7 @@ pub(crate) fn write_vlqhex_to_string(n: i32, string: &mut String) { let hex = char::try_from(if shift == 0 { '`' } else { '@' } as u32 + hexit).unwrap(); string.push(hex); shift = shift.wrapping_sub(4); - mask = mask >> 4; + mask >>= 4; } } @@ -64,7 +64,7 @@ impl Container { Container::Array(array) => { array.push(value); if array.len() >= 4096 { - let array = std::mem::replace(array, Vec::new()); + let array = std::mem::take(array); *self = Container::Bits(Box::new([0; 1024])); for value in array { self.push(value); @@ -123,7 +123,7 @@ impl Container { if 2 + 4 * r >= 2 * array.len() + 2 { return false; } - let array = std::mem::replace(array, Vec::new()); + let array = std::mem::take(array); *self = Container::Run(Vec::new()); for value in array { self.push(value); @@ -145,7 +145,7 @@ pub(crate) fn write_bitmap_to_bytes( let mut keys = Vec::::new(); let mut containers = Vec::::new(); let mut key: u16; - let mut domain_iter = domain.into_iter().copied().peekable(); + let mut domain_iter = domain.iter().copied().peekable(); let mut has_run = false; while let Some(entry) = domain_iter.next() { key = (entry >> 16).try_into().expect("shifted off the top 16 bits, so it should fit"); @@ -236,7 +236,7 @@ pub(crate) fn write_bitmap_to_bytes( pub(crate) fn bitmap_to_string(domain: &[u32]) -> String { let mut buf = Vec::new(); let mut strbuf = String::new(); - write_bitmap_to_bytes(&domain, &mut buf).unwrap(); + write_bitmap_to_bytes(domain, &mut buf).unwrap(); BASE64_STANDARD.encode_string(&buf, &mut strbuf); strbuf } diff --git a/src/librustdoc/html/render/sidebar.rs b/src/librustdoc/html/render/sidebar.rs index 6df9486e65809..76de8d872311e 100644 --- a/src/librustdoc/html/render/sidebar.rs +++ b/src/librustdoc/html/render/sidebar.rs @@ -44,7 +44,7 @@ pub(super) struct Sidebar<'a> { pub(super) path: String, } -impl<'a> Sidebar<'a> { +impl Sidebar<'_> { /// Only create a `

` if there are any blocks /// which should actually be rendered. pub fn should_render_blocks(&self) -> bool { @@ -564,9 +564,9 @@ pub(crate) fn sidebar_module_like( .filter(|sec| item_sections_in_use.contains(sec)) .map(|sec| Link::new(ids.derive(sec.id()), sec.name())) .collect(); - let header = if let Some(first_section) = item_sections.get(0) { + let header = if let Some(first_section) = item_sections.first() { Link::new( - first_section.href.to_owned(), + first_section.href.clone(), if module_like.is_crate() { "Crate Items" } else { "Module Items" }, ) } else { diff --git a/src/librustdoc/html/render/sorted_template.rs b/src/librustdoc/html/render/sorted_template.rs index 28f7766d7c7ac..dc894840f92a0 100644 --- a/src/librustdoc/html/render/sorted_template.rs +++ b/src/librustdoc/html/render/sorted_template.rs @@ -84,7 +84,7 @@ impl FromStr for SortedTemplate { let offset = offset .strip_suffix(F::COMMENT_END) .ok_or(Error("last line expected to end with a comment"))?; - let offset: Offset = serde_json::from_str(&offset).map_err(|_| { + let offset: Offset = serde_json::from_str(offset).map_err(|_| { Error("could not find insertion location descriptor object on last line") })?; let (before, mut s) = diff --git a/src/librustdoc/html/render/span_map.rs b/src/librustdoc/html/render/span_map.rs index d4cca562d6c4a..81d79a6be9683 100644 --- a/src/librustdoc/html/render/span_map.rs +++ b/src/librustdoc/html/render/span_map.rs @@ -63,7 +63,7 @@ struct SpanMapVisitor<'tcx> { pub(crate) matches: FxHashMap, } -impl<'tcx> SpanMapVisitor<'tcx> { +impl SpanMapVisitor<'_> { /// This function is where we handle `hir::Path` elements and add them into the "span map". fn handle_path(&mut self, path: &rustc_hir::Path<'_>) { match path.res { diff --git a/src/librustdoc/html/render/write_shared.rs b/src/librustdoc/html/render/write_shared.rs index c82f7e9aaf927..7c676469597dc 100644 --- a/src/librustdoc/html/render/write_shared.rs +++ b/src/librustdoc/html/render/write_shared.rs @@ -68,8 +68,8 @@ pub(crate) fn write_shared( let _lock = try_err!(flock::Lock::new(&lock_file, true, true, true), &lock_file); let SerializedSearchIndex { index, desc } = - build_index(&krate, &mut Rc::get_mut(&mut cx.shared).unwrap().cache, tcx); - write_search_desc(cx, &krate, &desc)?; // does not need to be merged + build_index(krate, &mut Rc::get_mut(&mut cx.shared).unwrap().cache, tcx); + write_search_desc(cx, krate, &desc)?; // does not need to be merged let crate_name = krate.name(cx.tcx()); let crate_name = crate_name.as_str(); // rand @@ -80,7 +80,7 @@ pub(crate) fn write_shared( src_files_js: SourcesPart::get(cx, &crate_name_json)?, search_index_js: SearchIndexPart::get(index, &cx.shared.resource_suffix)?, all_crates: AllCratesPart::get(crate_name_json.clone(), &cx.shared.resource_suffix)?, - crates_index: CratesIndexPart::get(&crate_name, &external_crates)?, + crates_index: CratesIndexPart::get(crate_name, &external_crates)?, trait_impl: TraitAliasPart::get(cx, &crate_name_json)?, type_impl: TypeAliasPart::get(cx, krate, &crate_name_json)?, }; @@ -112,7 +112,7 @@ pub(crate) fn write_shared( md_opts.output = cx.dst.clone(); md_opts.external_html = cx.shared.layout.external_html.clone(); try_err!( - crate::markdown::render_and_write(&index_page, md_opts, cx.shared.edition()), + crate::markdown::render_and_write(index_page, md_opts, cx.shared.edition()), &index_page ); } @@ -158,13 +158,13 @@ fn write_rendered_cross_crate_info( let m = &opt.should_merge; if opt.emit.is_empty() || opt.emit.contains(&EmitType::InvocationSpecific) { if include_sources { - write_rendered_cci::(SourcesPart::blank, dst, &crates, m)?; + write_rendered_cci::(SourcesPart::blank, dst, crates, m)?; } - write_rendered_cci::(SearchIndexPart::blank, dst, &crates, m)?; - write_rendered_cci::(AllCratesPart::blank, dst, &crates, m)?; + write_rendered_cci::(SearchIndexPart::blank, dst, crates, m)?; + write_rendered_cci::(AllCratesPart::blank, dst, crates, m)?; } - write_rendered_cci::(TraitAliasPart::blank, dst, &crates, m)?; - write_rendered_cci::(TypeAliasPart::blank, dst, &crates, m)?; + write_rendered_cci::(TraitAliasPart::blank, dst, crates, m)?; + write_rendered_cci::(TypeAliasPart::blank, dst, crates, m)?; Ok(()) } @@ -234,7 +234,7 @@ fn write_search_desc( &cx.shared.resource_suffix, ); let path = path.join(filename); - let part = OrderedJson::serialize(&part).unwrap(); + let part = OrderedJson::serialize(part).unwrap(); let part = format!("searchState.loadedDescShard({encoded_crate_name}, {i}, {part})"); create_parents(&path)?; try_err!(fs::write(&path, part), &path); @@ -261,7 +261,7 @@ impl CrateInfo { .iter() .map(|parts_path| { let path = &parts_path.0; - let parts = try_err!(fs::read(&path), &path); + let parts = try_err!(fs::read(path), &path); let parts: CrateInfo = try_err!(serde_json::from_slice(&parts), &path); Ok::<_, Error>(parts) }) @@ -439,7 +439,7 @@ impl CratesIndexPart { const DELIMITER: &str = "\u{FFFC}"; // users are being naughty if they have this let content = format!("

List of all crates

    {DELIMITER}
"); - let template = layout::render(layout, &page, "", content, &style_files); + let template = layout::render(layout, &page, "", content, style_files); match SortedTemplate::from_template(&template, DELIMITER) { Ok(template) => template, Err(e) => panic!( @@ -534,7 +534,7 @@ impl Hierarchy { } fn add_path(self: &Rc, path: &Path) { - let mut h = Rc::clone(&self); + let mut h = Rc::clone(self); let mut elems = path .components() .filter_map(|s| match s { @@ -606,7 +606,7 @@ impl TypeAliasPart { cache, cx, }; - DocVisitor::visit_crate(&mut type_impl_collector, &krate); + DocVisitor::visit_crate(&mut type_impl_collector, krate); let cx = type_impl_collector.cx; let aliased_types = type_impl_collector.aliased_types; for aliased_type in aliased_types.values() { @@ -623,7 +623,7 @@ impl TypeAliasPart { // render_impl will filter out "impossible-to-call" methods // to make that functionality work here, it needs to be called with // each type alias, and if it gives a different result, split the impl - for &(type_alias_fqp, ref type_alias_item) in type_aliases { + for &(type_alias_fqp, type_alias_item) in type_aliases { let mut buf = Buffer::html(); cx.id_map = Default::default(); cx.deref_id_map = Default::default(); @@ -643,8 +643,8 @@ impl TypeAliasPart { super::render_impl( &mut buf, cx, - *impl_, - &type_alias_item, + impl_, + type_alias_item, assoc_link, RenderMode::Normal, None, @@ -680,7 +680,7 @@ impl TypeAliasPart { path.push(component.as_str()); } let aliased_item_type = aliased_type.target_type; - path.push(&format!( + path.push(format!( "{aliased_item_type}.{}.js", aliased_type.target_fqp[aliased_type.target_fqp.len() - 1] )); @@ -781,7 +781,7 @@ impl TraitAliasPart { for component in &remote_path[..remote_path.len() - 1] { path.push(component.as_str()); } - path.push(&format!("{remote_item_type}.{}.js", remote_path[remote_path.len() - 1])); + path.push(format!("{remote_item_type}.{}.js", remote_path[remote_path.len() - 1])); let part = OrderedJson::array_sorted( implementors @@ -865,7 +865,7 @@ struct AliasedTypeImpl<'cache, 'item> { type_aliases: Vec<(&'cache [Symbol], &'item Item)>, } -impl<'cx, 'cache, 'item> DocVisitor<'item> for TypeImplCollector<'cx, 'cache, 'item> { +impl<'item> DocVisitor<'item> for TypeImplCollector<'_, '_, 'item> { fn visit_item(&mut self, it: &'item Item) { self.visit_item_recur(it); let cache = self.cache; @@ -963,15 +963,13 @@ fn get_path_parts( crates_info: &[CrateInfo], ) -> FxIndexMap> { let mut templates: FxIndexMap> = FxIndexMap::default(); - crates_info - .iter() - .map(|crate_info| T::from_crate_info(crate_info).parts.iter()) - .flatten() - .for_each(|(path, part)| { - let path = dst.join(&path); + crates_info.iter().flat_map(|crate_info| T::from_crate_info(crate_info).parts.iter()).for_each( + |(path, part)| { + let path = dst.join(path); let part = part.to_string(); templates.entry(path).or_default().push(part); - }); + }, + ); templates } @@ -994,10 +992,10 @@ where if !should_merge.read_rendered_cci { return Ok(make_blank()); } - match fs::read_to_string(&path) { + match fs::read_to_string(path) { Ok(template) => Ok(try_err!(SortedTemplate::from_str(&template), &path)), Err(e) if e.kind() == io::ErrorKind::NotFound => Ok(make_blank()), - Err(e) => Err(Error::new(e, &path)), + Err(e) => Err(Error::new(e, path)), } } diff --git a/src/librustdoc/html/sources.rs b/src/librustdoc/html/sources.rs index f4a0ef01c253b..2fe9364c259c3 100644 --- a/src/librustdoc/html/sources.rs +++ b/src/librustdoc/html/sources.rs @@ -35,8 +35,8 @@ pub(crate) fn render(cx: &mut Context<'_>, krate: &clean::Crate) -> Result<(), E Ok(()) } -pub(crate) fn collect_local_sources<'tcx>( - tcx: TyCtxt<'tcx>, +pub(crate) fn collect_local_sources( + tcx: TyCtxt<'_>, src_root: &Path, krate: &clean::Crate, ) -> FxIndexMap { @@ -80,7 +80,7 @@ impl LocalSourcesCollector<'_, '_> { let href = RefCell::new(PathBuf::new()); clean_path( - &self.src_root, + self.src_root, &p, |component| { href.borrow_mut().push(component); diff --git a/src/librustdoc/html/static_files.rs b/src/librustdoc/html/static_files.rs index a4dc8cd1ed912..6457ac731cb76 100644 --- a/src/librustdoc/html/static_files.rs +++ b/src/librustdoc/html/static_files.rs @@ -57,7 +57,7 @@ pub(crate) fn suffix_path(filename: &str, suffix: &str) -> PathBuf { pub(crate) fn static_filename(filename: &str, sha256: &str) -> PathBuf { let filename = filename.rsplit('/').next().unwrap(); - suffix_path(filename, &sha256) + suffix_path(filename, sha256) } macro_rules! static_files { diff --git a/src/librustdoc/json/mod.rs b/src/librustdoc/json/mod.rs index df97c5ea2634a..560ed872ef3af 100644 --- a/src/librustdoc/json/mod.rs +++ b/src/librustdoc/json/mod.rs @@ -73,7 +73,7 @@ impl<'tcx> JsonRenderer<'tcx> { .map(|i| { let item = &i.impl_item; self.item(item.clone()).unwrap(); - self.id_from_item(&item) + self.id_from_item(item) }) .collect() }) @@ -104,7 +104,7 @@ impl<'tcx> JsonRenderer<'tcx> { if item.item_id.is_local() || is_primitive_impl { self.item(item.clone()).unwrap(); - Some(self.id_from_item(&item)) + Some(self.id_from_item(item)) } else { None } @@ -223,7 +223,7 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> { | types::ItemEnum::Macro(_) | types::ItemEnum::ProcMacro(_) => false, }; - let removed = self.index.borrow_mut().insert(new_item.id.clone(), new_item.clone()); + let removed = self.index.borrow_mut().insert(new_item.id, new_item.clone()); // FIXME(adotinthevoid): Currently, the index is duplicated. This is a sanity check // to make sure the items are unique. The main place this happens is when an item, is @@ -289,7 +289,7 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> { format_version: types::FORMAT_VERSION, }; if let Some(ref out_dir) = self.out_dir { - try_err!(create_dir_all(&out_dir), out_dir); + try_err!(create_dir_all(out_dir), out_dir); let mut p = out_dir.clone(); p.push(output_crate.index.get(&output_crate.root).unwrap().name.clone().unwrap()); diff --git a/src/librustdoc/lint.rs b/src/librustdoc/lint.rs index 2afb9e549d902..dcc27cd62e389 100644 --- a/src/librustdoc/lint.rs +++ b/src/librustdoc/lint.rs @@ -222,7 +222,7 @@ pub(crate) static RUSTDOC_LINTS: Lazy> = Lazy::new(|| { }); pub(crate) fn register_lints(_sess: &Session, lint_store: &mut LintStore) { - lint_store.register_lints(&**RUSTDOC_LINTS); + lint_store.register_lints(&RUSTDOC_LINTS); lint_store.register_group( true, "rustdoc::all", diff --git a/src/librustdoc/passes/calculate_doc_coverage.rs b/src/librustdoc/passes/calculate_doc_coverage.rs index 9f9a093da8a38..135aa79906010 100644 --- a/src/librustdoc/passes/calculate_doc_coverage.rs +++ b/src/librustdoc/passes/calculate_doc_coverage.rs @@ -118,7 +118,7 @@ fn limit_filename_len(filename: String) -> String { } } -impl<'a, 'b> CoverageCalculator<'a, 'b> { +impl CoverageCalculator<'_, '_> { fn to_json(&self) -> String { serde_json::to_string( &self @@ -188,7 +188,7 @@ impl<'a, 'b> CoverageCalculator<'a, 'b> { } } -impl<'a, 'b> DocVisitor<'_> for CoverageCalculator<'a, 'b> { +impl DocVisitor<'_> for CoverageCalculator<'_, '_> { fn visit_item(&mut self, i: &clean::Item) { if !i.item_id.is_local() { // non-local items are skipped because they can be out of the users control, diff --git a/src/librustdoc/passes/check_doc_test_visibility.rs b/src/librustdoc/passes/check_doc_test_visibility.rs index 484bdb5627c37..bf851b278b82a 100644 --- a/src/librustdoc/passes/check_doc_test_visibility.rs +++ b/src/librustdoc/passes/check_doc_test_visibility.rs @@ -34,7 +34,7 @@ pub(crate) fn check_doc_test_visibility(krate: Crate, cx: &mut DocContext<'_>) - krate } -impl<'a, 'tcx> DocVisitor<'_> for DocTestVisibilityLinter<'a, 'tcx> { +impl DocVisitor<'_> for DocTestVisibilityLinter<'_, '_> { fn visit_item(&mut self, item: &Item) { look_for_tests(self.cx, &item.doc_value(), item); @@ -106,7 +106,7 @@ pub(crate) fn should_have_doc_example(cx: &DocContext<'_>, item: &clean::Item) - level != lint::Level::Allow || matches!(source, LintLevelSource::Default) } -pub(crate) fn look_for_tests<'tcx>(cx: &DocContext<'tcx>, dox: &str, item: &Item) { +pub(crate) fn look_for_tests(cx: &DocContext<'_>, dox: &str, item: &Item) { let Some(hir_id) = DocContext::as_local_hir_id(cx.tcx, item.item_id) else { // If non-local, no need to check anything. return; diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 140fda7091885..c9d1ceb0a91a9 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -53,12 +53,12 @@ pub(crate) fn collect_intra_doc_links<'a, 'tcx>( (krate, collector) } -fn filter_assoc_items_by_name_and_namespace<'a>( - tcx: TyCtxt<'a>, +fn filter_assoc_items_by_name_and_namespace( + tcx: TyCtxt<'_>, assoc_items_of: DefId, ident: Ident, ns: Namespace, -) -> impl Iterator + 'a { +) -> impl Iterator + '_ { tcx.associated_items(assoc_items_of).filter_by_name_unhygienic(ident.name).filter(move |item| { item.kind.namespace() == ns && tcx.hygienic_eq(ident, item.ident(tcx), assoc_items_of) }) @@ -232,7 +232,7 @@ impl UrlFragment { s.push_str(kind); s.push_str(tcx.item_name(def_id).as_str()); } - UrlFragment::UserWritten(raw) => s.push_str(&raw), + UrlFragment::UserWritten(raw) => s.push_str(raw), } } } @@ -307,7 +307,7 @@ pub(crate) struct AmbiguousLinks { resolved: Vec<(Res, Option)>, } -impl<'a, 'tcx> LinkCollector<'a, 'tcx> { +impl<'tcx> LinkCollector<'_, 'tcx> { /// Given a full link, parse it as an [enum struct variant]. /// /// In particular, this will return an error whenever there aren't three @@ -339,7 +339,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { // If there's no third component, we saw `[a::b]` before and it failed to resolve. // So there's no partial res. let path = split.next().ok_or_else(no_res)?; - let ty_res = self.resolve_path(&path, TypeNS, item_id, module_id).ok_or_else(no_res)?; + let ty_res = self.resolve_path(path, TypeNS, item_id, module_id).ok_or_else(no_res)?; match ty_res { Res::Def(DefKind::Enum, did) => match tcx.type_of(did).instantiate_identity().kind() { @@ -628,7 +628,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { .map(|item| (root_res, item.def_id)) .collect::>() }) - .unwrap_or(Vec::new()) + .unwrap_or_default() } } Res::Def(DefKind::TyAlias, did) => { @@ -693,7 +693,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { // Checks if item_name belongs to `impl SomeItem` let mut assoc_items: Vec<_> = tcx .inherent_impls(did) - .into_iter() + .iter() .flat_map(|&imp| { filter_assoc_items_by_name_and_namespace( tcx, @@ -878,7 +878,7 @@ fn is_derive_trait_collision(ns: &PerNS, ResolutionFailu } } -impl<'a, 'tcx> DocVisitor<'_> for LinkCollector<'a, 'tcx> { +impl DocVisitor<'_> for LinkCollector<'_, '_> { fn visit_item(&mut self, item: &Item) { self.resolve_links(item); self.visit_item_recur(item) @@ -1152,7 +1152,7 @@ impl LinkCollector<'_, '_> { } cache.paths.get(&did).is_some() - || cache.external_paths.get(&did).is_some() + || cache.external_paths.contains_key(&did) || !did.is_local() } @@ -1271,7 +1271,7 @@ impl LinkCollector<'_, '_> { } res.def_id(self.cx.tcx).map(|page_id| ItemLink { - link: Box::::from(&*diag_info.ori_link), + link: Box::::from(diag_info.ori_link), link_text: link_text.clone(), page_id, fragment, @@ -1293,7 +1293,7 @@ impl LinkCollector<'_, '_> { let page_id = clean::register_res(self.cx, rustc_hir::def::Res::Def(kind, id)); Some(ItemLink { - link: Box::::from(&*diag_info.ori_link), + link: Box::::from(diag_info.ori_link), link_text: link_text.clone(), page_id, fragment, @@ -1387,7 +1387,7 @@ impl LinkCollector<'_, '_> { ) .unwrap_or_else(|| item.attr_span(self.cx.tcx)); rustc_session::parse::feature_err( - &self.cx.tcx.sess, + self.cx.tcx.sess, sym::intra_doc_pointers, span, "linking to associated items of raw pointers is experimental", @@ -1414,7 +1414,7 @@ impl LinkCollector<'_, '_> { // FIXME: it would be nice to check that the feature gate was enabled in the original crate, not just ignore it altogether. // However I'm not sure how to check that across crates. - if let Some(candidate) = candidates.get(0) + if let Some(candidate) = candidates.first() && candidate.0 == Res::Primitive(PrimitiveType::RawPointer) && key.path_str.contains("::") // We only want to check this if this is an associated item. @@ -1493,7 +1493,7 @@ impl LinkCollector<'_, '_> { } } resolution_failure(self, diag, path_str, disambiguator, smallvec![err]); - return vec![]; + vec![] } } } @@ -1509,15 +1509,12 @@ impl LinkCollector<'_, '_> { type_ns: candidate(TypeNS), value_ns: candidate(ValueNS).and_then(|v_res| { for (res, _) in v_res.iter() { - match res { - // Constructors are picked up in the type namespace. - Res::Def(DefKind::Ctor(..), _) => { - return Err(ResolutionFailure::WrongNamespace { - res: *res, - expected_ns: TypeNS, - }); - } - _ => {} + // Constructors are picked up in the type namespace. + if let Res::Def(DefKind::Ctor(..), _) = res { + return Err(ResolutionFailure::WrongNamespace { + res: *res, + expected_ns: TypeNS, + }); } } Ok(v_res) @@ -1536,7 +1533,7 @@ impl LinkCollector<'_, '_> { disambiguator, candidates.into_iter().filter_map(|res| res.err()).collect(), ); - return vec![]; + vec![] } else if len == 1 { candidates.into_iter().filter_map(|res| res.ok()).flatten().collect::>() } else { @@ -1850,7 +1847,7 @@ fn report_diagnostic( (sp, MarkdownLinkRange::Destination(md_range)) } MarkdownLinkRange::WholeLink(md_range) => ( - source_span_for_markdown_range(tcx, dox, &md_range, &item.attrs.doc_strings), + source_span_for_markdown_range(tcx, dox, md_range, &item.attrs.doc_strings), link_range.clone(), ), }; @@ -1985,8 +1982,7 @@ fn resolution_failure( .tcx .resolutions(()) .all_macro_rules - .get(&Symbol::intern(path_str)) - .is_some() + .contains_key(&Symbol::intern(path_str)) { diag.note(format!( "`macro_rules` named `{path_str}` exists in this crate, \ diff --git a/src/librustdoc/passes/collect_trait_impls.rs b/src/librustdoc/passes/collect_trait_impls.rs index f358908032285..87f85c5731528 100644 --- a/src/librustdoc/passes/collect_trait_impls.rs +++ b/src/librustdoc/passes/collect_trait_impls.rs @@ -229,7 +229,7 @@ struct SyntheticImplCollector<'a, 'tcx> { impls: Vec, } -impl<'a, 'tcx> DocVisitor<'_> for SyntheticImplCollector<'a, 'tcx> { +impl DocVisitor<'_> for SyntheticImplCollector<'_, '_> { fn visit_item(&mut self, i: &Item) { if i.is_struct() || i.is_enum() || i.is_union() { // FIXME(eddyb) is this `doc(hidden)` check needed? @@ -256,7 +256,7 @@ impl<'cache> ItemAndAliasCollector<'cache> { } } -impl<'cache> DocVisitor<'_> for ItemAndAliasCollector<'cache> { +impl DocVisitor<'_> for ItemAndAliasCollector<'_> { fn visit_item(&mut self, i: &Item) { self.items.insert(i.item_id); @@ -276,7 +276,7 @@ struct BadImplStripper<'a> { cache: &'a Cache, } -impl<'a> BadImplStripper<'a> { +impl BadImplStripper<'_> { fn keep_impl(&self, ty: &Type, is_deref: bool) -> bool { if let Generic(_) = ty { // keep impls made on generics diff --git a/src/librustdoc/passes/lint.rs b/src/librustdoc/passes/lint.rs index 35b62370abb29..1ecb53e61ac39 100644 --- a/src/librustdoc/passes/lint.rs +++ b/src/librustdoc/passes/lint.rs @@ -25,7 +25,7 @@ pub(crate) fn run_lints(krate: Crate, cx: &mut DocContext<'_>) -> Crate { krate } -impl<'a, 'tcx> DocVisitor<'_> for Linter<'a, 'tcx> { +impl DocVisitor<'_> for Linter<'_, '_> { fn visit_item(&mut self, item: &Item) { let Some(hir_id) = DocContext::as_local_hir_id(self.cx.tcx, item.item_id) else { // If non-local, no need to check anything. @@ -34,7 +34,7 @@ impl<'a, 'tcx> DocVisitor<'_> for Linter<'a, 'tcx> { let dox = item.doc_value(); if !dox.is_empty() { let may_have_link = dox.contains(&[':', '['][..]); - let may_have_block_comment_or_html = dox.contains(&['<', '>']); + let may_have_block_comment_or_html = dox.contains(['<', '>']); // ~~~rust // // This is a real, supported commonmark syntax for block code // ~~~ diff --git a/src/librustdoc/passes/lint/bare_urls.rs b/src/librustdoc/passes/lint/bare_urls.rs index 1397eadb2884c..77d7cf5772d67 100644 --- a/src/librustdoc/passes/lint/bare_urls.rs +++ b/src/librustdoc/passes/lint/bare_urls.rs @@ -18,7 +18,7 @@ use crate::html::markdown::main_body_opts; pub(super) fn visit_item(cx: &DocContext<'_>, item: &Item, hir_id: HirId, dox: &str) { let report_diag = |cx: &DocContext<'_>, msg: &'static str, range: Range| { - let sp = source_span_for_markdown_range(cx.tcx, &dox, &range, &item.attrs.doc_strings) + let sp = source_span_for_markdown_range(cx.tcx, dox, &range, &item.attrs.doc_strings) .unwrap_or_else(|| item.attr_span(cx.tcx)); cx.tcx.node_span_lint(crate::lint::BARE_URLS, hir_id, sp, |lint| { lint.primary_message(msg) @@ -34,14 +34,14 @@ pub(super) fn visit_item(cx: &DocContext<'_>, item: &Item, hir_id: HirId, dox: & }); }; - let mut p = Parser::new_ext(&dox, main_body_opts()).into_offset_iter(); + let mut p = Parser::new_ext(dox, main_body_opts()).into_offset_iter(); while let Some((event, range)) = p.next() { match event { Event::Text(s) => find_raw_urls(cx, &s, range, &report_diag), // We don't want to check the text inside code blocks or links. Event::Start(tag @ (Tag::CodeBlock(_) | Tag::Link { .. })) => { - while let Some((event, _)) = p.next() { + for (event, _) in p.by_ref() { match event { Event::End(end) if mem::discriminant(&end) == mem::discriminant(&tag.to_end()) => diff --git a/src/librustdoc/passes/lint/check_code_block_syntax.rs b/src/librustdoc/passes/lint/check_code_block_syntax.rs index e0dc5b4c51333..20d65d8cd9f02 100644 --- a/src/librustdoc/passes/lint/check_code_block_syntax.rs +++ b/src/librustdoc/passes/lint/check_code_block_syntax.rs @@ -150,7 +150,7 @@ impl Translate for BufferEmitter { } fn fallback_fluent_bundle(&self) -> &rustc_errors::FluentBundle { - &**self.fallback_bundle + &self.fallback_bundle } } diff --git a/src/librustdoc/passes/lint/html_tags.rs b/src/librustdoc/passes/lint/html_tags.rs index 223174838ade0..3fb154dc51549 100644 --- a/src/librustdoc/passes/lint/html_tags.rs +++ b/src/librustdoc/passes/lint/html_tags.rs @@ -15,7 +15,7 @@ use crate::html::markdown::main_body_opts; pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item, hir_id: HirId, dox: &str) { let tcx = cx.tcx; let report_diag = |msg: String, range: &Range, is_open_tag: bool| { - let sp = match source_span_for_markdown_range(tcx, &dox, range, &item.attrs.doc_strings) { + let sp = match source_span_for_markdown_range(tcx, dox, range, &item.attrs.doc_strings) { Some(sp) => sp, None => item.attr_span(tcx), }; @@ -30,7 +30,7 @@ pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item, hir_id: HirId, dox: & let mut generics_end = range.end; if let Some(Some(mut generics_start)) = (is_open_tag && dox[..generics_end].ends_with('>')) - .then(|| extract_path_backwards(&dox, range.start)) + .then(|| extract_path_backwards(dox, range.start)) { while generics_start != 0 && generics_end < dox.len() @@ -39,19 +39,19 @@ pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item, hir_id: HirId, dox: & { generics_end += 1; generics_start -= 1; - if let Some(new_start) = extract_path_backwards(&dox, generics_start) { + if let Some(new_start) = extract_path_backwards(dox, generics_start) { generics_start = new_start; } - if let Some(new_end) = extract_path_forward(&dox, generics_end) { + if let Some(new_end) = extract_path_forward(dox, generics_end) { generics_end = new_end; } } - if let Some(new_end) = extract_path_forward(&dox, generics_end) { + if let Some(new_end) = extract_path_forward(dox, generics_end) { generics_end = new_end; } let generics_sp = match source_span_for_markdown_range( tcx, - &dox, + dox, &(generics_start..generics_end), &item.attrs.doc_strings, ) { @@ -125,7 +125,7 @@ pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item, hir_id: HirId, dox: & } }; - let p = Parser::new_with_broken_link_callback(&dox, main_body_opts(), Some(&mut replacer)) + let p = Parser::new_with_broken_link_callback(dox, main_body_opts(), Some(&mut replacer)) .into_offset_iter(); for (event, range) in p { @@ -233,7 +233,7 @@ fn extract_path_forward(text: &str, start_pos: usize) -> Option { break; } } - while let Some(c) = chars.next() { + for c in chars { if is_id_continue(c) { current_pos += c.len_utf8(); } else { diff --git a/src/librustdoc/passes/lint/redundant_explicit_links.rs b/src/librustdoc/passes/lint/redundant_explicit_links.rs index f3599688454b2..6bc4374c06b1d 100644 --- a/src/librustdoc/passes/lint/redundant_explicit_links.rs +++ b/src/librustdoc/passes/lint/redundant_explicit_links.rs @@ -35,12 +35,12 @@ pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item, hir_id: HirId) { } } -fn check_redundant_explicit_link_for_did<'md>( +fn check_redundant_explicit_link_for_did( cx: &DocContext<'_>, item: &Item, did: DefId, hir_id: HirId, - doc: &'md str, + doc: &str, ) { let Some(local_item_id) = did.as_local() else { return; @@ -71,7 +71,7 @@ fn check_redundant_explicit_link_for_did<'md>( return; }; - check_redundant_explicit_link(cx, item, hir_id, &doc, &resolutions); + check_redundant_explicit_link(cx, item, hir_id, doc, resolutions); } fn check_redundant_explicit_link<'md>( @@ -90,60 +90,52 @@ fn check_redundant_explicit_link<'md>( .into_offset_iter(); while let Some((event, link_range)) = offset_iter.next() { - match event { - Event::Start(Tag::Link { link_type, dest_url, .. }) => { - let link_data = collect_link_data(&mut offset_iter); - - if let Some(resolvable_link) = link_data.resolvable_link.as_ref() { - if &link_data.display_link.replace('`', "") != resolvable_link { - // Skips if display link does not match to actual - // resolvable link, usually happens if display link - // has several segments, e.g. - // [this is just an `Option`](Option) - continue; - } + if let Event::Start(Tag::Link { link_type, dest_url, .. }) = event { + let link_data = collect_link_data(&mut offset_iter); + + if let Some(resolvable_link) = link_data.resolvable_link.as_ref() { + if &link_data.display_link.replace('`', "") != resolvable_link { + // Skips if display link does not match to actual + // resolvable link, usually happens if display link + // has several segments, e.g. + // [this is just an `Option`](Option) + continue; } + } - let explicit_link = dest_url.to_string(); - let display_link = link_data.resolvable_link.clone()?; - - if explicit_link.ends_with(&display_link) || display_link.ends_with(&explicit_link) - { - match link_type { - LinkType::Inline | LinkType::ReferenceUnknown => { - check_inline_or_reference_unknown_redundancy( - cx, - item, - hir_id, - doc, - resolutions, - link_range, - dest_url.to_string(), - link_data, - if link_type == LinkType::Inline { - (b'(', b')') - } else { - (b'[', b']') - }, - ); - } - LinkType::Reference => { - check_reference_redundancy( - cx, - item, - hir_id, - doc, - resolutions, - link_range, - &dest_url, - link_data, - ); - } - _ => {} + let explicit_link = dest_url.to_string(); + let display_link = link_data.resolvable_link.clone()?; + + if explicit_link.ends_with(&display_link) || display_link.ends_with(&explicit_link) { + match link_type { + LinkType::Inline | LinkType::ReferenceUnknown => { + check_inline_or_reference_unknown_redundancy( + cx, + item, + hir_id, + doc, + resolutions, + link_range, + dest_url.to_string(), + link_data, + if link_type == LinkType::Inline { (b'(', b')') } else { (b'[', b']') }, + ); + } + LinkType::Reference => { + check_reference_redundancy( + cx, + item, + hir_id, + doc, + resolutions, + link_range, + &dest_url, + link_data, + ); } + _ => {} } } - _ => {} } } @@ -169,18 +161,18 @@ fn check_inline_or_reference_unknown_redundancy( if dest_res == display_res { let link_span = - source_span_for_markdown_range(cx.tcx, &doc, &link_range, &item.attrs.doc_strings) + source_span_for_markdown_range(cx.tcx, doc, &link_range, &item.attrs.doc_strings) .unwrap_or(item.attr_span(cx.tcx)); let explicit_span = source_span_for_markdown_range( cx.tcx, - &doc, + doc, &offset_explicit_range(doc, link_range, open, close), &item.attrs.doc_strings, )?; let display_span = source_span_for_markdown_range( cx.tcx, - &doc, - &resolvable_link_range, + doc, + resolvable_link_range, &item.attrs.doc_strings, )?; @@ -210,27 +202,27 @@ fn check_reference_redundancy( let (resolvable_link, resolvable_link_range) = (&link_data.resolvable_link?, &link_data.resolvable_link_range?); let (dest_res, display_res) = - (find_resolution(resolutions, &dest)?, find_resolution(resolutions, resolvable_link)?); + (find_resolution(resolutions, dest)?, find_resolution(resolutions, resolvable_link)?); if dest_res == display_res { let link_span = - source_span_for_markdown_range(cx.tcx, &doc, &link_range, &item.attrs.doc_strings) + source_span_for_markdown_range(cx.tcx, doc, &link_range, &item.attrs.doc_strings) .unwrap_or(item.attr_span(cx.tcx)); let explicit_span = source_span_for_markdown_range( cx.tcx, - &doc, + doc, &offset_explicit_range(doc, link_range.clone(), b'[', b']'), &item.attrs.doc_strings, )?; let display_span = source_span_for_markdown_range( cx.tcx, - &doc, - &resolvable_link_range, + doc, + resolvable_link_range, &item.attrs.doc_strings, )?; let def_span = source_span_for_markdown_range( cx.tcx, - &doc, + doc, &offset_reference_def_range(doc, dest, link_range), &item.attrs.doc_strings, )?; @@ -263,7 +255,7 @@ fn collect_link_data<'input, F: BrokenLinkCallback<'input>>( let mut display_link = String::new(); let mut is_resolvable = true; - while let Some((event, range)) = offset_iter.next() { + for (event, range) in offset_iter.by_ref() { match event { Event::Text(code) => { let code = code.to_string(); diff --git a/src/librustdoc/passes/lint/unescaped_backticks.rs b/src/librustdoc/passes/lint/unescaped_backticks.rs index d79f682a580f8..88f4c3ac1cd79 100644 --- a/src/librustdoc/passes/lint/unescaped_backticks.rs +++ b/src/librustdoc/passes/lint/unescaped_backticks.rs @@ -22,7 +22,7 @@ pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item, hir_id: HirId, dox: & .find(|link| *link.original_text == *broken_link.reference) .map(|link| ((*link.href).into(), (*link.new_text).into())) }; - let parser = Parser::new_with_broken_link_callback(&dox, main_body_opts(), Some(&mut replacer)) + let parser = Parser::new_with_broken_link_callback(dox, main_body_opts(), Some(&mut replacer)) .into_offset_iter(); let mut element_stack = Vec::new(); @@ -44,7 +44,7 @@ pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item, hir_id: HirId, dox: & // use the span of the entire attribute as a fallback. let span = source_span_for_markdown_range( tcx, - &dox, + dox, &(backtick_index..backtick_index + 1), &item.attrs.doc_strings, ) @@ -61,12 +61,12 @@ pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item, hir_id: HirId, dox: & // "foo` `bar`" -> "`foo` `bar`" if let Some(suggest_index) = clamp_start(guess, &element.suggestible_ranges) - && can_suggest_backtick(&dox, suggest_index) + && can_suggest_backtick(dox, suggest_index) { suggest_insertion( cx, item, - &dox, + dox, lint, suggest_index, '`', @@ -80,11 +80,11 @@ pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item, hir_id: HirId, dox: & // Don't `clamp_end` here, because the suggestion is guaranteed to be inside // an inline code node and we intentionally "break" the inline code here. let suggest_index = guess; - if can_suggest_backtick(&dox, suggest_index) { + if can_suggest_backtick(dox, suggest_index) { suggest_insertion( cx, item, - &dox, + dox, lint, suggest_index, '`', @@ -98,15 +98,15 @@ pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item, hir_id: HirId, dox: & if !element.prev_code_guess.is_confident() { // "`foo` bar`" -> "`foo` `bar`" if let Some(guess) = - guess_start_of_code(&dox, element.element_range.start..backtick_index) + guess_start_of_code(dox, element.element_range.start..backtick_index) && let Some(suggest_index) = clamp_start(guess, &element.suggestible_ranges) - && can_suggest_backtick(&dox, suggest_index) + && can_suggest_backtick(dox, suggest_index) { suggest_insertion( cx, item, - &dox, + dox, lint, suggest_index, '`', @@ -120,16 +120,16 @@ pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item, hir_id: HirId, dox: & // if we already suggested opening backtick. For example: // "foo`." -> "`foo`." or "foo`s" -> "`foo`s". if let Some(guess) = - guess_end_of_code(&dox, backtick_index + 1..element.element_range.end) + guess_end_of_code(dox, backtick_index + 1..element.element_range.end) && let Some(suggest_index) = clamp_end(guess, &element.suggestible_ranges) - && can_suggest_backtick(&dox, suggest_index) + && can_suggest_backtick(dox, suggest_index) && (!help_emitted || suggest_index - backtick_index > 2) { suggest_insertion( cx, item, - &dox, + dox, lint, suggest_index, '`', @@ -148,7 +148,7 @@ pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item, hir_id: HirId, dox: & suggest_insertion( cx, item, - &dox, + dox, lint, backtick_index, '\\', @@ -177,13 +177,13 @@ pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item, hir_id: HirId, dox: & let is_confident = text_inside.starts_with(char::is_whitespace) || text_inside.ends_with(char::is_whitespace); - if let Some(guess) = guess_end_of_code(&dox, range_inside) { + if let Some(guess) = guess_end_of_code(dox, range_inside) { // Find earlier end of code. element.prev_code_guess = PrevCodeGuess::End { guess, is_confident }; } else { // Find alternate start of code. let range_before = element.element_range.start..event_range.start; - if let Some(guess) = guess_start_of_code(&dox, range_before) { + if let Some(guess) = guess_start_of_code(dox, range_before) { element.prev_code_guess = PrevCodeGuess::Start { guess, is_confident }; } } @@ -421,7 +421,7 @@ fn suggest_insertion( if let Some(span) = source_span_for_markdown_range( cx.tcx, - &dox, + dox, &(insert_index..insert_index), &item.attrs.doc_strings, ) { diff --git a/src/librustdoc/passes/lint/unportable_markdown.rs b/src/librustdoc/passes/lint/unportable_markdown.rs index f8368a866c882..a3c3134f4c2c5 100644 --- a/src/librustdoc/passes/lint/unportable_markdown.rs +++ b/src/librustdoc/passes/lint/unportable_markdown.rs @@ -49,8 +49,8 @@ pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item, hir_id: HirId, dox: & | cmarkn::Options::ENABLE_TASKLISTS | cmarkn::Options::ENABLE_SMART_PUNCTUATION } - let mut parser_new = cmarkn::Parser::new_ext(&dox, main_body_opts_new()).into_offset_iter(); - while let Some((event, span)) = parser_new.next() { + let parser_new = cmarkn::Parser::new_ext(dox, main_body_opts_new()).into_offset_iter(); + for (event, span) in parser_new { if let cmarkn::Event::Start(cmarkn::Tag::BlockQuote(_)) = event { if !dox[span.clone()].starts_with("> ") { spaceless_block_quotes.insert(span.start); @@ -71,8 +71,8 @@ pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item, hir_id: HirId, dox: & | cmarko::Options::ENABLE_TASKLISTS | cmarko::Options::ENABLE_SMART_PUNCTUATION } - let mut parser_old = cmarko::Parser::new_ext(&dox, main_body_opts_old()).into_offset_iter(); - while let Some((event, span)) = parser_old.next() { + let parser_old = cmarko::Parser::new_ext(dox, main_body_opts_old()).into_offset_iter(); + for (event, span) in parser_old { if let cmarko::Event::Start(cmarko::Tag::BlockQuote) = event { if !dox[span.clone()].starts_with("> ") { spaceless_block_quotes.remove(&span.start); @@ -88,13 +88,13 @@ pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item, hir_id: HirId, dox: & for start in spaceless_block_quotes { let (span, precise) = - source_span_for_markdown_range(tcx, &dox, &(start..start + 1), &item.attrs.doc_strings) + source_span_for_markdown_range(tcx, dox, &(start..start + 1), &item.attrs.doc_strings) .map(|span| (span, true)) .unwrap_or_else(|| (item.attr_span(tcx), false)); tcx.node_span_lint(crate::lint::UNPORTABLE_MARKDOWN, hir_id, span, |lint| { lint.primary_message("unportable markdown"); - lint.help(format!("confusing block quote with no space after the `>` marker")); + lint.help("confusing block quote with no space after the `>` marker".to_string()); if precise { lint.span_suggestion( span.shrink_to_hi(), @@ -113,7 +113,7 @@ pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item, hir_id: HirId, dox: & } for (_caret, span) in missing_footnote_references { let (ref_span, precise) = - source_span_for_markdown_range(tcx, &dox, &span, &item.attrs.doc_strings) + source_span_for_markdown_range(tcx, dox, &span, &item.attrs.doc_strings) .map(|span| (span, true)) .unwrap_or_else(|| (item.attr_span(tcx), false)); diff --git a/src/librustdoc/passes/propagate_doc_cfg.rs b/src/librustdoc/passes/propagate_doc_cfg.rs index 350be37f553da..572c9bf7552fa 100644 --- a/src/librustdoc/passes/propagate_doc_cfg.rs +++ b/src/librustdoc/passes/propagate_doc_cfg.rs @@ -27,7 +27,7 @@ struct CfgPropagator<'a, 'tcx> { cx: &'a mut DocContext<'tcx>, } -impl<'a, 'tcx> CfgPropagator<'a, 'tcx> { +impl CfgPropagator<'_, '_> { // Some items need to merge their attributes with their parents' otherwise a few of them // (mostly `cfg` ones) will be missing. fn merge_with_parent_attributes(&mut self, item: &mut Item) { @@ -65,7 +65,7 @@ impl<'a, 'tcx> CfgPropagator<'a, 'tcx> { } } -impl<'a, 'tcx> DocFolder for CfgPropagator<'a, 'tcx> { +impl DocFolder for CfgPropagator<'_, '_> { fn fold_item(&mut self, mut item: Item) -> Option { let old_parent_cfg = self.parent_cfg.clone(); diff --git a/src/librustdoc/passes/propagate_stability.rs b/src/librustdoc/passes/propagate_stability.rs index a28487cc79e5d..a81b130a218b3 100644 --- a/src/librustdoc/passes/propagate_stability.rs +++ b/src/librustdoc/passes/propagate_stability.rs @@ -30,7 +30,7 @@ struct StabilityPropagator<'a, 'tcx> { cx: &'a mut DocContext<'tcx>, } -impl<'a, 'tcx> DocFolder for StabilityPropagator<'a, 'tcx> { +impl DocFolder for StabilityPropagator<'_, '_> { fn fold_item(&mut self, mut item: Item) -> Option { let parent_stability = self.parent_stability; diff --git a/src/librustdoc/passes/strip_aliased_non_local.rs b/src/librustdoc/passes/strip_aliased_non_local.rs index a078eec048ece..fa7737bc14386 100644 --- a/src/librustdoc/passes/strip_aliased_non_local.rs +++ b/src/librustdoc/passes/strip_aliased_non_local.rs @@ -21,7 +21,7 @@ struct AliasedNonLocalStripper<'tcx> { tcx: TyCtxt<'tcx>, } -impl<'tcx> DocFolder for AliasedNonLocalStripper<'tcx> { +impl DocFolder for AliasedNonLocalStripper<'_> { fn fold_item(&mut self, i: Item) -> Option { Some(match i.kind { clean::TypeAliasItem(..) => { @@ -39,7 +39,7 @@ struct NonLocalStripper<'tcx> { tcx: TyCtxt<'tcx>, } -impl<'tcx> DocFolder for NonLocalStripper<'tcx> { +impl DocFolder for NonLocalStripper<'_> { fn fold_item(&mut self, i: Item) -> Option { // If not local, we want to respect the original visibility of // the field and not the one given by the user for the currrent crate. @@ -50,7 +50,7 @@ impl<'tcx> DocFolder for NonLocalStripper<'tcx> { { if i.is_doc_hidden() // Default to *not* stripping items with inherited visibility. - || i.visibility(self.tcx).map_or(false, |viz| viz != Visibility::Public) + || i.visibility(self.tcx).is_some_and(|viz| viz != Visibility::Public) { return Some(strip_item(i)); } diff --git a/src/librustdoc/passes/strip_hidden.rs b/src/librustdoc/passes/strip_hidden.rs index 4ef5f7f20a917..a71bb62e56c74 100644 --- a/src/librustdoc/passes/strip_hidden.rs +++ b/src/librustdoc/passes/strip_hidden.rs @@ -57,7 +57,7 @@ struct Stripper<'a, 'tcx> { last_reexport: Option, } -impl<'a, 'tcx> Stripper<'a, 'tcx> { +impl Stripper<'_, '_> { fn set_last_reexport_then_fold_item(&mut self, i: Item) -> Item { let prev_from_reexport = self.last_reexport; if i.inline_stmt_id.is_some() { @@ -86,7 +86,7 @@ impl<'a, 'tcx> Stripper<'a, 'tcx> { } } -impl<'a, 'tcx> DocFolder for Stripper<'a, 'tcx> { +impl DocFolder for Stripper<'_, '_> { fn fold_item(&mut self, i: Item) -> Option { let has_doc_hidden = i.is_doc_hidden(); let is_impl_or_exported_macro = match i.kind { diff --git a/src/librustdoc/passes/stripper.rs b/src/librustdoc/passes/stripper.rs index 98b3446c26d23..60909754b3330 100644 --- a/src/librustdoc/passes/stripper.rs +++ b/src/librustdoc/passes/stripper.rs @@ -37,7 +37,7 @@ fn is_item_reachable( } } -impl<'a, 'tcx> DocFolder for Stripper<'a, 'tcx> { +impl DocFolder for Stripper<'_, '_> { fn fold_item(&mut self, i: Item) -> Option { match i.kind { clean::StrippedItem(..) => { @@ -171,7 +171,7 @@ pub(crate) struct ImplStripper<'a, 'tcx> { pub(crate) document_hidden: bool, } -impl<'a> ImplStripper<'a, '_> { +impl ImplStripper<'_, '_> { #[inline] fn should_keep_impl(&self, item: &Item, for_def_id: DefId) -> bool { if !for_def_id.is_local() || self.retained.contains(&for_def_id.into()) { @@ -193,7 +193,7 @@ impl<'a> ImplStripper<'a, '_> { } } -impl<'a> DocFolder for ImplStripper<'a, '_> { +impl DocFolder for ImplStripper<'_, '_> { fn fold_item(&mut self, i: Item) -> Option { if let clean::ImplItem(ref imp) = i.kind { // Impl blocks can be skipped if they are: empty; not a trait impl; and have no @@ -259,7 +259,7 @@ pub(crate) struct ImportStripper<'tcx> { pub(crate) document_hidden: bool, } -impl<'tcx> ImportStripper<'tcx> { +impl ImportStripper<'_> { fn import_should_be_hidden(&self, i: &Item, imp: &clean::Import) -> bool { if self.is_json_output { // FIXME: This should be handled the same way as for HTML output. @@ -270,11 +270,11 @@ impl<'tcx> ImportStripper<'tcx> { } } -impl<'tcx> DocFolder for ImportStripper<'tcx> { +impl DocFolder for ImportStripper<'_> { fn fold_item(&mut self, i: Item) -> Option { match &i.kind { clean::ImportItem(imp) - if !self.document_hidden && self.import_should_be_hidden(&i, &imp) => + if !self.document_hidden && self.import_should_be_hidden(&i, imp) => { None } diff --git a/src/librustdoc/theme.rs b/src/librustdoc/theme.rs index 2c00bb7e13295..a49fb06bde35f 100644 --- a/src/librustdoc/theme.rs +++ b/src/librustdoc/theme.rs @@ -54,7 +54,7 @@ fn skip_comment(iter: &mut Peekable>) { /// Skips a line comment (`//`). fn skip_line_comment(iter: &mut Peekable>) { - while let Some(c) = iter.next() { + for c in iter.by_ref() { if c == '\n' { break; } diff --git a/src/librustdoc/visit.rs b/src/librustdoc/visit.rs index bfa285c57fa93..c2e8ffd7665b8 100644 --- a/src/librustdoc/visit.rs +++ b/src/librustdoc/visit.rs @@ -55,7 +55,7 @@ pub(crate) trait DocVisitor<'a>: Sized { /// Don't override! fn visit_item_recur(&mut self, item: &'a Item) { match &item.kind { - StrippedItem(i) => self.visit_inner_recur(&*i), + StrippedItem(i) => self.visit_inner_recur(i), _ => self.visit_inner_recur(&item.kind), } } diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index 31c33fbf49737..11f06f7d917c5 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -312,7 +312,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { Node::Item(_) if is_bang_macro && !please_inline && renamed.is_some() && is_hidden => { return false; } - Node::Item(&hir::Item { kind: hir::ItemKind::Mod(ref m), .. }) if glob => { + Node::Item(&hir::Item { kind: hir::ItemKind::Mod(m), .. }) if glob => { let prev = mem::replace(&mut self.inlining, true); for &i in m.item_ids { let i = tcx.hir().item(i); @@ -476,7 +476,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { self.add_to_current_mod(item, renamed, import_id); } } - hir::ItemKind::Macro(ref macro_def, _) => { + hir::ItemKind::Macro(macro_def, _) => { // `#[macro_export] macro_rules!` items are handled separately in `visit()`, // above, since they need to be documented at the module top level. Accordingly, // we only want to handle macros if one of three conditions holds: @@ -496,7 +496,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { self.add_to_current_mod(item, renamed, import_id); } } - hir::ItemKind::Mod(ref m) => { + hir::ItemKind::Mod(m) => { self.enter_mod(item.owner_id.def_id, m, name, renamed, import_id); } hir::ItemKind::Fn(..) @@ -560,7 +560,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { // We need to implement this visitor so it'll go everywhere and retrieve items we're interested in // such as impl blocks in const blocks. -impl<'a, 'tcx> Visitor<'tcx> for RustdocVisitor<'a, 'tcx> { +impl<'tcx> Visitor<'tcx> for RustdocVisitor<'_, 'tcx> { type NestedFilter = nested_filter::All; fn nested_visit_map(&mut self) -> Self::Map { diff --git a/tests/crashes/126646.rs b/tests/crashes/126646.rs deleted file mode 100644 index 24e3530320a89..0000000000000 --- a/tests/crashes/126646.rs +++ /dev/null @@ -1,18 +0,0 @@ -//@ known-bug: rust-lang/rust#126646 -mod foo { - pub trait Callable { - type Output; - fn call() -> Self::Output; - } - - impl<'a, V: ?Sized> Callable for &'a () { - type Output = (); - } -} -use foo::*; - -fn test<'a>() -> impl Sized { - <&'a () as Callable>::call() -} - -fn main() {} diff --git a/tests/ui/impl-trait/in-trait/do-not-imply-from-trait-impl.rs b/tests/ui/impl-trait/in-trait/do-not-imply-from-trait-impl.rs new file mode 100644 index 0000000000000..30ca3d271b815 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/do-not-imply-from-trait-impl.rs @@ -0,0 +1,30 @@ +// Make sure that we don't accidentally collect an RPITIT hidden type that does not +// hold for all instantiations of the trait signature. + +trait MkStatic { + fn mk_static(self) -> &'static str; +} + +impl MkStatic for &'static str { + fn mk_static(self) -> &'static str { self } +} + +trait Foo { + fn foo<'a: 'static, 'late>(&'late self) -> impl MkStatic; +} + +impl Foo for str { + fn foo<'a: 'static>(&'a self) -> impl MkStatic + 'static { + //~^ ERROR method not compatible with trait + self + } +} + +fn call_foo(t: &T) -> &'static str { + t.foo().mk_static() +} + +fn main() { + let s = call_foo(String::from("hello, world").as_str()); + println!("> {s}"); +} diff --git a/tests/ui/impl-trait/in-trait/do-not-imply-from-trait-impl.stderr b/tests/ui/impl-trait/in-trait/do-not-imply-from-trait-impl.stderr new file mode 100644 index 0000000000000..95d8699e19ff1 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/do-not-imply-from-trait-impl.stderr @@ -0,0 +1,22 @@ +error[E0308]: method not compatible with trait + --> $DIR/do-not-imply-from-trait-impl.rs:17:38 + | +LL | fn foo<'a: 'static>(&'a self) -> impl MkStatic + 'static { + | ^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch + | + = note: expected signature `fn(&'late _) -> _` + found signature `fn(&'a _) -> _` +note: the lifetime `'late` as defined here... + --> $DIR/do-not-imply-from-trait-impl.rs:13:25 + | +LL | fn foo<'a: 'static, 'late>(&'late self) -> impl MkStatic; + | ^^^^^ +note: ...does not necessarily outlive the lifetime `'a` as defined here + --> $DIR/do-not-imply-from-trait-impl.rs:17:12 + | +LL | fn foo<'a: 'static>(&'a self) -> impl MkStatic + 'static { + | ^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/impl-trait/in-trait/method-signature-matches.lt.stderr b/tests/ui/impl-trait/in-trait/method-signature-matches.lt.stderr index 6f6b787b6fe1b..a23879eb6c376 100644 --- a/tests/ui/impl-trait/in-trait/method-signature-matches.lt.stderr +++ b/tests/ui/impl-trait/in-trait/method-signature-matches.lt.stderr @@ -11,12 +11,12 @@ note: type in trait | LL | fn early<'early, T>(x: &'early T) -> impl Sized; | ^^^^^^^^^ - = note: expected signature `fn(&T)` - found signature `fn(&'late ())` + = note: expected signature `fn(&'early T)` + found signature `fn(&())` help: change the parameter type to match the trait | -LL | fn early<'late, T>(_: &T) {} - | ~~ +LL | fn early<'late, T>(_: &'early T) {} + | ~~~~~~~~~ error: aborting due to 1 previous error diff --git a/tests/ui/impl-trait/in-trait/rpitit-hidden-types-self-implied-wf.stderr b/tests/ui/impl-trait/in-trait/rpitit-hidden-types-self-implied-wf.stderr index 3430055dab171..4c10422f985f1 100644 --- a/tests/ui/impl-trait/in-trait/rpitit-hidden-types-self-implied-wf.stderr +++ b/tests/ui/impl-trait/in-trait/rpitit-hidden-types-self-implied-wf.stderr @@ -6,9 +6,9 @@ LL | fn extend(s: &str) -> (Option<&'static &'_ ()>, &'static str) { | = note: the pointer is valid for the static lifetime note: but the referenced data is only valid for the anonymous lifetime defined here - --> $DIR/rpitit-hidden-types-self-implied-wf.rs:6:18 + --> $DIR/rpitit-hidden-types-self-implied-wf.rs:2:18 | -LL | fn extend(s: &str) -> (Option<&'static &'_ ()>, &'static str) { +LL | fn extend(_: &str) -> (impl Sized + '_, &'static str); | ^^^^ error: aborting due to 1 previous error diff --git a/tests/ui/impl-trait/in-trait/signature-mismatch.failure.stderr b/tests/ui/impl-trait/in-trait/signature-mismatch.failure.stderr index 56b83cbca77ac..b27d7870955ed 100644 --- a/tests/ui/impl-trait/in-trait/signature-mismatch.failure.stderr +++ b/tests/ui/impl-trait/in-trait/signature-mismatch.failure.stderr @@ -1,14 +1,15 @@ -error[E0623]: lifetime mismatch +error[E0477]: the type `impl Future>` does not fulfill the required lifetime --> $DIR/signature-mismatch.rs:77:10 | -LL | &'a self, - | -------- this parameter and the return type are declared with different lifetimes... -... LL | ) -> impl Future> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | | - | ...but data from `buff` is returned here + | +note: type must outlive the lifetime `'a` as defined here as required by this binding + --> $DIR/signature-mismatch.rs:73:32 + | +LL | fn async_fn_reduce_outlive<'a, 'b, T>( + | ^^ error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0623`. +For more information about this error, try `rustc --explain E0477`. diff --git a/tests/ui/impl-trait/in-trait/signature-mismatch.rs b/tests/ui/impl-trait/in-trait/signature-mismatch.rs index 55b9a0de5ff02..a9885c6a2986b 100644 --- a/tests/ui/impl-trait/in-trait/signature-mismatch.rs +++ b/tests/ui/impl-trait/in-trait/signature-mismatch.rs @@ -75,7 +75,7 @@ impl AsyncTrait for Struct { buff: &'b [u8], t: T, ) -> impl Future> { - //[failure]~^ ERROR lifetime mismatch + //[failure]~^ ERROR the type `impl Future>` does not fulfill the required lifetime async move { let _t = t; vec![] diff --git a/tests/ui/impl-trait/precise-capturing/rpitit-impl-captures-too-much.stderr b/tests/ui/impl-trait/precise-capturing/rpitit-impl-captures-too-much.stderr index e1856b929106e..360f0d7e7f37f 100644 --- a/tests/ui/impl-trait/precise-capturing/rpitit-impl-captures-too-much.stderr +++ b/tests/ui/impl-trait/precise-capturing/rpitit-impl-captures-too-much.stderr @@ -1,10 +1,11 @@ error: return type captures more lifetimes than trait definition --> $DIR/rpitit-impl-captures-too-much.rs:10:39 | +LL | fn hello(self_: Invariant<'_>) -> impl Sized + use; + | -- this lifetime was captured +... LL | fn hello(self_: Invariant<'_>) -> impl Sized + use<'_> {} - | -- ^^^^^^^^^^^^^^^^^^^^ - | | - | this lifetime was captured + | ^^^^^^^^^^^^^^^^^^^^ | note: hidden type must only reference lifetimes captured by this impl trait --> $DIR/rpitit-impl-captures-too-much.rs:6:39 diff --git a/tests/ui/lint/group-forbid-always-trumps-cli.stderr b/tests/ui/lint/forbid-always-trumps-cli.allow-first-group.stderr similarity index 82% rename from tests/ui/lint/group-forbid-always-trumps-cli.stderr rename to tests/ui/lint/forbid-always-trumps-cli.allow-first-group.stderr index ed1242eacfce7..07773ee4ddfea 100644 --- a/tests/ui/lint/group-forbid-always-trumps-cli.stderr +++ b/tests/ui/lint/forbid-always-trumps-cli.allow-first-group.stderr @@ -1,5 +1,5 @@ error: unused variable: `x` - --> $DIR/group-forbid-always-trumps-cli.rs:4:9 + --> $DIR/forbid-always-trumps-cli.rs:15:9 | LL | let x = 1; | ^ help: if this is intentional, prefix it with an underscore: `_x` diff --git a/tests/ui/lint/forbid-always-trumps-cli.allow-first-lint.stderr b/tests/ui/lint/forbid-always-trumps-cli.allow-first-lint.stderr new file mode 100644 index 0000000000000..cf357ef8ca8f9 --- /dev/null +++ b/tests/ui/lint/forbid-always-trumps-cli.allow-first-lint.stderr @@ -0,0 +1,10 @@ +error: unused variable: `x` + --> $DIR/forbid-always-trumps-cli.rs:15:9 + | +LL | let x = 1; + | ^ help: if this is intentional, prefix it with an underscore: `_x` + | + = note: requested on the command line with `-F unused-variables` + +error: aborting due to 1 previous error + diff --git a/tests/ui/lint/forbid-always-trumps-cli.allow-first-mix1.stderr b/tests/ui/lint/forbid-always-trumps-cli.allow-first-mix1.stderr new file mode 100644 index 0000000000000..07773ee4ddfea --- /dev/null +++ b/tests/ui/lint/forbid-always-trumps-cli.allow-first-mix1.stderr @@ -0,0 +1,10 @@ +error: unused variable: `x` + --> $DIR/forbid-always-trumps-cli.rs:15:9 + | +LL | let x = 1; + | ^ help: if this is intentional, prefix it with an underscore: `_x` + | + = note: `-F unused-variables` implied by `-F unused` + +error: aborting due to 1 previous error + diff --git a/tests/ui/lint/forbid-always-trumps-cli.allow-first-mix2.stderr b/tests/ui/lint/forbid-always-trumps-cli.allow-first-mix2.stderr new file mode 100644 index 0000000000000..cf357ef8ca8f9 --- /dev/null +++ b/tests/ui/lint/forbid-always-trumps-cli.allow-first-mix2.stderr @@ -0,0 +1,10 @@ +error: unused variable: `x` + --> $DIR/forbid-always-trumps-cli.rs:15:9 + | +LL | let x = 1; + | ^ help: if this is intentional, prefix it with an underscore: `_x` + | + = note: requested on the command line with `-F unused-variables` + +error: aborting due to 1 previous error + diff --git a/tests/ui/lint/forbid-always-trumps-cli.forbid-first-group.stderr b/tests/ui/lint/forbid-always-trumps-cli.forbid-first-group.stderr new file mode 100644 index 0000000000000..07773ee4ddfea --- /dev/null +++ b/tests/ui/lint/forbid-always-trumps-cli.forbid-first-group.stderr @@ -0,0 +1,10 @@ +error: unused variable: `x` + --> $DIR/forbid-always-trumps-cli.rs:15:9 + | +LL | let x = 1; + | ^ help: if this is intentional, prefix it with an underscore: `_x` + | + = note: `-F unused-variables` implied by `-F unused` + +error: aborting due to 1 previous error + diff --git a/tests/ui/lint/forbid-always-trumps-cli.forbid-first-lint.stderr b/tests/ui/lint/forbid-always-trumps-cli.forbid-first-lint.stderr new file mode 100644 index 0000000000000..cf357ef8ca8f9 --- /dev/null +++ b/tests/ui/lint/forbid-always-trumps-cli.forbid-first-lint.stderr @@ -0,0 +1,10 @@ +error: unused variable: `x` + --> $DIR/forbid-always-trumps-cli.rs:15:9 + | +LL | let x = 1; + | ^ help: if this is intentional, prefix it with an underscore: `_x` + | + = note: requested on the command line with `-F unused-variables` + +error: aborting due to 1 previous error + diff --git a/tests/ui/lint/forbid-always-trumps-cli.forbid-first-mix1.stderr b/tests/ui/lint/forbid-always-trumps-cli.forbid-first-mix1.stderr new file mode 100644 index 0000000000000..07773ee4ddfea --- /dev/null +++ b/tests/ui/lint/forbid-always-trumps-cli.forbid-first-mix1.stderr @@ -0,0 +1,10 @@ +error: unused variable: `x` + --> $DIR/forbid-always-trumps-cli.rs:15:9 + | +LL | let x = 1; + | ^ help: if this is intentional, prefix it with an underscore: `_x` + | + = note: `-F unused-variables` implied by `-F unused` + +error: aborting due to 1 previous error + diff --git a/tests/ui/lint/forbid-always-trumps-cli.forbid-first-mix2.stderr b/tests/ui/lint/forbid-always-trumps-cli.forbid-first-mix2.stderr new file mode 100644 index 0000000000000..cf357ef8ca8f9 --- /dev/null +++ b/tests/ui/lint/forbid-always-trumps-cli.forbid-first-mix2.stderr @@ -0,0 +1,10 @@ +error: unused variable: `x` + --> $DIR/forbid-always-trumps-cli.rs:15:9 + | +LL | let x = 1; + | ^ help: if this is intentional, prefix it with an underscore: `_x` + | + = note: requested on the command line with `-F unused-variables` + +error: aborting due to 1 previous error + diff --git a/tests/ui/lint/forbid-always-trumps-cli.rs b/tests/ui/lint/forbid-always-trumps-cli.rs new file mode 100644 index 0000000000000..d94cc2e8efef9 --- /dev/null +++ b/tests/ui/lint/forbid-always-trumps-cli.rs @@ -0,0 +1,17 @@ +//! Ensure that "forbid" always trumps" allow" in CLI arguments, no matter the order +//! and no matter whether it is used with a lint group vs an individual lint. +// ignore-tidy-linelength +//@ revisions: forbid-first-group allow-first-group forbid-first-lint allow-first-lint forbid-first-mix1 allow-first-mix1 forbid-first-mix2 allow-first-mix2 +//@[forbid-first-group] compile-flags: -F unused -A unused +//@[allow-first-group] compile-flags: -A unused -F unused +//@[forbid-first-lint] compile-flags: -F unused_variables -A unused_variables +//@[allow-first-lint] compile-flags: -A unused_variables -F unused_variables +//@[forbid-first-mix1] compile-flags: -F unused -A unused_variables +//@[allow-first-mix1] compile-flags: -A unused_variables -F unused +//@[forbid-first-mix2] compile-flags: -F unused_variables -A unused +//@[allow-first-mix2] compile-flags: -A unused -F unused_variables + +fn main() { + let x = 1; + //~^ ERROR unused variable: `x` +} diff --git a/tests/ui/lint/group-forbid-always-trumps-cli.rs b/tests/ui/lint/group-forbid-always-trumps-cli.rs deleted file mode 100644 index 4b63452bf5d46..0000000000000 --- a/tests/ui/lint/group-forbid-always-trumps-cli.rs +++ /dev/null @@ -1,6 +0,0 @@ -//@ compile-flags: -F unused -A unused - -fn main() { - let x = 1; - //~^ ERROR unused variable: `x` -} diff --git a/tests/ui/traits/next-solver/non-wf-ret.rs b/tests/ui/traits/next-solver/non-wf-ret.rs new file mode 100644 index 0000000000000..c54d61c895d23 --- /dev/null +++ b/tests/ui/traits/next-solver/non-wf-ret.rs @@ -0,0 +1,47 @@ +//@ check-pass +//@ compile-flags: -Znext-solver + +use std::ops::Deref; + +pub struct List { + skel: [T], +} + +impl<'a, T: Copy> IntoIterator for &'a List { + type Item = T; + type IntoIter = std::iter::Copied<<&'a [T] as IntoIterator>::IntoIter>; + + fn into_iter(self) -> Self::IntoIter { + todo!() + } +} + +impl Deref for List { + type Target = [T]; + + fn deref(&self) -> &[T] { + todo!() + } +} + +impl List { + fn iter(&self) -> <&Self as IntoIterator>::IntoIter + where + T: Copy, + { + todo!() + } +} + +fn test(t: &List) { + // Checking that `<&List as IntoIterator>::IntoIter` is WF + // will disqualify the inherent method, since normalizing it + // requires `Q: Copy` which does not hold. and allow us to fall + // through to the deref'd `<[Q]>::iter` method which works. + // + // In the old solver, the same behavior is achieved by just + // eagerly normalizing the return type. + t.iter(); +} + +fn main() {} diff --git a/tests/ui/traits/next-solver/structurally-normalize-in-borrowck-field-projection.rs b/tests/ui/traits/next-solver/structurally-normalize-in-borrowck-field-projection.rs new file mode 100644 index 0000000000000..d2d68128fde54 --- /dev/null +++ b/tests/ui/traits/next-solver/structurally-normalize-in-borrowck-field-projection.rs @@ -0,0 +1,32 @@ +//@ check-pass +//@ compile-flags: -Znext-solver + +trait Interner: Sized { + type Value; +} + +enum Kind { + Value(I::Value), +} + +struct Intern; + +impl Interner for Intern { + type Value = Wrap; +} + +struct Wrap(T); + +type KindAlias = Kind; + +trait PrettyPrinter: Sized { + fn hello(c: KindAlias) { + match c { + KindAlias::Value(Wrap(v)) => { + println!("{v:?}"); + } + } + } +} + +fn main() {} diff --git a/tests/ui/traits/resolve-impl-before-constrain-check.rs b/tests/ui/traits/resolve-impl-before-constrain-check.rs new file mode 100644 index 0000000000000..87f9c241e402b --- /dev/null +++ b/tests/ui/traits/resolve-impl-before-constrain-check.rs @@ -0,0 +1,20 @@ +// Need a different module so we try to build the mir for `test` +// before analyzing `mod foo`. + +mod foo { + pub trait Callable { + fn call(); + } + + impl Callable for () { + //~^ ERROR the type parameter `V` is not constrained by the impl trait, self type, or predicates + fn call() {} + } +} +use foo::*; + +fn test() -> impl Sized { + <() as Callable>::call() +} + +fn main() {} diff --git a/tests/ui/traits/resolve-impl-before-constrain-check.stderr b/tests/ui/traits/resolve-impl-before-constrain-check.stderr new file mode 100644 index 0000000000000..e8e569ba625ee --- /dev/null +++ b/tests/ui/traits/resolve-impl-before-constrain-check.stderr @@ -0,0 +1,9 @@ +error[E0207]: the type parameter `V` is not constrained by the impl trait, self type, or predicates + --> $DIR/resolve-impl-before-constrain-check.rs:9:10 + | +LL | impl Callable for () { + | ^ unconstrained type parameter + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0207`.