about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2022-09-29 13:27:28 +0000
committerbors <bors@rust-lang.org>2022-09-29 13:27:28 +0000
commit65445a571c11f07f4ca1ed0f63bad247ae295bd0 (patch)
treef98deb599ee3166a57ea2c49ac8939a6e9b36402
parentc5bbf36a31796b6b7b3add65ba20805b6659392c (diff)
parentf4e7094ffc3970a17884a5f933da45cb51dd3e1c (diff)
downloadrust-65445a571c11f07f4ca1ed0f63bad247ae295bd0.tar.gz
rust-65445a571c11f07f4ca1ed0f63bad247ae295bd0.zip
Auto merge of #102471 - Dylan-DPC:rollup-ij3okjt, r=Dylan-DPC
Rollup of 7 pull requests

Successful merges:

 - #102336 (Fix associated type bindings with anon const in GAT position)
 - #102342 (Add negation methods for signed non-zero integers.)
 - #102385 (Don't export `__heap_base` and `__data_end` on wasm32-wasi.)
 - #102435 (Improve example of Iterator::reduce)
 - #102436 (rustdoc: clean up "normalize.css 8" input override CSS)
 - #102452 (fix minor ungrammatical sentence)
 - #102455 (Use let-chaining in `WhileTrue::check_expr`.)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
-rw-r--r--compiler/rustc_codegen_ssa/src/back/linker.rs10
-rw-r--r--compiler/rustc_hir_analysis/src/collect/type_of.rs117
-rw-r--r--compiler/rustc_lint/src/builtin.rs46
-rw-r--r--library/core/src/convert/mod.rs2
-rw-r--r--library/core/src/iter/traits/iterator.rs19
-rw-r--r--library/core/src/num/nonzero.rs154
-rw-r--r--src/librustdoc/html/static/css/rustdoc.css21
-rw-r--r--src/librustdoc/html/static/css/settings.css3
-rw-r--r--src/test/ui/generic-associated-types/issue-102333.rs15
9 files changed, 301 insertions, 86 deletions
diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs
index e0bd7a33f73..061053ef2ac 100644
--- a/compiler/rustc_codegen_ssa/src/back/linker.rs
+++ b/compiler/rustc_codegen_ssa/src/back/linker.rs
@@ -1320,10 +1320,12 @@ impl<'a> Linker for WasmLd<'a> {
 
         // LLD will hide these otherwise-internal symbols since it only exports
         // symbols explicitly passed via the `--export` flags above and hides all
-        // others. Various bits and pieces of tooling use this, so be sure these
-        // symbols make their way out of the linker as well.
-        self.cmd.arg("--export=__heap_base");
-        self.cmd.arg("--export=__data_end");
+        // others. Various bits and pieces of wasm32-unknown-unknown tooling use
+        // this, so be sure these symbols make their way out of the linker as well.
+        if self.sess.target.os == "unknown" {
+            self.cmd.arg("--export=__heap_base");
+            self.cmd.arg("--export=__data_end");
+        }
     }
 
     fn subsystem(&mut self, _subsystem: &str) {}
diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs
index 24fb0b1fd26..f8a62c84910 100644
--- a/compiler/rustc_hir_analysis/src/collect/type_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs
@@ -333,7 +333,12 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
                     find_opaque_ty_constraints_for_tait(tcx, def_id)
                 }
                 // Opaque types desugared from `impl Trait`.
