@@ -37,22 +37,19 @@ pub(super) fn check_trait<'tcx>(
37
37
) -> Result < ( ) , ErrorGuaranteed > {
38
38
let lang_items = tcx. lang_items ( ) ;
39
39
let checker = Checker { tcx, trait_def_id, impl_def_id, impl_header } ;
40
- let mut res = checker. check ( lang_items. drop_trait ( ) , visit_implementation_of_drop) ;
41
- res = res . and ( checker. check ( lang_items. copy_trait ( ) , visit_implementation_of_copy) ) ;
42
- res = res . and ( checker. check ( lang_items. const_param_ty_trait ( ) , |checker| {
40
+ checker. check ( lang_items. drop_trait ( ) , visit_implementation_of_drop) ? ;
41
+ checker. check ( lang_items. copy_trait ( ) , visit_implementation_of_copy) ? ;
42
+ checker. check ( lang_items. const_param_ty_trait ( ) , |checker| {
43
43
visit_implementation_of_const_param_ty ( checker, LangItem :: ConstParamTy )
44
- } ) ) ;
45
- res = res . and ( checker. check ( lang_items. unsized_const_param_ty_trait ( ) , |checker| {
44
+ } ) ? ;
45
+ checker. check ( lang_items. unsized_const_param_ty_trait ( ) , |checker| {
46
46
visit_implementation_of_const_param_ty ( checker, LangItem :: UnsizedConstParamTy )
47
- } ) ) ;
48
-
49
- res = res. and (
50
- checker. check ( lang_items. coerce_unsized_trait ( ) , visit_implementation_of_coerce_unsized) ,
51
- ) ;
52
- res. and (
53
- checker
54
- . check ( lang_items. dispatch_from_dyn_trait ( ) , visit_implementation_of_dispatch_from_dyn) ,
55
- )
47
+ } ) ?;
48
+ checker. check ( lang_items. coerce_unsized_trait ( ) , visit_implementation_of_coerce_unsized) ?;
49
+ checker
50
+ . check ( lang_items. dispatch_from_dyn_trait ( ) , visit_implementation_of_dispatch_from_dyn) ?;
51
+ checker. check ( lang_items. pointer_like ( ) , visit_implementation_of_pointer_like) ?;
52
+ Ok ( ( ) )
56
53
}
57
54
58
55
struct Checker < ' tcx > {
@@ -663,3 +660,63 @@ fn infringing_fields_error<'tcx>(
663
660
664
661
err. emit ( )
665
662
}
663
+
664
+ fn visit_implementation_of_pointer_like ( checker : & Checker < ' _ > ) -> Result < ( ) , ErrorGuaranteed > {
665
+ let tcx = checker. tcx ;
666
+ let typing_env = ty:: TypingEnv :: non_body_analysis ( tcx, checker. impl_def_id ) ;
667
+ let impl_span = tcx. def_span ( checker. impl_def_id ) ;
668
+ let self_ty = tcx. impl_trait_ref ( checker. impl_def_id ) . unwrap ( ) . instantiate_identity ( ) . self_ty ( ) ;
669
+
670
+ // If an ADT is repr(transparent)...
671
+ if let ty:: Adt ( def, args) = * self_ty. kind ( )
672
+ && def. repr ( ) . transparent ( )
673
+ {
674
+ // FIXME(compiler-errors): This should and could be deduplicated into a query.
675
+ // Find the nontrivial field.
676
+ let adt_typing_env = ty:: TypingEnv :: non_body_analysis ( tcx, def. did ( ) ) ;
677
+ let nontrivial_field = def. all_fields ( ) . find ( |field_def| {
678
+ let field_ty = tcx. type_of ( field_def. did ) . instantiate_identity ( ) ;
679
+ !tcx. layout_of ( adt_typing_env. as_query_input ( field_ty) )
680
+ . is_ok_and ( |layout| layout. layout . is_1zst ( ) )
681
+ } ) ;
682
+
683
+ if let Some ( nontrivial_field) = nontrivial_field {
684
+ // Check that the nontrivial field implements `PointerLike`.
685
+ let nontrivial_field = nontrivial_field. ty ( tcx, args) ;
686
+ let ( infcx, param_env) = tcx. infer_ctxt ( ) . build_with_typing_env ( typing_env) ;
687
+ let ocx = ObligationCtxt :: new ( & infcx) ;
688
+ ocx. register_bound (
689
+ ObligationCause :: misc ( impl_span, checker. impl_def_id ) ,
690
+ param_env,
691
+ nontrivial_field,
692
+ tcx. lang_items ( ) . pointer_like ( ) . unwrap ( ) ,
693
+ ) ;
694
+ // FIXME(dyn-star): We should regionck this implementation.
695
+ if ocx. select_all_or_error ( ) . is_empty ( ) {
696
+ return Ok ( ( ) ) ;
697
+ }
698
+ }
699
+ }
700
+
701
+ let is_permitted_primitive = match * self_ty. kind ( ) {
702
+ ty:: Adt ( def, _) => def. is_box ( ) ,
703
+ ty:: Uint ( ..) | ty:: Int ( ..) | ty:: RawPtr ( ..) | ty:: Ref ( ..) | ty:: FnPtr ( ..) => true ,
704
+ _ => false ,
705
+ } ;
706
+
707
+ if is_permitted_primitive
708
+ && let Ok ( layout) = tcx. layout_of ( typing_env. as_query_input ( self_ty) )
709
+ && layout. layout . is_pointer_like ( & tcx. data_layout )
710
+ {
711
+ return Ok ( ( ) ) ;
712
+ }
713
+
714
+ Err ( tcx
715
+ . dcx ( )
716
+ . struct_span_err (
717
+ impl_span,
718
+ "implementation must be applied to type that has the same ABI as a pointer, \
719
+ or is `repr(transparent)` and whose field is `PointerLike`",
720
+ )
721
+ . emit ( ) )
722
+ }
0 commit comments