@@ -673,37 +673,6 @@ fn visit_implementation_of_pointer_like(checker: &Checker<'_>) -> Result<(), Err
673673 let impl_span = tcx. def_span ( checker. impl_def_id ) ;
674674 let self_ty = tcx. impl_trait_ref ( checker. impl_def_id ) . unwrap ( ) . instantiate_identity ( ) . self_ty ( ) ;
675675
676- // If an ADT is repr(transparent)...
677- if let ty:: Adt ( def, args) = * self_ty. kind ( )
678- && def. repr ( ) . transparent ( )
679- {
680- // FIXME(compiler-errors): This should and could be deduplicated into a query.
681- // Find the nontrivial field.
682- let adt_typing_env = ty:: TypingEnv :: non_body_analysis ( tcx, def. did ( ) ) ;
683- let nontrivial_field = def. all_fields ( ) . find ( |field_def| {
684- let field_ty = tcx. type_of ( field_def. did ) . instantiate_identity ( ) ;
685- !tcx. layout_of ( adt_typing_env. as_query_input ( field_ty) )
686- . is_ok_and ( |layout| layout. layout . is_1zst ( ) )
687- } ) ;
688-
689- if let Some ( nontrivial_field) = nontrivial_field {
690- // Check that the nontrivial field implements `PointerLike`.
691- let nontrivial_field = nontrivial_field. ty ( tcx, args) ;
692- let ( infcx, param_env) = tcx. infer_ctxt ( ) . build_with_typing_env ( typing_env) ;
693- let ocx = ObligationCtxt :: new ( & infcx) ;
694- ocx. register_bound (
695- ObligationCause :: misc ( impl_span, checker. impl_def_id ) ,
696- param_env,
697- nontrivial_field,
698- tcx. lang_items ( ) . pointer_like ( ) . unwrap ( ) ,
699- ) ;
700- // FIXME(dyn-star): We should regionck this implementation.
701- if ocx. select_all_or_error ( ) . is_empty ( ) {
702- return Ok ( ( ) ) ;
703- }
704- }
705- }
706-
707676 let is_permitted_primitive = match * self_ty. kind ( ) {
708677 ty:: Adt ( def, _) => def. is_box ( ) ,
709678 ty:: Uint ( ..) | ty:: Int ( ..) | ty:: RawPtr ( ..) | ty:: Ref ( ..) | ty:: FnPtr ( ..) => true ,
@@ -717,12 +686,81 @@ fn visit_implementation_of_pointer_like(checker: &Checker<'_>) -> Result<(), Err
717686 return Ok ( ( ) ) ;
718687 }
719688
689+ let why_disqualified = match * self_ty. kind ( ) {
690+ // If an ADT is repr(transparent)
691+ ty:: Adt ( self_ty_def, args) => {
692+ if self_ty_def. repr ( ) . transparent ( ) {
693+ // FIXME(compiler-errors): This should and could be deduplicated into a query.
694+ // Find the nontrivial field.
695+ let adt_typing_env = ty:: TypingEnv :: non_body_analysis ( tcx, self_ty_def. did ( ) ) ;
696+ let nontrivial_field = self_ty_def. all_fields ( ) . find ( |field_def| {
697+ let field_ty = tcx. type_of ( field_def. did ) . instantiate_identity ( ) ;
698+ !tcx. layout_of ( adt_typing_env. as_query_input ( field_ty) )
699+ . is_ok_and ( |layout| layout. layout . is_1zst ( ) )
700+ } ) ;
701+
702+ if let Some ( nontrivial_field) = nontrivial_field {
703+ // Check that the nontrivial field implements `PointerLike`.
704+ let nontrivial_field_ty = nontrivial_field. ty ( tcx, args) ;
705+ let ( infcx, param_env) = tcx. infer_ctxt ( ) . build_with_typing_env ( typing_env) ;
706+ let ocx = ObligationCtxt :: new ( & infcx) ;
707+ ocx. register_bound (
708+ ObligationCause :: misc ( impl_span, checker. impl_def_id ) ,
709+ param_env,
710+ nontrivial_field_ty,
711+ tcx. lang_items ( ) . pointer_like ( ) . unwrap ( ) ,
712+ ) ;
713+ // FIXME(dyn-star): We should regionck this implementation.
714+ if ocx. select_all_or_error ( ) . is_empty ( ) {
715+ return Ok ( ( ) ) ;
716+ } else {
717+ format ! (
718+ "the field `{field_name}` of {descr} `{self_ty}` \
719+ does not implement `PointerLike`",
720+ field_name = nontrivial_field. name,
721+ descr = self_ty_def. descr( )
722+ )
723+ }
724+ } else {
725+ format ! (
726+ "the {descr} `{self_ty}` is `repr(transparent)`, \
727+ but does not have a non-trivial field (it is zero-sized)",
728+ descr = self_ty_def. descr( )
729+ )
730+ }
731+ } else if self_ty_def. is_box ( ) {
732+ // If we got here, then the `layout.is_pointer_like()` check failed
733+ // and this box is not a thin pointer.
734+
735+ String :: from ( "boxes of dynamically-sized types are too large to be `PointerLike`" )
736+ } else {
737+ format ! (
738+ "the {descr} `{self_ty}` is not `repr(transparent)`" ,
739+ descr = self_ty_def. descr( )
740+ )
741+ }
742+ }
743+ ty:: Ref ( ..) => {
744+ // If we got here, then the `layout.is_pointer_like()` check failed
745+ // and this reference is not a thin pointer.
746+ String :: from ( "references to dynamically-sized types are too large to be `PointerLike`" )
747+ }
748+ ty:: Dynamic ( ..) | ty:: Foreign ( ..) => {
749+ String :: from ( "types of dynamic or unknown size may not implement `PointerLike`" )
750+ }
751+ _ => {
752+ // This is a white lie; it is true everywhere outside the standard library.
753+ format ! ( "only user-defined sized types are eligible for `impl PointerLike`" )
754+ }
755+ } ;
756+
720757 Err ( tcx
721758 . dcx ( )
722759 . struct_span_err (
723760 impl_span,
724761 "implementation must be applied to type that has the same ABI as a pointer, \
725762 or is `repr(transparent)` and whose field is `PointerLike`",
726763 )
764+ . with_note ( why_disqualified)
727765 . emit ( ) )
728766}
0 commit comments