From 2f3d599989883d0be932df3dceed65a6ec3274f8 Mon Sep 17 00:00:00 2001 From: Jeremy Smart Date: Wed, 25 Jun 2025 23:46:16 -0400 Subject: [PATCH 1/3] avoid suggesting traits from private dependencies --- .../rustc_hir_typeck/src/method/suggest.rs | 3 ++- library/rustc-std-workspace-core/Cargo.toml | 2 ++ .../dont-suggest-private-dependencies.rs | 15 ++++++++++++++ .../dont-suggest-private-dependencies.stderr | 20 +++++++++++++++++++ 4 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 tests/ui/typeck/dont-suggest-private-dependencies.rs create mode 100644 tests/ui/typeck/dont-suggest-private-dependencies.stderr diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index b35aef13c5255..646ba10541bec 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -3477,9 +3477,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &self, err: &mut Diag<'_>, item_name: Ident, - valid_out_of_scope_traits: Vec, + mut valid_out_of_scope_traits: Vec, explain: bool, ) -> bool { + valid_out_of_scope_traits.retain(|id| !self.tcx.is_private_dep(id.krate)); if !valid_out_of_scope_traits.is_empty() { let mut candidates = valid_out_of_scope_traits; candidates.sort_by_key(|id| self.tcx.def_path_str(id)); diff --git a/library/rustc-std-workspace-core/Cargo.toml b/library/rustc-std-workspace-core/Cargo.toml index bd318fc2f9e9c..769ca4486235a 100644 --- a/library/rustc-std-workspace-core/Cargo.toml +++ b/library/rustc-std-workspace-core/Cargo.toml @@ -1,3 +1,5 @@ +cargo-features = ["public-dependency"] + [package] name = "rustc-std-workspace-core" version = "1.99.0" diff --git a/tests/ui/typeck/dont-suggest-private-dependencies.rs b/tests/ui/typeck/dont-suggest-private-dependencies.rs new file mode 100644 index 0000000000000..807326a67ed0e --- /dev/null +++ b/tests/ui/typeck/dont-suggest-private-dependencies.rs @@ -0,0 +1,15 @@ +// Don't suggest importing a function from a private dependency. + +struct VecReader(Vec); + +impl std::io::Read for VecReader { + fn read(&mut self, buf: &mut [u8]) -> std::io::Result { + self.0.read(buf) + //~^ ERROR no method named `read` found for struct `Vec` + } +} + +fn main() { + let _ = u8::cast_from_lossy(9); + //~^ ERROR no function or associated item named `cast_from_lossy` found for type `u8` +} diff --git a/tests/ui/typeck/dont-suggest-private-dependencies.stderr b/tests/ui/typeck/dont-suggest-private-dependencies.stderr new file mode 100644 index 0000000000000..83964c19ffefc --- /dev/null +++ b/tests/ui/typeck/dont-suggest-private-dependencies.stderr @@ -0,0 +1,20 @@ +error[E0599]: no method named `read` found for struct `Vec` in the current scope + --> $DIR/dont-suggest-private-dependencies.rs:7:16 + | +LL | self.0.read(buf) + | ^^^^ + | +help: there is a method `read_at` with a similar name + | +LL | self.0.read_at(buf) + | +++ + +error[E0599]: no function or associated item named `cast_from_lossy` found for type `u8` in the current scope + --> $DIR/dont-suggest-private-dependencies.rs:13:17 + | +LL | let _ = u8::cast_from_lossy(9); + | ^^^^^^^^^^^^^^^ function or associated item not found in `u8` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0599`. From a9d5951b7fd5684abd989eb88d1aa920151a2fb6 Mon Sep 17 00:00:00 2001 From: Jeremy Smart Date: Thu, 26 Jun 2025 18:57:12 -0400 Subject: [PATCH 2/3] make test more reliable, rename all_traits -> all_traits_including_private --- compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs | 2 +- compiler/rustc_hir_typeck/src/method/suggest.rs | 6 +++--- compiler/rustc_middle/src/ty/context.rs | 2 +- compiler/rustc_smir/src/rustc_smir/context.rs | 6 +++++- .../src/error_reporting/traits/fulfillment_errors.rs | 2 +- src/librustdoc/clean/blanket_impl.rs | 2 +- src/librustdoc/core.rs | 2 +- tests/ui/typeck/dont-suggest-private-dependencies.rs | 5 +++++ tests/ui/typeck/dont-suggest-private-dependencies.stderr | 4 ++-- 9 files changed, 20 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index baf3b9b5bc9e0..51cd1b7704d83 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -1588,7 +1588,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { &infcx_ }; - tcx.all_traits() + tcx.all_traits_including_private() .filter(|trait_def_id| { // Consider only traits with the associated type tcx.associated_items(*trait_def_id) diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 646ba10541bec..f446bc468e488 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -1725,7 +1725,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if unsatisfied_predicates.is_empty() // ...or if we already suggested that name because of `rustc_confusable` annotation && Some(similar_candidate.name()) != confusable_suggested - // and if the we aren't in an expansion. + // and if we aren't in an expansion. && !span.from_expansion() { self.find_likely_intended_associated_item( @@ -3480,7 +3480,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { mut valid_out_of_scope_traits: Vec, explain: bool, ) -> bool { - valid_out_of_scope_traits.retain(|id| !self.tcx.is_private_dep(id.krate)); + valid_out_of_scope_traits.retain(|id| self.tcx.is_user_visible_dep(id.krate)); if !valid_out_of_scope_traits.is_empty() { let mut candidates = valid_out_of_scope_traits; candidates.sort_by_key(|id| self.tcx.def_path_str(id)); @@ -4385,7 +4385,7 @@ pub(crate) struct TraitInfo { /// Retrieves all traits in this crate and any dependent crates, /// and wraps them into `TraitInfo` for custom sorting. pub(crate) fn all_traits(tcx: TyCtxt<'_>) -> Vec { - tcx.all_traits().map(|def_id| TraitInfo { def_id }).collect() + tcx.all_traits_including_private().map(|def_id| TraitInfo { def_id }).collect() } fn print_disambiguation_help<'tcx>( diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index aa5355551ce06..f8b6a30682bc7 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -2318,7 +2318,7 @@ impl<'tcx> TyCtxt<'tcx> { } /// All traits in the crate graph, including those not visible to the user. - pub fn all_traits(self) -> impl Iterator { + pub fn all_traits_including_private(self) -> impl Iterator { iter::once(LOCAL_CRATE) .chain(self.crates(()).iter().copied()) .flat_map(move |cnum| self.traits(cnum).iter().copied()) diff --git a/compiler/rustc_smir/src/rustc_smir/context.rs b/compiler/rustc_smir/src/rustc_smir/context.rs index baa4c0681e806..3fa83cfc6a08c 100644 --- a/compiler/rustc_smir/src/rustc_smir/context.rs +++ b/compiler/rustc_smir/src/rustc_smir/context.rs @@ -130,7 +130,11 @@ impl<'tcx> SmirCtxt<'tcx> { pub fn all_trait_decls(&self) -> stable_mir::TraitDecls { let mut tables = self.0.borrow_mut(); - tables.tcx.all_traits().map(|trait_def_id| tables.trait_def(trait_def_id)).collect() + tables + .tcx + .all_traits_including_private() + .map(|trait_def_id| tables.trait_def(trait_def_id)) + .collect() } pub fn trait_decls(&self, crate_num: CrateNum) -> stable_mir::TraitDecls { 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 0c88bd3dcbc54..db2517a837948 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 @@ -1850,7 +1850,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let trait_def_id = trait_pred.def_id(); let trait_name = self.tcx.item_name(trait_def_id); let crate_name = self.tcx.crate_name(trait_def_id.krate); - if let Some(other_trait_def_id) = self.tcx.all_traits().find(|def_id| { + if let Some(other_trait_def_id) = self.tcx.all_traits_including_private().find(|def_id| { trait_name == self.tcx.item_name(trait_def_id) && trait_def_id.krate != def_id.krate && crate_name == self.tcx.crate_name(def_id.krate) diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs index c889f52b789a4..11d5b472d738b 100644 --- a/src/librustdoc/clean/blanket_impl.rs +++ b/src/librustdoc/clean/blanket_impl.rs @@ -23,7 +23,7 @@ pub(crate) fn synthesize_blanket_impls( let ty = tcx.type_of(item_def_id); let mut blanket_impls = Vec::new(); - for trait_def_id in tcx.all_traits() { + for trait_def_id in tcx.visible_traits() { if !cx.cache.effective_visibilities.is_reachable(tcx, trait_def_id) || cx.generated_synthetics.contains(&(ty.skip_binder(), trait_def_id)) { diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index cf3c4ac97af63..bd57bb21e639b 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -353,7 +353,7 @@ pub(crate) fn run_global_ctxt( rustc_passes::stability::check_unused_or_stable_features(tcx); let auto_traits = - tcx.all_traits().filter(|&trait_def_id| tcx.trait_is_auto(trait_def_id)).collect(); + tcx.visible_traits().filter(|&trait_def_id| tcx.trait_is_auto(trait_def_id)).collect(); let mut ctxt = DocContext { tcx, diff --git a/tests/ui/typeck/dont-suggest-private-dependencies.rs b/tests/ui/typeck/dont-suggest-private-dependencies.rs index 807326a67ed0e..9edee718badd7 100644 --- a/tests/ui/typeck/dont-suggest-private-dependencies.rs +++ b/tests/ui/typeck/dont-suggest-private-dependencies.rs @@ -1,4 +1,9 @@ // Don't suggest importing a function from a private dependency. +// Issues: #138191, #142676 + +// Avoid suggesting traits from std-private deps +//@ forbid-output: compiler_builtins +//@ forbid-output: object struct VecReader(Vec); diff --git a/tests/ui/typeck/dont-suggest-private-dependencies.stderr b/tests/ui/typeck/dont-suggest-private-dependencies.stderr index 83964c19ffefc..c175c9367375b 100644 --- a/tests/ui/typeck/dont-suggest-private-dependencies.stderr +++ b/tests/ui/typeck/dont-suggest-private-dependencies.stderr @@ -1,5 +1,5 @@ error[E0599]: no method named `read` found for struct `Vec` in the current scope - --> $DIR/dont-suggest-private-dependencies.rs:7:16 + --> $DIR/dont-suggest-private-dependencies.rs:12:16 | LL | self.0.read(buf) | ^^^^ @@ -10,7 +10,7 @@ LL | self.0.read_at(buf) | +++ error[E0599]: no function or associated item named `cast_from_lossy` found for type `u8` in the current scope - --> $DIR/dont-suggest-private-dependencies.rs:13:17 + --> $DIR/dont-suggest-private-dependencies.rs:18:17 | LL | let _ = u8::cast_from_lossy(9); | ^^^^^^^^^^^^^^^ function or associated item not found in `u8` From 0bd439605d8d90d409d882b9c82a8331ab42f4ab Mon Sep 17 00:00:00 2001 From: Jeremy Smart Date: Thu, 26 Jun 2025 19:50:32 -0400 Subject: [PATCH 3/3] add aux-crates to test --- tests/ui/typeck/auxiliary/private-dep.rs | 3 +++ tests/ui/typeck/auxiliary/public-dep.rs | 11 +++++++++++ tests/ui/typeck/dont-suggest-private-dependencies.rs | 10 ++++++++++ .../typeck/dont-suggest-private-dependencies.stderr | 12 +++++++++--- 4 files changed, 33 insertions(+), 3 deletions(-) create mode 100644 tests/ui/typeck/auxiliary/private-dep.rs create mode 100644 tests/ui/typeck/auxiliary/public-dep.rs diff --git a/tests/ui/typeck/auxiliary/private-dep.rs b/tests/ui/typeck/auxiliary/private-dep.rs new file mode 100644 index 0000000000000..472b40ef6229d --- /dev/null +++ b/tests/ui/typeck/auxiliary/private-dep.rs @@ -0,0 +1,3 @@ +pub trait A { + fn foo() {} +} diff --git a/tests/ui/typeck/auxiliary/public-dep.rs b/tests/ui/typeck/auxiliary/public-dep.rs new file mode 100644 index 0000000000000..438692a1caa39 --- /dev/null +++ b/tests/ui/typeck/auxiliary/public-dep.rs @@ -0,0 +1,11 @@ +//@ aux-crate:priv:private_dep=private-dep.rs +//@ compile-flags: -Zunstable-options + +extern crate private_dep; +use private_dep::A; + +pub struct B; + +impl A for B { + fn foo() {} +} diff --git a/tests/ui/typeck/dont-suggest-private-dependencies.rs b/tests/ui/typeck/dont-suggest-private-dependencies.rs index 9edee718badd7..afac00c521310 100644 --- a/tests/ui/typeck/dont-suggest-private-dependencies.rs +++ b/tests/ui/typeck/dont-suggest-private-dependencies.rs @@ -5,6 +5,11 @@ //@ forbid-output: compiler_builtins //@ forbid-output: object +// Check a custom trait to withstand changes in above crates +//@ aux-crate:public_dep=public-dep.rs +//@ compile-flags: -Zunstable-options +//@ forbid-output: private_dep + struct VecReader(Vec); impl std::io::Read for VecReader { @@ -14,7 +19,12 @@ impl std::io::Read for VecReader { } } +extern crate public_dep; +use public_dep::B; + fn main() { let _ = u8::cast_from_lossy(9); //~^ ERROR no function or associated item named `cast_from_lossy` found for type `u8` + let _ = B::foo(); + //~^ ERROR no function or associated item named `foo` found for struct `B` } diff --git a/tests/ui/typeck/dont-suggest-private-dependencies.stderr b/tests/ui/typeck/dont-suggest-private-dependencies.stderr index c175c9367375b..0fb1e69c28a21 100644 --- a/tests/ui/typeck/dont-suggest-private-dependencies.stderr +++ b/tests/ui/typeck/dont-suggest-private-dependencies.stderr @@ -1,5 +1,5 @@ error[E0599]: no method named `read` found for struct `Vec` in the current scope - --> $DIR/dont-suggest-private-dependencies.rs:12:16 + --> $DIR/dont-suggest-private-dependencies.rs:17:16 | LL | self.0.read(buf) | ^^^^ @@ -10,11 +10,17 @@ LL | self.0.read_at(buf) | +++ error[E0599]: no function or associated item named `cast_from_lossy` found for type `u8` in the current scope - --> $DIR/dont-suggest-private-dependencies.rs:18:17 + --> $DIR/dont-suggest-private-dependencies.rs:26:17 | LL | let _ = u8::cast_from_lossy(9); | ^^^^^^^^^^^^^^^ function or associated item not found in `u8` -error: aborting due to 2 previous errors +error[E0599]: no function or associated item named `foo` found for struct `B` in the current scope + --> $DIR/dont-suggest-private-dependencies.rs:28:16 + | +LL | let _ = B::foo(); + | ^^^ function or associated item not found in `B` + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0599`.