@@ -81,6 +81,7 @@ use middle::const_eval;
81
81
use middle:: lang_items:: { ExchangeHeapLangItem , GcLangItem } ;
82
82
use middle:: lang_items:: { ManagedHeapLangItem } ;
83
83
use middle:: lint:: UnreachableCode ;
84
+ use middle:: lint;
84
85
use middle:: pat_util:: pat_id_map;
85
86
use middle:: pat_util;
86
87
use middle:: subst:: Subst ;
@@ -1500,32 +1501,55 @@ fn check_type_parameter_positions_in_path(function_context: @FnCtxt,
1500
1501
// Make sure the number of type parameters supplied on the trait
1501
1502
// or implementation segment equals the number of type parameters
1502
1503
// on the trait or implementation definition.
1503
- let trait_type_parameter_count = generics. type_param_defs . len ( ) ;
1504
- let supplied_type_parameter_count = trait_segment. types . len ( ) ;
1505
- if trait_type_parameter_count != supplied_type_parameter_count {
1506
- let trait_count_suffix = if trait_type_parameter_count == 1 {
1504
+ let formal_ty_param_count = generics. type_param_defs . len ( ) ;
1505
+ let required_ty_param_count = generics. type_param_defs . iter ( )
1506
+ . take_while ( |x| x. default . is_none ( ) )
1507
+ . len ( ) ;
1508
+ let supplied_ty_param_count = trait_segment. types . len ( ) ;
1509
+ if supplied_ty_param_count < required_ty_param_count {
1510
+ let trait_count_suffix = if required_ty_param_count == 1 {
1507
1511
""
1508
1512
} else {
1509
1513
"s"
1510
1514
} ;
1511
- let supplied_count_suffix =
1512
- if supplied_type_parameter_count == 1 {
1513
- ""
1514
- } else {
1515
- "s"
1516
- } ;
1517
- function_context. tcx ( )
1518
- . sess
1519
- . span_err ( path. span ,
1520
- format ! ( "the {} referenced by this \
1521
- path has {} type \
1522
- parameter{}, but {} type \
1523
- parameter{} were supplied",
1524
- name,
1525
- trait_type_parameter_count,
1526
- trait_count_suffix,
1527
- supplied_type_parameter_count,
1528
- supplied_count_suffix) )
1515
+ let supplied_count_suffix = if supplied_ty_param_count == 1 {
1516
+ ""
1517
+ } else {
1518
+ "s"
1519
+ } ;
1520
+ let needs = if required_ty_param_count < generics. type_param_defs . len ( ) {
1521
+ "needs at least"
1522
+ } else {
1523
+ "needs"
1524
+ } ;
1525
+ function_context. tcx ( ) . sess . span_err ( path. span ,
1526
+ format ! ( "the {} referenced by this path {} {} type \
1527
+ parameter{}, but {} type parameter{} were supplied",
1528
+ name, needs,
1529
+ required_ty_param_count, trait_count_suffix,
1530
+ supplied_ty_param_count, supplied_count_suffix) )
1531
+ } else if supplied_ty_param_count > formal_ty_param_count {
1532
+ let trait_count_suffix = if formal_ty_param_count == 1 {
1533
+ ""
1534
+ } else {
1535
+ "s"
1536
+ } ;
1537
+ let supplied_count_suffix = if supplied_ty_param_count == 1 {
1538
+ ""
1539
+ } else {
1540
+ "s"
1541
+ } ;
1542
+ let needs = if required_ty_param_count < generics. type_param_defs . len ( ) {
1543
+ "needs at most"
1544
+ } else {
1545
+ "needs"
1546
+ } ;
1547
+ function_context. tcx ( ) . sess . span_err ( path. span ,
1548
+ format ! ( "the {} referenced by this path {} {} type \
1549
+ parameter{}, but {} type parameter{} were supplied",
1550
+ name, needs,
1551
+ formal_ty_param_count, trait_count_suffix,
1552
+ supplied_ty_param_count, supplied_count_suffix) )
1529
1553
}
1530
1554
}
1531
1555
_ => {
@@ -3683,6 +3707,9 @@ pub fn instantiate_path(fcx: @FnCtxt,
3683
3707
debug ! ( ">>> instantiate_path" ) ;
3684
3708
3685
3709
let ty_param_count = tpt. generics . type_param_defs . len ( ) ;
3710
+ let ty_param_req = tpt. generics . type_param_defs . iter ( )
3711
+ . take_while ( |x| x. default . is_none ( ) )
3712
+ . len ( ) ;
3686
3713
let mut ty_substs_len = 0 ;
3687
3714
for segment in pth. segments . iter ( ) {
3688
3715
ty_substs_len += segment. types . len ( )
@@ -3720,13 +3747,13 @@ pub fn instantiate_path(fcx: @FnCtxt,
3720
3747
// Here we calculate the "user type parameter count", which is the number
3721
3748
// of type parameters actually manifest in the AST. This will differ from
3722
3749
// the internal type parameter count when there are self types involved.
3723
- let ( user_type_parameter_count , self_parameter_index) = match def {
3750
+ let ( user_ty_param_count , user_ty_param_req , self_parameter_index) = match def {
3724
3751
ast:: DefStaticMethod ( _, provenance @ ast:: FromTrait ( _) , _) => {
3725
3752
let generics = generics_of_static_method_container ( fcx. ccx . tcx ,
3726
3753
provenance) ;
3727
- ( ty_param_count - 1 , Some ( generics. type_param_defs . len ( ) ) )
3754
+ ( ty_param_count - 1 , ty_param_req - 1 , Some ( generics. type_param_defs . len ( ) ) )
3728
3755
}
3729
- _ => ( ty_param_count, None ) ,
3756
+ _ => ( ty_param_count, ty_param_req , None ) ,
3730
3757
} ;
3731
3758
3732
3759
// determine values for type parameters, using the values given by
@@ -3737,35 +3764,63 @@ pub fn instantiate_path(fcx: @FnCtxt,
3737
3764
fcx. ccx . tcx . sess . span_err
3738
3765
( span, "this item does not take type parameters" ) ;
3739
3766
fcx. infcx ( ) . next_ty_vars ( ty_param_count)
3740
- } else if ty_substs_len > user_type_parameter_count {
3767
+ } else if ty_substs_len > user_ty_param_count {
3768
+ let expected = if user_ty_param_req < user_ty_param_count {
3769
+ "expected at most"
3770
+ } else {
3771
+ "expected"
3772
+ } ;
3741
3773
fcx. ccx . tcx . sess . span_err
3742
3774
( span,
3743
- format ! ( "too many type parameters provided: expected {}, found {}" ,
3744
- user_type_parameter_count , ty_substs_len) ) ;
3775
+ format ! ( "too many type parameters provided: {} {}, found {}" ,
3776
+ expected , user_ty_param_count , ty_substs_len) ) ;
3745
3777
fcx. infcx ( ) . next_ty_vars ( ty_param_count)
3746
- } else if ty_substs_len < user_type_parameter_count {
3778
+ } else if ty_substs_len < user_ty_param_req {
3779
+ let expected = if user_ty_param_req < user_ty_param_count {
3780
+ "expected at least"
3781
+ } else {
3782
+ "expected"
3783
+ } ;
3747
3784
fcx. ccx . tcx . sess . span_err
3748
3785
( span,
3749
- format ! ( "not enough type parameters provided: expected {}, found {}" ,
3750
- user_type_parameter_count , ty_substs_len) ) ;
3786
+ format ! ( "not enough type parameters provided: {} {}, found {}" ,
3787
+ expected , user_ty_param_req , ty_substs_len) ) ;
3751
3788
fcx. infcx ( ) . next_ty_vars ( ty_param_count)
3752
3789
} else {
3790
+ if ty_substs_len > user_ty_param_req {
3791
+ fcx. tcx ( ) . sess . add_lint ( lint:: DefaultTypeParamUsage , node_id, pth. span ,
3792
+ ~"provided type arguments with defaults") ;
3793
+ }
3794
+
3753
3795
// Build up the list of type parameters, inserting the self parameter
3754
3796
// at the appropriate position.
3755
3797
let mut result = ~[ ] ;
3756
3798
let mut pushed = false ;
3757
- for ( i, & ast_type) in pth. segments
3758
- . iter ( )
3759
- . flat_map ( |segment| segment. types . iter ( ) )
3760
- . enumerate ( ) {
3799
+ let defaults = tpt. generics . type_param_defs . iter ( )
3800
+ . enumerate ( ) . filter_map ( |( i, x) | {
3801
+ match self_parameter_index {
3802
+ Some ( index) if index == i => None ,
3803
+ _ => Some ( x. default )
3804
+ }
3805
+ } ) . skip ( ty_substs_len) . map ( |x| match x {
3806
+ Some ( default) => default,
3807
+ None => {
3808
+ fcx. tcx ( ) . sess . span_bug ( span,
3809
+ "missing default for a not explicitely provided type param" )
3810
+ }
3811
+ } ) ;
3812
+ for ( i, ty) in pth. segments . iter ( )
3813
+ . flat_map ( |segment| segment. types . iter ( ) )
3814
+ . map ( |& ast_type| fcx. to_ty ( ast_type) )
3815
+ . chain ( defaults) . enumerate ( ) {
3761
3816
match self_parameter_index {
3762
3817
Some ( index) if index == i => {
3763
3818
result. push ( fcx. infcx ( ) . next_ty_vars ( 1 ) [ 0 ] ) ;
3764
3819
pushed = true ;
3765
3820
}
3766
3821
_ => { }
3767
3822
}
3768
- result. push ( fcx . to_ty ( ast_type ) )
3823
+ result. push ( ty )
3769
3824
}
3770
3825
3771
3826
// If the self parameter goes at the end, insert it there.
0 commit comments