@@ -21,7 +21,7 @@ use rustc_middle::middle::stability::EvalResult;
2121use rustc_middle:: ty:: layout:: { LayoutError , MAX_SIMD_LANES } ;
2222use rustc_middle:: ty:: subst:: GenericArgKind ;
2323use rustc_middle:: ty:: util:: { Discr , IntTypeExt } ;
24- use rustc_middle:: ty:: { self , ParamEnv , Ty , TyCtxt , TypeSuperVisitable , TypeVisitable } ;
24+ use rustc_middle:: ty:: { self , AdtDef , ParamEnv , Ty , TyCtxt , TypeSuperVisitable , TypeVisitable } ;
2525use rustc_session:: lint:: builtin:: { UNINHABITED_STATIC , UNSUPPORTED_CALLING_CONVENTIONS } ;
2626use rustc_span:: symbol:: sym;
2727use rustc_span:: { self , Span } ;
@@ -479,10 +479,29 @@ fn check_opaque_meets_bounds<'tcx>(
479479 let _ = infcx. inner . borrow_mut ( ) . opaque_type_storage . take_opaque_types ( ) ;
480480}
481481
482+ fn is_enum_of_nonnullable_ptr < ' tcx > (
483+ tcx : TyCtxt < ' tcx > ,
484+ adt_def : AdtDef < ' tcx > ,
485+ substs : SubstsRef < ' tcx > ,
486+ ) -> bool {
487+ if adt_def. repr ( ) . inhibit_enum_layout_opt ( ) {
488+ return false ;
489+ }
490+
491+ let [ var_one, var_two] = & adt_def. variants ( ) . raw [ ..] else {
492+ return false ;
493+ } ;
494+ let ( ( [ ] , [ field] ) | ( [ field] , [ ] ) ) = ( & var_one. fields [ ..] , & var_two. fields [ ..] ) else {
495+ return false ;
496+ } ;
497+ matches ! ( field. ty( tcx, substs) . kind( ) , ty:: FnPtr ( ..) | ty:: Ref ( ..) )
498+ }
499+
482500fn check_static_linkage < ' tcx > ( tcx : TyCtxt < ' tcx > , def_id : LocalDefId ) {
483501 if tcx. codegen_fn_attrs ( def_id) . import_linkage . is_some ( ) {
484502 if match tcx. type_of ( def_id) . kind ( ) {
485503 ty:: RawPtr ( _) => false ,
504+ ty:: Adt ( adt_def, substs) => !is_enum_of_nonnullable_ptr ( tcx, * adt_def, * substs) ,
486505 _ => true ,
487506 } {
488507 tcx. sess . emit_err ( LinkageType { span : tcx. def_span ( def_id) } ) ;
0 commit comments