@@ -21,7 +21,7 @@ use rustc_middle::middle::stability::EvalResult;
21
21
use rustc_middle:: ty:: layout:: { LayoutError , MAX_SIMD_LANES } ;
22
22
use rustc_middle:: ty:: subst:: GenericArgKind ;
23
23
use 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 } ;
25
25
use rustc_session:: lint:: builtin:: { UNINHABITED_STATIC , UNSUPPORTED_CALLING_CONVENTIONS } ;
26
26
use rustc_span:: symbol:: sym;
27
27
use rustc_span:: { self , Span } ;
@@ -479,10 +479,29 @@ fn check_opaque_meets_bounds<'tcx>(
479
479
let _ = infcx. inner . borrow_mut ( ) . opaque_type_storage . take_opaque_types ( ) ;
480
480
}
481
481
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
+
482
500
fn check_static_linkage < ' tcx > ( tcx : TyCtxt < ' tcx > , def_id : LocalDefId ) {
483
501
if tcx. codegen_fn_attrs ( def_id) . import_linkage . is_some ( ) {
484
502
if match tcx. type_of ( def_id) . kind ( ) {
485
503
ty:: RawPtr ( _) => false ,
504
+ ty:: Adt ( adt_def, substs) => !is_enum_of_nonnullable_ptr ( tcx, * adt_def, * substs) ,
486
505
_ => true ,
487
506
} {
488
507
tcx. sess . emit_err ( LinkageType { span : tcx. def_span ( def_id) } ) ;
0 commit comments