Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

When encountering sealed traits, point types that implement it #116945

Merged
merged 1 commit into from
Oct 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2691,15 +2691,41 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
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 implement `{}`, 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)),
));
let impls_of = tcx.trait_impls_of(def_id);
let impls = impls_of
.non_blanket_impls()
.values()
.flatten()
.chain(impls_of.blanket_impls().iter())
.collect::<Vec<_>>();
if !impls.is_empty() {
let len = impls.len();
let mut types = impls.iter()
.map(|t| with_no_trimmed_paths!(format!(
" {}",
tcx.type_of(*t).instantiate_identity(),
)))
.collect::<Vec<_>>();
let post = if types.len() > 9 {
types.truncate(8);
format!("\nand {} others", len - 8)
} else {
String::new()
};
err.help(format!(
"the following type{} implement{} the trait:\n{}{post}",
pluralize!(len),
if len == 1 { "s" } else { "" },
types.join("\n"),
));
}
}
}
} else {
Expand Down
40 changes: 38 additions & 2 deletions tests/ui/privacy/sealed-traits/sealed-trait-local.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,43 @@ pub mod a {
}
}

struct S;
impl a::Sealed for S {} //~ ERROR the trait bound `S: Hidden` is not satisfied
pub mod c {
pub trait Sealed: self::d::Hidden {
fn foo() {}
}

struct X;
impl Sealed for X {}
impl self::d::Hidden for X {}

struct Y;
impl Sealed for Y {}
impl self::d::Hidden for Y {}

mod d {
pub trait Hidden {}
}
}

pub mod e {
pub trait Sealed: self::f::Hidden {
fn foo() {}
}

struct X;
impl self::f::Hidden for X {}

struct Y;
impl self::f::Hidden for Y {}
impl<T: self::f::Hidden> Sealed for T {}

mod f {
pub trait Hidden {}
}
}

struct S;
impl a::Sealed for S {} //~ ERROR the trait bound
impl c::Sealed for S {} //~ ERROR the trait bound
impl e::Sealed for S {} //~ ERROR the trait bound
fn main() {}
44 changes: 39 additions & 5 deletions tests/ui/privacy/sealed-traits/sealed-trait-local.stderr
Original file line number Diff line number Diff line change
@@ -1,16 +1,50 @@
error[E0277]: the trait bound `S: Hidden` is not satisfied
--> $DIR/sealed-trait-local.rs:17:20
error[E0277]: the trait bound `S: b::Hidden` is not satisfied
--> $DIR/sealed-trait-local.rs:52:20
|
LL | impl a::Sealed for S {}
| ^ the trait `Hidden` is not implemented for `S`
| ^ the trait `b::Hidden` is not implemented for `S`
|
note: required by a bound in `Sealed`
note: required by a bound in `a::Sealed`
--> $DIR/sealed-trait-local.rs:3:23
|
LL | pub trait Sealed: self::b::Hidden {
| ^^^^^^^^^^^^^^^ required by this bound in `Sealed`
= note: `Sealed` is a "sealed trait", because to implement it you also need to implement `a::b::Hidden`, which is not accessible; this is usually done to force you to use one of the provided types that already implement it
= help: the following type implements the trait:
a::X

error: aborting due to previous error
error[E0277]: the trait bound `S: d::Hidden` is not satisfied
--> $DIR/sealed-trait-local.rs:53:20
|
LL | impl c::Sealed for S {}
| ^ the trait `d::Hidden` is not implemented for `S`
|
note: required by a bound in `c::Sealed`
--> $DIR/sealed-trait-local.rs:17:23
|
LL | pub trait Sealed: self::d::Hidden {
| ^^^^^^^^^^^^^^^ required by this bound in `Sealed`
= note: `Sealed` is a "sealed trait", because to implement it you also need to implement `c::d::Hidden`, which is not accessible; this is usually done to force you to use one of the provided types that already implement it
= help: the following types implement the trait:
c::X
c::Y

error[E0277]: the trait bound `S: f::Hidden` is not satisfied
--> $DIR/sealed-trait-local.rs:54:20
|
LL | impl e::Sealed for S {}
| ^ the trait `f::Hidden` is not implemented for `S`
|
note: required by a bound in `e::Sealed`
--> $DIR/sealed-trait-local.rs:35:23
|
LL | pub trait Sealed: self::f::Hidden {
| ^^^^^^^^^^^^^^^ required by this bound in `Sealed`
= note: `Sealed` is a "sealed trait", because to implement it you also need to implement `e::f::Hidden`, which is not accessible; this is usually done to force you to use one of the provided types that already implement it
= help: the following types implement the trait:
e::X
e::Y

error: aborting due to 3 previous errors

For more information about this error, try `rustc --explain E0277`.
Loading