@@ -22,6 +22,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
22
22
sess : & Session ,
23
23
arg : & GenericArg < ' _ > ,
24
24
kind : & ' static str ,
25
+ possible_ordering_error : bool ,
25
26
help : Option < & str > ,
26
27
) {
27
28
let mut err = struct_span_err ! (
@@ -48,8 +49,23 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
48
49
GenericArg :: Const ( _) => ParamKindOrd :: Const { unordered } ,
49
50
} ;
50
51
52
+ if matches ! ( arg, GenericArg :: Type ( hir:: Ty { kind: hir:: TyKind :: Path { .. } , .. } ) )
53
+ && matches ! ( kind_ord, ParamKindOrd :: Const { .. } )
54
+ {
55
+ let suggestions = vec ! [
56
+ ( arg. span( ) . shrink_to_lo( ) , String :: from( "{ " ) ) ,
57
+ ( arg. span( ) . shrink_to_hi( ) , String :: from( " }" ) ) ,
58
+ ] ;
59
+ err. multipart_suggestion (
60
+ "if this generic argument was intended as a const parameter, \
61
+ try surrounding it with braces:",
62
+ suggestions,
63
+ Applicability :: MaybeIncorrect ,
64
+ ) ;
65
+ }
66
+
51
67
// This note is only true when generic parameters are strictly ordered by their kind.
52
- if kind_ord. cmp ( & arg_ord) != core:: cmp:: Ordering :: Equal {
68
+ if possible_ordering_error && kind_ord. cmp ( & arg_ord) != core:: cmp:: Ordering :: Equal {
53
69
let ( first, last) =
54
70
if kind_ord < arg_ord { ( kind, arg. descr ( ) ) } else { ( arg. descr ( ) , kind) } ;
55
71
err. note ( & format ! ( "{} arguments must be provided before {} arguments" , first, last) ) ;
@@ -153,8 +169,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
153
169
// Check whether this segment takes generic arguments and the user has provided any.
154
170
let ( generic_args, infer_args) = args_for_def_id ( def_id) ;
155
171
156
- let mut args =
157
- generic_args . iter ( ) . flat_map ( |generic_args| generic_args . args . iter ( ) ) . peekable ( ) ;
172
+ let args_iter = generic_args . iter ( ) . flat_map ( |generic_args| generic_args . args . iter ( ) ) ;
173
+ let mut args = args_iter . clone ( ) . peekable ( ) ;
158
174
159
175
// If we encounter a type or const when we expect a lifetime, we infer the lifetimes.
160
176
// If we later encounter a lifetime, we know that the arguments were provided in the
@@ -221,8 +237,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
221
237
GenericParamDefKind :: Const => {
222
238
ParamKindOrd :: Const {
223
239
unordered : tcx
224
- . sess
225
- . features_untracked ( )
240
+ . features ( )
226
241
. const_generics ,
227
242
}
228
243
}
@@ -242,6 +257,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
242
257
tcx. sess ,
243
258
arg,
244
259
kind. descr ( ) ,
260
+ !args_iter. clone ( ) . is_sorted_by_key ( |arg| match arg {
261
+ GenericArg :: Lifetime ( _) => ParamKindOrd :: Lifetime ,
262
+ GenericArg :: Type ( _) => ParamKindOrd :: Type ,
263
+ GenericArg :: Const ( _) => ParamKindOrd :: Const {
264
+ unordered : tcx. features ( ) . const_generics ,
265
+ } ,
266
+ } ) ,
245
267
Some ( & format ! (
246
268
"reorder the arguments: {}: `<{}>`" ,
247
269
param_types_present
@@ -293,7 +315,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
293
315
assert_eq ! ( kind, "lifetime" ) ;
294
316
let provided =
295
317
force_infer_lt. expect ( "lifetimes ought to have been inferred" ) ;
296
- Self :: generic_arg_mismatch_err ( tcx. sess , provided, kind, None ) ;
318
+ Self :: generic_arg_mismatch_err ( tcx. sess , provided, kind, false , None ) ;
297
319
}
298
320
299
321
break ;
@@ -351,6 +373,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
351
373
// that lifetimes will proceed types. So it suffices to check the number of each generic
352
374
// arguments in order to validate them with respect to the generic parameters.
353
375
let param_counts = def. own_counts ( ) ;
376
+ let named_type_param_count = param_counts. types - has_self as usize ;
354
377
let arg_counts = args. own_counts ( ) ;
355
378
let infer_lifetimes = position != GenericArgPosition :: Type && arg_counts. lifetimes == 0 ;
356
379
@@ -389,11 +412,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
389
412
// For kinds without defaults (e.g.., lifetimes), `required == permitted`.
390
413
// For other kinds (i.e., types), `permitted` may be greater than `required`.
391
414
if required <= provided && provided <= permitted {
392
- return Ok ( ( ) ) ;
415
+ return true ;
393
416
}
394
417
395
418
if silent {
396
- return Err ( ( 0i32 , None ) ) ;
419
+ return false ;
397
420
}
398
421
399
422
// Unfortunately lifetime and type parameter mismatches are typically styled
@@ -409,25 +432,26 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
409
432
( required, "" )
410
433
} ;
411
434
412
- let ( spans, label ) = if provided > permitted {
435
+ let ( spans, labels ) = if provided > permitted {
413
436
// In the case when the user has provided too many arguments,
414
437
// we want to point to the unexpected arguments.
415
- let spans: Vec < Span > = args. args [ offset + permitted..offset + provided]
438
+ let ( spans, labels) : ( Vec < Span > , Vec < String > ) = args. args
439
+ [ offset + permitted..offset + provided]
416
440
. iter ( )
417
- . map ( |arg| arg. span ( ) )
418
- . collect ( ) ;
441
+ . map ( |arg| ( arg. span ( ) , format ! ( "unexpected {} argument" , arg . short_descr ( ) ) ) )
442
+ . unzip ( ) ;
419
443
unexpected_spans. extend ( spans. clone ( ) ) ;
420
- ( spans, format ! ( "unexpected {} argument" , kind ) )
444
+ ( spans, labels )
421
445
} else {
422
446
(
423
447
vec ! [ span] ,
424
- format ! (
448
+ vec ! [ format!(
425
449
"expected {}{} {} argument{}" ,
426
450
quantifier,
427
451
bound,
428
452
kind,
429
453
pluralize!( bound) ,
430
- ) ,
454
+ ) ] ,
431
455
)
432
456
} ;
433
457
@@ -439,12 +463,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
439
463
) ,
440
464
DiagnosticId :: Error ( "E0107" . into ( ) ) ,
441
465
) ;
442
- for span in spans {
466
+ for ( span, label ) in spans. into_iter ( ) . zip ( labels ) {
443
467
err. span_label ( span, label. as_str ( ) ) ;
444
468
}
445
-
446
- assert_ne ! ( bound, provided) ;
447
- Err ( ( bound as i32 - provided as i32 , Some ( err) ) )
469
+ err. emit ( ) ;
470
+ false
448
471
} ;
449
472
450
473
let mut unexpected_spans = vec ! [ ] ;
@@ -459,75 +482,38 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
459
482
explicit_late_bound == ExplicitLateBound :: Yes ,
460
483
) ;
461
484
462
- // FIXME(const_generics:defaults)
463
- let mut const_count_correct = check_kind_count (
464
- "const" ,
465
- if infer_args { 0 } else { 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
- ) ;
485
+ let kind_str = if param_counts. consts + arg_counts. consts == 0 {
486
+ "type"
487
+ } else if named_type_param_count + arg_counts. types == 0 {
488
+ "const"
489
+ } else {
490
+ "generic"
491
+ } ;
472
492
473
- // Note that type errors are currently be emitted *after* const errors.
474
- let mut type_count_correct = check_kind_count (
475
- "type" ,
476
- if infer_args { 0 } else { param_counts. types - defaults. types - has_self as usize } ,
477
- param_counts. types - has_self as usize ,
478
- arg_counts. types ,
493
+ let arg_count_correct = check_kind_count (
494
+ kind_str,
495
+ if infer_args {
496
+ 0
497
+ } else {
498
+ param_counts. consts + named_type_param_count - defaults. types
499
+ } ,
500
+ param_counts. consts + named_type_param_count,
501
+ arg_counts. consts + arg_counts. types ,
479
502
arg_counts. lifetimes ,
480
503
& mut unexpected_spans,
481
504
false ,
482
505
) ;
483
506
484
- // Emit a help message if it's possible that a type could be surrounded in braces
485
- if let Err ( ( c_mismatch, Some ( ref mut _const_err) ) ) = const_count_correct {
486
- if let Err ( ( _, Some ( ref mut type_err) ) ) = type_count_correct {
487
- let possible_matches = args. args [ arg_counts. lifetimes ..]
488
- . iter ( )
489
- . filter ( |arg| {
490
- matches ! (
491
- arg,
492
- GenericArg :: Type ( hir:: Ty { kind: hir:: TyKind :: Path { .. } , .. } )
493
- )
494
- } )
495
- . take ( c_mismatch. max ( 0 ) as usize ) ;
496
- for arg in possible_matches {
497
- let suggestions = vec ! [
498
- ( arg. span( ) . shrink_to_lo( ) , String :: from( "{ " ) ) ,
499
- ( arg. span( ) . shrink_to_hi( ) , String :: from( " }" ) ) ,
500
- ] ;
501
- type_err. multipart_suggestion (
502
- "If this generic argument was intended as a const parameter, \
503
- try surrounding it with braces:",
504
- suggestions,
505
- Applicability :: MaybeIncorrect ,
506
- ) ;
507
- }
508
- }
509
- }
510
-
511
- let emit_correct =
512
- |correct : Result < ( ) , ( _ , Option < rustc_errors:: DiagnosticBuilder < ' _ > > ) > | match correct {
513
- Ok ( ( ) ) => Ok ( ( ) ) ,
514
- Err ( ( _, None ) ) => Err ( ( ) ) ,
515
- Err ( ( _, Some ( mut err) ) ) => {
516
- err. emit ( ) ;
517
- Err ( ( ) )
518
- }
519
- } ;
520
-
521
- let arg_count_correct = emit_correct ( lifetime_count_correct)
522
- . and ( emit_correct ( const_count_correct) )
523
- . and ( emit_correct ( type_count_correct) ) ;
524
-
525
507
GenericArgCountResult {
526
508
explicit_late_bound,
527
- correct : arg_count_correct. map_err ( |( ) | GenericArgCountMismatch {
528
- reported : Some ( ErrorReported ) ,
529
- invalid_args : unexpected_spans,
530
- } ) ,
509
+ correct : if lifetime_count_correct && arg_count_correct {
510
+ Ok ( ( ) )
511
+ } else {
512
+ Err ( GenericArgCountMismatch {
513
+ reported : Some ( ErrorReported ) ,
514
+ invalid_args : unexpected_spans,
515
+ } )
516
+ } ,
531
517
}
532
518
}
533
519
0 commit comments