@@ -9,7 +9,9 @@ use rustc_data_structures::thin_vec::ThinVec;
9
9
use rustc_errors:: struct_span_err;
10
10
use rustc_hir as hir;
11
11
use rustc_hir:: def:: Res ;
12
+ use rustc_hir:: definitions:: DefPathData ;
12
13
use rustc_session:: parse:: feature_err;
14
+ use rustc_span:: hygiene:: ExpnId ;
13
15
use rustc_span:: source_map:: { respan, DesugaringKind , Span , Spanned } ;
14
16
use rustc_span:: symbol:: { sym, Ident , Symbol } ;
15
17
use rustc_span:: { hygiene:: ForLoopLoc , DUMMY_SP } ;
@@ -42,8 +44,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
42
44
}
43
45
ExprKind :: Tup ( ref elts) => hir:: ExprKind :: Tup ( self . lower_exprs ( elts) ) ,
44
46
ExprKind :: Call ( ref f, ref args) => {
45
- let f = self . lower_expr ( f) ;
46
- hir:: ExprKind :: Call ( f, self . lower_exprs ( args) )
47
+ if let Some ( legacy_args) = self . legacy_const_generic_args ( f) {
48
+ self . lower_legacy_const_generics ( ( * * f) . clone ( ) , args. clone ( ) , & legacy_args)
49
+ } else {
50
+ let f = self . lower_expr ( f) ;
51
+ hir:: ExprKind :: Call ( f, self . lower_exprs ( args) )
52
+ }
47
53
}
48
54
ExprKind :: MethodCall ( ref seg, ref args, span) => {
49
55
let hir_seg = self . arena . alloc ( self . lower_path_segment (
@@ -292,6 +298,86 @@ impl<'hir> LoweringContext<'_, 'hir> {
292
298
}
293
299
}
294
300
301
+ /// Checks if an expression refers to a function marked with
302
+ /// `#[rustc_legacy_const_generics]` and returns the argument index list
303
+ /// from the attribute.
304
+ fn legacy_const_generic_args ( & mut self , expr : & Expr ) -> Option < Vec < usize > > {
305
+ if let ExprKind :: Path ( None , path) = & expr. kind {
306
+ if path. segments . last ( ) . unwrap ( ) . args . is_some ( ) {
307
+ return None ;
308
+ }
309
+ if let Some ( partial_res) = self . resolver . get_partial_res ( expr. id ) {
310
+ if partial_res. unresolved_segments ( ) != 0 {
311
+ return None ;
312
+ }
313
+ if let Res :: Def ( hir:: def:: DefKind :: Fn , def_id) = partial_res. base_res ( ) {
314
+ let attrs = self . item_attrs ( def_id) ;
315
+ let attr = attrs
316
+ . iter ( )
317
+ . find ( |a| self . sess . check_name ( a, sym:: rustc_legacy_const_generics) ) ?;
318
+ let mut ret = vec ! [ ] ;
319
+ for meta in attr. meta_item_list ( ) ? {
320
+ match meta. literal ( ) ?. kind {
321
+ LitKind :: Int ( a, _) => {
322
+ ret. push ( a as usize ) ;
323
+ }
324
+ _ => panic ! ( "invalid arg index" ) ,
325
+ }
326
+ }
327
+ return Some ( ret) ;
328
+ }
329
+ }
330
+ }
331
+ None
332
+ }
333
+
334
+ fn lower_legacy_const_generics (
335
+ & mut self ,
336
+ mut f : Expr ,
337
+ args : Vec < AstP < Expr > > ,
338
+ legacy_args_idx : & [ usize ] ,
339
+ ) -> hir:: ExprKind < ' hir > {
340
+ let path = match f. kind {
341
+ ExprKind :: Path ( None , ref mut path) => path,
342
+ _ => unreachable ! ( ) ,
343
+ } ;
344
+
345
+ // Split the arguments into const generics and normal arguments
346
+ let mut real_args = vec ! [ ] ;
347
+ let mut generic_args = vec ! [ ] ;
348
+ for ( idx, arg) in args. into_iter ( ) . enumerate ( ) {
349
+ if legacy_args_idx. contains ( & idx) {
350
+ let parent_def_id = self . current_hir_id_owner . last ( ) . unwrap ( ) . 0 ;
351
+ let node_id = self . resolver . next_node_id ( ) ;
352
+
353
+ // Add a definition for the in-band const def.
354
+ self . resolver . create_def (
355
+ parent_def_id,
356
+ node_id,
357
+ DefPathData :: AnonConst ,
358
+ ExpnId :: root ( ) ,
359
+ arg. span ,
360
+ ) ;
361
+
362
+ let anon_const = AnonConst { id : node_id, value : arg } ;
363
+ generic_args. push ( AngleBracketedArg :: Arg ( GenericArg :: Const ( anon_const) ) ) ;
364
+ } else {
365
+ real_args. push ( arg) ;
366
+ }
367
+ }
368
+
369
+ // Add generic args to the last element of the path
370
+ path. segments . last_mut ( ) . unwrap ( ) . args =
371
+ Some ( AstP ( GenericArgs :: AngleBracketed ( AngleBracketedArgs {
372
+ span : DUMMY_SP ,
373
+ args : generic_args,
374
+ } ) ) ) ;
375
+
376
+ // Now lower everything as normal.
377
+ let f = self . lower_expr ( & f) ;
378
+ hir:: ExprKind :: Call ( f, self . lower_exprs ( & real_args) )
379
+ }
380
+
295
381
/// Emit an error and lower `ast::ExprKind::Let(pat, scrutinee)` into:
296
382
/// ```rust
297
383
/// match scrutinee { pats => true, _ => false }
0 commit comments