@@ -4491,8 +4491,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
4491
4491
// variables. If the user provided some types, we may still need
4492
4492
// to add defaults. If the user provided *too many* types, that's
4493
4493
// a problem.
4494
- self . check_path_parameter_count ( span, & mut type_segment) ;
4495
- self . check_path_parameter_count ( span, & mut fn_segment) ;
4494
+ self . check_path_parameter_count ( span, & mut type_segment, false ) ;
4495
+ self . check_path_parameter_count ( span, & mut fn_segment, false ) ;
4496
4496
4497
4497
let ( fn_start, has_self) = match ( type_segment, fn_segment) {
4498
4498
( _, Some ( ( _, generics) ) ) => {
@@ -4618,7 +4618,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
4618
4618
/// Report errors if the provided parameters are too few or too many.
4619
4619
fn check_path_parameter_count ( & self ,
4620
4620
span : Span ,
4621
- segment : & mut Option < ( & hir:: PathSegment , & ty:: Generics ) > ) {
4621
+ segment : & mut Option < ( & hir:: PathSegment , & ty:: Generics ) > ,
4622
+ is_method_call : bool ) {
4622
4623
let ( lifetimes, types, infer_types, bindings) = {
4623
4624
match segment. map ( |( s, _) | & s. parameters ) {
4624
4625
Some ( & hir:: AngleBracketedParameters ( ref data) ) => {
@@ -4632,6 +4633,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
4632
4633
None => ( & [ ] [ ..] , & [ ] [ ..] , true , & [ ] [ ..] )
4633
4634
}
4634
4635
} ;
4636
+ let infer_lifetimes = lifetimes. len ( ) == 0 ;
4635
4637
4636
4638
let count_lifetime_params = |n| {
4637
4639
format ! ( "{} lifetime parameter{}" , n, if n == 1 { "" } else { "s" } )
@@ -4640,32 +4642,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
4640
4642
format ! ( "{} type parameter{}" , n, if n == 1 { "" } else { "s" } )
4641
4643
} ;
4642
4644
4643
- // Check provided lifetime parameters.
4644
- let lifetime_defs = segment. map_or ( & [ ] [ ..] , |( _, generics) | & generics. regions ) ;
4645
- if lifetimes. len ( ) > lifetime_defs. len ( ) {
4646
- let expected_text = count_lifetime_params ( lifetime_defs. len ( ) ) ;
4647
- let actual_text = count_lifetime_params ( lifetimes. len ( ) ) ;
4648
- struct_span_err ! ( self . tcx. sess, span, E0088 ,
4649
- "too many lifetime parameters provided: \
4650
- expected at most {}, found {}",
4651
- expected_text, actual_text)
4652
- . span_label ( span, format ! ( "expected {}" , expected_text) )
4653
- . emit ( ) ;
4654
- } else if lifetimes. len ( ) > 0 && lifetimes. len ( ) < lifetime_defs. len ( ) {
4655
- let expected_text = count_lifetime_params ( lifetime_defs. len ( ) ) ;
4656
- let actual_text = count_lifetime_params ( lifetimes. len ( ) ) ;
4657
- struct_span_err ! ( self . tcx. sess, span, E0090 ,
4658
- "too few lifetime parameters provided: \
4659
- expected {}, found {}",
4660
- expected_text, actual_text)
4661
- . span_label ( span, format ! ( "expected {}" , expected_text) )
4662
- . emit ( ) ;
4663
- }
4664
-
4665
- // The case where there is not enough lifetime parameters is not checked,
4666
- // because this is not possible - a function never takes lifetime parameters.
4667
- // See discussion for Pull Request 36208.
4668
-
4669
4645
// Check provided type parameters.
4670
4646
let type_defs = segment. map_or ( & [ ] [ ..] , |( _, generics) | {
4671
4647
if generics. parent . is_none ( ) {
@@ -4690,7 +4666,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
4690
4666
// type parameters, we force instantiate_value_path to
4691
4667
// use inference variables instead of the provided types.
4692
4668
* segment = None ;
4693
- } else if !infer_types && types. len ( ) < required_len {
4669
+ } else if types. len ( ) < required_len && !infer_types {
4694
4670
let expected_text = count_type_params ( required_len) ;
4695
4671
let actual_text = count_type_params ( types. len ( ) ) ;
4696
4672
struct_span_err ! ( self . tcx. sess, span, E0089 ,
@@ -4706,6 +4682,51 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
4706
4682
"unexpected binding of associated item in expression path \
4707
4683
(only allowed in type paths)") ;
4708
4684
}
4685
+
4686
+ // Check provided lifetime parameters.
4687
+ let lifetime_defs = segment. map_or ( & [ ] [ ..] , |( _, generics) | & generics. regions ) ;
4688
+ let required_len = lifetime_defs. len ( ) ;
4689
+
4690
+ // Prohibit explicit lifetime arguments if late bound lifetime parameters are present.
4691
+ let has_late_bound_lifetime_defs =
4692
+ segment. map_or ( false , |( _, generics) | generics. has_late_bound_regions ) ;
4693
+ if has_late_bound_lifetime_defs && !lifetimes. is_empty ( ) {
4694
+ // Report this as a lint only if no error was reported previously.
4695
+ if !is_method_call && ( lifetimes. len ( ) > lifetime_defs. len ( ) ||
4696
+ lifetimes. len ( ) < required_len && !infer_lifetimes) {
4697
+ self . tcx . sess . span_err ( lifetimes[ 0 ] . span ,
4698
+ "cannot specify lifetime arguments explicitly \
4699
+ if late bound lifetime parameters are present") ;
4700
+ * segment = None ;
4701
+ } else {
4702
+ self . tcx . sess . add_lint ( lint:: builtin:: LATE_BOUND_LIFETIME_ARGUMENTS ,
4703
+ lifetimes[ 0 ] . id , lifetimes[ 0 ] . span ,
4704
+ format ! ( "cannot specify lifetime arguments explicitly \
4705
+ if late bound lifetime parameters are present") ) ;
4706
+ }
4707
+ return ;
4708
+ }
4709
+
4710
+ if lifetimes. len ( ) > lifetime_defs. len ( ) {
4711
+ let span = lifetimes[ lifetime_defs. len ( ) ] . span ;
4712
+ let expected_text = count_lifetime_params ( lifetime_defs. len ( ) ) ;
4713
+ let actual_text = count_lifetime_params ( lifetimes. len ( ) ) ;
4714
+ struct_span_err ! ( self . tcx. sess, span, E0088 ,
4715
+ "too many lifetime parameters provided: \
4716
+ expected at most {}, found {}",
4717
+ expected_text, actual_text)
4718
+ . span_label ( span, format ! ( "expected {}" , expected_text) )
4719
+ . emit ( ) ;
4720
+ } else if lifetimes. len ( ) < required_len && !infer_lifetimes {
4721
+ let expected_text = count_lifetime_params ( lifetime_defs. len ( ) ) ;
4722
+ let actual_text = count_lifetime_params ( lifetimes. len ( ) ) ;
4723
+ struct_span_err ! ( self . tcx. sess, span, E0090 ,
4724
+ "too few lifetime parameters provided: \
4725
+ expected {}, found {}",
4726
+ expected_text, actual_text)
4727
+ . span_label ( span, format ! ( "expected {}" , expected_text) )
4728
+ . emit ( ) ;
4729
+ }
4709
4730
}
4710
4731
4711
4732
fn structurally_resolve_type_or_else < F > ( & self , sp : Span , ty : Ty < ' tcx > , f : F )
0 commit comments