@@ -23,6 +23,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
23
23
sess : & Session ,
24
24
arg : & GenericArg < ' _ > ,
25
25
kind : & ' static str ,
26
+ possible_ordering_error : bool ,
26
27
help : Option < & str > ,
27
28
) {
28
29
let mut err = struct_span_err ! (
@@ -49,8 +50,23 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
49
50
GenericArg :: Const ( _) => ParamKindOrd :: Const { unordered } ,
50
51
} ;
51
52
53
+ if matches ! ( arg, GenericArg :: Type ( hir:: Ty { kind: hir:: TyKind :: Path { .. } , .. } ) )
54
+ && matches ! ( kind_ord, ParamKindOrd :: Const { .. } )
55
+ {
56
+ let suggestions = vec ! [
57
+ ( arg. span( ) . shrink_to_lo( ) , String :: from( "{ " ) ) ,
58
+ ( arg. span( ) . shrink_to_hi( ) , String :: from( " }" ) ) ,
59
+ ] ;
60
+ err. multipart_suggestion (
61
+ "if this generic argument was intended as a const parameter, \
62
+ try surrounding it with braces:",
63
+ suggestions,
64
+ Applicability :: MaybeIncorrect ,
65
+ ) ;
66
+ }
67
+
52
68
// This note is only true when generic parameters are strictly ordered by their kind.
53
- if kind_ord. cmp ( & arg_ord) != core:: cmp:: Ordering :: Equal {
69
+ if possible_ordering_error && kind_ord. cmp ( & arg_ord) != core:: cmp:: Ordering :: Equal {
54
70
let ( first, last) =
55
71
if kind_ord < arg_ord { ( kind, arg. descr ( ) ) } else { ( arg. descr ( ) , kind) } ;
56
72
err. note ( & format ! ( "{} arguments must be provided before {} arguments" , first, last) ) ;
@@ -148,8 +164,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
148
164
// Check whether this segment takes generic arguments and the user has provided any.
149
165
let ( generic_args, infer_args) = ctx. args_for_def_id ( def_id) ;
150
166
151
- let mut args =
152
- generic_args . iter ( ) . flat_map ( |generic_args| generic_args . args . iter ( ) ) . peekable ( ) ;
167
+ let args_iter = generic_args . iter ( ) . flat_map ( |generic_args| generic_args . args . iter ( ) ) ;
168
+ let mut args = args_iter . clone ( ) . peekable ( ) ;
153
169
154
170
// If we encounter a type or const when we expect a lifetime, we infer the lifetimes.
155
171
// If we later encounter a lifetime, we know that the arguments were provided in the
@@ -216,8 +232,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
216
232
GenericParamDefKind :: Const => {
217
233
ParamKindOrd :: Const {
218
234
unordered : tcx
219
- . sess
220
- . features_untracked ( )
235
+ . features ( )
221
236
. const_generics ,
222
237
}
223
238
}
@@ -237,6 +252,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
237
252
tcx. sess ,
238
253
arg,
239
254
kind. descr ( ) ,
255
+ !args_iter. clone ( ) . is_sorted_by_key ( |arg| match arg {
256
+ GenericArg :: Lifetime ( _) => ParamKindOrd :: Lifetime ,
257
+ GenericArg :: Type ( _) => ParamKindOrd :: Type ,
258
+ GenericArg :: Const ( _) => ParamKindOrd :: Const {
259
+ unordered : tcx. features ( ) . const_generics ,
260
+ } ,
261
+ } ) ,
240
262
Some ( & format ! (
241
263
"reorder the arguments: {}: `<{}>`" ,
242
264
param_types_present
@@ -288,7 +310,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
288
310
assert_eq ! ( kind, "lifetime" ) ;
289
311
let provided =
290
312
force_infer_lt. expect ( "lifetimes ought to have been inferred" ) ;
291
- Self :: generic_arg_mismatch_err ( tcx. sess , provided, kind, None ) ;
313
+ Self :: generic_arg_mismatch_err ( tcx. sess , provided, kind, false , None ) ;
292
314
}
293
315
294
316
break ;
@@ -346,6 +368,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
346
368
// that lifetimes will proceed types. So it suffices to check the number of each generic
347
369
// arguments in order to validate them with respect to the generic parameters.
348
370
let param_counts = def. own_counts ( ) ;
371
+ let named_type_param_count = param_counts. types - has_self as usize ;
349
372
let arg_counts = args. own_counts ( ) ;
350
373
let infer_lifetimes = position != GenericArgPosition :: Type && arg_counts. lifetimes == 0 ;
351
374
@@ -384,11 +407,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
384
407
// For kinds without defaults (e.g.., lifetimes), `required == permitted`.
385
408
// For other kinds (i.e., types), `permitted` may be greater than `required`.
386
409
if required <= provided && provided <= permitted {
387
- return Ok ( ( ) ) ;
410
+ return true ;
388
411
}
389
412
390
413
if silent {
391
- return Err ( ( 0i32 , None ) ) ;
414
+ return false ;
392
415
}
393
416
394
417
// Unfortunately lifetime and type parameter mismatches are typically styled
@@ -404,25 +427,26 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
404
427
( required, "" )
405
428
} ;
406
429
407
- let ( spans, label ) = if required == permitted && provided > permitted {
430
+ let ( spans, labels ) = if provided > permitted {
408
431
// In the case when the user has provided too many arguments,
409
432
// we want to point to the unexpected arguments.
410
- let spans: Vec < Span > = args. args [ offset + permitted..offset + provided]
433
+ let ( spans, labels) : ( Vec < Span > , Vec < String > ) = args. args
434
+ [ offset + permitted..offset + provided]
411
435
. iter ( )
412
- . map ( |arg| arg. span ( ) )
413
- . collect ( ) ;
436
+ . map ( |arg| ( arg. span ( ) , format ! ( "unexpected {} argument" , arg . short_descr ( ) ) ) )
437
+ . unzip ( ) ;
414
438
unexpected_spans. extend ( spans. clone ( ) ) ;
415
- ( spans, format ! ( "unexpected {} argument" , kind ) )
439
+ ( spans, labels )
416
440
} else {
417
441
(
418
442
vec ! [ span] ,
419
- format ! (
443
+ vec ! [ format!(
420
444
"expected {}{} {} argument{}" ,
421
445
quantifier,
422
446
bound,
423
447
kind,
424
448
pluralize!( bound) ,
425
- ) ,
449
+ ) ] ,
426
450
)
427
451
} ;
428
452
@@ -434,105 +458,57 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
434
458
) ,
435
459
DiagnosticId :: Error ( "E0107" . into ( ) ) ,
436
460
) ;
437
- for span in spans {
461
+ for ( span, label ) in spans. into_iter ( ) . zip ( labels ) {
438
462
err. span_label ( span, label. as_str ( ) ) ;
439
463
}
440
-
441
- assert_ne ! ( bound, provided) ;
442
- Err ( ( bound as i32 - provided as i32 , Some ( err) ) )
464
+ err. emit ( ) ;
465
+ false
443
466
} ;
444
467
445
468
let mut unexpected_spans = vec ! [ ] ;
446
469
447
- let mut lifetime_count_correct = Ok ( ( ) ) ;
448
- if !infer_lifetimes || arg_counts. lifetimes > param_counts. lifetimes {
449
- lifetime_count_correct = check_kind_count (
450
- "lifetime" ,
451
- param_counts. lifetimes ,
452
- param_counts. lifetimes ,
453
- arg_counts. lifetimes ,
454
- 0 ,
455
- & mut unexpected_spans,
456
- explicit_late_bound == ExplicitLateBound :: Yes ,
457
- ) ;
458
- }
459
-
460
- // FIXME(const_generics:defaults)
461
- let mut const_count_correct = Ok ( ( ) ) ;
462
- if !infer_args || arg_counts. consts > param_counts. consts {
463
- const_count_correct = check_kind_count (
464
- "const" ,
465
- param_counts. consts ,
466
- param_counts. consts ,
467
- arg_counts. consts ,
468
- arg_counts. lifetimes + arg_counts. types ,
469
- & mut unexpected_spans,
470
- false ,
471
- ) ;
472
- }
473
-
474
- // Note that type errors are currently be emitted *after* const errors.
475
- let mut type_count_correct = Ok ( ( ) ) ;
476
- if !infer_args || arg_counts. types > param_counts. types - defaults. types - has_self as usize
477
- {
478
- type_count_correct = check_kind_count (
479
- "type" ,
480
- param_counts. types - defaults. types - has_self as usize ,
481
- param_counts. types - has_self as usize ,
482
- arg_counts. types ,
483
- arg_counts. lifetimes ,
484
- & mut unexpected_spans,
485
- false ,
486
- ) ;
487
- }
488
-
489
- // Emit a help message if it's possible that a type could be surrounded in braces
490
- if let Err ( ( c_mismatch, Some ( ref mut _const_err) ) ) = const_count_correct {
491
- if let Err ( ( _, Some ( ref mut type_err) ) ) = type_count_correct {
492
- let possible_matches = args. args [ arg_counts. lifetimes ..]
493
- . iter ( )
494
- . filter ( |arg| {
495
- matches ! (
496
- arg,
497
- GenericArg :: Type ( hir:: Ty { kind: hir:: TyKind :: Path { .. } , .. } )
498
- )
499
- } )
500
- . take ( c_mismatch. max ( 0 ) as usize ) ;
501
- for arg in possible_matches {
502
- let suggestions = vec ! [
503
- ( arg. span( ) . shrink_to_lo( ) , String :: from( "{ " ) ) ,
504
- ( arg. span( ) . shrink_to_hi( ) , String :: from( " }" ) ) ,
505
- ] ;
506
- type_err. multipart_suggestion (
507
- "If this generic argument was intended as a const parameter, \
508
- try surrounding it with braces:",
509
- suggestions,
510
- Applicability :: MaybeIncorrect ,
511
- ) ;
512
- }
513
- }
514
- }
470
+ let lifetime_count_correct = check_kind_count (
471
+ "lifetime" ,
472
+ if infer_lifetimes { 0 } else { param_counts. lifetimes } ,
473
+ param_counts. lifetimes ,
474
+ arg_counts. lifetimes ,
475
+ 0 ,
476
+ & mut unexpected_spans,
477
+ explicit_late_bound == ExplicitLateBound :: Yes ,
478
+ ) ;
515
479
516
- let emit_correct =
517
- |correct : Result < ( ) , ( _ , Option < rustc_errors:: DiagnosticBuilder < ' _ > > ) > | match correct {
518
- Ok ( ( ) ) => Ok ( ( ) ) ,
519
- Err ( ( _, None ) ) => Err ( ( ) ) ,
520
- Err ( ( _, Some ( mut err) ) ) => {
521
- err. emit ( ) ;
522
- Err ( ( ) )
523
- }
524
- } ;
480
+ let kind_str = if param_counts. consts + arg_counts. consts == 0 {
481
+ "type"
482
+ } else if named_type_param_count + arg_counts. types == 0 {
483
+ "const"
484
+ } else {
485
+ "generic"
486
+ } ;
525
487
526
- let arg_count_correct = emit_correct ( lifetime_count_correct)
527
- . and ( emit_correct ( const_count_correct) )
528
- . and ( emit_correct ( type_count_correct) ) ;
488
+ let arg_count_correct = check_kind_count (
489
+ kind_str,
490
+ if infer_args {
491
+ 0
492
+ } else {
493
+ param_counts. consts + named_type_param_count - defaults. types
494
+ } ,
495
+ param_counts. consts + named_type_param_count,
496
+ arg_counts. consts + arg_counts. types ,
497
+ arg_counts. lifetimes ,
498
+ & mut unexpected_spans,
499
+ false ,
500
+ ) ;
529
501
530
502
GenericArgCountResult {
531
503
explicit_late_bound,
532
- correct : arg_count_correct. map_err ( |( ) | GenericArgCountMismatch {
533
- reported : Some ( ErrorReported ) ,
534
- invalid_args : unexpected_spans,
535
- } ) ,
504
+ correct : if lifetime_count_correct && arg_count_correct {
505
+ Ok ( ( ) )
506
+ } else {
507
+ Err ( GenericArgCountMismatch {
508
+ reported : Some ( ErrorReported ) ,
509
+ invalid_args : unexpected_spans,
510
+ } )
511
+ } ,
536
512
}
537
513
}
538
514
0 commit comments