about summary refs log tree commit diff
diff options
context:
space:
mode:
authorxizheyin <xizheyin@smail.nju.edu.cn>2025-07-04 21:38:46 +0800
committerxizheyin <xizheyin@smail.nju.edu.cn>2025-07-05 04:13:52 +0800
commit4a261a15131e5eec10252d5131c8a3c3f89edbf7 (patch)
tree1ddf952900125d2ed6bd13e8e81131415c109f2f
parent2111525850863ec2f4c14c964ae37a761de64f63 (diff)
downloadrust-4a261a15131e5eec10252d5131c8a3c3f89edbf7.tar.gz
rust-4a261a15131e5eec10252d5131c8a3c3f89edbf7.zip
Use relative visibility when noting sealed trait to reduce false positive
Signed-off-by: xizheyin <xizheyin@smail.nju.edu.cn>
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs20
-rw-r--r--tests/ui/privacy/sealed-traits/false-sealed-traits-note.rs4
-rw-r--r--tests/ui/privacy/sealed-traits/false-sealed-traits-note.stderr1
3 files changed, 17 insertions, 8 deletions
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
index 362052e9fdb..dda517074f4 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
@@ -22,6 +22,7 @@ use rustc_hir::{
     expr_needs_parens, is_range_literal,
 };
 use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes, InferCtxt, InferOk};
+use rustc_middle::middle::privacy::Level;
 use rustc_middle::traits::IsConstable;
 use rustc_middle::ty::error::TypeError;
 use rustc_middle::ty::print::{
@@ -2775,11 +2776,20 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                         ty::ClauseKind::Trait(trait_pred) => {
                             let def_id = trait_pred.def_id();
                             let visible_item = if let Some(local) = def_id.as_local() {
-                                // Check for local traits being reachable.
-                                let vis = &tcx.resolutions(()).effective_visibilities;
-                                // Account for non-`pub` traits in the root of the local crate.
-                                let is_locally_reachable = tcx.parent(def_id).is_crate_root();
-                                vis.is_reachable(local) || is_locally_reachable
+                                let ty = trait_pred.self_ty();
+                                // when `TraitA: TraitB` and `S` only impl TraitA,
+                                // we check if `TraitB` can be reachable from `S`
+                                // to determine whether to note `TraitA` is sealed trait.
+                                if let ty::Adt(adt, _) = ty.kind() {
+                                    let visibilities = tcx.effective_visibilities(());
+                                    visibilities.effective_vis(local).is_none_or(|v| {
+                                        v.at_level(Level::Reexported)
+                                            .is_accessible_from(adt.did(), tcx)
+                                    })
+                                } else {
+                                    // FIXME(xizheyin): if the type is not ADT, we should not suggest it
+                                    true
+                                }
                             } else {
                                 // Check for foreign traits being reachable.
                                 tcx.visible_parent_map(()).get(&def_id).is_some()
diff --git a/tests/ui/privacy/sealed-traits/false-sealed-traits-note.rs b/tests/ui/privacy/sealed-traits/false-sealed-traits-note.rs
index 75bc11b0678..13f3065e442 100644
--- a/tests/ui/privacy/sealed-traits/false-sealed-traits-note.rs
+++ b/tests/ui/privacy/sealed-traits/false-sealed-traits-note.rs
@@ -1,4 +1,4 @@
-// when we impl TraitA for Struct, it can compile, we should not emit sealed traits note, see issue #143392
+// We should not emit sealed traits note, see issue #143392
 
 mod inner {
     pub trait TraitA {}
@@ -10,4 +10,4 @@ struct Struct;
 
 impl inner::TraitB for Struct {} //~ ERROR the trait bound `Struct: TraitA` is not satisfied [E0277]
 
-fn main(){}
\ No newline at end of file
+fn main(){}
diff --git a/tests/ui/privacy/sealed-traits/false-sealed-traits-note.stderr b/tests/ui/privacy/sealed-traits/false-sealed-traits-note.stderr
index 38555160285..f80d985ad6e 100644
--- a/tests/ui/privacy/sealed-traits/false-sealed-traits-note.stderr
+++ b/tests/ui/privacy/sealed-traits/false-sealed-traits-note.stderr
@@ -14,7 +14,6 @@ note: required by a bound in `TraitB`
    |
 LL |     pub trait TraitB: TraitA {}
    |                       ^^^^^^ required by this bound in `TraitB`
-   = note: `TraitB` is a "sealed trait", because to implement it you also need to implement `inner::TraitA`, which is not accessible; this is usually done to force you to use one of the provided types that already implement it
 
 error: aborting due to 1 previous error