@@ -223,60 +223,27 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
223
223
"synthetic HIR should have its `generics_of` explicitly fed"
224
224
) ,
225
225
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:?}" ) ,
227
227
} ;
228
228
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
278
243
} ;
279
244
245
+ let param_default_policy = param_default_policy ( node) ;
246
+ let hir_generics = node. generics ( ) . unwrap_or ( hir:: Generics :: empty ( ) ) ;
280
247
let has_self = opt_self. is_some ( ) ;
281
248
let mut parent_has_self = false ;
282
249
let mut own_start = has_self as u32 ;
@@ -312,60 +279,53 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
312
279
prev + type_start
313
280
} ;
314
281
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
+ }
336
303
}
337
304
}
338
- }
339
-
340
- let kind = ty:: GenericParamDefKind :: Type { has_default : default. is_some ( ) , synthetic } ;
341
305
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 }
357
307
}
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
+ }
358
318
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
+ } )
369
329
} ) ) ;
370
330
371
331
// 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 {
444
404
}
445
405
}
446
406
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
+
447
449
fn has_late_bound_regions < ' tcx > ( tcx : TyCtxt < ' tcx > , node : Node < ' tcx > ) -> Option < Span > {
448
450
struct LateBoundRegionsDetector < ' tcx > {
449
451
tcx : TyCtxt < ' tcx > ,
0 commit comments