@@ -32,13 +32,16 @@ use trans::type_of;
32
32
use middle:: subst:: Substs ;
33
33
use middle:: ty:: { self , Ty } ;
34
34
use util:: ppaux:: { Repr , ty_to_string} ;
35
+ use util:: nodemap:: NodeMap ;
35
36
36
37
use std:: iter:: repeat;
37
38
use libc:: c_uint;
38
39
use syntax:: { ast, ast_util} ;
39
40
use syntax:: parse:: token;
40
41
use syntax:: ptr:: P ;
41
42
43
+ type FnArgMap < ' a > = Option < & ' a NodeMap < ValueRef > > ;
44
+
42
45
pub fn const_lit ( cx : & CrateContext , e : & ast:: Expr , lit : & ast:: Lit )
43
46
-> ValueRef {
44
47
let _icx = push_ctxt ( "trans_lit" ) ;
@@ -162,6 +165,29 @@ fn const_deref<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
162
165
}
163
166
}
164
167
168
+ fn const_fn_call < ' a , ' tcx > ( ccx : & CrateContext < ' a , ' tcx > ,
169
+ node : ExprOrMethodCall ,
170
+ def_id : ast:: DefId ,
171
+ arg_vals : & [ ValueRef ] ,
172
+ param_substs : & ' tcx Substs < ' tcx > ) -> ValueRef {
173
+ let fn_like = const_eval:: lookup_const_fn_by_id ( ccx. tcx ( ) , def_id) ;
174
+ let fn_like = fn_like. expect ( "lookup_const_fn_by_id failed in const_fn_call" ) ;
175
+
176
+ let args = & fn_like. decl ( ) . inputs ;
177
+ assert_eq ! ( args. len( ) , arg_vals. len( ) ) ;
178
+
179
+ let arg_ids = args. iter ( ) . map ( |arg| arg. pat . id ) ;
180
+ let fn_args = arg_ids. zip ( arg_vals. iter ( ) . cloned ( ) ) . collect ( ) ;
181
+
182
+ let substs = ccx. tcx ( ) . mk_substs ( node_id_substs ( ccx, node, param_substs) ) ;
183
+ match fn_like. body ( ) . expr {
184
+ Some ( ref expr) => {
185
+ const_expr ( ccx, & * * expr, substs, Some ( & fn_args) ) . 0
186
+ }
187
+ None => C_nil ( ccx)
188
+ }
189
+ }
190
+
165
191
pub fn get_const_expr < ' a , ' tcx > ( ccx : & CrateContext < ' a , ' tcx > ,
166
192
def_id : ast:: DefId ,
167
193
ref_expr : & ast:: Expr )
@@ -220,9 +246,9 @@ pub fn get_const_expr_as_global<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
220
246
// references, even when only the latter are correct.
221
247
let ty = monomorphize:: apply_param_substs ( ccx. tcx ( ) , param_substs,
222
248
& ty:: expr_ty ( ccx. tcx ( ) , expr) ) ;
223
- const_expr_unadjusted ( ccx, expr, ty, param_substs)
249
+ const_expr_unadjusted ( ccx, expr, ty, param_substs, None )
224
250
} else {
225
- const_expr ( ccx, expr, param_substs) . 0
251
+ const_expr ( ccx, expr, param_substs, None ) . 0
226
252
} ;
227
253
228
254
// boolean SSA values are i1, but they have to be stored in i8 slots,
@@ -242,11 +268,12 @@ pub fn get_const_expr_as_global<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
242
268
243
269
pub fn const_expr < ' a , ' tcx > ( cx : & CrateContext < ' a , ' tcx > ,
244
270
e : & ast:: Expr ,
245
- param_substs : & ' tcx Substs < ' tcx > )
271
+ param_substs : & ' tcx Substs < ' tcx > ,
272
+ fn_args : FnArgMap )
246
273
-> ( ValueRef , Ty < ' tcx > ) {
247
274
let ety = monomorphize:: apply_param_substs ( cx. tcx ( ) , param_substs,
248
275
& ty:: expr_ty ( cx. tcx ( ) , e) ) ;
249
- let llconst = const_expr_unadjusted ( cx, e, ety, param_substs) ;
276
+ let llconst = const_expr_unadjusted ( cx, e, ety, param_substs, fn_args ) ;
250
277
let mut llconst = llconst;
251
278
let mut ety_adjusted = monomorphize:: apply_param_substs ( cx. tcx ( ) , param_substs,
252
279
& ty:: expr_ty_adjusted ( cx. tcx ( ) , e) ) ;
@@ -439,17 +466,19 @@ fn check_binary_expr_validity(cx: &CrateContext, e: &ast::Expr, t: Ty,
439
466
fn const_expr_unadjusted < ' a , ' tcx > ( cx : & CrateContext < ' a , ' tcx > ,
440
467
e : & ast:: Expr ,
441
468
ety : Ty < ' tcx > ,
442
- param_substs : & ' tcx Substs < ' tcx > )
469
+ param_substs : & ' tcx Substs < ' tcx > ,
470
+ fn_args : FnArgMap )
443
471
-> ValueRef
444
472
{
445
473
debug ! ( "const_expr_unadjusted(e={}, ety={}, param_substs={})" ,
446
474
e. repr( cx. tcx( ) ) ,
447
475
ety. repr( cx. tcx( ) ) ,
448
476
param_substs. repr( cx. tcx( ) ) ) ;
449
477
450
- let map_list = |exprs : & [ P < ast:: Expr > ] | {
451
- exprs. iter ( ) . map ( |e| const_expr ( cx, & * * e, param_substs) . 0 )
452
- . fold ( Vec :: new ( ) , |mut l, val| { l. push ( val) ; l } )
478
+ let map_list = |exprs : & [ P < ast:: Expr > ] | -> Vec < ValueRef > {
479
+ exprs. iter ( )
480
+ . map ( |e| const_expr ( cx, & * * e, param_substs, fn_args) . 0 )
481
+ . collect ( )
453
482
} ;
454
483
unsafe {
455
484
let _icx = push_ctxt ( "const_expr" ) ;
@@ -460,7 +489,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
460
489
ast:: ExprBinary ( b, ref e1, ref e2) => {
461
490
/* Neither type is bottom, and we expect them to be unified
462
491
* already, so the following is safe. */
463
- let ( te1, ty) = const_expr ( cx, & * * e1, param_substs) ;
492
+ let ( te1, ty) = const_expr ( cx, & * * e1, param_substs, fn_args ) ;
464
493
debug ! ( "const_expr_unadjusted: te1={}, ty={}" ,
465
494
cx. tn( ) . val_to_string( te1) ,
466
495
ty. repr( cx. tcx( ) ) ) ;
@@ -473,7 +502,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
473
502
let is_float = ty:: type_is_fp ( intype) ;
474
503
let signed = ty:: type_is_signed ( intype) ;
475
504
476
- let ( te2, _) = const_expr ( cx, & * * e2, param_substs) ;
505
+ let ( te2, _) = const_expr ( cx, & * * e2, param_substs, fn_args ) ;
477
506
478
507
check_binary_expr_validity ( cx, e, ty, te1, te2) ;
479
508
@@ -533,7 +562,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
533
562
}
534
563
} ,
535
564
ast:: ExprUnary ( u, ref inner_e) => {
536
- let ( te, ty) = const_expr ( cx, & * * inner_e, param_substs) ;
565
+ let ( te, ty) = const_expr ( cx, & * * inner_e, param_substs, fn_args ) ;
537
566
538
567
check_unary_expr_validity ( cx, e, ty, te) ;
539
568
@@ -550,23 +579,23 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
550
579
}
551
580
}
552
581
ast:: ExprField ( ref base, field) => {
553
- let ( bv, bt) = const_expr ( cx, & * * base, param_substs) ;
582
+ let ( bv, bt) = const_expr ( cx, & * * base, param_substs, fn_args ) ;
554
583
let brepr = adt:: represent_type ( cx, bt) ;
555
584
expr:: with_field_tys ( cx. tcx ( ) , bt, None , |discr, field_tys| {
556
585
let ix = ty:: field_idx_strict ( cx. tcx ( ) , field. node . name , field_tys) ;
557
586
adt:: const_get_field ( cx, & * brepr, bv, discr, ix)
558
587
} )
559
588
}
560
589
ast:: ExprTupField ( ref base, idx) => {
561
- let ( bv, bt) = const_expr ( cx, & * * base, param_substs) ;
590
+ let ( bv, bt) = const_expr ( cx, & * * base, param_substs, fn_args ) ;
562
591
let brepr = adt:: represent_type ( cx, bt) ;
563
592
expr:: with_field_tys ( cx. tcx ( ) , bt, None , |discr, _| {
564
593
adt:: const_get_field ( cx, & * brepr, bv, discr, idx. node )
565
594
} )
566
595
}
567
596
568
597
ast:: ExprIndex ( ref base, ref index) => {
569
- let ( bv, bt) = const_expr ( cx, & * * base, param_substs) ;
598
+ let ( bv, bt) = const_expr ( cx, & * * base, param_substs, fn_args ) ;
570
599
let iv = match const_eval:: eval_const_expr_partial ( cx. tcx ( ) , & * * index, None ) {
571
600
Ok ( const_eval:: const_int( i) ) => i as u64 ,
572
601
Ok ( const_eval:: const_uint( u) ) => u,
@@ -617,7 +646,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
617
646
}
618
647
ast:: ExprCast ( ref base, _) => {
619
648
let llty = type_of:: type_of ( cx, ety) ;
620
- let ( v, basety) = const_expr ( cx, & * * base, param_substs) ;
649
+ let ( v, basety) = const_expr ( cx, & * * base, param_substs, fn_args ) ;
621
650
if expr:: cast_is_noop ( basety, ety) {
622
651
return v;
623
652
}
@@ -695,12 +724,12 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
695
724
} else {
696
725
// If this isn't the address of a static, then keep going through
697
726
// normal constant evaluation.
698
- let ( v, _) = const_expr ( cx, & * * sub, param_substs) ;
727
+ let ( v, _) = const_expr ( cx, & * * sub, param_substs, fn_args ) ;
699
728
addr_of ( cx, v, "ref" )
700
729
}
701
730
}
702
731
ast:: ExprAddrOf ( ast:: MutMutable , ref sub) => {
703
- let ( v, _) = const_expr ( cx, & * * sub, param_substs) ;
732
+ let ( v, _) = const_expr ( cx, & * * sub, param_substs, fn_args ) ;
704
733
addr_of_mut ( cx, v, "ref_mut_slice" )
705
734
}
706
735
ast:: ExprTup ( ref es) => {
@@ -712,15 +741,15 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
712
741
let repr = adt:: represent_type ( cx, ety) ;
713
742
714
743
let base_val = match * base_opt {
715
- Some ( ref base) => Some ( const_expr ( cx, & * * base, param_substs) ) ,
744
+ Some ( ref base) => Some ( const_expr ( cx, & * * base, param_substs, fn_args ) ) ,
716
745
None => None
717
746
} ;
718
747
719
748
expr:: with_field_tys ( cx. tcx ( ) , ety, Some ( e. id ) , |discr, field_tys| {
720
749
let cs = field_tys. iter ( ) . enumerate ( )
721
750
. map ( |( ix, & field_ty) | {
722
751
match fs. iter ( ) . find ( |f| field_ty. name == f. ident . node . name ) {
723
- Some ( ref f) => const_expr ( cx, & * f. expr , param_substs) . 0 ,
752
+ Some ( ref f) => const_expr ( cx, & * f. expr , param_substs, fn_args ) . 0 ,
724
753
None => {
725
754
match base_val {
726
755
Some ( ( bv, _) ) => {
@@ -745,7 +774,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
745
774
ast:: ExprVec ( ref es) => {
746
775
let unit_ty = ty:: sequence_element_type ( cx. tcx ( ) , ety) ;
747
776
let llunitty = type_of:: type_of ( cx, unit_ty) ;
748
- let vs = es. iter ( ) . map ( |e| const_expr ( cx, & * * e, param_substs) . 0 )
777
+ let vs = es. iter ( ) . map ( |e| const_expr ( cx, & * * e, param_substs, fn_args ) . 0 )
749
778
. collect :: < Vec < _ > > ( ) ;
750
779
// If the vector contains enums, an LLVM array won't work.
751
780
if vs. iter ( ) . any ( |vi| val_ty ( * vi) != llunitty) {
@@ -758,7 +787,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
758
787
let unit_ty = ty:: sequence_element_type ( cx. tcx ( ) , ety) ;
759
788
let llunitty = type_of:: type_of ( cx, unit_ty) ;
760
789
let n = ty:: eval_repeat_count ( cx. tcx ( ) , count) ;
761
- let unit_val = const_expr ( cx, & * * elem, param_substs) . 0 ;
790
+ let unit_val = const_expr ( cx, & * * elem, param_substs, fn_args ) . 0 ;
762
791
let vs: Vec < _ > = repeat ( unit_val) . take ( n) . collect ( ) ;
763
792
if val_ty ( unit_val) != llunitty {
764
793
C_struct ( cx, & vs[ ..] , false )
@@ -769,6 +798,13 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
769
798
ast:: ExprPath ( ..) => {
770
799
let def = cx. tcx ( ) . def_map . borrow ( ) . get ( & e. id ) . unwrap ( ) . full_def ( ) ;
771
800
match def {
801
+ def:: DefLocal ( id) => {
802
+ if let Some ( val) = fn_args. and_then ( |args| args. get ( & id) . cloned ( ) ) {
803
+ val
804
+ } else {
805
+ cx. sess ( ) . span_bug ( e. span , "const fn argument not found" )
806
+ }
807
+ }
772
808
def:: DefFn ( ..) | def:: DefMethod ( ..) => {
773
809
expr:: trans_def_fn_unadjusted ( cx, e, def, param_substs) . val
774
810
}
@@ -804,18 +840,32 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
804
840
}
805
841
}
806
842
ast:: ExprCall ( ref callee, ref args) => {
807
- let opt_def = cx. tcx ( ) . def_map . borrow ( ) . get ( & callee. id ) . map ( |d| d. full_def ( ) ) ;
808
- let arg_vals = map_list ( & args[ ..] ) ;
809
- match opt_def {
810
- Some ( def:: DefStruct ( _) ) => {
843
+ let mut callee = & * * callee;
844
+ loop {
845
+ callee = match callee. node {
846
+ ast:: ExprParen ( ref inner) => & * * inner,
847
+ ast:: ExprBlock ( ref block) => match block. expr {
848
+ Some ( ref tail) => & * * tail,
849
+ None => break
850
+ } ,
851
+ _ => break
852
+ } ;
853
+ }
854
+ let def = cx. tcx ( ) . def_map . borrow ( ) [ callee. id ] . full_def ( ) ;
855
+ let arg_vals = map_list ( args) ;
856
+ match def {
857
+ def:: DefFn ( did, _) | def:: DefMethod ( did, _) => {
858
+ const_fn_call ( cx, ExprId ( callee. id ) , did, & arg_vals, param_substs)
859
+ }
860
+ def:: DefStruct ( _) => {
811
861
if ty:: type_is_simd ( cx. tcx ( ) , ety) {
812
862
C_vector ( & arg_vals[ ..] )
813
863
} else {
814
864
let repr = adt:: represent_type ( cx, ety) ;
815
865
adt:: trans_const ( cx, & * repr, 0 , & arg_vals[ ..] )
816
866
}
817
867
}
818
- Some ( def:: DefVariant ( enum_did, variant_did, _) ) => {
868
+ def:: DefVariant ( enum_did, variant_did, _) => {
819
869
let repr = adt:: represent_type ( cx, ety) ;
820
870
let vinfo = ty:: enum_variant_with_id ( cx. tcx ( ) ,
821
871
enum_did,
@@ -825,13 +875,23 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
825
875
vinfo. disr_val ,
826
876
& arg_vals[ ..] )
827
877
}
828
- _ => cx. sess ( ) . span_bug ( e. span , "expected a struct or variant def" )
878
+ _ => cx. sess ( ) . span_bug ( e. span , "expected a struct, variant, or const fn def" )
829
879
}
830
880
}
831
- ast:: ExprParen ( ref e) => const_expr ( cx, & * * e, param_substs) . 0 ,
881
+ ast:: ExprMethodCall ( _, _, ref args) => {
882
+ let arg_vals = map_list ( args) ;
883
+ let method_call = ty:: MethodCall :: expr ( e. id ) ;
884
+ let method_did = match cx. tcx ( ) . method_map . borrow ( ) [ method_call] . origin {
885
+ ty:: MethodStatic ( did) => did,
886
+ _ => cx. sess ( ) . span_bug ( e. span , "expected a const method def" )
887
+ } ;
888
+ const_fn_call ( cx, MethodCallKey ( method_call) ,
889
+ method_did, & arg_vals, param_substs)
890
+ }
891
+ ast:: ExprParen ( ref e) => const_expr ( cx, & * * e, param_substs, fn_args) . 0 ,
832
892
ast:: ExprBlock ( ref block) => {
833
893
match block. expr {
834
- Some ( ref expr) => const_expr ( cx, & * * expr, param_substs) . 0 ,
894
+ Some ( ref expr) => const_expr ( cx, & * * expr, param_substs, fn_args ) . 0 ,
835
895
None => C_nil ( cx)
836
896
}
837
897
}
0 commit comments