@@ -37,22 +37,23 @@ 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| {
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+ } ) ( )
5657}
5758
5859struct Checker < ' tcx > {
@@ -663,3 +664,63 @@ fn infringing_fields_error<'tcx>(
663664
664665 err. emit ( )
665666}
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+ // FIXME(compiler-errors): This should and could be deduplicated into a query.
679+ // Find the nontrivial field.
680+ let adt_typing_env = ty:: TypingEnv :: non_body_analysis ( tcx, def. did ( ) ) ;
681+ let nontrivial_field = def. all_fields ( ) . find ( |field_def| {
682+ let field_ty = tcx. type_of ( field_def. did ) . instantiate_identity ( ) ;
683+ !tcx. layout_of ( adt_typing_env. as_query_input ( field_ty) )
684+ . is_ok_and ( |layout| layout. layout . is_1zst ( ) )
685+ } ) ;
686+
687+ if let Some ( nontrivial_field) = nontrivial_field {
688+ // Check that the nontrivial field implements `PointerLike`.
689+ let nontrivial_field = nontrivial_field. ty ( tcx, args) ;
690+ let ( infcx, param_env) = tcx. infer_ctxt ( ) . build_with_typing_env ( typing_env) ;
691+ let ocx = ObligationCtxt :: new ( & infcx) ;
692+ ocx. register_bound (
693+ ObligationCause :: misc ( impl_span, checker. impl_def_id ) ,
694+ param_env,
695+ nontrivial_field,
696+ tcx. lang_items ( ) . pointer_like ( ) . unwrap ( ) ,
697+ ) ;
698+ // FIXME(dyn-star): We should regionck this implementation.
699+ if ocx. select_all_or_error ( ) . is_empty ( ) {
700+ return Ok ( ( ) ) ;
701+ }
702+ }
703+ }
704+
705+ let is_permitted_primitive = match * self_ty. kind ( ) {
706+ ty:: Adt ( def, _) => def. is_box ( ) ,
707+ ty:: Uint ( ..) | ty:: Int ( ..) | ty:: RawPtr ( ..) | ty:: Ref ( ..) | ty:: FnPtr ( ..) => true ,
708+ _ => false ,
709+ } ;
710+
711+ if is_permitted_primitive
712+ && let Ok ( layout) = tcx. layout_of ( typing_env. as_query_input ( self_ty) )
713+ && layout. layout . is_pointer_like ( & tcx. data_layout )
714+ {
715+ return Ok ( ( ) ) ;
716+ }
717+
718+ Err ( tcx
719+ . dcx ( )
720+ . struct_span_err (
721+ impl_span,
722+ "implementation must be applied to type that has the same ABI as a pointer, \
723+ or is `repr(transparent)` and whose field is `PointerLike`",
724+ )
725+ . emit ( ) )
726+ }
0 commit comments