diff options
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/rustc_middle/src/ty/trait_def.rs | 4 | ||||
| -rw-r--r-- | compiler/rustc_trait_selection/messages.ftl | 2 | ||||
| -rw-r--r-- | compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs | 24 |
3 files changed, 25 insertions, 5 deletions
diff --git a/compiler/rustc_middle/src/ty/trait_def.rs b/compiler/rustc_middle/src/ty/trait_def.rs index 6e55e7915c9..bf9b244936f 100644 --- a/compiler/rustc_middle/src/ty/trait_def.rs +++ b/compiler/rustc_middle/src/ty/trait_def.rs @@ -90,6 +90,10 @@ pub struct TraitImpls { } impl TraitImpls { + pub fn is_empty(&self) -> bool { + self.blanket_impls.is_empty() && self.non_blanket_impls.is_empty() + } + pub fn blanket_impls(&self) -> &[DefId] { self.blanket_impls.as_slice() } diff --git a/compiler/rustc_trait_selection/messages.ftl b/compiler/rustc_trait_selection/messages.ftl index 2a09a7dcd89..2db24c43734 100644 --- a/compiler/rustc_trait_selection/messages.ftl +++ b/compiler/rustc_trait_selection/messages.ftl @@ -40,5 +40,7 @@ trait_selection_no_value_in_rustc_on_unimplemented = this attribute must have a .label = expected value here .note = eg `#[rustc_on_unimplemented(message="foo")]` +trait_selection_trait_has_no_impls = this trait has no implementations, consider adding one + trait_selection_ty_alias_overflow = in case this is a recursive type alias, consider using a struct, enum, or union instead trait_selection_unable_to_construct_constant_value = unable to construct a constant value for the unevaluated constant {$unevaluated} diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index 746a38f956a..e4f5c4003c9 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -3009,10 +3009,10 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { // Try to report a help message if is_fn_trait && let Ok((implemented_kind, params)) = self.type_implements_fn_trait( - obligation.param_env, - trait_ref.self_ty(), - trait_predicate.skip_binder().polarity, - ) + obligation.param_env, + trait_ref.self_ty(), + trait_predicate.skip_binder().polarity, + ) { self.add_help_message_for_fn_trait(trait_ref, err, implemented_kind, params); } else if !trait_ref.has_non_region_infer() @@ -3031,6 +3031,15 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { None, obligation.cause.body_id, ); + } else if trait_ref.def_id().is_local() + && self.tcx.trait_impls_of(trait_ref.def_id()).is_empty() + && !self.tcx.trait_is_auto(trait_ref.def_id()) + && !self.tcx.trait_is_alias(trait_ref.def_id()) + { + err.span_help( + self.tcx.def_span(trait_ref.def_id()), + crate::fluent_generated::trait_selection_trait_has_no_impls, + ); } else if !suggested && !unsatisfied_const { // Can't show anything else useful, try to find similar impls. let impl_candidates = self.find_similar_impl_candidates(*trait_predicate); @@ -3041,7 +3050,12 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { err, true, ) { - self.report_similar_impl_candidates_for_root_obligation(&obligation, *trait_predicate, body_def_id, err); + self.report_similar_impl_candidates_for_root_obligation( + &obligation, + *trait_predicate, + body_def_id, + err, + ); } self.suggest_convert_to_slice( |
