@@ -37,22 +37,19 @@ pub(super) fn check_trait<'tcx>(
3737) -> Result < ( ) , ErrorGuaranteed > {
3838 let lang_items = tcx. lang_items ( ) ;
3939 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| {
4343 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| {
4646 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 ( ( ) )
5653}
5754
5855struct Checker < ' tcx > {
@@ -663,3 +660,63 @@ fn infringing_fields_error<'tcx>(
663660
664661 err. emit ( )
665662}
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