diff --git a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs index 904a8a22e01..2a906e41b8c 100644 --- a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs @@ -142,11 +142,9 @@ fn report_error( let tcx = mbcx.infcx.tcx; let base_universe = self.base_universe(); - let adjusted_universe = if let Some(adjusted) = + let Some(adjusted_universe) = placeholder.universe.as_u32().checked_sub(base_universe.as_u32()) - { - adjusted - } else { + else { mbcx.buffer_error(self.fallback_error(tcx, cause.span)); return; }; diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index 5da2021e711..73b0d398285 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -867,15 +867,14 @@ pub(super) fn move_spans( kind: TerminatorKind::Call { fn_span, from_hir_call, .. }, .. }) = &self.body[location.block].terminator { - let (method_did, method_substs) = if let Some(info) = + let Some((method_did, method_substs)) = rustc_const_eval::util::find_self_call( self.infcx.tcx, &self.body, target_temp, location.block, - ) { - info - } else { + ) + else { return normal_ret; }; diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index 5963904aa0b..7d0dde53c2b 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -639,11 +639,9 @@ fn is_error_in_trait(&self, local: Local) -> (bool, Option) { let hir_map = self.infcx.tcx.hir(); let my_def = self.body.source.def_id(); let my_hir = hir_map.local_def_id_to_hir_id(my_def.as_local().unwrap()); - let td = if let Some(a) = + let Some(td) = self.infcx.tcx.impl_of_method(my_def).and_then(|x| self.infcx.tcx.trait_id_of_impl(x)) - { - a - } else { + else { return (false, None); }; ( diff --git a/compiler/rustc_builtin_macros/src/concat_bytes.rs b/compiler/rustc_builtin_macros/src/concat_bytes.rs index eb08170959b..c06af5206d5 100644 --- a/compiler/rustc_builtin_macros/src/concat_bytes.rs +++ b/compiler/rustc_builtin_macros/src/concat_bytes.rs @@ -6,9 +6,7 @@ /// Emits errors for literal expressions that are invalid inside and outside of an array. fn invalid_type_err(cx: &mut base::ExtCtxt<'_>, expr: &P, is_nested: bool) { - let lit = if let ast::ExprKind::Lit(lit) = &expr.kind { - lit - } else { + let ast::ExprKind::Lit(lit) = &expr.kind else { unreachable!(); }; match lit.kind { diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs index 0289acac606..38877399943 100644 --- a/compiler/rustc_builtin_macros/src/lib.rs +++ b/compiler/rustc_builtin_macros/src/lib.rs @@ -9,6 +9,7 @@ #![feature(decl_macro)] #![feature(is_sorted)] #![feature(nll)] +#![feature(let_else)] #![feature(proc_macro_internals)] #![feature(proc_macro_quote)] #![recursion_limit = "256"] diff --git a/compiler/rustc_codegen_llvm/src/type_of.rs b/compiler/rustc_codegen_llvm/src/type_of.rs index 81d0603bc52..fafb9a6dbde 100644 --- a/compiler/rustc_codegen_llvm/src/type_of.rs +++ b/compiler/rustc_codegen_llvm/src/type_of.rs @@ -330,7 +330,9 @@ fn scalar_pair_element_llvm_type<'a>( ty::Ref(..) | ty::RawPtr(_) => { return self.field(cx, index).llvm_type(cx); } - ty::Adt(def, _) if def.is_box() => { + // only wide pointer boxes are handled as pointers + // thin pointer boxes with scalar allocators are handled by the general logic below + ty::Adt(def, substs) if def.is_box() && cx.layout_of(substs.type_at(1)).is_zst() => { let ptr_ty = cx.tcx.mk_mut_ptr(self.ty.boxed_ty()); return cx.layout_of(ptr_ty).scalar_pair_element_llvm_type(cx, index, immediate); } diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index e53c9842117..58e0667d678 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -216,17 +216,18 @@ pub fn each_linked_rlib( } let name = &info.crate_name[&cnum]; let used_crate_source = &info.used_crate_source[&cnum]; - let path = if let Some((path, _)) = &used_crate_source.rlib { - path - } else if used_crate_source.rmeta.is_some() { - return Err(format!( - "could not find rlib for: `{}`, found rmeta (metadata) file", - name - )); + if let Some((path, _)) = &used_crate_source.rlib { + f(cnum, &path); } else { - return Err(format!("could not find rlib for: `{}`", name)); - }; - f(cnum, &path); + if used_crate_source.rmeta.is_some() { + return Err(format!( + "could not find rlib for: `{}`, found rmeta (metadata) file", + name + )); + } else { + return Err(format!("could not find rlib for: `{}`", name)); + } + } } Ok(()) } diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs index 6849533abc0..9ebbcac76a2 100644 --- a/compiler/rustc_codegen_ssa/src/back/metadata.rs +++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs @@ -200,9 +200,7 @@ fn create_object_file(sess: &Session) -> Option> { // `SHF_EXCLUDE` flag we can set on sections in an object file to get // automatically removed from the final output. pub fn create_rmeta_file(sess: &Session, metadata: &[u8]) -> Vec { - let mut file = if let Some(file) = create_object_file(sess) { - file - } else { + let Some(mut file) = create_object_file(sess) else { // This is used to handle all "other" targets. This includes targets // in two categories: // @@ -262,9 +260,7 @@ pub fn create_compressed_metadata_file( ) -> Vec { let mut compressed = rustc_metadata::METADATA_HEADER.to_vec(); FrameEncoder::new(&mut compressed).write_all(metadata.raw_data()).unwrap(); - let mut file = if let Some(file) = create_object_file(sess) { - file - } else { + let Some(mut file) = create_object_file(sess) else { return compressed.to_vec(); }; let section = file.add_section( diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index 3c85ff77cfb..9cb12778a56 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -285,13 +285,13 @@ pub fn set(&self, features: &mut Features, span: Span) { /// Allows trait methods with arbitrary self types. (active, arbitrary_self_types, "1.23.0", Some(44874), None), /// Allows using `const` operands in inline assembly. - (active, asm_const, "1.58.0", Some(72016), None), + (active, asm_const, "1.58.0", Some(93332), None), /// Enables experimental inline assembly support for additional architectures. - (active, asm_experimental_arch, "1.58.0", Some(72016), None), + (active, asm_experimental_arch, "1.58.0", Some(93335), None), /// Allows using `sym` operands in inline assembly. - (active, asm_sym, "1.58.0", Some(72016), None), + (active, asm_sym, "1.58.0", Some(93333), None), /// Allows the `may_unwind` option in inline assembly. - (active, asm_unwind, "1.58.0", Some(72016), None), + (active, asm_unwind, "1.58.0", Some(93334), None), /// Allows users to enforce equality of associated constants `TraitImpl`. (active, associated_const_equality, "1.58.0", Some(92827), None), /// Allows the user of associated type bounds. diff --git a/compiler/rustc_index/src/bit_set.rs b/compiler/rustc_index/src/bit_set.rs index cf86c450a5b..7f376c5fbe5 100644 --- a/compiler/rustc_index/src/bit_set.rs +++ b/compiler/rustc_index/src/bit_set.rs @@ -852,11 +852,7 @@ pub fn insert_range(&mut self, elems: impl RangeBounds) { Bound::Excluded(end) => end.index(), Bound::Unbounded => self.domain_size() - 1, }; - let len = if let Some(l) = end.checked_sub(start) { - l - } else { - return; - }; + let Some(len) = end.checked_sub(start) else { return }; match self { HybridBitSet::Sparse(sparse) if sparse.len() + len < SPARSE_MAX => { // The set is sparse and has space for `elems`. diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs index aba5666b58c..a61100d907b 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs @@ -553,8 +553,7 @@ pub fn emit_inference_failure_err( let ty_msg = match (local_visitor.found_node_ty, local_visitor.found_exact_method_call) { (_, Some(_)) => String::new(), (Some(ty), _) if ty.is_closure() => { - let substs = - if let ty::Closure(_, substs) = *ty.kind() { substs } else { unreachable!() }; + let ty::Closure(_, substs) = *ty.kind() else { unreachable!() }; let fn_sig = substs.as_closure().sig(); let args = closure_args(&fn_sig); let ret = fn_sig.output().skip_binder().to_string(); @@ -597,8 +596,7 @@ pub fn emit_inference_failure_err( let param_type = arg_data.kind.descr(); let suffix = match local_visitor.found_node_ty { Some(ty) if ty.is_closure() => { - let substs = - if let ty::Closure(_, substs) = *ty.kind() { substs } else { unreachable!() }; + let ty::Closure(_, substs) = *ty.kind() else { unreachable!() }; let fn_sig = substs.as_closure().sig(); let ret = fn_sig.output().skip_binder().to_string(); diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 4d6b97eff24..4dea04e62ff 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -982,7 +982,7 @@ fn encode_def_ids(&mut self) { for local_id in hir.iter_local_def_id() { let def_id = local_id.to_def_id(); let def_kind = tcx.opt_def_kind(local_id); - let def_kind = if let Some(def_kind) = def_kind { def_kind } else { continue }; + let Some(def_kind) = def_kind else { continue }; record!(self.tables.def_kind[def_id] <- match def_kind { // Replace Ctor by the enclosing object to avoid leaking details in children crates. DefKind::Ctor(CtorOf::Struct, _) => DefKind::Struct, diff --git a/compiler/rustc_middle/src/dep_graph/mod.rs b/compiler/rustc_middle/src/dep_graph/mod.rs index cf50378ad60..6bfd1b7ffab 100644 --- a/compiler/rustc_middle/src/dep_graph/mod.rs +++ b/compiler/rustc_middle/src/dep_graph/mod.rs @@ -61,7 +61,7 @@ fn read_deps(op: OP) OP: for<'a> FnOnce(TaskDepsRef<'a>), { ty::tls::with_context_opt(|icx| { - let icx = if let Some(icx) = icx { icx } else { return }; + let Some(icx) = icx else { return }; op(icx.task_deps) }) } diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs index b3006672e22..4922d07ae1c 100644 --- a/compiler/rustc_middle/src/ty/fold.rs +++ b/compiler/rustc_middle/src/ty/fold.rs @@ -1,38 +1,56 @@ -//! Generalized type folding mechanism. The setup is a bit convoluted -//! but allows for convenient usage. Let T be an instance of some -//! "foldable type" (one which implements `TypeFoldable`) and F be an -//! instance of a "folder" (a type which implements `TypeFolder`). Then -//! the setup is intended to be: +//! A generalized traversal mechanism for complex data structures that contain +//! type information. //! -//! T.fold_with(F) --calls--> F.fold_T(T) --calls--> T.super_fold_with(F) +//! There are two types of traversal. +//! - Folding. This is a modifying traversal. It consumes the data structure, +//! producing a (possibly) modified version of it. Both fallible and +//! infallible versions are available. The name is potentially +//! confusing, because this traversal is more like `Iterator::map` than +//! `Iterator::fold`. +//! - Visiting. This is a read-only traversal of the data structure. //! -//! This way, when you define a new folder F, you can override -//! `fold_T()` to customize the behavior, and invoke `T.super_fold_with()` -//! to get the original behavior. Meanwhile, to actually fold -//! something, you can just write `T.fold_with(F)`, which is -//! convenient. (Note that `fold_with` will also transparently handle -//! things like a `Vec` where T is foldable and so on.) +//! These traversals have limited flexibility. Only a small number of "types of +//! interest" within the complex data structures can receive custom +//! modification (when folding) or custom visitation (when visiting). These are +//! the ones containing the most important type-related information, such as +//! `Ty`, `Predicate`, `Region`, and `Const`. //! -//! In this ideal setup, the only function that actually *does* -//! anything is `T.super_fold_with()`, which traverses the type `T`. -//! Moreover, `T.super_fold_with()` should only ever call `T.fold_with()`. +//! There are two traits involved in each traversal type. +//! - The first trait is `TypeFoldable`, which is implemented once for many +//! types. This includes both (a) types of interest, and (b) all other +//! relevant types, including generic containers like `Vec` and `Option`. It +//! defines a "skeleton" of how they should be traversed, for both folding +//! and visiting. +//! - The second trait is `TypeFolder`/`FallibleTypeFolder` (for +//! infallible/fallible folding traversals) or `TypeVisitor` (for visiting +//! traversals). One of these is implemented for each folder/visitor. This +//! defines how types of interest are handled. //! -//! In some cases, we follow a degenerate pattern where we do not have -//! a `fold_T` method. Instead, `T.fold_with` traverses the structure directly. -//! This is suboptimal because the behavior cannot be overridden, but it's -//! much less work to implement. If you ever *do* need an override that -//! doesn't exist, it's not hard to convert the degenerate pattern into the -//! proper thing. +//! This means each traversal is a mixture of (a) generic traversal operations, +//! and (b) custom fold/visit operations that are specific to the +//! folder/visitor. +//! - The `TypeFoldable` impls handle most of the traversal, and call into +//! `TypeFolder`/`FallibleTypeFolder`/`TypeVisitor` when they encounter a +//! type of interest. +//! - A `TypeFolder`/`FallibleTypeFolder`/`TypeVisitor` may also call back into +//! a `TypeFoldable` impl, because (a) the types of interest are recursive +//! and can contain other types of interest, and (b) each folder/visitor +//! might provide custom handling only for some types of interest, or only +//! for some variants of each type of interest, and then use default +//! traversal for the remaining cases. //! -//! A `TypeFoldable` T can also be visited by a `TypeVisitor` V using similar setup: -//! -//! T.visit_with(V) --calls--> V.visit_T(T) --calls--> T.super_visit_with(V). -//! -//! These methods return true to indicate that the visitor has found what it is -//! looking for, and does not need to visit anything else. +//! For example, if you have `struct S(Ty, U)` where `S: TypeFoldable` and `U: +//! TypeFoldable`, and an instance `S(ty, u)`, it would be visited like so: +//! ``` +//! s.visit_with(visitor) calls +//! - s.super_visit_with(visitor) calls +//! - ty.visit_with(visitor) calls +//! - visitor.visit_ty(ty) may call +//! - ty.super_visit_with(visitor) +//! - u.visit_with(visitor) +//! ``` use crate::mir; use crate::ty::{self, flags::FlagComputation, Binder, Ty, TyCtxt, TypeFlags}; -use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_data_structures::fx::FxHashSet; @@ -41,42 +59,67 @@ use std::fmt; use std::ops::ControlFlow; -/// This trait is implemented for every type that can be folded. -/// Basically, every type that has a corresponding method in `TypeFolder`. +/// This trait is implemented for every type that can be folded/visited, +/// providing the skeleton of the traversal. /// -/// To implement this conveniently, use the derive macro located in `rustc_macros`. +/// To implement this conveniently, use the derive macro located in +/// `rustc_macros`. pub trait TypeFoldable<'tcx>: fmt::Debug + Clone { - /// Consumers may find this more convenient to use with infallible folders than - /// [`try_super_fold_with`][`TypeFoldable::try_super_fold_with`], to which the - /// provided default definition delegates. Implementors **should not** override - /// this provided default definition, to ensure that the two methods are coherent - /// (provide a definition of `try_super_fold_with` instead). - fn super_fold_with>(self, folder: &mut F) -> Self { - self.try_super_fold_with(folder).into_ok() + /// The main entry point for folding. To fold a value `t` with a folder `f` + /// call: `t.try_fold_with(f)`. + /// + /// For types of interest (such as `Ty`), this default is overridden with a + /// method that calls a folder method specifically for that type (such as + /// `F::try_fold_ty`). This is where control transfers from `TypeFoldable` + /// to `TypeFolder`. + /// + /// For other types, this default is used. + fn try_fold_with>(self, folder: &mut F) -> Result { + self.try_super_fold_with(folder) } - /// Consumers may find this more convenient to use with infallible folders than - /// [`try_fold_with`][`TypeFoldable::try_fold_with`], to which the provided - /// default definition delegates. Implementors **should not** override this - /// provided default definition, to ensure that the two methods are coherent - /// (provide a definition of `try_fold_with` instead). + + /// A convenient alternative to `try_fold_with` for use with infallible + /// folders. Do not override this method, to ensure coherence with + /// `try_fold_with`. fn fold_with>(self, folder: &mut F) -> Self { self.try_fold_with(folder).into_ok() } + /// Traverses the type in question, typically by calling `try_fold_with` on + /// each field/element. This is true even for types of interest such as + /// `Ty`. This should only be called within `TypeFolder` methods, when + /// non-custom traversals are desired for types of interest. fn try_super_fold_with>( self, folder: &mut F, ) -> Result; - fn try_fold_with>(self, folder: &mut F) -> Result { - self.try_super_fold_with(folder) + /// A convenient alternative to `try_super_fold_with` for use with + /// infallible folders. Do not override this method, to ensure coherence + /// with `try_super_fold_with`. + fn super_fold_with>(self, folder: &mut F) -> Self { + self.try_super_fold_with(folder).into_ok() } - fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow; + /// The entry point for visiting. To visit a value `t` with a visitor `v` + /// call: `t.visit_with(v)`. + /// + /// For types of interest (such as `Ty`), this default is overridden with a + /// method that calls a visitor method specifically for that type (such as + /// `V::visit_ty`). This is where control transfers from `TypeFoldable` to + /// `TypeVisitor`. + /// + /// For other types, this default is used. fn visit_with>(&self, visitor: &mut V) -> ControlFlow { self.super_visit_with(visitor) } + /// Traverses the type in question, typically by calling `visit_with` on + /// each field/element. This is true even for types of interest such as + /// `Ty`. This should only be called within `TypeVisitor` methods, when + /// non-custom traversals are desired for types of interest. + fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow; + /// Returns `true` if `self` has any late-bound regions that are either /// bound by `binder` or bound by some binder outside of `binder`. /// If `binder` is `ty::INNERMOST`, this indicates whether @@ -168,24 +211,13 @@ fn still_further_specializable(&self) -> bool { } } -impl<'tcx> TypeFoldable<'tcx> for hir::Constness { - fn try_super_fold_with>(self, _: &mut F) -> Result { - Ok(self) - } - fn super_visit_with>(&self, _: &mut V) -> ControlFlow { - ControlFlow::CONTINUE - } -} - -/// The `TypeFolder` trait defines the actual *folding*. There is a -/// method defined for every foldable type. Each of these has a -/// default implementation that does an "identity" fold. Within each -/// identity fold, it should invoke `foo.fold_with(self)` to fold each -/// sub-item. +/// This trait is implemented for every folding traversal. There is a fold +/// method defined for every type of interest. Each such method has a default +/// that does an "identity" fold. /// /// If this folder is fallible (and therefore its [`Error`][`TypeFolder::Error`] -/// associated type is something other than the default, never), -/// [`FallibleTypeFolder`] should be implemented manually; otherwise, +/// associated type is something other than the default `!`) then +/// [`FallibleTypeFolder`] should be implemented manually. Otherwise, /// a blanket implementation of [`FallibleTypeFolder`] will defer to /// the infallible methods of this trait to ensure that the two APIs /// are coherent. @@ -238,11 +270,9 @@ fn fold_mir_const(&mut self, c: mir::ConstantKind<'tcx>) -> mir::ConstantKind<'t } } -/// The `FallibleTypeFolder` trait defines the actual *folding*. There is a -/// method defined for every foldable type. Each of these has a -/// default implementation that does an "identity" fold. Within each -/// identity fold, it should invoke `foo.try_fold_with(self)` to fold each -/// sub-item. +/// This trait is implemented for every folding traversal. There is a fold +/// method defined for every type of interest. Each such method has a default +/// that does an "identity" fold. /// /// A blanket implementation of this trait (that defers to the relevant /// method of [`TypeFolder`]) is provided for all infallible folders in @@ -282,8 +312,8 @@ fn try_fold_mir_const( } } -// Blanket implementation of fallible trait for infallible folders -// delegates to infallible methods to prevent incoherence +// This blanket implementation of the fallible trait for infallible folders +// delegates to infallible methods to ensure coherence. impl<'tcx, F> FallibleTypeFolder<'tcx> for F where F: TypeFolder<'tcx, Error = !>, @@ -322,6 +352,9 @@ fn try_fold_mir_const( } } +/// This trait is implemented for every visiting traversal. There is a visit +/// method defined for every type of interest. Each such method has a default +/// that recurses into the type's fields in a non-custom fashion. pub trait TypeVisitor<'tcx>: Sized { type BreakTy = !; diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index c1d714ed8d6..e4691dee779 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -8,6 +8,7 @@ use crate::ty::print::{with_no_trimmed_paths, FmtPrinter, Printer}; use crate::ty::{self, InferConst, Lift, Term, Ty, TyCtxt}; use rustc_data_structures::functor::IdFunctor; +use rustc_hir as hir; use rustc_hir::def::Namespace; use rustc_hir::def_id::CRATE_DEF_INDEX; use rustc_index::vec::{Idx, IndexVec}; @@ -663,14 +664,6 @@ fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option { /////////////////////////////////////////////////////////////////////////// // TypeFoldable implementations. -// -// Ideally, each type should invoke `folder.fold_foo(self)` and -// nothing else. In some cases, though, we haven't gotten around to -// adding methods on the `folder` yet, and thus the folding is -// hard-coded here. This is less-flexible, because folders cannot -// override the behavior, but there are a lot of random types and one -// can easily refactor the folding into the TypeFolder trait as -// needed. /// AdtDefs are basically the same as a DefId. impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::AdtDef { @@ -1270,3 +1263,13 @@ fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow self.substs.visit_with(visitor) } } + +impl<'tcx> TypeFoldable<'tcx> for hir::Constness { + fn try_super_fold_with>(self, _: &mut F) -> Result { + Ok(self) + } + + fn super_visit_with>(&self, _: &mut V) -> ControlFlow { + ControlFlow::CONTINUE + } +} diff --git a/compiler/rustc_mir_transform/src/generator.rs b/compiler/rustc_mir_transform/src/generator.rs index 433a1c6ad67..05de52458ad 100644 --- a/compiler/rustc_mir_transform/src/generator.rs +++ b/compiler/rustc_mir_transform/src/generator.rs @@ -1241,9 +1241,7 @@ fn phase_change(&self) -> Option { } fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - let yield_ty = if let Some(yield_ty) = body.yield_ty() { - yield_ty - } else { + let Some(yield_ty) = body.yield_ty() else { // This only applies to generators return; }; diff --git a/compiler/rustc_mir_transform/src/normalize_array_len.rs b/compiler/rustc_mir_transform/src/normalize_array_len.rs index 0392c5a5468..cdfd49ef478 100644 --- a/compiler/rustc_mir_transform/src/normalize_array_len.rs +++ b/compiler/rustc_mir_transform/src/normalize_array_len.rs @@ -212,12 +212,7 @@ fn normalize_array_len_call<'tcx>( let Some(local) = place.as_local() else { return }; match operand { Operand::Copy(place) | Operand::Move(place) => { - let operand_local = - if let Some(local) = place.local_or_deref_local() { - local - } else { - return; - }; + let Some(operand_local) = place.local_or_deref_local() else { return; }; if !interesting_locals.contains(operand_local) { return; } diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 8a1fe6e91cb..72c1b3fa6e9 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -947,9 +947,7 @@ fn visit_instance_use<'tcx>( /// Returns `true` if we should codegen an instance in the local crate, or returns `false` if we /// can just link to the upstream crate and therefore don't need a mono item. fn should_codegen_locally<'tcx>(tcx: TyCtxt<'tcx>, instance: &Instance<'tcx>) -> bool { - let def_id = if let Some(def_id) = instance.def.def_id_if_not_guaranteed_local_codegen() { - def_id - } else { + let Some(def_id) = instance.def.def_id_if_not_guaranteed_local_codegen() else { return true; }; diff --git a/compiler/rustc_monomorphize/src/util.rs b/compiler/rustc_monomorphize/src/util.rs index 27540395c07..04baa01832b 100644 --- a/compiler/rustc_monomorphize/src/util.rs +++ b/compiler/rustc_monomorphize/src/util.rs @@ -8,13 +8,11 @@ /// During the same compile all closures dump the information in the same file /// "closure_profile_XXXXX.csv", which is created in the directory where the compiler is invoked. crate fn dump_closure_profile<'tcx>(tcx: TyCtxt<'tcx>, closure_instance: Instance<'tcx>) { - let mut file = if let Ok(file) = OpenOptions::new() + let Ok(mut file) = OpenOptions::new() .create(true) .append(true) .open(&format!("closure_profile_{}.csv", std::process::id())) - { - file - } else { + else { eprintln!("Cound't open file for writing closure profile"); return; }; diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index 1a620968d56..4cdd83c0acd 100644 --- a/compiler/rustc_parse/src/lexer/mod.rs +++ b/compiler/rustc_parse/src/lexer/mod.rs @@ -158,9 +158,7 @@ fn cook_lexer_token(&self, token: rustc_lexer::TokenKind, start: BytePos) -> Opt Some(match token { rustc_lexer::TokenKind::LineComment { doc_style } => { // Skip non-doc comments - let doc_style = if let Some(doc_style) = doc_style { - doc_style - } else { + let Some(doc_style) = doc_style else { self.lint_unicode_text_flow(start); return None; }; @@ -185,9 +183,7 @@ fn cook_lexer_token(&self, token: rustc_lexer::TokenKind, start: BytePos) -> Opt } // Skip non-doc comments - let doc_style = if let Some(doc_style) = doc_style { - doc_style - } else { + let Some(doc_style) = doc_style else { self.lint_unicode_text_flow(start); return None; }; diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs index 2b1b2f3fce4..eb0d1a12c77 100644 --- a/compiler/rustc_parse/src/lib.rs +++ b/compiler/rustc_parse/src/lib.rs @@ -4,6 +4,7 @@ #![feature(crate_visibility_modifier)] #![feature(if_let_guard)] #![feature(box_patterns)] +#![feature(let_else)] #![recursion_limit = "256"] #[macro_use] diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 5d843b46ee2..f9926a71c30 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -704,7 +704,7 @@ fn restrict_assoc_type_in_where_clause( ) = &bounded_ty.kind { // use this to verify that ident is a type param. - let partial_res = if let Ok(Some(partial_res)) = self.resolve_qpath_anywhere( + let Ok(Some(partial_res)) = self.resolve_qpath_anywhere( bounded_ty.id, None, &Segment::from_path(path), @@ -712,9 +712,7 @@ fn restrict_assoc_type_in_where_clause( span, true, CrateLint::No, - ) { - partial_res - } else { + ) else { return false; }; if !(matches!( @@ -731,7 +729,7 @@ fn restrict_assoc_type_in_where_clause( if let ast::TyKind::Path(None, type_param_path) = &ty.peel_refs().kind { // Confirm that the `SelfTy` is a type parameter. - let partial_res = if let Ok(Some(partial_res)) = self.resolve_qpath_anywhere( + let Ok(Some(partial_res)) = self.resolve_qpath_anywhere( bounded_ty.id, None, &Segment::from_path(type_param_path), @@ -739,9 +737,7 @@ fn restrict_assoc_type_in_where_clause( span, true, CrateLint::No, - ) { - partial_res - } else { + ) else { return false; }; if !(matches!( diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 40cb9647a35..6d1b6e5ac84 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -1099,9 +1099,7 @@ fn suggest_impl_trait( _ => return false, }; - let ret_ty = if let hir::FnRetTy::Return(ret_ty) = sig.decl.output { - ret_ty - } else { + let hir::FnRetTy::Return(ret_ty) = sig.decl.output else { return false; }; @@ -1168,7 +1166,7 @@ fn suggest_impl_trait( }; let sm = self.tcx.sess.source_map(); - let snippet = if let (true, hir::TyKind::TraitObject(..), Ok(snippet), true) = ( + let (true, hir::TyKind::TraitObject(..), Ok(snippet), true) = ( // Verify that we're dealing with a return `dyn Trait` ret_ty.span.overlaps(span), &ret_ty.kind, @@ -1176,9 +1174,7 @@ fn suggest_impl_trait( // If any of the return types does not conform to the trait, then we can't // suggest `impl Trait` nor trait objects: it is a type mismatch error. all_returns_conform_to_trait, - ) { - snippet - } else { + ) else { return false; }; err.code(error_code!(E0746)); diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs index b5f13703edf..4869d193d80 100644 --- a/compiler/rustc_typeck/src/check/expr.rs +++ b/compiler/rustc_typeck/src/check/expr.rs @@ -1318,10 +1318,7 @@ fn check_expr_struct( base_expr: &'tcx Option<&'tcx hir::Expr<'tcx>>, ) -> Ty<'tcx> { // Find the relevant variant - let (variant, adt_ty) = if let Some(variant_ty) = self.check_struct_path(qpath, expr.hir_id) - { - variant_ty - } else { + let Some((variant, adt_ty)) = self.check_struct_path(qpath, expr.hir_id) else { self.check_struct_fields_on_error(fields, base_expr); return self.tcx.ty_error(); }; diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index a8fe5f59bae..5a361edecd9 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -1,6 +1,7 @@ use crate::cmp::{self, Ordering}; use crate::ops::{ChangeOutputType, ControlFlow, FromResidual, Residual, Try}; +use super::super::try_process; use super::super::TrustedRandomAccessNoCoerce; use super::super::{Chain, Cloned, Copied, Cycle, Enumerate, Filter, FilterMap, Fuse}; use super::super::{FlatMap, Flatten}; @@ -1777,6 +1778,87 @@ fn collect>(self) -> B FromIterator::from_iter(self) } + /// Fallibly transforms an iterator into a collection, short circuiting if + /// a failure is encountered. + /// + /// `try_collect()` is a variation of [`collect()`][`collect`] that allows fallible + /// conversions during collection. Its main use case is simplifying conversions from + /// iterators yielding [`Option`][`Option`] into `Option>`, or similarly for other [`Try`] + /// types (e.g. [`Result`]). + /// + /// Importantly, `try_collect()` doesn't require that the outer [`Try`] type also implements [`FromIterator`]; + /// only the inner type produced on `Try::Output` must implement it. Concretely, + /// this means that collecting into `ControlFlow<_, Vec>` is valid because `Vec` implements + /// [`FromIterator`], even though [`ControlFlow`] doesn't. + /// + /// Also, if a failure is encountered during `try_collect()`, the iterator is still valid and + /// may continue to be used, in which case it will continue iterating starting after the element that + /// triggered the failure. See the last example below for an example of how this works. + /// + /// # Examples + /// Successfully collecting an iterator of `Option` into `Option>`: + /// ``` + /// #![feature(iterator_try_collect)] + /// + /// let u = vec![Some(1), Some(2), Some(3)]; + /// let v = u.into_iter().try_collect::>(); + /// assert_eq!(v, Some(vec![1, 2, 3])); + /// ``` + /// + /// Failing to collect in the same way: + /// ``` + /// #![feature(iterator_try_collect)] + /// + /// let u = vec![Some(1), Some(2), None, Some(3)]; + /// let v = u.into_iter().try_collect::>(); + /// assert_eq!(v, None); + /// ``` + /// + /// A similar example, but with `Result`: + /// ``` + /// #![feature(iterator_try_collect)] + /// + /// let u: Vec> = vec![Ok(1), Ok(2), Ok(3)]; + /// let v = u.into_iter().try_collect::>(); + /// assert_eq!(v, Ok(vec![1, 2, 3])); + /// + /// let u = vec![Ok(1), Ok(2), Err(()), Ok(3)]; + /// let v = u.into_iter().try_collect::>(); + /// assert_eq!(v, Err(())); + /// ``` + /// + /// Finally, even [`ControlFlow`] works, despite the fact that it + /// doesn't implement [`FromIterator`]. Note also that the iterator can + /// continue to be used, even if a failure is encountered: + /// + /// ``` + /// #![feature(iterator_try_collect)] + /// + /// use core::ops::ControlFlow::{Break, Continue}; + /// + /// let u = [Continue(1), Continue(2), Break(3), Continue(4), Continue(5)]; + /// let mut it = u.into_iter(); + /// + /// let v = it.try_collect::>(); + /// assert_eq!(v, Break(3)); + /// + /// let v = it.try_collect::>(); + /// assert_eq!(v, Continue(vec![4, 5])); + /// ``` + /// + /// [`collect`]: Iterator::collect + #[inline] + #[unstable(feature = "iterator_try_collect", issue = "94047")] + fn try_collect(&mut self) -> ChangeOutputType + where + Self: Sized, + ::Item: Try, + <::Item as Try>::Residual: Residual, + B: FromIterator<::Output>, + { + try_process(self, |i| i.collect()) + } + /// Consumes an iterator, creating two collections from it. /// /// The predicate passed to `partition()` can return `true`, or `false`. diff --git a/library/core/tests/iter/traits/iterator.rs b/library/core/tests/iter/traits/iterator.rs index 972d61ba909..cf69f0a7a4d 100644 --- a/library/core/tests/iter/traits/iterator.rs +++ b/library/core/tests/iter/traits/iterator.rs @@ -497,6 +497,52 @@ fn test_collect() { assert!(a == b); } +#[test] +fn test_try_collect() { + use core::ops::ControlFlow::{Break, Continue}; + + let u = vec![Some(1), Some(2), Some(3)]; + let v = u.into_iter().try_collect::>(); + assert_eq!(v, Some(vec![1, 2, 3])); + + let u = vec![Some(1), Some(2), None, Some(3)]; + let mut it = u.into_iter(); + let v = it.try_collect::>(); + assert_eq!(v, None); + let v = it.try_collect::>(); + assert_eq!(v, Some(vec![3])); + + let u: Vec> = vec![Ok(1), Ok(2), Ok(3)]; + let v = u.into_iter().try_collect::>(); + assert_eq!(v, Ok(vec![1, 2, 3])); + + let u = vec![Ok(1), Ok(2), Err(()), Ok(3)]; + let v = u.into_iter().try_collect::>(); + assert_eq!(v, Err(())); + + let numbers = vec![1, 2, 3, 4, 5]; + let all_positive = numbers + .iter() + .cloned() + .map(|n| if n > 0 { Some(n) } else { None }) + .try_collect::>(); + assert_eq!(all_positive, Some(numbers)); + + let numbers = vec![-2, -1, 0, 1, 2]; + let all_positive = + numbers.into_iter().map(|n| if n > 0 { Some(n) } else { None }).try_collect::>(); + assert_eq!(all_positive, None); + + let u = [Continue(1), Continue(2), Break(3), Continue(4), Continue(5)]; + let mut it = u.into_iter(); + + let v = it.try_collect::>(); + assert_eq!(v, Break(3)); + + let v = it.try_collect::>(); + assert_eq!(v, Continue(vec![4, 5])); +} + // just tests by whether or not this compiles fn _empty_impl_all_auto_traits() { use std::panic::{RefUnwindSafe, UnwindSafe}; diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index 65be0c320c2..32f3405243c 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -67,6 +67,7 @@ #![feature(iter_intersperse)] #![feature(iter_is_partitioned)] #![feature(iter_order_by)] +#![feature(iterator_try_collect)] #![feature(iterator_try_reduce)] #![feature(const_mut_refs)] #![feature(const_pin)] diff --git a/library/std/src/path.rs b/library/std/src/path.rs index adb8b30ec08..e544608f83c 100644 --- a/library/std/src/path.rs +++ b/library/std/src/path.rs @@ -268,6 +268,12 @@ pub fn is_separator(c: char) -> bool { #[stable(feature = "rust1", since = "1.0.0")] pub const MAIN_SEPARATOR: char = crate::sys::path::MAIN_SEP; +/// The primary separator of path components for the current platform. +/// +/// For example, `/` on Unix and `\` on Windows. +#[unstable(feature = "main_separator_str", issue = "94071")] +pub const MAIN_SEPARATOR_STR: &str = crate::sys::path::MAIN_SEP_STR; + //////////////////////////////////////////////////////////////////////////////// // Misc helpers //////////////////////////////////////////////////////////////////////////////// diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 013687ce377..029049d5434 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -1877,12 +1877,6 @@ fn add_env(builder: &Builder<'_>, cmd: &mut Command, target: TargetSelection) { } else { cmd.env("CFG_MINGW", "0").env("CFG_ABI", "MSVC"); } - - if target.contains("x86_64") { - cmd.env("CFG_PLATFORM", "x64"); - } else { - cmd.env("CFG_PLATFORM", "x86"); - } } /// Maybe add LLVM object files to the given destination lib-dir. Allows either static or dynamic linking. diff --git a/src/doc/unstable-book/src/language-features/asm-const.md b/src/doc/unstable-book/src/language-features/asm-const.md index 1063c23b6df..670c4df414f 100644 --- a/src/doc/unstable-book/src/language-features/asm-const.md +++ b/src/doc/unstable-book/src/language-features/asm-const.md @@ -1,8 +1,8 @@ # `asm_const` -The tracking issue for this feature is: [#72016] +The tracking issue for this feature is: [#93332] -[#72016]: https://github.com/rust-lang/rust/issues/72016 +[#93332]: https://github.com/rust-lang/rust/issues/93332 ------------------------ diff --git a/src/doc/unstable-book/src/language-features/asm-experimental-arch.md b/src/doc/unstable-book/src/language-features/asm-experimental-arch.md index 37fd67447c1..0a48eb4f81a 100644 --- a/src/doc/unstable-book/src/language-features/asm-experimental-arch.md +++ b/src/doc/unstable-book/src/language-features/asm-experimental-arch.md @@ -1,8 +1,8 @@ # `asm_experimental_arch` -The tracking issue for this feature is: [#72016] +The tracking issue for this feature is: [#93335] -[#72016]: https://github.com/rust-lang/rust/issues/72016 +[#93335]: https://github.com/rust-lang/rust/issues/93335 ------------------------ diff --git a/src/doc/unstable-book/src/language-features/asm-sym.md b/src/doc/unstable-book/src/language-features/asm-sym.md index 7544e20807e..103d91caf4c 100644 --- a/src/doc/unstable-book/src/language-features/asm-sym.md +++ b/src/doc/unstable-book/src/language-features/asm-sym.md @@ -1,8 +1,8 @@ # `asm_sym` -The tracking issue for this feature is: [#72016] +The tracking issue for this feature is: [#93333] -[#72016]: https://github.com/rust-lang/rust/issues/72016 +[#93333]: https://github.com/rust-lang/rust/issues/93333 ------------------------ diff --git a/src/doc/unstable-book/src/language-features/asm-unwind.md b/src/doc/unstable-book/src/language-features/asm-unwind.md index 414193fe801..809e6d75b35 100644 --- a/src/doc/unstable-book/src/language-features/asm-unwind.md +++ b/src/doc/unstable-book/src/language-features/asm-unwind.md @@ -1,8 +1,8 @@ # `asm_unwind` -The tracking issue for this feature is: [#72016] +The tracking issue for this feature is: [#93334] -[#72016]: https://github.com/rust-lang/rust/issues/72016 +[#93334]: https://github.com/rust-lang/rust/issues/93334 ------------------------ diff --git a/src/librustdoc/clean/simplify.rs b/src/librustdoc/clean/simplify.rs index 0bad1532808..ea18d915deb 100644 --- a/src/librustdoc/clean/simplify.rs +++ b/src/librustdoc/clean/simplify.rs @@ -51,9 +51,7 @@ // Look for equality predicates on associated types that can be merged into // general bound predicates equalities.retain(|&(ref lhs, ref rhs)| { - let (self_, trait_did, name) = if let Some(p) = lhs.projection() { - p - } else { + let Some((self_, trait_did, name)) = lhs.projection() else { return true; }; let generic = match self_ { diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index 1c0448828a2..7061a9674e4 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -236,9 +236,7 @@ fn next(&mut self) -> Option { let should_panic; let ignore; let edition; - let kind = if let Some(Event::Start(Tag::CodeBlock(kind))) = event { - kind - } else { + let Some(Event::Start(Tag::CodeBlock(kind))) = event else { return event; }; diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 1c3f9b56b47..3e3302f8f4d 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -1963,16 +1963,12 @@ fn sidebar_assoc_items(cx: &Context<'_>, out: &mut Buffer, it: &clean::Item) { // We want links' order to be reproducible so we don't use unstable sort. assoc_consts.sort(); - out.push_str( - "

\ - Associated Constants\ -

\ -
", + print_sidebar_block( + out, + "implementations", + "Associated Constants", + assoc_consts.iter(), ); - for line in assoc_consts { - write!(out, "{}", line); - } - out.push_str("
"); } let mut methods = v .iter() @@ -1983,14 +1979,7 @@ fn sidebar_assoc_items(cx: &Context<'_>, out: &mut Buffer, it: &clean::Item) { // We want links' order to be reproducible so we don't use unstable sort. methods.sort(); - out.push_str( - "

Methods

\ -
", - ); - for line in methods { - write!(out, "{}", line); - } - out.push_str("
"); + print_sidebar_block(out, "implementations", "Methods", methods.iter()); } } @@ -2029,14 +2018,6 @@ fn sidebar_assoc_items(cx: &Context<'_>, out: &mut Buffer, it: &clean::Item) { ret }; - let write_sidebar_links = |out: &mut Buffer, links: Vec| { - out.push_str("
"); - for link in links { - out.push_str(&link); - } - out.push_str("
"); - }; - let (synthetic, concrete): (Vec<&Impl>, Vec<&Impl>) = v.iter().partition::, _>(|i| i.inner_impl().kind.is_auto()); let (blanket_impl, concrete): (Vec<&Impl>, Vec<&Impl>) = @@ -2047,27 +2028,30 @@ fn sidebar_assoc_items(cx: &Context<'_>, out: &mut Buffer, it: &clean::Item) { let blanket_format = format_impls(blanket_impl); if !concrete_format.is_empty() { - out.push_str( - "

\ - Trait Implementations

", + print_sidebar_block( + out, + "trait-implementations", + "Trait Implementations", + concrete_format.iter(), ); - write_sidebar_links(out, concrete_format); } if !synthetic_format.is_empty() { - out.push_str( - "

\ - Auto Trait Implementations

", + print_sidebar_block( + out, + "synthetic-implementations", + "Auto Trait Implementations", + synthetic_format.iter(), ); - write_sidebar_links(out, synthetic_format); } if !blanket_format.is_empty() { - out.push_str( - "

\ - Blanket Implementations

", + print_sidebar_block( + out, + "blanket-implementations", + "Blanket Implementations", + blanket_format.iter(), ); - write_sidebar_links(out, blanket_format); } } } @@ -2127,20 +2111,14 @@ fn sidebar_deref_methods( } else { "deref-methods" }; - write!( - out, - "

Methods from {}<Target={}>

", - id, + let title = format!( + "Methods from {}<Target={}>", Escape(&format!("{:#}", impl_.inner_impl().trait_.as_ref().unwrap().print(cx))), Escape(&format!("{:#}", real_target.print(cx))), ); // We want links' order to be reproducible so we don't use unstable sort. ret.sort(); - out.push_str("
"); - for link in ret { - write!(out, "{}", link); - } - out.push_str("
"); + print_sidebar_block(out, id, &title, ret.iter()); } } @@ -2166,27 +2144,19 @@ fn sidebar_struct(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item, s: &clea let fields = get_struct_fields_name(&s.fields); if !fields.is_empty() { - if let CtorKind::Fictive = s.struct_type { - sidebar.push_str( - "

Fields

\ -
", - ); - - for field in fields { - sidebar.push_str(&field); + match s.struct_type { + CtorKind::Fictive => { + print_sidebar_block(&mut sidebar, "fields", "Fields", fields.iter()); } - - sidebar.push_str("
"); - } else if let CtorKind::Fn = s.struct_type { - sidebar - .push_str("

Tuple Fields

"); + CtorKind::Fn => print_sidebar_title(&mut sidebar, "fields", "Tuple Fields"), + CtorKind::Const => {} } } sidebar_assoc_items(cx, &mut sidebar, it); if !sidebar.is_empty() { - write!(buf, "
{}
", sidebar.into_inner()); + write!(buf, "
{}
", sidebar.into_inner()); } } @@ -2214,18 +2184,50 @@ fn extract_for_impl_name(item: &clean::Item, cx: &Context<'_>) -> Option<(String } } +/// Don't call this function directly!!! Use `print_sidebar_title` or `print_sidebar_block` instead! +fn print_sidebar_title_inner(buf: &mut Buffer, id: &str, title: &str) { + write!( + buf, + "

\ + {}\ +

", + id, title + ); +} + +fn print_sidebar_title(buf: &mut Buffer, id: &str, title: &str) { + buf.push_str("
"); + print_sidebar_title_inner(buf, id, title); + buf.push_str("
"); +} + +fn print_sidebar_block( + buf: &mut Buffer, + id: &str, + title: &str, + items: impl Iterator, +) { + buf.push_str("
"); + print_sidebar_title_inner(buf, id, title); + buf.push_str("
    "); + for item in items { + write!(buf, "
  • {}
  • ", item); + } + buf.push_str("
"); +} + fn sidebar_trait(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item, t: &clean::Trait) { - buf.write_str("
"); + buf.write_str("
"); fn print_sidebar_section( out: &mut Buffer, items: &[clean::Item], - before: &str, + id: &str, + title: &str, filter: impl Fn(&clean::Item) -> bool, - write: impl Fn(&mut Buffer, &str), - after: &str, + mapper: impl Fn(&str) -> String, ) { - let mut items = items + let mut items: Vec<&str> = items .iter() .filter_map(|m| match m.name { Some(ref name) if filter(m) => Some(name.as_str()), @@ -2235,52 +2237,44 @@ fn print_sidebar_section( if !items.is_empty() { items.sort_unstable(); - out.push_str(before); - for item in items.into_iter() { - write(out, &item); - } - out.push_str(after); + print_sidebar_block(out, id, title, items.into_iter().map(mapper)); } } print_sidebar_section( buf, &t.items, - "

\ - Associated Types

", + "associated-types", + "Associated Types", |m| m.is_associated_type(), - |out, sym| write!(out, "{0}", sym), - "
", + |sym| format!("{0}", sym), ); print_sidebar_section( buf, &t.items, - "

\ - Associated Constants

", + "associated-const", + "Associated Constants", |m| m.is_associated_const(), - |out, sym| write!(out, "{0}", sym), - "
", + |sym| format!("{0}", sym), ); print_sidebar_section( buf, &t.items, - "

\ - Required Methods

", + "required-methods", + "Required Methods", |m| m.is_ty_method(), - |out, sym| write!(out, "{0}", sym), - "
", + |sym| format!("{0}", sym), ); print_sidebar_section( buf, &t.items, - "

\ - Provided Methods

", + "provided-methods", + "Provided Methods", |m| m.is_method(), - |out, sym| write!(out, "{0}", sym), - "
", + |sym| format!("{0}", sym), ); let cache = cx.cache(); @@ -2295,29 +2289,23 @@ fn print_sidebar_section( if !res.is_empty() { res.sort(); - buf.push_str( - "

\ - Implementations on Foreign Types

\ -
", + print_sidebar_block( + buf, + "foreign-impls", + "Implementations on Foreign Types", + res.iter().map(|(name, id)| format!("{}", id, Escape(&name))), ); - for (name, id) in res.into_iter() { - write!(buf, "{}", id, Escape(&name)); - } - buf.push_str("
"); } } sidebar_assoc_items(cx, buf, it); - buf.push_str("

Implementors

"); + print_sidebar_title(buf, "implementors", "Implementors"); if t.is_auto { - buf.push_str( - "

Auto Implementors

", - ); + print_sidebar_title(buf, "synthetic-implementors", "Auto Implementors"); } - buf.push_str("
") + buf.push_str("") } fn sidebar_primitive(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item) { @@ -2325,7 +2313,7 @@ fn sidebar_primitive(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item) { sidebar_assoc_items(cx, &mut sidebar, it); if !sidebar.is_empty() { - write!(buf, "
{}
", sidebar.into_inner()); + write!(buf, "
{}
", sidebar.into_inner()); } } @@ -2334,7 +2322,7 @@ fn sidebar_typedef(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item) { sidebar_assoc_items(cx, &mut sidebar, it); if !sidebar.is_empty() { - write!(buf, "
{}
", sidebar.into_inner()); + write!(buf, "
{}
", sidebar.into_inner()); } } @@ -2355,22 +2343,13 @@ fn sidebar_union(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item, u: &clean let fields = get_struct_fields_name(&u.fields); if !fields.is_empty() { - sidebar.push_str( - "

Fields

\ -
", - ); - - for field in fields { - sidebar.push_str(&field); - } - - sidebar.push_str("
"); + print_sidebar_block(&mut sidebar, "fields", "Fields", fields.iter()); } sidebar_assoc_items(cx, &mut sidebar, it); if !sidebar.is_empty() { - write!(buf, "
{}
", sidebar.into_inner()); + write!(buf, "
{}
", sidebar.into_inner()); } } @@ -2388,17 +2367,13 @@ fn sidebar_enum(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item, e: &clean: .collect::>(); if !variants.is_empty() { variants.sort_unstable(); - sidebar.push_str(&format!( - "

Variants

\ -
{}
", - variants.join(""), - )); + print_sidebar_block(&mut sidebar, "variants", "Variants", variants.iter()); } sidebar_assoc_items(cx, &mut sidebar, it); if !sidebar.is_empty() { - write!(buf, "
{}
", sidebar.into_inner()); + write!(buf, "
{}
", sidebar.into_inner()); } } @@ -2569,7 +2544,15 @@ fn sidebar_module(buf: &mut Buffer, items: &[clean::Item]) { } if !sidebar.is_empty() { - write!(buf, "
    {}
", sidebar); + write!( + buf, + "
\ +
\ +
    {}
\ +
\ +
", + sidebar + ); } } @@ -2578,7 +2561,7 @@ fn sidebar_foreign_type(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item) { sidebar_assoc_items(cx, &mut sidebar, it); if !sidebar.is_empty() { - write!(buf, "
{}
", sidebar.into_inner()); + write!(buf, "
{}
", sidebar.into_inner()); } } diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 2ae7626b886..e84dc6c7240 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -1752,9 +1752,7 @@ fn write_size_of_layout(w: &mut Buffer, layout: &Layout, tag_size: u64) {
    ", ); - let adt = if let Adt(adt, _) = ty_layout.ty.kind() { - adt - } else { + let Adt(adt, _) = ty_layout.ty.kind() else { span_bug!(tcx.def_span(ty_def_id), "not an adt") }; diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 662221ae773..f1e0a89883a 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -484,10 +484,6 @@ h2.location a { overflow: hidden; } -.sidebar-links a { - white-space: nowrap; -} - .sidebar h2 { border-bottom: none; font-weight: 500; @@ -504,11 +500,14 @@ h2.location a { margin: 0; } -.sidebar-links, -.block { +.sidebar-elems .block { margin-bottom: 2em; } +.sidebar-elems .block li a { + white-space: nowrap; +} + .mobile-topbar { display: none; } diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 8621fe6ba1b..33a1530d588 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -1226,9 +1226,7 @@ fn resolve_link( let base_node = if item.is_mod() && inner_docs { self.mod_ids.last().copied() } else { parent_node }; - let mut module_id = if let Some(id) = base_node { - id - } else { + let Some(mut module_id) = base_node else { // This is a bug. debug!("attempting to resolve item without parent module: {}", path_str); resolution_failure( @@ -1977,9 +1975,7 @@ fn split(path: &str) -> Option<(&str, &str)> { // If so, report it and say the first which failed; if not, say the first path segment didn't resolve. let mut name = path_str; 'outer: loop { - let (start, end) = if let Some(x) = split(name) { - x - } else { + let Some((start, end)) = split(name) else { // avoid bug that marked [Quux::Z] as missing Z, not Quux if partial_res.is_none() { *unresolved = name.into(); diff --git a/src/librustdoc/scrape_examples.rs b/src/librustdoc/scrape_examples.rs index 16882cf83d0..f9e91c299ea 100644 --- a/src/librustdoc/scrape_examples.rs +++ b/src/librustdoc/scrape_examples.rs @@ -152,9 +152,7 @@ fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) { } hir::ExprKind::MethodCall(_, _, span) => { let types = tcx.typeck(ex.hir_id.owner); - let def_id = if let Some(def_id) = types.type_dependent_def_id(ex.hir_id) { - def_id - } else { + let Some(def_id) = types.type_dependent_def_id(ex.hir_id) else { trace!("type_dependent_def_id({}) = None", ex.hir_id); return; }; diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index 2cbb3324a5e..e8b3a0929db 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -188,9 +188,7 @@ fn maybe_inline_local( debug!("maybe_inline_local res: {:?}", res); let tcx = self.cx.tcx; - let res_did = if let Some(did) = res.opt_def_id() { - did - } else { + let Some(res_did) = res.opt_def_id() else { return false; }; diff --git a/src/test/rustdoc-gui/hash-item-expansion.goml b/src/test/rustdoc-gui/hash-item-expansion.goml index 2885978ce1f..a680635ef8a 100644 --- a/src/test/rustdoc-gui/hash-item-expansion.goml +++ b/src/test/rustdoc-gui/hash-item-expansion.goml @@ -5,7 +5,7 @@ assert-attribute: ("#blanket-implementations-list > details:nth-child(2)", {"ope // We first check that the impl block is open by default. assert-attribute: ("#implementations + details", {"open": ""}) // To ensure that we will click on the currently hidden method. -assert-text: (".sidebar-links > a", "must_use") -click: ".sidebar-links > a" +assert-text: (".sidebar-elems section .block li > a", "must_use") +click: ".sidebar-elems section .block li > a" // We check that the impl block was opened as expected so that we can see the method. assert-attribute: ("#implementations + details", {"open": ""}) diff --git a/src/test/rustdoc-gui/sidebar-mobile.goml b/src/test/rustdoc-gui/sidebar-mobile.goml index 9581aa74b0f..79f18db8fc7 100644 --- a/src/test/rustdoc-gui/sidebar-mobile.goml +++ b/src/test/rustdoc-gui/sidebar-mobile.goml @@ -33,7 +33,7 @@ assert-property: (".mobile-topbar", {"clientHeight": "45"}) // Check that clicking an element from the sidebar scrolls to the right place // so the target is not obscured by the topbar. click: ".sidebar-menu-toggle" -click: ".sidebar-links a" +click: ".sidebar-elems section .block li > a" assert-position: ("#method\.must_use", {"y": 45}) // Check that the bottom-most item on the sidebar menu can be scrolled fully into view. diff --git a/src/test/rustdoc-gui/sidebar.goml b/src/test/rustdoc-gui/sidebar.goml index 9505e00512f..6b79b00d3f7 100644 --- a/src/test/rustdoc-gui/sidebar.goml +++ b/src/test/rustdoc-gui/sidebar.goml @@ -13,15 +13,15 @@ assert-css: ("#all-types", {"color": "rgb(53, 109, 164)"}) // We check that we have the crates list and that the "current" on is "test_docs". assert-text: (".sidebar-elems .crate > ul > li > a.current", "test_docs") // And we're also supposed to have the list of items in the current module. -assert-text: (".sidebar-elems .items > ul > li:nth-child(1)", "Modules") -assert-text: (".sidebar-elems .items > ul > li:nth-child(2)", "Macros") -assert-text: (".sidebar-elems .items > ul > li:nth-child(3)", "Structs") -assert-text: (".sidebar-elems .items > ul > li:nth-child(4)", "Enums") -assert-text: (".sidebar-elems .items > ul > li:nth-child(5)", "Traits") -assert-text: (".sidebar-elems .items > ul > li:nth-child(6)", "Functions") -assert-text: (".sidebar-elems .items > ul > li:nth-child(7)", "Type Definitions") -assert-text: (".sidebar-elems .items > ul > li:nth-child(8)", "Unions") -assert-text: (".sidebar-elems .items > ul > li:nth-child(9)", "Keywords") +assert-text: (".sidebar-elems section ul > li:nth-child(1)", "Modules") +assert-text: (".sidebar-elems section ul > li:nth-child(2)", "Macros") +assert-text: (".sidebar-elems section ul > li:nth-child(3)", "Structs") +assert-text: (".sidebar-elems section ul > li:nth-child(4)", "Enums") +assert-text: (".sidebar-elems section ul > li:nth-child(5)", "Traits") +assert-text: (".sidebar-elems section ul > li:nth-child(6)", "Functions") +assert-text: (".sidebar-elems section ul > li:nth-child(7)", "Type Definitions") +assert-text: (".sidebar-elems section ul > li:nth-child(8)", "Unions") +assert-text: (".sidebar-elems section ul > li:nth-child(9)", "Keywords") assert-text: ("#structs + .item-table .item-left > a", "Foo") click: "#structs + .item-table .item-left > a" @@ -30,7 +30,7 @@ assert-count: (".sidebar .location", 2) // We check that there is no crate listed outside of the top level. assert-false: ".sidebar-elems > .crate" -click: ".sidebar-links a" +click: ".sidebar-elems section .block li > a" assert-property-false: ("html", {"scrollTop": "0"}) click: ".sidebar h2.location a" @@ -47,11 +47,11 @@ assert-text: (".sidebar > .location", "Crate lib2") // We check that we have the crates list and that the "current" on is now "lib2". assert-text: (".sidebar-elems .crate > ul > li > a.current", "lib2") // We now go to the "foobar" function page. -assert-text: (".sidebar-elems > .items > ul > li:nth-child(1)", "Modules") -assert-text: (".sidebar-elems > .items > ul > li:nth-child(2)", "Structs") -assert-text: (".sidebar-elems > .items > ul > li:nth-child(3)", "Traits") -assert-text: (".sidebar-elems > .items > ul > li:nth-child(4)", "Functions") -assert-text: (".sidebar-elems > .items > ul > li:nth-child(5)", "Type Definitions") +assert-text: (".sidebar-elems > section .block ul > li:nth-child(1)", "Modules") +assert-text: (".sidebar-elems > section .block ul > li:nth-child(2)", "Structs") +assert-text: (".sidebar-elems > section .block ul > li:nth-child(3)", "Traits") +assert-text: (".sidebar-elems > section .block ul > li:nth-child(4)", "Functions") +assert-text: (".sidebar-elems > section .block ul > li:nth-child(5)", "Type Definitions") assert-text: ("#functions + .item-table .item-left > a", "foobar") click: "#functions + .item-table .item-left > a" @@ -72,12 +72,12 @@ goto: ./sub_module/sub_sub_module/index.html assert-text: (".sidebar > .location", "Module sub_sub_module") // We check that we don't have the crate list. assert-false: ".sidebar-elems .crate" -assert-text: (".sidebar-elems .items > ul > li:nth-child(1)", "Functions") +assert-text: (".sidebar-elems > section ul > li:nth-child(1)", "Functions") assert-text: ("#functions + .item-table .item-left > a", "foo") // Links to trait implementations in the sidebar should not wrap even if they are long. goto: file://|DOC_PATH|/lib2/struct.HasALongTraitWithParams.html -assert-property: (".sidebar-links a", {"offsetHeight": 29}) +assert-property: (".sidebar-elems section .block li > a", {"offsetHeight": 29}) // Test that clicking on of the "In " headings in the sidebar links to the // appropriate anchor in index.html. diff --git a/src/test/rustdoc-gui/trait-sidebar-item-order.goml b/src/test/rustdoc-gui/trait-sidebar-item-order.goml index 38942baa0b5..d77d1dca483 100644 --- a/src/test/rustdoc-gui/trait-sidebar-item-order.goml +++ b/src/test/rustdoc-gui/trait-sidebar-item-order.goml @@ -1,8 +1,8 @@ // Checks that the elements in the sidebar are alphabetically sorted. goto: file://|DOC_PATH|/test_docs/trait.AnotherOne.html -assert-text: (".sidebar-links a:nth-of-type(1)", "another") -assert-text: (".sidebar-links a:nth-of-type(2)", "func1") -assert-text: (".sidebar-links a:nth-of-type(3)", "func2") -assert-text: (".sidebar-links a:nth-of-type(4)", "func3") -assert-text: (".sidebar-links a:nth-of-type(5)", "hello") -assert-text: (".sidebar-links a:nth-of-type(6)", "why_not") +assert-text: (".sidebar-elems section .block li:nth-of-type(1) > a", "another") +assert-text: (".sidebar-elems section .block li:nth-of-type(2) > a", "func1") +assert-text: (".sidebar-elems section .block li:nth-of-type(3) > a", "func2") +assert-text: (".sidebar-elems section .block li:nth-of-type(4) > a", "func3") +assert-text: (".sidebar-elems section .block li:nth-of-type(5) > a", "hello") +assert-text: (".sidebar-elems section .block li:nth-of-type(6) > a", "why_not") diff --git a/src/test/rustdoc/associated-consts.rs b/src/test/rustdoc/associated-consts.rs index 6ae5e20632e..da50fb86cd5 100644 --- a/src/test/rustdoc/associated-consts.rs +++ b/src/test/rustdoc/associated-consts.rs @@ -10,7 +10,7 @@ pub trait Trait { // @has 'foo/struct.Bar.html' // @has - '//h3[@class="sidebar-title"]' 'Associated Constants' -// @has - '//div[@class="sidebar-elems"]//div[@class="sidebar-links"]/a' 'FOO' +// @has - '//div[@class="sidebar-elems"]//a' 'FOO' impl Trait for Bar { const FOO: u32 = 1; @@ -23,7 +23,7 @@ pub enum Foo { // @has 'foo/enum.Foo.html' // @has - '//h3[@class="sidebar-title"]' 'Associated Constants' -// @has - '//div[@class="sidebar-elems"]//div[@class="sidebar-links"]/a' 'FOO' +// @has - '//div[@class="sidebar-elems"]//a' 'FOO' impl Trait for Foo { const FOO: u32 = 1; diff --git a/src/test/rustdoc/deref-mut-methods.rs b/src/test/rustdoc/deref-mut-methods.rs index 0e27fc90b69..fdf8434224f 100644 --- a/src/test/rustdoc/deref-mut-methods.rs +++ b/src/test/rustdoc/deref-mut-methods.rs @@ -9,7 +9,7 @@ pub fn foo(&mut self) {} } // @has foo/struct.Bar.html -// @has - '//div[@class="sidebar-links"]/a[@href="#method.foo"]' 'foo' +// @has - '//*[@class="sidebar-elems"]//*[@class="block"]//a[@href="#method.foo"]' 'foo' pub struct Bar { foo: Foo, } diff --git a/src/test/rustdoc/deref-recursive-pathbuf.rs b/src/test/rustdoc/deref-recursive-pathbuf.rs index 9ab338ca9b1..746df9c804e 100644 --- a/src/test/rustdoc/deref-recursive-pathbuf.rs +++ b/src/test/rustdoc/deref-recursive-pathbuf.rs @@ -8,9 +8,9 @@ // @has '-' '//*[@id="deref-methods-Path"]' 'Methods from Deref' // @has '-' '//*[@class="impl-items"]//*[@id="method.exists"]' 'pub fn exists(&self)' // @has '-' '//*[@class="sidebar-title"]/a[@href="#deref-methods-PathBuf"]' 'Methods from Deref' -// @has '-' '//*[@class="sidebar-links"]/a[@href="#method.as_path"]' 'as_path' +// @has '-' '//*[@class="sidebar-elems"]//*[@class="block"]//a[@href="#method.as_path"]' 'as_path' // @has '-' '//*[@class="sidebar-title"]/a[@href="#deref-methods-Path"]' 'Methods from Deref' -// @has '-' '//*[@class="sidebar-links"]/a[@href="#method.exists"]' 'exists' +// @has '-' '//*[@class="sidebar-elems"]//*[@class="block"]//a[@href="#method.exists"]' 'exists' #![crate_name = "foo"] diff --git a/src/test/rustdoc/deref-recursive.rs b/src/test/rustdoc/deref-recursive.rs index c07e048b065..d5f8473f284 100644 --- a/src/test/rustdoc/deref-recursive.rs +++ b/src/test/rustdoc/deref-recursive.rs @@ -8,9 +8,9 @@ // @has '-' '//*[@id="deref-methods-Baz"]' 'Methods from Deref' // @has '-' '//*[@class="impl-items"]//*[@id="method.baz"]' 'pub fn baz(&self)' // @has '-' '//*[@class="sidebar-title"]/a[@href="#deref-methods-Bar"]' 'Methods from Deref' -// @has '-' '//*[@class="sidebar-links"]/a[@href="#method.bar"]' 'bar' +// @has '-' '//*[@class="sidebar-elems"]//section//a[@href="#method.bar"]' 'bar' // @has '-' '//*[@class="sidebar-title"]/a[@href="#deref-methods-Baz"]' 'Methods from Deref' -// @has '-' '//*[@class="sidebar-links"]/a[@href="#method.baz"]' 'baz' +// @has '-' '//*[@class="sidebar-elems"]//section//a[@href="#method.baz"]' 'baz' #![crate_name = "foo"] diff --git a/src/test/rustdoc/deref-typedef.rs b/src/test/rustdoc/deref-typedef.rs index ad7a96c5dad..28f977e315a 100644 --- a/src/test/rustdoc/deref-typedef.rs +++ b/src/test/rustdoc/deref-typedef.rs @@ -7,10 +7,10 @@ // @has '-' '//*[@class="impl-items"]//*[@id="method.foo_c"]' 'pub fn foo_c(&self)' // @has '-' '//*[@class="impl-items"]//*[@id="method.foo_j"]' 'pub fn foo_j(&self)' // @has '-' '//*[@class="sidebar-title"]/a[@href="#deref-methods-FooJ"]' 'Methods from Deref' -// @has '-' '//*[@class="sidebar-links"]/a[@href="#method.foo_a"]' 'foo_a' -// @has '-' '//*[@class="sidebar-links"]/a[@href="#method.foo_b"]' 'foo_b' -// @has '-' '//*[@class="sidebar-links"]/a[@href="#method.foo_c"]' 'foo_c' -// @has '-' '//*[@class="sidebar-links"]/a[@href="#method.foo_j"]' 'foo_j' +// @has '-' '//*[@class="sidebar-elems"]//section//a[@href="#method.foo_a"]' 'foo_a' +// @has '-' '//*[@class="sidebar-elems"]//section//a[@href="#method.foo_b"]' 'foo_b' +// @has '-' '//*[@class="sidebar-elems"]//section//a[@href="#method.foo_c"]' 'foo_c' +// @has '-' '//*[@class="sidebar-elems"]//section//a[@href="#method.foo_j"]' 'foo_j' pub struct FooA; pub type FooB = FooA; diff --git a/src/test/rustdoc/double-quote-escape.rs b/src/test/rustdoc/double-quote-escape.rs index 546af2c121a..b7bbf140cfd 100644 --- a/src/test/rustdoc/double-quote-escape.rs +++ b/src/test/rustdoc/double-quote-escape.rs @@ -8,5 +8,5 @@ fn foo() {} pub struct Bar; // @has foo/struct.Bar.html -// @has - '//*[@class="sidebar-links"]/a[@href="#impl-Foo%3Cunsafe%20extern%20%22C%22%20fn()%3E"]' 'Foo' +// @has - '//*[@class="sidebar-elems"]//section//a[@href="#impl-Foo%3Cunsafe%20extern%20%22C%22%20fn()%3E"]' 'Foo' impl Foo for Bar {} diff --git a/src/test/rustdoc/generic-impl.rs b/src/test/rustdoc/generic-impl.rs index 0f6cba93f95..1268c9587f8 100644 --- a/src/test/rustdoc/generic-impl.rs +++ b/src/test/rustdoc/generic-impl.rs @@ -7,7 +7,7 @@ // @has foo/struct.Foo.html '//*[@id="impl-ToString"]//h3[@class="code-header in-band"]' 'impl ToString for T' pub struct Foo; -// @has foo/struct.Foo.html '//div[@class="sidebar-links"]/a[@href="#impl-ToString"]' 'ToString' +// @has foo/struct.Foo.html '//*[@class="sidebar-elems"]//section//a[@href="#impl-ToString"]' 'ToString' impl fmt::Display for Foo { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { diff --git a/src/test/rustdoc/method-list.rs b/src/test/rustdoc/method-list.rs index 9f24e817fd3..50f4af3aaaf 100644 --- a/src/test/rustdoc/method-list.rs +++ b/src/test/rustdoc/method-list.rs @@ -1,8 +1,8 @@ #![crate_name = "foo"] // @has foo/struct.Foo.html -// @has - '//*[@class="sidebar-links"]/a' 'super_long_name' -// @has - '//*[@class="sidebar-links"]/a' 'Disp' +// @has - '//*[@class="sidebar-elems"]//section//a' 'super_long_name' +// @has - '//*[@class="sidebar-elems"]//section//a' 'Disp' pub struct Foo(usize); impl Foo { diff --git a/src/test/rustdoc/negative-impl-sidebar.rs b/src/test/rustdoc/negative-impl-sidebar.rs index d63ab346045..b995fff1f9a 100644 --- a/src/test/rustdoc/negative-impl-sidebar.rs +++ b/src/test/rustdoc/negative-impl-sidebar.rs @@ -5,5 +5,5 @@ // @has foo/struct.Foo.html // @has - '//*[@class="sidebar-title"]/a[@href="#trait-implementations"]' 'Trait Implementations' -// @has - '//*[@class="sidebar-links"]/a' '!Sync' +// @has - '//*[@class="sidebar-elems"]//section//a' '!Sync' impl !Sync for Foo {} diff --git a/src/test/rustdoc/recursive-deref-sidebar.rs b/src/test/rustdoc/recursive-deref-sidebar.rs index 65a7debc253..619f40eff89 100644 --- a/src/test/rustdoc/recursive-deref-sidebar.rs +++ b/src/test/rustdoc/recursive-deref-sidebar.rs @@ -9,13 +9,13 @@ impl B { pub fn foo_b(&self) {} } pub struct C {} impl C { pub fn foo_c(&self) {} } -// @has recursive_deref_sidebar/struct.A.html '//div[@class="sidebar-links"]' 'foo_b' +// @has recursive_deref_sidebar/struct.A.html '//*[@class="sidebar-elems"]//section' 'foo_b' impl Deref for A { type Target = B; fn deref(&self) -> &B { todo!() } } -// @has recursive_deref_sidebar/struct.A.html '//div[@class="sidebar-links"]' 'foo_c' +// @has recursive_deref_sidebar/struct.A.html '//*[@class="sidebar-elems"]//section' 'foo_c' impl Deref for B { type Target = C; fn deref(&self) -> &C { todo!() } diff --git a/src/test/rustdoc/sidebar-items.rs b/src/test/rustdoc/sidebar-items.rs index ee670e88b5c..375cad9da7f 100644 --- a/src/test/rustdoc/sidebar-items.rs +++ b/src/test/rustdoc/sidebar-items.rs @@ -2,13 +2,13 @@ // @has foo/trait.Foo.html // @has - '//*[@class="sidebar-title"]/a[@href="#required-methods"]' 'Required Methods' -// @has - '//*[@class="sidebar-links"]/a' 'bar' +// @has - '//*[@class="sidebar-elems"]//section//a' 'bar' // @has - '//*[@class="sidebar-title"]/a[@href="#provided-methods"]' 'Provided Methods' -// @has - '//*[@class="sidebar-links"]/a' 'foo' +// @has - '//*[@class="sidebar-elems"]//section//a' 'foo' // @has - '//*[@class="sidebar-title"]/a[@href="#associated-const"]' 'Associated Constants' -// @has - '//*[@class="sidebar-links"]/a' 'BAR' +// @has - '//*[@class="sidebar-elems"]//section//a' 'BAR' // @has - '//*[@class="sidebar-title"]/a[@href="#associated-types"]' 'Associated Types' -// @has - '//*[@class="sidebar-links"]/a' 'Output' +// @has - '//*[@class="sidebar-elems"]//section//a' 'Output' pub trait Foo { const BAR: u32 = 0; type Output: ?Sized; @@ -19,9 +19,9 @@ fn foo() {} // @has foo/struct.Bar.html // @has - '//*[@class="sidebar-title"]/a[@href="#fields"]' 'Fields' -// @has - '//*[@class="sidebar-links"]/a[@href="#structfield.f"]' 'f' -// @has - '//*[@class="sidebar-links"]/a[@href="#structfield.u"]' 'u' -// @!has - '//*[@class="sidebar-links"]/a' 'waza' +// @has - '//*[@class="sidebar-elems"]//section//a[@href="#structfield.f"]' 'f' +// @has - '//*[@class="sidebar-elems"]//section//a[@href="#structfield.u"]' 'u' +// @!has - '//*[@class="sidebar-elems"]//section//a' 'waza' pub struct Bar { pub f: u32, pub u: u32, @@ -30,8 +30,8 @@ pub struct Bar { // @has foo/enum.En.html // @has - '//*[@class="sidebar-title"]/a[@href="#variants"]' 'Variants' -// @has - '//*[@class="sidebar-links"]/a' 'Foo' -// @has - '//*[@class="sidebar-links"]/a' 'Bar' +// @has - '//*[@class="sidebar-elems"]//section//a' 'Foo' +// @has - '//*[@class="sidebar-elems"]//section//a' 'Bar' pub enum En { Foo, Bar, @@ -39,9 +39,9 @@ pub enum En { // @has foo/union.MyUnion.html // @has - '//*[@class="sidebar-title"]/a[@href="#fields"]' 'Fields' -// @has - '//*[@class="sidebar-links"]/a[@href="#structfield.f1"]' 'f1' -// @has - '//*[@class="sidebar-links"]/a[@href="#structfield.f2"]' 'f2' -// @!has - '//*[@class="sidebar-links"]/a' 'waza' +// @has - '//*[@class="sidebar-elems"]//section//a[@href="#structfield.f1"]' 'f1' +// @has - '//*[@class="sidebar-elems"]//section//a[@href="#structfield.f2"]' 'f2' +// @!has - '//*[@class="sidebar-elems"]//section//a' 'waza' pub union MyUnion { pub f1: u32, pub f2: f32, diff --git a/src/test/rustdoc/sidebar-link-generation.rs b/src/test/rustdoc/sidebar-link-generation.rs index 76b77b9bcbb..7858f35a261 100644 --- a/src/test/rustdoc/sidebar-link-generation.rs +++ b/src/test/rustdoc/sidebar-link-generation.rs @@ -1,6 +1,6 @@ #![crate_name = "foo"] -// @has foo/struct.SomeStruct.html '//*[@class="sidebar-links"]/a[@href="#method.some_fn-1"]' \ +// @has foo/struct.SomeStruct.html '//*[@class="sidebar-elems"]//section//li/a[@href="#method.some_fn-1"]' \ // "some_fn" pub struct SomeStruct { _inner: T } diff --git a/src/test/rustdoc/sidebar-links-to-foreign-impl.rs b/src/test/rustdoc/sidebar-links-to-foreign-impl.rs index 63e486b8834..15515039659 100644 --- a/src/test/rustdoc/sidebar-links-to-foreign-impl.rs +++ b/src/test/rustdoc/sidebar-links-to-foreign-impl.rs @@ -5,9 +5,9 @@ // @has foo/trait.Foo.html // @has - '//*[@class="sidebar-title"]/a[@href="#foreign-impls"]' 'Implementations on Foreign Types' // @has - '//h2[@id="foreign-impls"]' 'Implementations on Foreign Types' -// @has - '//*[@class="sidebar-links"]/a[@href="#impl-Foo-for-u32"]' 'u32' +// @has - '//*[@class="sidebar-elems"]//section//a[@href="#impl-Foo-for-u32"]' 'u32' // @has - '//*[@id="impl-Foo-for-u32"]//h3[@class="code-header in-band"]' 'impl Foo for u32' -// @has - '//*[@class="sidebar-links"]/a[@href="#impl-Foo-for-%26%27a%20str"]' "&'a str" +// @has - '//*[@class="sidebar-elems"]//section//a[@href="#impl-Foo-for-%26%27a%20str"]' "&'a str" // @has - '//*[@id="impl-Foo-for-%26%27a%20str"]//h3[@class="code-header in-band"]' "impl<'a> Foo for &'a str" pub trait Foo {} diff --git a/src/test/ui/box/issue-78459-ice.rs b/src/test/ui/box/issue-78459-ice.rs new file mode 100644 index 00000000000..89f75fea15b --- /dev/null +++ b/src/test/ui/box/issue-78459-ice.rs @@ -0,0 +1,6 @@ +// check-pass +#![feature(allocator_api)] + +fn main() { + Box::new_in((), &std::alloc::Global); +} diff --git a/src/test/ui/feature-gates/feature-gate-asm_const.stderr b/src/test/ui/feature-gates/feature-gate-asm_const.stderr index 2851a9b0ae6..0202ccbe5a2 100644 --- a/src/test/ui/feature-gates/feature-gate-asm_const.stderr +++ b/src/test/ui/feature-gates/feature-gate-asm_const.stderr @@ -4,7 +4,7 @@ error[E0658]: const operands for inline assembly are unstable LL | asm!("mov eax, {}", const 123); | ^^^^^^^^^ | - = note: see issue #72016 for more information + = note: see issue #93332 for more information = help: add `#![feature(asm_const)]` to the crate attributes to enable error: aborting due to previous error diff --git a/src/test/ui/feature-gates/feature-gate-asm_experimental_arch.stderr b/src/test/ui/feature-gates/feature-gate-asm_experimental_arch.stderr index 1b4188ae1ad..4a859430e04 100644 --- a/src/test/ui/feature-gates/feature-gate-asm_experimental_arch.stderr +++ b/src/test/ui/feature-gates/feature-gate-asm_experimental_arch.stderr @@ -4,7 +4,7 @@ error[E0658]: inline assembly is not stable yet on this architecture LL | asm!(""); | ^^^^^^^^ | - = note: see issue #72016 for more information + = note: see issue #93335 for more information = help: add `#![feature(asm_experimental_arch)]` to the crate attributes to enable error: aborting due to previous error diff --git a/src/test/ui/feature-gates/feature-gate-asm_sym.stderr b/src/test/ui/feature-gates/feature-gate-asm_sym.stderr index 99b61b829fb..68f2d0f6c18 100644 --- a/src/test/ui/feature-gates/feature-gate-asm_sym.stderr +++ b/src/test/ui/feature-gates/feature-gate-asm_sym.stderr @@ -4,7 +4,7 @@ error[E0658]: sym operands for inline assembly are unstable LL | asm!("mov eax, {}", sym main); | ^^^^^^^^ | - = note: see issue #72016 for more information + = note: see issue #93333 for more information = help: add `#![feature(asm_sym)]` to the crate attributes to enable error: aborting due to previous error diff --git a/src/test/ui/feature-gates/feature-gate-asm_unwind.stderr b/src/test/ui/feature-gates/feature-gate-asm_unwind.stderr index 6b5bf286e7b..05e66acb556 100644 --- a/src/test/ui/feature-gates/feature-gate-asm_unwind.stderr +++ b/src/test/ui/feature-gates/feature-gate-asm_unwind.stderr @@ -4,7 +4,7 @@ error[E0658]: the `may_unwind` option is unstable LL | asm!("", options(may_unwind)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: see issue #72016 for more information + = note: see issue #93334 for more information = help: add `#![feature(asm_unwind)]` to the crate attributes to enable error: aborting due to previous error diff --git a/src/tools/clippy/clippy_lints/src/dereference.rs b/src/tools/clippy/clippy_lints/src/dereference.rs index 6d0851d804c..fe391198342 100644 --- a/src/tools/clippy/clippy_lints/src/dereference.rs +++ b/src/tools/clippy/clippy_lints/src/dereference.rs @@ -528,7 +528,7 @@ fn is_auto_reborrow_position(parent: Option>) -> bool { fn is_auto_borrow_position(parent: Option>, child_id: HirId) -> bool { if let Some(Node::Expr(parent)) = parent { match parent.kind { - ExprKind::MethodCall(_, [self_arg, ..], _) => self_arg.hir_id == child_id, + // ExprKind::MethodCall(_, [self_arg, ..], _) => self_arg.hir_id == child_id, ExprKind::Field(..) => true, ExprKind::Call(f, _) => f.hir_id == child_id, _ => false, diff --git a/src/tools/clippy/tests/ui/needless_borrow.fixed b/src/tools/clippy/tests/ui/needless_borrow.fixed index b856f1375d3..efeb5cf5b2b 100644 --- a/src/tools/clippy/tests/ui/needless_borrow.fixed +++ b/src/tools/clippy/tests/ui/needless_borrow.fixed @@ -64,9 +64,9 @@ fn main() { *x = 5; let s = String::new(); - let _ = s.len(); - let _ = s.capacity(); - let _ = s.capacity(); + // let _ = (&s).len(); + // let _ = (&s).capacity(); + // let _ = (&&s).capacity(); let x = (1, 2); let _ = x.0; diff --git a/src/tools/clippy/tests/ui/needless_borrow.rs b/src/tools/clippy/tests/ui/needless_borrow.rs index 0bfe222a3dc..3e416a0eb84 100644 --- a/src/tools/clippy/tests/ui/needless_borrow.rs +++ b/src/tools/clippy/tests/ui/needless_borrow.rs @@ -64,9 +64,9 @@ fn main() { *x = 5; let s = String::new(); - let _ = (&s).len(); - let _ = (&s).capacity(); - let _ = (&&s).capacity(); + // let _ = (&s).len(); + // let _ = (&s).capacity(); + // let _ = (&&s).capacity(); let x = (1, 2); let _ = (&x).0; diff --git a/src/tools/clippy/tests/ui/needless_borrow.stderr b/src/tools/clippy/tests/ui/needless_borrow.stderr index b90e8448db0..05591ce4117 100644 --- a/src/tools/clippy/tests/ui/needless_borrow.stderr +++ b/src/tools/clippy/tests/ui/needless_borrow.stderr @@ -84,24 +84,6 @@ error: this expression creates a reference which is immediately dereferenced by LL | let y: &mut i32 = &mut &mut x; | ^^^^^^^^^^^ help: change this to: `x` -error: this expression borrows a value the compiler would automatically borrow - --> $DIR/needless_borrow.rs:67:13 - | -LL | let _ = (&s).len(); - | ^^^^ help: change this to: `s` - -error: this expression borrows a value the compiler would automatically borrow - --> $DIR/needless_borrow.rs:68:13 - | -LL | let _ = (&s).capacity(); - | ^^^^ help: change this to: `s` - -error: this expression creates a reference which is immediately dereferenced by the compiler - --> $DIR/needless_borrow.rs:69:13 - | -LL | let _ = (&&s).capacity(); - | ^^^^^ help: change this to: `s` - error: this expression borrows a value the compiler would automatically borrow --> $DIR/needless_borrow.rs:72:13 | @@ -114,5 +96,5 @@ error: this expression borrows a value the compiler would automatically borrow LL | let _ = unsafe { (&*x).0 }; | ^^^^^ help: change this to: `(*x)` -error: aborting due to 19 previous errors +error: aborting due to 16 previous errors