@@ -6,9 +6,11 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
6
6
use rustc_errors:: { struct_span_err, Applicability , DiagnosticBuilder } ;
7
7
use rustc_hir as hir;
8
8
use rustc_hir:: def_id:: { DefId , LocalDefId } ;
9
- use rustc_hir:: itemlikevisit:: ParItemLikeVisitor ;
9
+ use rustc_hir:: intravisit as hir_visit;
10
+ use rustc_hir:: intravisit:: Visitor ;
10
11
use rustc_hir:: lang_items;
11
12
use rustc_hir:: ItemKind ;
13
+ use rustc_middle:: hir:: map as hir_map;
12
14
use rustc_middle:: ty:: subst:: { GenericArgKind , InternalSubsts , Subst } ;
13
15
use rustc_middle:: ty:: trait_def:: TraitSpecializationKind ;
14
16
use rustc_middle:: ty:: {
@@ -275,6 +277,95 @@ pub fn check_impl_item(tcx: TyCtxt<'_>, def_id: LocalDefId) {
275
277
check_associated_item ( tcx, impl_item. hir_id , impl_item. span , method_sig) ;
276
278
}
277
279
280
+ fn check_param_wf ( tcx : TyCtxt < ' _ > , param : & hir:: GenericParam < ' _ > ) {
281
+ match param. kind {
282
+ // We currently only check wf of const params here.
283
+ hir:: GenericParamKind :: Lifetime { .. } | hir:: GenericParamKind :: Type { .. } => ( ) ,
284
+
285
+ // Const parameters are well formed if their
286
+ // type is structural match.
287
+ hir:: GenericParamKind :: Const { ty : hir_ty } => {
288
+ let ty = tcx. type_of ( tcx. hir ( ) . local_def_id ( param. hir_id ) ) ;
289
+
290
+ let err_ty_str;
291
+ let err = if tcx. features ( ) . min_const_generics {
292
+ match ty. kind {
293
+ ty:: Bool | ty:: Char | ty:: Int ( _) | ty:: Uint ( _) | ty:: Error ( _) => None ,
294
+ ty:: FnPtr ( _) => Some ( "function pointers" ) ,
295
+ ty:: RawPtr ( _) => Some ( "raw pointers" ) ,
296
+ _ => {
297
+ err_ty_str = format ! ( "`{}`" , ty) ;
298
+ Some ( err_ty_str. as_str ( ) )
299
+ }
300
+ }
301
+ } else {
302
+ match ty. peel_refs ( ) . kind {
303
+ ty:: FnPtr ( _) => Some ( "function pointers" ) ,
304
+ ty:: RawPtr ( _) => Some ( "raw pointers" ) ,
305
+ _ => None ,
306
+ }
307
+ } ;
308
+ if let Some ( unsupported_type) = err {
309
+ let mut err = tcx. sess . struct_span_err (
310
+ hir_ty. span ,
311
+ & format ! ( "using {} as const generic parameters is forbidden" , unsupported_type) ,
312
+ ) ;
313
+
314
+ if tcx. features ( ) . min_const_generics {
315
+ err. note ( "the only supported types are integers, `bool` and `char`" )
316
+ . note ( "more complex types are supported with `#[feature(const_generics)]`" )
317
+ . emit ( )
318
+ } else {
319
+ err. emit ( ) ;
320
+ }
321
+ } ;
322
+ if traits:: search_for_structural_match_violation ( param. hir_id , param. span , tcx, ty)
323
+ . is_some ( )
324
+ {
325
+ // We use the same error code in both branches, because this is really the same
326
+ // issue: we just special-case the message for type parameters to make it
327
+ // clearer.
328
+ if let ty:: Param ( _) = ty. peel_refs ( ) . kind {
329
+ // Const parameters may not have type parameters as their types,
330
+ // because we cannot be sure that the type parameter derives `PartialEq`
331
+ // and `Eq` (just implementing them is not enough for `structural_match`).
332
+ struct_span_err ! (
333
+ tcx. sess,
334
+ hir_ty. span,
335
+ E0741 ,
336
+ "`{}` is not guaranteed to `#[derive(PartialEq, Eq)]`, so may not be \
337
+ used as the type of a const parameter",
338
+ ty,
339
+ )
340
+ . span_label (
341
+ hir_ty. span ,
342
+ format ! ( "`{}` may not derive both `PartialEq` and `Eq`" , ty) ,
343
+ )
344
+ . note (
345
+ "it is not currently possible to use a type parameter as the type of a \
346
+ const parameter",
347
+ )
348
+ . emit ( ) ;
349
+ } else {
350
+ struct_span_err ! (
351
+ tcx. sess,
352
+ hir_ty. span,
353
+ E0741 ,
354
+ "`{}` must be annotated with `#[derive(PartialEq, Eq)]` to be used as \
355
+ the type of a const parameter",
356
+ ty,
357
+ )
358
+ . span_label (
359
+ hir_ty. span ,
360
+ format ! ( "`{}` doesn't derive both `PartialEq` and `Eq`" , ty) ,
361
+ )
362
+ . emit ( ) ;
363
+ }
364
+ }
365
+ }
366
+ }
367
+ }
368
+
278
369
fn check_associated_item (
279
370
tcx : TyCtxt < ' _ > ,
280
371
item_id : hir:: HirId ,
@@ -1292,23 +1383,38 @@ impl CheckTypeWellFormedVisitor<'tcx> {
1292
1383
}
1293
1384
}
1294
1385
1295
- impl ParItemLikeVisitor < ' tcx > for CheckTypeWellFormedVisitor < ' tcx > {
1296
- fn visit_item ( & self , i : & ' tcx hir:: Item < ' tcx > ) {
1386
+ impl Visitor < ' tcx > for CheckTypeWellFormedVisitor < ' tcx > {
1387
+ type Map = hir_map:: Map < ' tcx > ;
1388
+
1389
+ fn nested_visit_map ( & mut self ) -> hir_visit:: NestedVisitorMap < Self :: Map > {
1390
+ hir_visit:: NestedVisitorMap :: OnlyBodies ( self . tcx . hir ( ) )
1391
+ }
1392
+
1393
+ fn visit_item ( & mut self , i : & ' tcx hir:: Item < ' tcx > ) {
1297
1394
debug ! ( "visit_item: {:?}" , i) ;
1298
1395
let def_id = self . tcx . hir ( ) . local_def_id ( i. hir_id ) ;
1299
1396
self . tcx . ensure ( ) . check_item_well_formed ( def_id) ;
1397
+ hir_visit:: walk_item ( self , i) ;
1300
1398
}
1301
1399
1302
- fn visit_trait_item ( & self , trait_item : & ' tcx hir:: TraitItem < ' tcx > ) {
1400
+ fn visit_trait_item ( & mut self , trait_item : & ' tcx hir:: TraitItem < ' tcx > ) {
1303
1401
debug ! ( "visit_trait_item: {:?}" , trait_item) ;
1304
1402
let def_id = self . tcx . hir ( ) . local_def_id ( trait_item. hir_id ) ;
1305
1403
self . tcx . ensure ( ) . check_trait_item_well_formed ( def_id) ;
1404
+ hir_visit:: walk_trait_item ( self , trait_item) ;
1306
1405
}
1307
1406
1308
- fn visit_impl_item ( & self , impl_item : & ' tcx hir:: ImplItem < ' tcx > ) {
1407
+ fn visit_impl_item ( & mut self , impl_item : & ' tcx hir:: ImplItem < ' tcx > ) {
1309
1408
debug ! ( "visit_impl_item: {:?}" , impl_item) ;
1310
1409
let def_id = self . tcx . hir ( ) . local_def_id ( impl_item. hir_id ) ;
1311
1410
self . tcx . ensure ( ) . check_impl_item_well_formed ( def_id) ;
1411
+ hir_visit:: walk_impl_item ( self , impl_item) ;
1412
+ }
1413
+
1414
+ fn visit_generic_param ( & mut self , p : & ' tcx hir:: GenericParam < ' tcx > ) {
1415
+ check_param_wf ( self . tcx , p) ;
1416
+ // No need to walk further here, there is nothing interesting
1417
+ // inside of generic params we don't already check in `check_param_wf`.
1312
1418
}
1313
1419
}
1314
1420
0 commit comments