From f580357863c1689ea1903b9570092a53f85a5c44 Mon Sep 17 00:00:00 2001 From: Jules Bertholet Date: Fri, 21 Nov 2025 11:43:53 -0500 Subject: [PATCH] Handle cycles when checking impl candidates for `doc(hidden)` Fixes https://github.com/rust-lang/rust/issues/149092 --- .../traits/fulfillment_errors.rs | 13 +++++++--- compiler/rustc_trait_selection/src/lib.rs | 1 + .../ui/suggestions/auxiliary/hidden-struct.rs | 3 +++ .../dont-suggest-foreign-doc-hidden.rs | 5 ++++ .../dont-suggest-foreign-doc-hidden.stderr | 26 +++++++++++++++++-- 5 files changed, 43 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index d2f2c92dda080..0f5607dd7fecb 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -1,12 +1,13 @@ // ignore-tidy-filelength use core::ops::ControlFlow; use std::borrow::Cow; +use std::collections::hash_set; use std::path::PathBuf; use rustc_abi::ExternAbi; use rustc_ast::ast::LitKind; use rustc_ast::{LitIntType, TraitObjectSyntax}; -use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::unord::UnordSet; use rustc_errors::codes::*; use rustc_errors::{ @@ -1956,11 +1957,17 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { if self.tcx.visibility(did).is_accessible_from(body_def_id, self.tcx) { // don't suggest foreign `#[doc(hidden)]` types if !did.is_local() { - while let Some(parent) = parent_map.get(&did) { + let mut previously_seen_dids: FxHashSet = Default::default(); + previously_seen_dids.insert(did); + while let Some(&parent) = parent_map.get(&did) + && let hash_set::Entry::Vacant(v) = + previously_seen_dids.entry(parent) + { if self.tcx.is_doc_hidden(did) { return false; } - did = *parent; + v.insert(); + did = parent; } } true diff --git a/compiler/rustc_trait_selection/src/lib.rs b/compiler/rustc_trait_selection/src/lib.rs index c5dfaa2a60d87..0184b2ccde784 100644 --- a/compiler/rustc_trait_selection/src/lib.rs +++ b/compiler/rustc_trait_selection/src/lib.rs @@ -17,6 +17,7 @@ #![feature(associated_type_defaults)] #![feature(box_patterns)] #![feature(default_field_values)] +#![feature(hash_set_entry)] #![feature(if_let_guard)] #![feature(iter_intersperse)] #![feature(iterator_try_reduce)] diff --git a/tests/ui/suggestions/auxiliary/hidden-struct.rs b/tests/ui/suggestions/auxiliary/hidden-struct.rs index 1f495a9f2224a..ee24389bebd7c 100644 --- a/tests/ui/suggestions/auxiliary/hidden-struct.rs +++ b/tests/ui/suggestions/auxiliary/hidden-struct.rs @@ -33,3 +33,6 @@ impl Marker for hidden::Foo {} impl Marker for hidden1::Bar {} impl Marker for Baz {} impl Marker for Quux {} + + +pub use crate as library; diff --git a/tests/ui/suggestions/dont-suggest-foreign-doc-hidden.rs b/tests/ui/suggestions/dont-suggest-foreign-doc-hidden.rs index a83e496f2703d..0716e4e2e143b 100644 --- a/tests/ui/suggestions/dont-suggest-foreign-doc-hidden.rs +++ b/tests/ui/suggestions/dont-suggest-foreign-doc-hidden.rs @@ -21,7 +21,12 @@ pub fn test4(_: Quux) {} fn test5() {} +fn test6() {} + fn main() { test5::(); //~^ ERROR [E0277] + + test6::(); + //~^ ERROR [E0277] } diff --git a/tests/ui/suggestions/dont-suggest-foreign-doc-hidden.stderr b/tests/ui/suggestions/dont-suggest-foreign-doc-hidden.stderr index e0444c93eeece..a111d0e5aa95a 100644 --- a/tests/ui/suggestions/dont-suggest-foreign-doc-hidden.stderr +++ b/tests/ui/suggestions/dont-suggest-foreign-doc-hidden.stderr @@ -38,7 +38,7 @@ LL + use hidden_struct::Quux; | error[E0277]: the trait bound `i32: Marker` is not satisfied - --> $DIR/dont-suggest-foreign-doc-hidden.rs:25:13 + --> $DIR/dont-suggest-foreign-doc-hidden.rs:27:13 | LL | test5::(); | ^^^ the trait `Marker` is not implemented for `i32` @@ -59,7 +59,29 @@ note: required by a bound in `test5` LL | fn test5() {} | ^^^^^^^^^^^^^^^^^^^^^ required by this bound in `test5` -error: aborting due to 5 previous errors +error[E0277]: the trait bound `i32: Marker` is not satisfied + --> $DIR/dont-suggest-foreign-doc-hidden.rs:30:13 + | +LL | test6::(); + | ^^^ the trait `Marker` is not implemented for `i32` + | +help: the following other types implement trait `Marker` + --> $DIR/auxiliary/hidden-struct.rs:31:1 + | +LL | impl Marker for Option {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Option` +... +LL | impl Marker for Baz {} + | ^^^^^^^^^^^^^^^^^^^ `Baz` +LL | impl Marker for Quux {} + | ^^^^^^^^^^^^^^^^^^^^ `Quux` +note: required by a bound in `test6` + --> $DIR/dont-suggest-foreign-doc-hidden.rs:24:13 + | +LL | fn test6() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `test6` + +error: aborting due to 6 previous errors Some errors have detailed explanations: E0277, E0412. For more information about an error, try `rustc --explain E0277`.