Skip to content

Commit

Permalink
Add tcx.visible_traits() and use it for producing diagnostics
Browse files Browse the repository at this point in the history
Add an alternative to `tcx.all_traits()` that only shows traits that the
user might be able to use, for diagnostic purposes. With this available,
make use of it for diagnostics including associated type errors which
fixes [1].

Includes a few comment updates for related API.

Fixes: #135232 [1]
  • Loading branch information
tgross35 committed Jan 13, 2025
1 parent d96c647 commit 35ad309
Show file tree
Hide file tree
Showing 10 changed files with 41 additions and 19 deletions.
2 changes: 1 addition & 1 deletion compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
// all visible traits. If there's one clear winner, just suggest that.

let visible_traits: Vec<_> = tcx
.all_traits()
.visible_traits()
.filter(|trait_def_id| {
let viz = tcx.visibility(*trait_def_id);
let def_id = self.item_def_id();
Expand Down
10 changes: 6 additions & 4 deletions compiler/rustc_metadata/src/creader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -390,10 +390,12 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
None
}

// The `dependency` type is determined by the command line arguments(`--extern`) and
// `private_dep`. However, sometimes the directly dependent crate is not specified by
// `--extern`, in this case, `private-dep` is none during loading. This is equivalent to the
// scenario where the command parameter is set to `public-dependency`
/// The `dependency` type is determined by the command line arguments(`--extern`) and
/// `private_dep`.
///
/// Sometimes the directly dependent crate is not specified by `--extern`, in this case,
/// `private-dep` is none during loading. This is equivalent to the scenario where the
/// command parameter is set to `public-dependency`
fn is_private_dep(&self, name: &str, private_dep: Option<bool>) -> bool {
self.sess.opts.externs.get(name).map_or(private_dep.unwrap_or(false), |e| e.is_private_dep)
&& private_dep.unwrap_or(true)
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_metadata/src/locator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ pub(crate) struct CrateLocator<'a> {

#[derive(Clone)]
pub(crate) struct CratePaths {
name: Symbol,
pub(crate) name: Symbol,
source: CrateSource,
}

Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_middle/src/query/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2128,6 +2128,8 @@ rustc_queries! {
eval_always
desc { "calculating the stability index for the local crate" }
}
/// All available crates in the graph, including those that should not be user-facing
/// (such as private crates).
query crates(_: ()) -> &'tcx [CrateNum] {
eval_always
desc { "fetching all foreign CrateNum instances" }
Expand Down
11 changes: 11 additions & 0 deletions compiler/rustc_middle/src/ty/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2078,12 +2078,23 @@ impl<'tcx> TyCtxt<'tcx> {
self.limits(()).move_size_limit
}

/// All traits in the crate graph, including those not visible to the user.
pub fn all_traits(self) -> impl Iterator<Item = DefId> + 'tcx {
iter::once(LOCAL_CRATE)
.chain(self.crates(()).iter().copied())
.flat_map(move |cnum| self.traits(cnum).iter().copied())
}

/// All traits that are visible within the crate graph (i.e. excluding private dependencies).
pub fn visible_traits(self) -> impl Iterator<Item = DefId> + 'tcx {
let visible_crates =
self.crates(()).iter().copied().filter(move |cnum| self.is_user_visible_dep(*cnum));

iter::once(LOCAL_CRATE)
.chain(visible_crates)
.flat_map(move |cnum| self.traits(cnum).iter().copied())
}

