@@ -16,13 +16,14 @@ use rustc_middle::ty::print::PrintTraitRefExt as _;
1616use rustc_middle:: ty:: {
1717 self , Ty , TyCtxt , TypeVisitableExt , TypingMode , suggest_constraining_type_params,
1818} ;
19+ use rustc_session:: parse:: feature_err;
1920use rustc_span:: { DUMMY_SP , Span , sym} ;
2021use rustc_trait_selection:: error_reporting:: InferCtxtErrorExt ;
2122use rustc_trait_selection:: traits:: misc:: {
2223 ConstParamTyImplementationError , CopyImplementationError , InfringingFieldsReason ,
2324 type_allowed_to_implement_const_param_ty, type_allowed_to_implement_copy,
2425} ;
25- use rustc_trait_selection:: traits:: { self , ObligationCause , ObligationCtxt } ;
26+ use rustc_trait_selection:: traits:: { self , NormalizeExt , ObligationCause , ObligationCtxt } ;
2627use tracing:: debug;
2728
2829use crate :: errors;
@@ -49,6 +50,7 @@ pub(super) fn check_trait<'tcx>(
4950 lang_items. coerce_pointee_validated_trait ( ) ,
5051 visit_implementation_of_coerce_pointee_validity,
5152 ) ?;
53+ checker. check ( lang_items. receiver_trait ( ) , visit_implementation_of_receiver) ?;
5254 Ok ( ( ) )
5355}
5456
@@ -792,3 +794,55 @@ fn visit_implementation_of_coerce_pointee_validity(
792794 }
793795 Ok ( ( ) )
794796}
797+
798+ fn visit_implementation_of_receiver ( checker : & Checker < ' _ > ) -> Result < ( ) , ErrorGuaranteed > {
799+ let tcx = checker. tcx ;
800+ if tcx. features ( ) . arbitrary_self_types_split_chains ( ) {
801+ return Ok ( ( ) ) ;
802+ }
803+ let impl_did = checker. impl_def_id ;
804+ let span = tcx. def_span ( impl_did) ;
805+ let deref_target_did = tcx. require_lang_item ( LangItem :: DerefTarget , span) ;
806+ let receiver_target_did = tcx. require_lang_item ( LangItem :: ReceiverTarget , span) ;
807+ let self_ty = tcx. impl_trait_ref ( impl_did) . instantiate_identity ( ) . self_ty ( ) ;
808+ let param_env = tcx. param_env ( impl_did) ;
809+ let infcx = tcx. infer_ctxt ( ) . build ( TypingMode :: non_body_analysis ( ) ) ;
810+ let ocx = ObligationCtxt :: new ( & infcx) ;
811+ let cause = ObligationCause :: misc ( span, impl_did) ;
812+ ocx. register_obligation ( Obligation :: new (
813+ tcx,
814+ cause. clone ( ) ,
815+ param_env,
816+ ty:: TraitRef :: new ( tcx, tcx. require_lang_item ( LangItem :: Deref , span) , [ self_ty] ) ,
817+ ) ) ;
818+ if !ocx. evaluate_obligations_error_on_ambiguity ( ) . is_empty ( ) {
819+ // We cannot enforce Deref::Target == Receiver::Target because we cannot find `impl Deref`
820+ return Ok ( ( ) ) ;
821+ }
822+ let infer:: InferOk { value : deref_target_ty, .. } = infcx. at ( & cause, param_env) . normalize (
823+ Ty :: new_projection_from_args ( tcx, deref_target_did, tcx. mk_args ( & [ self_ty. into ( ) ] ) ) ,
824+ ) ;
825+ let infer:: InferOk { value : receiver_target_ty, .. } = infcx. at ( & cause, param_env) . normalize (
826+ Ty :: new_projection_from_args ( tcx, receiver_target_did, tcx. mk_args ( & [ self_ty. into ( ) ] ) ) ,
827+ ) ;
828+ if let Err ( _) = infcx. at ( & cause, param_env) . eq (
829+ infer:: DefineOpaqueTypes :: No ,
830+ deref_target_ty,
831+ receiver_target_ty,
832+ ) {
833+ feature_err (
834+ tcx. sess ,
835+ sym:: arbitrary_self_types_split_chains,
836+ span,
837+ "`Receiver::Target` diverging from `Deref::Target` is not supported; we look forward to your feedback" ,
838+ )
839+ . emit ( ) ;
840+ Err ( tcx. dcx ( ) . emit_err ( errors:: DerefReceiverTargetDiverge {
841+ span,
842+ deref_ty : deref_target_ty,
843+ recv_ty : receiver_target_ty,
844+ } ) )
845+ } else {
846+ Ok ( ( ) )
847+ }
848+ }
0 commit comments