From f2d8af10c24324f85a6ad82d3f8595ce4bd7ce95 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 9 Jul 2022 18:39:51 +0000 Subject: [PATCH 1/2] Do not mention private Self types from other crates --- .../src/traits/error_reporting/mod.rs | 22 +++++++++++++++++-- src/test/ui/suggestions/auxiliary/meow.rs | 11 ++++++++++ src/test/ui/suggestions/issue-99080.rs | 16 ++++++++++++++ src/test/ui/suggestions/issue-99080.stderr | 20 +++++++++++++++++ .../assoc-fn-bound-root-obligation.stderr | 1 - 5 files changed, 67 insertions(+), 3 deletions(-) create mode 100644 src/test/ui/suggestions/auxiliary/meow.rs create mode 100644 src/test/ui/suggestions/issue-99080.rs create mode 100644 src/test/ui/suggestions/issue-99080.stderr diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index aa1c91362891b..7ac3815179a39 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -1805,8 +1805,26 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> { || self.tcx.is_builtin_derive(def_id) }) .filter_map(|def_id| self.tcx.impl_trait_ref(def_id)) - // Avoid mentioning type parameters. - .filter(|trait_ref| !matches!(trait_ref.self_ty().kind(), ty::Param(_))) + .filter(|trait_ref| { + let self_ty = trait_ref.self_ty(); + // Avoid mentioning type parameters. + if let ty::Param(_) = self_ty.kind() { + false + } + // Avoid mentioning types that are private to another crate + else if let ty::Adt(def, _) = self_ty.peel_refs().kind() { + // FIXME(compiler-errors): This could be generalized, both to + // be more granular, and probably look past other `#[fundamental]` + // types, too. + match self.tcx.visibility(def.did()) { + ty::Visibility::Public => true, + ty::Visibility::Restricted(def_id) => def_id.is_local(), + ty::Visibility::Invisible => false, + } + } else { + true + } + }) .collect(); return report(normalized_impl_candidates, err); } diff --git a/src/test/ui/suggestions/auxiliary/meow.rs b/src/test/ui/suggestions/auxiliary/meow.rs new file mode 100644 index 0000000000000..115df70a69060 --- /dev/null +++ b/src/test/ui/suggestions/auxiliary/meow.rs @@ -0,0 +1,11 @@ +pub trait Meow { + fn meow(&self) {} +} + +pub struct GlobalMeow; + +impl Meow for GlobalMeow {} + +pub(crate) struct PrivateMeow; + +impl Meow for PrivateMeow {} diff --git a/src/test/ui/suggestions/issue-99080.rs b/src/test/ui/suggestions/issue-99080.rs new file mode 100644 index 0000000000000..91f574f35b80b --- /dev/null +++ b/src/test/ui/suggestions/issue-99080.rs @@ -0,0 +1,16 @@ +// aux-build:meow.rs + +extern crate meow; + +use meow::Meow; + +fn needs_meow(t: T) {} + +fn main() { + needs_meow(1usize); + //~^ ERROR the trait bound `usize: Meow` is not satisfied +} + +struct LocalMeow; + +impl Meow for LocalMeow {} diff --git a/src/test/ui/suggestions/issue-99080.stderr b/src/test/ui/suggestions/issue-99080.stderr new file mode 100644 index 0000000000000..d1908dd9d0d86 --- /dev/null +++ b/src/test/ui/suggestions/issue-99080.stderr @@ -0,0 +1,20 @@ +error[E0277]: the trait bound `usize: Meow` is not satisfied + --> $DIR/issue-99080.rs:10:16 + | +LL | needs_meow(1usize); + | ---------- ^^^^^^ the trait `Meow` is not implemented for `usize` + | | + | required by a bound introduced by this call + | + = help: the following other types implement trait `Meow`: + GlobalMeow + LocalMeow +note: required by a bound in `needs_meow` + --> $DIR/issue-99080.rs:7:18 + | +LL | fn needs_meow(t: T) {} + | ^^^^ required by this bound in `needs_meow` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/traits/bound/assoc-fn-bound-root-obligation.stderr b/src/test/ui/traits/bound/assoc-fn-bound-root-obligation.stderr index 115539a6dc28d..6ce57b6263e41 100644 --- a/src/test/ui/traits/bound/assoc-fn-bound-root-obligation.stderr +++ b/src/test/ui/traits/bound/assoc-fn-bound-root-obligation.stderr @@ -15,7 +15,6 @@ LL | s.strip_suffix(b'\n').unwrap_or(s) &'c &'b str [char; N] char - pattern::MultiCharEqPattern = note: required because of the requirements on the impl of `Pattern<'_>` for `u8` error: aborting due to previous error From 913023b6b475ac5caed060771526e0777a13ae94 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 11 Jul 2022 07:06:18 +0000 Subject: [PATCH 2/2] Use Visibility::is_accessible_from to make suggestion more specific --- .../src/traits/error_reporting/mod.rs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index 7ac3815179a39..34f4a9f790266 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -673,6 +673,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { if !self.report_similar_impl_candidates( impl_candidates, trait_ref, + obligation.cause.body_id, &mut err, ) { // This is *almost* equivalent to @@ -707,6 +708,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { self.report_similar_impl_candidates( impl_candidates, trait_ref, + obligation.cause.body_id, &mut err, ); } @@ -1353,6 +1355,7 @@ trait InferCtxtPrivExt<'hir, 'tcx> { &self, impl_candidates: Vec>, trait_ref: ty::PolyTraitRef<'tcx>, + body_id: hir::HirId, err: &mut Diagnostic, ) -> bool; @@ -1735,6 +1738,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> { &self, impl_candidates: Vec>, trait_ref: ty::PolyTraitRef<'tcx>, + body_id: hir::HirId, err: &mut Diagnostic, ) -> bool { let report = |mut candidates: Vec>, err: &mut Diagnostic| { @@ -1816,11 +1820,9 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> { // FIXME(compiler-errors): This could be generalized, both to // be more granular, and probably look past other `#[fundamental]` // types, too. - match self.tcx.visibility(def.did()) { - ty::Visibility::Public => true, - ty::Visibility::Restricted(def_id) => def_id.is_local(), - ty::Visibility::Invisible => false, - } + self.tcx + .visibility(def.did()) + .is_accessible_from(body_id.owner.to_def_id(), self.tcx) } else { true }