@@ -84,9 +84,10 @@ pub use self::compare_method::{compare_impl_method, compare_const_impl};
8484use self :: method:: MethodCallee ;
8585use self :: TupleArgumentsFlag :: * ;
8686
87- use astconv:: AstConv ;
87+ use astconv:: { AstConv , GenericArgMismatchErrorCode } ;
8888use hir:: GenericArg ;
8989use hir:: def:: Def ;
90+ use hir:: HirVec ;
9091use hir:: def_id:: { CrateNum , DefId , LOCAL_CRATE } ;
9192use std:: slice;
9293use namespace:: Namespace ;
@@ -4937,16 +4938,30 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
49374938 // to add defaults. If the user provided *too many* types, that's
49384939 // a problem.
49394940
4940- let mut supress_errors = FxHashMap ( ) ;
4941+ let mut suppress_errors = FxHashMap ( ) ;
49414942 for & PathSeg ( def_id, index) in & path_segs {
49424943 let seg = & segments[ index] ;
49434944 let generics = self . tcx . generics_of ( def_id) ;
49444945 // `impl Trait` is treated as a normal generic parameter internally,
49454946 // but we don't allow users to specify the parameter's value
49464947 // explicitly, so we have to do some error-checking here.
4947- let supress_mismatch = self . check_impl_trait ( span, seg, & generics) ;
4948- supress_errors. insert ( index,
4949- self . check_generic_arg_count ( span, seg, & generics, false , supress_mismatch) ) ;
4948+ let suppress_mismatch = self . check_impl_trait ( span, seg, & generics) ;
4949+ suppress_errors. insert ( index, AstConv :: check_generic_arg_count (
4950+ self . tcx ,
4951+ span,
4952+ & generics,
4953+ & seg. args . clone ( ) . unwrap_or_else ( || P ( hir:: GenericArgs {
4954+ args : HirVec :: new ( ) , bindings : HirVec :: new ( ) , parenthesized : false ,
4955+ } ) ) ,
4956+ false , // `is_declaration`
4957+ false , // `is_method_call`
4958+ generics. parent . is_none ( ) && generics. has_self ,
4959+ seg. infer_types || suppress_mismatch,
4960+ GenericArgMismatchErrorCode {
4961+ lifetimes : ( "E0090" , "E0088" ) , // FIXME: E0090 and E0088 should be unified.
4962+ types : ( "E0089" , "E0087" ) , // FIXME: E0089 and E0087 should be unified.
4963+ } ,
4964+ ) ) ;
49504965 }
49514966
49524967 let has_self = path_segs. last ( ) . map ( |PathSeg ( def_id, _) | {
@@ -4968,7 +4983,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
49684983 } ) {
49694984 // If we've encountered an `impl Trait`-related error, we're just
49704985 // going to infer the arguments for better error messages.
4971- if !supress_errors [ & index] {
4986+ if !suppress_errors [ & index] {
49724987 // Check whether the user has provided generic arguments.
49734988 if let Some ( ref data) = segments[ index] . args {
49744989 return ( Some ( data) , segments[ index] . infer_types ) ;
@@ -5097,128 +5112,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
50975112 directly, not through a function pointer") ;
50985113 }
50995114
5100- /// Report errors if the provided parameters are too few or too many.
5101- fn check_generic_arg_count ( & self ,
5102- span : Span ,
5103- segment : & hir:: PathSegment ,
5104- generics : & ty:: Generics ,
5105- is_method_call : bool ,
5106- supress_mismatch_error : bool )
5107- -> bool {
5108- let mut supress_errors = false ;
5109- let ( mut lifetimes, mut types) = ( vec ! [ ] , vec ! [ ] ) ;
5110- let infer_types = segment. infer_types ;
5111- let mut bindings = vec ! [ ] ;
5112- if let Some ( ref data) = segment. args {
5113- data. args . iter ( ) . for_each ( |arg| match arg {
5114- GenericArg :: Lifetime ( lt) => lifetimes. push ( lt. clone ( ) ) ,
5115- GenericArg :: Type ( ty) => types. push ( ty. clone ( ) ) ,
5116- } ) ;
5117- bindings = data. bindings . clone ( ) . to_vec ( ) ;
5118- }
5119-
5120- struct ParamRange {
5121- required : usize ,
5122- accepted : usize
5123- } ;
5124-
5125- let mut lt_accepted = 0 ;
5126- let mut ty_params = ParamRange { required : 0 , accepted : 0 } ;
5127- for param in & generics. params {
5128- match param. kind {
5129- GenericParamDefKind :: Lifetime => lt_accepted += 1 ,
5130- GenericParamDefKind :: Type { has_default, .. } => {
5131- ty_params. accepted += 1 ;
5132- if !has_default {
5133- ty_params. required += 1 ;
5134- }
5135- }
5136- } ;
5137- }
5138- if generics. parent . is_none ( ) && generics. has_self {
5139- ty_params. required -= 1 ;
5140- ty_params. accepted -= 1 ;
5141- }
5142- let ty_accepted = ty_params. accepted ;
5143- let ty_required = ty_params. required ;
5144-
5145- let count_ty_params = |n| format ! ( "{} type parameter{}" , n, if n == 1 { "" } else { "s" } ) ;
5146- let expected_text = count_ty_params ( ty_accepted) ;
5147- let actual_text = count_ty_params ( types. len ( ) ) ;
5148- if let Some ( ( mut err, span) ) = if types. len ( ) > ty_accepted {
5149- // To prevent derived errors to accumulate due to extra
5150- // type parameters, we force instantiate_value_path to
5151- // use inference variables instead of the provided types.
5152- supress_errors = true ;
5153- let span = types[ ty_accepted] . span ;
5154- Some ( ( struct_span_err ! ( self . tcx. sess, span, E0087 ,
5155- "too many type parameters provided: \
5156- expected at most {}, found {}",
5157- expected_text, actual_text) , span) )
5158- } else if types. len ( ) < ty_required && !infer_types && !supress_mismatch_error {
5159- Some ( ( struct_span_err ! ( self . tcx. sess, span, E0089 ,
5160- "too few type parameters provided: \
5161- expected {}, found {}",
5162- expected_text, actual_text) , span) )
5163- } else {
5164- None
5165- } {
5166- self . set_tainted_by_errors ( ) ; // #53251
5167- err. span_label ( span, format ! ( "expected {}" , expected_text) ) . emit ( ) ;
5168- }
5169-
5170- if !bindings. is_empty ( ) {
5171- AstConv :: prohibit_assoc_ty_binding ( self . tcx , bindings[ 0 ] . span ) ;
5172- }
5173-
5174- let infer_lifetimes = lifetimes. len ( ) == 0 ;
5175- // Prohibit explicit lifetime arguments if late bound lifetime parameters are present.
5176- let has_late_bound_lifetime_defs = generics. has_late_bound_regions ;
5177- if let ( Some ( span_late) , false ) = ( has_late_bound_lifetime_defs, lifetimes. is_empty ( ) ) {
5178- // Report this as a lint only if no error was reported previously.
5179- let primary_msg = "cannot specify lifetime arguments explicitly \
5180- if late bound lifetime parameters are present";
5181- let note_msg = "the late bound lifetime parameter is introduced here" ;
5182- if !is_method_call && ( lifetimes. len ( ) > lt_accepted ||
5183- lifetimes. len ( ) < lt_accepted && !infer_lifetimes) {
5184- supress_errors = true ;
5185- let mut err = self . tcx . sess . struct_span_err ( lifetimes[ 0 ] . span , primary_msg) ;
5186- err. span_note ( span_late, note_msg) ;
5187- err. emit ( ) ;
5188- } else {
5189- let mut multispan = MultiSpan :: from_span ( lifetimes[ 0 ] . span ) ;
5190- multispan. push_span_label ( span_late, note_msg. to_string ( ) ) ;
5191- self . tcx . lint_node ( lint:: builtin:: LATE_BOUND_LIFETIME_ARGUMENTS ,
5192- lifetimes[ 0 ] . id , multispan, primary_msg) ;
5193- }
5194- return supress_errors;
5195- }
5196-
5197- let count_lifetime_params = |n| {
5198- format ! ( "{} lifetime parameter{}" , n, if n == 1 { "" } else { "s" } )
5199- } ;
5200- let expected_text = count_lifetime_params ( lt_accepted) ;
5201- let actual_text = count_lifetime_params ( lifetimes. len ( ) ) ;
5202- if let Some ( ( mut err, span) ) = if lifetimes. len ( ) > lt_accepted {
5203- let span = lifetimes[ lt_accepted] . span ;
5204- Some ( ( struct_span_err ! ( self . tcx. sess, span, E0088 ,
5205- "too many lifetime parameters provided: \
5206- expected at most {}, found {}",
5207- expected_text, actual_text) , span) )
5208- } else if lifetimes. len ( ) < lt_accepted && !infer_lifetimes {
5209- Some ( ( struct_span_err ! ( self . tcx. sess, span, E0090 ,
5210- "too few lifetime parameters provided: \
5211- expected {}, found {}",
5212- expected_text, actual_text) , span) )
5213- } else {
5214- None
5215- } {
5216- err. span_label ( span, format ! ( "expected {}" , expected_text) ) . emit ( ) ;
5217- }
5218-
5219- supress_errors
5220- }
5221-
52225115 /// Report error if there is an explicit type parameter when using `impl Trait`.
52235116 fn check_impl_trait ( & self ,
52245117 span : Span ,
0 commit comments