@@ -8,10 +8,11 @@ use super::*;
88use rustc_attr as attr;
99use rustc_errors:: { Applicability , ErrorGuaranteed , MultiSpan } ;
1010use rustc_hir as hir;
11+ use rustc_hir:: def:: { DefKind , Res } ;
1112use rustc_hir:: def_id:: { DefId , LocalDefId } ;
1213use rustc_hir:: intravisit:: Visitor ;
1314use rustc_hir:: lang_items:: LangItem ;
14- use rustc_hir:: { def :: Res , ItemKind , Node , PathSegment } ;
15+ use rustc_hir:: { ItemKind , Node , PathSegment } ;
1516use rustc_infer:: infer:: type_variable:: { TypeVariableOrigin , TypeVariableOriginKind } ;
1617use rustc_infer:: infer:: { RegionVariableOrigin , TyCtxtInferExt } ;
1718use rustc_infer:: traits:: Obligation ;
@@ -29,7 +30,6 @@ use rustc_trait_selection::traits;
2930use rustc_trait_selection:: traits:: error_reporting:: InferCtxtExt as _;
3031use rustc_ty_utils:: representability:: { self , Representability } ;
3132
32- use rustc_hir:: def:: DefKind ;
3333use std:: iter;
3434use std:: ops:: ControlFlow ;
3535
@@ -93,7 +93,6 @@ pub(super) fn check_fn<'a, 'tcx>(
9393 fcx. return_type_pre_known = return_type_pre_known;
9494
9595 let tcx = fcx. tcx ;
96- let sess = tcx. sess ;
9796 let hir = tcx. hir ( ) ;
9897
9998 let declared_ret_ty = fn_sig. output ( ) ;
@@ -260,85 +259,123 @@ pub(super) fn check_fn<'a, 'tcx>(
260259 if let Some ( panic_impl_did) = tcx. lang_items ( ) . panic_impl ( )
261260 && panic_impl_did == hir. local_def_id ( fn_id) . to_def_id ( )
262261 {
263- if let Some ( panic_info_did) = tcx. lang_items ( ) . panic_info ( ) {
264- if * declared_ret_ty. kind ( ) != ty:: Never {
265- sess. span_err ( decl. output . span ( ) , "return type should be `!`" ) ;
266- }
267-
268- let inputs = fn_sig. inputs ( ) ;
269- let span = hir. span ( fn_id) ;
270- if inputs. len ( ) == 1 {
271- let arg_is_panic_info = match * inputs[ 0 ] . kind ( ) {
272- ty:: Ref ( region, ty, mutbl) => match * ty. kind ( ) {
273- ty:: Adt ( ref adt, _) => {
274- adt. did ( ) == panic_info_did
275- && mutbl == hir:: Mutability :: Not
276- && !region. is_static ( )
277- }
278- _ => false ,
279- } ,
280- _ => false ,
281- } ;
282-
283- if !arg_is_panic_info {
284- sess. span_err ( decl. inputs [ 0 ] . span , "argument should be `&PanicInfo`" ) ;
285- }
286-
287- if let Node :: Item ( item) = hir. get ( fn_id)
288- && let ItemKind :: Fn ( _, ref generics, _) = item. kind
289- && !generics. params . is_empty ( )
290- {
291- sess. span_err ( span, "should have no type parameters" ) ;
292- }
293- } else {
294- let span = sess. source_map ( ) . guess_head_span ( span) ;
295- sess. span_err ( span, "function should have one argument" ) ;
296- }
297- } else {
298- sess. err ( "language item required, but not found: `panic_info`" ) ;
299- }
262+ check_panic_info_fn ( tcx, panic_impl_did. expect_local ( ) , fn_sig, decl, declared_ret_ty) ;
300263 }
301264
302265 // Check that a function marked as `#[alloc_error_handler]` has signature `fn(Layout) -> !`
303266 if let Some ( alloc_error_handler_did) = tcx. lang_items ( ) . oom ( )
304267 && alloc_error_handler_did == hir. local_def_id ( fn_id) . to_def_id ( )
305268 {
306- if let Some ( alloc_layout_did) = tcx. lang_items ( ) . alloc_layout ( ) {
307- if * declared_ret_ty. kind ( ) != ty:: Never {
308- sess. span_err ( decl. output . span ( ) , "return type should be `!`" ) ;
309- }
269+ check_alloc_error_fn ( tcx, alloc_error_handler_did. expect_local ( ) , fn_sig, decl, declared_ret_ty) ;
270+ }
310271
311- let inputs = fn_sig. inputs ( ) ;
312- let span = hir. span ( fn_id) ;
313- if inputs. len ( ) == 1 {
314- let arg_is_alloc_layout = match inputs[ 0 ] . kind ( ) {
315- ty:: Adt ( ref adt, _) => adt. did ( ) == alloc_layout_did,
316- _ => false ,
317- } ;
272+ ( fcx, gen_ty)
273+ }
318274
319- if !arg_is_alloc_layout {
320- sess. span_err ( decl. inputs [ 0 ] . span , "argument should be `Layout`" ) ;
321- }
275+ fn check_panic_info_fn (
276+ tcx : TyCtxt < ' _ > ,
277+ fn_id : LocalDefId ,
278+ fn_sig : ty:: FnSig < ' _ > ,
279+ decl : & hir:: FnDecl < ' _ > ,
280+ declared_ret_ty : Ty < ' _ > ,
281+ ) {
282+ let Some ( panic_info_did) = tcx. lang_items ( ) . panic_info ( ) else {
283+ tcx. sess . err ( "language item required, but not found: `panic_info`" ) ;
284+ return ;
285+ } ;
322286
323- if let Node :: Item ( item) = hir. get ( fn_id)
324- && let ItemKind :: Fn ( _, ref generics, _) = item. kind
325- && !generics. params . is_empty ( )
326- {
327- sess. span_err (
328- span,
329- "`#[alloc_error_handler]` function should have no type parameters" ,
330- ) ;
331- }
332- } else {
333- let span = sess. source_map ( ) . guess_head_span ( span) ;
334- sess. span_err ( span, "function should have one argument" ) ;
287+ if * declared_ret_ty. kind ( ) != ty:: Never {
288+ tcx. sess . span_err ( decl. output . span ( ) , "return type should be `!`" ) ;
289+ }
290+
291+ let span = tcx. def_span ( fn_id) ;
292+ let inputs = fn_sig. inputs ( ) ;
293+ if inputs. len ( ) != 1 {
294+ let span = tcx. sess . source_map ( ) . guess_head_span ( span) ;
295+ tcx. sess . span_err ( span, "function should have one argument" ) ;
296+ return ;
297+ }
298+
299+ let arg_is_panic_info = match * inputs[ 0 ] . kind ( ) {
300+ ty:: Ref ( region, ty, mutbl) => match * ty. kind ( ) {
301+ ty:: Adt ( ref adt, _) => {
302+ adt. did ( ) == panic_info_did && mutbl == hir:: Mutability :: Not && !region. is_static ( )
335303 }
336- } else {
337- sess. err ( "language item required, but not found: `alloc_layout`" ) ;
338- }
304+ _ => false ,
305+ } ,
306+ _ => false ,
307+ } ;
308+
309+ if !arg_is_panic_info {
310+ tcx. sess . span_err ( decl. inputs [ 0 ] . span , "argument should be `&PanicInfo`" ) ;
339311 }
340312
341- ( fcx, gen_ty)
313+ let DefKind :: Fn = tcx. def_kind ( fn_id) else {
314+ let span = tcx. def_span ( fn_id) ;
315+ tcx. sess . span_err ( span, "should be a function" ) ;
316+ return ;
317+ } ;
318+
319+ let generic_counts = tcx. generics_of ( fn_id) . own_counts ( ) ;
320+ if generic_counts. types != 0 {
321+ let span = tcx. def_span ( fn_id) ;
322+ tcx. sess . span_err ( span, "should have no type parameters" ) ;
323+ }
324+ if generic_counts. consts != 0 {
325+ let span = tcx. def_span ( fn_id) ;
326+ tcx. sess . span_err ( span, "should have no const parameters" ) ;
327+ }
328+ }
329+
330+ fn check_alloc_error_fn (
331+ tcx : TyCtxt < ' _ > ,
332+ fn_id : LocalDefId ,
333+ fn_sig : ty:: FnSig < ' _ > ,
334+ decl : & hir:: FnDecl < ' _ > ,
335+ declared_ret_ty : Ty < ' _ > ,
336+ ) {
337+ let Some ( alloc_layout_did) = tcx. lang_items ( ) . alloc_layout ( ) else {
338+ tcx. sess . err ( "language item required, but not found: `alloc_layout`" ) ;
339+ return ;
340+ } ;
341+
342+ if * declared_ret_ty. kind ( ) != ty:: Never {
343+ tcx. sess . span_err ( decl. output . span ( ) , "return type should be `!`" ) ;
344+ }
345+
346+ let inputs = fn_sig. inputs ( ) ;
347+ if inputs. len ( ) != 1 {
348+ let span = tcx. def_span ( fn_id) ;
349+ let span = tcx. sess . source_map ( ) . guess_head_span ( span) ;
350+ tcx. sess . span_err ( span, "function should have one argument" ) ;
351+ return ;
352+ }
353+
354+ let arg_is_alloc_layout = match inputs[ 0 ] . kind ( ) {
355+ ty:: Adt ( ref adt, _) => adt. did ( ) == alloc_layout_did,
356+ _ => false ,
357+ } ;
358+
359+ if !arg_is_alloc_layout {
360+ tcx. sess . span_err ( decl. inputs [ 0 ] . span , "argument should be `Layout`" ) ;
361+ }
362+
363+ let DefKind :: Fn = tcx. def_kind ( fn_id) else {
364+ let span = tcx. def_span ( fn_id) ;
365+ tcx. sess . span_err ( span, "`#[alloc_error_handler]` should be a function" ) ;
366+ return ;
367+ } ;
368+
369+ let generic_counts = tcx. generics_of ( fn_id) . own_counts ( ) ;
370+ if generic_counts. types != 0 {
371+ let span = tcx. def_span ( fn_id) ;
372+ tcx. sess . span_err ( span, "`#[alloc_error_handler]` function should have no type parameters" ) ;
373+ }
374+ if generic_counts. consts != 0 {
375+ let span = tcx. def_span ( fn_id) ;
376+ tcx. sess
377+ . span_err ( span, "`#[alloc_error_handler]` function should have no const parameters" ) ;
378+ }
342379}
343380
344381fn check_struct ( tcx : TyCtxt < ' _ > , def_id : LocalDefId , span : Span ) {
0 commit comments