Auto merge of #112686 - estebank:sealed-traits, r=petrochenkov
Account for sealed traits in privacy and trait bound errors On trait bound errors caused by super-traits, identify if the super-trait is publicly accessibly and if not, explain "sealed traits". ``` error[E0277]: the trait bound `S: Hidden` is not satisfied --> $DIR/sealed-trait-local.rs:17:20 | LL | impl a::Sealed for S {} | ^ the trait `Hidden` is not implemented for `S` | note: required by a bound in `Sealed` --> $DIR/sealed-trait-local.rs:3:23 | LL | pub trait Sealed: self:🅱️:Hidden { | ^^^^^^^^^^^^^^^ required by this bound in `Sealed` = note: `Sealed` is a "sealed trait", because to implement it you also need to implelement `a:🅱️:Hidden`, which is not accessible; this is usually done to force you to use one of the provided types that already implement it ``` Deduplicate privacy errors that point to the same path segment even if their deduplication span are different. When encountering a path that is not reachable due to privacy constraints path segments other than the last, keep metadata for the last path segment's `Res` in order to look for alternative import paths for that item to suggest. If there are none, be explicit that the item is not accessible. ``` error[E0603]: module `b` is private --> $DIR/re-exported-trait.rs:11:9 | LL | impl a:🅱️:Trait for S {} | ^ private module | note: the module `b` is defined here --> $DIR/re-exported-trait.rs:5:5 | LL | mod b { | ^^^^^ help: consider importing this trait through its public re-export instead | LL | impl a::Trait for S {} | ~~~~~~~~ ``` ``` error[E0603]: module `b` is private --> $DIR/private-trait.rs:8:9 | LL | impl a:🅱️:Hidden for S {} | ^ ------ trait `b` is not publicly reachable | | | private module | note: the module `b` is defined here --> $DIR/private-trait.rs:2:5 | LL | mod b { | ^^^^^ ```
This commit is contained in:
commit
04075b3202
29 changed files with 337 additions and 54 deletions
|
@ -2724,6 +2724,32 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
let msg = format!("required by this bound in `{short_item_name}`");
|
||||
multispan.push_span_label(span, msg);
|
||||
err.span_note(multispan, descr);
|
||||
if let ty::PredicateKind::Clause(clause) = predicate.kind().skip_binder()
|
||||
&& let ty::ClauseKind::Trait(trait_pred) = clause
|
||||
{
|
||||
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 = &self.tcx.resolutions(()).effective_visibilities;
|
||||
// Account for non-`pub` traits in the root of the local crate.
|
||||
let is_locally_reachable = self.tcx.parent(def_id).is_crate_root();
|
||||
vis.is_reachable(local) || is_locally_reachable
|
||||
} else {
|
||||
// Check for foreign traits being reachable.
|
||||
self.tcx.visible_parent_map(()).get(&def_id).is_some()
|
||||
};
|
||||
if let DefKind::Trait = tcx.def_kind(item_def_id) && !visible_item {
|
||||
// FIXME(estebank): extend this to search for all the types that do
|
||||
// implement this trait and list them.
|
||||
err.note(format!(
|
||||
"`{short_item_name}` is a \"sealed trait\", because to implement \
|
||||
it you also need to implelement `{}`, which is not accessible; \
|
||||
this is usually done to force you to use one of the provided \
|
||||
types that already implement it",
|
||||
with_no_trimmed_paths!(tcx.def_path_str(def_id)),
|
||||
));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
err.span_note(tcx.def_span(item_def_id), descr);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue