@@ -144,19 +144,60 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
144
144
stack. push ( ( def_id, parent_defs) ) ;
145
145
}
146
146
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
+
147
186
// We manually build up the substitution, rather than using convenience
148
187
// methods in `subst.rs`, so that we can iterate over the arguments and
149
188
// parameters in lock-step linearly, instead of trying to match each pair.
150
189
let mut substs: SmallVec < [ subst:: GenericArg < ' tcx > ; 8 ] > = SmallVec :: with_capacity ( count) ;
151
190
// 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 ( ) {
153
192
let mut params = defs. params . iter ( ) . peekable ( ) ;
154
193
194
+ let mut skip = 0 ;
155
195
// If we have already computed substitutions for parents, we can use those directly.
156
196
while let Some ( & param) = params. peek ( ) {
157
197
if let Some ( & kind) = parent_substs. get ( param. index as usize ) {
158
198
substs. push ( kind) ;
159
199
params. next ( ) ;
200
+ skip += 1 ;
160
201
} else {
161
202
break ;
162
203
}
@@ -173,22 +214,26 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
173
214
. unwrap_or_else ( || ctx. inferred_kind ( None , param, true ) ) ,
174
215
) ;
175
216
params. next ( ) ;
217
+ skip += 1 ;
176
218
}
177
219
}
178
220
}
179
221
}
180
222
181
223
// Check whether this segment takes generic arguments and the user has provided any.
182
224
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
+ } ;
183
235
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 ( ) ;
192
237
193
238
loop {
194
239
// We're going to iterate through the generic arguments that the user
@@ -213,7 +258,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
213
258
// We expected a lifetime argument, but got a type or const
214
259
// argument. That means we're inferring the lifetimes.
215
260
substs. push ( ctx. inferred_kind ( None , param, infer_args) ) ;
216
- force_infer_lt = Some ( ( arg, param) ) ;
217
261
params. next ( ) ;
218
262
}
219
263
( GenericArg :: Lifetime ( _) , _, ExplicitLateBound :: Yes ) => {
@@ -231,73 +275,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
231
275
if arg_count. correct . is_ok ( )
232
276
&& arg_count. explicit_late_bound == ExplicitLateBound :: No
233
277
{
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 (
269
279
tcx,
280
+ defs,
281
+ generic_args. args . iter ( ) ,
270
282
arg,
271
283
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
+ )
299
285
}
300
-
301
286
// We've reported the error, but we want to make sure that this
302
287
// problem doesn't bubble down and create additional, irrelevant
303
288
// errors. In this case, we're simply going to ignore the argument
@@ -323,11 +308,15 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
323
308
if arg_count. correct . is_ok ( )
324
309
&& arg_count. explicit_late_bound == ExplicitLateBound :: No
325
310
{
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
+ )
331
320
}
332
321
333
322
break ;
@@ -338,6 +327,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
338
327
// we're inferring the remaining arguments.
339
328
substs. push ( ctx. inferred_kind ( Some ( & substs) , param, infer_args) ) ;
340
329
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 ;
341
335
}
342
336
343
337
( None , None ) => break ,
@@ -348,6 +342,70 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
348
342
tcx. intern_substs ( & substs)
349
343
}
350
344
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
+
351
409
/// Checks that the correct number of generic arguments have been provided.
352
410
/// Used specifically for function calls.
353
411
pub fn check_generic_arg_count_for_call (
0 commit comments