#[inline]
pub fn local_visibility(self, def_id: LocalDefId) -> Visibility {
self.visibility(def_id).expect_local()
Expand Down
10 changes: 8 additions & 2 deletions compiler/rustc_passes/src/diagnostic_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,14 @@ fn all_diagnostic_items(tcx: TyCtxt<'_>, (): ()) -> DiagnosticItems {
// Initialize the collector.
let mut items = DiagnosticItems::default();

// Collect diagnostic items in other crates.
for &cnum in tcx.crates(()).iter().chain(std::iter::once(&LOCAL_CRATE)) {
// Collect diagnostic items in visible crates.
for cnum in tcx
.crates(())
.iter()
.copied()
.filter(|cnum| tcx.is_user_visible_dep(*cnum))
.chain(std::iter::once(LOCAL_CRATE))
{
for (&name, &def_id) in &tcx.diagnostic_items(cnum).name_to_id {
collect_item(tcx, &mut items, name, def_id);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2189,7 +2189,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
let required_trait_path = self.tcx.def_path_str(trait_ref.def_id());
let traits_with_same_path: UnordSet<_> = self
.tcx
.all_traits()
.visible_traits()
.filter(|trait_def_id| *trait_def_id != trait_ref.def_id())
.map(|trait_def_id| (self.tcx.def_path_str(trait_def_id), trait_def_id))
.filter(|(p, _)| *p == required_trait_path)
Expand Down
10 changes: 5 additions & 5 deletions tests/ui/std/sysroot-private.default.stderr
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
error[E0405]: cannot find trait `Equivalent` in this scope
--> $DIR/sysroot-private.rs:24:18
--> $DIR/sysroot-private.rs:25:18
|
LL | trait Trait2<K>: Equivalent<K> {}
| ^^^^^^^^^^ not found in this scope

error[E0412]: cannot find type `K` in this scope
--> $DIR/sysroot-private.rs:29:35
--> $DIR/sysroot-private.rs:30:35
|
LL | fn trait_member<T>(val: &T, key: &K) -> bool {
| - ^
Expand All @@ -22,13 +22,13 @@ LL | fn trait_member<T, K>(val: &T, key: &K) -> bool {
| +++

error[E0220]: associated type `Buf` not found for `Trait`
--> $DIR/sysroot-private.rs:19:31
--> $DIR/sysroot-private.rs:20:31
|
LL | type AssociatedTy = dyn Trait<Buf = i32, Bar = i32>;
| ^^^ there is an associated type `Buf` in the trait `addr2line::lookup::LookupContinuation`
| ^^^ help: `Trait` has the following associated type: `Bar`

error[E0425]: cannot find function `memchr2` in this scope
--> $DIR/sysroot-private.rs:37:5
--> $DIR/sysroot-private.rs:38:5
|
LL | memchr2(b'a', b'b', buf)
| ^^^^^^^ not found in this scope
Expand Down
3 changes: 2 additions & 1 deletion tests/ui/std/sysroot-private.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,10 @@
trait Trait { type Bar; }

// Attempt to get a suggestion for `addr2line::LookupContinuation`, which has member `Buf`
// Note that the suggestion only happens when `rustc_private` is enabled.
type AssociatedTy = dyn Trait<Buf = i32, Bar = i32>;
//~^ ERROR associated type `Buf` not found
//~| NOTE there is an associated type `Buf` in the trait `addr2line::lookup::LookupContinuation`
//[rustc_private_enabled]~| NOTE there is an associated type `Buf` in the trait `addr2line::lookup::LookupContinuation`

// Attempt to get a suggestion for `hashbrown::Equivalent`
trait Trait2<K>: Equivalent<K> {}
Expand Down
8 changes: 4 additions & 4 deletions tests/ui/std/sysroot-private.rustc_private_enabled.stderr
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
error[E0405]: cannot find trait `Equivalent` in this scope
--> $DIR/sysroot-private.rs:24:18
--> $DIR/sysroot-private.rs:25:18
|
LL | trait Trait2<K>: Equivalent<K> {}
| ^^^^^^^^^^ not found in this scope

error[E0412]: cannot find type `K` in this scope
--> $DIR/sysroot-private.rs:29:35
--> $DIR/sysroot-private.rs:30:35
|
LL | fn trait_member<T>(val: &T, key: &K) -> bool {
| - ^
Expand All @@ -22,13 +22,13 @@ LL | fn trait_member<T, K>(val: &T, key: &K) -> bool {
| +++

error[E0220]: associated type `Buf` not found for `Trait`
--> $DIR/sysroot-private.rs:19:31
--> $DIR/sysroot-private.rs:20:31
|
LL | type AssociatedTy = dyn Trait<Buf = i32, Bar = i32>;
| ^^^ there is an associated type `Buf` in the trait `addr2line::lookup::LookupContinuation`

error[E0425]: cannot find function `memchr2` in this scope
--> $DIR/sysroot-private.rs:37:5
--> $DIR/sysroot-private.rs:38:5
|
LL | memchr2(b'a', b'b', buf)
| ^^^^^^^ not found in this scope
Expand Down

0 comments on commit 35ad309

Please sign in to comment.