diff options
| author | xizheyin <xizheyin@smail.nju.edu.cn> | 2025-07-04 21:38:46 +0800 |
|---|---|---|
| committer | xizheyin <xizheyin@smail.nju.edu.cn> | 2025-07-05 04:13:52 +0800 |
| commit | 4a261a15131e5eec10252d5131c8a3c3f89edbf7 (patch) | |
| tree | 1ddf952900125d2ed6bd13e8e81131415c109f2f | |
| parent | 2111525850863ec2f4c14c964ae37a761de64f63 (diff) | |
| download | rust-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>
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 |
