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