@@ -9,7 +9,9 @@ use rustc_data_structures::thin_vec::ThinVec;
99use rustc_errors:: struct_span_err;
1010use rustc_hir as hir;
1111use rustc_hir:: def:: Res ;
12+ use rustc_hir:: definitions:: DefPathData ;
1213use rustc_session:: parse:: feature_err;
14+ use rustc_span:: hygiene:: ExpnId ;
1315use rustc_span:: source_map:: { respan, DesugaringKind , Span , Spanned } ;
1416use rustc_span:: symbol:: { sym, Ident , Symbol } ;
1517use rustc_span:: { hygiene:: ForLoopLoc , DUMMY_SP } ;
@@ -42,8 +44,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
4244 }
4345 ExprKind :: Tup ( ref elts) => hir:: ExprKind :: Tup ( self . lower_exprs ( elts) ) ,
4446 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+ }
4753 }
4854 ExprKind :: MethodCall ( ref seg, ref args, span) => {
4955 let hir_seg = self . arena . alloc ( self . lower_path_segment (
@@ -292,6 +298,86 @@ impl<'hir> LoweringContext<'_, 'hir> {
292298 }
293299 }
294300
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+
295381 /// Emit an error and lower `ast::ExprKind::Let(pat, scrutinee)` into:
296382 /// ```rust
297383 /// match scrutinee { pats => true, _ => false }
0 commit comments