@@ -223,60 +223,27 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
223223            "synthetic HIR should have its `generics_of` explicitly fed" 
224224        ) , 
225225
226-         _ => span_bug ! ( tcx. def_span( def_id) ,  "unhandled  node {node:?}" ) , 
226+         _ => span_bug ! ( tcx. def_span( def_id) ,  "generics_of: unexpected  node kind  {node:?}" ) , 
227227    } ; 
228228
229-     enum  Defaults  { 
230-         Allowed , 
231-         // See #36887 
232-         FutureCompatDisallowed , 
233-         Deny , 
234-     } 
235- 
236-     let  hir_generics = node. generics ( ) . unwrap_or ( hir:: Generics :: empty ( ) ) ; 
237-     let  ( opt_self,  allow_defaults)  = match  node { 
238-         Node :: Item ( item)  => { 
239-             match  item. kind  { 
240-                 ItemKind :: Trait ( ..)  | ItemKind :: TraitAlias ( ..)  => { 
241-                     // Add in the self type parameter. 
242-                     // 
243-                     // Something of a hack: use the node id for the trait, also as 
244-                     // the node id for the Self type parameter. 
245-                     let  opt_self = Some ( ty:: GenericParamDef  { 
246-                         index :  0 , 
247-                         name :  kw:: SelfUpper , 
248-                         def_id :  def_id. to_def_id ( ) , 
249-                         pure_wrt_drop :  false , 
250-                         kind :  ty:: GenericParamDefKind :: Type  { 
251-                             has_default :  false , 
252-                             synthetic :  false , 
253-                         } , 
254-                     } ) ; 
255- 
256-                     ( opt_self,  Defaults :: Allowed ) 
257-                 } 
258-                 ItemKind :: TyAlias ( ..) 
259-                 | ItemKind :: Enum ( ..) 
260-                 | ItemKind :: Struct ( ..) 
261-                 | ItemKind :: Union ( ..)  => ( None ,  Defaults :: Allowed ) , 
262-                 ItemKind :: Const ( ..)  => ( None ,  Defaults :: Deny ) , 
263-                 _ => ( None ,  Defaults :: FutureCompatDisallowed ) , 
264-             } 
265-         } 
266- 
267-         Node :: OpaqueTy ( ..)  => ( None ,  Defaults :: Allowed ) , 
268- 
269-         // GATs 
270-         Node :: TraitItem ( item)  if  matches ! ( item. kind,  TraitItemKind :: Type ( ..) )  => { 
271-             ( None ,  Defaults :: Deny ) 
272-         } 
273-         Node :: ImplItem ( item)  if  matches ! ( item. kind,  ImplItemKind :: Type ( ..) )  => { 
274-             ( None ,  Defaults :: Deny ) 
275-         } 
276- 
277-         _ => ( None ,  Defaults :: FutureCompatDisallowed ) , 
229+     // Add in the self type parameter. 
230+     let  opt_self = if  let  Node :: Item ( item)  = node
231+         && let  ItemKind :: Trait ( ..)  | ItemKind :: TraitAlias ( ..)  = item. kind 
232+     { 
233+         // Something of a hack: We reuse the node ID of the trait for the self type parameter. 
234+         Some ( ty:: GenericParamDef  { 
235+             index :  0 , 
236+             name :  kw:: SelfUpper , 
237+             def_id :  def_id. to_def_id ( ) , 
238+             pure_wrt_drop :  false , 
239+             kind :  ty:: GenericParamDefKind :: Type  {  has_default :  false ,  synthetic :  false  } , 
240+         } ) 
241+     }  else  { 
242+         None 
278243    } ; 
279244
245+     let  param_default_policy = param_default_policy ( node) ; 
246+     let  hir_generics = node. generics ( ) . unwrap_or ( hir:: Generics :: empty ( ) ) ; 
280247    let  has_self = opt_self. is_some ( ) ; 
281248    let  mut  parent_has_self = false ; 
282249    let  mut  own_start = has_self as  u32 ; 
@@ -312,60 +279,53 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
312279        prev + type_start
313280    } ; 
314281
315-     const   TYPE_DEFAULT_NOT_ALLOWED :   & ' static   str  =  "defaults for type parameters are only allowed in  \ 
316- `struct`, `enum`, `type`, or `trait` definitions "; 
317- 
318-     own_params . extend ( hir_generics . params . iter ( ) . filter_map ( |param|  match  param . kind   { 
319-         GenericParamKind :: Lifetime  {  ..  }  => None , 
320-         GenericParamKind :: Type   {  default ,  synthetic ,  ..  }  =>  { 
321-             if  default . is_some ( )  { 
322-                 match  allow_defaults  { 
323-                     Defaults :: Allowed  => { } 
324-                     Defaults :: FutureCompatDisallowed  =>  { 
325-                         tcx . node_span_lint ( 
326-                             lint :: builtin :: INVALID_TYPE_PARAM_DEFAULT , 
327-                             param. hir_id , 
328-                             param . span , 
329-                             |lint|  { 
330-                                 lint . primary_message ( TYPE_DEFAULT_NOT_ALLOWED ) ; 
331-                             } , 
332-                         ) ; 
333-                     } 
334-                     Defaults :: Deny  =>  { 
335-                         tcx . dcx ( ) . span_err ( param . span ,   TYPE_DEFAULT_NOT_ALLOWED ) ; 
282+     own_params . extend ( hir_generics . params . iter ( ) . filter_map ( |param|  { 
283+          const   MESSAGE :   & str  =  "defaults for generic parameters are not allowed here "; 
284+          let  kind =  match  param . kind   { 
285+              GenericParamKind :: Lifetime   {  ..  }  =>  return   None , 
286+              GenericParamKind :: Type  {  default ,  synthetic  }  => { 
287+                  if  default . is_some ( )  { 
288+                      match  param_default_policy . expect ( "no policy for generic param default" )  { 
289+                          ParamDefaultPolicy :: Allowed  =>  { } 
290+                          ParamDefaultPolicy :: FutureCompatForbidden  => { 
291+                             tcx . node_span_lint ( 
292+                                 lint :: builtin :: INVALID_TYPE_PARAM_DEFAULT , 
293+                                 param . hir_id , 
294+                                  param. span , 
295+                                 |lint|  { 
296+                                     lint . primary_message ( MESSAGE ) ; 
297+                                 } , 
298+                             ) ; 
299+                         } 
300+                          ParamDefaultPolicy :: Forbidden  =>  { 
301+                             tcx . dcx ( ) . span_err ( param . span ,   MESSAGE ) ; 
302+                         } 
336303                    } 
337304                } 
338-             } 
339- 
340-             let  kind = ty:: GenericParamDefKind :: Type  {  has_default :  default. is_some ( ) ,  synthetic } ; 
341305
342-             Some ( ty:: GenericParamDef  { 
343-                 index :  next_index ( ) , 
344-                 name :  param. name . ident ( ) . name , 
345-                 def_id :  param. def_id . to_def_id ( ) , 
346-                 pure_wrt_drop :  param. pure_wrt_drop , 
347-                 kind, 
348-             } ) 
349-         } 
350-         GenericParamKind :: Const  {  ty :  _,  default,  synthetic }  => { 
351-             if  !matches ! ( allow_defaults,  Defaults :: Allowed )  && default. is_some ( )  { 
352-                 tcx. dcx ( ) . span_err ( 
353-                     param. span , 
354-                     "defaults for const parameters are only allowed in \  
355- , 
356-                 ) ; 
306+                 ty:: GenericParamDefKind :: Type  {  has_default :  default. is_some ( ) ,  synthetic } 
357307            } 
308+             GenericParamKind :: Const  {  ty :  _,  default,  synthetic }  => { 
309+                 if  default. is_some ( )  { 
310+                     match  param_default_policy. expect ( "no policy for generic param default" )  { 
311+                         ParamDefaultPolicy :: Allowed  => { } 
312+                         ParamDefaultPolicy :: FutureCompatForbidden 
313+                         | ParamDefaultPolicy :: Forbidden  => { 
314+                             tcx. dcx ( ) . span_err ( param. span ,  MESSAGE ) ; 
315+                         } 
316+                     } 
317+                 } 
358318
359-             let  index =  next_index ( ) ; 
360- 
361-              Some ( ty :: GenericParamDef   { 
362-                 index , 
363-                  name :  param . name . ident ( ) . name , 
364-                  def_id :  param. def_id . to_def_id ( ) , 
365-                  pure_wrt_drop :  param. pure_wrt_drop , 
366-                  kind :  ty :: GenericParamDefKind :: Const   {   has_default :  default . is_some ( ) ,  synthetic  } , 
367-             } ) 
368-         } 
319+                 ty :: GenericParamDefKind :: Const   {   has_default :  default . is_some ( ) ,  synthetic  } 
320+              } 
321+         } ; 
322+         Some ( ty :: GenericParamDef   { 
323+             index :   next_index ( ) , 
324+             name :  param. name . ident ( ) . name , 
325+             def_id :  param. def_id . to_def_id ( ) , 
326+             pure_wrt_drop :  param . pure_wrt_drop , 
327+             kind , 
328+         } ) 
369329    } ) ) ; 
370330
371331    // provide junk type parameter defs - the only place that 
@@ -444,6 +404,48 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
444404    } 
445405} 
446406
407+ #[ derive( Clone ,  Copy ) ]  
408+ enum  ParamDefaultPolicy  { 
409+     Allowed , 
410+     /// Tracked in <https://github.com/rust-lang/rust/issues/36887>. 
411+ FutureCompatForbidden , 
412+     Forbidden , 
413+ } 
414+ 
415+ fn  param_default_policy ( node :  Node < ' _ > )  -> Option < ParamDefaultPolicy >  { 
416+     use  rustc_hir:: * ; 
417+ 
418+     Some ( match  node { 
419+         Node :: Item ( item)  => match  item. kind  { 
420+             ItemKind :: Trait ( ..) 
421+             | ItemKind :: TraitAlias ( ..) 
422+             | ItemKind :: TyAlias ( ..) 
423+             | ItemKind :: Enum ( ..) 
424+             | ItemKind :: Struct ( ..) 
425+             | ItemKind :: Union ( ..)  => ParamDefaultPolicy :: Allowed , 
426+             ItemKind :: Fn  {  .. }  | ItemKind :: Impl ( _)  => ParamDefaultPolicy :: FutureCompatForbidden , 
427+             // Re. GCI, we're not bound by backward compatibility. 
428+             ItemKind :: Const ( ..)  => ParamDefaultPolicy :: Forbidden , 
429+             _ => return  None , 
430+         } , 
431+         Node :: TraitItem ( item)  => match  item. kind  { 
432+             // Re. GATs and GACs (generic_const_items), we're not bound by backward compatibility. 
433+             TraitItemKind :: Const ( ..)  | TraitItemKind :: Type ( ..)  => ParamDefaultPolicy :: Forbidden , 
434+             TraitItemKind :: Fn ( ..)  => ParamDefaultPolicy :: FutureCompatForbidden , 
435+         } , 
436+         Node :: ImplItem ( item)  => match  item. kind  { 
437+             // Re. GATs and GACs (generic_const_items), we're not bound by backward compatibility. 
438+             ImplItemKind :: Const ( ..)  | ImplItemKind :: Type ( ..)  => ParamDefaultPolicy :: Forbidden , 
439+             ImplItemKind :: Fn ( ..)  => ParamDefaultPolicy :: FutureCompatForbidden , 
440+         } , 
441+         // Generic params are (semantically) invalid on foreign items. Still, for maximum forward 
442+         // compatibility, let's hard-reject defaults on them. 
443+         Node :: ForeignItem ( _)  => ParamDefaultPolicy :: Forbidden , 
444+         Node :: OpaqueTy ( ..)  => ParamDefaultPolicy :: Allowed , 
445+         _ => return  None , 
446+     } ) 
447+ } 
448+ 
447449fn  has_late_bound_regions < ' tcx > ( tcx :  TyCtxt < ' tcx > ,  node :  Node < ' tcx > )  -> Option < Span >  { 
448450    struct  LateBoundRegionsDetector < ' tcx >  { 
449451        tcx :  TyCtxt < ' tcx > , 
0 commit comments