-                ItemKind::OpaqueTy(OpaqueTy { origin: hir::OpaqueTyOrigin::FnReturn(owner) | hir::OpaqueTyOrigin::AsyncFn(owner), in_trait, .. }) => {
+                ItemKind::OpaqueTy(OpaqueTy {
+                    origin:
+                        hir::OpaqueTyOrigin::FnReturn(owner) | hir::OpaqueTyOrigin::AsyncFn(owner),
+                    in_trait,
+                    ..
+                }) => {
                     if in_trait {
                         span_bug!(item.span, "impl-trait in trait has no default")
                     } else {
@@ -378,7 +383,9 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
 
         Node::Field(field) => icx.to_ty(field.ty),
 
-        Node::Expr(&Expr { kind: ExprKind::Closure{..}, .. }) => tcx.typeck(def_id).node_type(hir_id),
+        Node::Expr(&Expr { kind: ExprKind::Closure { .. }, .. }) => {
+            tcx.typeck(def_id).node_type(hir_id)
+        }
 
         Node::AnonConst(_) if let Some(param) = tcx.opt_const_param_of(def_id) => {
             // We defer to `type_of` of the corresponding parameter
@@ -410,40 +417,91 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
                 | Node::Item(&Item { kind: ItemKind::GlobalAsm(asm), .. })
                     if asm.operands.iter().any(|(op, _op_sp)| match op {
                         hir::InlineAsmOperand::Const { anon_const }
-                        | hir::InlineAsmOperand::SymFn { anon_const } => anon_const.hir_id == hir_id,
+                        | hir::InlineAsmOperand::SymFn { anon_const } => {
+                            anon_const.hir_id == hir_id
+                        }
                         _ => false,
                     }) =>
                 {
                     tcx.typeck(def_id).node_type(hir_id)
                 }
 
-                Node::Variant(Variant { disr_expr: Some(ref e), .. }) if e.hir_id == hir_id => tcx
-                    .adt_def(tcx.hir().get_parent_item(hir_id))
-                    .repr()
-                    .discr_type()
-                    .to_ty(tcx),
+                Node::Variant(Variant { disr_expr: Some(ref e), .. }) if e.hir_id == hir_id => {
+                    tcx.adt_def(tcx.hir().get_parent_item(hir_id)).repr().discr_type().to_ty(tcx)
+                }
 
-                Node::TypeBinding(binding @ &TypeBinding { hir_id: binding_id, ..  })
-                    if let Node::TraitRef(trait_ref) = tcx.hir().get(
-                        tcx.hir().get_parent_node(binding_id)
-                    ) =>
+                Node::TypeBinding(
+                    binding @ &TypeBinding {
+                        hir_id: binding_id,
+                        kind: TypeBindingKind::Equality { term: Term::Const(ref e) },
+                        ..
+                    },
+                ) if let Node::TraitRef(trait_ref) =
+                    tcx.hir().get(tcx.hir().get_parent_node(binding_id))
+                    && e.hir_id == hir_id =>
                 {
-                  let Some(trait_def_id) = trait_ref.trait_def_id() else {
-                    return tcx.ty_error_with_message(DUMMY_SP, "Could not find trait");
-                  };
-                  let assoc_items = tcx.associated_items(trait_def_id);
-                  let assoc_item = assoc_items.find_by_name_and_kind(
-                    tcx, binding.ident, ty::AssocKind::Const, def_id.to_def_id(),
-                  );
-                  if let Some(assoc_item) = assoc_item {
-                    tcx.type_of(assoc_item.def_id)
-                  } else {
-                      // FIXME(associated_const_equality): add a useful error message here.
-                      tcx.ty_error_with_message(
-                        DUMMY_SP,
-                        "Could not find associated const on trait",
-                    )
-                  }
+                    let Some(trait_def_id) = trait_ref.trait_def_id() else {
+                        return tcx.ty_error_with_message(DUMMY_SP, "Could not find trait");
+                    };
+                    let assoc_items = tcx.associated_items(trait_def_id);
+                    let assoc_item = assoc_items.find_by_name_and_kind(
+                        tcx,
+                        binding.ident,
+                        ty::AssocKind::Const,
+                        def_id.to_def_id(),
+                    );
+                    if let Some(assoc_item) = assoc_item {
+                        tcx.type_of(assoc_item.def_id)
+                    } else {
+                        // FIXME(associated_const_equality): add a useful error message here.
+                        tcx.ty_error_with_message(
+                            DUMMY_SP,
+                            "Could not find associated const on trait",
+                        )
+                    }
+                }
+
+                Node::TypeBinding(
+                    binding @ &TypeBinding { hir_id: binding_id, gen_args, ref kind, .. },
+                ) if let Node::TraitRef(trait_ref) =
+                    tcx.hir().get(tcx.hir().get_parent_node(binding_id))
+                    && let Some((idx, _)) =
+                        gen_args.args.iter().enumerate().find(|(_, arg)| {
+                            if let GenericArg::Const(ct) = arg {
+                                ct.value.hir_id == hir_id
+                            } else {
+                                false
+                            }
+                        }) =>
+                {
+                    let Some(trait_def_id) = trait_ref.trait_def_id() else {
+                        return tcx.ty_error_with_message(DUMMY_SP, "Could not find trait");
+                    };
+                    let assoc_items = tcx.associated_items(trait_def_id);
+                    let assoc_item = assoc_items.find_by_name_and_kind(
+                        tcx,
+                        binding.ident,
+                        match kind {
+                            // I think `<A: T>` type bindings requires that `A` is a type
+                            TypeBindingKind::Constraint { .. }
+                            | TypeBindingKind::Equality { term: Term::Ty(..) } => {
+                                ty::AssocKind::Type
+                            }
+                            TypeBindingKind::Equality { term: Term::Const(..) } => {
+                                ty::AssocKind::Const
+                            }
+                        },
+                        def_id.to_def_id(),
+                    );
+                    if let Some(assoc_item) = assoc_item {
+                        tcx.type_of(tcx.generics_of(assoc_item.def_id).params[idx].def_id)
+                    } else {
+                        // FIXME(associated_const_equality): add a useful error message here.
+                        tcx.ty_error_with_message(
+                            DUMMY_SP,
+                            "Could not find associated const on trait",
+                        )
+                    }
                 }
 
                 Node::GenericParam(&GenericParam {
@@ -452,8 +510,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
                     ..
                 }) if ct.hir_id == hir_id => tcx.type_of(tcx.hir().local_def_id(param_hir_id)),
 
-                x =>
-                  tcx.ty_error_with_message(
+                x => tcx.ty_error_with_message(
                     DUMMY_SP,
                     &format!("unexpected const parent in type_of(): {x:?}"),
                 ),
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index 146c4971348..5d69c35ebfc 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -97,30 +97,28 @@ fn pierce_parens(mut expr: &ast::Expr) -> &ast::Expr {
 
 impl EarlyLintPass for WhileTrue {
     fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) {
-        if let ast::ExprKind::While(cond, _, label) = &e.kind {
-            if let ast::ExprKind::Lit(ref lit) = pierce_parens(cond).kind {
-                if let ast::LitKind::Bool(true) = lit.kind {
-                    if !lit.span.from_expansion() {
-                        let condition_span = e.span.with_hi(cond.span.hi());
-                        cx.struct_span_lint(WHILE_TRUE, condition_span, |lint| {
-                            lint.build(fluent::lint::builtin_while_true)
-                                .span_suggestion_short(
-                                    condition_span,
-                                    fluent::lint::suggestion,
-                                    format!(
-                                        "{}loop",
-                                        label.map_or_else(String::new, |label| format!(
-                                            "{}: ",
-                                            label.ident,
-                                        ))
-                                    ),
-                                    Applicability::MachineApplicable,
-                                )
-                                .emit();
-                        })
-                    }
-                }
-            }
+        if let ast::ExprKind::While(cond, _, label) = &e.kind
+            && let ast::ExprKind::Lit(ref lit) = pierce_parens(cond).kind
+            && let ast::LitKind::Bool(true) = lit.kind
+            && !lit.span.from_expansion()
+        {
+            let condition_span = e.span.with_hi(cond.span.hi());
+            cx.struct_span_lint(WHILE_TRUE, condition_span, |lint| {
+                lint.build(fluent::lint::builtin_while_true)
+                    .span_suggestion_short(
+                        condition_span,
+                        fluent::lint::suggestion,
+                        format!(
+                            "{}loop",
+                            label.map_or_else(String::new, |label| format!(
+                                "{}: ",
+                                label.ident,
+                            ))
+                        ),
+                        Applicability::MachineApplicable,
+                    )
+                    .emit();
+            })
         }
     }
 }
diff --git a/library/core/src/convert/mod.rs b/library/core/src/convert/mod.rs
index c42adda8da5..6f23b9d908d 100644
--- a/library/core/src/convert/mod.rs
+++ b/library/core/src/convert/mod.rs
@@ -440,7 +440,7 @@ pub trait TryInto<T>: Sized {
 ///
 ///     fn try_from(value: i32) -> Result<Self, Self::Error> {
 ///         if value <= 0 {
-///             Err("GreaterThanZero only accepts value superior than zero!")
+///             Err("GreaterThanZero only accepts values greater than zero!")
 ///         } else {
 ///             Ok(GreaterThanZero(value))
 ///         }
diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs
index e26920b25cc..f6e6732b0e3 100644
--- a/library/core/src/iter/traits/iterator.rs
+++ b/library/core/src/iter/traits/iterator.rs
@@ -2431,22 +2431,13 @@ pub trait Iterator {
     ///
     /// # Example
     ///
-    /// Find the maximum value:
-    ///
     /// ```
-    /// fn find_max<I>(iter: I) -> Option<I::Item>
-    ///     where I: Iterator,
-    ///           I::Item: Ord,
-    /// {
-    ///     iter.reduce(|accum, item| {
-    ///         if accum >= item { accum } else { item }
-    ///     })
-    /// }
-    /// let a = [10, 20, 5, -23, 0];
-    /// let b: [u32; 0] = [];
+    /// let reduced: i32 = (1..10).reduce(|acc, e| acc + e).unwrap();
+    /// assert_eq!(reduced, 45);
     ///
-    /// assert_eq!(find_max(a.iter()), Some(&20));
-    /// assert_eq!(find_max(b.iter()), None);
+    /// // Which is equivalent to doing it with `fold`:
+    /// let folded: i32 = (1..10).fold(0, |acc, e| acc + e);
+    /// assert_eq!(reduced, folded);
     /// ```
     #[inline]
     #[stable(feature = "iterator_fold_self", since = "1.51.0")]
diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs
index 532a09736a7..da402d66502 100644
--- a/library/core/src/num/nonzero.rs
+++ b/library/core/src/num/nonzero.rs
@@ -721,6 +721,160 @@ macro_rules! nonzero_signed_operations {
                     // SAFETY: absolute value of nonzero cannot yield zero values.
                     unsafe { $Uty::new_unchecked(self.get().unsigned_abs()) }
                 }
+
+                /// Returns `true` if `self` is negative and `false` if the
+                /// number is positive.
+                ///
+                /// # Example
+                ///
+                /// ```
+                /// #![feature(nonzero_negation_ops)]
+                ///
+                #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
+                /// # fn main() { test().unwrap(); }
+                /// # fn test() -> Option<()> {
+                #[doc = concat!("let pos_five = ", stringify!($Ty), "::new(5)?;")]
+                #[doc = concat!("let neg_five = ", stringify!($Ty), "::new(-5)?;")]
+                ///
+                /// assert!(neg_five.is_negative());
+                /// assert!(!pos_five.is_negative());
+                /// # Some(())
+                /// # }
+                /// ```
+                #[must_use]
+                #[inline]
+                #[unstable(feature = "nonzero_negation_ops", issue = "102443")]
+                pub const fn is_negative(self) -> bool {
+                    self.get().is_negative()
+                }
+
+                /// Checked negation. Computes `-self`, returning `None` if `self == i32::MIN`.
+                ///
+                /// # Example
+                ///
+                /// ```
+                /// #![feature(nonzero_negation_ops)]
+                ///
+                #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
+                /// # fn main() { test().unwrap(); }
+                /// # fn test() -> Option<()> {
+                #[doc = concat!("let pos_five = ", stringify!($Ty), "::new(5)?;")]
+                #[doc = concat!("let neg_five = ", stringify!($Ty), "::new(-5)?;")]
+                #[doc = concat!("let min = ", stringify!($Ty), "::new(",
+                                stringify!($Int), "::MIN)?;")]
+                ///
+                /// assert_eq!(pos_five.checked_neg(), Some(neg_five));
+                /// assert_eq!(min.checked_neg(), None);
+                /// # Some(())
+                /// # }
+                /// ```
+                #[inline]
+                #[unstable(feature = "nonzero_negation_ops", issue = "102443")]
+                pub const fn checked_neg(self) -> Option<$Ty> {
+                    if let Some(result) = self.get().checked_neg() {
+                        // SAFETY: negation of nonzero cannot yield zero values.
+                        return Some(unsafe { $Ty::new_unchecked(result) });
+                    }
+                    None
+                }
+
+                /// Negates self, overflowing if this is equal to the minimum value.
+                ///
+                #[doc = concat!("See [`", stringify!($Int), "::overflowing_neg`]")]
+                /// for documentation on overflow behaviour.
+                ///
+                /// # Example
+                ///
+                /// ```
+                /// #![feature(nonzero_negation_ops)]
+                ///
+                #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
+                /// # fn main() { test().unwrap(); }
+                /// # fn test() -> Option<()> {
+                #[doc = concat!("let pos_five = ", stringify!($Ty), "::new(5)?;")]
+                #[doc = concat!("let neg_five = ", stringify!($Ty), "::new(-5)?;")]
+                #[doc = concat!("let min = ", stringify!($Ty), "::new(",
+                                stringify!($Int), "::MIN)?;")]
+                ///
+                /// assert_eq!(pos_five.overflowing_neg(), (neg_five, false));
+                /// assert_eq!(min.overflowing_neg(), (min, true));
+                /// # Some(())
+                /// # }
+                /// ```
+                #[inline]
+                #[unstable(feature = "nonzero_negation_ops", issue = "102443")]
+                pub const fn overflowing_neg(self) -> ($Ty, bool) {
+                    let (result, overflow) = self.get().overflowing_neg();
+                    // SAFETY: negation of nonzero cannot yield zero values.
+                    ((unsafe { $Ty::new_unchecked(result) }), overflow)
+                }
+
+                /// Saturating negation. Computes `-self`, returning `MAX` if
+                /// `self == i32::MIN` instead of overflowing.
+                ///
+                /// # Example
+                ///
+                /// ```
+                /// #![feature(nonzero_negation_ops)]
+                ///
+                #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
+                /// # fn main() { test().unwrap(); }
+                /// # fn test() -> Option<()> {
+                #[doc = concat!("let pos_five = ", stringify!($Ty), "::new(5)?;")]
+                #[doc = concat!("let neg_five = ", stringify!($Ty), "::new(-5)?;")]
+                #[doc = concat!("let min = ", stringify!($Ty), "::new(",
+                                stringify!($Int), "::MIN)?;")]
+                #[doc = concat!("let min_plus_one = ", stringify!($Ty), "::new(",
+                                stringify!($Int), "::MIN + 1)?;")]
+                #[doc = concat!("let max = ", stringify!($Ty), "::new(",
+                                stringify!($Int), "::MAX)?;")]
+                ///
+                /// assert_eq!(pos_five.saturating_neg(), neg_five);
+                /// assert_eq!(min.saturating_neg(), max);
+                /// assert_eq!(max.saturating_neg(), min_plus_one);
+                /// # Some(())
+                /// # }
+                /// ```
+                #[inline]
+                #[unstable(feature = "nonzero_negation_ops", issue = "102443")]
+                pub const fn saturating_neg(self) -> $Ty {
+                    if let Some(result) = self.checked_neg() {
+                        return result;
+                    }
+                    $Ty::MAX
+                }
+
+                /// Wrapping (modular) negation. Computes `-self`, wrapping around at the boundary
+                /// of the type.
+                ///
+                #[doc = concat!("See [`", stringify!($Int), "::wrapping_neg`]")]
+                /// for documentation on overflow behaviour.
+                ///
+                /// # Example
+                ///
+                /// ```
+                /// #![feature(nonzero_negation_ops)]
+                ///
+                #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
+                /// # fn main() { test().unwrap(); }
+                /// # fn test() -> Option<()> {
+                #[doc = concat!("let pos_five = ", stringify!($Ty), "::new(5)?;")]
+                #[doc = concat!("let neg_five = ", stringify!($Ty), "::new(-5)?;")]
+                #[doc = concat!("let min = ", stringify!($Ty), "::new(",
+                                stringify!($Int), "::MIN)?;")]
+                ///
+                /// assert_eq!(pos_five.wrapping_neg(), neg_five);
+                /// assert_eq!(min.wrapping_neg(), min);
+                /// # Some(())
+                /// # }
+                /// ```
+                #[inline]
+                #[unstable(feature = "nonzero_negation_ops", issue = "102443")]
+                pub const fn wrapping_neg(self) -> $Ty {
+                    let result = self.get().wrapping_neg();
+                    // SAFETY: negation of nonzero cannot yield zero values.
+                    unsafe { $Ty::new_unchecked(result) }
+                }
             }
         )+
     }
diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css
index 0ea6d9c38b6..7bc8fbb1ea7 100644
--- a/src/librustdoc/html/static/css/rustdoc.css
+++ b/src/librustdoc/html/static/css/rustdoc.css
@@ -191,6 +191,7 @@ h4.code-header {
 	position: relative;
 }
 
+#crate-search,
 h1, h2, h3, h4, h5, h6,
 .sidebar,
 .mobile-topbar,
@@ -304,16 +305,6 @@ summary {
 
 /* Fix some style changes due to normalize.css 8 */
 
-button,
-input,
-optgroup,
-select,
-textarea {
-	color: inherit;
-	font: inherit;
-	margin: 0;
-}
-
 button {
 	/* Buttons on Safari have different default padding than other platforms. Make them the same. */
 	padding: 1px 6px;
@@ -887,6 +878,9 @@ table,
 	/* Removes default arrow from firefox */
 	text-indent: 0.01px;
 	background-color: var(--main-background-color);
+	color: inherit;
+	line-height: 1.5;
+	font-weight: 500;
 }
 /* cancel stylistic differences in padding in firefox
 for "appearance: none"-style (or equivalent) <select>s */
@@ -1363,6 +1357,8 @@ pre.rust {
 	border: 0;
 	border-top: 2px solid;
 	flex: 1;
+	line-height: 1.5;
+	color: inherit;
 }
 
 #titles > button > div.count {
@@ -1380,7 +1376,6 @@ pre.rust {
 	position: sticky;
 	top: 0;
 	left: 0;
-	font-weight: bold;
 	font-size: 1.25rem;
 	border-bottom: 1px solid;
 	display: flex;
@@ -1400,6 +1395,8 @@ pre.rust {
 	margin-bottom: 6px;
 }
 #sidebar-toggle > button {
+	font-size: inherit;
+	font-weight: bold;
 	background: none;
 	color: inherit;
 	cursor: pointer;
@@ -1428,6 +1425,7 @@ pre.rust {
 	border: 1px solid var(--border-color);
 	border-radius: 2px;
 	cursor: pointer;
+	line-height: 1.5;
 }
 
 #settings-menu > a, #help-button > button {
@@ -1887,7 +1885,6 @@ in storage.js plus the media query with (min-width: 701px)
 		border-top-right-radius: 3px;
 		border-bottom-right-radius: 3px;
 		cursor: pointer;
-		font-weight: bold;
 		border: 1px solid;
 		border-left: 0;
 	}
diff --git a/src/librustdoc/html/static/css/settings.css b/src/librustdoc/html/static/css/settings.css
index e82ec042637..821c4e978e8 100644
--- a/src/librustdoc/html/static/css/settings.css
+++ b/src/librustdoc/html/static/css/settings.css
@@ -12,7 +12,8 @@
 	margin-right: 0.3em;
 	height: 1.2rem;
 	width: 1.2rem;
-	border: 1px solid;
+	color: inherit;
+	border: 1px solid currentColor;
 	outline: none;
 	-webkit-appearance: none;
 	cursor: pointer;
diff --git a/src/test/ui/generic-associated-types/issue-102333.rs b/src/test/ui/generic-associated-types/issue-102333.rs
new file mode 100644
index 00000000000..6c72563322f
--- /dev/null
+++ b/src/test/ui/generic-associated-types/issue-102333.rs
@@ -0,0 +1,15 @@
+// check-pass
+
+trait A {
+    type T: B<U<1i32> = ()>;
+}
+
+trait B {
+    type U<const C: i32>;
+}
+
+fn f<T: A>() {
+    let _: <<T as A>::T as B>::U<1i32> = ();
+}
+
+fn main() {}