@@ -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- `struct`, `enum`, `type`, or `trait` definitions",
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