about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_middle/src/ty/util.rs23
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs1
-rw-r--r--tests/ui/suggestions/issue-88696.rs14
-rw-r--r--tests/ui/suggestions/issue-88696.stderr11
4 files changed, 48 insertions, 1 deletions
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs
index ba05135638e..8bf60c40b85 100644
--- a/compiler/rustc_middle/src/ty/util.rs
+++ b/compiler/rustc_middle/src/ty/util.rs
@@ -15,7 +15,7 @@ use rustc_data_structures::stable_hasher::{Hash64, HashStable, StableHasher};
 use rustc_errors::ErrorGuaranteed;
 use rustc_hir as hir;
 use rustc_hir::def::{CtorOf, DefKind, Res};
-use rustc_hir::def_id::{DefId, LocalDefId};
+use rustc_hir::def_id::{CrateNum, DefId, LocalDefId};
 use rustc_index::bit_set::GrowableBitSet;
 use rustc_index::{Idx, IndexVec};
 use rustc_macros::HashStable;
@@ -857,6 +857,27 @@ impl<'tcx> TyCtxt<'tcx> {
             _ => def_kind.article(),
         }
     }
+
+    /// Return `true` if the supplied `CrateNum` is "user-visible," meaning either a [public]
+    /// dependency, or a [direct] private dependency. This is used to decide whether the crate can
+    /// be shown in `impl` suggestions.
+    ///
+    /// # Panics
+    ///
+    /// This function assumes `key` exists.
+    ///
+    /// [public]: TyCtxt::is_private_dep
+    /// [direct]: rustc_session::cstore::ExternCrate::is_direct
+    pub fn is_user_visible_dep(self, key: CrateNum) -> bool {
+        // | Private | Direct | Visible |                    |
+        // |---------|--------|---------|--------------------|
+        // | Yes     | Yes    | Yes     | !(true && !true)   |
+        // | No      | Yes    | Yes     | !(false && !true)  |
+        // | Yes     | No     | No      | !(true && !false)  |
+        // | No      | No     | Yes     | !(false && !false) |
+        !(self.is_private_dep(key)
+            && !self.extern_crate(key.as_def_id()).expect("crate must exist").is_direct())
+    }
 }
 
 struct OpaqueTypeExpander<'tcx> {
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 a10ececbb1e..d2cb8971708 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -1775,6 +1775,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                     || !trait_pred
                         .skip_binder()
                         .is_constness_satisfied_by(self.tcx.constness(def_id))
+                    || !self.tcx.is_user_visible_dep(def_id.krate)
                 {
                     return None;
                 }
diff --git a/tests/ui/suggestions/issue-88696.rs b/tests/ui/suggestions/issue-88696.rs
new file mode 100644
index 00000000000..745fdef1546
--- /dev/null
+++ b/tests/ui/suggestions/issue-88696.rs
@@ -0,0 +1,14 @@
+// This test case should ensure that miniz_oxide isn't
+// suggested, since it's not a direct dependency.
+
+fn a() -> Result<u64, i32> {
+    Err(1)
+}
+
+fn b() -> Result<u32, i32> {
+    a().into() //~ERROR [E0277]
+}
+
+fn main() {
+    let _ = dbg!(b());
+}
diff --git a/tests/ui/suggestions/issue-88696.stderr b/tests/ui/suggestions/issue-88696.stderr
new file mode 100644
index 00000000000..4947269d759
--- /dev/null
+++ b/tests/ui/suggestions/issue-88696.stderr
@@ -0,0 +1,11 @@
+error[E0277]: the trait bound `Result<u32, i32>: From<Result<u64, i32>>` is not satisfied
+  --> $DIR/issue-88696.rs:9:9
+   |
+LL |     a().into()
+   |         ^^^^ the trait `From<Result<u64, i32>>` is not implemented for `Result<u32, i32>`
+   |
+   = note: required for `Result<u64, i32>` to implement `Into<Result<u32, i32>>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.