@@ -43,6 +43,7 @@ use super::{
4343} ;
4444use crate :: error_reporting:: TypeErrCtxt ;
4545use crate :: error_reporting:: infer:: TyCategory ;
46+ use crate :: error_reporting:: traits:: on_unimplemented:: OnUnimplementedDirective ;
4647use crate :: error_reporting:: traits:: report_dyn_incompatibility;
4748use crate :: errors:: { ClosureFnMutLabel , ClosureFnOnceLabel , ClosureKindMismatch , CoroClosureNotFn } ;
4849use crate :: infer:: { self , InferCtxt , InferCtxtExt as _} ;
@@ -587,7 +588,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
587588 }
588589
589590 ty:: PredicateKind :: Clause ( ty:: ClauseKind :: HostEffect ( predicate) ) => {
590- self . report_host_effect_error ( bound_predicate. rebind ( predicate) , obligation. param_env , span)
591+ self . report_host_effect_error ( bound_predicate. rebind ( predicate) , & obligation, span)
591592 }
592593
593594 ty:: PredicateKind :: Subtype ( predicate) => {
@@ -808,20 +809,18 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
808809 fn report_host_effect_error (
809810 & self ,
810811 predicate : ty:: Binder < ' tcx , ty:: HostEffectPredicate < ' tcx > > ,
811- param_env : ty :: ParamEnv < ' tcx > ,
812+ main_obligation : & PredicateObligation < ' tcx > ,
812813 span : Span ,
813814 ) -> Diag < ' a > {
814815 // FIXME(const_trait_impl): We should recompute the predicate with `[const]`
815816 // if it's `const`, and if it holds, explain that this bound only
816- // *conditionally* holds. If that fails, we should also do selection
817- // to drill this down to an impl or built-in source, so we can
818- // point at it and explain that while the trait *is* implemented,
819- // that implementation is not const.
817+ // *conditionally* holds.
820818 let trait_ref = predicate. map_bound ( |predicate| ty:: TraitPredicate {
821819 trait_ref : predicate. trait_ref ,
822820 polarity : ty:: PredicatePolarity :: Positive ,
823821 } ) ;
824822 let mut file = None ;
823+
825824 let err_msg = self . get_standard_error_message (
826825 trait_ref,
827826 None ,
@@ -832,18 +831,21 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
832831 ) ;
833832 let mut diag = struct_span_code_err ! ( self . dcx( ) , span, E0277 , "{}" , err_msg) ;
834833 * diag. long_ty_path ( ) = file;
835- if ! self . predicate_may_hold ( & Obligation :: new (
834+ let obligation = Obligation :: new (
836835 self . tcx ,
837836 ObligationCause :: dummy ( ) ,
838- param_env,
837+ main_obligation . param_env ,
839838 trait_ref,
840- ) ) {
839+ ) ;
840+ if !self . predicate_may_hold ( & obligation) {
841841 diag. downgrade_to_delayed_bug ( ) ;
842842 }
843- for candidate in self . find_similar_impl_candidates ( trait_ref) {
844- let CandidateSimilarity :: Exact { .. } = candidate. similarity else { continue } ;
845- let impl_did = candidate. impl_def_id ;
846- let trait_did = candidate. trait_ref . def_id ;
843+
844+ if let Ok ( Some ( ImplSource :: UserDefined ( impl_data) ) ) =
845+ SelectionContext :: new ( self ) . select ( & obligation. with ( self . tcx , trait_ref. skip_binder ( ) ) )
846+ {
847+ let impl_did = impl_data. impl_def_id ;
848+ let trait_did = trait_ref. def_id ( ) ;
847849 let impl_span = self . tcx . def_span ( impl_did) ;
848850 let trait_name = self . tcx . item_name ( trait_did) ;
849851
@@ -865,6 +867,42 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
865867 impl_span,
866868 format ! ( "trait `{trait_name}` is implemented but not `const`" ) ,
867869 ) ;
870+
871+ let ( condition_options, format_args) = self . on_unimplemented_components (
872+ trait_ref,
873+ main_obligation,
874+ diag. long_ty_path ( ) ,
875+ ) ;
876+
877+ if let Ok ( Some ( command) ) = OnUnimplementedDirective :: of_item ( self . tcx , impl_did)
878+ {
879+ let note = command. evaluate (
880+ self . tcx ,
881+ predicate. skip_binder ( ) . trait_ref ,
882+ & condition_options,
883+ & format_args,
884+ ) ;
885+ let OnUnimplementedNote {
886+ message,
887+ label,
888+ notes,
889+ parent_label,
890+ append_const_msg : _,
891+ } = note;
892+
893+ if let Some ( message) = message {
894+ diag. primary_message ( message) ;
895+ }
896+ if let Some ( label) = label {
897+ diag. span_label ( impl_span, label) ;
898+ }
899+ for note in notes {
900+ diag. note ( note) ;
901+ }
902+ if let Some ( parent_label) = parent_label {
903+ diag. span_label ( impl_span, parent_label) ;
904+ }
905+ }
868906 }
869907 }
870908 }
0 commit comments