@@ -144,19 +144,60 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
144144 stack. push ( ( def_id, parent_defs) ) ;
145145 }
146146
147+ let report_error =
148+ |mut args : std:: iter:: Peekable < std:: slice:: Iter < ' _ , GenericArg < ' _ > > > ,
149+ mut params : std:: iter:: Peekable < std:: slice:: Iter < ' _ , GenericParamDef > > | {
150+ // redo some work to compute the lifetime inferred.
151+ let mut force_infer_lt = None ;
152+ loop {
153+ match ( args. peek ( ) , params. peek ( ) ) {
154+ ( Some ( & a) , Some ( & p) ) => match ( a, & p. kind ) {
155+ ( GenericArg :: Lifetime ( _) , GenericParamDefKind :: Lifetime )
156+ | ( GenericArg :: Type ( _) , GenericParamDefKind :: Type { .. } )
157+ | ( GenericArg :: Const ( _) , GenericParamDefKind :: Const ) => {
158+ params. next ( ) ;
159+ args. next ( ) ;
160+ }
161+ (
162+ GenericArg :: Type ( _) | GenericArg :: Const ( _) ,
163+ GenericParamDefKind :: Lifetime ,
164+ ) => {
165+ force_infer_lt = Some ( ( a, p) ) ;
166+ params. next ( ) ;
167+ }
168+ ( GenericArg :: Lifetime ( _) , _)
169+ if arg_count. explicit_late_bound == ExplicitLateBound :: Yes =>
170+ {
171+ args. next ( ) ;
172+ }
173+ ( _, _) => { }
174+ } ,
175+ ( None , Some ( _) ) => {
176+ params. next ( ) ;
177+ }
178+ ( Some ( _) | None , None ) => break ,
179+ }
180+ }
181+ let ( provided_arg, param) =
182+ force_infer_lt. expect ( "lifetimes ought to have been inferred" ) ;
183+ Self :: generic_arg_mismatch_err ( tcx, provided_arg, param, false , None ) ;
184+ } ;
185+
147186 // We manually build up the substitution, rather than using convenience
148187 // methods in `subst.rs`, so that we can iterate over the arguments and
149188 // parameters in lock-step linearly, instead of trying to match each pair.
150189 let mut substs: SmallVec < [ subst:: GenericArg < ' tcx > ; 8 ] > = SmallVec :: with_capacity ( count) ;
151190 // Iterate over each segment of the path.
152- while let Some ( ( def_id, defs) ) = stack. pop ( ) {
191+ ' outer : while let Some ( ( def_id, defs) ) = stack. pop ( ) {
153192 let mut params = defs. params . iter ( ) . peekable ( ) ;
154193
194+ let mut skip = 0 ;
155195 // If we have already computed substitutions for parents, we can use those directly.
156196 while let Some ( & param) = params. peek ( ) {
157197 if let Some ( & kind) = parent_substs. get ( param. index as usize ) {
158198 substs. push ( kind) ;
159199 params. next ( ) ;
200+ skip += 1 ;
160201 } else {
161202 break ;
162203 }
@@ -173,22 +214,26 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
173214 . unwrap_or_else ( || ctx. inferred_kind ( None , param, true ) ) ,
174215 ) ;
175216 params. next ( ) ;
217+ skip += 1 ;
176218 }
177219 }
178220 }
179221 }
180222
181223 // Check whether this segment takes generic arguments and the user has provided any.
182224 let ( generic_args, infer_args) = ctx. args_for_def_id ( def_id) ;
225+ let generic_args = match generic_args {
226+ Some ( ga) => ga,
227+ None => {
228+ substs. reserve ( params. len ( ) ) ;
229+ for p in params {
230+ substs. push ( ctx. inferred_kind ( Some ( & substs) , p, infer_args) ) ;
231+ }
232+ continue ' outer;
233+ }
234+ } ;
183235
184- let args_iter = generic_args. iter ( ) . flat_map ( |generic_args| generic_args. args . iter ( ) ) ;
185- let mut args = args_iter. clone ( ) . peekable ( ) ;
186-
187- // If we encounter a type or const when we expect a lifetime, we infer the lifetimes.
188- // If we later encounter a lifetime, we know that the arguments were provided in the
189- // wrong order. `force_infer_lt` records the type or const that forced lifetimes to be
190- // inferred, so we can use it for diagnostics later.
191- let mut force_infer_lt = None ;
236+ let mut args = generic_args. args . iter ( ) . peekable ( ) ;
192237
193238 loop {
194239 // We're going to iterate through the generic arguments that the user
@@ -213,7 +258,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
213258 // We expected a lifetime argument, but got a type or const
214259 // argument. That means we're inferring the lifetimes.
215260 substs. push ( ctx. inferred_kind ( None , param, infer_args) ) ;
216- force_infer_lt = Some ( ( arg, param) ) ;
217261 params. next ( ) ;
218262 }
219263 ( GenericArg :: Lifetime ( _) , _, ExplicitLateBound :: Yes ) => {
@@ -231,73 +275,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
231275 if arg_count. correct . is_ok ( )
232276 && arg_count. explicit_late_bound == ExplicitLateBound :: No
233277 {
234- // We're going to iterate over the parameters to sort them out, and
235- // show that order to the user as a possible order for the parameters
236- let mut param_types_present = defs
237- . params
238- . clone ( )
239- . into_iter ( )
240- . map ( |param| {
241- (
242- match param. kind {
243- GenericParamDefKind :: Lifetime => {
244- ParamKindOrd :: Lifetime
245- }
246- GenericParamDefKind :: Type { .. } => {
247- ParamKindOrd :: Type
248- }
249- GenericParamDefKind :: Const => {
250- ParamKindOrd :: Const {
251- unordered : tcx
252- . features ( )
253- . const_generics ,
254- }
255- }
256- } ,
257- param,
258- )
259- } )
260- . collect :: < Vec < ( ParamKindOrd , GenericParamDef ) > > ( ) ;
261- param_types_present. sort_by_key ( |( ord, _) | * ord) ;
262- let ( mut param_types_present, ordered_params) : (
263- Vec < ParamKindOrd > ,
264- Vec < GenericParamDef > ,
265- ) = param_types_present. into_iter ( ) . unzip ( ) ;
266- param_types_present. dedup ( ) ;
267-
268- Self :: generic_arg_mismatch_err (
278+ Self :: generic_arg_mismatch_errs (
269279 tcx,
280+ defs,
281+ generic_args. args . iter ( ) ,
270282 arg,
271283 param,
272- !args_iter. clone ( ) . is_sorted_by_key ( |arg| match arg {
273- GenericArg :: Lifetime ( _) => ParamKindOrd :: Lifetime ,
274- GenericArg :: Type ( _) => ParamKindOrd :: Type ,
275- GenericArg :: Const ( _) => ParamKindOrd :: Const {
276- unordered : tcx. features ( ) . const_generics ,
277- } ,
278- } ) ,
279- Some ( & format ! (
280- "reorder the arguments: {}: `<{}>`" ,
281- param_types_present
282- . into_iter( )
283- . map( |ord| format!( "{}s" , ord. to_string( ) ) )
284- . collect:: <Vec <String >>( )
285- . join( ", then " ) ,
286- ordered_params
287- . into_iter( )
288- . filter_map( |param| {
289- if param. name == kw:: SelfUpper {
290- None
291- } else {
292- Some ( param. name. to_string( ) )
293- }
294- } )
295- . collect:: <Vec <String >>( )
296- . join( ", " )
297- ) ) ,
298- ) ;
284+ )
299285 }
300-
301286 // We've reported the error, but we want to make sure that this
302287 // problem doesn't bubble down and create additional, irrelevant
303288 // errors. In this case, we're simply going to ignore the argument
@@ -323,11 +308,15 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
323308 if arg_count. correct . is_ok ( )
324309 && arg_count. explicit_late_bound == ExplicitLateBound :: No
325310 {
326- let kind = arg. descr ( ) ;
327- assert_eq ! ( kind, "lifetime" ) ;
328- let ( provided_arg, param) =
329- force_infer_lt. expect ( "lifetimes ought to have been inferred" ) ;
330- Self :: generic_arg_mismatch_err ( tcx, provided_arg, param, false , None ) ;
311+ assert ! ( matches!( arg, GenericArg :: Lifetime ( _) ) ) ;
312+ // If we encounter a type or const when we expect a lifetime, we infer the lifetimes.
313+ // If we later encounter a lifetime, we know that the arguments were provided in the
314+ // wrong order. `force_infer_lt` records the type or const that forced lifetimes to be
315+ // inferred, so we can use it for diagnostics later.
316+ report_error (
317+ generic_args. args . iter ( ) . peekable ( ) ,
318+ defs. params [ skip..] . iter ( ) . peekable ( ) ,
319+ )
331320 }
332321
333322 break ;
@@ -338,6 +327,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
338327 // we're inferring the remaining arguments.
339328 substs. push ( ctx. inferred_kind ( Some ( & substs) , param, infer_args) ) ;
340329 params. next ( ) ;
330+ substs. reserve ( params. len ( ) ) ;
331+ for p in params {
332+ substs. push ( ctx. inferred_kind ( Some ( & substs) , p, infer_args) ) ;
333+ }
334+ break ;
341335 }
342336
343337 ( None , None ) => break ,
@@ -348,6 +342,70 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
348342 tcx. intern_substs ( & substs)
349343 }
350344
345+ fn generic_arg_mismatch_errs < ' a > (
346+ tcx : TyCtxt < ' _ > ,
347+ defs : & rustc_middle:: ty:: Generics ,
348+ args_iter : impl Iterator < Item = & ' a GenericArg < ' a > > ,
349+ arg : & GenericArg < ' _ > ,
350+ param : & GenericParamDef ,
351+ ) {
352+ // We're going to iterate over the parameters to sort them out, and
353+ // show that order to the user as a possible order for the parameters
354+ let mut param_types_present = defs
355+ . params
356+ . clone ( )
357+ . into_iter ( )
358+ . map ( |param| {
359+ (
360+ match param. kind {
361+ GenericParamDefKind :: Lifetime => ParamKindOrd :: Lifetime ,
362+ GenericParamDefKind :: Type { .. } => ParamKindOrd :: Type ,
363+ GenericParamDefKind :: Const => {
364+ ParamKindOrd :: Const { unordered : tcx. features ( ) . const_generics }
365+ }
366+ } ,
367+ param,
368+ )
369+ } )
370+ . collect :: < Vec < ( ParamKindOrd , GenericParamDef ) > > ( ) ;
371+ param_types_present. sort_by_key ( |( ord, _) | * ord) ;
372+ let ( mut param_types_present, ordered_params) : ( Vec < ParamKindOrd > , Vec < GenericParamDef > ) =
373+ param_types_present. into_iter ( ) . unzip ( ) ;
374+ param_types_present. dedup ( ) ;
375+
376+ Self :: generic_arg_mismatch_err (
377+ tcx,
378+ arg,
379+ param,
380+ !args_iter. is_sorted_by_key ( |arg| match arg {
381+ GenericArg :: Lifetime ( _) => ParamKindOrd :: Lifetime ,
382+ GenericArg :: Type ( _) => ParamKindOrd :: Type ,
383+ GenericArg :: Const ( _) => {
384+ ParamKindOrd :: Const { unordered : tcx. features ( ) . const_generics }
385+ }
386+ } ) ,
387+ Some ( & format ! (
388+ "reorder the arguments: {}: `<{}>`" ,
389+ param_types_present
390+ . into_iter( )
391+ . map( |ord| format!( "{}s" , ord. to_string( ) ) )
392+ . collect:: <Vec <String >>( )
393+ . join( ", then " ) ,
394+ ordered_params
395+ . into_iter( )
396+ . filter_map( |param| {
397+ if param. name == kw:: SelfUpper {
398+ None
399+ } else {
400+ Some ( param. name. to_string( ) )
401+ }
402+ } )
403+ . collect:: <Vec <String >>( )
404+ . join( ", " )
405+ ) ) ,
406+ ) ;
407+ }
408+
351409 /// Checks that the correct number of generic arguments have been provided.
352410 /// Used specifically for function calls.
353411 pub fn check_generic_arg_count_for_call (
0 commit comments