When encountering sealed traits, point types that implement it
``` 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 ``` The last `help` is new.
This commit is contained in:
parent
9d6d5d4894
commit
6dbad23641
3 changed files with 105 additions and 9 deletions
|
@ -2691,8 +2691,6 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
||||||
if let DefKind::Trait = tcx.def_kind(item_def_id)
|
if let DefKind::Trait = tcx.def_kind(item_def_id)
|
||||||
&& !visible_item
|
&& !visible_item
|
||||||
{
|
{
|
||||||
// FIXME(estebank): extend this to search for all the types that do
|
|
||||||
// implement this trait and list them.
|
|
||||||
err.note(format!(
|
err.note(format!(
|
||||||
"`{short_item_name}` is a \"sealed trait\", because to implement \
|
"`{short_item_name}` is a \"sealed trait\", because to implement \
|
||||||
it you also need to implement `{}`, which is not accessible; \
|
it you also need to implement `{}`, which is not accessible; \
|
||||||
|
@ -2700,6 +2698,34 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
||||||
types that already implement it",
|
types that already implement it",
|
||||||
with_no_trimmed_paths!(tcx.def_path_str(def_id)),
|
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 {
|
} else {
|
||||||
|
|
|
@ -13,7 +13,43 @@ pub mod a {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct S;
|
pub mod c {
|
||||||
impl a::Sealed for S {} //~ ERROR the trait bound `S: Hidden` is not satisfied
|
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() {}
|
fn main() {}
|
||||||
|
|
|
@ -1,16 +1,50 @@
|
||||||
error[E0277]: the trait bound `S: Hidden` is not satisfied
|
error[E0277]: the trait bound `S: b::Hidden` is not satisfied
|
||||||
--> $DIR/sealed-trait-local.rs:17:20
|
--> $DIR/sealed-trait-local.rs:52:20
|
||||||
|
|
|
|
||||||
LL | impl a::Sealed for S {}
|
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
|
--> $DIR/sealed-trait-local.rs:3:23
|
||||||
|
|
|
|
||||||
LL | pub trait Sealed: self::b::Hidden {
|
LL | pub trait Sealed: self::b::Hidden {
|
||||||
| ^^^^^^^^^^^^^^^ required by this bound in `Sealed`
|
| ^^^^^^^^^^^^^^^ 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
|
= 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`.
|
For more information about this error, try `rustc --explain E0277`.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue