]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #100754 - davidtwco:translation-incremental, r=compiler-errors
authorbors <bors@rust-lang.org>
Tue, 31 Jan 2023 10:20:58 +0000 (10:20 +0000)
committerbors <bors@rust-lang.org>
Tue, 31 Jan 2023 10:20:58 +0000 (10:20 +0000)
incremental: migrate diagnostics

- Apply the diagnostic migration lints to more functions on `Session`, namely: `span_warn`, `span_warn_with_code`, `warn` `note_without_error`, `span_note_without_error`, `struct_note_without_error`.
- Add impls of `IntoDiagnosticArg` for `std::io::Error`, `std::path::Path` and `std::path::PathBuf`.
- Migrate the `rustc_incremental` crate's diagnostics to translatable diagnostic structs.

r? `@compiler-errors`
cc #100717

157 files changed:
compiler/rustc_borrowck/src/type_check/canonical.rs
compiler/rustc_hir/src/hir.rs
compiler/rustc_hir_analysis/src/astconv/mod.rs
compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
compiler/rustc_hir_analysis/src/check/wfcheck.rs
compiler/rustc_hir_analysis/src/check_unused.rs
compiler/rustc_hir_analysis/src/coherence/builtin.rs
compiler/rustc_hir_analysis/src/coherence/unsafety.rs
compiler/rustc_hir_analysis/src/collect.rs
compiler/rustc_metadata/src/rmeta/encoder.rs
compiler/rustc_middle/src/mir/mono.rs
compiler/rustc_middle/src/query/mod.rs
compiler/rustc_mir_transform/src/lib.rs
compiler/rustc_mir_transform/src/normalize_array_len.rs
compiler/rustc_monomorphize/src/partitioning/mod.rs
compiler/rustc_parse/src/parser/expr.rs
compiler/rustc_passes/src/dead.rs
compiler/rustc_trait_selection/src/solve/assembly.rs
compiler/rustc_trait_selection/src/solve/project_goals.rs
compiler/rustc_trait_selection/src/solve/trait_goals.rs
compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
compiler/rustc_trait_selection/src/traits/select/confirmation.rs
compiler/rustc_ty_utils/src/ty.rs
config.toml.example
library/alloc/src/fmt.rs
library/alloc/src/rc.rs
library/alloc/src/slice.rs
library/alloc/src/sync.rs
library/alloc/src/vec/mod.rs
library/core/src/future/mod.rs
library/core/src/num/int_macros.rs
library/std/src/os/fuchsia/raw.rs
library/std/src/os/l4re/raw.rs
library/std/src/os/linux/raw.rs
library/std/src/path.rs
src/bootstrap/config.rs
src/bootstrap/doc.rs
src/bootstrap/lib.rs
src/doc/book
src/doc/embedded-book
src/doc/nomicon
src/doc/reference
src/doc/rust-by-example
src/doc/rustc-dev-guide
src/librustdoc/config.rs
src/librustdoc/html/highlight.rs
src/librustdoc/html/layout.rs
src/librustdoc/html/render/context.rs
src/librustdoc/html/render/mod.rs
src/librustdoc/html/render/print_item.rs
src/librustdoc/html/render/write_shared.rs
src/librustdoc/html/sources.rs
src/librustdoc/html/static/css/rustdoc.css
src/librustdoc/html/static/css/themes/ayu.css
src/librustdoc/html/static/css/themes/dark.css
src/librustdoc/html/static/css/themes/light.css
src/librustdoc/html/static/js/settings.js
src/librustdoc/html/static/js/storage.js
src/librustdoc/html/templates/page.html
tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.32bit.diff
tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.64bit.diff
tests/mir-opt/issue_76432.rs
tests/mir-opt/lower_array_len.array_bound.NormalizeArrayLen.diff
tests/mir-opt/lower_array_len.array_bound_mut.NormalizeArrayLen.diff
tests/mir-opt/lower_array_len.array_len.NormalizeArrayLen.diff
tests/mir-opt/lower_array_len.array_len_by_value.NormalizeArrayLen.diff
tests/mir-opt/lower_array_len.array_len_raw.NormalizeArrayLen.diff [new file with mode: 0644]
tests/mir-opt/lower_array_len.array_len_reborrow.NormalizeArrayLen.diff [new file with mode: 0644]
tests/mir-opt/lower_array_len.rs
tests/mir-opt/lower_array_len_e2e.array_bound.PreCodegen.after.mir [deleted file]
tests/mir-opt/lower_array_len_e2e.array_bound_mut.PreCodegen.after.mir [deleted file]
tests/mir-opt/lower_array_len_e2e.array_len.PreCodegen.after.mir [deleted file]
tests/mir-opt/lower_array_len_e2e.array_len_by_value.PreCodegen.after.mir [deleted file]
tests/mir-opt/lower_array_len_e2e.rs [deleted file]
tests/pretty/issue-4264.pp
tests/rustdoc-gui/code-tags.goml
tests/rustdoc-gui/font-weight.goml
tests/rustdoc-gui/list_code_block.goml
tests/rustdoc-gui/type-declation-overflow.goml
tests/rustdoc/array-links.rs
tests/rustdoc/assoc-consts.rs
tests/rustdoc/assoc-item-cast.rs
tests/rustdoc/assoc-types.rs
tests/rustdoc/async-fn.rs
tests/rustdoc/attribute-rendering.rs
tests/rustdoc/attributes.rs
tests/rustdoc/auxiliary/issue-85454.rs
tests/rustdoc/const-fn.rs
tests/rustdoc/const-generics/add-impl.rs
tests/rustdoc/const-generics/const-generic-defaults.rs
tests/rustdoc/const-generics/const-generics-docs.rs
tests/rustdoc/const-generics/const-impl.rs
tests/rustdoc/const-generics/generic_const_exprs.rs
tests/rustdoc/const-generics/type-alias.rs
tests/rustdoc/const-intrinsic.rs
tests/rustdoc/const-value-display.rs
tests/rustdoc/decl-trailing-whitespace.rs
tests/rustdoc/document-item-with-associated-const-in-where-clause.rs [new file with mode: 0644]
tests/rustdoc/fn-pointer-arg-name.rs
tests/rustdoc/hide-complex-unevaluated-const-arguments.rs
tests/rustdoc/inline-default-methods.rs
tests/rustdoc/inline_cross/dyn_trait.rs
tests/rustdoc/inline_cross/impl_trait.rs
tests/rustdoc/inline_cross/issue-24183.rs
tests/rustdoc/issue-20646.rs
tests/rustdoc/issue-20727-2.rs
tests/rustdoc/issue-20727-3.rs
tests/rustdoc/issue-20727-4.rs
tests/rustdoc/issue-20727.rs
tests/rustdoc/issue-22038.rs
tests/rustdoc/issue-33302.rs
tests/rustdoc/issue-85454.rs
tests/rustdoc/issue-98697.rs
tests/rustdoc/legacy-const-generic.rs
tests/rustdoc/lifetime-name.rs
tests/rustdoc/macro-higher-kinded-function.rs
tests/rustdoc/mut-params.rs
tests/rustdoc/normalize-assoc-item.rs
tests/rustdoc/pub-method.rs
tests/rustdoc/range-arg-pattern.rs
tests/rustdoc/reexport-dep-foreign-fn.rs
tests/rustdoc/reexports-priv.rs
tests/rustdoc/reexports.rs
tests/rustdoc/rfc-2632-const-trait-impl.rs
tests/rustdoc/safe-intrinsic.rs
tests/rustdoc/slice-links.rs
tests/rustdoc/struct-arg-pattern.rs
tests/rustdoc/test-parens.rs
tests/rustdoc/toggle-item-contents.rs
tests/rustdoc/trait_alias.rs
tests/rustdoc/tuple-struct-fields-doc.rs
tests/rustdoc/tuples.rs
tests/rustdoc/unit-return.rs
tests/rustdoc/where-sized.rs
tests/rustdoc/where.SWhere_Simd_item-decl.html
tests/rustdoc/where.SWhere_TraitWhere_item-decl.html
tests/rustdoc/where.rs
tests/rustdoc/whitespace-after-where-clause.enum.html
tests/rustdoc/whitespace-after-where-clause.enum2.html
tests/rustdoc/whitespace-after-where-clause.rs
tests/rustdoc/whitespace-after-where-clause.struct.html
tests/rustdoc/whitespace-after-where-clause.struct2.html
tests/rustdoc/whitespace-after-where-clause.trait.html
tests/rustdoc/whitespace-after-where-clause.trait2.html
tests/rustdoc/whitespace-after-where-clause.union.html
tests/rustdoc/whitespace-after-where-clause.union2.html
tests/rustdoc/wrapping.rs
tests/ui/const-generics/generic_const_exprs/single-satisfied-ConstEvaluatable-in-probe.rs [new file with mode: 0644]
tests/ui/fmt/ifmt-unimpl.stderr
tests/ui/fmt/send-sync.stderr
tests/ui/parser/bastion-of-the-turbofish.rs
tests/ui/suggestions/recover-invalid-float-invalid.rs [new file with mode: 0644]
tests/ui/suggestions/recover-invalid-float-invalid.stderr [new file with mode: 0644]
tests/ui/traits/new-solver/unsize-good.rs [new file with mode: 0644]
tests/ui/traits/new-solver/upcast-right-substs.rs [new file with mode: 0644]
tests/ui/traits/new-solver/upcast-wrong-substs.rs [new file with mode: 0644]
tests/ui/traits/new-solver/upcast-wrong-substs.stderr [new file with mode: 0644]

index 11729e2c83f0b9d098788e495a6db5ea5b271ce5..2b81a35052d7b6055eb277fe9c2706abfddbaa9a 100644 (file)
@@ -181,9 +181,6 @@ pub(super) fn ascribe_user_type(
         user_ty: ty::UserType<'tcx>,
         span: Span,
     ) {
-        // FIXME: Ideally MIR types are normalized, but this is not always true.
-        let mir_ty = self.normalize(mir_ty, Locations::All(span));
-
         self.fully_perform_op(
             Locations::All(span),
             ConstraintCategory::Boring,
@@ -217,7 +214,9 @@ pub(super) fn ascribe_user_type_skip_wf(
             return;
         }
 
+        // FIXME: Ideally MIR types are normalized, but this is not always true.
         let mir_ty = self.normalize(mir_ty, Locations::All(span));
+
         let cause = ObligationCause::dummy_with_span(span);
         let param_env = self.param_env;
         let op = |infcx: &'_ _| {
index 4696a4bd9ab63aeab10c4291c451fc93d1eddce4..a063307af0cb4109e7c14dddf7504df9584e9839 100644 (file)
@@ -2263,7 +2263,7 @@ pub struct TraitItem<'hir> {
     pub defaultness: Defaultness,
 }
 
-impl TraitItem<'_> {
+impl<'hir> TraitItem<'hir> {
     #[inline]
     pub fn hir_id(&self) -> HirId {
         // Items are always HIR owners.
@@ -2273,6 +2273,32 @@ pub fn hir_id(&self) -> HirId {
     pub fn trait_item_id(&self) -> TraitItemId {
         TraitItemId { owner_id: self.owner_id }
     }
+
+    /// Expect an [`TraitItemKind::Const`] or panic.
+    #[track_caller]
+    pub fn expect_const(&self) -> (&'hir Ty<'hir>, Option<BodyId>) {
+        let TraitItemKind::Const(ty, body) = self.kind else { self.expect_failed("a constant") };
+        (ty, body)
+    }
+
+    /// Expect an [`TraitItemKind::Fn`] or panic.
+    #[track_caller]
+    pub fn expect_fn(&self) -> (&FnSig<'hir>, &TraitFn<'hir>) {
+        let TraitItemKind::Fn(ty, trfn) = &self.kind else { self.expect_failed("a function") };
+        (ty, trfn)
+    }
+
+    /// Expect an [`TraitItemKind::Type`] or panic.
+    #[track_caller]
+    pub fn expect_type(&self) -> (GenericBounds<'hir>, Option<&'hir Ty<'hir>>) {
+        let TraitItemKind::Type(bounds, ty) = self.kind else { self.expect_failed("a type") };
+        (bounds, ty)
+    }
+
+    #[track_caller]
+    fn expect_failed(&self, expected: &'static str) -> ! {
+        panic!("expected {expected} item, found {self:?}")
+    }
 }
 
 /// Represents a trait method's body (or just argument names).
@@ -2325,7 +2351,7 @@ pub struct ImplItem<'hir> {
     pub vis_span: Span,
 }
 
-impl ImplItem<'_> {
+impl<'hir> ImplItem<'hir> {
     #[inline]
     pub fn hir_id(&self) -> HirId {
         // Items are always HIR owners.
@@ -2335,6 +2361,32 @@ pub fn hir_id(&self) -> HirId {
     pub fn impl_item_id(&self) -> ImplItemId {
         ImplItemId { owner_id: self.owner_id }
     }
+
+    /// Expect an [`ImplItemKind::Const`] or panic.
+    #[track_caller]
+    pub fn expect_const(&self) -> (&'hir Ty<'hir>, BodyId) {
+        let ImplItemKind::Const(ty, body) = self.kind else { self.expect_failed("a constant") };
+        (ty, body)
+    }
+
+    /// Expect an [`ImplItemKind::Fn`] or panic.
+    #[track_caller]
+    pub fn expect_fn(&self) -> (&FnSig<'hir>, BodyId) {
+        let ImplItemKind::Fn(ty, body) = &self.kind else { self.expect_failed("a function") };
+        (ty, *body)
+    }
+
+    /// Expect an [`ImplItemKind::Type`] or panic.
+    #[track_caller]
+    pub fn expect_type(&self) -> &'hir Ty<'hir> {
+        let ImplItemKind::Type(ty) = self.kind else { self.expect_failed("a type") };
+        ty
+    }
+
+    #[track_caller]
+    fn expect_failed(&self, expected: &'static str) -> ! {
+        panic!("expected {expected} item, found {self:?}")
+    }
 }
 
 /// Represents various kinds of content within an `impl`.
@@ -2995,7 +3047,7 @@ pub struct Item<'hir> {
     pub vis_span: Span,
 }
 
-impl Item<'_> {
+impl<'hir> Item<'hir> {
     #[inline]
     pub fn hir_id(&self) -> HirId {
         // Items are always HIR owners.
@@ -3005,6 +3057,132 @@ pub fn hir_id(&self) -> HirId {
     pub fn item_id(&self) -> ItemId {
         ItemId { owner_id: self.owner_id }
     }
+
+    /// Expect an [`ItemKind::ExternCrate`] or panic.
+    #[track_caller]
+    pub fn expect_extern_crate(&self) -> Option<Symbol> {
+        let ItemKind::ExternCrate(s) = self.kind else { self.expect_failed("an extern crate") };
+        s
+    }
+
+    /// Expect an [`ItemKind::Use`] or panic.
+    #[track_caller]
+    pub fn expect_use(&self) -> (&'hir UsePath<'hir>, UseKind) {
+        let ItemKind::Use(p, uk) = self.kind else { self.expect_failed("a use") };
+        (p, uk)
+    }
+
+    /// Expect an [`ItemKind::Static`] or panic.
+    #[track_caller]
+    pub fn expect_static(&self) -> (&'hir Ty<'hir>, Mutability, BodyId) {
+        let ItemKind::Static(ty, mutbl, body) = self.kind else { self.expect_failed("a static") };
+        (ty, mutbl, body)
+    }
+    /// Expect an [`ItemKind::Const`] or panic.
+    #[track_caller]
+    pub fn expect_const(&self) -> (&'hir Ty<'hir>, BodyId) {
+        let ItemKind::Const(ty, body) = self.kind else { self.expect_failed("a constant") };
+        (ty, body)
+    }
+    /// Expect an [`ItemKind::Fn`] or panic.
+    #[track_caller]
+    pub fn expect_fn(&self) -> (&FnSig<'hir>, &'hir Generics<'hir>, BodyId) {
+        let ItemKind::Fn(sig, gen, body) = &self.kind else { self.expect_failed("a function") };
+        (sig, gen, *body)
+    }
+
+    /// Expect an [`ItemKind::Macro`] or panic.
+    #[track_caller]
+    pub fn expect_macro(&self) -> (&ast::MacroDef, MacroKind) {
+        let ItemKind::Macro(def, mk) = &self.kind else { self.expect_failed("a macro") };
+        (def, *mk)
+    }
+
+    /// Expect an [`ItemKind::Mod`] or panic.
+    #[track_caller]
+    pub fn expect_mod(&self) -> &'hir Mod<'hir> {
+        let ItemKind::Mod(m) = self.kind else { self.expect_failed("a module") };
+        m
+    }
+
+    /// Expect an [`ItemKind::ForeignMod`] or panic.
+    #[track_caller]
+    pub fn expect_foreign_mod(&self) -> (Abi, &'hir [ForeignItemRef]) {
+        let ItemKind::ForeignMod { abi, items } = self.kind else { self.expect_failed("a foreign module") };
+        (abi, items)
+    }
+
+    /// Expect an [`ItemKind::GlobalAsm`] or panic.
+    #[track_caller]
+    pub fn expect_global_asm(&self) -> &'hir InlineAsm<'hir> {
+        let ItemKind::GlobalAsm(asm) = self.kind else { self.expect_failed("a global asm") };
+        asm
+    }
+
+    /// Expect an [`ItemKind::TyAlias`] or panic.
+    #[track_caller]
+    pub fn expect_ty_alias(&self) -> (&'hir Ty<'hir>, &'hir Generics<'hir>) {
+        let ItemKind::TyAlias(ty, gen) = self.kind else { self.expect_failed("a type alias") };
+        (ty, gen)
+    }
+
+    /// An opaque `impl Trait` type alias, e.g., `type Foo = impl Bar;`.
+    /// Expect an [`ItemKind::OpaqueTy`] or panic.
+    #[track_caller]
+    pub fn expect_opaque_ty(&self) -> &OpaqueTy<'hir> {
+        let ItemKind::OpaqueTy(ty) = &self.kind else { self.expect_failed("an opaque type") };
+        ty
+    }
+
+    /// Expect an [`ItemKind::Enum`] or panic.
+    #[track_caller]
+    pub fn expect_enum(&self) -> (&EnumDef<'hir>, &'hir Generics<'hir>) {
+        let ItemKind::Enum(def, gen) = &self.kind else { self.expect_failed("an enum") };
+        (def, gen)
+    }
+
+    /// Expect an [`ItemKind::Struct`] or panic.
+    #[track_caller]
+    pub fn expect_struct(&self) -> (&VariantData<'hir>, &'hir Generics<'hir>) {
+        let ItemKind::Struct(data, gen) = &self.kind else { self.expect_failed("a struct") };
+        (data, gen)
+    }
+
+    /// A union definition, e.g., `union Foo<A, B> {x: A, y: B}`.
+    /// Expect an [`ItemKind::Union`] or panic.
+    #[track_caller]
+    pub fn expect_union(&self) -> (&VariantData<'hir>, &'hir Generics<'hir>) {
+        let ItemKind::Union(data, gen) = &self.kind else { self.expect_failed("a union") };
+        (data, gen)
+    }
+
+    /// Expect an [`ItemKind::Trait`] or panic.
+    #[track_caller]
+    pub fn expect_trait(
+        self,
+    ) -> (IsAuto, Unsafety, &'hir Generics<'hir>, GenericBounds<'hir>, &'hir [TraitItemRef]) {
+        let ItemKind::Trait(is_auto, unsafety, gen, bounds, items) = self.kind else { self.expect_failed("a trait") };
+        (is_auto, unsafety, gen, bounds, items)
+    }
+
+    /// Expect an [`ItemKind::TraitAlias`] or panic.
+    #[track_caller]
+    pub fn expect_trait_alias(&self) -> (&'hir Generics<'hir>, GenericBounds<'hir>) {
+        let ItemKind::TraitAlias(gen, bounds) = self.kind else { self.expect_failed("a trait alias") };
+        (gen, bounds)
+    }
+
+    /// Expect an [`ItemKind::Impl`] or panic.
+    #[track_caller]
+    pub fn expect_impl(&self) -> &'hir Impl<'hir> {
+        let ItemKind::Impl(imp) = self.kind else { self.expect_failed("an impl") };
+        imp
+    }
+
+    #[track_caller]
+    fn expect_failed(&self, expected: &'static str) -> ! {
+        panic!("expected {expected} item, found {self:?}")
+    }
 }
 
 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
@@ -3597,6 +3775,185 @@ pub fn fn_kind(self) -> Option<FnKind<'hir>> {
     pub fn tuple_fields(&self) -> Option<&'hir [FieldDef<'hir>]> {
         if let Node::Ctor(&VariantData::Tuple(fields, _, _)) = self { Some(fields) } else { None }
     }
+
+    /// Expect a [`Node::Param`] or panic.
+    #[track_caller]
+    pub fn expect_param(self) -> &'hir Param<'hir> {
+        let Node::Param(this) = self else { self.expect_failed("a parameter") };
+        this
+    }
+
+    /// Expect a [`Node::Item`] or panic.
+    #[track_caller]
+    pub fn expect_item(self) -> &'hir Item<'hir> {
+        let Node::Item(this) = self else { self.expect_failed("a item") };
+        this
+    }
+
+    /// Expect a [`Node::ForeignItem`] or panic.
+    #[track_caller]
+    pub fn expect_foreign_item(self) -> &'hir ForeignItem<'hir> {
+        let Node::ForeignItem(this) = self else { self.expect_failed("a foreign item") };
+        this
+    }
+
+    /// Expect a [`Node::TraitItem`] or panic.
+    #[track_caller]
+    pub fn expect_trait_item(self) -> &'hir TraitItem<'hir> {
+        let Node::TraitItem(this) = self else { self.expect_failed("a trait item") };
+        this
+    }
+
+    /// Expect a [`Node::ImplItem`] or panic.
+    #[track_caller]
+    pub fn expect_impl_item(self) -> &'hir ImplItem<'hir> {
+        let Node::ImplItem(this) = self else { self.expect_failed("an implementation item") };
+        this
+    }
+
+    /// Expect a [`Node::Variant`] or panic.
+    #[track_caller]
+    pub fn expect_variant(self) -> &'hir Variant<'hir> {
+        let Node::Variant(this) = self else { self.expect_failed("a variant") };
+        this
+    }
+
+    /// Expect a [`Node::Field`] or panic.
+    #[track_caller]
+    pub fn expect_field(self) -> &'hir FieldDef<'hir> {
+        let Node::Field(this) = self else { self.expect_failed("a field definition") };
+        this
+    }
+
+    /// Expect a [`Node::AnonConst`] or panic.
+    #[track_caller]
+    pub fn expect_anon_const(self) -> &'hir AnonConst {
+        let Node::AnonConst(this) = self else { self.expect_failed("an anonymous constant") };
+        this
+    }
+
+    /// Expect a [`Node::Expr`] or panic.
+    #[track_caller]
+    pub fn expect_expr(self) -> &'hir Expr<'hir> {
+        let Node::Expr(this) = self else { self.expect_failed("an expression") };
+        this
+    }
+    /// Expect a [`Node::ExprField`] or panic.
+    #[track_caller]
+    pub fn expect_expr_field(self) -> &'hir ExprField<'hir> {
+        let Node::ExprField(this) = self else { self.expect_failed("an expression field") };
+        this
+    }
+
+    /// Expect a [`Node::Stmt`] or panic.
+    #[track_caller]
+    pub fn expect_stmt(self) -> &'hir Stmt<'hir> {
+        let Node::Stmt(this) = self else { self.expect_failed("a statement") };
+        this
+    }
+
+    /// Expect a [`Node::PathSegment`] or panic.
+    #[track_caller]
+    pub fn expect_path_segment(self) -> &'hir PathSegment<'hir> {
+        let Node::PathSegment(this) = self else { self.expect_failed("a path segment") };
+        this
+    }
+
+    /// Expect a [`Node::Ty`] or panic.
+    #[track_caller]
+    pub fn expect_ty(self) -> &'hir Ty<'hir> {
+        let Node::Ty(this) = self else { self.expect_failed("a type") };
+        this
+    }
+
+    /// Expect a [`Node::TypeBinding`] or panic.
+    #[track_caller]
+    pub fn expect_type_binding(self) -> &'hir TypeBinding<'hir> {
+        let Node::TypeBinding(this) = self else { self.expect_failed("a type binding") };
+        this
+    }
+
+    /// Expect a [`Node::TraitRef`] or panic.
+    #[track_caller]
+    pub fn expect_trait_ref(self) -> &'hir TraitRef<'hir> {
+        let Node::TraitRef(this) = self else { self.expect_failed("a trait reference") };
+        this
+    }
+
+    /// Expect a [`Node::Pat`] or panic.
+    #[track_caller]
+    pub fn expect_pat(self) -> &'hir Pat<'hir> {
+        let Node::Pat(this) = self else { self.expect_failed("a pattern") };
+        this
+    }
+
+    /// Expect a [`Node::PatField`] or panic.
+    #[track_caller]
+    pub fn expect_pat_field(self) -> &'hir PatField<'hir> {
+        let Node::PatField(this) = self else { self.expect_failed("a pattern field") };
+        this
+    }
+
+    /// Expect a [`Node::Arm`] or panic.
+    #[track_caller]
+    pub fn expect_arm(self) -> &'hir Arm<'hir> {
+        let Node::Arm(this) = self else { self.expect_failed("an arm") };
+        this
+    }
+
+    /// Expect a [`Node::Block`] or panic.
+    #[track_caller]
+    pub fn expect_block(self) -> &'hir Block<'hir> {
+        let Node::Block(this) = self else { self.expect_failed("a block") };
+        this
+    }
+
+    /// Expect a [`Node::Local`] or panic.
+    #[track_caller]
+    pub fn expect_local(self) -> &'hir Local<'hir> {
+        let Node::Local(this) = self else { self.expect_failed("a local") };
+        this
+    }
+
+    /// Expect a [`Node::Ctor`] or panic.
+    #[track_caller]
+    pub fn expect_ctor(self) -> &'hir VariantData<'hir> {
+        let Node::Ctor(this) = self else { self.expect_failed("a constructor") };
+        this
+    }
+
+    /// Expect a [`Node::Lifetime`] or panic.
+    #[track_caller]
+    pub fn expect_lifetime(self) -> &'hir Lifetime {
+        let Node::Lifetime(this) = self else { self.expect_failed("a lifetime") };
+        this
+    }
+
+    /// Expect a [`Node::GenericParam`] or panic.
+    #[track_caller]
+    pub fn expect_generic_param(self) -> &'hir GenericParam<'hir> {
+        let Node::GenericParam(this) = self else { self.expect_failed("a generic parameter") };
+        this
+    }
+
+    /// Expect a [`Node::Crate`] or panic.
+    #[track_caller]
+    pub fn expect_crate(self) -> &'hir Mod<'hir> {
+        let Node::Crate(this) = self else { self.expect_failed("a crate") };
+        this
+    }
+
+    /// Expect a [`Node::Infer`] or panic.
+    #[track_caller]
+    pub fn expect_infer(self) -> &'hir InferArg {
+        let Node::Infer(this) = self else { self.expect_failed("an infer") };
+        this
+    }
+
+    #[track_caller]
+    fn expect_failed(&self, expected: &'static str) -> ! {
+        panic!("expected {expected} node, found {self:?}")
+    }
 }
 
 // Some nodes are used a lot. Make sure they don't unintentionally get bigger.
index caf26a75d3cc4c18b4bfabcac1af7e84875b0b09..bec9f0ff0772cb8a9862d65f761f07282b4be2cf 100644 (file)
@@ -3140,8 +3140,7 @@ fn suggest_trait_fn_ty_for_impl_fn_infer(
 
         let hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Fn(..), ident, .. }) =
             hir.get(fn_hir_id) else { return None };
-        let hir::Node::Item(hir::Item { kind: hir::ItemKind::Impl(i), .. }) =
-                hir.get_parent(fn_hir_id) else { bug!("ImplItem should have Impl parent") };
+        let i = hir.get_parent(fn_hir_id).expect_item().expect_impl();
 
         let trait_ref = self.instantiate_mono_trait_ref(
             i.of_trait.as_ref()?,
index 780d5271619e7ef90a4af4a0172eb7aaf639ad80..3115f5f464a09c44969f09a03cd1d81db92dd27a 100644 (file)
@@ -8,7 +8,7 @@
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::intravisit;
-use rustc_hir::{GenericParamKind, ImplItemKind, TraitItemKind};
+use rustc_hir::{GenericParamKind, ImplItemKind};
 use rustc_infer::infer::outlives::env::OutlivesEnvironment;
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt};
@@ -918,7 +918,7 @@ fn report_trait_method_mismatch<'tcx>(
             // When the `impl` receiver is an arbitrary self type, like `self: Box<Self>`, the
             // span points only at the type `Box<Self`>, but we want to cover the whole
             // argument pattern and type.
-            let ImplItemKind::Fn(ref sig, body) = tcx.hir().expect_impl_item(impl_m.def_id.expect_local()).kind else { bug!("{impl_m:?} is not a method") };
+            let (sig, body) = tcx.hir().expect_impl_item(impl_m.def_id.expect_local()).expect_fn();
             let span = tcx
                 .hir()
                 .body_param_names(body)
@@ -1080,12 +1080,12 @@ fn extract_spans_for_error_reporting<'tcx>(
 ) -> (Span, Option<Span>) {
     let tcx = infcx.tcx;
     let mut impl_args = {
-        let ImplItemKind::Fn(sig, _) = &tcx.hir().expect_impl_item(impl_m.def_id.expect_local()).kind else { bug!("{:?} is not a method", impl_m) };
+        let (sig, _) = tcx.hir().expect_impl_item(impl_m.def_id.expect_local()).expect_fn();
         sig.decl.inputs.iter().map(|t| t.span).chain(iter::once(sig.decl.output.span()))
     };
 
     let trait_args = trait_m.def_id.as_local().map(|def_id| {
-        let TraitItemKind::Fn(sig, _) = &tcx.hir().expect_trait_item(def_id).kind else { bug!("{:?} is not a TraitItemKind::Fn", trait_m) };
+        let (sig, _) = tcx.hir().expect_trait_item(def_id).expect_fn();
         sig.decl.inputs.iter().map(|t| t.span).chain(iter::once(sig.decl.output.span()))
     });
 
@@ -1358,7 +1358,7 @@ fn compare_number_of_method_arguments<'tcx>(
             .def_id
             .as_local()
             .and_then(|def_id| {
-                let TraitItemKind::Fn(trait_m_sig, _) = &tcx.hir().expect_trait_item(def_id).kind else { bug!("{:?} is not a method", impl_m) };
+                let (trait_m_sig, _) = &tcx.hir().expect_trait_item(def_id).expect_fn();
                 let pos = trait_number_args.saturating_sub(1);
                 trait_m_sig.decl.inputs.get(pos).map(|arg| {
                     if pos == 0 {
@@ -1370,7 +1370,7 @@ fn compare_number_of_method_arguments<'tcx>(
             })
             .or(trait_item_span);
 
-        let ImplItemKind::Fn(impl_m_sig, _) = &tcx.hir().expect_impl_item(impl_m.def_id.expect_local()).kind else { bug!("{:?} is not a method", impl_m) };
+        let (impl_m_sig, _) = &tcx.hir().expect_impl_item(impl_m.def_id.expect_local()).expect_fn();
         let pos = impl_number_args.saturating_sub(1);
         let impl_span = impl_m_sig
             .decl
@@ -1506,7 +1506,7 @@ fn compare_synthetic_generics<'tcx>(
                     let _: Option<_> = try {
                         let impl_m = impl_m.def_id.as_local()?;
                         let impl_m = tcx.hir().expect_impl_item(impl_m);
-                        let hir::ImplItemKind::Fn(sig, _) = &impl_m.kind else { unreachable!() };
+                        let (sig, _) = impl_m.expect_fn();
                         let input_tys = sig.decl.inputs;
 
                         struct Visitor(Option<Span>, hir::def_id::LocalDefId);
@@ -1704,7 +1704,7 @@ pub(super) fn compare_impl_const_raw(
         );
 
         // Locate the Span containing just the type of the offending impl
-        let ImplItemKind::Const(ty, _) = tcx.hir().expect_impl_item(impl_const_item_def).kind else { bug!("{impl_const_item:?} is not a impl const") };
+        let (ty, _) = tcx.hir().expect_impl_item(impl_const_item_def).expect_const();
         cause.span = ty.span;
 
         let mut diag = struct_span_err!(
@@ -1717,7 +1717,7 @@ pub(super) fn compare_impl_const_raw(
 
         let trait_c_span = trait_const_item_def.as_local().map(|trait_c_def_id| {
             // Add a label to the Span containing just the type of the const
-            let TraitItemKind::Const(ty, _) = tcx.hir().expect_trait_item(trait_c_def_id).kind else { bug!("{trait_const_item:?} is not a trait const") };
+            let (ty, _) = tcx.hir().expect_trait_item(trait_c_def_id).expect_const();
             ty.span
         });
 
index 67bcfb1cb70fc0c32605101035fc35fdfdcde64c..5b9b57da3820e48e8a2c42a8364db3971384d272 100644 (file)
@@ -1072,8 +1072,8 @@ fn check_type_defn<'tcx>(tcx: TyCtxt<'tcx>, item: &hir::Item<'tcx>, all_sized: b
             // All field types must be well-formed.
             for field in &variant.fields {
                 let field_id = field.did.expect_local();
-                let hir::Node::Field(hir::FieldDef { ty: hir_ty, .. }) = tcx.hir().get_by_def_id(field_id)
-                else { bug!() };
+                let hir::FieldDef { ty: hir_ty, .. } =
+                    tcx.hir().get_by_def_id(field_id).expect_field();
                 let ty = wfcx.normalize(hir_ty.span, None, tcx.type_of(field.did));
                 wfcx.register_wf_obligation(
                     hir_ty.span,
@@ -1106,8 +1106,8 @@ fn check_type_defn<'tcx>(tcx: TyCtxt<'tcx>, item: &hir::Item<'tcx>, all_sized: b
             {
                 let last = idx == variant.fields.len() - 1;
                 let field_id = field.did.expect_local();
-                let hir::Node::Field(hir::FieldDef { ty: hir_ty, .. }) = tcx.hir().get_by_def_id(field_id)
-                else { bug!() };
+                let hir::FieldDef { ty: hir_ty, .. } =
+                    tcx.hir().get_by_def_id(field_id).expect_field();
                 let ty = wfcx.normalize(hir_ty.span, None, tcx.type_of(field.did));
                 wfcx.register_bound(
                     traits::ObligationCause::new(
index ebb78213a63a13dd052f0b3b4e7c48f5c5acc451..5716be4f1a95445c5f4db941b7c89123f440c13b 100644 (file)
@@ -29,7 +29,7 @@ pub fn check_crate(tcx: TyCtxt<'_>) {
         if item.span.is_dummy() {
             continue;
         }
-        let hir::ItemKind::Use(path, _) = item.kind else { unreachable!() };
+        let (path, _) = item.expect_use();
         let msg = if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(path.span) {
             format!("unused import: `{}`", snippet)
         } else {
index 76668f7e9ac4b0379a5ff9db80e6a20ebe42e003..6600e4216bd1f4a54304af6e41bc128ff22d4670 100644 (file)
@@ -56,7 +56,7 @@ fn visit_implementation_of_drop(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
         _ => {}
     }
 
-    let ItemKind::Impl(impl_) = tcx.hir().expect_item(impl_did).kind else { bug!("expected Drop impl item") };
+    let impl_ = tcx.hir().expect_item(impl_did).expect_impl();
 
     tcx.sess.emit_err(DropImplOnWrongItem { span: impl_.self_ty.span });
 }
index fe6119dce873573baf819591798c33e3ecc19b92..c6b16171311fb0de221c0bbcb9c2c667a7aba35d 100644 (file)
@@ -3,15 +3,13 @@
 
 use rustc_errors::struct_span_err;
 use rustc_hir as hir;
-use rustc_hir::def::DefKind;
 use rustc_hir::Unsafety;
 use rustc_middle::ty::TyCtxt;
 use rustc_span::def_id::LocalDefId;
 
 pub(super) fn check_item(tcx: TyCtxt<'_>, def_id: LocalDefId) {
-    debug_assert!(matches!(tcx.def_kind(def_id), DefKind::Impl));
     let item = tcx.hir().expect_item(def_id);
-    let hir::ItemKind::Impl(impl_) = item.kind else { bug!() };
+    let impl_ = item.expect_impl();
 
     if let Some(trait_ref) = tcx.impl_trait_ref(item.owner_id) {
         let trait_ref = trait_ref.subst_identity();
index f5a1e51c07b2f53edecc49e633318789dfeb08fd..cc7235a61c0b822ef6c9ba0cbc71162b2ab949f9 100644 (file)
@@ -1348,8 +1348,7 @@ fn suggest_impl_trait<'tcx>(
 
 fn impl_trait_ref(tcx: TyCtxt<'_>, def_id: DefId) -> Option<ty::EarlyBinder<ty::TraitRef<'_>>> {
     let icx = ItemCtxt::new(tcx, def_id);
-    let item = tcx.hir().expect_item(def_id.expect_local());
-    let hir::ItemKind::Impl(impl_) = item.kind else { bug!() };
+    let impl_ = tcx.hir().expect_item(def_id.expect_local()).expect_impl();
     impl_
         .of_trait
         .as_ref()
index 29507ff3a86c1dc2f27e66027f67e46ceea53331..9d8f14058f681203548cd2a703b3556b5d6c7129 100644 (file)
@@ -1415,7 +1415,7 @@ fn encode_mir(&mut self) {
             if encode_opt {
                 record!(self.tables.optimized_mir[def_id.to_def_id()] <- tcx.optimized_mir(def_id));
 
-                if let DefKind::Generator = self.tcx.def_kind(def_id) && tcx.sess.opts.unstable_opts.drop_tracking_mir {
+                if tcx.sess.opts.unstable_opts.drop_tracking_mir && let DefKind::Generator = self.tcx.def_kind(def_id) {
                     record!(self.tables.mir_generator_witnesses[def_id.to_def_id()] <- tcx.mir_generator_witnesses(def_id));
                 }
             }
index 1e8d5f7eae87a8881edadb729794f43e43fc9a9e..7a05ee2ff37fdc3dbc3324603b203fec44e59f60 100644 (file)
@@ -318,16 +318,19 @@ pub fn mangle_name(human_readable_name: &str) -> String {
         base_n::encode(hash, base_n::CASE_INSENSITIVE)
     }
 
-    pub fn estimate_size(&mut self, tcx: TyCtxt<'tcx>) {
+    pub fn create_size_estimate(&mut self, tcx: TyCtxt<'tcx>) {
         // Estimate the size of a codegen unit as (approximately) the number of MIR
         // statements it corresponds to.
         self.size_estimate = Some(self.items.keys().map(|mi| mi.size_estimate(tcx)).sum());
     }
 
     #[inline]
+    /// Should only be called if [`create_size_estimate`] has previously been called.
+    ///
+    /// [`create_size_estimate`]: Self::create_size_estimate
     pub fn size_estimate(&self) -> usize {
-        // Should only be called if `estimate_size` has previously been called.
-        self.size_estimate.expect("estimate_size must be called before getting a size_estimate")
+        self.size_estimate
+            .expect("create_size_estimate must be called before getting a size_estimate")
     }
 
     pub fn modify_size_estimate(&mut self, delta: usize) {
index 1eff796e91b3bf01c7a0e839700610d0b61440c2..4cebe416354a928fd423f0cd4c56f68af5d3c253 100644 (file)
         separate_provide_extern
     }
 
+    query unsizing_params_for_adt(key: DefId) -> rustc_index::bit_set::BitSet<u32>
+    {
+        arena_cache
+        desc { |tcx|
+            "determining what parameters of `{}` can participate in unsizing",
+            tcx.def_path_str(key),
+        }
+    }
+
     query analysis(key: ()) -> Result<(), ErrorGuaranteed> {
         eval_always
         desc { "running analysis passes on this crate" }
index 3d9137fa10253cc4934c3f2f8e4d0aa19be96315..6815289776e9372059aecd2df65d93a4d7525efa 100644 (file)
@@ -23,6 +23,7 @@
 use rustc_data_structures::fx::FxIndexSet;
 use rustc_data_structures::steal::Steal;
 use rustc_hir as hir;
+use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::intravisit::{self, Visitor};
 use rustc_index::vec::IndexVec;
@@ -430,7 +431,9 @@ fn mir_drops_elaborated_and_const_checked(
         return tcx.mir_drops_elaborated_and_const_checked(def);
     }
 
-    if tcx.generator_kind(def.did).is_some() && tcx.sess.opts.unstable_opts.drop_tracking_mir {
+    if tcx.sess.opts.unstable_opts.drop_tracking_mir
+        && let DefKind::Generator = tcx.def_kind(def.did)
+    {
         tcx.ensure().mir_generator_witnesses(def.did);
     }
     let mir_borrowck = tcx.mir_borrowck_opt_const_arg(def);
@@ -548,13 +551,13 @@ fn o1<T>(x: T) -> WithMinOptLevel<T> {
         &[
             &reveal_all::RevealAll, // has to be done before inlining, since inlined code is in RevealAll mode.
             &lower_slice_len::LowerSliceLenCalls, // has to be done before inlining, otherwise actual call will be almost always inlined. Also simple, so can just do first
-            &normalize_array_len::NormalizeArrayLen, // has to run after `slice::len` lowering
             &unreachable_prop::UnreachablePropagation,
             &uninhabited_enum_branching::UninhabitedEnumBranching,
             &o1(simplify::SimplifyCfg::new("after-uninhabited-enum-branching")),
             &inline::Inline,
             &remove_storage_markers::RemoveStorageMarkers,
             &remove_zsts::RemoveZsts,
+            &normalize_array_len::NormalizeArrayLen, // has to run after `slice::len` lowering
             &const_goto::ConstGoto,
             &remove_unneeded_drops::RemoveUnneededDrops,
             &sroa::ScalarReplacementOfAggregates,
index 1708b287e56f25bca285136fca3a92649a0bafd6..b36c8a0bd5369b45fbb2864b5302957c576c4d7c 100644 (file)
 //! This pass eliminates casting of arrays into slices when their length
 //! is taken using `.len()` method. Handy to preserve information in MIR for const prop
 
+use crate::ssa::SsaLocals;
 use crate::MirPass;
-use rustc_data_structures::fx::FxIndexMap;
-use rustc_data_structures::intern::Interned;
-use rustc_index::bit_set::BitSet;
 use rustc_index::vec::IndexVec;
+use rustc_middle::mir::visit::*;
 use rustc_middle::mir::*;
-use rustc_middle::ty::{self, ReErased, Region, TyCtxt};
-
-const MAX_NUM_BLOCKS: usize = 800;
-const MAX_NUM_LOCALS: usize = 3000;
+use rustc_middle::ty::{self, TyCtxt};
+use rustc_mir_dataflow::impls::borrowed_locals;
 
 pub struct NormalizeArrayLen;
 
 impl<'tcx> MirPass<'tcx> for NormalizeArrayLen {
     fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
-        // See #105929
-        sess.mir_opt_level() >= 4 && sess.opts.unstable_opts.unsound_mir_opts
+        sess.mir_opt_level() >= 3
     }
 
+    #[instrument(level = "trace", skip(self, tcx, body))]
     fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
-        // early returns for edge cases of highly unrolled functions
-        if body.basic_blocks.len() > MAX_NUM_BLOCKS {
-            return;
-        }
-        if body.local_decls.len() > MAX_NUM_LOCALS {
-            return;
-        }
+        debug!(def_id = ?body.source.def_id());
         normalize_array_len_calls(tcx, body)
     }
 }
 
-pub fn normalize_array_len_calls<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
-    // We don't ever touch terminators, so no need to invalidate the CFG cache
-    let basic_blocks = body.basic_blocks.as_mut_preserves_cfg();
-    let local_decls = &mut body.local_decls;
+fn normalize_array_len_calls<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
+    let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id());
+    let borrowed_locals = borrowed_locals(body);
+    let ssa = SsaLocals::new(tcx, param_env, body, &borrowed_locals);
 
-    // do a preliminary analysis to see if we ever have locals of type `[T;N]` or `&[T;N]`
-    let mut interesting_locals = BitSet::new_empty(local_decls.len());
-    for (local, decl) in local_decls.iter_enumerated() {
-        match decl.ty.kind() {
-            ty::Array(..) => {
-                interesting_locals.insert(local);
-            }
-            ty::Ref(.., ty, Mutability::Not) => match ty.kind() {
-                ty::Array(..) => {
-                    interesting_locals.insert(local);
-                }
-                _ => {}
-            },
-            _ => {}
-        }
-    }
-    if interesting_locals.is_empty() {
-        // we have found nothing to analyze
-        return;
-    }
-    let num_intesting_locals = interesting_locals.count();
-    let mut state = FxIndexMap::with_capacity_and_hasher(num_intesting_locals, Default::default());
-    let mut patches_scratchpad =
-        FxIndexMap::with_capacity_and_hasher(num_intesting_locals, Default::default());
-    let mut replacements_scratchpad =
-        FxIndexMap::with_capacity_and_hasher(num_intesting_locals, Default::default());
-    for block in basic_blocks {
-        // make length calls for arrays [T; N] not to decay into length calls for &[T]
-        // that forbids constant propagation
-        normalize_array_len_call(
-            tcx,
-            block,
-            local_decls,
-            &interesting_locals,
-            &mut state,
-            &mut patches_scratchpad,
-            &mut replacements_scratchpad,
-        );
-        state.clear();
-        patches_scratchpad.clear();
-        replacements_scratchpad.clear();
-    }
-}
+    let slice_lengths = compute_slice_length(tcx, &ssa, body);
+    debug!(?slice_lengths);
 
-struct Patcher<'a, 'tcx> {
-    tcx: TyCtxt<'tcx>,
-    patches_scratchpad: &'a FxIndexMap<usize, usize>,
-    replacements_scratchpad: &'a mut FxIndexMap<usize, Local>,
-    local_decls: &'a mut IndexVec<Local, LocalDecl<'tcx>>,
-    statement_idx: usize,
+    Replacer { tcx, slice_lengths }.visit_body_preserves_cfg(body);
 }
 
-impl<'tcx> Patcher<'_, 'tcx> {
-    fn patch_expand_statement(
-        &mut self,
-        statement: &mut Statement<'tcx>,
-    ) -> Option<std::vec::IntoIter<Statement<'tcx>>> {
-        let idx = self.statement_idx;
-        if let Some(len_statemnt_idx) = self.patches_scratchpad.get(&idx).copied() {
-            let mut statements = Vec::with_capacity(2);
-
-            // we are at statement that performs a cast. The only sound way is
-            // to create another local that performs a similar copy without a cast and then
-            // use this copy in the Len operation
-
-            match &statement.kind {
-                StatementKind::Assign(box (
-                    ..,
-                    Rvalue::Cast(
-                        CastKind::Pointer(ty::adjustment::PointerCast::Unsize),
-                        operand,
-                        _,
-                    ),
-                )) => {
-                    match operand {
-                        Operand::Copy(place) | Operand::Move(place) => {
-                            // create new local
-                            let ty = operand.ty(self.local_decls, self.tcx);
-                            let local_decl = LocalDecl::with_source_info(ty, statement.source_info);
-                            let local = self.local_decls.push(local_decl);
-                            // make it live
-                            let mut make_live_statement = statement.clone();
-                            make_live_statement.kind = StatementKind::StorageLive(local);
-                            statements.push(make_live_statement);
-                            // copy into it
-
-                            let operand = Operand::Copy(*place);
-                            let mut make_copy_statement = statement.clone();
-                            let assign_to = Place::from(local);
-                            let rvalue = Rvalue::Use(operand);
-                            make_copy_statement.kind =
-                                StatementKind::Assign(Box::new((assign_to, rvalue)));
-                            statements.push(make_copy_statement);
-
-                            // to reorder we have to copy and make NOP
-                            statements.push(statement.clone());
-                            statement.make_nop();
-
-                            self.replacements_scratchpad.insert(len_statemnt_idx, local);
-                        }
-                        _ => {
-                            unreachable!("it's a bug in the implementation")
-                        }
-                    }
-                }
-                _ => {
-                    unreachable!("it's a bug in the implementation")
+fn compute_slice_length<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    ssa: &SsaLocals,
+    body: &Body<'tcx>,
+) -> IndexVec<Local, Option<ty::Const<'tcx>>> {
+    let mut slice_lengths = IndexVec::from_elem(None, &body.local_decls);
+
+    for (local, rvalue) in ssa.assignments(body) {
+        match rvalue {
+            Rvalue::Cast(
+                CastKind::Pointer(ty::adjustment::PointerCast::Unsize),
+                operand,
+                cast_ty,
+            ) => {
+                let operand_ty = operand.ty(body, tcx);
+                debug!(?operand_ty);
+                if let Some(operand_ty) = operand_ty.builtin_deref(true)
+                    && let ty::Array(_, len) = operand_ty.ty.kind()
+                    && let Some(cast_ty) = cast_ty.builtin_deref(true)
+                    && let ty::Slice(..) = cast_ty.ty.kind()
+                {
+                    slice_lengths[local] = Some(*len);
                 }
             }
-
-            self.statement_idx += 1;
-
-            Some(statements.into_iter())
-        } else if let Some(local) = self.replacements_scratchpad.get(&idx).copied() {
-            let mut statements = Vec::with_capacity(2);
-
-            match &statement.kind {
-                StatementKind::Assign(box (into, Rvalue::Len(place))) => {
-                    let add_deref = if let Some(..) = place.as_local() {
-                        false
-                    } else if let Some(..) = place.local_or_deref_local() {
-                        true
-                    } else {
-                        unreachable!("it's a bug in the implementation")
-                    };
-                    // replace len statement
-                    let mut len_statement = statement.clone();
-                    let mut place = Place::from(local);
-                    if add_deref {
-                        place = self.tcx.mk_place_deref(place);
-                    }
-                    len_statement.kind =
-                        StatementKind::Assign(Box::new((*into, Rvalue::Len(place))));
-                    statements.push(len_statement);
-
-                    // make temporary dead
-                    let mut make_dead_statement = statement.clone();
-                    make_dead_statement.kind = StatementKind::StorageDead(local);
-                    statements.push(make_dead_statement);
-
-                    // make original statement NOP
-                    statement.make_nop();
+            // The length information is stored in the fat pointer, so we treat `operand` as a value.
+            Rvalue::Use(operand) => {
+                if let Some(rhs) = operand.place() && let Some(rhs) = rhs.as_local() {
+                    slice_lengths[local] = slice_lengths[rhs];
                 }
-                _ => {
-                    unreachable!("it's a bug in the implementation")
+            }
+            // The length information is stored in the fat pointer.
+            // Reborrowing copies length information from one pointer to the other.
+            Rvalue::Ref(_, _, rhs) | Rvalue::AddressOf(_, rhs) => {
+                if let [PlaceElem::Deref] = rhs.projection[..] {
+                    slice_lengths[local] = slice_lengths[rhs.local];
                 }
             }
-
-            self.statement_idx += 1;
-
-            Some(statements.into_iter())
-        } else {
-            self.statement_idx += 1;
-            None
+            _ => {}
         }
     }
+
+    slice_lengths
 }
 
-fn normalize_array_len_call<'tcx>(
+struct Replacer<'tcx> {
     tcx: TyCtxt<'tcx>,
-    block: &mut BasicBlockData<'tcx>,
-    local_decls: &mut IndexVec<Local, LocalDecl<'tcx>>,
-    interesting_locals: &BitSet<Local>,
-    state: &mut FxIndexMap<Local, usize>,
-    patches_scratchpad: &mut FxIndexMap<usize, usize>,
-    replacements_scratchpad: &mut FxIndexMap<usize, Local>,
-) {
-    for (statement_idx, statement) in block.statements.iter_mut().enumerate() {
-        match &mut statement.kind {
-            StatementKind::Assign(box (place, rvalue)) => {
-                match rvalue {
-                    Rvalue::Cast(
-                        CastKind::Pointer(ty::adjustment::PointerCast::Unsize),
-                        operand,
-                        cast_ty,
-                    ) => {
-                        let Some(local) = place.as_local() else { return };
-                        match operand {
-                            Operand::Copy(place) | Operand::Move(place) => {
-                                let Some(operand_local) = place.local_or_deref_local() else { return; };
-                                if !interesting_locals.contains(operand_local) {
-                                    return;
-                                }
-                                let operand_ty = local_decls[operand_local].ty;
-                                match (operand_ty.kind(), cast_ty.kind()) {
-                                    (ty::Array(of_ty_src, ..), ty::Slice(of_ty_dst)) => {
-                                        if of_ty_src == of_ty_dst {
-                                            // this is a cast from [T; N] into [T], so we are good
-                                            state.insert(local, statement_idx);
-                                        }
-                                    }
-                                    // current way of patching doesn't allow to work with `mut`
-                                    (
-                                        ty::Ref(
-                                            Region(Interned(ReErased, _)),
-                                            operand_ty,
-                                            Mutability::Not,
-                                        ),
-                                        ty::Ref(
-                                            Region(Interned(ReErased, _)),
-                                            cast_ty,
-                                            Mutability::Not,
-                                        ),
-                                    ) => {
-                                        match (operand_ty.kind(), cast_ty.kind()) {
-                                            // current way of patching doesn't allow to work with `mut`
-                                            (ty::Array(of_ty_src, ..), ty::Slice(of_ty_dst)) => {
-                                                if of_ty_src == of_ty_dst {
-                                                    // this is a cast from [T; N] into [T], so we are good
-                                                    state.insert(local, statement_idx);
-                                                }
-                                            }
-                                            _ => {}
-                                        }
-                                    }
-                                    _ => {}
-                                }
-                            }
-                            _ => {}
-                        }
-                    }
-                    Rvalue::Len(place) => {
-                        let Some(local) = place.local_or_deref_local() else {
-                            return;
-                        };
-                        if let Some(cast_statement_idx) = state.get(&local).copied() {
-                            patches_scratchpad.insert(cast_statement_idx, statement_idx);
-                        }
-                    }
-                    _ => {
-                        // invalidate
-                        state.remove(&place.local);
-                    }
-                }
-            }
-            _ => {}
-        }
-    }
+    slice_lengths: IndexVec<Local, Option<ty::Const<'tcx>>>,
+}
 
-    let mut patcher = Patcher {
-        tcx,
-        patches_scratchpad: &*patches_scratchpad,
-        replacements_scratchpad,
-        local_decls,
-        statement_idx: 0,
-    };
+impl<'tcx> MutVisitor<'tcx> for Replacer<'tcx> {
+    fn tcx(&self) -> TyCtxt<'tcx> {
+        self.tcx
+    }
 
-    block.expand_statements(|st| patcher.patch_expand_statement(st));
+    fn visit_rvalue(&mut self, rvalue: &mut Rvalue<'tcx>, loc: Location) {
+        if let Rvalue::Len(place) = rvalue
+            && let [PlaceElem::Deref] = &place.projection[..]
+            && let Some(len) = self.slice_lengths[place.local]
+        {
+            *rvalue = Rvalue::Use(Operand::Constant(Box::new(Constant {
+                span: rustc_span::DUMMY_SP,
+                user_ty: None,
+                literal: ConstantKind::from_const(len, self.tcx),
+            })));
+        }
+        self.super_rvalue(rvalue, loc);
+    }
 }
index af3f60bb9326d6f0796e480a5b2c5f8f6d74efcc..524c51d88d75519260e767a6980036206b2932c2 100644 (file)
@@ -182,7 +182,7 @@ pub fn partition<'tcx>(
         partitioner.place_root_mono_items(cx, mono_items)
     };
 
-    initial_partitioning.codegen_units.iter_mut().for_each(|cgu| cgu.estimate_size(tcx));
+    initial_partitioning.codegen_units.iter_mut().for_each(|cgu| cgu.create_size_estimate(tcx));
 
     debug_dump(tcx, "INITIAL PARTITIONING:", initial_partitioning.codegen_units.iter());
 
@@ -202,7 +202,7 @@ pub fn partition<'tcx>(
         partitioner.place_inlined_mono_items(cx, initial_partitioning)
     };
 
-    post_inlining.codegen_units.iter_mut().for_each(|cgu| cgu.estimate_size(tcx));
+    post_inlining.codegen_units.iter_mut().for_each(|cgu| cgu.create_size_estimate(tcx));
 
     debug_dump(tcx, "POST INLINING:", post_inlining.codegen_units.iter());
 
index 17d1e200b41aab6bd677a8e0c9e19d7104194056..dcc3059a7f44ca5d7838bf4873d76ae511833a33 100644 (file)
@@ -1882,7 +1882,16 @@ fn recover_after_dot(&mut self) -> Option<Token> {
                 if let token::Literal(token::Lit { kind: token::Integer, symbol, suffix }) =
                     next_token.kind
                 {
-                    if self.token.span.hi() == next_token.span.lo() {
+                    // If this integer looks like a float, then recover as such.
+                    //
+                    // We will never encounter the exponent part of a floating
+                    // point literal here, since there's no use of the exponent
+                    // syntax that also constitutes a valid integer, so we need
+                    // not check for that.
+                    if suffix.map_or(true, |s| s == sym::f32 || s == sym::f64)
+                        && symbol.as_str().chars().all(|c| c.is_numeric() || c == '_')
+                        && self.token.span.hi() == next_token.span.lo()
+                    {
                         let s = String::from("0.") + symbol.as_str();
                         let kind = TokenKind::lit(token::Float, Symbol::intern(&s), suffix);
                         return Some(Token::new(kind, self.token.span.to(next_token.span)));
index 127acb46e9242c36de20f6d42ddb098020d5445c..83adfeb6b10b6ef2c5d317bb28172c131e335fd9 100644 (file)
@@ -459,30 +459,32 @@ fn visit_anon_const(&mut self, c: &'tcx hir::AnonConst) {
 }
 
 fn has_allow_dead_code_or_lang_attr(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
-    if tcx.has_attr(def_id.to_def_id(), sym::lang) {
-        return true;
+    fn has_lang_attr(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
+        tcx.has_attr(def_id.to_def_id(), sym::lang)
+            // Stable attribute for #[lang = "panic_impl"]
+            || tcx.has_attr(def_id.to_def_id(), sym::panic_handler)
     }
 
-    // Stable attribute for #[lang = "panic_impl"]
-    if tcx.has_attr(def_id.to_def_id(), sym::panic_handler) {
-        return true;
+    fn has_allow_dead_code(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
+        let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
+        tcx.lint_level_at_node(lint::builtin::DEAD_CODE, hir_id).0 == lint::Allow
     }
 
-    if tcx.def_kind(def_id).has_codegen_attrs() {
-        let cg_attrs = tcx.codegen_fn_attrs(def_id);
+    fn has_used_like_attr(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
+        tcx.def_kind(def_id).has_codegen_attrs() && {
+            let cg_attrs = tcx.codegen_fn_attrs(def_id);
 
-        // #[used], #[no_mangle], #[export_name], etc also keeps the item alive
-        // forcefully, e.g., for placing it in a specific section.
-        if cg_attrs.contains_extern_indicator()
-            || cg_attrs.flags.contains(CodegenFnAttrFlags::USED)
-            || cg_attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER)
-        {
-            return true;
+            // #[used], #[no_mangle], #[export_name], etc also keeps the item alive
+            // forcefully, e.g., for placing it in a specific section.
+            cg_attrs.contains_extern_indicator()
+                || cg_attrs.flags.contains(CodegenFnAttrFlags::USED)
+                || cg_attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER)
         }
     }
 
-    let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
-    tcx.lint_level_at_node(lint::builtin::DEAD_CODE, hir_id).0 == lint::Allow
+    has_allow_dead_code(tcx, def_id)
+        || has_used_like_attr(tcx, def_id)
+        || has_lang_attr(tcx, def_id)
 }
 
 // These check_* functions seeds items that
index e44fd82ba22362d1b26e06032c275027e36c39a2..5690b6536bbc0b9e8ce7a96414999fed495a5a40 100644 (file)
@@ -173,6 +173,21 @@ fn consider_builtin_generator_candidate(
         ecx: &mut EvalCtxt<'_, 'tcx>,
         goal: Goal<'tcx, Self>,
     ) -> QueryResult<'tcx>;
+
+    // The most common forms of unsizing are array to slice, and concrete (Sized)
+    // type into a `dyn Trait`. ADTs and Tuples can also have their final field
+    // unsized if it's generic.
+    fn consider_builtin_unsize_candidate(
+        ecx: &mut EvalCtxt<'_, 'tcx>,
+        goal: Goal<'tcx, Self>,
+    ) -> QueryResult<'tcx>;
+
+    // `dyn Trait1` can be unsized to `dyn Trait2` if they are the same trait, or
+    // if `Trait2` is a (transitive) supertrait of `Trait2`.
+    fn consider_builtin_dyn_upcast_candidates(
+        ecx: &mut EvalCtxt<'_, 'tcx>,
+        goal: Goal<'tcx, Self>,
+    ) -> Vec<CanonicalResponse<'tcx>>;
 }
 
 impl<'tcx> EvalCtxt<'_, 'tcx> {
@@ -303,6 +318,8 @@ fn assemble_builtin_impl_candidates<G: GoalKind<'tcx>>(
             G::consider_builtin_future_candidate(self, goal)
         } else if lang_items.gen_trait() == Some(trait_def_id) {
             G::consider_builtin_generator_candidate(self, goal)
+        } else if lang_items.unsize_trait() == Some(trait_def_id) {
+            G::consider_builtin_unsize_candidate(self, goal)
         } else {
             Err(NoSolution)
         };
@@ -313,6 +330,14 @@ fn assemble_builtin_impl_candidates<G: GoalKind<'tcx>>(
             }
             Err(NoSolution) => (),
         }
+
+        // There may be multiple unsize candidates for a trait with several supertraits:
+        // `trait Foo: Bar<A> + Bar<B>` and `dyn Foo: Unsize<dyn Bar<_>>`
+        if lang_items.unsize_trait() == Some(trait_def_id) {
+            for result in G::consider_builtin_dyn_upcast_candidates(self, goal) {
+                candidates.push(Candidate { source: CandidateSource::BuiltinImpl, result });
+            }
+        }
     }
 
     fn assemble_param_env_candidates<G: GoalKind<'tcx>>(
index b175a6dde179f1378ab0570c69607a5bbce246df..879f18843c9171def566dea30e95cf45e33d6d4c 100644 (file)
@@ -554,6 +554,20 @@ fn consider_builtin_generator_candidate(
             .to_predicate(tcx),
         )
     }
+
+    fn consider_builtin_unsize_candidate(
+        _ecx: &mut EvalCtxt<'_, 'tcx>,
+        goal: Goal<'tcx, Self>,
+    ) -> QueryResult<'tcx> {
+        bug!("`Unsize` does not have an associated type: {:?}", goal);
+    }
+
+    fn consider_builtin_dyn_upcast_candidates(
+        _ecx: &mut EvalCtxt<'_, 'tcx>,
+        goal: Goal<'tcx, Self>,
+    ) -> Vec<super::CanonicalResponse<'tcx>> {
+        bug!("`Unsize` does not have an associated type: {:?}", goal);
+    }
 }
 
 /// This behavior is also implemented in `rustc_ty_utils` and in the old `project` code.
index 1ea8fb8fd3dcc8d0d40a2c9dd415e46d808bc101..29ee9da38e08be5b391709294baac16b1630236b 100644 (file)
@@ -4,10 +4,11 @@
 
 use super::assembly::{self, Candidate, CandidateSource};
 use super::infcx_ext::InferCtxtExt;
-use super::{Certainty, EvalCtxt, Goal, QueryResult};
+use super::{CanonicalResponse, Certainty, EvalCtxt, Goal, QueryResult};
 use rustc_hir::def_id::DefId;
 use rustc_infer::infer::InferCtxt;
 use rustc_infer::traits::query::NoSolution;
+use rustc_infer::traits::util::supertraits;
 use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
 use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt};
 use rustc_middle::ty::{TraitPredicate, TypeVisitable};
@@ -238,6 +239,206 @@ fn consider_builtin_generator_candidate(
             .to_predicate(tcx),
         )
     }
+
+    fn consider_builtin_unsize_candidate(
+        ecx: &mut EvalCtxt<'_, 'tcx>,
+        goal: Goal<'tcx, Self>,
+    ) -> QueryResult<'tcx> {
+        let tcx = ecx.tcx();
+        let a_ty = goal.predicate.self_ty();
+        let b_ty = goal.predicate.trait_ref.substs.type_at(1);
+        if b_ty.is_ty_var() {
+            return ecx.make_canonical_response(Certainty::AMBIGUOUS);
+        }
+        ecx.infcx.probe(|_| {
+            match (a_ty.kind(), b_ty.kind()) {
+                // Trait upcasting, or `dyn Trait + Auto + 'a` -> `dyn Trait + 'b`
+                (&ty::Dynamic(_, _, ty::Dyn), &ty::Dynamic(_, _, ty::Dyn)) => {
+                    // Dyn upcasting is handled separately, since due to upcasting,
+                    // when there are two supertraits that differ by substs, we
+                    // may return more than one query response.
+                    return Err(NoSolution);
+                }
+                // `T` -> `dyn Trait` unsizing
+                (_, &ty::Dynamic(data, region, ty::Dyn)) => {
+                    // Can only unsize to an object-safe type
+                    if data
+                        .principal_def_id()
+                        .map_or(false, |def_id| !tcx.check_is_object_safe(def_id))
+                    {
+                        return Err(NoSolution);
+                    }
+
+                    let Some(sized_def_id) = tcx.lang_items().sized_trait() else {
+                        return Err(NoSolution);
+                    };
+                    let nested_goals: Vec<_> = data
+                        .iter()
+                        // Check that the type implements all of the predicates of the def-id.
+                        // (i.e. the principal, all of the associated types match, and any auto traits)
+                        .map(|pred| goal.with(tcx, pred.with_self_ty(tcx, a_ty)))
+                        .chain([
+                            // The type must be Sized to be unsized.
+                            goal.with(
+                                tcx,
+                                ty::Binder::dummy(tcx.mk_trait_ref(sized_def_id, [a_ty])),
+                            ),
+                            // The type must outlive the lifetime of the `dyn` we're unsizing into.
+                            goal.with(tcx, ty::Binder::dummy(ty::OutlivesPredicate(a_ty, region))),
+                        ])
+                        .collect();
+
+                    ecx.evaluate_all_and_make_canonical_response(nested_goals)
+                }
+                // `[T; n]` -> `[T]` unsizing
+                (&ty::Array(a_elem_ty, ..), &ty::Slice(b_elem_ty)) => {
+                    // We just require that the element type stays the same
+                    let nested_goals = ecx.infcx.eq(goal.param_env, a_elem_ty, b_elem_ty)?;
+                    ecx.evaluate_all_and_make_canonical_response(nested_goals)
+                }
+                // Struct unsizing `Struct<T>` -> `Struct<U>` where `T: Unsize<U>`
+                (&ty::Adt(a_def, a_substs), &ty::Adt(b_def, b_substs))
+                    if a_def.is_struct() && a_def.did() == b_def.did() =>
+                {
+                    let unsizing_params = tcx.unsizing_params_for_adt(a_def.did());
+                    // We must be unsizing some type parameters. This also implies
+                    // that the struct has a tail field.
+                    if unsizing_params.is_empty() {
+                        return Err(NoSolution);
+                    }
+
+                    let tail_field = a_def
+                        .non_enum_variant()
+                        .fields
+                        .last()
+                        .expect("expected unsized ADT to have a tail field");
+                    let tail_field_ty = tcx.bound_type_of(tail_field.did);
+
+                    let a_tail_ty = tail_field_ty.subst(tcx, a_substs);
+                    let b_tail_ty = tail_field_ty.subst(tcx, b_substs);
+
+                    // Substitute just the unsizing params from B into A. The type after
+                    // this substitution must be equal to B. This is so we don't unsize
+                    // unrelated type parameters.
+                    let new_a_substs = tcx.mk_substs(a_substs.iter().enumerate().map(|(i, a)| {
+                        if unsizing_params.contains(i as u32) { b_substs[i] } else { a }
+                    }));
+                    let unsized_a_ty = tcx.mk_adt(a_def, new_a_substs);
+
+                    // Finally, we require that `TailA: Unsize<TailB>` for the tail field
+                    // types.
+                    let mut nested_goals = ecx.infcx.eq(goal.param_env, unsized_a_ty, b_ty)?;
+                    nested_goals.push(goal.with(
+                        tcx,
+                        ty::Binder::dummy(
+                            tcx.mk_trait_ref(goal.predicate.def_id(), [a_tail_ty, b_tail_ty]),
+                        ),
+                    ));
+
+                    ecx.evaluate_all_and_make_canonical_response(nested_goals)
+                }
+                // Tuple unsizing `(.., T)` -> `(.., U)` where `T: Unsize<U>`
+                (&ty::Tuple(a_tys), &ty::Tuple(b_tys))
+                    if a_tys.len() == b_tys.len() && !a_tys.is_empty() =>
+                {
+                    let (a_last_ty, a_rest_tys) = a_tys.split_last().unwrap();
+                    let b_last_ty = b_tys.last().unwrap();
+
+                    // Substitute just the tail field of B., and require that they're equal.
+                    let unsized_a_ty = tcx.mk_tup(a_rest_tys.iter().chain([b_last_ty]));
+                    let mut nested_goals = ecx.infcx.eq(goal.param_env, unsized_a_ty, b_ty)?;
+
+                    // Similar to ADTs, require that the rest of the fields are equal.
+                    nested_goals.push(goal.with(
+                        tcx,
+                        ty::Binder::dummy(
+                            tcx.mk_trait_ref(goal.predicate.def_id(), [*a_last_ty, *b_last_ty]),
+                        ),
+                    ));
+
+                    ecx.evaluate_all_and_make_canonical_response(nested_goals)
+                }
+                _ => Err(NoSolution),
+            }
+        })
+    }
+
+    fn consider_builtin_dyn_upcast_candidates(
+        ecx: &mut EvalCtxt<'_, 'tcx>,
+        goal: Goal<'tcx, Self>,
+    ) -> Vec<CanonicalResponse<'tcx>> {
+        let tcx = ecx.tcx();
+
+        let a_ty = goal.predicate.self_ty();
+        let b_ty = goal.predicate.trait_ref.substs.type_at(1);
+        let ty::Dynamic(a_data, a_region, ty::Dyn) = *a_ty.kind() else {
+            return vec![];
+        };
+        let ty::Dynamic(b_data, b_region, ty::Dyn) = *b_ty.kind() else {
+            return vec![];
+        };
+
+        // All of a's auto traits need to be in b's auto traits.
+        let auto_traits_compatible =
+            b_data.auto_traits().all(|b| a_data.auto_traits().any(|a| a == b));
+        if !auto_traits_compatible {
+            return vec![];
+        }
+
+        let mut unsize_dyn_to_principal = |principal: Option<ty::PolyExistentialTraitRef<'tcx>>| {
+            ecx.infcx.probe(|_| -> Result<_, NoSolution> {
+                // Require that all of the trait predicates from A match B, except for
+                // the auto traits. We do this by constructing a new A type with B's
+                // auto traits, and equating these types.
+                let new_a_data = principal
+                    .into_iter()
+                    .map(|trait_ref| trait_ref.map_bound(ty::ExistentialPredicate::Trait))
+                    .chain(a_data.iter().filter(|a| {
+                        matches!(a.skip_binder(), ty::ExistentialPredicate::Projection(_))
+                    }))
+                    .chain(
+                        b_data
+                            .auto_traits()
+                            .map(ty::ExistentialPredicate::AutoTrait)
+                            .map(ty::Binder::dummy),
+                    );
+                let new_a_data = tcx.mk_poly_existential_predicates(new_a_data);
+                let new_a_ty = tcx.mk_dynamic(new_a_data, b_region, ty::Dyn);
+
+                // We also require that A's lifetime outlives B's lifetime.
+                let mut nested_obligations = ecx.infcx.eq(goal.param_env, new_a_ty, b_ty)?;
+                nested_obligations.push(
+                    goal.with(tcx, ty::Binder::dummy(ty::OutlivesPredicate(a_region, b_region))),
+                );
+
+                ecx.evaluate_all_and_make_canonical_response(nested_obligations)
+            })
+        };
+
+        let mut responses = vec![];
+        // If the principal def ids match (or are both none), then we're not doing
+        // trait upcasting. We're just removing auto traits (or shortening the lifetime).
+        if a_data.principal_def_id() == b_data.principal_def_id() {
+            if let Ok(response) = unsize_dyn_to_principal(a_data.principal()) {
+                responses.push(response);
+            }
+        } else if let Some(a_principal) = a_data.principal()
+            && let Some(b_principal) = b_data.principal()
+        {
+            for super_trait_ref in supertraits(tcx, a_principal.with_self_ty(tcx, a_ty)) {
+                if super_trait_ref.def_id() != b_principal.def_id() {
+                    continue;
+                }
+                let erased_trait_ref = super_trait_ref
+                    .map_bound(|trait_ref| ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref));
+                if let Ok(response) = unsize_dyn_to_principal(Some(erased_trait_ref)) {
+                    responses.push(response);
+                }
+            }
+        }
+
+        responses
+    }
 }
 
 impl<'tcx> EvalCtxt<'_, 'tcx> {
index f779d9dd8d93560302988bd9d03d981eda133ae8..786473457ae43c27d9805256d2b478a0ae88ec45 100644 (file)
@@ -219,7 +219,7 @@ fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
     }
 
     if let Some(Ok(c)) = single_match {
-        let ocx = ObligationCtxt::new(infcx);
+        let ocx = ObligationCtxt::new_in_snapshot(infcx);
         assert!(ocx.eq(&ObligationCause::dummy(), param_env, c.ty(), ct.ty()).is_ok());
         assert!(ocx.eq(&ObligationCause::dummy(), param_env, c, ct).is_ok());
         assert!(ocx.select_all_or_error().is_empty());
index 9c84bfaad492bce593d072a43b55c36bda4c707d..89a8fdbac1cbc7794ae63b2d01c47a6da3da3d95 100644 (file)
@@ -8,12 +8,11 @@
 //! https://rustc-dev-guide.rust-lang.org/traits/resolution.html#confirmation
 use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_hir::lang_items::LangItem;
-use rustc_index::bit_set::GrowableBitSet;
 use rustc_infer::infer::InferOk;
 use rustc_infer::infer::LateBoundRegionConversionTime::HigherRankedType;
 use rustc_middle::ty::{
-    self, Binder, GenericArg, GenericArgKind, GenericParamDefKind, InternalSubsts, SubstsRef,
-    ToPolyTraitRef, ToPredicate, TraitRef, Ty, TyCtxt, TypeVisitable,
+    self, Binder, GenericParamDefKind, InternalSubsts, SubstsRef, ToPolyTraitRef, ToPredicate,
+    TraitRef, Ty, TyCtxt, TypeVisitable,
 };
 use rustc_session::config::TraitSolver;
 use rustc_span::def_id::DefId;
@@ -1064,51 +1063,18 @@ fn confirm_builtin_unsize_candidate(
 
             // `Struct<T>` -> `Struct<U>`
             (&ty::Adt(def, substs_a), &ty::Adt(_, substs_b)) => {
-                let maybe_unsizing_param_idx = |arg: GenericArg<'tcx>| match arg.unpack() {
-                    GenericArgKind::Type(ty) => match ty.kind() {
-                        ty::Param(p) => Some(p.index),
-                        _ => None,
-                    },
-
-                    // Lifetimes aren't allowed to change during unsizing.
-                    GenericArgKind::Lifetime(_) => None,
-
-                    GenericArgKind::Const(ct) => match ct.kind() {
-                        ty::ConstKind::Param(p) => Some(p.index),
-                        _ => None,
-                    },
-                };
-
-                // FIXME(eddyb) cache this (including computing `unsizing_params`)
-                // by putting it in a query; it would only need the `DefId` as it
-                // looks at declared field types, not anything substituted.
-
-                // The last field of the structure has to exist and contain type/const parameters.
-                let (tail_field, prefix_fields) =
-                    def.non_enum_variant().fields.split_last().ok_or(Unimplemented)?;
-                let tail_field_ty = tcx.bound_type_of(tail_field.did);
-
-                let mut unsizing_params = GrowableBitSet::new_empty();
-                for arg in tail_field_ty.0.walk() {
-                    if let Some(i) = maybe_unsizing_param_idx(arg) {
-                        unsizing_params.insert(i);
-                    }
-                }
-
-                // Ensure none of the other fields mention the parameters used
-                // in unsizing.
-                for field in prefix_fields {
-                    for arg in tcx.type_of(field.did).walk() {
-                        if let Some(i) = maybe_unsizing_param_idx(arg) {
-                            unsizing_params.remove(i);
-                        }
-                    }
-                }
-
+                let unsizing_params = tcx.unsizing_params_for_adt(def.did());
                 if unsizing_params.is_empty() {
                     return Err(Unimplemented);
                 }
 
+                let tail_field = def
+                    .non_enum_variant()
+                    .fields
+                    .last()
+                    .expect("expected unsized ADT to have a tail field");
+                let tail_field_ty = tcx.bound_type_of(tail_field.did);
+
                 // Extract `TailField<T>` and `TailField<U>` from `Struct<T>` and `Struct<U>`,
                 // normalizing in the process, since `type_of` returns something directly from
                 // astconv (which means it's un-normalized).
index 89abffebdc68406b887a4b73f54303a3164065ba..41e837e8b754e64608bb58321c5f28b287f56ac2 100644 (file)
@@ -1,5 +1,6 @@
 use rustc_data_structures::fx::FxIndexSet;
 use rustc_hir as hir;
+use rustc_index::bit_set::BitSet;
 use rustc_middle::ty::{self, Binder, Predicate, PredicateKind, ToPredicate, Ty, TyCtxt};
 use rustc_session::config::TraitSolver;
 use rustc_span::def_id::{DefId, CRATE_DEF_ID};
@@ -406,6 +407,52 @@ fn asyncness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::IsAsync {
     node.fn_sig().map_or(hir::IsAsync::NotAsync, |sig| sig.header.asyncness)
 }
 
+fn unsizing_params_for_adt<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> BitSet<u32> {
+    let def = tcx.adt_def(def_id);
+    let num_params = tcx.generics_of(def_id).count();
+
+    let maybe_unsizing_param_idx = |arg: ty::GenericArg<'tcx>| match arg.unpack() {
+        ty::GenericArgKind::Type(ty) => match ty.kind() {
+            ty::Param(p) => Some(p.index),
+            _ => None,
+        },
+
+        // We can't unsize a lifetime
+        ty::GenericArgKind::Lifetime(_) => None,
+
+        ty::GenericArgKind::Const(ct) => match ct.kind() {
+            ty::ConstKind::Param(p) => Some(p.index),
+            _ => None,
+        },
+    };
+
+    // The last field of the structure has to exist and contain type/const parameters.
+    let Some((tail_field, prefix_fields)) =
+        def.non_enum_variant().fields.split_last() else
+    {
+        return BitSet::new_empty(num_params);
+    };
+
+    let mut unsizing_params = BitSet::new_empty(num_params);
+    for arg in tcx.bound_type_of(tail_field.did).subst_identity().walk() {
+        if let Some(i) = maybe_unsizing_param_idx(arg) {
+            unsizing_params.insert(i);
+        }
+    }
+
+    // Ensure none of the other fields mention the parameters used
+    // in unsizing.
+    for field in prefix_fields {
+        for arg in tcx.bound_type_of(field.did).subst_identity().walk() {
+            if let Some(i) = maybe_unsizing_param_idx(arg) {
+                unsizing_params.remove(i);
+            }
+        }
+    }
+
+    unsizing_params
+}
+
 pub fn provide(providers: &mut ty::query::Providers) {
     *providers = ty::query::Providers {
         asyncness,
@@ -415,6 +462,7 @@ pub fn provide(providers: &mut ty::query::Providers) {
         instance_def_size_estimate,
         issue33140_self_ty,
         impl_defaultness,
+        unsizing_params_for_adt,
         ..*providers
     };
 }
index 299bfd779e57a83461efc1167ae9de9e3d603ab8..85f058f3664e3e5d388643fb86e70feeca400f83 100644 (file)
@@ -233,6 +233,9 @@ changelog-seen = 2
 # and generated in already-minified form from the beginning.
 #docs-minification = true
 
+# Flag to specify whether private items should be included in the library docs.
+#library-docs-private-items = false
+
 # Indicate whether the compiler should be documented in addition to the standard
 # library and facade crates.
 #compiler-docs = false
index eadb35cb96d422cfcdc84250b820b7cef65ea54c..1da86e1a46a572149937f8fcd7de92c942da5cfe 100644 (file)
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use core::fmt::Error;
 #[stable(feature = "rust1", since = "1.0.0")]
-pub use core::fmt::{write, ArgumentV1, Arguments};
+pub use core::fmt::{write, Arguments};
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use core::fmt::{Binary, Octal};
 #[stable(feature = "rust1", since = "1.0.0")]
index c9aa23fc4af1f275e98ff6352e4e34480d6044cb..fd1e3e0f75b09a68ca2531423d361878bf8cfcf6 100644 (file)
@@ -1092,7 +1092,7 @@ pub fn get_mut(this: &mut Self) -> Option<&mut T> {
     /// # Safety
     ///
     /// If any other `Rc` or [`Weak`] pointers to the same allocation exist, then
-    /// they must be must not be dereferenced or have active borrows for the duration
+    /// they must not be dereferenced or have active borrows for the duration
     /// of the returned borrow, and their inner type must be exactly the same as the
     /// inner type of this Rc (including lifetimes). This is trivially the case if no
     /// such pointers exist, for example immediately after `Rc::new`.
index fecacc2bb639508836b4090fa22280a368051a67..093dcbbe8bf775c3b437ee7329527ca7ed5d6da7 100644 (file)
@@ -782,6 +782,38 @@ fn borrow_mut(&mut self) -> &mut [T] {
     }
 }
 
+// Specializable trait for implementing ToOwned::clone_into. This is
+// public in the crate and has the Allocator parameter so that
+// vec::clone_from use it too.
+#[cfg(not(no_global_oom_handling))]
+pub(crate) trait SpecCloneIntoVec<T, A: Allocator> {
+    fn clone_into(&self, target: &mut Vec<T, A>);
+}
+
+#[cfg(not(no_global_oom_handling))]
+impl<T: Clone, A: Allocator> SpecCloneIntoVec<T, A> for [T] {
+    default fn clone_into(&self, target: &mut Vec<T, A>) {
+        // drop anything in target that will not be overwritten
+        target.truncate(self.len());
+
+        // target.len <= self.len due to the truncate above, so the
+        // slices here are always in-bounds.
+        let (init, tail) = self.split_at(target.len());
+
+        // reuse the contained values' allocations/resources.
+        target.clone_from_slice(init);
+        target.extend_from_slice(tail);
+    }
+}
+
+#[cfg(not(no_global_oom_handling))]
+impl<T: Copy, A: Allocator> SpecCloneIntoVec<T, A> for [T] {
+    fn clone_into(&self, target: &mut Vec<T, A>) {
+        target.clear();
+        target.extend_from_slice(self);
+    }
+}
+
 #[cfg(not(no_global_oom_handling))]
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: Clone> ToOwned for [T] {
@@ -797,16 +829,7 @@ fn to_owned(&self) -> Vec<T> {
     }
 
     fn clone_into(&self, target: &mut Vec<T>) {
-        // drop anything in target that will not be overwritten
-        target.truncate(self.len());
-
-        // target.len <= self.len due to the truncate above, so the
-        // slices here are always in-bounds.
-        let (init, tail) = self.split_at(target.len());
-
-        // reuse the contained values' allocations/resources.
-        target.clone_from_slice(init);
-        target.extend_from_slice(tail);
+        SpecCloneIntoVec::clone_into(self, target);
     }
 }
 
index 9bc9182f7b53c3b170d0634ed959164f5b4204ea..f20486ca9e4dbf792c4a44e996180d9156698a8d 100644 (file)
@@ -1733,7 +1733,7 @@ pub fn get_mut(this: &mut Self) -> Option<&mut T> {
     /// # Safety
     ///
     /// If any other `Arc` or [`Weak`] pointers to the same allocation exist, then
-    /// they must be must not be dereferenced or have active borrows for the duration
+    /// they must not be dereferenced or have active borrows for the duration
     /// of the returned borrow, and their inner type must be exactly the same as the
     /// inner type of this Rc (including lifetimes). This is trivially the case if no
     /// such pointers exist, for example immediately after `Arc::new`.
index 36b0b3c9e7cc072aca6f39d2f165d277d52cbdc3..a07f3da78d33e58c4ec92954130d6816c1e6a8ee 100644 (file)
@@ -2646,35 +2646,6 @@ fn deref_mut(&mut self) -> &mut [T] {
     }
 }
 
-#[cfg(not(no_global_oom_handling))]
-trait SpecCloneFrom {
-    fn clone_from(this: &mut Self, other: &Self);
-}
-
-#[cfg(not(no_global_oom_handling))]
-impl<T: Clone, A: Allocator> SpecCloneFrom for Vec<T, A> {
-    default fn clone_from(this: &mut Self, other: &Self) {
-        // drop anything that will not be overwritten
-        this.truncate(other.len());
-
-        // self.len <= other.len due to the truncate above, so the
-        // slices here are always in-bounds.
-        let (init, tail) = other.split_at(this.len());
-
-        // reuse the contained values' allocations/resources.
-        this.clone_from_slice(init);
-        this.extend_from_slice(tail);
-    }
-}
-
-#[cfg(not(no_global_oom_handling))]
-impl<T: Copy, A: Allocator> SpecCloneFrom for Vec<T, A> {
-    fn clone_from(this: &mut Self, other: &Self) {
-        this.clear();
-        this.extend_from_slice(other);
-    }
-}
-
 #[cfg(not(no_global_oom_handling))]
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: Clone, A: Allocator + Clone> Clone for Vec<T, A> {
@@ -2695,7 +2666,7 @@ fn clone(&self) -> Self {
     }
 
     fn clone_from(&mut self, other: &Self) {
-        SpecCloneFrom::clone_from(self, other)
+        crate::slice::SpecCloneIntoVec::clone_into(other.as_slice(), self);
     }
 }
 
index c4fb362094664196a354070a1a8a246062734959..46cbcd43530d5eafa2d6bad1d0c4df9ed675bcba 100644 (file)
@@ -56,51 +56,6 @@ unsafe impl Send for ResumeTy {}
 #[unstable(feature = "gen_future", issue = "50547")]
 unsafe impl Sync for ResumeTy {}
 
-/// Wrap a generator in a future.
-///
-/// This function returns a `GenFuture` underneath, but hides it in `impl Trait` to give
-/// better error messages (`impl Future` rather than `GenFuture<[closure.....]>`).
-// This is `const` to avoid extra errors after we recover from `const async fn`
-#[doc(hidden)]
-#[unstable(feature = "gen_future", issue = "50547")]
-#[rustc_const_unstable(feature = "gen_future", issue = "50547")]
-#[inline]
-pub const fn from_generator<T>(gen: T) -> impl Future<Output = T::Return>
-where
-    T: crate::ops::Generator<ResumeTy, Yield = ()>,
-{
-    use crate::{
-        ops::{Generator, GeneratorState},
-        pin::Pin,
-        task::Poll,
-    };
-
-    #[rustc_diagnostic_item = "gen_future"]
-    struct GenFuture<T: Generator<ResumeTy, Yield = ()>>(T);
-
-    // We rely on the fact that async/await futures are immovable in order to create
-    // self-referential borrows in the underlying generator.
-    impl<T: Generator<ResumeTy, Yield = ()>> !Unpin for GenFuture<T> {}
-
-    impl<T: Generator<ResumeTy, Yield = ()>> Future for GenFuture<T> {
-        type Output = T::Return;
-        #[track_caller]
-        fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
-            // SAFETY: Safe because we're !Unpin + !Drop, and this is just a field projection.
-            let gen = unsafe { Pin::map_unchecked_mut(self, |s| &mut s.0) };
-
-            // Resume the generator, turning the `&mut Context` into a `NonNull` raw pointer. The
-            // `.await` lowering will safely cast that back to a `&mut Context`.
-            match gen.resume(ResumeTy(NonNull::from(cx).cast::<Context<'static>>())) {
-                GeneratorState::Yielded(()) => Poll::Pending,
-                GeneratorState::Complete(x) => Poll::Ready(x),
-            }
-        }
-    }
-
-    GenFuture(gen)
-}
-
 #[lang = "get_context"]
 #[doc(hidden)]
 #[unstable(feature = "gen_future", issue = "50547")]
index acd0fea4bc4105a03a1d793098e0a45a866a5166..b59f28193e2bdc24fddce4bc4ff7b3ed060a6c9e 100644 (file)
@@ -5,7 +5,7 @@ macro_rules! int_impl {
      $to_xe_bytes_doc:expr, $from_xe_bytes_doc:expr,
      $bound_condition:expr) => {
         /// The smallest value that can be represented by this integer type
-        #[doc = concat!("(&minus;2<sup>", $BITS_MINUS_ONE, "</sup>", $bound_condition, ")")]
+        #[doc = concat!("(&minus;2<sup>", $BITS_MINUS_ONE, "</sup>", $bound_condition, ").")]
         ///
         /// # Examples
         ///
@@ -18,7 +18,7 @@ macro_rules! int_impl {
         pub const MIN: Self = !0 ^ ((!0 as $UnsignedT) >> 1) as Self;
 
         /// The largest value that can be represented by this integer type
-        #[doc = concat!("(2<sup>", $BITS_MINUS_ONE, "</sup> &minus; 1", $bound_condition, ")")]
+        #[doc = concat!("(2<sup>", $BITS_MINUS_ONE, "</sup> &minus; 1", $bound_condition, ").")]
         ///
         /// # Examples
         ///
index 060d6e86b6c2bcf27d253ed013eafb5f6fac9f54..ea6b94f2f13c4e89253e743bc2c72795d421b6c9 100644 (file)
 #[stable(feature = "raw_ext", since = "1.1.0")]
 pub use self::arch::{blkcnt_t, blksize_t, ino_t, nlink_t, off_t, stat, time_t};
 
-#[cfg(any(
-    target_arch = "x86",
-    target_arch = "le32",
-    target_arch = "powerpc",
-    target_arch = "arm"
-))]
+#[cfg(any(target_arch = "x86", target_arch = "powerpc", target_arch = "arm"))]
 mod arch {
     use crate::os::raw::{c_long, c_short, c_uint};
 
index 699e8be33c8a81cb21699cdac5800dd451ea8257..b3f7439f8cdc045e7b52ff3e1866cd7942092962 100644 (file)
@@ -26,7 +26,6 @@
 
 #[cfg(any(
     target_arch = "x86",
-    target_arch = "le32",
     target_arch = "m68k",
     target_arch = "powerpc",
     target_arch = "sparc",
index c73791d14529c6976adec84643f01976433c05be..f46028c3a96c9d62a03151902aea14cbfa48c821 100644 (file)
@@ -26,7 +26,6 @@
 
 #[cfg(any(
     target_arch = "x86",
-    target_arch = "le32",
     target_arch = "m68k",
     target_arch = "powerpc",
     target_arch = "sparc",
index 2f53cf83936910e1df1dc217f96a8884c6f53302..e36e088896d02f7967171980fdd40777ff5dd1c1 100644 (file)
@@ -2688,6 +2688,7 @@ pub fn iter(&self) -> Iter<'_> {
     /// escapes the path please use [`Debug`] instead.
     ///
     /// [`Display`]: fmt::Display
+    /// [`Debug`]: fmt::Debug
     ///
     /// # Examples
     ///
index fdd659c60ca7f51181fc0280a1b5309a0207ad03..165502b0a41d8214d8389a075bdfe07ea2d7b26f 100644 (file)
@@ -65,6 +65,7 @@ pub struct Config {
     pub verbose: usize,
     pub submodules: Option<bool>,
     pub compiler_docs: bool,
+    pub library_docs_private_items: bool,
     pub docs_minification: bool,
     pub docs: bool,
     pub locked_deps: bool,
@@ -606,6 +607,7 @@ struct Build {
         rustfmt: Option<PathBuf> = "rustfmt",
         docs: Option<bool> = "docs",
         compiler_docs: Option<bool> = "compiler-docs",
+        library_docs_private_items: Option<bool> = "library-docs-private-items",
         docs_minification: Option<bool> = "docs-minification",
         submodules: Option<bool> = "submodules",
         gdb: Option<String> = "gdb",
@@ -1018,6 +1020,7 @@ fn parse_inner<'a>(args: &[String], get_toml: impl 'a + Fn(&Path) -> TomlConfig)
         config.submodules = build.submodules;
         set(&mut config.low_priority, build.low_priority);
         set(&mut config.compiler_docs, build.compiler_docs);
+        set(&mut config.library_docs_private_items, build.library_docs_private_items);
         set(&mut config.docs_minification, build.docs_minification);
         set(&mut config.docs, build.docs);
         set(&mut config.locked_deps, build.locked_deps);
index 9bad9046ecc2c4fed4a122d5d2a60ccf2adda4c1..7f8aa2573ddb316b2549c65267792a4a91280102 100644 (file)
@@ -597,6 +597,9 @@ fn doc_std(
             .arg("--resource-suffix")
             .arg(&builder.version)
             .args(extra_args);
+        if builder.config.library_docs_private_items {
+            cargo.arg("--document-private-items").arg("--document-hidden-items");
+        }
         builder.run(&mut cargo.into());
     };
 
index 3b9dba4109d3e6f1d2b8fe6c4aa047b204da4b5f..267aa3278d8ffcb0e6e4b17c276eca7bf6760afe 100644 (file)
 use std::io;
 use std::io::ErrorKind;
 use std::path::{Path, PathBuf};
-use std::process::Command;
+use std::process::{Command, Stdio};
 use std::str;
 
 use build_helper::ci::CiEnv;
@@ -203,7 +203,6 @@ pub unsafe fn setup(_build: &mut crate::Build) {}
     (None, "bootstrap", None),
     (Some(Mode::Rustc), "parallel_compiler", None),
     (Some(Mode::ToolRustc), "parallel_compiler", None),
-    (Some(Mode::ToolRustc), "emulate_second_only_system", None),
     (Some(Mode::Codegen), "parallel_compiler", None),
     (Some(Mode::Std), "stdarch_intel_sde", None),
     (Some(Mode::Std), "no_fp_fmt_parse", None),
@@ -214,18 +213,9 @@ pub unsafe fn setup(_build: &mut crate::Build) {}
     (Some(Mode::Std), "backtrace_in_libstd", None),
     /* Extra values not defined in the built-in targets yet, but used in std */
     (Some(Mode::Std), "target_env", Some(&["libnx"])),
-    (Some(Mode::Std), "target_os", Some(&["watchos"])),
-    (
-        Some(Mode::Std),
-        "target_arch",
-        Some(&["asmjs", "spirv", "nvptx", "nvptx64", "le32", "xtensa"]),
-    ),
+    // (Some(Mode::Std), "target_os", Some(&[])),
+    (Some(Mode::Std), "target_arch", Some(&["asmjs", "spirv", "nvptx", "xtensa"])),
     /* Extra names used by dependencies */
-    // FIXME: Used by rustfmt is their test but is invalid (neither cargo nor bootstrap ever set
-    // this config) should probably by removed or use a allow attribute.
-    (Some(Mode::ToolRustc), "release", None),
-    // FIXME: Used by stdarch in their test, should use a allow attribute instead.
-    (Some(Mode::Std), "dont_compile_me", None),
     // FIXME: Used by serde_json, but we should not be triggering on external dependencies.
     (Some(Mode::Rustc), "no_btreemap_remove_entry", None),
     (Some(Mode::ToolRustc), "no_btreemap_remove_entry", None),
@@ -235,8 +225,12 @@ pub unsafe fn setup(_build: &mut crate::Build) {}
     // FIXME: Used by proc-macro2, but we should not be triggering on external dependencies.
     (Some(Mode::Rustc), "span_locations", None),
     (Some(Mode::ToolRustc), "span_locations", None),
-    // Can be passed in RUSTFLAGS to prevent direct syscalls in rustix.
-    (None, "rustix_use_libc", None),
+    // FIXME: Used by rustix, but we should not be triggering on external dependencies.
+    (Some(Mode::Rustc), "rustix_use_libc", None),
+    (Some(Mode::ToolRustc), "rustix_use_libc", None),
+    // FIXME: Used by filetime, but we should not be triggering on external dependencies.
+    (Some(Mode::Rustc), "emulate_second_only_system", None),
+    (Some(Mode::ToolRustc), "emulate_second_only_system", None),
 ];
 
 /// A structure representing a Rust compiler.
@@ -662,12 +656,32 @@ fn dir_is_empty(dir: &Path) -> bool {
 
         // Try passing `--progress` to start, then run git again without if that fails.
         let update = |progress: bool| {
-            let mut git = Command::new("git");
+            // Git is buggy and will try to fetch submodules from the tracking branch for *this* repository,
+            // even though that has no relation to the upstream for the submodule.
+            let current_branch = {
+                let output = self
+                    .config
+                    .git()
+                    .args(["symbolic-ref", "--short", "HEAD"])
+                    .stderr(Stdio::inherit())
+                    .output();
+                let output = t!(output);
+                if output.status.success() {
+                    Some(String::from_utf8(output.stdout).unwrap().trim().to_owned())
+                } else {
+                    None
+                }
+            };
+
+            let mut git = self.config.git();
+            if let Some(branch) = current_branch {
+                git.arg("-c").arg(format!("branch.{branch}.remote=origin"));
+            }
             git.args(&["submodule", "update", "--init", "--recursive", "--depth=1"]);
             if progress {
                 git.arg("--progress");
             }
-            git.arg(relative_path).current_dir(&self.config.src);
+            git.arg(relative_path);
             git
         };
         // NOTE: doesn't use `try_run` because this shouldn't print an error if it fails.
index 2cd1b5593d26dc6a03c20f8619187ad4b2485552..f2a78f64b668f63f581203c6bac509903f7c00ee 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 2cd1b5593d26dc6a03c20f8619187ad4b2485552
+Subproject commit f2a78f64b668f63f581203c6bac509903f7c00ee
index 19f798d448835a4888e3b3eae7fe69f1d61d8681..f1a4614aa41cc544b91b79760a709e113f3451d7 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 19f798d448835a4888e3b3eae7fe69f1d61d8681
+Subproject commit f1a4614aa41cc544b91b79760a709e113f3451d7
index 960d610e7f33889a2577f5f17c26f0d5c82b30df..bd1829d235296952bf72ca55635e360584b8805e 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 960d610e7f33889a2577f5f17c26f0d5c82b30df
+Subproject commit bd1829d235296952bf72ca55635e360584b8805e
index 2cb0ed9ba56360949f492f9866afe8c293f9f9da..22882fb3f7b4d69fdc0d1731e8b9cfcb6910537d 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 2cb0ed9ba56360949f492f9866afe8c293f9f9da
+Subproject commit 22882fb3f7b4d69fdc0d1731e8b9cfcb6910537d
index a9fb7d13eadfcc5f457962731f105b97f9a7474a..134376872e8c387ef369507e0ee9b5a0e3272718 160000 (submodule)
@@ -1 +1 @@
-Subproject commit a9fb7d13eadfcc5f457962731f105b97f9a7474a
+Subproject commit 134376872e8c387ef369507e0ee9b5a0e3272718
index 7352353ae91c48b136d2ca7d03822e1448165e1e..e359ee27fc3da3356d71a732128c0a1abe02e53a 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 7352353ae91c48b136d2ca7d03822e1448165e1e
+Subproject commit e359ee27fc3da3356d71a732128c0a1abe02e53a
index 56b40d8c66baffa627ab03e1a9b83788b73d276d..2c514a0c8267b80b7763660520a80b5803e2e3e1 100644 (file)
@@ -509,7 +509,7 @@ fn println_condition(condition: Condition) {
                 // these values up both in `dataset` and in the storage API, so it needs to be able
                 // to convert the names back and forth.  Despite doing this kebab-case to
                 // StudlyCaps transformation automatically, the JS DOM API does not provide a
-                // mechanism for doing the just transformation on a string.  So we want to avoid
+                // mechanism for doing just the transformation on a string.  So we want to avoid
                 // the StudlyCaps representation in the `dataset` property.
                 //
                 // We solve this by replacing all the `-`s with `_`s.  We do that here, when we
index 8a9e6caf611bad111308874cd8bd3d7685cb130d..1644d1c5a29a78e561f2da29c5fa1004e9e93aec 100644 (file)
@@ -58,11 +58,11 @@ pub(crate) fn render_example_with_highlighting(
     write_footer(out, playground_button);
 }
 
-/// Highlights `src` as a macro, returning the HTML output.
-pub(crate) fn render_macro_with_highlighting(src: &str, out: &mut Buffer) {
-    write_header(out, "macro", None, Tooltip::None);
+/// Highlights `src` as an item-decl, returning the HTML output.
+pub(crate) fn render_item_decl_with_highlighting(src: &str, out: &mut Buffer) {
+    write!(out, "<pre class=\"rust item-decl\">");
     write_code(out, src, None, None);
-    write_footer(out, None);
+    write!(out, "</pre>");
 }
 
 /// Highlights `src` as a source code page, returning the HTML output.
index a60e7cb10fa515c8b4f17745808f7f8d3d575f70..6ab849c92a0768bac3c2e0c31f3be0d5e9014b0d 100644 (file)
@@ -30,7 +30,6 @@ pub(crate) struct Page<'a> {
     pub(crate) root_path: &'a str,
     pub(crate) static_root_path: Option<&'a str>,
     pub(crate) description: &'a str,
-    pub(crate) keywords: &'a str,
     pub(crate) resource_suffix: &'a str,
 }
 
index 15258a467a228106abf2a18d728c066681b2bc6a..b59645ec2e2d5e88b9ea82a59315e552aec06ccf 100644 (file)
@@ -18,7 +18,7 @@
 use super::write_shared::write_shared;
 use super::{
     collect_spans_and_sources, print_sidebar, scrape_examples_help, sidebar_module_like, AllTypes,
-    LinkFromSrc, NameDoc, StylePath, BASIC_KEYWORDS,
+    LinkFromSrc, NameDoc, StylePath,
 };
 
 use crate::clean::{self, types::ExternalLocation, ExternalCrate};
@@ -195,7 +195,6 @@ fn render_item(&mut self, it: &clean::Item, is_module: bool) -> String {
                 self.shared.layout.krate
             )
         };
-        let keywords = make_item_keywords(it);
         let name;
         let tyname_s = if it.is_crate() {
             name = format!("{} crate", tyname);
@@ -212,7 +211,6 @@ fn render_item(&mut self, it: &clean::Item, is_module: bool) -> String {
                 static_root_path: clone_shared.static_root_path.as_deref(),
                 title: &title,
                 description: &desc,
-                keywords: &keywords,
                 resource_suffix: &clone_shared.resource_suffix,
             };
             let mut page_buffer = Buffer::html();
@@ -598,7 +596,6 @@ fn after_krate(&mut self) -> Result<(), Error> {
             root_path: "../",
             static_root_path: shared.static_root_path.as_deref(),
             description: "List of all items in this crate",
-            keywords: BASIC_KEYWORDS,
             resource_suffix: &shared.resource_suffix,
         };
         let all = shared.all.replace(AllTypes::new());
@@ -828,7 +825,3 @@ fn cache(&self) -> &Cache {
         &self.shared.cache
     }
 }
-
-fn make_item_keywords(it: &clean::Item) -> String {
-    format!("{}, {}", BASIC_KEYWORDS, it.name.as_ref().unwrap())
-}
index be6de231854ba1198b32710da0bc41467dbeb6e7..816a8f4e274ce20c10c5cadc2bfd1a2600cc0c85 100644 (file)
@@ -2743,8 +2743,6 @@ fn sidebar_foreign_type(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item) {
     }
 }
 
-pub(crate) const BASIC_KEYWORDS: &str = "rust, rustlang, rust-lang";
-
 /// Returns a list of all paths used in the type.
 /// This is used to help deduplicate imported impls
 /// for reexported types. If any of the contained
index b0288d55c256ad84e90c04ab8bc3eb9ff992092b..71cde1f964cd96813e0a1da139df0e8c2a6490f4 100644 (file)
@@ -530,26 +530,24 @@ fn item_function(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, f: &cle
     let notable_traits =
         f.decl.output.as_return().and_then(|output| notable_traits_button(output, cx));
 
-    wrap_into_item_decl(w, |w| {
-        wrap_item(w, |w| {
-            render_attributes_in_pre(w, it, "");
-            w.reserve(header_len);
-            write!(
-                w,
-                "{vis}{constness}{asyncness}{unsafety}{abi}fn \
-                 {name}{generics}{decl}{notable_traits}{where_clause}",
-                vis = visibility,
-                constness = constness,
-                asyncness = asyncness,
-                unsafety = unsafety,
-                abi = abi,
-                name = name,
-                generics = f.generics.print(cx),
-                where_clause = print_where_clause(&f.generics, cx, 0, Ending::Newline),
-                decl = f.decl.full_print(header_len, 0, cx),
-                notable_traits = notable_traits.unwrap_or_default(),
-            );
-        });
+    wrap_item(w, |w| {
+        render_attributes_in_pre(w, it, "");
+        w.reserve(header_len);
+        write!(
+            w,
+            "{vis}{constness}{asyncness}{unsafety}{abi}fn \
+                {name}{generics}{decl}{notable_traits}{where_clause}",
+            vis = visibility,
+            constness = constness,
+            asyncness = asyncness,
+            unsafety = unsafety,
+            abi = abi,
+            name = name,
+            generics = f.generics.print(cx),
+            where_clause = print_where_clause(&f.generics, cx, 0, Ending::Newline),
+            decl = f.decl.full_print(header_len, 0, cx),
+            notable_traits = notable_traits.unwrap_or_default(),
+        );
     });
     document(w, cx, it, None, HeadingOffset::H2);
 }
@@ -569,145 +567,140 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
     let must_implement_one_of_functions = tcx.trait_def(t.def_id).must_implement_one_of.clone();
 
     // Output the trait definition
-    wrap_into_item_decl(w, |w| {
-        wrap_item(w, |w| {
-            render_attributes_in_pre(w, it, "");
-            write!(
-                w,
-                "{}{}{}trait {}{}{}",
-                visibility_print_with_space(it.visibility(tcx), it.item_id, cx),
-                t.unsafety(tcx).print_with_space(),
-                if t.is_auto(tcx) { "auto " } else { "" },
-                it.name.unwrap(),
-                t.generics.print(cx),
-                bounds
-            );
+    wrap_item(w, |w| {
+        render_attributes_in_pre(w, it, "");
+        write!(
+            w,
+            "{}{}{}trait {}{}{}",
+            visibility_print_with_space(it.visibility(tcx), it.item_id, cx),
+            t.unsafety(tcx).print_with_space(),
+            if t.is_auto(tcx) { "auto " } else { "" },
+            it.name.unwrap(),
+            t.generics.print(cx),
+            bounds
+        );
 
-            if !t.generics.where_predicates.is_empty() {
-                write!(w, "{}", print_where_clause(&t.generics, cx, 0, Ending::Newline));
-            } else {
-                w.write_str(" ");
-            }
+        if !t.generics.where_predicates.is_empty() {
+            write!(w, "{}", print_where_clause(&t.generics, cx, 0, Ending::Newline));
+        } else {
+            w.write_str(" ");
+        }
 
-            if t.items.is_empty() {
-                w.write_str("{ }");
-            } else {
-                // FIXME: we should be using a derived_id for the Anchors here
-                w.write_str("{\n");
-                let mut toggle = false;
-
-                // If there are too many associated types, hide _everything_
-                if should_hide_fields(count_types) {
-                    toggle = true;
-                    toggle_open(
-                        w,
-                        format_args!(
-                            "{} associated items",
-                            count_types + count_consts + count_methods
-                        ),
-                    );
-                }
-                for types in [&required_types, &provided_types] {
-                    for t in types {
-                        render_assoc_item(
-                            w,
-                            t,
-                            AssocItemLink::Anchor(None),
-                            ItemType::Trait,
-                            cx,
-                            RenderMode::Normal,
-                        );
-                        w.write_str(";\n");
-                    }
-                }
-                // If there are too many associated constants, hide everything after them
-                // We also do this if the types + consts is large because otherwise we could
-                // render a bunch of types and _then_ a bunch of consts just because both were
-                // _just_ under the limit
-                if !toggle && should_hide_fields(count_types + count_consts) {
-                    toggle = true;
-                    toggle_open(
-                        w,
-                        format_args!(
-                            "{} associated constant{} and {} method{}",
-                            count_consts,
-                            pluralize(count_consts),
-                            count_methods,
-                            pluralize(count_methods),
-                        ),
-                    );
-                }
-                if count_types != 0 && (count_consts != 0 || count_methods != 0) {
-                    w.write_str("\n");
-                }
-                for consts in [&required_consts, &provided_consts] {
-                    for c in consts {
-                        render_assoc_item(
-                            w,
-                            c,
-                            AssocItemLink::Anchor(None),
-                            ItemType::Trait,
-                            cx,
-                            RenderMode::Normal,
-                        );
-                        w.write_str(";\n");
-                    }
-                }
-                if !toggle && should_hide_fields(count_methods) {
-                    toggle = true;
-                    toggle_open(w, format_args!("{} methods", count_methods));
-                }
-                if count_consts != 0 && count_methods != 0 {
-                    w.write_str("\n");
-                }
-                for (pos, m) in required_methods.iter().enumerate() {
+        if t.items.is_empty() {
+            w.write_str("{ }");
+        } else {
+            // FIXME: we should be using a derived_id for the Anchors here
+            w.write_str("{\n");
+            let mut toggle = false;
+
+            // If there are too many associated types, hide _everything_
+            if should_hide_fields(count_types) {
+                toggle = true;
+                toggle_open(
+                    w,
+                    format_args!("{} associated items", count_types + count_consts + count_methods),
+                );
+            }
+            for types in [&required_types, &provided_types] {
+                for t in types {
                     render_assoc_item(
                         w,
-                        m,
+                        t,
                         AssocItemLink::Anchor(None),
                         ItemType::Trait,
                         cx,
                         RenderMode::Normal,
                     );
                     w.write_str(";\n");
-
-                    if pos < required_methods.len() - 1 {
-                        w.write_str("<span class=\"item-spacer\"></span>");
-                    }
-                }
-                if !required_methods.is_empty() && !provided_methods.is_empty() {
-                    w.write_str("\n");
                 }
-                for (pos, m) in provided_methods.iter().enumerate() {
+            }
+            // If there are too many associated constants, hide everything after them
+            // We also do this if the types + consts is large because otherwise we could
+            // render a bunch of types and _then_ a bunch of consts just because both were
+            // _just_ under the limit
+            if !toggle && should_hide_fields(count_types + count_consts) {
+                toggle = true;
+                toggle_open(
+                    w,
+                    format_args!(
+                        "{} associated constant{} and {} method{}",
+                        count_consts,
+                        pluralize(count_consts),
+                        count_methods,
+                        pluralize(count_methods),
+                    ),
+                );
+            }
+            if count_types != 0 && (count_consts != 0 || count_methods != 0) {
+                w.write_str("\n");
+            }
+            for consts in [&required_consts, &provided_consts] {
+                for c in consts {
                     render_assoc_item(
                         w,
-                        m,
+                        c,
                         AssocItemLink::Anchor(None),
                         ItemType::Trait,
                         cx,
                         RenderMode::Normal,
                     );
-                    match *m.kind {
-                        clean::MethodItem(ref inner, _)
-                            if !inner.generics.where_predicates.is_empty() =>
-                        {
-                            w.write_str(",\n    { ... }\n");
-                        }
-                        _ => {
-                            w.write_str(" { ... }\n");
-                        }
-                    }
+                    w.write_str(";\n");
+                }
+            }
+            if !toggle && should_hide_fields(count_methods) {
+                toggle = true;
+                toggle_open(w, format_args!("{} methods", count_methods));
+            }
+            if count_consts != 0 && count_methods != 0 {
+                w.write_str("\n");
+            }
+            for (pos, m) in required_methods.iter().enumerate() {
+                render_assoc_item(
+                    w,
+                    m,
+                    AssocItemLink::Anchor(None),
+                    ItemType::Trait,
+                    cx,
+                    RenderMode::Normal,
+                );
+                w.write_str(";\n");
 
-                    if pos < provided_methods.len() - 1 {
-                        w.write_str("<span class=\"item-spacer\"></span>");
+                if pos < required_methods.len() - 1 {
+                    w.write_str("<span class=\"item-spacer\"></span>");
+                }
+            }
+            if !required_methods.is_empty() && !provided_methods.is_empty() {
+                w.write_str("\n");
+            }
+            for (pos, m) in provided_methods.iter().enumerate() {
+                render_assoc_item(
+                    w,
+                    m,
+                    AssocItemLink::Anchor(None),
+                    ItemType::Trait,
+                    cx,
+                    RenderMode::Normal,
+                );
+                match *m.kind {
+                    clean::MethodItem(ref inner, _)
+                        if !inner.generics.where_predicates.is_empty() =>
+                    {
+                        w.write_str(",\n    { ... }\n");
+                    }
+                    _ => {
+                        w.write_str(" { ... }\n");
                     }
                 }
-                if toggle {
-                    toggle_close(w);
+
+                if pos < provided_methods.len() - 1 {
+                    w.write_str("<span class=\"item-spacer\"></span>");
                 }
-                w.write_str("}");
             }
-        });
+            if toggle {
+                toggle_close(w);
+            }
+            w.write_str("}");
+        }
     });
 
     // Trait documentation
@@ -1050,18 +1043,16 @@ fn trait_item(w: &mut Buffer, cx: &mut Context<'_>, m: &clean::Item, t: &clean::
 }
 
 fn item_trait_alias(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean::TraitAlias) {
-    wrap_into_item_decl(w, |w| {
-        wrap_item(w, |w| {
-            render_attributes_in_pre(w, it, "");
-            write!(
-                w,
-                "trait {}{}{} = {};",
-                it.name.unwrap(),
-                t.generics.print(cx),
-                print_where_clause(&t.generics, cx, 0, Ending::Newline),
-                bounds(&t.bounds, true, cx)
-            );
-        });
+    wrap_item(w, |w| {
+        render_attributes_in_pre(w, it, "");
+        write!(
+            w,
+            "trait {}{}{} = {};",
+            it.name.unwrap(),
+            t.generics.print(cx),
+            print_where_clause(&t.generics, cx, 0, Ending::Newline),
+            bounds(&t.bounds, true, cx)
+        );
     });
 
     document(w, cx, it, None, HeadingOffset::H2);
@@ -1074,18 +1065,16 @@ fn item_trait_alias(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &
 }
 
 fn item_opaque_ty(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean::OpaqueTy) {
-    wrap_into_item_decl(w, |w| {
-        wrap_item(w, |w| {
-            render_attributes_in_pre(w, it, "");
-            write!(
-                w,
-                "type {}{}{where_clause} = impl {bounds};",
-                it.name.unwrap(),
-                t.generics.print(cx),
-                where_clause = print_where_clause(&t.generics, cx, 0, Ending::Newline),
-                bounds = bounds(&t.bounds, false, cx),
-            );
-        });
+    wrap_item(w, |w| {
+        render_attributes_in_pre(w, it, "");
+        write!(
+            w,
+            "type {}{}{where_clause} = impl {bounds};",
+            it.name.unwrap(),
+            t.generics.print(cx),
+            where_clause = print_where_clause(&t.generics, cx, 0, Ending::Newline),
+            bounds = bounds(&t.bounds, false, cx),
+        );
     });
 
     document(w, cx, it, None, HeadingOffset::H2);
@@ -1113,7 +1102,7 @@ fn write_content(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::
         });
     }
 
-    wrap_into_item_decl(w, |w| write_content(w, cx, it, t));
+    write_content(w, cx, it, t);
 
     document(w, cx, it, None, HeadingOffset::H2);
 
@@ -1127,11 +1116,9 @@ fn write_content(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::
 }
 
 fn item_union(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean::Union) {
-    wrap_into_item_decl(w, |w| {
-        wrap_item(w, |w| {
-            render_attributes_in_pre(w, it, "");
-            render_union(w, it, Some(&s.generics), &s.fields, "", cx);
-        });
+    wrap_item(w, |w| {
+        render_attributes_in_pre(w, it, "");
+        render_union(w, it, Some(&s.generics), &s.fields, "", cx);
     });
 
     document(w, cx, it, None, HeadingOffset::H2);
@@ -1192,60 +1179,58 @@ fn print_tuple_struct_fields(w: &mut Buffer, cx: &Context<'_>, s: &[clean::Item]
 fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean::Enum) {
     let tcx = cx.tcx();
     let count_variants = e.variants().count();
-    wrap_into_item_decl(w, |w| {
-        wrap_item(w, |w| {
-            render_attributes_in_pre(w, it, "");
-            write!(
-                w,
-                "{}enum {}{}",
-                visibility_print_with_space(it.visibility(tcx), it.item_id, cx),
-                it.name.unwrap(),
-                e.generics.print(cx),
-            );
-            if !print_where_clause_and_check(w, &e.generics, cx) {
-                // If there wasn't a `where` clause, we add a whitespace.
-                w.write_str(" ");
-            }
+    wrap_item(w, |w| {
+        render_attributes_in_pre(w, it, "");
+        write!(
+            w,
+            "{}enum {}{}",
+            visibility_print_with_space(it.visibility(tcx), it.item_id, cx),
+            it.name.unwrap(),
+            e.generics.print(cx),
+        );
+        if !print_where_clause_and_check(w, &e.generics, cx) {
+            // If there wasn't a `where` clause, we add a whitespace.
+            w.write_str(" ");
+        }
 
-            let variants_stripped = e.has_stripped_entries();
-            if count_variants == 0 && !variants_stripped {
-                w.write_str("{}");
-            } else {
-                w.write_str("{\n");
-                let toggle = should_hide_fields(count_variants);
-                if toggle {
-                    toggle_open(w, format_args!("{} variants", count_variants));
-                }
-                for v in e.variants() {
-                    w.write_str("    ");
-                    let name = v.name.unwrap();
-                    match *v.kind {
-                        // FIXME(#101337): Show discriminant
-                        clean::VariantItem(ref var) => match var.kind {
-                            clean::VariantKind::CLike => write!(w, "{}", name),
-                            clean::VariantKind::Tuple(ref s) => {
-                                write!(w, "{}(", name);
-                                print_tuple_struct_fields(w, cx, s);
-                                w.write_str(")");
-                            }
-                            clean::VariantKind::Struct(ref s) => {
-                                render_struct(w, v, None, None, &s.fields, "    ", false, cx);
-                            }
-                        },
-                        _ => unreachable!(),
-                    }
-                    w.write_str(",\n");
+        let variants_stripped = e.has_stripped_entries();
+        if count_variants == 0 && !variants_stripped {
+            w.write_str("{}");
+        } else {
+            w.write_str("{\n");
+            let toggle = should_hide_fields(count_variants);
+            if toggle {
+                toggle_open(w, format_args!("{} variants", count_variants));
+            }
+            for v in e.variants() {
+                w.write_str("    ");
+                let name = v.name.unwrap();
+                match *v.kind {
+                    // FIXME(#101337): Show discriminant
+                    clean::VariantItem(ref var) => match var.kind {
+                        clean::VariantKind::CLike => write!(w, "{}", name),
+                        clean::VariantKind::Tuple(ref s) => {
+                            write!(w, "{}(", name);
+                            print_tuple_struct_fields(w, cx, s);
+                            w.write_str(")");
+                        }
+                        clean::VariantKind::Struct(ref s) => {
+                            render_struct(w, v, None, None, &s.fields, "    ", false, cx);
+                        }
+                    },
+                    _ => unreachable!(),
                 }
+                w.write_str(",\n");
+            }
 
-                if variants_stripped {
-                    w.write_str("    // some variants omitted\n");
-                }
-                if toggle {
-                    toggle_close(w);
-                }
-                w.write_str("}");
+            if variants_stripped {
+                w.write_str("    // some variants omitted\n");
             }
-        });
+            if toggle {
+                toggle_close(w);
+            }
+            w.write_str("}");
+        }
     });
 
     document(w, cx, it, None, HeadingOffset::H2);
@@ -1346,38 +1331,30 @@ fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean::
 }
 
 fn item_macro(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean::Macro) {
-    wrap_into_item_decl(w, |w| {
-        highlight::render_macro_with_highlighting(&t.source, w);
-    });
+    highlight::render_item_decl_with_highlighting(&t.source, w);
     document(w, cx, it, None, HeadingOffset::H2)
 }
 
 fn item_proc_macro(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, m: &clean::ProcMacro) {
-    wrap_into_item_decl(w, |w| {
+    wrap_item(w, |w| {
         let name = it.name.expect("proc-macros always have names");
         match m.kind {
             MacroKind::Bang => {
-                wrap_item(w, |w| {
-                    write!(w, "{}!() {{ /* proc-macro */ }}", name);
-                });
+                write!(w, "{}!() {{ /* proc-macro */ }}", name);
             }
             MacroKind::Attr => {
-                wrap_item(w, |w| {
-                    write!(w, "#[{}]", name);
-                });
+                write!(w, "#[{}]", name);
             }
             MacroKind::Derive => {
-                wrap_item(w, |w| {
-                    write!(w, "#[derive({})]", name);
-                    if !m.helpers.is_empty() {
-                        w.push_str("\n{\n");
-                        w.push_str("    // Attributes available to this derive:\n");
-                        for attr in &m.helpers {
-                            writeln!(w, "    #[{}]", attr);
-                        }
-                        w.push_str("}\n");
+                write!(w, "#[derive({})]", name);
+                if !m.helpers.is_empty() {
+                    w.push_str("\n{\n");
+                    w.push_str("    // Attributes available to this derive:\n");
+                    for attr in &m.helpers {
+                        writeln!(w, "    #[{}]", attr);
                     }
-                });
+                    w.push_str("}\n");
+                }
             }
         }
     });
@@ -1400,61 +1377,57 @@ fn item_primitive(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item) {
 }
 
 fn item_constant(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, c: &clean::Constant) {
-    wrap_into_item_decl(w, |w| {
-        wrap_item(w, |w| {
-            let tcx = cx.tcx();
-            render_attributes_in_code(w, it);
+    wrap_item(w, |w| {
+        let tcx = cx.tcx();
+        render_attributes_in_code(w, it);
 
-            write!(
-                w,
-                "{vis}const {name}: {typ}",
-                vis = visibility_print_with_space(it.visibility(tcx), it.item_id, cx),
-                name = it.name.unwrap(),
-                typ = c.type_.print(cx),
-            );
+        write!(
+            w,
+            "{vis}const {name}: {typ}",
+            vis = visibility_print_with_space(it.visibility(tcx), it.item_id, cx),
+            name = it.name.unwrap(),
+            typ = c.type_.print(cx),
+        );
 
-            // FIXME: The code below now prints
-            //            ` = _; // 100i32`
-            //        if the expression is
-            //            `50 + 50`
-            //        which looks just wrong.
-            //        Should we print
-            //            ` = 100i32;`
-            //        instead?
-
-            let value = c.value(tcx);
-            let is_literal = c.is_literal(tcx);
-            let expr = c.expr(tcx);
-            if value.is_some() || is_literal {
-                write!(w, " = {expr};", expr = Escape(&expr));
-            } else {
-                w.write_str(";");
-            }
+        // FIXME: The code below now prints
+        //            ` = _; // 100i32`
+        //        if the expression is
+        //            `50 + 50`
+        //        which looks just wrong.
+        //        Should we print
+        //            ` = 100i32;`
+        //        instead?
+
+        let value = c.value(tcx);
+        let is_literal = c.is_literal(tcx);
+        let expr = c.expr(tcx);
+        if value.is_some() || is_literal {
+            write!(w, " = {expr};", expr = Escape(&expr));
+        } else {
+            w.write_str(";");
+        }
 
-            if !is_literal {
-                if let Some(value) = &value {
-                    let value_lowercase = value.to_lowercase();
-                    let expr_lowercase = expr.to_lowercase();
+        if !is_literal {
+            if let Some(value) = &value {
+                let value_lowercase = value.to_lowercase();
+                let expr_lowercase = expr.to_lowercase();
 
-                    if value_lowercase != expr_lowercase
-                        && value_lowercase.trim_end_matches("i32") != expr_lowercase
-                    {
-                        write!(w, " // {value}", value = Escape(value));
-                    }
+                if value_lowercase != expr_lowercase
+                    && value_lowercase.trim_end_matches("i32") != expr_lowercase
+                {
+                    write!(w, " // {value}", value = Escape(value));
                 }
             }
-        });
+        }
     });
 
     document(w, cx, it, None, HeadingOffset::H2)
 }
 
 fn item_struct(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean::Struct) {
-    wrap_into_item_decl(w, |w| {
-        wrap_item(w, |w| {
-            render_attributes_in_code(w, it);
-            render_struct(w, it, Some(&s.generics), s.ctor_kind, &s.fields, "", true, cx);
-        });
+    wrap_item(w, |w| {
+        render_attributes_in_code(w, it);
+        render_struct(w, it, Some(&s.generics), s.ctor_kind, &s.fields, "", true, cx);
     });
 
     document(w, cx, it, None, HeadingOffset::H2);
@@ -1503,34 +1476,30 @@ fn item_struct(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean
 }
 
 fn item_static(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean::Static) {
-    wrap_into_item_decl(w, |w| {
-        wrap_item(w, |w| {
-            render_attributes_in_code(w, it);
-            write!(
-                w,
-                "{vis}static {mutability}{name}: {typ}",
-                vis = visibility_print_with_space(it.visibility(cx.tcx()), it.item_id, cx),
-                mutability = s.mutability.print_with_space(),
-                name = it.name.unwrap(),
-                typ = s.type_.print(cx)
-            );
-        });
+    wrap_item(w, |w| {
+        render_attributes_in_code(w, it);
+        write!(
+            w,
+            "{vis}static {mutability}{name}: {typ}",
+            vis = visibility_print_with_space(it.visibility(cx.tcx()), it.item_id, cx),
+            mutability = s.mutability.print_with_space(),
+            name = it.name.unwrap(),
+            typ = s.type_.print(cx)
+        );
     });
     document(w, cx, it, None, HeadingOffset::H2)
 }
 
 fn item_foreign_type(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item) {
-    wrap_into_item_decl(w, |w| {
-        wrap_item(w, |w| {
-            w.write_str("extern {\n");
-            render_attributes_in_code(w, it);
-            write!(
-                w,
-                "    {}type {};\n}}",
-                visibility_print_with_space(it.visibility(cx.tcx()), it.item_id, cx),
-                it.name.unwrap(),
-            );
-        });
+    wrap_item(w, |w| {
+        w.write_str("extern {\n");
+        render_attributes_in_code(w, it);
+        write!(
+            w,
+            "    {}type {};\n}}",
+            visibility_print_with_space(it.visibility(cx.tcx()), it.item_id, cx),
+            it.name.unwrap(),
+        );
     });
 
     document(w, cx, it, None, HeadingOffset::H2);
@@ -1609,20 +1578,11 @@ fn bounds(t_bounds: &[clean::GenericBound], trait_alias: bool, cx: &Context<'_>)
     bounds
 }
 
-fn wrap_into_item_decl<F>(w: &mut Buffer, f: F)
-where
-    F: FnOnce(&mut Buffer),
-{
-    w.write_str("<div class=\"item-decl\">");
-    f(w);
-    w.write_str("</div>")
-}
-
 fn wrap_item<F>(w: &mut Buffer, f: F)
 where
     F: FnOnce(&mut Buffer),
 {
-    w.write_str(r#"<pre class="rust"><code>"#);
+    w.write_str(r#"<pre class="rust item-decl"><code>"#);
     f(w);
     w.write_str("</code></pre>");
 }
index bc8badad38eb0578ea3a0b5f40310241b66eab0c..6b71ecc24bde6f8e3604729a57e0df84172ea715 100644 (file)
@@ -11,7 +11,7 @@
 use serde::ser::SerializeSeq;
 use serde::{Serialize, Serializer};
 
-use super::{collect_paths_for_type, ensure_trailing_slash, Context, BASIC_KEYWORDS};
+use super::{collect_paths_for_type, ensure_trailing_slash, Context};
 use crate::clean::Crate;
 use crate::config::{EmitType, RenderOptions};
 use crate::docfs::PathError;
@@ -340,7 +340,6 @@ fn add_path(self: &Rc<Self>, path: &Path) {
                 root_path: "./",
                 static_root_path: shared.static_root_path.as_deref(),
                 description: "List of crates",
-                keywords: BASIC_KEYWORDS,
                 resource_suffix: &shared.resource_suffix,
             };
 
index 799c497d13709a00d95c7fcf6a07dc2fc482f8c4..2c90bf4fadc0186ee8633a4e0dead6231fab7fdb 100644 (file)
@@ -4,7 +4,7 @@
 use crate::html::format::Buffer;
 use crate::html::highlight;
 use crate::html::layout;
-use crate::html::render::{Context, BASIC_KEYWORDS};
+use crate::html::render::Context;
 use crate::visit::DocVisitor;
 
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
@@ -228,7 +228,6 @@ fn emit_source(
             root_path: &root_path,
             static_root_path: shared.static_root_path.as_deref(),
             description: &desc,
-            keywords: BASIC_KEYWORDS,
             resource_suffix: &shared.resource_suffix,
         };
         let v = layout::render(
index 8699508e43916af754f142937b60ac7312714c8b..c8ab3ef70d7b7e6ce8233d0048f3f6b3f1929d0c 100644 (file)
@@ -335,7 +335,7 @@ pre {
        padding: 14px;
        line-height: 1.5; /* https://github.com/rust-lang/rust/issues/105906 */
 }
-.item-decl pre {
+pre.item-decl {
        overflow-x: auto;
 }
 /* This rule allows to have scrolling on the X axis. */
@@ -1262,6 +1262,14 @@ a.test-arrow:hover {
        line-height: 1.5;
        color: inherit;
 }
+#search-tabs button:not(.selected) {
+       background-color: var(--search-tab-button-not-selected-background);
+       border-top-color: var(--search-tab-button-not-selected-border-top-color);
+}
+#search-tabs button:hover, #search-tabs button.selected {
+       background-color: var(--search-tab-button-selected-background);
+       border-top-color: var(--search-tab-button-selected-border-top-color);
+}
 
 #search-tabs .count {
        font-size: 1rem;
index ed779bf6166eed34cb97036796868426617b05aa..d20d13ab36d2d892ff800792bb778457c52257c2 100644 (file)
@@ -46,6 +46,10 @@ Original by Dempfi (https://github.com/dempfi/ayu)
        --search-results-alias-color: #c5c5c5;
        --search-results-grey-color: #999;
        --search-tab-title-count-color: #888;
+       --search-tab-button-not-selected-border-top-color: none;
+       --search-tab-button-not-selected-background: transparent !important;
+       --search-tab-button-selected-border-top-color: none;
+       --search-tab-button-selected-background: #141920 !important;
        --stab-background-color: #314559;
        --stab-code-color: #e6e1cf;
        --code-highlight-kw-color: #ff7733;
@@ -171,28 +175,17 @@ pre, .rustdoc.source .example-wrap {
 }
 
 #search-tabs > button.selected {
-       background-color: #141920 !important;
        border-bottom: 1px solid #ffb44c !important;
        border-top: none;
 }
-
 #search-tabs > button:not(.selected) {
-       background-color: transparent !important;
        border: none;
+       background-color: transparent !important;
 }
-
 #search-tabs > button:hover {
        border-bottom: 1px solid rgba(242, 151, 24, 0.3);
 }
 
-/* rules that this theme does not need to set, here to satisfy the rule checker */
-/* note that a lot of these are partially set in some way (meaning they are set
-individually rather than as a group) */
-/* FIXME: these rules should be at the bottom of the file but currently must be
-above the `@media (max-width: 700px)` rules due to a bug in the css checker */
-/* see https://github.com/rust-lang/rust/pull/71237#issuecomment-618170143 */
-#search-tabs > button:hover, #search-tabs > button.selected {}
-
 #settings-menu > a img {
        filter: invert(100);
 }
index 3766f0daa42ff837264542bee9f59c15212b3170..b84d87c4a54f3827150507ed1d78a69d1c238b2f 100644 (file)
        --search-results-alias-color: #fff;
        --search-results-grey-color: #ccc;
        --search-tab-title-count-color: #888;
+       --search-tab-button-not-selected-border-top-color: #252525;
+       --search-tab-button-not-selected-background: #252525;
+       --search-tab-button-selected-border-top-color: #0089ff;
+       --search-tab-button-selected-background: #353535;
        --stab-background-color: #314559;
        --stab-code-color: #e6e1cf;
        --code-highlight-kw-color: #ab8ac1;
        --scrape-example-code-wrapper-background-start: rgba(53, 53, 53, 1);
        --scrape-example-code-wrapper-background-end: rgba(53, 53, 53, 0);
 }
-
-#search-tabs > button:not(.selected) {
-       background-color: #252525;
-       border-top-color: #252525;
-}
-
-#search-tabs > button:hover, #search-tabs > button.selected {
-       border-top-color: #0089ff;
-       background-color: #353535;
-}
index 8a7f6abcf8d8e83141923f3a8400bd38606725bd..342274e67671870b55db646efd65ebe0c851e6b7 100644 (file)
        --search-results-alias-color: #000;
        --search-results-grey-color: #999;
        --search-tab-title-count-color: #888;
+       --search-tab-button-not-selected-border-top-color: #e6e6e6;
+       --search-tab-button-not-selected-background: #e6e6e6;
+       --search-tab-button-selected-border-top-color: #0089ff;
+       --search-tab-button-selected-background: #ffffff;
        --stab-background-color: #fff5d6;
        --stab-code-color: #000;
        --code-highlight-kw-color: #8959a8;
        --scrape-example-code-wrapper-background-start: rgba(255, 255, 255, 1);
        --scrape-example-code-wrapper-background-end: rgba(255, 255, 255, 0);
 }
-
-#search-tabs > button:not(.selected) {
-       background-color: #e6e6e6;
-       border-top-color: #e6e6e6;
-}
-
-#search-tabs > button:hover, #search-tabs > button.selected {
-       background-color: #ffffff;
-       border-top-color: #0089ff;
-}
index a841b4b63bae8c1c557fd29475bcb6f016144380..1cd552e7f25b712799c2855fd2dc6281e34ed215 100644 (file)
@@ -1,5 +1,5 @@
 // Local js definitions:
-/* global getSettingValue, getVirtualKey, updateLocalStorage, updateSystemTheme */
+/* global getSettingValue, getVirtualKey, updateLocalStorage, updateTheme */
 /* global addClass, removeClass, onEach, onEachLazy, blurHandler, elemIsInParent */
 /* global MAIN_ID, getVar, getSettingsButton */
 
@@ -19,7 +19,7 @@
             case "theme":
             case "preferred-dark-theme":
             case "preferred-light-theme":
-                updateSystemTheme();
+                updateTheme();
                 updateLightAndDark();
                 break;
             case "line-numbers":
index db2db83ca631008030a6f30f447011c8363211fb..8836d1b2e464bca1dd00c35ad9bd240ddbf72152 100644 (file)
@@ -153,79 +153,74 @@ function switchTheme(styleElem, mainStyleElem, newThemeName, saveTheme) {
     }
 }
 
-// This function is called from "main.js".
-// eslint-disable-next-line no-unused-vars
-function useSystemTheme(value) {
-    if (value === undefined) {
-        value = true;
-    }
-
-    updateLocalStorage("use-system-theme", value);
-
-    // update the toggle if we're on the settings page
-    const toggle = document.getElementById("use-system-theme");
-    if (toggle && toggle instanceof HTMLInputElement) {
-        toggle.checked = value;
-    }
-}
-
-const updateSystemTheme = (function() {
-    if (!window.matchMedia) {
-        // fallback to the CSS computed value
-        return () => {
-            const cssTheme = getComputedStyle(document.documentElement)
-                .getPropertyValue("content");
-
-            switchTheme(
-                window.currentTheme,
-                window.mainTheme,
-                JSON.parse(cssTheme) || "light",
-                true
-            );
+const updateTheme = (function() {
+    /**
+     * Update the current theme to match whatever the current combination of
+     * * the preference for using the system theme
+     *   (if this is the case, the value of preferred-light-theme, if the
+     *   system theme is light, otherwise if dark, the value of
+     *   preferred-dark-theme.)
+     * * the preferred theme
+     * â€¦ dictates that it should be.
+     */
+    function updateTheme() {
+        const use = (theme, saveTheme) => {
+            switchTheme(window.currentTheme, window.mainTheme, theme, saveTheme);
         };
-    }
-
-    // only listen to (prefers-color-scheme: dark) because light is the default
-    const mql = window.matchMedia("(prefers-color-scheme: dark)");
 
-    function handlePreferenceChange(mql) {
-        const use = theme => {
-            switchTheme(window.currentTheme, window.mainTheme, theme, true);
-        };
         // maybe the user has disabled the setting in the meantime!
         if (getSettingValue("use-system-theme") !== "false") {
             const lightTheme = getSettingValue("preferred-light-theme") || "light";
             const darkTheme = getSettingValue("preferred-dark-theme") || "dark";
 
-            if (mql.matches) {
-                use(darkTheme);
+            if (isDarkMode()) {
+                use(darkTheme, true);
             } else {
                 // prefers a light theme, or has no preference
-                use(lightTheme);
+                use(lightTheme, true);
             }
             // note: we save the theme so that it doesn't suddenly change when
             // the user disables "use-system-theme" and reloads the page or
             // navigates to another page
         } else {
-            use(getSettingValue("theme"));
+            use(getSettingValue("theme"), false);
         }
     }
 
-    mql.addListener(handlePreferenceChange);
+    // This is always updated below to a function () => bool.
+    let isDarkMode;
 
-    return () => {
-        handlePreferenceChange(mql);
-    };
-})();
+    // Determine the function for isDarkMode, and if we have
+    // `window.matchMedia`, set up an event listener on the preferred color
+    // scheme.
+    //
+    // Otherwise, fall back to the prefers-color-scheme value CSS captured in
+    // the "content" property.
+    if (window.matchMedia) {
+        // only listen to (prefers-color-scheme: dark) because light is the default
+        const mql = window.matchMedia("(prefers-color-scheme: dark)");
 
-function switchToSavedTheme() {
-    switchTheme(
-        window.currentTheme,
-        window.mainTheme,
-        getSettingValue("theme") || "light",
-        false
-    );
-}
+        isDarkMode = () => mql.matches;
+
+        if (mql.addEventListener) {
+            mql.addEventListener("change", updateTheme);
+        } else {
+            // This is deprecated, see:
+            // https://developer.mozilla.org/en-US/docs/Web/API/MediaQueryList/addListener
+            mql.addListener(updateTheme);
+        }
+    } else {
+        // fallback to the CSS computed value
+        const cssContent = getComputedStyle(document.documentElement)
+            .getPropertyValue("content");
+        // (Note: the double-quotes come from that this is a CSS value, which
+        // might be a length, string, etc.)
+        const cssColorScheme = cssContent || "\"light\"";
+        isDarkMode = () => (cssColorScheme === "\"dark\"");
+    }
+
+    return updateTheme;
+})();
 
 if (getSettingValue("use-system-theme") !== "false" && window.matchMedia) {
     // update the preferred dark theme if the user is already using a dark theme
@@ -235,13 +230,10 @@ if (getSettingValue("use-system-theme") !== "false" && window.matchMedia) {
         && darkThemes.indexOf(localStoredTheme) >= 0) {
         updateLocalStorage("preferred-dark-theme", localStoredTheme);
     }
-
-    // call the function to initialize the theme at least once!
-    updateSystemTheme();
-} else {
-    switchToSavedTheme();
 }
 
+updateTheme();
+
 if (getSettingValue("source-sidebar-show") === "true") {
     // At this point in page load, `document.body` is not available yet.
     // Set a class on the `<html>` element instead.
@@ -259,6 +251,6 @@ if (getSettingValue("source-sidebar-show") === "true") {
 // specifically when talking to a remote website with no caching.
 window.addEventListener("pageshow", ev => {
     if (ev.persisted) {
-        setTimeout(switchToSavedTheme, 0);
+        setTimeout(updateTheme, 0);
     }
 });
index fddda293b9a86d98cf300cb1ebc672ae80fe1df3..8540ee6631934c7d163644fd17e52553b9f5b1a2 100644 (file)
@@ -5,7 +5,6 @@
     <meta name="viewport" content="width=device-width, initial-scale=1.0"> {#- -#}
     <meta name="generator" content="rustdoc"> {#- -#}
     <meta name="description" content="{{page.description}}"> {#- -#}
-    <meta name="keywords" content="{{page.keywords}}"> {#- -#}
     <title>{{page.title}}</title> {#- -#}
     <link rel="preload" as="font" type="font/woff2" crossorigin href="{{static_root_path|safe}}{{files.source_serif_4_regular}}"> {#- -#}
     <link rel="preload" as="font" type="font/woff2" crossorigin href="{{static_root_path|safe}}{{files.fira_sans_regular}}"> {#- -#}
index 4bd0aa09872398959e3fbe0a1ea2c12050020756..38d402b8f21610381d70f397bae53822793f76e9 100644 (file)
           StorageLive(_4);                 // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:13: +3:15
           StorageLive(_5);                 // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:23: +3:24
           _5 = const 3_usize;              // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:23: +3:24
-          _6 = Len((*_1));                 // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25
+          _6 = const 3_usize;              // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25
 -         _7 = Lt(_5, _6);                 // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25
 -         assert(move _7, "index out of bounds: the length is {} but the index is {}", move _6, _5) -> bb1; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25
-+         _7 = Lt(const 3_usize, _6);      // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25
-+         assert(move _7, "index out of bounds: the length is {} but the index is {}", move _6, const 3_usize) -> bb1; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25
++         _7 = const false;                // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25
++         assert(const false, "index out of bounds: the length is {} but the index is {}", const 3_usize, const 3_usize) -> bb1; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25
       }
   
       bb1: {
index 4bd0aa09872398959e3fbe0a1ea2c12050020756..38d402b8f21610381d70f397bae53822793f76e9 100644 (file)
           StorageLive(_4);                 // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:13: +3:15
           StorageLive(_5);                 // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:23: +3:24
           _5 = const 3_usize;              // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:23: +3:24
-          _6 = Len((*_1));                 // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25
+          _6 = const 3_usize;              // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25
 -         _7 = Lt(_5, _6);                 // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25
 -         assert(move _7, "index out of bounds: the length is {} but the index is {}", move _6, _5) -> bb1; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25
-+         _7 = Lt(const 3_usize, _6);      // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25
-+         assert(move _7, "index out of bounds: the length is {} but the index is {}", move _6, const 3_usize) -> bb1; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25
++         _7 = const false;                // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25
++         assert(const false, "index out of bounds: the length is {} but the index is {}", const 3_usize, const 3_usize) -> bb1; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25
       }
   
       bb1: {
index c8b405ca8eaaf374702246cd420f0a63eb9dd996..fbbfd4ceb112ba59980ecfd1da1ae8f1d28f4cc6 100644 (file)
@@ -1,3 +1,4 @@
+// compile-flags: -Zmir-enable-passes=-NormalizeArrayLen
 // Check that we do not insert StorageDead at each target if StorageDead was never seen
 
 // EMIT_MIR issue_76432.test.SimplifyComparisonIntegral.diff
index 9bc7060e958ebf56c4083692fc647fcc9d746149..59de067f4a4f8c9773ff04726b13cbd9e8aab13f 100644 (file)
@@ -13,7 +13,6 @@
       let _8: usize;                       // in scope 0 at $DIR/lower_array_len.rs:+2:15: +2:20
       let mut _9: usize;                   // in scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21
       let mut _10: bool;                   // in scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21
-+     let mut _11: &[u8; N];               // in scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
   
       bb0: {
           StorageLive(_3);                 // scope 0 at $DIR/lower_array_len.rs:+1:8: +1:27
           StorageLive(_6);                 // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
           StorageLive(_7);                 // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
           _7 = &(*_2);                     // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
-+         StorageLive(_11);                // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
-+         _11 = _7;                        // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
           _6 = move _7 as &[u8] (Pointer(Unsize)); // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
           StorageDead(_7);                 // scope 0 at $DIR/lower_array_len.rs:+1:20: +1:21
 -         _5 = Len((*_6));                 // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
-+         _5 = Len((*_11));                // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
-+         StorageDead(_11);                // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
++         _5 = const N;                    // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
           goto -> bb1;                     // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
       }
   
index cf427cfd1e6dbb7a71c4b57401847c4b37cc500a..17574b1b635681aee95cfd859ad695a51f61e153 100644 (file)
@@ -16,7 +16,6 @@
       let _11: usize;                      // in scope 0 at $DIR/lower_array_len.rs:+4:15: +4:16
       let mut _12: usize;                  // in scope 0 at $DIR/lower_array_len.rs:+4:9: +4:17
       let mut _13: bool;                   // in scope 0 at $DIR/lower_array_len.rs:+4:9: +4:17
-+     let mut _14: &[u8; N];               // in scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
   
       bb0: {
           StorageLive(_3);                 // scope 0 at $DIR/lower_array_len.rs:+1:8: +1:27
           StorageLive(_6);                 // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
           StorageLive(_7);                 // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
           _7 = &(*_2);                     // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
-+         StorageLive(_14);                // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
-+         _14 = _7;                        // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
           _6 = move _7 as &[u8] (Pointer(Unsize)); // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
           StorageDead(_7);                 // scope 0 at $DIR/lower_array_len.rs:+1:20: +1:21
 -         _5 = Len((*_6));                 // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
-+         _5 = Len((*_14));                // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
-+         StorageDead(_14);                // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
++         _5 = const N;                    // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
           goto -> bb1;                     // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
       }
   
index 3ed68f5f7256872070e47f02585ce5771aa492cf..66feff62f424680192a6bb3549433058facf6d2a 100644 (file)
@@ -6,19 +6,15 @@
       let mut _0: usize;                   // return place in scope 0 at $DIR/lower_array_len.rs:+0:52: +0:57
       let mut _2: &[u8];                   // in scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
       let mut _3: &[u8; N];                // in scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
-+     let mut _4: &[u8; N];                // in scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
   
       bb0: {
           StorageLive(_2);                 // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
           StorageLive(_3);                 // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
           _3 = &(*_1);                     // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
-+         StorageLive(_4);                 // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
-+         _4 = _3;                         // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
           _2 = move _3 as &[u8] (Pointer(Unsize)); // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
           StorageDead(_3);                 // scope 0 at $DIR/lower_array_len.rs:+1:7: +1:8
 -         _0 = Len((*_2));                 // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
-+         _0 = Len((*_4));                 // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
-+         StorageDead(_4);                 // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
++         _0 = const N;                    // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
           goto -> bb1;                     // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
       }
   
index f0e0cdcfdc0e4e2f85e6f28d31b8d2c681bf628b..c0a277edc46700ea9ece6e395f77f5bb1a4430bd 100644 (file)
@@ -6,19 +6,15 @@
       let mut _0: usize;                   // return place in scope 0 at $DIR/lower_array_len.rs:+0:60: +0:65
       let mut _2: &[u8];                   // in scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
       let mut _3: &[u8; N];                // in scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
-+     let mut _4: &[u8; N];                // in scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
   
       bb0: {
           StorageLive(_2);                 // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
           StorageLive(_3);                 // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
           _3 = &_1;                        // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
-+         StorageLive(_4);                 // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
-+         _4 = _3;                         // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
           _2 = move _3 as &[u8] (Pointer(Unsize)); // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
           StorageDead(_3);                 // scope 0 at $DIR/lower_array_len.rs:+1:7: +1:8
 -         _0 = Len((*_2));                 // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
-+         _0 = Len((*_4));                 // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
-+         StorageDead(_4);                 // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
++         _0 = const N;                    // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
           goto -> bb1;                     // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
       }
   
diff --git a/tests/mir-opt/lower_array_len.array_len_raw.NormalizeArrayLen.diff b/tests/mir-opt/lower_array_len.array_len_raw.NormalizeArrayLen.diff
new file mode 100644 (file)
index 0000000..8b35fd5
--- /dev/null
@@ -0,0 +1,50 @@
+- // MIR for `array_len_raw` before NormalizeArrayLen
++ // MIR for `array_len_raw` after NormalizeArrayLen
+  
+  fn array_len_raw(_1: [u8; N]) -> usize {
+      debug arr => _1;                     // in scope 0 at $DIR/lower_array_len.rs:+0:38: +0:41
+      let mut _0: usize;                   // return place in scope 0 at $DIR/lower_array_len.rs:+0:55: +0:60
+      let _2: &[u8];                       // in scope 0 at $DIR/lower_array_len.rs:+1:9: +1:12
+      let mut _3: &[u8; N];                // in scope 0 at $DIR/lower_array_len.rs:+1:21: +1:25
+      let _4: &[u8; N];                    // in scope 0 at $DIR/lower_array_len.rs:+1:21: +1:25
+      let mut _6: &[u8];                   // in scope 0 at $DIR/lower_array_len.rs:+3:5: +3:27
+      let _7: &[u8];                       // in scope 0 at $DIR/lower_array_len.rs:+3:14: +3:19
+      scope 1 {
+          debug arr => _2;                 // in scope 1 at $DIR/lower_array_len.rs:+1:9: +1:12
+          let _5: *const [u8];             // in scope 1 at $DIR/lower_array_len.rs:+2:9: +2:12
+          scope 2 {
+              debug arr => _5;             // in scope 2 at $DIR/lower_array_len.rs:+2:9: +2:12
+              scope 3 {
+              }
+          }
+      }
+  
+      bb0: {
+          StorageLive(_2);                 // scope 0 at $DIR/lower_array_len.rs:+1:9: +1:12
+          StorageLive(_3);                 // scope 0 at $DIR/lower_array_len.rs:+1:21: +1:25
+          StorageLive(_4);                 // scope 0 at $DIR/lower_array_len.rs:+1:21: +1:25
+          _4 = &_1;                        // scope 0 at $DIR/lower_array_len.rs:+1:21: +1:25
+          _3 = &(*_4);                     // scope 0 at $DIR/lower_array_len.rs:+1:21: +1:25
+          _2 = move _3 as &[u8] (Pointer(Unsize)); // scope 0 at $DIR/lower_array_len.rs:+1:21: +1:25
+          StorageDead(_3);                 // scope 0 at $DIR/lower_array_len.rs:+1:24: +1:25
+          StorageDead(_4);                 // scope 0 at $DIR/lower_array_len.rs:+1:25: +1:26
+          StorageLive(_5);                 // scope 1 at $DIR/lower_array_len.rs:+2:9: +2:12
+          _5 = &raw const (*_2);           // scope 1 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+          StorageLive(_6);                 // scope 2 at $DIR/lower_array_len.rs:+3:5: +3:27
+          StorageLive(_7);                 // scope 2 at $DIR/lower_array_len.rs:+3:14: +3:19
+          _7 = &(*_5);                     // scope 3 at $DIR/lower_array_len.rs:+3:14: +3:19
+          _6 = &(*_7);                     // scope 2 at $DIR/lower_array_len.rs:+3:5: +3:27
+-         _0 = Len((*_6));                 // scope 2 at $DIR/lower_array_len.rs:+3:5: +3:27
++         _0 = const N;                    // scope 2 at $DIR/lower_array_len.rs:+3:5: +3:27
+          goto -> bb1;                     // scope 2 at $DIR/lower_array_len.rs:+3:5: +3:27
+      }
+  
+      bb1: {
+          StorageDead(_6);                 // scope 2 at $DIR/lower_array_len.rs:+3:26: +3:27
+          StorageDead(_5);                 // scope 1 at $DIR/lower_array_len.rs:+4:1: +4:2
+          StorageDead(_2);                 // scope 0 at $DIR/lower_array_len.rs:+4:1: +4:2
+          StorageDead(_7);                 // scope 0 at $DIR/lower_array_len.rs:+4:1: +4:2
+          return;                          // scope 0 at $DIR/lower_array_len.rs:+4:2: +4:2
+      }
+  }
+  
diff --git a/tests/mir-opt/lower_array_len.array_len_reborrow.NormalizeArrayLen.diff b/tests/mir-opt/lower_array_len.array_len_reborrow.NormalizeArrayLen.diff
new file mode 100644 (file)
index 0000000..8bdd2ed
--- /dev/null
@@ -0,0 +1,44 @@
+- // MIR for `array_len_reborrow` before NormalizeArrayLen
++ // MIR for `array_len_reborrow` after NormalizeArrayLen
+  
+  fn array_len_reborrow(_1: [u8; N]) -> usize {
+      debug arr => _1;                     // in scope 0 at $DIR/lower_array_len.rs:+0:43: +0:50
+      let mut _0: usize;                   // return place in scope 0 at $DIR/lower_array_len.rs:+0:64: +0:69
+      let _2: &mut [u8];                   // in scope 0 at $DIR/lower_array_len.rs:+1:9: +1:12
+      let mut _3: &mut [u8; N];            // in scope 0 at $DIR/lower_array_len.rs:+1:25: +1:33
+      let mut _4: &mut [u8; N];            // in scope 0 at $DIR/lower_array_len.rs:+1:25: +1:33
+      let mut _6: &[u8];                   // in scope 0 at $DIR/lower_array_len.rs:+3:5: +3:14
+      scope 1 {
+          debug arr => _2;                 // in scope 1 at $DIR/lower_array_len.rs:+1:9: +1:12
+          let _5: &[u8];                   // in scope 1 at $DIR/lower_array_len.rs:+2:9: +2:12
+          scope 2 {
+              debug arr => _5;             // in scope 2 at $DIR/lower_array_len.rs:+2:9: +2:12
+          }
+      }
+  
+      bb0: {
+          StorageLive(_2);                 // scope 0 at $DIR/lower_array_len.rs:+1:9: +1:12
+          StorageLive(_3);                 // scope 0 at $DIR/lower_array_len.rs:+1:25: +1:33
+          StorageLive(_4);                 // scope 0 at $DIR/lower_array_len.rs:+1:25: +1:33
+          _4 = &mut _1;                    // scope 0 at $DIR/lower_array_len.rs:+1:25: +1:33
+          _3 = &mut (*_4);                 // scope 0 at $DIR/lower_array_len.rs:+1:25: +1:33
+          _2 = move _3 as &mut [u8] (Pointer(Unsize)); // scope 0 at $DIR/lower_array_len.rs:+1:25: +1:33
+          StorageDead(_3);                 // scope 0 at $DIR/lower_array_len.rs:+1:32: +1:33
+          StorageDead(_4);                 // scope 0 at $DIR/lower_array_len.rs:+1:33: +1:34
+          StorageLive(_5);                 // scope 1 at $DIR/lower_array_len.rs:+2:9: +2:12
+          _5 = &(*_2);                     // scope 1 at $DIR/lower_array_len.rs:+2:15: +2:20
+          StorageLive(_6);                 // scope 2 at $DIR/lower_array_len.rs:+3:5: +3:14
+          _6 = &(*_5);                     // scope 2 at $DIR/lower_array_len.rs:+3:5: +3:14
+-         _0 = Len((*_6));                 // scope 2 at $DIR/lower_array_len.rs:+3:5: +3:14
++         _0 = const N;                    // scope 2 at $DIR/lower_array_len.rs:+3:5: +3:14
+          goto -> bb1;                     // scope 2 at $DIR/lower_array_len.rs:+3:5: +3:14
+      }
+  
+      bb1: {
+          StorageDead(_6);                 // scope 2 at $DIR/lower_array_len.rs:+3:13: +3:14
+          StorageDead(_5);                 // scope 1 at $DIR/lower_array_len.rs:+4:1: +4:2
+          StorageDead(_2);                 // scope 0 at $DIR/lower_array_len.rs:+4:1: +4:2
+          return;                          // scope 0 at $DIR/lower_array_len.rs:+4:2: +4:2
+      }
+  }
+  
index ea0224b21d72d769972aef5f75c3c0876ae8b495..972d46cb8e2bd284976d1bdee770da63aa3a7f86 100644 (file)
     arr.len()
 }
 
+// EMIT_MIR lower_array_len.array_len_reborrow.NormalizeArrayLen.diff
+pub fn array_len_reborrow<const N: usize>(mut arr: [u8; N]) -> usize {
+    let arr: &mut [_] = &mut arr;
+    let arr = &*arr;
+    arr.len()
+}
+
+// EMIT_MIR lower_array_len.array_len_raw.NormalizeArrayLen.diff
+pub fn array_len_raw<const N: usize>(arr: [u8; N]) -> usize {
+    let arr: &[_] = &arr;
+    let arr = std::ptr::addr_of!(*arr);
+    unsafe { &*arr }.len()
+}
+
 fn main() {
     let _ = array_bound(3, &[0, 1, 2, 3]);
     let mut tmp = [0, 1, 2, 3, 4];
     let _ = array_bound_mut(3, &mut [0, 1, 2, 3]);
     let _ = array_len(&[0]);
     let _ = array_len_by_value([0, 2]);
+    let _ = array_len_reborrow([0, 2]);
+    let _ = array_len_raw([0, 2]);
 }
diff --git a/tests/mir-opt/lower_array_len_e2e.array_bound.PreCodegen.after.mir b/tests/mir-opt/lower_array_len_e2e.array_bound.PreCodegen.after.mir
deleted file mode 100644 (file)
index dee1d53..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-// MIR for `array_bound` after PreCodegen
-
-fn array_bound(_1: usize, _2: &[u8; N]) -> u8 {
-    debug index => _1;                   // in scope 0 at $DIR/lower_array_len_e2e.rs:+0:36: +0:41
-    debug slice => _2;                   // in scope 0 at $DIR/lower_array_len_e2e.rs:+0:50: +0:55
-    let mut _0: u8;                      // return place in scope 0 at $DIR/lower_array_len_e2e.rs:+0:70: +0:72
-    let mut _3: bool;                    // in scope 0 at $DIR/lower_array_len_e2e.rs:+1:8: +1:27
-    let mut _4: usize;                   // in scope 0 at $DIR/lower_array_len_e2e.rs:+1:16: +1:27
-    let mut _5: usize;                   // in scope 0 at $DIR/lower_array_len_e2e.rs:+2:9: +2:21
-    let mut _6: bool;                    // in scope 0 at $DIR/lower_array_len_e2e.rs:+2:9: +2:21
-
-    bb0: {
-        StorageLive(_3);                 // scope 0 at $DIR/lower_array_len_e2e.rs:+1:8: +1:27
-        StorageLive(_4);                 // scope 0 at $DIR/lower_array_len_e2e.rs:+1:16: +1:27
-        _4 = const N;                    // scope 0 at $DIR/lower_array_len_e2e.rs:+1:16: +1:27
-        _3 = Lt(_1, move _4);            // scope 0 at $DIR/lower_array_len_e2e.rs:+1:8: +1:27
-        StorageDead(_4);                 // scope 0 at $DIR/lower_array_len_e2e.rs:+1:26: +1:27
-        switchInt(move _3) -> [0: bb3, otherwise: bb1]; // scope 0 at $DIR/lower_array_len_e2e.rs:+1:8: +1:27
-    }
-
-    bb1: {
-        _5 = const N;                    // scope 0 at $DIR/lower_array_len_e2e.rs:+2:9: +2:21
-        _6 = Lt(_1, _5);                 // scope 0 at $DIR/lower_array_len_e2e.rs:+2:9: +2:21
-        assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, _1) -> bb2; // scope 0 at $DIR/lower_array_len_e2e.rs:+2:9: +2:21
-    }
-
-    bb2: {
-        _0 = (*_2)[_1];                  // scope 0 at $DIR/lower_array_len_e2e.rs:+2:9: +2:21
-        goto -> bb4;                     // scope 0 at $DIR/lower_array_len_e2e.rs:+1:5: +5:6
-    }
-
-    bb3: {
-        _0 = const 42_u8;                // scope 0 at $DIR/lower_array_len_e2e.rs:+4:9: +4:11
-        goto -> bb4;                     // scope 0 at $DIR/lower_array_len_e2e.rs:+1:5: +5:6
-    }
-
-    bb4: {
-        StorageDead(_3);                 // scope 0 at $DIR/lower_array_len_e2e.rs:+5:5: +5:6
-        return;                          // scope 0 at $DIR/lower_array_len_e2e.rs:+6:2: +6:2
-    }
-}
diff --git a/tests/mir-opt/lower_array_len_e2e.array_bound_mut.PreCodegen.after.mir b/tests/mir-opt/lower_array_len_e2e.array_bound_mut.PreCodegen.after.mir
deleted file mode 100644 (file)
index e35fe75..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-// MIR for `array_bound_mut` after PreCodegen
-
-fn array_bound_mut(_1: usize, _2: &mut [u8; N]) -> u8 {
-    debug index => _1;                   // in scope 0 at $DIR/lower_array_len_e2e.rs:+0:40: +0:45
-    debug slice => _2;                   // in scope 0 at $DIR/lower_array_len_e2e.rs:+0:54: +0:59
-    let mut _0: u8;                      // return place in scope 0 at $DIR/lower_array_len_e2e.rs:+0:78: +0:80
-    let mut _3: bool;                    // in scope 0 at $DIR/lower_array_len_e2e.rs:+1:8: +1:27
-    let mut _4: usize;                   // in scope 0 at $DIR/lower_array_len_e2e.rs:+1:16: +1:27
-    let mut _5: usize;                   // in scope 0 at $DIR/lower_array_len_e2e.rs:+2:9: +2:21
-    let mut _6: bool;                    // in scope 0 at $DIR/lower_array_len_e2e.rs:+2:9: +2:21
-    let _7: usize;                       // in scope 0 at $DIR/lower_array_len_e2e.rs:+4:15: +4:16
-    let mut _8: usize;                   // in scope 0 at $DIR/lower_array_len_e2e.rs:+4:9: +4:17
-    let mut _9: bool;                    // in scope 0 at $DIR/lower_array_len_e2e.rs:+4:9: +4:17
-
-    bb0: {
-        StorageLive(_3);                 // scope 0 at $DIR/lower_array_len_e2e.rs:+1:8: +1:27
-        StorageLive(_4);                 // scope 0 at $DIR/lower_array_len_e2e.rs:+1:16: +1:27
-        _4 = const N;                    // scope 0 at $DIR/lower_array_len_e2e.rs:+1:16: +1:27
-        _3 = Lt(_1, move _4);            // scope 0 at $DIR/lower_array_len_e2e.rs:+1:8: +1:27
-        StorageDead(_4);                 // scope 0 at $DIR/lower_array_len_e2e.rs:+1:26: +1:27
-        switchInt(move _3) -> [0: bb3, otherwise: bb1]; // scope 0 at $DIR/lower_array_len_e2e.rs:+1:8: +1:27
-    }
-
-    bb1: {
-        _5 = const N;                    // scope 0 at $DIR/lower_array_len_e2e.rs:+2:9: +2:21
-        _6 = Lt(_1, _5);                 // scope 0 at $DIR/lower_array_len_e2e.rs:+2:9: +2:21
-        assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, _1) -> bb2; // scope 0 at $DIR/lower_array_len_e2e.rs:+2:9: +2:21
-    }
-
-    bb2: {
-        _0 = (*_2)[_1];                  // scope 0 at $DIR/lower_array_len_e2e.rs:+2:9: +2:21
-        goto -> bb5;                     // scope 0 at $DIR/lower_array_len_e2e.rs:+1:5: +7:6
-    }
-
-    bb3: {
-        StorageLive(_7);                 // scope 0 at $DIR/lower_array_len_e2e.rs:+4:15: +4:16
-        _7 = const 0_usize;              // scope 0 at $DIR/lower_array_len_e2e.rs:+4:15: +4:16
-        _8 = const N;                    // scope 0 at $DIR/lower_array_len_e2e.rs:+4:9: +4:17
-        _9 = Lt(const 0_usize, _8);      // scope 0 at $DIR/lower_array_len_e2e.rs:+4:9: +4:17
-        assert(move _9, "index out of bounds: the length is {} but the index is {}", move _8, const 0_usize) -> bb4; // scope 0 at $DIR/lower_array_len_e2e.rs:+4:9: +4:17
-    }
-
-    bb4: {
-        (*_2)[_7] = const 42_u8;         // scope 0 at $DIR/lower_array_len_e2e.rs:+4:9: +4:22
-        StorageDead(_7);                 // scope 0 at $DIR/lower_array_len_e2e.rs:+4:22: +4:23
-        _0 = const 42_u8;                // scope 0 at $DIR/lower_array_len_e2e.rs:+6:9: +6:11
-        goto -> bb5;                     // scope 0 at $DIR/lower_array_len_e2e.rs:+1:5: +7:6
-    }
-
-    bb5: {
-        StorageDead(_3);                 // scope 0 at $DIR/lower_array_len_e2e.rs:+7:5: +7:6
-        return;                          // scope 0 at $DIR/lower_array_len_e2e.rs:+8:2: +8:2
-    }
-}
diff --git a/tests/mir-opt/lower_array_len_e2e.array_len.PreCodegen.after.mir b/tests/mir-opt/lower_array_len_e2e.array_len.PreCodegen.after.mir
deleted file mode 100644 (file)
index 4b19f67..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-// MIR for `array_len` after PreCodegen
-
-fn array_len(_1: &[u8; N]) -> usize {
-    debug arr => _1;                     // in scope 0 at $DIR/lower_array_len_e2e.rs:+0:34: +0:37
-    let mut _0: usize;                   // return place in scope 0 at $DIR/lower_array_len_e2e.rs:+0:52: +0:57
-
-    bb0: {
-        _0 = const N;                    // scope 0 at $DIR/lower_array_len_e2e.rs:+1:5: +1:14
-        return;                          // scope 0 at $DIR/lower_array_len_e2e.rs:+2:2: +2:2
-    }
-}
diff --git a/tests/mir-opt/lower_array_len_e2e.array_len_by_value.PreCodegen.after.mir b/tests/mir-opt/lower_array_len_e2e.array_len_by_value.PreCodegen.after.mir
deleted file mode 100644 (file)
index 4dc0ba9..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-// MIR for `array_len_by_value` after PreCodegen
-
-fn array_len_by_value(_1: [u8; N]) -> usize {
-    debug arr => _1;                     // in scope 0 at $DIR/lower_array_len_e2e.rs:+0:43: +0:46
-    let mut _0: usize;                   // return place in scope 0 at $DIR/lower_array_len_e2e.rs:+0:60: +0:65
-
-    bb0: {
-        _0 = const N;                    // scope 0 at $DIR/lower_array_len_e2e.rs:+1:5: +1:14
-        return;                          // scope 0 at $DIR/lower_array_len_e2e.rs:+2:2: +2:2
-    }
-}
diff --git a/tests/mir-opt/lower_array_len_e2e.rs b/tests/mir-opt/lower_array_len_e2e.rs
deleted file mode 100644 (file)
index d8e4e52..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-// compile-flags: -Z mir-opt-level=4 -Zunsound-mir-opts
-
-// EMIT_MIR lower_array_len_e2e.array_bound.PreCodegen.after.mir
-pub fn array_bound<const N: usize>(index: usize, slice: &[u8; N]) -> u8 {
-    if index < slice.len() {
-        slice[index]
-    } else {
-        42
-    }
-}
-
-// EMIT_MIR lower_array_len_e2e.array_bound_mut.PreCodegen.after.mir
-pub fn array_bound_mut<const N: usize>(index: usize, slice: &mut [u8; N]) -> u8 {
-    if index < slice.len() {
-        slice[index]
-    } else {
-        slice[0] = 42;
-
-        42
-    }
-}
-
-// EMIT_MIR lower_array_len_e2e.array_len.PreCodegen.after.mir
-pub fn array_len<const N: usize>(arr: &[u8; N]) -> usize {
-    arr.len()
-}
-
-// EMIT_MIR lower_array_len_e2e.array_len_by_value.PreCodegen.after.mir
-pub fn array_len_by_value<const N: usize>(arr: [u8; N]) -> usize {
-    arr.len()
-}
-
-fn main() {
-    let _ = array_bound(3, &[0, 1, 2, 3]);
-    let mut tmp = [0, 1, 2, 3, 4];
-    let _ = array_bound_mut(3, &mut [0, 1, 2, 3]);
-    let _ = array_len(&[0]);
-    let _ = array_len_by_value([0, 2]);
-}
index 44d21625a2d108a2e14e966d2e14328215adfa7b..e0fa1fe28246e7be95de552a3642e0666adb8d38 100644 (file)
@@ -34,10 +34,11 @@ fn bar() ({
                     ((::alloc::fmt::format as
                             for<'a> fn(Arguments<'a>) -> String {format})(((<#[lang = "format_arguments"]>::new_v1
                                 as
-                                fn(&[&'static str], &[ArgumentV1<'_>]) -> Arguments<'_> {Arguments::<'_>::new_v1})((&([("test"
+                                fn(&[&'static str], &[core::fmt::ArgumentV1<'_>]) -> Arguments<'_> {Arguments::<'_>::new_v1})((&([("test"
                                             as &str)] as [&str; 1]) as &[&str; 1]),
-                            (&([] as [ArgumentV1<'_>; 0]) as &[ArgumentV1<'_>; 0])) as
-                            Arguments<'_>)) as String);
+                            (&([] as [core::fmt::ArgumentV1<'_>; 0]) as
+                                &[core::fmt::ArgumentV1<'_>; 0])) as Arguments<'_>)) as
+                        String);
                 (res as String)
             } as String);
     } as ())
index 8561f537f3d32a8a18ce237832d04593fdf37be7..ca337cbc323e219c56590138e641e6c1c33f0cae 100644 (file)
@@ -9,16 +9,16 @@ size: (1080, 600)
 // Check that their content is inside <pre><code>
 assert-count: (".example-wrap pre > code", 4)
 // Check that function signature is inside <pre><code>
-assert: ".item-decl pre.rust > code"
+assert: "pre.rust.item-decl > code"
 
 goto: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html"
-assert: ".item-decl pre.rust > code"
+assert: "pre.rust.item-decl > code"
 
 goto: "file://" + |DOC_PATH| + "/test_docs/enum.AnEnum.html"
-assert: ".item-decl pre.rust > code"
+assert: "pre.rust.item-decl > code"
 
 goto: "file://" + |DOC_PATH| + "/test_docs/trait.AnotherOne.html"
-assert: ".item-decl pre.rust > code"
+assert: "pre.rust.item-decl > code"
 
 goto: "file://" + |DOC_PATH| + "/test_docs/type.SomeType.html"
-assert: ".item-decl pre.rust > code"
+assert: "pre.rust.item-decl > code"
index fafb156317866cc1970c78c0cc1395a0485afdf2..aad334d2bd29586e8aef37365aaacae1cf9e610b 100644 (file)
@@ -1,6 +1,6 @@
 // This test checks that the font weight is correctly applied.
 goto: "file://" + |DOC_PATH| + "/lib2/struct.Foo.html"
-assert-css: ("//*[@class='item-decl']//a[text()='Alias']", {"font-weight": "400"})
+assert-css: ("//*[@class='rust item-decl']//a[text()='Alias']", {"font-weight": "400"})
 assert-css: (
     "//*[@class='structfield small-section-header']//a[text()='Alias']",
     {"font-weight": "400"},
@@ -19,8 +19,7 @@ goto: "file://" + |DOC_PATH| + "/lib2/trait.Trait.html"
 
 // This is a complex selector, so here's how it works:
 //
-// * //*[@class='item-decl'] â€” selects element of any tag with classes docblock and item-decl
-// * /pre[@class='rust'] â€” selects immediate child with tag pre and class rust
+// * //pre[@class='rust item-decl'] â€” selects item-decl code block
 // * /code â€” selects immediate child with tag code
 // * /a[@class='constant'] â€” selects immediate child with tag a and class constant
 // * //text() â€” selects child that is text node
@@ -29,11 +28,11 @@ goto: "file://" + |DOC_PATH| + "/lib2/trait.Trait.html"
 // This uses '/parent::*' as a proxy for the style of the text node.
 // We can't just select the '<a>' because intermediate tags could be added.
 assert-count: (
-    "//*[@class='item-decl']/pre[@class='rust']/code/a[@class='constant']//text()/parent::*",
+    "//pre[@class='rust item-decl']/code/a[@class='constant']//text()/parent::*",
     1,
 )
 assert-css: (
-    "//*[@class='item-decl']/pre[@class='rust']/code/a[@class='constant']//text()/parent::*",
+    "//pre[@class='rust item-decl']/code/a[@class='constant']//text()/parent::*",
     {"font-weight": "400"},
 )
 
index c527cfbfcbc5630558ab81e40d3fd7c0d094d109..4c477d70c8956e1a1335a5d6a5859d5bfec6ebfe 100644 (file)
@@ -1,4 +1,4 @@
 // This test checks that code blocks in list are supported.
 goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
 goto: "./fn.check_list_code_block.html"
-assert: (".item-decl pre.rust")
+assert: ("pre.rust.item-decl")
index 644429c014c1801c9dedefe6c35ae6a3eedded92..708e9dca0ee7b5d73e56d87a21ff2e9ec541216e 100644 (file)
@@ -12,7 +12,7 @@ size: (1100, 800)
 // Logically, the <body> scroll width should be the width of the window.
 assert-property: ("body", {"scrollWidth": "1100"})
 // However, since there is overflow in the type declaration, its scroll width is bigger.
-assert-property: (".item-decl pre", {"scrollWidth": "1324"})
+assert-property: ("pre.item-decl", {"scrollWidth": "1324"})
 
 // In the table-ish view on the module index, the name should not be wrapped more than necessary.
 goto: "file://" + |DOC_PATH| + "/lib2/too_long/index.html"
@@ -24,7 +24,7 @@ assert-property: ("body", {"scrollWidth": "1100"})
 // We now check that the section width hasn't grown because of it.
 assert-property: ("#main-content", {"scrollWidth": "840"})
 // And now checking that it has scrollable content.
-assert-property: (".item-decl pre", {"scrollWidth": "1103"})
+assert-property: ("pre.item-decl", {"scrollWidth": "1103"})
 
 // ... and constant.
 // On a sidenote, it also checks that the (very) long title isn't changing the docblock width.
@@ -33,7 +33,7 @@ assert-property: ("body", {"scrollWidth": "1100"})
 // We now check that the section width hasn't grown because of it.
 assert-property: ("#main-content", {"scrollWidth": "840"})
 // And now checking that it has scrollable content.
-assert-property: (".item-decl pre", {"scrollWidth": "950"})
+assert-property: ("pre.item-decl", {"scrollWidth": "950"})
 
 // On mobile:
 size: (600, 600)
@@ -65,12 +65,12 @@ compare-elements-position-false: (".main-heading h1", ".main-heading .out-of-ban
 goto: "file://" + |DOC_PATH| + "/lib2/scroll_traits/trait.Iterator.html"
 
 click: ".item-decl .type-contents-toggle"
-assert-property: (".item-decl > pre", {"scrollLeft": 0})
-scroll-to: "//*[@class='item-decl']//details/a[text()='String']"
-assert-property-false: (".item-decl > pre", {"scrollLeft": 0})
+assert-property: ("pre.item-decl", {"scrollLeft": 0})
+scroll-to: "//*[@class='rust item-decl']//details/a[text()='String']"
+assert-property-false: ("pre.item-decl", {"scrollLeft": 0})
 
 // Then on an item without "hidden methods".
 goto: "file://" + |DOC_PATH| + "/lib2/scroll_traits/trait.TraitWithLongItemsName.html"
-assert-property: (".item-decl > pre", {"scrollLeft": 0})
-scroll-to: "//*[@class='item-decl']//code/a[text()='String']"
-assert-property-false: (".item-decl > pre", {"scrollLeft": 0})
+assert-property: ("pre.item-decl", {"scrollLeft": 0})
+scroll-to: "//*[@class='rust item-decl']//code/a[text()='String']"
+assert-property-false: ("pre.item-decl", {"scrollLeft": 0})
index e7c0ee2de1a7a9036cc55a6ea9f6aecd588acfd5..8ee294daa963d7e535c23889f4eb83277c94f430 100644 (file)
@@ -4,25 +4,25 @@
 pub struct MyBox<T: ?Sized>(*const T);
 
 // @has 'foo/fn.alpha.html'
-// @snapshot link_slice_u32 - '//div[@class="item-decl"]/pre[@class="rust"]/code'
+// @snapshot link_slice_u32 - '//pre[@class="rust item-decl"]/code'
 pub fn alpha() -> &'static [u32; 1] {
     loop {}
 }
 
 // @has 'foo/fn.beta.html'
-// @snapshot link_slice_generic - '//div[@class="item-decl"]/pre[@class="rust"]/code'
+// @snapshot link_slice_generic - '//pre[@class="rust item-decl"]/code'
 pub fn beta<T>() -> &'static [T; 1] {
     loop {}
 }
 
 // @has 'foo/fn.gamma.html'
-// @snapshot link_box_u32 - '//div[@class="item-decl"]/pre[@class="rust"]/code'
+// @snapshot link_box_u32 - '//pre[@class="rust item-decl"]/code'
 pub fn gamma() -> MyBox<[u32; 1]> {
     loop {}
 }
 
 // @has 'foo/fn.delta.html'
-// @snapshot link_box_generic - '//div[@class="item-decl"]/pre[@class="rust"]/code'
+// @snapshot link_box_generic - '//pre[@class="rust item-decl"]/code'
 pub fn delta<T>() -> MyBox<[T; 1]> {
     loop {}
 }
index 77b139b644f3a8dd97b0cff39336735535d6c22e..68a11c57b5292e81cf5abda3dbccf75156cac080 100644 (file)
@@ -1,5 +1,5 @@
 pub trait Foo {
-    // @has assoc_consts/trait.Foo.html '//div[@class="item-decl"]/pre[@class="rust"]' \
+    // @has assoc_consts/trait.Foo.html '//pre[@class="rust item-decl"]' \
     //      'const FOO: usize = 13usize;'
     // @has - '//*[@id="associatedconstant.FOO"]' 'const FOO: usize'
     const FOO: usize = 12 + 1;
index ab9702a24f469834a8fba8881cd660977831b744..ad8235985bcf06e45a1a842df03f1778b6abb362 100644 (file)
@@ -10,5 +10,5 @@ pub trait AsExpression<T> {
 }
 
 // @has foo/type.AsExprOf.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'type AsExprOf<Item, Type> = <Item as AsExpression<Type>>::Expression;'
+// @has - '//pre[@class="rust item-decl"]' 'type AsExprOf<Item, Type> = <Item as AsExpression<Type>>::Expression;'
 pub type AsExprOf<Item, Type> = <Item as AsExpression<Type>>::Expression;
index de36c8ffeff0f6121e63f6ef38a24efb28d4ed8b..e74db7578d132cd6379bf3e6af46b4ca89c0f230 100644 (file)
@@ -12,8 +12,8 @@ pub trait Index<I: ?Sized> {
 }
 
 // @has assoc_types/fn.use_output.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' '-> &T::Output'
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]//a[@href="trait.Index.html#associatedtype.Output"]' 'Output'
+// @has - '//pre[@class="rust item-decl"]' '-> &T::Output'
+// @has - '//pre[@class="rust item-decl"]//a[@href="trait.Index.html#associatedtype.Output"]' 'Output'
 pub fn use_output<T: Index<usize>>(obj: &T, index: usize) -> &T::Output {
     obj.index(index)
 }
@@ -23,13 +23,13 @@ pub trait Feed {
 }
 
 // @has assoc_types/fn.use_input.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'T::Input'
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]//a[@href="trait.Feed.html#associatedtype.Input"]' 'Input'
+// @has - '//pre[@class="rust item-decl"]' 'T::Input'
+// @has - '//pre[@class="rust item-decl"]//a[@href="trait.Feed.html#associatedtype.Input"]' 'Input'
 pub fn use_input<T: Feed>(_feed: &T, _element: T::Input) { }
 
 // @has assoc_types/fn.cmp_input.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'where T::Input: PartialEq<U::Input>'
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]//a[@href="trait.Feed.html#associatedtype.Input"]' 'Input'
+// @has - '//pre[@class="rust item-decl"]' 'where T::Input: PartialEq<U::Input>'
+// @has - '//pre[@class="rust item-decl"]//a[@href="trait.Feed.html#associatedtype.Input"]' 'Input'
 pub fn cmp_input<T: Feed, U: Feed>(a: &T::Input, b: &U::Input) -> bool
     where T::Input: PartialEq<U::Input>
 {
index 8cafb5a2497a385acfaa94d5e757bc970b28d443..3db344af67439c5c877b2d532dfc538eea9623d5 100644 (file)
@@ -1,35 +1,35 @@
 // edition:2018
-// @has async_fn/fn.foo.html '//div[@class="item-decl"]/pre[@class="rust"]' 'pub async fn foo() -> Option<Foo>'
+// @has async_fn/fn.foo.html '//pre[@class="rust item-decl"]' 'pub async fn foo() -> Option<Foo>'
 pub async fn foo() -> Option<Foo> {
     None
 }
 
-// @has async_fn/fn.bar.html '//div[@class="item-decl"]/pre[@class="rust"]' 'pub async fn bar(a: i32, b: i32) -> i32'
+// @has async_fn/fn.bar.html '//pre[@class="rust item-decl"]' 'pub async fn bar(a: i32, b: i32) -> i32'
 pub async fn bar(a: i32, b: i32) -> i32 {
     0
 }
 
-// @has async_fn/fn.baz.html '//div[@class="item-decl"]/pre[@class="rust"]' 'pub async fn baz<T>(a: T) -> T'
+// @has async_fn/fn.baz.html '//pre[@class="rust item-decl"]' 'pub async fn baz<T>(a: T) -> T'
 pub async fn baz<T>(a: T) -> T {
     a
 }
 
-// @has async_fn/fn.qux.html '//div[@class="item-decl"]/pre[@class="rust"]' 'pub async unsafe fn qux() -> char'
+// @has async_fn/fn.qux.html '//pre[@class="rust item-decl"]' 'pub async unsafe fn qux() -> char'
 pub async unsafe fn qux() -> char {
     'âš '
 }
 
-// @has async_fn/fn.mut_args.html '//div[@class="item-decl"]/pre[@class="rust"]' 'pub async fn mut_args(a: usize)'
+// @has async_fn/fn.mut_args.html '//pre[@class="rust item-decl"]' 'pub async fn mut_args(a: usize)'
 pub async fn mut_args(mut a: usize) {}
 
-// @has async_fn/fn.mut_ref.html '//div[@class="item-decl"]/pre[@class="rust"]' 'pub async fn mut_ref(x: i32)'
+// @has async_fn/fn.mut_ref.html '//pre[@class="rust item-decl"]' 'pub async fn mut_ref(x: i32)'
 pub async fn mut_ref(ref mut x: i32) {}
 
 trait Bar {}
 
 impl Bar for () {}
 
-// @has async_fn/fn.quux.html '//div[@class="item-decl"]/pre[@class="rust"]' 'pub async fn quux() -> impl Bar'
+// @has async_fn/fn.quux.html '//pre[@class="rust item-decl"]' 'pub async fn quux() -> impl Bar'
 pub async fn quux() -> impl Bar {
     ()
 }
@@ -50,27 +50,27 @@ pub trait Pattern<'a> {}
 
 pub trait Trait<const N: usize> {}
 // @has async_fn/fn.const_generics.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'pub async fn const_generics<const N: usize>(_: impl Trait<N>)'
+// @has - '//pre[@class="rust item-decl"]' 'pub async fn const_generics<const N: usize>(_: impl Trait<N>)'
 pub async fn const_generics<const N: usize>(_: impl Trait<N>) {}
 
 // test that elided lifetimes are properly elided and not displayed as `'_`
 // regression test for #63037
 // @has async_fn/fn.elided.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'pub async fn elided(foo: &str) -> &str'
+// @has - '//pre[@class="rust item-decl"]' 'pub async fn elided(foo: &str) -> &str'
 pub async fn elided(foo: &str) -> &str {}
 // This should really be shown as written, but for implementation reasons it's difficult.
 // See `impl Clean for TyKind::Ref`.
 // @has async_fn/fn.user_elided.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'pub async fn user_elided(foo: &str) -> &str'
+// @has - '//pre[@class="rust item-decl"]' 'pub async fn user_elided(foo: &str) -> &str'
 pub async fn user_elided(foo: &'_ str) -> &str {}
 // @has async_fn/fn.static_trait.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'pub async fn static_trait(foo: &str) -> Box<dyn Bar>'
+// @has - '//pre[@class="rust item-decl"]' 'pub async fn static_trait(foo: &str) -> Box<dyn Bar>'
 pub async fn static_trait(foo: &str) -> Box<dyn Bar> {}
 // @has async_fn/fn.lifetime_for_trait.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "pub async fn lifetime_for_trait(foo: &str) -> Box<dyn Bar + '_>"
+// @has - '//pre[@class="rust item-decl"]' "pub async fn lifetime_for_trait(foo: &str) -> Box<dyn Bar + '_>"
 pub async fn lifetime_for_trait(foo: &str) -> Box<dyn Bar + '_> {}
 // @has async_fn/fn.elided_in_input_trait.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "pub async fn elided_in_input_trait(t: impl Pattern<'_>)"
+// @has - '//pre[@class="rust item-decl"]' "pub async fn elided_in_input_trait(t: impl Pattern<'_>)"
 pub async fn elided_in_input_trait(t: impl Pattern<'_>) {}
 
 struct AsyncFdReadyGuard<'a, T> { x: &'a T }
@@ -88,8 +88,8 @@ pub async fn mut_self(&mut self) {}
 
 // test named lifetimes, just in case
 // @has async_fn/fn.named.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "pub async fn named<'a, 'b>(foo: &'a str) -> &'b str"
+// @has - '//pre[@class="rust item-decl"]' "pub async fn named<'a, 'b>(foo: &'a str) -> &'b str"
 pub async fn named<'a, 'b>(foo: &'a str) -> &'b str {}
 // @has async_fn/fn.named_trait.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "pub async fn named_trait<'a, 'b>(foo: impl Pattern<'a>) -> impl Pattern<'b>"
+// @has - '//pre[@class="rust item-decl"]' "pub async fn named_trait<'a, 'b>(foo: impl Pattern<'a>) -> impl Pattern<'b>"
 pub async fn named_trait<'a, 'b>(foo: impl Pattern<'a>) -> impl Pattern<'b> {}
index 36e10923c85354e44ef7658f031ed5e5b49fd090..a652fda1604cdbc6ea6fac045925a4c8ca5da0de 100644 (file)
@@ -1,7 +1,7 @@
 #![crate_name = "foo"]
 
 // @has 'foo/fn.f.html'
-// @has - //*[@'class="item-decl"]' '#[export_name = "f"] pub fn f()'
+// @has - //*[@'class="rust item-decl"]' '#[export_name = "f"] pub fn f()'
 #[export_name = "\
 f"]
 pub fn f() {}
index 70e2e5c29508c211b28246df05e984b8fc2167b4..86333c7534a3f0e61be90c62aa9f52ec6a7d64dd 100644 (file)
@@ -1,13 +1,13 @@
 #![crate_name = "foo"]
 
-// @has foo/fn.f.html '//div[@class="item-decl"]/pre[@class="rust"]' '#[no_mangle]'
+// @has foo/fn.f.html '//pre[@class="rust item-decl"]' '#[no_mangle]'
 #[no_mangle]
 pub extern "C" fn f() {}
 
-// @has foo/fn.g.html '//div[@class="item-decl"]/pre[@class="rust"]' '#[export_name = "bar"]'
+// @has foo/fn.g.html '//pre[@class="rust item-decl"]' '#[export_name = "bar"]'
 #[export_name = "bar"]
 pub extern "C" fn g() {}
 
-// @has foo/struct.Repr.html '//div[@class="item-decl"]' '#[repr(C, align(8))]'
+// @has foo/struct.Repr.html '//pre[@class="rust item-decl"]' '#[repr(C, align(8))]'
 #[repr(C, align(8))]
 pub struct Repr;
index 5143968bbd4390df0bab4c66cb4eb1f611eeb7c6..5db4fe053af6e00d7ba35e7002fd0dbe084645f1 100644 (file)
@@ -1,5 +1,5 @@
 // @has issue_85454/trait.FromResidual.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'pub trait FromResidual<R = <Self as Try>::Residual> { fn from_residual(residual: R) -> Self; }'
+// @has - '//pre[@class="rust item-decl"]' 'pub trait FromResidual<R = <Self as Try>::Residual> { fn from_residual(residual: R) -> Self; }'
 pub trait FromResidual<R = <Self as Try>::Residual> {
     fn from_residual(residual: R) -> Self;
 }
index 18863abaeaccd3dd70c10c493639126b677f5848..f661618568121c2d4d611b028e00e89132bf6f1e 100644 (file)
@@ -1,7 +1,7 @@
 #![crate_name = "foo"]
 
 // @has foo/fn.bar.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'pub const fn bar() -> '
+// @has - '//pre[@class="rust item-decl"]' 'pub const fn bar() -> '
 /// foo
 pub const fn bar() -> usize {
     2
index b5226ad3f78bd6e0199ce2a4629b2207e406fbfa..195e47bc8ba80aff1557b80618c1e7415e1c5b7a 100644 (file)
@@ -2,7 +2,7 @@
 
 use std::ops::Add;
 
-// @has foo/struct.Simd.html '//div[@class="item-decl"]/pre[@class="rust"]' 'pub struct Simd<T, const WIDTH: usize>'
+// @has foo/struct.Simd.html '//pre[@class="rust item-decl"]' 'pub struct Simd<T, const WIDTH: usize>'
 pub struct Simd<T, const WIDTH: usize> {
     inner: T,
 }
index acc3b853e5679c577696ffb87ff3578e00791293..f781c6a62f24b4b397e6594e9b8073880052abe4 100644 (file)
@@ -1,5 +1,5 @@
 #![crate_name = "foo"]
 
-// @has foo/struct.Foo.html '//div[@class="item-decl"]/pre[@class="rust"]' \
+// @has foo/struct.Foo.html '//pre[@class="rust item-decl"]' \
 //      'pub struct Foo<const M: usize = 10, const N: usize = M, T = i32>(_);'
 pub struct Foo<const M: usize = 10, const N: usize = M, T = i32>(T);
index 543332d2c320b8922d18135ee7e27cfe01d25606..ade70bbe80d923a1b5f02467eecd13e6e4b5916e 100644 (file)
@@ -3,21 +3,21 @@
 #![crate_name = "foo"]
 
 extern crate extern_crate;
-// @has foo/fn.extern_fn.html '//div[@class="item-decl"]/pre[@class="rust"]' \
+// @has foo/fn.extern_fn.html '//pre[@class="rust item-decl"]' \
 //      'pub fn extern_fn<const N: usize>() -> impl Iterator<Item = [u8; N]>'
 pub use extern_crate::extern_fn;
-// @has foo/struct.ExternTy.html '//div[@class="item-decl"]/pre[@class="rust"]' \
+// @has foo/struct.ExternTy.html '//pre[@class="rust item-decl"]' \
 //      'pub struct ExternTy<const N: usize> {'
 pub use extern_crate::ExternTy;
-// @has foo/type.TyAlias.html '//div[@class="item-decl"]/pre[@class="rust"]' \
+// @has foo/type.TyAlias.html '//pre[@class="rust item-decl"]' \
 //      'type TyAlias<const N: usize> = ExternTy<N>;'
 pub use extern_crate::TyAlias;
-// @has foo/trait.WTrait.html '//div[@class="item-decl"]/pre[@class="rust"]' \
+// @has foo/trait.WTrait.html '//pre[@class="rust item-decl"]' \
 //      'pub trait WTrait<const N: usize, const M: usize>'
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'fn hey<const P: usize>() -> usize'
+// @has - '//pre[@class="rust item-decl"]' 'fn hey<const P: usize>() -> usize'
 pub use extern_crate::WTrait;
 
-// @has foo/trait.Trait.html '//div[@class="item-decl"]/pre[@class="rust"]' \
+// @has foo/trait.Trait.html '//pre[@class="rust item-decl"]' \
 //      'pub trait Trait<const N: usize>'
 // @has - '//*[@id="impl-Trait%3C1%3E-for-u8"]//h3[@class="code-header"]' 'impl Trait<1> for u8'
 // @has - '//*[@id="impl-Trait%3C2%3E-for-u8"]//h3[@class="code-header"]' 'impl Trait<2> for u8'
@@ -30,10 +30,10 @@ impl Trait<2> for u8 {}
 impl Trait<{1 + 2}> for u8 {}
 impl<const N: usize> Trait<N> for [u8; N] {}
 
-// @has foo/struct.Foo.html '//div[@class="item-decl"]/pre[@class="rust"]' \
+// @has foo/struct.Foo.html '//pre[@class="rust item-decl"]' \
 //      'pub struct Foo<const N: usize>where u8: Trait<N>'
 pub struct Foo<const N: usize> where u8: Trait<N>;
-// @has foo/struct.Bar.html '//div[@class="item-decl"]/pre[@class="rust"]' 'pub struct Bar<T, const N: usize>(_)'
+// @has foo/struct.Bar.html '//pre[@class="rust item-decl"]' 'pub struct Bar<T, const N: usize>(_)'
 pub struct Bar<T, const N: usize>([T; N]);
 
 // @has foo/struct.Foo.html '//*[@id="impl-Foo%3CM%3E"]/h3[@class="code-header"]' 'impl<const M: usize> Foo<M>where u8: Trait<M>'
@@ -56,32 +56,32 @@ pub fn hey<const N: usize>(&self) -> Foo<N> where u8: Trait<N> {
     }
 }
 
-// @has foo/fn.test.html '//div[@class="item-decl"]/pre[@class="rust"]' \
+// @has foo/fn.test.html '//pre[@class="rust item-decl"]' \
 //      'pub fn test<const N: usize>() -> impl Trait<N>where u8: Trait<N>'
 pub fn test<const N: usize>() -> impl Trait<N> where u8: Trait<N> {
     2u8
 }
 
-// @has foo/fn.a_sink.html '//div[@class="item-decl"]/pre[@class="rust"]' \
+// @has foo/fn.a_sink.html '//pre[@class="rust item-decl"]' \
 //      'pub async fn a_sink<const N: usize>(v: [u8; N]) -> impl Trait<N>'
 pub async fn a_sink<const N: usize>(v: [u8; N]) -> impl Trait<N> {
     v
 }
 
-// @has foo/fn.b_sink.html '//div[@class="item-decl"]/pre[@class="rust"]' \
+// @has foo/fn.b_sink.html '//pre[@class="rust item-decl"]' \
 //      'pub async fn b_sink<const N: usize>(_: impl Trait<N>)'
 pub async fn b_sink<const N: usize>(_: impl Trait<N>) {}
 
-// @has foo/fn.concrete.html '//div[@class="item-decl"]/pre[@class="rust"]' \
+// @has foo/fn.concrete.html '//pre[@class="rust item-decl"]' \
 //      'pub fn concrete() -> [u8; 22]'
 pub fn concrete() -> [u8; 3 + std::mem::size_of::<u64>() << 1] {
     Default::default()
 }
 
-// @has foo/type.Faz.html '//div[@class="item-decl"]/pre[@class="rust"]' \
+// @has foo/type.Faz.html '//pre[@class="rust item-decl"]' \
 //      'type Faz<const N: usize> = [u8; N];'
 pub type Faz<const N: usize> = [u8; N];
-// @has foo/type.Fiz.html '//div[@class="item-decl"]/pre[@class="rust"]' \
+// @has foo/type.Fiz.html '//pre[@class="rust item-decl"]' \
 //      'type Fiz<const N: usize> = [[u8; N]; 48];'
 pub type Fiz<const N: usize> = [[u8; N]; 3 << 4];
 
@@ -91,7 +91,7 @@ macro_rules! define_me {
     }
 }
 
-// @has foo/struct.Foz.html '//div[@class="item-decl"]/pre[@class="rust"]' \
+// @has foo/struct.Foz.html '//pre[@class="rust item-decl"]' \
 //      'pub struct Foz<const N: usize>(_);'
 define_me!(Foz<N>);
 
@@ -103,13 +103,13 @@ trait Q {
     const ASSOC: usize = N;
 }
 
-// @has foo/fn.q_user.html '//div[@class="item-decl"]/pre[@class="rust"]' \
+// @has foo/fn.q_user.html '//pre[@class="rust item-decl"]' \
 //      'pub fn q_user() -> [u8; 13]'
 pub fn q_user() -> [u8; <[u8; 13] as Q>::ASSOC] {
     [0; <[u8; 13] as Q>::ASSOC]
 }
 
-// @has foo/union.Union.html '//div[@class="item-decl"]/pre[@class="rust"]' \
+// @has foo/union.Union.html '//pre[@class="rust item-decl"]' \
 //      'pub union Union<const N: usize>'
 pub union Union<const N: usize> {
     // @has - //pre "pub arr: [u8; N]"
@@ -118,7 +118,7 @@ pub union Union<const N: usize> {
     pub another_arr: [(); N],
 }
 
-// @has foo/enum.Enum.html '//div[@class="item-decl"]/pre[@class="rust"]' \
+// @has foo/enum.Enum.html '//pre[@class="rust item-decl"]' \
 //      'pub enum Enum<const N: usize>'
 pub enum Enum<const N: usize> {
     // @has - //pre "Variant([u8; N])"
index 726fb8f0c341681af2ca5df0b666ee9dc6643c3e..91866b7d890c77f34d8d78544694d831e496da61 100644 (file)
@@ -8,7 +8,7 @@ pub enum Order {
     Unsorted,
 }
 
-// @has foo/struct.VSet.html '//div[@class="item-decl"]/pre[@class="rust"]' 'pub struct VSet<T, const ORDER: Order>'
+// @has foo/struct.VSet.html '//pre[@class="rust item-decl"]' 'pub struct VSet<T, const ORDER: Order>'
 // @has foo/struct.VSet.html '//*[@id="impl-Send-for-VSet%3CT%2C%20ORDER%3E"]/h3[@class="code-header"]' 'impl<T, const ORDER: Order> Send for VSet<T, ORDER>'
 // @has foo/struct.VSet.html '//*[@id="impl-Sync-for-VSet%3CT%2C%20ORDER%3E"]/h3[@class="code-header"]' 'impl<T, const ORDER: Order> Sync for VSet<T, ORDER>'
 pub struct VSet<T, const ORDER: Order> {
index c53cf6dcd0570b4f0717ca79062cb2f35333ee74..e23b3006da6cda335b7670fd964860c5908d030f 100644 (file)
@@ -2,6 +2,6 @@
 #![feature(generic_const_exprs)]
 #![allow(incomplete_features)]
 // make sure that `ConstEvaluatable` predicates dont cause rustdoc to ICE #77647
-// @has foo/struct.Ice.html '//div[@class="item-decl"]/pre[@class="rust"]' \
+// @has foo/struct.Ice.html '//pre[@class="rust item-decl"]' \
 //      'pub struct Ice<const N: usize>;'
 pub struct Ice<const N: usize> where [(); N + 1]:;
index 72473a112440ce28414f01b479f18dc3e4a789db..4b93e72d27370ecfd3ce8dc5cc886cb40c914beb 100644 (file)
@@ -1,4 +1,4 @@
 #![crate_name = "foo"]
 
-// @has foo/type.CellIndex.html '//div[@class="item-decl"]/pre[@class="rust"]' 'type CellIndex<const D: usize> = [i64; D];'
+// @has foo/type.CellIndex.html '//pre[@class="rust item-decl"]' 'type CellIndex<const D: usize> = [i64; D];'
 pub type CellIndex<const D: usize> = [i64; D];
index 42f6ac7923bf2e12b6a95944a29a69c824ce881c..6d2c6cce29c294f29bc7455912eca792b1a941d3 100644 (file)
@@ -6,20 +6,20 @@
 
 extern "rust-intrinsic" {
     // @has 'foo/fn.transmute.html'
-    // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'pub const unsafe extern "rust-intrinsic" fn transmute<T, U>(_: T) -> U'
+    // @has - '//pre[@class="rust item-decl"]' 'pub const unsafe extern "rust-intrinsic" fn transmute<T, U>(_: T) -> U'
     #[stable(since="1.0.0", feature="rust1")]
     #[rustc_const_stable(feature = "const_transmute", since = "1.56.0")]
     pub fn transmute<T, U>(_: T) -> U;
 
     // @has 'foo/fn.unreachable.html'
-    // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'pub unsafe extern "rust-intrinsic" fn unreachable() -> !'
+    // @has - '//pre[@class="rust item-decl"]' 'pub unsafe extern "rust-intrinsic" fn unreachable() -> !'
     #[stable(since="1.0.0", feature="rust1")]
     pub fn unreachable() -> !;
 }
 
 extern "C" {
     // @has 'foo/fn.needs_drop.html'
-    // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'pub unsafe extern "C" fn needs_drop() -> !'
+    // @has - '//pre[@class="rust item-decl"]' 'pub unsafe extern "C" fn needs_drop() -> !'
     #[stable(since="1.0.0", feature="rust1")]
     pub fn needs_drop() -> !;
 }
index 8d95f0de9d098809873d8299e430c65a7e07ea25..a7548ad2cc4671ae9433e032dadc15ed3816fc5a 100644 (file)
@@ -1,9 +1,9 @@
 #![crate_name = "foo"]
 
 // @has 'foo/constant.HOUR_IN_SECONDS.html'
-// @has - '//*[@class="item-decl"]//code' 'pub const HOUR_IN_SECONDS: u64 = _; // 3_600u64'
+// @has - '//*[@class="rust item-decl"]//code' 'pub const HOUR_IN_SECONDS: u64 = _; // 3_600u64'
 pub const HOUR_IN_SECONDS: u64 = 60 * 60;
 
 // @has 'foo/constant.NEGATIVE.html'
-// @has - '//*[@class="item-decl"]//code' 'pub const NEGATIVE: i64 = _; // -3_600i64'
+// @has - '//*[@class="rust item-decl"]//code' 'pub const NEGATIVE: i64 = _; // -3_600i64'
 pub const NEGATIVE: i64 = -60 * 60;
index e47edc1321851744137066320b05838c0084ac67..d2a12435d8f2758d4c01056a2c98b66d009114a4 100644 (file)
@@ -7,7 +7,7 @@
 // @has 'foo/trait.Write.html'
 
 pub trait Write {
-    // @snapshot 'declaration' - '//*[@class="item-decl"]//code'
+    // @snapshot 'declaration' - '//*[@class="rust item-decl"]//code'
     fn poll_write(
         self: Option<String>,
         cx: &mut Option<String>,
diff --git a/tests/rustdoc/document-item-with-associated-const-in-where-clause.rs b/tests/rustdoc/document-item-with-associated-const-in-where-clause.rs
new file mode 100644 (file)
index 0000000..c9408ef
--- /dev/null
@@ -0,0 +1,17 @@
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+pub trait Enumerable {
+    const N: usize;
+}
+
+#[derive(Clone)]
+pub struct SymmetricGroup<S>
+where
+    S: Enumerable,
+    [(); S::N]: Sized,
+{
+    _phantom: std::marker::PhantomData<S>,
+}
+
+fn main() {}
index 96c64ac4e0211b2c09873e337208f6913899e1b9..359ca64ee8d6777a96b364dd1987d64a0cf1eae5 100644 (file)
@@ -1,5 +1,5 @@
 #![crate_name = "foo"]
 
 // @has foo/fn.f.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'pub fn f(callback: fn(len: usize, foo: u32))'
+// @has - '//pre[@class="rust item-decl"]' 'pub fn f(callback: fn(len: usize, foo: u32))'
 pub fn f(callback: fn(len: usize, foo: u32)) {}
index 406157ce26c8093e4de47be334f9d4bf02a03d05..d368db909fa013267ddbde68946532d1202f4b11 100644 (file)
@@ -63,7 +63,7 @@ impl<const S: Struct, St: Stage + ?Sized> Helper<S> for St {
 // this test as long as one can ensure that private fields are not leaked!
 //
 // @has hide_complex_unevaluated_const_arguments/trait.Sub.html \
-//      '//div[@class="item-decl"]/pre[@class="rust"]' \
+//      '//pre[@class="rust item-decl"]' \
 //      'pub trait Sub: Sup<{ _ }, { _ }> { }'
 pub trait Sub: Sup<{ 90 * 20 * 4 }, { Struct { private: () } }> {}
 
index a4ca928f3331b94068dd7cd89d75dc1f8d8d9cc8..e6468316f583b46b7f2dba066807c94b9dd89f62 100644 (file)
@@ -4,6 +4,6 @@
 extern crate inline_default_methods;
 
 // @has inline_default_methods/trait.Foo.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'fn bar(&self);'
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'fn foo(&mut self) { ... }'
+// @has - '//pre[@class="rust item-decl"]' 'fn bar(&self);'
+// @has - '//pre[@class="rust item-decl"]' 'fn foo(&mut self) { ... }'
 pub use inline_default_methods::Foo;
index 0da8bfc3a9ae368460d0c44fb3307b30c6515170..649d98f71396a24f0200d7ca7ee6c5eb7f4b6f5b 100644 (file)
@@ -4,28 +4,28 @@
 // edition:2021
 
 // @has user/type.Ty0.html
-// @has - '//*[@class="item-decl"]//code' "dyn for<'any> FnOnce(&'any str) -> bool + 'static"
+// @has - '//*[@class="rust item-decl"]//code' "dyn for<'any> FnOnce(&'any str) -> bool + 'static"
 // FIXME(fmease): Hide default lifetime bound `'static`
 pub use dyn_trait::Ty0;
 
 // @has user/type.Ty1.html
-// @has - '//*[@class="item-decl"]//code' "dyn Display + 'obj"
+// @has - '//*[@class="rust item-decl"]//code' "dyn Display + 'obj"
 pub use dyn_trait::Ty1;
 
 // @has user/type.Ty2.html
-// @has - '//*[@class="item-decl"]//code' "dyn for<'a, 'r> Container<'r, Item<'a, 'static> = ()>"
+// @has - '//*[@class="rust item-decl"]//code' "dyn for<'a, 'r> Container<'r, Item<'a, 'static> = ()>"
 pub use dyn_trait::Ty2;
 
 // @has user/type.Ty3.html
-// @has - '//*[@class="item-decl"]//code' "&'s (dyn ToString + 's)"
+// @has - '//*[@class="rust item-decl"]//code' "&'s (dyn ToString + 's)"
 // FIXME(fmease): Hide default lifetime bound, render "&'s dyn ToString"
 pub use dyn_trait::Ty3;
 
 // @has user/fn.func0.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "func0(_: &dyn Fn())"
+// @has - '//pre[@class="rust item-decl"]' "func0(_: &dyn Fn())"
 // FIXME(fmease): Show placeholder-lifetime bound, render "func0(_: &(dyn Fn() + '_))"
 pub use dyn_trait::func0;
 
 // @has user/fn.func1.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "func1<'func>(_: &(dyn Fn() + 'func))"
+// @has - '//pre[@class="rust item-decl"]' "func1<'func>(_: &(dyn Fn() + 'func))"
 pub use dyn_trait::func1;
index e8587209b61655ea358c161a77580a1c4a2e9d22..7d810ab4813720120026e9f21a4c8fd0f15d0561 100644 (file)
@@ -4,37 +4,37 @@
 extern crate impl_trait_aux;
 
 // @has impl_trait/fn.func.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "pub fn func<'a>(_x: impl Clone + Into<Vec<u8, Global>> + 'a)"
-// @!has - '//div[@class="item-decl"]/pre[@class="rust"]' 'where'
+// @has - '//pre[@class="rust item-decl"]' "pub fn func<'a>(_x: impl Clone + Into<Vec<u8, Global>> + 'a)"
+// @!has - '//pre[@class="rust item-decl"]' 'where'
 pub use impl_trait_aux::func;
 
 // @has impl_trait/fn.func2.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "func2<T>("
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "_x: impl Deref<Target = Option<T>> + Iterator<Item = T>,"
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "_y: impl Iterator<Item = u8>)"
-// @!has - '//div[@class="item-decl"]/pre[@class="rust"]' 'where'
+// @has - '//pre[@class="rust item-decl"]' "func2<T>("
+// @has - '//pre[@class="rust item-decl"]' "_x: impl Deref<Target = Option<T>> + Iterator<Item = T>,"
+// @has - '//pre[@class="rust item-decl"]' "_y: impl Iterator<Item = u8>)"
+// @!has - '//pre[@class="rust item-decl"]' 'where'
 pub use impl_trait_aux::func2;
 
 // @has impl_trait/fn.func3.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "func3("
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "_x: impl Iterator<Item = impl Iterator<Item = u8>> + Clone)"
-// @!has - '//div[@class="item-decl"]/pre[@class="rust"]' 'where'
+// @has - '//pre[@class="rust item-decl"]' "func3("
+// @has - '//pre[@class="rust item-decl"]' "_x: impl Iterator<Item = impl Iterator<Item = u8>> + Clone)"
+// @!has - '//pre[@class="rust item-decl"]' 'where'
 pub use impl_trait_aux::func3;
 
 // @has impl_trait/fn.func4.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "func4<T>("
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "T: Iterator<Item = impl Clone>,"
+// @has - '//pre[@class="rust item-decl"]' "func4<T>("
+// @has - '//pre[@class="rust item-decl"]' "T: Iterator<Item = impl Clone>,"
 pub use impl_trait_aux::func4;
 
 // @has impl_trait/fn.func5.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "func5("
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "_f: impl for<'any> Fn(&'any str, &'any str) -> bool + for<'r> Other<T<'r> = ()>,"
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "_a: impl for<'alpha, 'beta> Auxiliary<'alpha, Item<'beta> = fn(_: &'beta ())>"
-// @!has - '//div[@class="item-decl"]/pre[@class="rust"]' 'where'
+// @has - '//pre[@class="rust item-decl"]' "func5("
+// @has - '//pre[@class="rust item-decl"]' "_f: impl for<'any> Fn(&'any str, &'any str) -> bool + for<'r> Other<T<'r> = ()>,"
+// @has - '//pre[@class="rust item-decl"]' "_a: impl for<'alpha, 'beta> Auxiliary<'alpha, Item<'beta> = fn(_: &'beta ())>"
+// @!has - '//pre[@class="rust item-decl"]' 'where'
 pub use impl_trait_aux::func5;
 
 // @has impl_trait/fn.async_fn.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "pub async fn async_fn()"
+// @has - '//pre[@class="rust item-decl"]' "pub async fn async_fn()"
 pub use impl_trait_aux::async_fn;
 
 // @has impl_trait/struct.Foo.html
index d11b6955f3c0f796d9fd46281404f909c2bc156c..751a32385e812d30e6ab5142e5763fed659c2b7d 100644 (file)
@@ -5,7 +5,7 @@
 // edition: 2021
 
 // @has usr/trait.U.html
-// @has - '//*[@class="item-decl"]' "pub trait U {"
+// @has - '//*[@class="rust item-decl"]' "pub trait U {"
 // @has - '//*[@id="method.modified"]' \
 // "fn modified(self) -> Self\
 // where \
@@ -14,5 +14,5 @@
 pub use issue_24183::U;
 
 // @has usr/trait.S.html
-// @has - '//*[@class="item-decl"]' 'pub trait S: Sized {'
+// @has - '//*[@class="rust item-decl"]' 'pub trait S: Sized {'
 pub use issue_24183::S;
index a774b0ca7cd7a4ca54324b86e49f17406b641a18..b2ee9c26014b3d90e089f579d0609ad398bbb161 100644 (file)
@@ -13,7 +13,7 @@ pub trait Trait {
 }
 
 // @has issue_20646/fn.fun.html \
-//      '//div[@class="item-decl"]/pre[@class="rust"]' 'where T: Trait<Output = i32>'
+//      '//pre[@class="rust item-decl"]' 'where T: Trait<Output = i32>'
 pub fn fun<T>(_: T) where T: Trait<Output=i32> {}
 
 pub mod reexport {
@@ -21,6 +21,6 @@ pub mod reexport {
     //      '//*[@id="associatedtype.Output"]' \
     //      'type Output'
     // @has issue_20646/reexport/fn.fun.html \
-    //      '//div[@class="item-decl"]/pre[@class="rust"]' 'where T: Trait<Output = i32>'
+    //      '//pre[@class="rust item-decl"]' 'where T: Trait<Output = i32>'
     pub use issue_20646::{Trait, fun};
 }
index 026b4f5acc912d7b2eb6889e81d2f20341e1814b..c1aa9617b2e25ea5e1fc492a439f38fb5e9f710c 100644 (file)
@@ -5,18 +5,18 @@
 
 // @has issue_20727_2/trait.Add.html
 pub trait Add<RHS = Self> {
-    // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'trait Add<RHS = Self> {'
-    // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'type Output;'
+    // @has - '//pre[@class="rust item-decl"]' 'trait Add<RHS = Self> {'
+    // @has - '//pre[@class="rust item-decl"]' 'type Output;'
     type Output;
 
-    // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'fn add(self, rhs: RHS) -> Self::Output;'
+    // @has - '//pre[@class="rust item-decl"]' 'fn add(self, rhs: RHS) -> Self::Output;'
     fn add(self, rhs: RHS) -> Self::Output;
 }
 
 // @has issue_20727_2/reexport/trait.Add.html
 pub mod reexport {
-    // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'trait Add<RHS = Self> {'
-    // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'type Output;'
-    // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'fn add(self, rhs: RHS) -> Self::Output;'
+    // @has - '//pre[@class="rust item-decl"]' 'trait Add<RHS = Self> {'
+    // @has - '//pre[@class="rust item-decl"]' 'type Output;'
+    // @has - '//pre[@class="rust item-decl"]' 'fn add(self, rhs: RHS) -> Self::Output;'
     pub use issue_20727::Add;
 }
index 741ce8023d7e78bfb58fae0d34cd6e7b27baf512..2f9d91fc5f724188d8941fbf3df52866ef3f26a8 100644 (file)
@@ -7,18 +7,18 @@ pub trait Bar {}
 
 // @has issue_20727_3/trait.Deref2.html
 pub trait Deref2 {
-    // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'trait Deref2 {'
-    // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'type Target: Bar;'
+    // @has - '//pre[@class="rust item-decl"]' 'trait Deref2 {'
+    // @has - '//pre[@class="rust item-decl"]' 'type Target: Bar;'
     type Target: Bar;
 
-    // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'fn deref(&self) -> Self::Target;'
+    // @has - '//pre[@class="rust item-decl"]' 'fn deref(&self) -> Self::Target;'
     fn deref(&self) -> Self::Target;
 }
 
 // @has issue_20727_3/reexport/trait.Deref2.html
 pub mod reexport {
-    // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'trait Deref2 {'
-    // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'type Target: Bar;'
-    // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'fn deref(&self) -> Self::Target;'
+    // @has - '//pre[@class="rust item-decl"]' 'trait Deref2 {'
+    // @has - '//pre[@class="rust item-decl"]' 'type Target: Bar;'
+    // @has - '//pre[@class="rust item-decl"]' 'fn deref(&self) -> Self::Target;'
     pub use issue_20727::Deref2;
 }
index b8fac4da6eadf8288b91c9370d730291873cbed7..ec9f18fc3feb848124d9ec3fb3f0bd6907e2850e 100644 (file)
@@ -5,36 +5,36 @@
 
 // @has issue_20727_4/trait.Index.html
 pub trait Index<Idx: ?Sized> {
-    // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'trait Index<Idx: ?Sized> {'
-    // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'type Output: ?Sized'
+    // @has - '//pre[@class="rust item-decl"]' 'trait Index<Idx: ?Sized> {'
+    // @has - '//pre[@class="rust item-decl"]' 'type Output: ?Sized'
     type Output: ?Sized;
 
-    // @has - '//div[@class="item-decl"]/pre[@class="rust"]' \
+    // @has - '//pre[@class="rust item-decl"]' \
     //        'fn index(&self, index: Idx) -> &Self::Output'
     fn index(&self, index: Idx) -> &Self::Output;
 }
 
 // @has issue_20727_4/trait.IndexMut.html
 pub trait IndexMut<Idx: ?Sized>: Index<Idx> {
-    // @has - '//div[@class="item-decl"]/pre[@class="rust"]' \
+    // @has - '//pre[@class="rust item-decl"]' \
     //        'trait IndexMut<Idx: ?Sized>: Index<Idx> {'
-    // @has - '//div[@class="item-decl"]/pre[@class="rust"]' \
+    // @has - '//pre[@class="rust item-decl"]' \
     //        'fn index_mut(&mut self, index: Idx) -> &mut Self::Output;'
     fn index_mut(&mut self, index: Idx) -> &mut Self::Output;
 }
 
 pub mod reexport {
     // @has issue_20727_4/reexport/trait.Index.html
-    // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'trait Index<Idx>where Idx: ?Sized,{'
-    // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'type Output: ?Sized'
-    // @has - '//div[@class="item-decl"]/pre[@class="rust"]' \
+    // @has - '//pre[@class="rust item-decl"]' 'trait Index<Idx>where Idx: ?Sized,{'
+    // @has - '//pre[@class="rust item-decl"]' 'type Output: ?Sized'
+    // @has - '//pre[@class="rust item-decl"]' \
     //        'fn index(&self, index: Idx) -> &Self::Output'
     pub use issue_20727::Index;
 
     // @has issue_20727_4/reexport/trait.IndexMut.html
-    // @has - '//div[@class="item-decl"]/pre[@class="rust"]' \
+    // @has - '//pre[@class="rust item-decl"]' \
     //        'trait IndexMut<Idx>: Index<Idx>where Idx: ?Sized,{'
-    // @has - '//div[@class="item-decl"]/pre[@class="rust"]' \
+    // @has - '//pre[@class="rust item-decl"]' \
     //        'fn index_mut(&mut self, index: Idx) -> &mut Self::Output;'
     pub use issue_20727::IndexMut;
 }
index df334821cccc97868e71746592ff6e100c7bb6e6..266848beef93d9aa531e2e5ff51b7740a75fa2f9 100644 (file)
@@ -5,20 +5,20 @@
 
 // @has issue_20727/trait.Deref.html
 pub trait Deref {
-    // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'trait Deref {'
-    // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'type Target: ?Sized;'
+    // @has - '//pre[@class="rust item-decl"]' 'trait Deref {'
+    // @has - '//pre[@class="rust item-decl"]' 'type Target: ?Sized;'
     type Target: ?Sized;
 
-    // @has - '//div[@class="item-decl"]/pre[@class="rust"]' \
+    // @has - '//pre[@class="rust item-decl"]' \
     //        "fn deref<'a>(&'a self) -> &'a Self::Target;"
     fn deref<'a>(&'a self) -> &'a Self::Target;
 }
 
 // @has issue_20727/reexport/trait.Deref.html
 pub mod reexport {
-    // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'trait Deref {'
-    // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'type Target: ?Sized;'
-    // @has - '//div[@class="item-decl"]/pre[@class="rust"]' \
+    // @has - '//pre[@class="rust item-decl"]' 'trait Deref {'
+    // @has - '//pre[@class="rust item-decl"]' 'type Target: ?Sized;'
+    // @has - '//pre[@class="rust item-decl"]' \
     //      "fn deref<'a>(&'a self) -> &'a Self::Target;"
     pub use issue_20727::Deref;
 }
index 19e626ba132356d69889be10f1fe80a42849824e..de6cc78707c6d10bd76b69f34172aad532ea0f9d 100644 (file)
@@ -1,19 +1,19 @@
 extern "C" {
     // @has issue_22038/fn.foo1.html \
-    //      '//div[@class="item-decl"]/pre[@class="rust"]' 'pub unsafe extern "C" fn foo1()'
+    //      '//pre[@class="rust item-decl"]' 'pub unsafe extern "C" fn foo1()'
     pub fn foo1();
 }
 
 extern "system" {
     // @has issue_22038/fn.foo2.html \
-    //      '//div[@class="item-decl"]/pre[@class="rust"]' 'pub unsafe extern "system" fn foo2()'
+    //      '//pre[@class="rust item-decl"]' 'pub unsafe extern "system" fn foo2()'
     pub fn foo2();
 }
 
 // @has issue_22038/fn.bar.html \
-//      '//div[@class="item-decl"]/pre[@class="rust"]' 'pub extern "C" fn bar()'
+//      '//pre[@class="rust item-decl"]' 'pub extern "C" fn bar()'
 pub extern "C" fn bar() {}
 
 // @has issue_22038/fn.baz.html \
-//      '//div[@class="item-decl"]/pre[@class="rust"]' 'pub extern "system" fn baz()'
+//      '//pre[@class="rust item-decl"]' 'pub extern "system" fn baz()'
 pub extern "system" fn baz() {}
index 7af00c778361d3042300ba9b8a2ae059aa6fcf07..a316f3ad99bcf891b7dca835a3f0eefe2520f091 100644 (file)
@@ -6,17 +6,17 @@ macro_rules! make {
         pub struct S;
 
         // @has issue_33302/constant.CST.html \
-        //        '//div[@class="item-decl"]/pre[@class="rust"]' 'pub const CST: i32'
+        //        '//pre[@class="rust item-decl"]' 'pub const CST: i32'
         pub const CST: i32 = ($n * $n);
         // @has issue_33302/static.ST.html \
-        //        '//div[@class="item-decl"]/pre[@class="rust"]' 'pub static ST: i32'
+        //        '//pre[@class="rust item-decl"]' 'pub static ST: i32'
         pub static ST: i32 = ($n * $n);
 
         pub trait T<X> {
             fn ignore(_: &X) {}
             const C: X;
             // @has issue_33302/trait.T.html \
-            //        '//div[@class="item-decl"]/pre[@class="rust"]' 'const D: i32'
+            //        '//pre[@class="rust item-decl"]' 'const D: i32'
             // @has - '//*[@id="associatedconstant.D"]' 'const D: i32'
             const D: i32 = ($n * $n);
         }
index 74fc22b31dc0c84cd6956e52bb6aff5173bfd85e..2d410a5974afa46d40bc363afd2d94a780cd5971 100644 (file)
@@ -5,7 +5,7 @@
 extern crate issue_85454;
 
 // @has foo/trait.FromResidual.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'pub trait FromResidual<R = <Self as Try>::Residual> { fn from_residual(residual: R) -> Self; }'
+// @has - '//pre[@class="rust item-decl"]' 'pub trait FromResidual<R = <Self as Try>::Residual> { fn from_residual(residual: R) -> Self; }'
 pub trait FromResidual<R = <Self as Try>::Residual> {
     fn from_residual(residual: R) -> Self;
 }
@@ -24,6 +24,6 @@ pub enum ControlFlow<B, C = ()> {
 
 pub mod reexport {
     // @has foo/reexport/trait.FromResidual.html
-    // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'pub trait FromResidual<R = <Self as Try>::Residual> { fn from_residual(residual: R) -> Self; }'
+    // @has - '//pre[@class="rust item-decl"]' 'pub trait FromResidual<R = <Self as Try>::Residual> { fn from_residual(residual: R) -> Self; }'
     pub use issue_85454::*;
 }
index 884b63ac97ffceee0fc6f6033ed96b742372fcbf..5d5aee1fe1df67cd66cabca132645ac7febeda8c 100644 (file)
@@ -8,8 +8,8 @@
 
 extern crate issue_98697_reexport_with_anonymous_lifetime;
 
-// @has issue_98697/fn.repro.html '//div[@class="item-decl"]/pre[@class="rust"]/code' 'fn repro<F>()where F: Fn(&str)'
-// @!has issue_98697/fn.repro.html '//div[@class="item-decl"]/pre[@class="rust"]/code' 'for<'
+// @has issue_98697/fn.repro.html '//pre[@class="rust item-decl"]/code' 'fn repro<F>()where F: Fn(&str)'
+// @!has issue_98697/fn.repro.html '//pre[@class="rust item-decl"]/code' 'for<'
 pub use issue_98697_reexport_with_anonymous_lifetime::repro;
 
 // @has issue_98697/struct.Extra.html '//div[@id="trait-implementations-list"]//h3[@class="code-header"]' 'impl MyTrait<&Extra> for Extra'
index 14533624e448e6f059699be88c56dd554d7b34fc..3a488bdd2088b6320cd9951c207efb46287a81d6 100644 (file)
@@ -2,14 +2,14 @@
 #![feature(rustc_attrs)]
 
 // @has 'foo/fn.foo.html'
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'fn foo(x: usize, const Y: usize, z: usize) -> [usize; 3]'
+// @has - '//pre[@class="rust item-decl"]' 'fn foo(x: usize, const Y: usize, z: usize) -> [usize; 3]'
 #[rustc_legacy_const_generics(1)]
 pub fn foo<const Y: usize>(x: usize, z: usize) -> [usize; 3] {
     [x, Y, z]
 }
 
 // @has 'foo/fn.bar.html'
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'fn bar(x: usize, const Y: usize, const Z: usize) -> [usize; 3]'
+// @has - '//pre[@class="rust item-decl"]' 'fn bar(x: usize, const Y: usize, const Z: usize) -> [usize; 3]'
 #[rustc_legacy_const_generics(1, 2)]
 pub fn bar<const Y: usize, const Z: usize>(x: usize) -> [usize; 3] {
     [x, Y, z]
index 0fb66059109071885e06a42ac2b60cc12db8f26e..15e09f5165a2fbb2984a2670369c59290a9a5e11 100644 (file)
@@ -1,5 +1,5 @@
 #![crate_name = "foo"]
 
 // @has 'foo/type.Resolutions.html'
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "pub type Resolutions<'tcx> = &'tcx u8;"
+// @has - '//pre[@class="rust item-decl"]' "pub type Resolutions<'tcx> = &'tcx u8;"
 pub type Resolutions<'tcx> = &'tcx u8;
index b8c52b7b791d61c3acbf000adb2c3c8262acc829..a45ef37a7fce594c1ade8ad784dbf98c1bbf7e92 100644 (file)
@@ -11,8 +11,8 @@ pub struct Providers {
 }
 
 // @has 'foo/struct.Providers.html'
-// @has - '//*[@class="item-decl"]//code' "pub a: for<'tcx> fn(_: TyCtxt<'tcx>, _: u8) -> i8,"
-// @has - '//*[@class="item-decl"]//code' "pub b: for<'tcx> fn(_: TyCtxt<'tcx>, _: u16) -> i16,"
+// @has - '//*[@class="rust item-decl"]//code' "pub a: for<'tcx> fn(_: TyCtxt<'tcx>, _: u8) -> i8,"
+// @has - '//*[@class="rust item-decl"]//code' "pub b: for<'tcx> fn(_: TyCtxt<'tcx>, _: u16) -> i16,"
 // @has - '//*[@id="structfield.a"]/code' "a: for<'tcx> fn(_: TyCtxt<'tcx>, _: u8) -> i8"
 // @has - '//*[@id="structfield.b"]/code' "b: for<'tcx> fn(_: TyCtxt<'tcx>, _: u16) -> i16"
 gen! {
index 431db51d95f7c3a1fb84db3381df8dee6e5e429b..e403b7b78c9e74ea3744ccd25d7fbb7328b4702a 100644 (file)
@@ -13,6 +13,6 @@ pub fn foo(mut self) {}
     pub fn bar(mut bar: ()) {}
 }
 
-// @count foo/fn.baz.html '//div[@class="item-decl"]/pre[@class="rust"]' 1
-// @!has - '//div[@class="item-decl"]/pre[@class="rust"]' 'mut'
+// @count foo/fn.baz.html '//pre[@class="rust item-decl"]' 1
+// @!has - '//pre[@class="rust item-decl"]' 'mut'
 pub fn baz(mut foo: Foo) {}
index 659480479fd13e9dd747eb52294909696ac08891..af7b2f955fd4eaa174a883452395ad9241e95bc6 100644 (file)
@@ -19,12 +19,12 @@ impl Trait for isize {
     type X = <() as Trait>::X;
 }
 
-// @has 'normalize_assoc_item/fn.f.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub fn f() -> isize'
+// @has 'normalize_assoc_item/fn.f.html' '//pre[@class="rust item-decl"]' 'pub fn f() -> isize'
 pub fn f() -> <usize as Trait>::X {
     0
 }
 
-// @has 'normalize_assoc_item/fn.f2.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub fn f2() -> fn() -> i32'
+// @has 'normalize_assoc_item/fn.f2.html' '//pre[@class="rust item-decl"]' 'pub fn f2() -> fn() -> i32'
 pub fn f2() -> <isize as Trait>::X {
     todo!()
 }
@@ -49,10 +49,10 @@ impl<Inner: Trait> Trait for Generic<Inner> {
 // These can't be normalized because they depend on a generic parameter.
 // However the user can choose whether the text should be displayed as `Inner::X` or `<Inner as Trait>::X`.
 
-// @has 'normalize_assoc_item/struct.Unknown.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub struct Unknown<Inner: Trait>(pub <Inner as Trait>::X);'
+// @has 'normalize_assoc_item/struct.Unknown.html' '//pre[@class="rust item-decl"]' 'pub struct Unknown<Inner: Trait>(pub <Inner as Trait>::X);'
 pub struct Unknown<Inner: Trait>(pub <Inner as Trait>::X);
 
-// @has 'normalize_assoc_item/struct.Unknown2.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub struct Unknown2<Inner: Trait>(pub Inner::X);'
+// @has 'normalize_assoc_item/struct.Unknown2.html' '//pre[@class="rust item-decl"]' 'pub struct Unknown2<Inner: Trait>(pub Inner::X);'
 pub struct Unknown2<Inner: Trait>(pub Inner::X);
 
 trait Lifetimes<'a> {
@@ -63,20 +63,20 @@ impl<'a> Lifetimes<'a> for usize {
     type Y = &'a isize;
 }
 
-// @has 'normalize_assoc_item/fn.g.html' '//div[@class="item-decl"]/pre[@class="rust"]' "pub fn g() -> &isize"
+// @has 'normalize_assoc_item/fn.g.html' '//pre[@class="rust item-decl"]' "pub fn g() -> &isize"
 pub fn g() -> <usize as Lifetimes<'static>>::Y {
     &0
 }
 
-// @has 'normalize_assoc_item/constant.A.html' '//div[@class="item-decl"]/pre[@class="rust"]' "pub const A: &isize"
+// @has 'normalize_assoc_item/constant.A.html' '//pre[@class="rust item-decl"]' "pub const A: &isize"
 pub const A: <usize as Lifetimes<'static>>::Y = &0;
 
 // test cross-crate re-exports
 extern crate inner;
-// @has 'normalize_assoc_item/fn.foo.html' '//div[@class="item-decl"]/pre[@class="rust"]' "pub fn foo() -> i32"
+// @has 'normalize_assoc_item/fn.foo.html' '//pre[@class="rust item-decl"]' "pub fn foo() -> i32"
 pub use inner::foo;
 
-// @has 'normalize_assoc_item/fn.h.html' '//div[@class="item-decl"]/pre[@class="rust"]' "pub fn h<T>() -> IntoIter<T, Global>"
+// @has 'normalize_assoc_item/fn.h.html' '//pre[@class="rust item-decl"]' "pub fn h<T>() -> IntoIter<T, Global>"
 pub fn h<T>() -> <Vec<T> as IntoIterator>::IntoIter {
     vec![].into_iter()
 }
index 7115a01d079ff15b99d7befd2badf45028ffb970..ea4791579cd65baba1a7e3422f32d640ce4dc9b1 100644 (file)
@@ -3,7 +3,7 @@
 #![crate_name = "foo"]
 
 // @has foo/fn.bar.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'pub fn bar() -> '
+// @has - '//pre[@class="rust item-decl"]' 'pub fn bar() -> '
 /// foo
 pub fn bar() -> usize {
     2
index bdbcc47c9f28dd4328e3f28c2c9d006277de5efd..d0d9111bb4088187b742cc6a535a95c22c66d45c 100644 (file)
@@ -1,5 +1,5 @@
 #![crate_name = "foo"]
 
 // @has foo/fn.f.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'pub fn f(_: u8)'
+// @has - '//pre[@class="rust item-decl"]' 'pub fn f(_: u8)'
 pub fn f(0u8..=255: u8) {}
index 6694c91d104425c9653c7879194a56a596a34370..e7f5720d583c90b56234ef5b82849e6c31df73ae 100644 (file)
@@ -8,5 +8,5 @@
 extern crate all_item_types;
 
 // @has 'foo/fn.foo_ffn.html'
-// @has - '//*[@class="item-decl"]//code' 'pub unsafe extern "C" fn foo_ffn()'
+// @has - '//*[@class="rust item-decl"]//code' 'pub unsafe extern "C" fn foo_ffn()'
 pub use all_item_types::foo_ffn;
index 35c90ba5d7b894fac9f3e5fa9bb81882031d98d4..84ea4ad2c9ef30ea8fbb08b948661821ce29cbbe 100644 (file)
@@ -5,7 +5,7 @@
 
 extern crate reexports;
 
-// @has 'foo/macro.addr_of.html' '//*[@class="item-decl"]' 'pub macro addr_of($place:expr) {'
+// @has 'foo/macro.addr_of.html' '//*[@class="rust item-decl"]' 'pub macro addr_of($place:expr) {'
 pub use reexports::addr_of;
 // @!has 'foo/macro.addr_of_crate.html'
 pub(crate) use reexports::addr_of_crate;
@@ -14,7 +14,7 @@
 // @!has 'foo/macro.addr_of_local.html'
 use reexports::addr_of_local;
 
-// @has 'foo/struct.Foo.html' '//*[@class="item-decl"]' 'pub struct Foo;'
+// @has 'foo/struct.Foo.html' '//*[@class="rust item-decl"]' 'pub struct Foo;'
 pub use reexports::Foo;
 // @!has 'foo/struct.FooCrate.html'
 pub(crate) use reexports::FooCrate;
@@ -23,7 +23,7 @@
 // @!has 'foo/struct.FooLocal.html'
 use reexports::FooLocal;
 
-// @has 'foo/enum.Bar.html' '//*[@class="item-decl"]' 'pub enum Bar {'
+// @has 'foo/enum.Bar.html' '//*[@class="rust item-decl"]' 'pub enum Bar {'
 pub use reexports::Bar;
 // @!has 'foo/enum.BarCrate.html'
 pub(crate) use reexports::BarCrate;
@@ -32,7 +32,7 @@
 // @!has 'foo/enum.BarLocal.html'
 use reexports::BarLocal;
 
-// @has 'foo/fn.foo.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub fn foo()'
+// @has 'foo/fn.foo.html' '//pre[@class="rust item-decl"]' 'pub fn foo()'
 pub use reexports::foo;
 // @!has 'foo/fn.foo_crate.html'
 pub(crate) use reexports::foo_crate;
@@ -41,7 +41,7 @@
 // @!has 'foo/fn.foo_local.html'
 use reexports::foo_local;
 
-// @has 'foo/type.Type.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub type Type ='
+// @has 'foo/type.Type.html' '//pre[@class="rust item-decl"]' 'pub type Type ='
 pub use reexports::Type;
 // @!has 'foo/type.TypeCrate.html'
 pub(crate) use reexports::TypeCrate;
@@ -50,7 +50,7 @@
 // @!has 'foo/type.TypeLocal.html'
 use reexports::TypeLocal;
 
-// @has 'foo/union.Union.html' '//*[@class="item-decl"]' 'pub union Union {'
+// @has 'foo/union.Union.html' '//*[@class="rust item-decl"]' 'pub union Union {'
 pub use reexports::Union;
 // @!has 'foo/union.UnionCrate.html'
 pub(crate) use reexports::UnionCrate;
 
 pub mod outer {
     pub mod inner {
-        // @has 'foo/outer/inner/macro.addr_of.html' '//*[@class="item-decl"]' 'pub macro addr_of($place:expr) {'
+        // @has 'foo/outer/inner/macro.addr_of.html' '//*[@class="rust item-decl"]' 'pub macro addr_of($place:expr) {'
         pub use reexports::addr_of;
-        // @has 'foo/outer/inner/macro.addr_of_crate.html' '//*[@class="item-decl"]' 'pub(crate) macro addr_of_crate($place:expr) {'
+        // @has 'foo/outer/inner/macro.addr_of_crate.html' '//*[@class="rust item-decl"]' 'pub(crate) macro addr_of_crate($place:expr) {'
         pub(crate) use reexports::addr_of_crate;
-        // @has 'foo/outer/inner/macro.addr_of_super.html' '//*[@class="item-decl"]' 'pub(in outer) macro addr_of_super($place:expr) {'
+        // @has 'foo/outer/inner/macro.addr_of_super.html' '//*[@class="rust item-decl"]' 'pub(in outer) macro addr_of_super($place:expr) {'
         pub(super) use reexports::addr_of_super;
         // @!has 'foo/outer/inner/macro.addr_of_self.html'
         pub(self) use reexports::addr_of_self;
         // @!has 'foo/outer/inner/macro.addr_of_local.html'
         use reexports::addr_of_local;
 
-        // @has 'foo/outer/inner/struct.Foo.html' '//*[@class="item-decl"]' 'pub struct Foo;'
+        // @has 'foo/outer/inner/struct.Foo.html' '//*[@class="rust item-decl"]' 'pub struct Foo;'
         pub use reexports::Foo;
-        // @has 'foo/outer/inner/struct.FooCrate.html' '//*[@class="item-decl"]' 'pub(crate) struct FooCrate;'
+        // @has 'foo/outer/inner/struct.FooCrate.html' '//*[@class="rust item-decl"]' 'pub(crate) struct FooCrate;'
         pub(crate) use reexports::FooCrate;
-        // @has 'foo/outer/inner/struct.FooSuper.html' '//*[@class="item-decl"]' 'pub(in outer) struct FooSuper;'
+        // @has 'foo/outer/inner/struct.FooSuper.html' '//*[@class="rust item-decl"]' 'pub(in outer) struct FooSuper;'
         pub(super) use reexports::FooSuper;
         // @!has 'foo/outer/inner/struct.FooSelf.html'
         pub(self) use reexports::FooSelf;
         // @!has 'foo/outer/inner/struct.FooLocal.html'
         use reexports::FooLocal;
 
-        // @has 'foo/outer/inner/enum.Bar.html' '//*[@class="item-decl"]' 'pub enum Bar {'
+        // @has 'foo/outer/inner/enum.Bar.html' '//*[@class="rust item-decl"]' 'pub enum Bar {'
         pub use reexports::Bar;
-        // @has 'foo/outer/inner/enum.BarCrate.html' '//*[@class="item-decl"]' 'pub(crate) enum BarCrate {'
+        // @has 'foo/outer/inner/enum.BarCrate.html' '//*[@class="rust item-decl"]' 'pub(crate) enum BarCrate {'
         pub(crate) use reexports::BarCrate;
-        // @has 'foo/outer/inner/enum.BarSuper.html' '//*[@class="item-decl"]' 'pub(in outer) enum BarSuper {'
+        // @has 'foo/outer/inner/enum.BarSuper.html' '//*[@class="rust item-decl"]' 'pub(in outer) enum BarSuper {'
         pub(super) use reexports::BarSuper;
         // @!has 'foo/outer/inner/enum.BarSelf.html'
         pub(self) use reexports::BarSelf;
         // @!has 'foo/outer/inner/enum.BarLocal.html'
         use reexports::BarLocal;
 
-        // @has 'foo/outer/inner/fn.foo.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub fn foo()'
+        // @has 'foo/outer/inner/fn.foo.html' '//pre[@class="rust item-decl"]' 'pub fn foo()'
         pub use reexports::foo;
-        // @has 'foo/outer/inner/fn.foo_crate.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub(crate) fn foo_crate()'
+        // @has 'foo/outer/inner/fn.foo_crate.html' '//pre[@class="rust item-decl"]' 'pub(crate) fn foo_crate()'
         pub(crate) use reexports::foo_crate;
-        // @has 'foo/outer/inner/fn.foo_super.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub(in outer) fn foo_super()'
+        // @has 'foo/outer/inner/fn.foo_super.html' '//pre[@class="rust item-decl"]' 'pub(in outer) fn foo_super()'
         pub(super) use::reexports::foo_super;
         // @!has 'foo/outer/inner/fn.foo_self.html'
         pub(self) use reexports::foo_self;
         // @!has 'foo/outer/inner/fn.foo_local.html'
         use reexports::foo_local;
 
-        // @has 'foo/outer/inner/type.Type.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub type Type ='
+        // @has 'foo/outer/inner/type.Type.html' '//pre[@class="rust item-decl"]' 'pub type Type ='
         pub use reexports::Type;
-        // @has 'foo/outer/inner/type.TypeCrate.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub(crate) type TypeCrate ='
+        // @has 'foo/outer/inner/type.TypeCrate.html' '//pre[@class="rust item-decl"]' 'pub(crate) type TypeCrate ='
         pub(crate) use reexports::TypeCrate;
-        // @has 'foo/outer/inner/type.TypeSuper.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub(in outer) type TypeSuper ='
+        // @has 'foo/outer/inner/type.TypeSuper.html' '//pre[@class="rust item-decl"]' 'pub(in outer) type TypeSuper ='
         pub(super) use reexports::TypeSuper;
         // @!has 'foo/outer/inner/type.TypeSelf.html'
         pub(self) use reexports::TypeSelf;
         // @!has 'foo/outer/inner/type.TypeLocal.html'
         use reexports::TypeLocal;
 
-        // @has 'foo/outer/inner/union.Union.html' '//*[@class="item-decl"]' 'pub union Union {'
+        // @has 'foo/outer/inner/union.Union.html' '//*[@class="rust item-decl"]' 'pub union Union {'
         pub use reexports::Union;
-        // @has 'foo/outer/inner/union.UnionCrate.html' '//*[@class="item-decl"]' 'pub(crate) union UnionCrate {'
+        // @has 'foo/outer/inner/union.UnionCrate.html' '//*[@class="rust item-decl"]' 'pub(crate) union UnionCrate {'
         pub(crate) use reexports::UnionCrate;
-        // @has 'foo/outer/inner/union.UnionSuper.html' '//*[@class="item-decl"]' 'pub(in outer) union UnionSuper {'
+        // @has 'foo/outer/inner/union.UnionSuper.html' '//*[@class="rust item-decl"]' 'pub(in outer) union UnionSuper {'
         pub(super) use reexports::UnionSuper;
         // @!has 'foo/outer/inner/union.UnionSelf.html'
         pub(self) use reexports::UnionSelf;
index 65d305c6d2c4202b7a2b6e6f61e59ed74eb68914..3c51ac395afc5f987b354e6a17c8a481d7d92159 100644 (file)
@@ -4,7 +4,7 @@
 
 extern crate reexports;
 
-// @has 'foo/macro.addr_of.html' '//*[@class="item-decl"]' 'pub macro addr_of($place:expr) {'
+// @has 'foo/macro.addr_of.html' '//*[@class="rust item-decl"]' 'pub macro addr_of($place:expr) {'
 pub use reexports::addr_of;
 // @!has 'foo/macro.addr_of_crate.html'
 pub(crate) use reexports::addr_of_crate;
@@ -13,7 +13,7 @@
 // @!has 'foo/macro.addr_of_local.html'
 use reexports::addr_of_local;
 
-// @has 'foo/struct.Foo.html' '//*[@class="item-decl"]' 'pub struct Foo;'
+// @has 'foo/struct.Foo.html' '//*[@class="rust item-decl"]' 'pub struct Foo;'
 pub use reexports::Foo;
 // @!has 'foo/struct.FooCrate.html'
 pub(crate) use reexports::FooCrate;
@@ -22,7 +22,7 @@
 // @!has 'foo/struct.FooLocal.html'
 use reexports::FooLocal;
 
-// @has 'foo/enum.Bar.html' '//*[@class="item-decl"]' 'pub enum Bar {'
+// @has 'foo/enum.Bar.html' '//*[@class="rust item-decl"]' 'pub enum Bar {'
 pub use reexports::Bar;
 // @!has 'foo/enum.BarCrate.html'
 pub(crate) use reexports::BarCrate;
@@ -31,7 +31,7 @@
 // @!has 'foo/enum.BarLocal.html'
 use reexports::BarLocal;
 
-// @has 'foo/fn.foo.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub fn foo()'
+// @has 'foo/fn.foo.html' '//pre[@class="rust item-decl"]' 'pub fn foo()'
 pub use reexports::foo;
 // @!has 'foo/fn.foo_crate.html'
 pub(crate) use reexports::foo_crate;
@@ -40,7 +40,7 @@
 // @!has 'foo/fn.foo_local.html'
 use reexports::foo_local;
 
-// @has 'foo/type.Type.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub type Type ='
+// @has 'foo/type.Type.html' '//pre[@class="rust item-decl"]' 'pub type Type ='
 pub use reexports::Type;
 // @!has 'foo/type.TypeCrate.html'
 pub(crate) use reexports::TypeCrate;
@@ -49,7 +49,7 @@
 // @!has 'foo/type.TypeLocal.html'
 use reexports::TypeLocal;
 
-// @has 'foo/union.Union.html' '//*[@class="item-decl"]' 'pub union Union {'
+// @has 'foo/union.Union.html' '//*[@class="rust item-decl"]' 'pub union Union {'
 pub use reexports::Union;
 // @!has 'foo/union.UnionCrate.html'
 pub(crate) use reexports::UnionCrate;
@@ -60,7 +60,7 @@
 
 pub mod outer {
     pub mod inner {
-        // @has 'foo/outer/inner/macro.addr_of.html' '//*[@class="item-decl"]' 'pub macro addr_of($place:expr) {'
+        // @has 'foo/outer/inner/macro.addr_of.html' '//*[@class="rust item-decl"]' 'pub macro addr_of($place:expr) {'
         pub use reexports::addr_of;
         // @!has 'foo/outer/inner/macro.addr_of_crate.html'
         pub(crate) use reexports::addr_of_crate;
@@ -71,7 +71,7 @@ pub mod inner {
         // @!has 'foo/outer/inner/macro.addr_of_local.html'
         use reexports::addr_of_local;
 
-        // @has 'foo/outer/inner/struct.Foo.html' '//*[@class="item-decl"]' 'pub struct Foo;'
+        // @has 'foo/outer/inner/struct.Foo.html' '//*[@class="rust item-decl"]' 'pub struct Foo;'
         pub use reexports::Foo;
         // @!has 'foo/outer/inner/struct.FooCrate.html'
         pub(crate) use reexports::FooCrate;
@@ -82,7 +82,7 @@ pub mod inner {
         // @!has 'foo/outer/inner/struct.FooLocal.html'
         use reexports::FooLocal;
 
-        // @has 'foo/outer/inner/enum.Bar.html' '//*[@class="item-decl"]' 'pub enum Bar {'
+        // @has 'foo/outer/inner/enum.Bar.html' '//*[@class="rust item-decl"]' 'pub enum Bar {'
         pub use reexports::Bar;
         // @!has 'foo/outer/inner/enum.BarCrate.html'
         pub(crate) use reexports::BarCrate;
@@ -93,7 +93,7 @@ pub mod inner {
         // @!has 'foo/outer/inner/enum.BarLocal.html'
         use reexports::BarLocal;
 
-        // @has 'foo/outer/inner/fn.foo.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub fn foo()'
+        // @has 'foo/outer/inner/fn.foo.html' '//pre[@class="rust item-decl"]' 'pub fn foo()'
         pub use reexports::foo;
         // @!has 'foo/outer/inner/fn.foo_crate.html'
         pub(crate) use reexports::foo_crate;
@@ -104,7 +104,7 @@ pub mod inner {
         // @!has 'foo/outer/inner/fn.foo_local.html'
         use reexports::foo_local;
 
-        // @has 'foo/outer/inner/type.Type.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub type Type ='
+        // @has 'foo/outer/inner/type.Type.html' '//pre[@class="rust item-decl"]' 'pub type Type ='
         pub use reexports::Type;
         // @!has 'foo/outer/inner/type.TypeCrate.html'
         pub(crate) use reexports::TypeCrate;
@@ -115,7 +115,7 @@ pub mod inner {
         // @!has 'foo/outer/inner/type.TypeLocal.html'
         use reexports::TypeLocal;
 
-        // @has 'foo/outer/inner/union.Union.html' '//*[@class="item-decl"]' 'pub union Union {'
+        // @has 'foo/outer/inner/union.Union.html' '//*[@class="rust item-decl"]' 'pub union Union {'
         pub use reexports::Union;
         // @!has 'foo/outer/inner/union.UnionCrate.html'
         pub(crate) use reexports::UnionCrate;
index a229a4e29fefb43a2ec580474fa492e3444dfe99..1120302ac7ea92efe4c80a1969dc577def92c7c8 100644 (file)
 
 pub struct S<T>(T);
 
-// @!has foo/trait.Tr.html '//div[@class="item-decl"]/pre[@class="rust"]/code/a[@class="trait"]' '~const'
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]/code/a[@class="trait"]' 'Clone'
-// @!has - '//div[@class="item-decl"]/pre[@class="rust"]/code/span[@class="where"]' '~const'
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]/code/span[@class="where"]' ': Clone'
+// @!has foo/trait.Tr.html '//pre[@class="rust item-decl"]/code/a[@class="trait"]' '~const'
+// @has - '//pre[@class="rust item-decl"]/code/a[@class="trait"]' 'Clone'
+// @!has - '//pre[@class="rust item-decl"]/code/span[@class="where"]' '~const'
+// @has - '//pre[@class="rust item-decl"]/code/span[@class="where"]' ': Clone'
 #[const_trait]
 pub trait Tr<T> {
     // @!has - '//section[@id="method.a"]/h4[@class="code-header"]' '~const'
@@ -45,10 +45,10 @@ fn a<A: ~const Clone + ~const Destruct>()
     }
 }
 
-// @!has foo/fn.foo.html '//div[@class="item-decl"]/pre[@class="rust"]/code/a[@class="trait"]' '~const'
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]/code/a[@class="trait"]' 'Clone'
-// @!has - '//div[@class="item-decl"]/pre[@class="rust"]/code/span[@class="where fmt-newline"]' '~const'
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]/code/span[@class="where fmt-newline"]' ': Clone'
+// @!has foo/fn.foo.html '//pre[@class="rust item-decl"]/code/a[@class="trait"]' '~const'
+// @has - '//pre[@class="rust item-decl"]/code/a[@class="trait"]' 'Clone'
+// @!has - '//pre[@class="rust item-decl"]/code/span[@class="where fmt-newline"]' '~const'
+// @has - '//pre[@class="rust item-decl"]/code/span[@class="where fmt-newline"]' ': Clone'
 pub const fn foo<F: ~const Clone + ~const Destruct>()
 where
     Option<F>: ~const Clone + ~const Destruct,
index 0b65bf1dfed0fa5f2d3b85bd3c7cefdaec169f6e..c508909f9aafa2421296ad0a54baca7f812311c4 100644 (file)
@@ -7,16 +7,16 @@
 
 extern "rust-intrinsic" {
     // @has 'foo/fn.abort.html'
-    // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'pub extern "rust-intrinsic" fn abort() -> !'
+    // @has - '//pre[@class="rust item-decl"]' 'pub extern "rust-intrinsic" fn abort() -> !'
     #[rustc_safe_intrinsic]
     pub fn abort() -> !;
     // @has 'foo/fn.unreachable.html'
-    // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'pub unsafe extern "rust-intrinsic" fn unreachable() -> !'
+    // @has - '//pre[@class="rust item-decl"]' 'pub unsafe extern "rust-intrinsic" fn unreachable() -> !'
     pub fn unreachable() -> !;
 }
 
 extern "C" {
     // @has 'foo/fn.needs_drop.html'
-    // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'pub unsafe extern "C" fn needs_drop() -> !'
+    // @has - '//pre[@class="rust item-decl"]' 'pub unsafe extern "C" fn needs_drop() -> !'
     pub fn needs_drop() -> !;
 }
index 67137fdcab274a75332d87f977bd365ccaf727c7..6dea3b74ea3ec901dcc2fb78ea21bd784d3f4e97 100644 (file)
@@ -4,25 +4,25 @@
 pub struct MyBox<T: ?Sized>(*const T);
 
 // @has 'foo/fn.alpha.html'
-// @snapshot link_slice_u32 - '//div[@class="item-decl"]/pre[@class="rust"]/code'
+// @snapshot link_slice_u32 - '//pre[@class="rust item-decl"]/code'
 pub fn alpha() -> &'static [u32] {
     loop {}
 }
 
 // @has 'foo/fn.beta.html'
-// @snapshot link_slice_generic - '//div[@class="item-decl"]/pre[@class="rust"]/code'
+// @snapshot link_slice_generic - '//pre[@class="rust item-decl"]/code'
 pub fn beta<T>() -> &'static [T] {
     loop {}
 }
 
 // @has 'foo/fn.gamma.html'
-// @snapshot link_box_u32 - '//div[@class="item-decl"]/pre[@class="rust"]/code'
+// @snapshot link_box_u32 - '//pre[@class="rust item-decl"]/code'
 pub fn gamma() -> MyBox<[u32]> {
     loop {}
 }
 
 // @has 'foo/fn.delta.html'
-// @snapshot link_box_generic - '//div[@class="item-decl"]/pre[@class="rust"]/code'
+// @snapshot link_box_generic - '//pre[@class="rust item-decl"]/code'
 pub fn delta<T>() -> MyBox<[T]> {
     loop {}
 }
index 3bfb43a0bef2c7fed5758002ec0bf30484a185ce..6f06c8c9c49965f1ee4199ed27e169401fcf6eab 100644 (file)
@@ -4,7 +4,7 @@ struct BodyId {
     hir_id: usize,
 }
 
-// @has 'foo/fn.body_owner.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub fn body_owner(_: BodyId)'
+// @has 'foo/fn.body_owner.html' '//pre[@class="rust item-decl"]' 'pub fn body_owner(_: BodyId)'
 pub fn body_owner(BodyId { hir_id }: BodyId) {
     // ...
 }
index f5fdb1f52bf8ece496e19348de475cee5d5821a1..9640b96b6b546b2aac923e62df70484d8647a6d9 100644 (file)
@@ -1,5 +1,5 @@
 #![crate_name = "foo"]
 
 // @has foo/fn.foo.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "_: &(dyn ToString + 'static)"
+// @has - '//pre[@class="rust item-decl"]' "_: &(dyn ToString + 'static)"
 pub fn foo(_: &(ToString + 'static)) {}
index 5d34ec09b66dc621a2d1bd3b0ddac44acac71f2d..1f745043894ea8fa7a974c55e035f3788da93e68 100644 (file)
@@ -55,7 +55,7 @@ pub union Union {
 
 // @has 'toggle_item_contents/struct.PrivStruct.html'
 // @count - '//details[@class="toggle type-contents-toggle"]' 0
-// @has - '//div[@class="item-decl"]' '/* private fields */'
+// @has - '//pre[@class="rust item-decl"]' '/* private fields */'
 pub struct PrivStruct {
     a: usize,
     b: usize,
@@ -81,8 +81,8 @@ pub enum EnumStructVariant {
 }
 
 // @has 'toggle_item_contents/enum.LargeEnum.html'
-// @count - '//div[@class="item-decl"]/pre//details[@class="toggle type-contents-toggle"]' 1
-// @has - '//div[@class="item-decl"]/pre//details[@class="toggle type-contents-toggle"]' 'Show 13 variants'
+// @count - '//pre[@class="rust item-decl"]//details[@class="toggle type-contents-toggle"]' 1
+// @has - '//pre[@class="rust item-decl"]//details[@class="toggle type-contents-toggle"]' 'Show 13 variants'
 pub enum LargeEnum {
     A, B, C, D, E, F(u8), G, H, I, J, K, L, M
 }
index 791c099cc52336451cbfa9418c460ca82d3834cb..5c3f82c6b3cff0f2b8ff6cbcf91ca8dc8ce45911 100644 (file)
 // @has foo/index.html '//a[@class="traitalias"]' 'Foo'
 
 // @has foo/traitalias.CopyAlias.html
-// @has - '//section[@id="main-content"]/div[@class="item-decl"]/pre' 'trait CopyAlias = Copy;'
+// @has - '//section[@id="main-content"]/pre[@class="rust item-decl"]' 'trait CopyAlias = Copy;'
 pub trait CopyAlias = Copy;
 // @has foo/traitalias.Alias2.html
-// @has - '//section[@id="main-content"]/div[@class="item-decl"]/pre' 'trait Alias2 = Copy + Debug;'
+// @has - '//section[@id="main-content"]/pre[@class="rust item-decl"]' 'trait Alias2 = Copy + Debug;'
 pub trait Alias2 = Copy + Debug;
 // @has foo/traitalias.Foo.html
-// @has - '//section[@id="main-content"]/div[@class="item-decl"]/pre' 'trait Foo<T> = Into<T> + Debug;'
+// @has - '//section[@id="main-content"]/pre[@class="rust item-decl"]' 'trait Foo<T> = Into<T> + Debug;'
 pub trait Foo<T> = Into<T> + Debug;
 // @has foo/fn.bar.html '//a[@href="traitalias.Alias2.html"]' 'Alias2'
 pub fn bar<T>() where T: Alias2 {}
index d72c10f2b2542e9a04df62cb6ddd72da877ea208..2836ddedc2b20f952726d4a0cdc720da8dc26331 100644 (file)
@@ -19,7 +19,7 @@ pub struct Foo(
 );
 
 // @has foo/enum.Bar.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'BarVariant(String),'
+// @has - '//pre[@class="rust item-decl"]' 'BarVariant(String),'
 // @matches - '//*[@id="variant.BarVariant.fields"]/h4' '^Tuple Fields$'
 // @has - '//*[@id="variant.BarVariant.field.0"]' '0: String'
 // @has - '//*[@id="variant.BarVariant.fields"]//*[@class="docblock"]' 'Hello docs'
index e716de8b55c8fdfe3a037eedee8c4d237c9919fb..0ea5b5bfac90833c994b61f338b4bde6e4ae6e64 100644 (file)
@@ -1,20 +1,20 @@
 #![crate_name = "foo"]
 
 // @has foo/fn.tuple0.html //pre 'pub fn tuple0(x: ())'
-// @snapshot link_unit - '//div[@class="item-decl"]/pre[@class="rust"]/code'
+// @snapshot link_unit - '//pre[@class="rust item-decl"]/code'
 pub fn tuple0(x: ()) -> () { x }
 // @has foo/fn.tuple1.html //pre 'pub fn tuple1(x: (i32,)) -> (i32,)'
-// @snapshot link1_i32 - '//div[@class="item-decl"]/pre[@class="rust"]/code'
+// @snapshot link1_i32 - '//pre[@class="rust item-decl"]/code'
 pub fn tuple1(x: (i32,)) -> (i32,) { x }
 // @has foo/fn.tuple2.html //pre 'pub fn tuple2(x: (i32, i32)) -> (i32, i32)'
-// @snapshot link2_i32 - '//div[@class="item-decl"]/pre[@class="rust"]/code'
+// @snapshot link2_i32 - '//pre[@class="rust item-decl"]/code'
 pub fn tuple2(x: (i32, i32)) -> (i32, i32) { x }
 // @has foo/fn.tuple1_t.html //pre 'pub fn tuple1_t<T>(x: (T,)) -> (T,)'
-// @snapshot link1_t - '//div[@class="item-decl"]/pre[@class="rust"]/code'
+// @snapshot link1_t - '//pre[@class="rust item-decl"]/code'
 pub fn tuple1_t<T>(x: (T,)) -> (T,) { x }
 // @has foo/fn.tuple2_t.html //pre 'pub fn tuple2_t<T>(x: (T, T)) -> (T, T)'
-// @snapshot link2_t - '//div[@class="item-decl"]/pre[@class="rust"]/code'
+// @snapshot link2_t - '//pre[@class="rust item-decl"]/code'
 pub fn tuple2_t<T>(x: (T, T)) -> (T, T) { x }
 // @has foo/fn.tuple2_tu.html //pre 'pub fn tuple2_tu<T, U>(x: (T, U)) -> (T, U)'
-// @snapshot link2_tu - '//div[@class="item-decl"]/pre[@class="rust"]/code'
+// @snapshot link2_tu - '//pre[@class="rust item-decl"]/code'
 pub fn tuple2_tu<T, U>(x: (T, U)) -> (T, U) { x }
index 353cd1c477249dae11398e389762048d56f53b9a..6ddfa0c4d5ca2f9a624e74a38a6f52671974d591 100644 (file)
@@ -4,14 +4,14 @@
 
 extern crate unit_return;
 
-// @has 'foo/fn.f0.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'F: FnMut(u8) + Clone'
+// @has 'foo/fn.f0.html' '//pre[@class="rust item-decl"]' 'F: FnMut(u8) + Clone'
 pub fn f0<F: FnMut(u8) + Clone>(f: F) {}
 
-// @has 'foo/fn.f1.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'F: FnMut(u16) + Clone'
+// @has 'foo/fn.f1.html' '//pre[@class="rust item-decl"]' 'F: FnMut(u16) + Clone'
 pub fn f1<F: FnMut(u16) -> () + Clone>(f: F) {}
 
-// @has 'foo/fn.f2.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'F: FnMut(u32) + Clone'
+// @has 'foo/fn.f2.html' '//pre[@class="rust item-decl"]' 'F: FnMut(u32) + Clone'
 pub use unit_return::f2;
 
-// @has 'foo/fn.f3.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'F: FnMut(u64) + Clone'
+// @has 'foo/fn.f3.html' '//pre[@class="rust item-decl"]' 'F: FnMut(u64) + Clone'
 pub use unit_return::f3;
index c0c085e6ac72500d63deb2848063d4f54654b136..c1ac834b2fcb8544001591942218d8aaeb6c33b9 100644 (file)
@@ -1,6 +1,6 @@
 #![crate_name = "foo"]
 
 // @has foo/fn.foo.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'pub fn foo<X, Y: ?Sized>(_: &X)'
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'where X: ?Sized,'
+// @has - '//pre[@class="rust item-decl"]' 'pub fn foo<X, Y: ?Sized>(_: &X)'
+// @has - '//pre[@class="rust item-decl"]' 'where X: ?Sized,'
 pub fn foo<X, Y: ?Sized>(_: &X) where X: ?Sized {}
index f84cb3753cb93a119ab72b7fc3a91eb5c76c0c99..6f151f2328e4f69878f096086df403ef0610e6fa 100644 (file)
@@ -1 +1 @@
-<div class="item-decl"><pre class="rust"><code>pub struct Simd&lt;T&gt;(_)<br /><span class="where">where<br />&#160;&#160;&#160;&#160;T: <a class="trait" href="trait.MyTrait.html" title="trait foo::MyTrait">MyTrait</a></span>;</code></pre></div>
\ No newline at end of file
+<pre class="rust item-decl"><code>pub struct Simd&lt;T&gt;(_)<br /><span class="where">where<br />&#160;&#160;&#160;&#160;T: <a class="trait" href="trait.MyTrait.html" title="trait foo::MyTrait">MyTrait</a></span>;</code></pre>
\ No newline at end of file
index 85b626674274cff6f4f4fd53b3c2e7bdcc9f1251..11df902f3720f7d6cc9c87d72fd1163b3bacb2b8 100644 (file)
@@ -1,8 +1,8 @@
-<div class="item-decl"><pre class="rust"><code>pub trait TraitWhere {
+<pre class="rust item-decl"><code>pub trait TraitWhere {
     type <a href="#associatedtype.Item" class="associatedtype">Item</a>&lt;'a&gt;<br />&#160;&#160;&#160;&#160;<span class="where">where<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Self: 'a</span>;
 
     fn <a href="#method.func" class="fn">func</a>(self)<br />&#160;&#160;&#160;&#160;<span class="where">where<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Self: <a class="trait" href="{{channel}}/core/marker/trait.Sized.html" title="trait core::marker::Sized">Sized</a></span>,
     { ... }
 <span class="item-spacer" />    fn <a href="#method.lines" class="fn">lines</a>(self) -&gt; <a class="struct" href="{{channel}}/std/io/struct.Lines.html" title="struct std::io::Lines">Lines</a>&lt;Self&gt;<br />&#160;&#160;&#160;&#160;<span class="where">where<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Self: <a class="trait" href="{{channel}}/core/marker/trait.Sized.html" title="trait core::marker::Sized">Sized</a></span>,
     { ... }
-}</code></pre></div>
\ No newline at end of file
+}</code></pre>
\ No newline at end of file
index 644a0058244522a55be5bb50683b51130497927e..4c34c7e51d93793338ecfa1c6ce6d272fe45d27a 100644 (file)
@@ -22,13 +22,13 @@ pub fn delta() {}
 pub struct Echo<E>(E);
 
 // @has 'foo/struct.Simd.html'
-// @snapshot SWhere_Simd_item-decl - '//div[@class="item-decl"]'
+// @snapshot SWhere_Simd_item-decl - '//pre[@class="rust item-decl"]'
 pub struct Simd<T>([T; 1])
 where
     T: MyTrait;
 
 // @has 'foo/trait.TraitWhere.html'
-// @snapshot SWhere_TraitWhere_item-decl - '//div[@class="item-decl"]'
+// @snapshot SWhere_TraitWhere_item-decl - '//pre[@class="rust item-decl"]'
 pub trait TraitWhere {
     type Item<'a> where Self: 'a;
 
@@ -57,6 +57,6 @@ pub enum Foxtrot<F> { Foxtrot1(F) }
 //          "impl<F> MyTrait for Foxtrot<F>where F: MyTrait"
 impl<F> MyTrait for Foxtrot<F>where F: MyTrait {}
 
-// @has foo/type.Golf.html '//div[@class="item-decl"]/pre[@class="rust"]' \
+// @has foo/type.Golf.html '//pre[@class="rust item-decl"]' \
 //          "type Golf<T>where T: Clone, = (T, T)"
 pub type Golf<T> where T: Clone = (T, T);
index eeb22878f3c63f7c6f4fd1da7e361f5a8f2bcfdb..904d461103617eefdc2fdc39f3db10c064c440cf 100644 (file)
@@ -1,4 +1,4 @@
-<div class="item-decl"><pre class="rust"><code>pub enum Cow&lt;'a, B&gt;<span class="where fmt-newline">where<br />&#160;&#160;&#160;&#160;B: <a class="trait" href="trait.ToOwned.html" title="trait foo::ToOwned">ToOwned</a>&lt;dyn <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>&gt; + ?<a class="trait" href="{{channel}}/core/marker/trait.Sized.html" title="trait core::marker::Sized">Sized</a> + 'a,</span>{
+<pre class="rust item-decl"><code>pub enum Cow&lt;'a, B&gt;<span class="where fmt-newline">where<br />&#160;&#160;&#160;&#160;B: <a class="trait" href="trait.ToOwned.html" title="trait foo::ToOwned">ToOwned</a>&lt;dyn <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>&gt; + ?<a class="trait" href="{{channel}}/core/marker/trait.Sized.html" title="trait core::marker::Sized">Sized</a> + 'a,</span>{
     Borrowed(<a class="primitive" href="{{channel}}/std/primitive.reference.html">&amp;'a B</a>),
     Whatever(<a class="primitive" href="{{channel}}/std/primitive.u32.html">u32</a>),
-}</code></pre></div>
\ No newline at end of file
+}</code></pre>
\ No newline at end of file
index c8037c2a8df5a946527d14945c30514be80c0418..7bc9b780197bb58467800803801a7e5d727dee6e 100644 (file)
@@ -1,4 +1,4 @@
-<div class="item-decl"><pre class="rust"><code>pub enum Cow2&lt;'a, B:&#160;?<a class="trait" href="{{channel}}/core/marker/trait.Sized.html" title="trait core::marker::Sized">Sized</a> + <a class="trait" href="trait.ToOwned.html" title="trait foo::ToOwned">ToOwned</a>&lt;dyn <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>&gt; + 'a&gt; {
+<pre class="rust item-decl"><code>pub enum Cow2&lt;'a, B:&#160;?<a class="trait" href="{{channel}}/core/marker/trait.Sized.html" title="trait core::marker::Sized">Sized</a> + <a class="trait" href="trait.ToOwned.html" title="trait foo::ToOwned">ToOwned</a>&lt;dyn <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>&gt; + 'a&gt; {
     Borrowed(<a class="primitive" href="{{channel}}/std/primitive.reference.html">&amp;'a B</a>),
     Whatever(<a class="primitive" href="{{channel}}/std/primitive.u32.html">u32</a>),
-}</code></pre></div>
\ No newline at end of file
+}</code></pre>
\ No newline at end of file
index 4b740b970fc20a425028f175aab99d4b8f9cd578..b540c7c97c1f40e6d909e7eec7df074f95d1460e 100644 (file)
@@ -4,7 +4,7 @@
 #![crate_name = "foo"]
 
 // @has 'foo/trait.ToOwned.html'
-// @snapshot trait - '//*[@class="item-decl"]'
+// @snapshot trait - '//*[@class="rust item-decl"]'
 pub trait ToOwned<T>
 where T: Clone
 {
@@ -14,7 +14,7 @@ pub trait ToOwned<T>
 }
 
 // @has 'foo/trait.ToOwned2.html'
-// @snapshot trait2 - '//*[@class="item-decl"]'
+// @snapshot trait2 - '//*[@class="rust item-decl"]'
 // There should be a whitespace before `{` in this case!
 pub trait ToOwned2<T: Clone> {
     type Owned;
@@ -23,7 +23,7 @@ pub trait ToOwned2<T: Clone> {
 }
 
 // @has 'foo/enum.Cow.html'
-// @snapshot enum - '//*[@class="item-decl"]'
+// @snapshot enum - '//*[@class="rust item-decl"]'
 pub enum Cow<'a, B: ?Sized + 'a>
 where
     B: ToOwned<Clone>,
@@ -33,7 +33,7 @@ pub enum Cow<'a, B: ?Sized + 'a>
 }
 
 // @has 'foo/enum.Cow2.html'
-// @snapshot enum2 - '//*[@class="item-decl"]'
+// @snapshot enum2 - '//*[@class="rust item-decl"]'
 // There should be a whitespace before `{` in this case!
 pub enum Cow2<'a, B: ?Sized + ToOwned<Clone> + 'a> {
     Borrowed(&'a B),
@@ -41,7 +41,7 @@ pub enum Cow2<'a, B: ?Sized + ToOwned<Clone> + 'a> {
 }
 
 // @has 'foo/struct.Struct.html'
-// @snapshot struct - '//*[@class="item-decl"]'
+// @snapshot struct - '//*[@class="rust item-decl"]'
 pub struct Struct<'a, B: ?Sized + 'a>
 where
     B: ToOwned<Clone>,
@@ -51,7 +51,7 @@ pub struct Struct<'a, B: ?Sized + 'a>
 }
 
 // @has 'foo/struct.Struct2.html'
-// @snapshot struct2 - '//*[@class="item-decl"]'
+// @snapshot struct2 - '//*[@class="rust item-decl"]'
 // There should be a whitespace before `{` in this case!
 pub struct Struct2<'a, B: ?Sized + ToOwned<Clone> + 'a> {
     pub a: &'a B,
@@ -59,7 +59,7 @@ pub struct Struct2<'a, B: ?Sized + ToOwned<Clone> + 'a> {
 }
 
 // @has 'foo/union.Union.html'
-// @snapshot union - '//*[@class="item-decl"]'
+// @snapshot union - '//*[@class="rust item-decl"]'
 pub union Union<'a, B: ?Sized + 'a>
 where
     B: ToOwned<Clone>,
@@ -69,7 +69,7 @@ pub union Union<'a, B: ?Sized + 'a>
 }
 
 // @has 'foo/union.Union2.html'
-// @snapshot union2 - '//*[@class="item-decl"]'
+// @snapshot union2 - '//*[@class="rust item-decl"]'
 // There should be a whitespace before `{` in this case!
 pub union Union2<'a, B: ?Sized + ToOwned<Clone> + 'a> {
     a: &'a B,
index 5892270b2f9309aa04495227d0f921c6d539fbbc..54faee9e4052bc0da60e9db96d78e6fbd5a4bf6d 100644 (file)
@@ -1,4 +1,4 @@
-<div class="item-decl"><pre class="rust"><code>pub struct Struct&lt;'a, B&gt;<span class="where fmt-newline">where<br />&#160;&#160;&#160;&#160;B: <a class="trait" href="trait.ToOwned.html" title="trait foo::ToOwned">ToOwned</a>&lt;dyn <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>&gt; + ?<a class="trait" href="{{channel}}/core/marker/trait.Sized.html" title="trait core::marker::Sized">Sized</a> + 'a,</span>{
+<pre class="rust item-decl"><code>pub struct Struct&lt;'a, B&gt;<span class="where fmt-newline">where<br />&#160;&#160;&#160;&#160;B: <a class="trait" href="trait.ToOwned.html" title="trait foo::ToOwned">ToOwned</a>&lt;dyn <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>&gt; + ?<a class="trait" href="{{channel}}/core/marker/trait.Sized.html" title="trait core::marker::Sized">Sized</a> + 'a,</span>{
     pub a: <a class="primitive" href="{{channel}}/std/primitive.reference.html">&amp;'a B</a>,
     pub b: <a class="primitive" href="{{channel}}/std/primitive.u32.html">u32</a>,
-}</code></pre></div>
\ No newline at end of file
+}</code></pre>
\ No newline at end of file
index d3952b0c56699eecd68e68005bb243b737d82285..d872d516c09438c91107b43db2270e3b24867366 100644 (file)
@@ -1,4 +1,4 @@
-<div class="item-decl"><pre class="rust"><code>pub struct Struct2&lt;'a, B:&#160;?<a class="trait" href="{{channel}}/core/marker/trait.Sized.html" title="trait core::marker::Sized">Sized</a> + <a class="trait" href="trait.ToOwned.html" title="trait foo::ToOwned">ToOwned</a>&lt;dyn <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>&gt; + 'a&gt; {
+<pre class="rust item-decl"><code>pub struct Struct2&lt;'a, B:&#160;?<a class="trait" href="{{channel}}/core/marker/trait.Sized.html" title="trait core::marker::Sized">Sized</a> + <a class="trait" href="trait.ToOwned.html" title="trait foo::ToOwned">ToOwned</a>&lt;dyn <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>&gt; + 'a&gt; {
     pub a: <a class="primitive" href="{{channel}}/std/primitive.reference.html">&amp;'a B</a>,
     pub b: <a class="primitive" href="{{channel}}/std/primitive.u32.html">u32</a>,
-}</code></pre></div>
\ No newline at end of file
+}</code></pre>
\ No newline at end of file
index a2df06e7736af684b7ed8e12eedded83148491b0..bc3653de52d165d53fb8bd3af0730ca4b70c1fd8 100644 (file)
@@ -1,6 +1,6 @@
-<div class="item-decl"><pre class="rust"><code>pub trait ToOwned&lt;T&gt;<span class="where fmt-newline">where<br />&#160;&#160;&#160;&#160;T: <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>,</span>{
+<pre class="rust item-decl"><code>pub trait ToOwned&lt;T&gt;<span class="where fmt-newline">where<br />&#160;&#160;&#160;&#160;T: <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>,</span>{
     type <a href="#associatedtype.Owned" class="associatedtype">Owned</a>;
 
     fn <a href="#tymethod.to_owned" class="fn">to_owned</a>(&amp;self) -&gt; Self::<a class="associatedtype" href="trait.ToOwned.html#associatedtype.Owned" title="type foo::ToOwned::Owned">Owned</a>;
 <span class="item-spacer" />    fn <a href="#tymethod.whatever" class="fn">whatever</a>(&amp;self) -&gt; T;
-}</code></pre></div>
\ No newline at end of file
+}</code></pre>
\ No newline at end of file
index 2bfd6f7685a6729dc8e1b2ffbe679978f04eaf58..eda4ca72acc1805ad6fda74dbcdcedfb62b26c2d 100644 (file)
@@ -1,6 +1,6 @@
-<div class="item-decl"><pre class="rust"><code>pub trait ToOwned2&lt;T:&#160;<a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>&gt; {
+<pre class="rust item-decl"><code>pub trait ToOwned2&lt;T:&#160;<a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>&gt; {
     type <a href="#associatedtype.Owned" class="associatedtype">Owned</a>;
 
     fn <a href="#tymethod.to_owned" class="fn">to_owned</a>(&amp;self) -&gt; Self::<a class="associatedtype" href="trait.ToOwned2.html#associatedtype.Owned" title="type foo::ToOwned2::Owned">Owned</a>;
 <span class="item-spacer" />    fn <a href="#tymethod.whatever" class="fn">whatever</a>(&amp;self) -&gt; T;
-}</code></pre></div>
\ No newline at end of file
+}</code></pre>
\ No newline at end of file
index 066f8f87b160b6af62cfce0a1955940fd26c7304..03a26280ba2cf9f5eb27e848f8651138227c8413 100644 (file)
@@ -1,3 +1,3 @@
-<div class="item-decl"><pre class="rust"><code>pub union Union&lt;'a, B&gt;<span class="where fmt-newline">where<br />&#160;&#160;&#160;&#160;B: <a class="trait" href="trait.ToOwned.html" title="trait foo::ToOwned">ToOwned</a>&lt;dyn <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>&gt; + ?<a class="trait" href="{{channel}}/core/marker/trait.Sized.html" title="trait core::marker::Sized">Sized</a> + 'a,</span>{
+<pre class="rust item-decl"><code>pub union Union&lt;'a, B&gt;<span class="where fmt-newline">where<br />&#160;&#160;&#160;&#160;B: <a class="trait" href="trait.ToOwned.html" title="trait foo::ToOwned">ToOwned</a>&lt;dyn <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>&gt; + ?<a class="trait" href="{{channel}}/core/marker/trait.Sized.html" title="trait core::marker::Sized">Sized</a> + 'a,</span>{
     /* private fields */
-}</code></pre></div>
\ No newline at end of file
+}</code></pre>
\ No newline at end of file
index 6b48c5dbd3e2803a1027e8eeec408fd1c9f8472f..fc78e9b6039b0f2c7a32917ddd8a3461eae4056d 100644 (file)
@@ -1,3 +1,3 @@
-<div class="item-decl"><pre class="rust"><code>pub union Union2&lt;'a, B:&#160;?<a class="trait" href="{{channel}}/core/marker/trait.Sized.html" title="trait core::marker::Sized">Sized</a> + <a class="trait" href="trait.ToOwned.html" title="trait foo::ToOwned">ToOwned</a>&lt;dyn <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>&gt; + 'a&gt; {
+<pre class="rust item-decl"><code>pub union Union2&lt;'a, B:&#160;?<a class="trait" href="{{channel}}/core/marker/trait.Sized.html" title="trait core::marker::Sized">Sized</a> + <a class="trait" href="trait.ToOwned.html" title="trait foo::ToOwned">ToOwned</a>&lt;dyn <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>&gt; + 'a&gt; {
     /* private fields */
-}</code></pre></div>
\ No newline at end of file
+}</code></pre>
\ No newline at end of file
index 178b8adc3f04af8f6de30df590a7de6e7499430e..dd5c700329f14eafa5d2c3519f1fbd7f0a451589 100644 (file)
@@ -1,5 +1,5 @@
 use std::fmt::Debug;
 
-// @has 'wrapping/fn.foo.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub fn foo() -> impl Debug'
-// @count - '//div[@class="item-decl"]/pre[@class="rust"]/br' 0
+// @has 'wrapping/fn.foo.html' '//pre[@class="rust item-decl"]' 'pub fn foo() -> impl Debug'
+// @count - '//pre[@class="rust item-decl"]/br' 0
 pub fn foo() -> impl Debug {}
diff --git a/tests/ui/const-generics/generic_const_exprs/single-satisfied-ConstEvaluatable-in-probe.rs b/tests/ui/const-generics/generic_const_exprs/single-satisfied-ConstEvaluatable-in-probe.rs
new file mode 100644 (file)
index 0000000..0ba0c5a
--- /dev/null
@@ -0,0 +1,39 @@
+// check-pass
+
+#![allow(incomplete_features)]
+#![feature(generic_const_exprs)]
+
+use std::marker::PhantomData;
+
+pub trait Bytes {
+    const BYTES: usize;
+}
+
+#[derive(Clone, Debug)]
+pub struct Conster<OT>
+where
+    OT: Bytes,
+    [(); OT::BYTES]: Sized,
+{
+    _offset_type: PhantomData<fn(OT) -> OT>,
+}
+
+impl<OT> Conster<OT>
+where
+    OT: Bytes,
+    [(); OT::BYTES]: Sized,
+{
+    pub fn new() -> Self {
+        Conster { _offset_type: PhantomData }
+    }
+}
+
+pub fn make_conster<COT>() -> Conster<COT>
+where
+    COT: Bytes,
+    [(); COT::BYTES]: Sized,
+{
+    Conster::new()
+}
+
+fn main() {}
index be321c3c5c08f1279e539132933ba9d391027627..3480a2ec8154806572d6255a4523745a7873f3b0 100644 (file)
@@ -15,7 +15,7 @@ LL |     format!("{:X}", "3");
              NonZeroIsize
            and 21 others
    = note: required for `&str` to implement `UpperHex`
-note: required by a bound in `ArgumentV1::<'a>::new_upper_hex`
+note: required by a bound in `core::fmt::ArgumentV1::<'a>::new_upper_hex`
   --> $SRC_DIR/core/src/fmt/mod.rs:LL:COL
    = note: this error originates in the macro `$crate::__export::format_args` which comes from the expansion of the macro `arg_new` (in Nightly builds, run with -Z macro-backtrace for more info)
 
index 3ed040c3ab35926e91d4d0731b008da25cd2f0e1..d43f4f0d9570b0ce3ffc8c32bd01baf2d887e53a 100644 (file)
@@ -6,11 +6,11 @@ LL |     send(format_args!("{:?}", c));
    |     |
    |     required by a bound introduced by this call
    |
-   = help: within `[ArgumentV1<'_>]`, the trait `Sync` is not implemented for `core::fmt::Opaque`
+   = help: within `[core::fmt::ArgumentV1<'_>]`, the trait `Sync` is not implemented for `core::fmt::Opaque`
    = note: required because it appears within the type `&core::fmt::Opaque`
    = note: required because it appears within the type `ArgumentV1<'_>`
    = note: required because it appears within the type `[ArgumentV1<'_>]`
-   = note: required for `&[ArgumentV1<'_>]` to implement `Send`
+   = note: required for `&[core::fmt::ArgumentV1<'_>]` to implement `Send`
    = note: required because it appears within the type `Arguments<'_>`
 note: required by a bound in `send`
   --> $DIR/send-sync.rs:1:12
index e12857008a5e0e44c6a7bc4c5dcd8a0bf3495419..7ceea676d3a37d0bf9bc68dc8946ead9d029846d 100644 (file)
@@ -34,7 +34,7 @@
 
 // See https://github.com/rust-lang/rust/pull/53562
 // and https://github.com/rust-lang/rfcs/pull/2527
-// and https://twitter.com/garblefart/status/1393236602856611843
+// and https://web.archive.org/web/20211010063452/https://twitter.com/garblefart/status/1393236602856611843
 // for context.
 
 fn main() {
diff --git a/tests/ui/suggestions/recover-invalid-float-invalid.rs b/tests/ui/suggestions/recover-invalid-float-invalid.rs
new file mode 100644 (file)
index 0000000..79430d8
--- /dev/null
@@ -0,0 +1,24 @@
+// Check that suggestions to add a zero to integers with a preceding dot only appear when the change
+// will result in a valid floating point literal.
+
+fn main() {}
+
+fn a() {
+    _ = .3u32;
+    //~^ ERROR expected expression, found `.`
+}
+
+fn b() {
+    _ = .0b0;
+    //~^ ERROR expected expression, found `.`
+}
+
+fn c() {
+    _ = .0o07;
+    //~^ ERROR expected expression, found `.`
+}
+
+fn d() {
+    _ = .0x0ABC;
+    //~^ ERROR expected expression, found `.`
+}
diff --git a/tests/ui/suggestions/recover-invalid-float-invalid.stderr b/tests/ui/suggestions/recover-invalid-float-invalid.stderr
new file mode 100644 (file)
index 0000000..5764afc
--- /dev/null
@@ -0,0 +1,26 @@
+error: expected expression, found `.`
+  --> $DIR/recover-invalid-float-invalid.rs:7:9
+   |
+LL |     _ = .3u32;
+   |         ^ expected expression
+
+error: expected expression, found `.`
+  --> $DIR/recover-invalid-float-invalid.rs:12:9
+   |
+LL |     _ = .0b0;
+   |         ^ expected expression
+
+error: expected expression, found `.`
+  --> $DIR/recover-invalid-float-invalid.rs:17:9
+   |
+LL |     _ = .0o07;
+   |         ^ expected expression
+
+error: expected expression, found `.`
+  --> $DIR/recover-invalid-float-invalid.rs:22:9
+   |
+LL |     _ = .0x0ABC;
+   |         ^ expected expression
+
+error: aborting due to 4 previous errors
+
diff --git a/tests/ui/traits/new-solver/unsize-good.rs b/tests/ui/traits/new-solver/unsize-good.rs
new file mode 100644 (file)
index 0000000..87ed9cf
--- /dev/null
@@ -0,0 +1,25 @@
+// compile-flags: -Ztrait-solver=next
+// check-pass
+
+#![feature(unsized_tuple_coercion)]
+
+trait Foo {}
+
+impl Foo for i32 {}
+
+fn main() {
+    // Unsizing via struct
+    let _: Box<dyn Foo> = Box::new(1i32);
+
+    // Slice unsizing
+    let y = [1, 2, 3];
+    let _: &[i32] = &y;
+
+    // Tuple unsizing
+    let hi = (1i32,);
+    let _: &(dyn Foo,) = &hi;
+
+    // Dropping auto traits
+    let a: &(dyn Foo + Send) = &1;
+    let _: &dyn Foo = a;
+}
diff --git a/tests/ui/traits/new-solver/upcast-right-substs.rs b/tests/ui/traits/new-solver/upcast-right-substs.rs
new file mode 100644 (file)
index 0000000..c19c82a
--- /dev/null
@@ -0,0 +1,14 @@
+// compile-flags: -Ztrait-solver=next
+// check-pass
+
+#![feature(trait_upcasting)]
+
+trait Foo: Bar<i32> + Bar<u32> {}
+
+trait Bar<T> {}
+
+fn main() {
+    let x: &dyn Foo = todo!();
+    let y: &dyn Bar<i32> = x;
+    let z: &dyn Bar<u32> = x;
+}
diff --git a/tests/ui/traits/new-solver/upcast-wrong-substs.rs b/tests/ui/traits/new-solver/upcast-wrong-substs.rs
new file mode 100644 (file)
index 0000000..f2d04d9
--- /dev/null
@@ -0,0 +1,13 @@
+// compile-flags: -Ztrait-solver=next
+
+#![feature(trait_upcasting)]
+
+trait Foo: Bar<i32> + Bar<u32> {}
+
+trait Bar<T> {}
+
+fn main() {
+    let x: &dyn Foo = todo!();
+    let y: &dyn Bar<usize> = x;
+    //~^ ERROR mismatched types
+}
diff --git a/tests/ui/traits/new-solver/upcast-wrong-substs.stderr b/tests/ui/traits/new-solver/upcast-wrong-substs.stderr
new file mode 100644 (file)
index 0000000..8623f39
--- /dev/null
@@ -0,0 +1,14 @@
+error[E0308]: mismatched types
+  --> $DIR/upcast-wrong-substs.rs:11:30
+   |
+LL |     let y: &dyn Bar<usize> = x;
+   |            ---------------   ^ expected trait `Bar`, found trait `Foo`
+   |            |
+   |            expected due to this
+   |
+   = note: expected reference `&dyn Bar<usize>`
+              found reference `&dyn Foo`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.