@@ -4491,8 +4491,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
44914491 // variables. If the user provided some types, we may still need
44924492 // to add defaults. If the user provided *too many* types, that's
44934493 // 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 ) ;
44964496
44974497 let ( fn_start, has_self) = match ( type_segment, fn_segment) {
44984498 ( _, Some ( ( _, generics) ) ) => {
@@ -4618,7 +4618,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
46184618 /// Report errors if the provided parameters are too few or too many.
46194619 fn check_path_parameter_count ( & self ,
46204620 span : Span ,
4621- segment : & mut Option < ( & hir:: PathSegment , & ty:: Generics ) > ) {
4621+ segment : & mut Option < ( & hir:: PathSegment , & ty:: Generics ) > ,
4622+ is_method_call : bool ) {
46224623 let ( lifetimes, types, infer_types, bindings) = {
46234624 match segment. map ( |( s, _) | & s. parameters ) {
46244625 Some ( & hir:: AngleBracketedParameters ( ref data) ) => {
@@ -4632,6 +4633,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
46324633 None => ( & [ ] [ ..] , & [ ] [ ..] , true , & [ ] [ ..] )
46334634 }
46344635 } ;
4636+ let infer_lifetimes = lifetimes. len ( ) == 0 ;
46354637
46364638 let count_lifetime_params = |n| {
46374639 format ! ( "{} lifetime parameter{}" , n, if n == 1 { "" } else { "s" } )
@@ -4640,32 +4642,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
46404642 format ! ( "{} type parameter{}" , n, if n == 1 { "" } else { "s" } )
46414643 } ;
46424644
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-
46694645 // Check provided type parameters.
46704646 let type_defs = segment. map_or ( & [ ] [ ..] , |( _, generics) | {
46714647 if generics. parent . is_none ( ) {
@@ -4690,7 +4666,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
46904666 // type parameters, we force instantiate_value_path to
46914667 // use inference variables instead of the provided types.
46924668 * segment = None ;
4693- } else if !infer_types && types. len ( ) < required_len {
4669+ } else if types. len ( ) < required_len && !infer_types {
46944670 let expected_text = count_type_params ( required_len) ;
46954671 let actual_text = count_type_params ( types. len ( ) ) ;
46964672 struct_span_err ! ( self . tcx. sess, span, E0089 ,
@@ -4706,6 +4682,51 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
47064682 "unexpected binding of associated item in expression path \
47074683 (only allowed in type paths)") ;
47084684 }
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+ }
47094730 }
47104731
47114732 fn structurally_resolve_type_or_else < F > ( & self , sp : Span , ty : Ty < ' tcx > , f : F )
0 commit comments