@@ -413,6 +413,7 @@ pub enum ErrKind {
413
413
BadType ( ConstVal ) ,
414
414
ErroneousReferencedConstant ( Box < ConstEvalErr > ) ,
415
415
CharCast ( ConstInt ) ,
416
+ Aggregate ( Vec < ConstEvalErr > ) ,
416
417
}
417
418
418
419
impl From < ConstMathErr > for ErrKind {
@@ -476,6 +477,7 @@ impl ConstEvalErr {
476
477
CharCast ( ref got) => {
477
478
format ! ( "only `u8` can be cast as `char`, not `{}`" , got. description( ) ) . into_cow ( )
478
479
} ,
480
+ Aggregate ( ref v) => format ! ( "evaluation of {} fields failed" , v. len( ) ) . into_cow ( ) ,
479
481
}
480
482
}
481
483
}
@@ -771,9 +773,7 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
771
773
signal ! ( e, UnimplementedConstVal ( "enum variants" ) ) ;
772
774
}
773
775
}
774
- Def :: Struct ( ..) => {
775
- ConstVal :: Struct ( e. id )
776
- }
776
+ Def :: Struct ( did) => Struct ( did, BTreeMap :: new ( ) ) ,
777
777
Def :: Local ( _, id) => {
778
778
debug ! ( "Def::Local({:?}): {:?}" , id, fn_args) ;
779
779
if let Some ( val) = fn_args. and_then ( |args| args. get ( & id) ) {
@@ -791,7 +791,7 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
791
791
let callee_val = eval_const_expr_partial ( tcx, callee, sub_ty_hint, fn_args) ?;
792
792
let did = match callee_val {
793
793
Function ( did) => did,
794
- Struct ( _ ) => signal ! ( e, UnimplementedConstVal ( "tuple struct constructors" ) ) ,
794
+ Struct ( .. ) => signal ! ( e, UnimplementedConstVal ( "tuple struct constructors" ) ) ,
795
795
callee => signal ! ( e, CallOn ( callee) ) ,
796
796
} ;
797
797
let ( decl, result) = if let Some ( fn_like) = lookup_const_fn_by_id ( tcx, did) {
@@ -829,8 +829,42 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
829
829
}
830
830
}
831
831
hir:: ExprType ( ref e, _) => eval_const_expr_partial ( tcx, & e, ty_hint, fn_args) ?,
832
- hir:: ExprTup ( _) => Tuple ( e. id ) ,
833
- hir:: ExprStruct ( ..) => Struct ( e. id ) ,
832
+ hir:: ExprTup ( ref v) => {
833
+ let mut fields = Vec :: with_capacity ( v. len ( ) ) ;
834
+ let mut errors = Vec :: new ( ) ;
835
+ for field in v {
836
+ match eval_const_expr_partial ( tcx, field, ty_hint. erase_hint ( ) , fn_args) {
837
+ Ok ( v) => fields. push ( v) ,
838
+ Err ( e) => errors. push ( e) ,
839
+ }
840
+ }
841
+ if !errors. is_empty ( ) {
842
+ signal ! ( e, Aggregate ( errors) ) ;
843
+ }
844
+ assert_eq ! ( fields. len( ) , v. len( ) ) ;
845
+ Tuple ( None , fields)
846
+ } ,
847
+ hir:: ExprStruct ( _, _, Some ( _) ) => signal ! ( e, UnimplementedConstVal ( "struct base" ) ) ,
848
+ hir:: ExprStruct ( _, ref fields, None ) => {
849
+ let def_id = match tcx. def_map . borrow ( ) . get ( & e. id ) . map ( |def| def. full_def ( ) ) {
850
+ Some ( Def :: Struct ( def_id) ) => def_id,
851
+ Some ( Def :: Variant ( ..) ) => signal ! ( e, UnimplementedConstVal ( "enums" ) ) ,
852
+ _ => signal ! ( e, NonConstPath ) ,
853
+ } ;
854
+ let mut new_fields = BTreeMap :: new ( ) ;
855
+ let mut errors = Vec :: new ( ) ;
856
+ for field in fields {
857
+ match eval_const_expr_partial ( tcx, & field. expr , ty_hint. erase_hint ( ) , fn_args) {
858
+ Ok ( f_val) => assert ! ( new_fields. insert( field. name. node, f_val) . is_none( ) ) ,
859
+ Err ( e) => errors. push ( e) ,
860
+ }
861
+ }
862
+ if !errors. is_empty ( ) {
863
+ signal ! ( e, Aggregate ( errors) ) ;
864
+ }
865
+ assert_eq ! ( new_fields. len( ) , fields. len( ) ) ;
866
+ Struct ( def_id, new_fields)
867
+ } ,
834
868
hir:: ExprIndex ( ref arr, ref idx) => {
835
869
if !tcx. sess . features . borrow ( ) . const_indexing {
836
870
signal ! ( e, IndexOpFeatureGated ) ;
@@ -845,21 +879,11 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
845
879
} ;
846
880
assert_eq ! ( idx as usize as u64 , idx) ;
847
881
match arr {
848
- Array ( _, n) if idx >= n => signal ! ( e, IndexOutOfBounds ) ,
849
- Array ( v, n) => if let hir:: ExprVec ( ref v) = tcx. map . expect_expr ( v) . node {
850
- assert_eq ! ( n as usize as u64 , n) ;
851
- eval_const_expr_partial ( tcx, & v[ idx as usize ] , ty_hint, fn_args) ?
852
- } else {
853
- bug ! ( )
854
- } ,
882
+ Array ( ref v) if idx as usize >= v. len ( ) => signal ! ( e, IndexOutOfBounds ) ,
883
+ Array ( ref v) => v[ idx as usize ] . clone ( ) ,
855
884
856
885
Repeat ( _, n) if idx >= n => signal ! ( e, IndexOutOfBounds ) ,
857
- Repeat ( elem, _) => eval_const_expr_partial (
858
- tcx,
859
- & tcx. map . expect_expr ( elem) ,
860
- ty_hint,
861
- fn_args,
862
- ) ?,
886
+ Repeat ( elem, _) => * elem,
863
887
864
888
ByteStr ( ref data) if idx >= data. len ( ) as u64 => signal ! ( e, IndexOutOfBounds ) ,
865
889
ByteStr ( data) => {
@@ -872,11 +896,30 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
872
896
_ => signal ! ( e, IndexedNonVec ) ,
873
897
}
874
898
}
875
- hir:: ExprVec ( ref v) => Array ( e. id , v. len ( ) as u64 ) ,
876
- hir:: ExprRepeat ( _, ref n) => {
899
+ hir:: ExprVec ( ref v) => {
900
+ let mut elems = Vec :: with_capacity ( v. len ( ) ) ;
901
+ let mut errors = Vec :: new ( ) ;
902
+ for elem in v {
903
+ match eval_const_expr_partial ( tcx, elem, ty_hint. erase_hint ( ) , fn_args) {
904
+ Ok ( elem) => elems. push ( elem) ,
905
+ Err ( e) => errors. push ( e) ,
906
+ }
907
+ }
908
+ if !errors. is_empty ( ) {
909
+ signal ! ( e, Aggregate ( errors) ) ;
910
+ }
911
+ assert_eq ! ( elems. len( ) , v. len( ) ) ;
912
+ Array ( elems)
913
+ } ,
914
+ hir:: ExprRepeat ( ref elem, ref n) => {
877
915
let len_hint = ty_hint. checked_or ( tcx. types . usize ) ;
916
+ let val_hint = match ty_hint {
917
+ ExprTypeChecked => ExprTypeChecked ,
918
+ UncheckedExprNoHint => UncheckedExprNoHint ,
919
+ UncheckedExprHint ( ty) => UncheckedExprHint ( ty. sequence_element_type ( tcx) ) ,
920
+ } ;
878
921
Repeat (
879
- e . id ,
922
+ box eval_const_expr_partial ( tcx , elem , val_hint , fn_args ) ? ,
880
923
match eval_const_expr_partial ( tcx, & n, len_hint, fn_args) ? {
881
924
Integral ( Usize ( i) ) => i. as_u64 ( tcx. sess . target . uint_type ) ,
882
925
Integral ( _) => signal ! ( e, RepeatCountNotNatural ) ,
@@ -886,40 +929,24 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
886
929
} ,
887
930
hir:: ExprTupField ( ref base, index) => {
888
931
let base_hint = ty_hint. erase_hint ( ) ;
889
- let c = eval_const_expr_partial ( tcx, base, base_hint, fn_args) ?;
890
- if let Tuple ( tup_id) = c {
891
- if let hir:: ExprTup ( ref fields) = tcx. map . expect_expr ( tup_id) . node {
892
- if index. node < fields. len ( ) {
893
- eval_const_expr_partial ( tcx, & fields[ index. node ] , ty_hint, fn_args) ?
894
- } else {
895
- signal ! ( e, TupleIndexOutOfBounds ) ;
896
- }
897
- } else {
898
- bug ! ( )
899
- }
900
- } else {
901
- signal ! ( base, ExpectedConstTuple ) ;
932
+ match eval_const_expr_partial ( tcx, base, base_hint, fn_args) ? {
933
+ Tuple ( _, ref v) if index. node >= v. len ( ) => signal ! ( e, TupleIndexOutOfBounds ) ,
934
+ Tuple ( _, v) => v[ index. node as usize ] . clone ( ) ,
935
+ _ => signal ! ( base, ExpectedConstTuple ) ,
902
936
}
903
937
}
904
938
hir:: ExprField ( ref base, field_name) => {
905
939
let base_hint = ty_hint. erase_hint ( ) ;
906
940
// Get the base expression if it is a struct and it is constant
907
- let c = eval_const_expr_partial ( tcx, base, base_hint, fn_args) ?;
908
- if let Struct ( struct_id) = c {
909
- if let hir:: ExprStruct ( _, ref fields, _) = tcx. map . expect_expr ( struct_id) . node {
910
- // Check that the given field exists and evaluate it
911
- // if the idents are compared run-pass/issue-19244 fails
912
- if let Some ( f) = fields. iter ( ) . find ( |f| f. name . node
913
- == field_name. node ) {
914
- eval_const_expr_partial ( tcx, & f. expr , ty_hint, fn_args) ?
941
+ match eval_const_expr_partial ( tcx, base, base_hint, fn_args) ? {
942
+ Struct ( _, fields) => {
943
+ if let Some ( f) = fields. get ( & field_name. node ) {
944
+ f. clone ( )
915
945
} else {
916
946
signal ! ( e, MissingStructField ) ;
917
947
}
918
- } else {
919
- bug ! ( )
920
- }
921
- } else {
922
- signal ! ( base, ExpectedConstStruct ) ;
948
+ } ,
949
+ _ => signal ! ( base, ExpectedConstStruct ) ,
923
950
}
924
951
}
925
952
hir:: ExprAddrOf ( ..) => signal ! ( e, UnimplementedConstVal ( "address operator" ) ) ,
0 commit comments