@@ -87,9 +87,8 @@ impl<'tcx> LateLintPass<'tcx> for RuntimeSymbols {
8787 } ;
8888
8989 let def_id = item. owner_id . def_id ;
90- let static_ty = cx. tcx . type_of ( def_id) . instantiate_identity ( ) ;
9190
92- check_static ( cx, & symbol_name, static_ty , item. span ) ;
91+ check_static ( cx, & symbol_name, def_id , item. span ) ;
9392 }
9493 hir:: ItemKind :: ForeignMod { abi : _, items } => {
9594 for item in items {
@@ -107,9 +106,7 @@ impl<'tcx> LateLintPass<'tcx> for RuntimeSymbols {
107106 check_fn ( cx, & symbol_name. name , fn_sig, did) ;
108107 }
109108 ForeignItemKind :: Static ( ..) => {
110- let def_id = item. owner_id . def_id ;
111- let static_ty = cx. tcx . type_of ( def_id) . instantiate_identity ( ) ;
112- check_static ( cx, & symbol_name. name , static_ty, item. span ) ;
109+ check_static ( cx, & symbol_name. name , did, item. span ) ;
113110 }
114111 ForeignItemKind :: Type => return ,
115112 }
@@ -163,7 +160,7 @@ fn check_fn(cx: &LateContext<'_>, symbol_name: &str, sig: FnSig<'_>, did: LocalD
163160 }
164161}
165162
166- fn check_static < ' tcx > ( cx : & LateContext < ' tcx > , symbol_name : & str , static_ty : Ty < ' tcx > , sp : Span ) {
163+ fn check_static < ' tcx > ( cx : & LateContext < ' tcx > , symbol_name : & str , did : LocalDefId , sp : Span ) {
167164 let Some ( expected_symbol) = EXPECTED_SYMBOLS . iter ( ) . find ( |es| es. symbol == symbol_name) else {
168165 // The symbol name does not correspond to a runtime symbols, bail out
169166 return ;
@@ -174,22 +171,35 @@ fn check_static<'tcx>(cx: &LateContext<'tcx>, symbol_name: &str, static_ty: Ty<'
174171 return ;
175172 } ;
176173
177- // Unconditionally report a mismatch, a static cannot ever be a function definition
174+ // Get the static type
175+ let static_ty = cx. tcx . type_of ( did) . instantiate_identity ( ) . skip_norm_wip ( ) ;
178176
177+ // Peel Option<...> and get the inner type (see std weak! macro with #[linkage = "extern_weak"])
178+ let inner_static_ty: Ty < ' _ > = match static_ty. kind ( ) {
179+ ty:: Adt ( def, args) if Some ( def. did ( ) ) == cx. tcx . lang_items ( ) . option_type ( ) => {
180+ args. type_at ( 0 )
181+ }
182+ _ => static_ty,
183+ } ;
184+
185+ // Get the expected symbol function signature
179186 let lang_sig = cx. tcx . normalize_erasing_regions (
180187 cx. typing_env ( ) ,
181188 cx. tcx . fn_sig ( expected_def_id) . instantiate_identity ( ) ,
182189 ) ;
183190
184191 let expected = Ty :: new_fn_ptr ( cx. tcx , lang_sig) ;
185192
186- cx. emit_span_lint (
187- INVALID_RUNTIME_SYMBOL_DEFINITIONS ,
188- sp,
189- RedefiningRuntimeSymbolsDiag :: Static {
190- static_ty,
191- symbol_name : symbol_name. to_string ( ) ,
192- expected_fn_sig : expected,
193- } ,
194- ) ;
193+ // Compare the expected function signature with the static type, report an error if they don't match
194+ if expected != inner_static_ty {
195+ cx. emit_span_lint (
196+ INVALID_RUNTIME_SYMBOL_DEFINITIONS ,
197+ sp,
198+ RedefiningRuntimeSymbolsDiag :: Static {
199+ static_ty,
200+ symbol_name : symbol_name. to_string ( ) ,
201+ expected_fn_sig : expected,
202+ } ,
203+ ) ;
204+ }
195205}
0 commit comments