@@ -673,37 +673,6 @@ fn visit_implementation_of_pointer_like(checker: &Checker<'_>) -> Result<(), Err
673
673
let impl_span = tcx. def_span ( checker. impl_def_id ) ;
674
674
let self_ty = tcx. impl_trait_ref ( checker. impl_def_id ) . unwrap ( ) . instantiate_identity ( ) . self_ty ( ) ;
675
675
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
-
707
676
let is_permitted_primitive = match * self_ty. kind ( ) {
708
677
ty:: Adt ( def, _) => def. is_box ( ) ,
709
678
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
717
686
return Ok ( ( ) ) ;
718
687
}
719
688
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
+
720
757
Err ( tcx
721
758
. dcx ( )
722
759
. struct_span_err (
723
760
impl_span,
724
761
"implementation must be applied to type that has the same ABI as a pointer, \
725
762
or is `repr(transparent)` and whose field is `PointerLike`",
726
763
)
764
+ . with_note ( why_disqualified)
727
765
. emit ( ) )
728
766
}
0 commit comments