Use relative visibility when noting sealed trait to reduce false positive
Signed-off-by: xizheyin <xizheyin@smail.nju.edu.cn>
This commit is contained in:
parent
2111525850
commit
4a261a1513
3 changed files with 17 additions and 8 deletions
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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(){}
|
||||
fn main(){}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue