@@ -3,7 +3,7 @@ use crate::astconv::{
3
3
} ;
4
4
use crate :: errors:: AssocTypeBindingNotAllowed ;
5
5
use rustc_ast:: ast:: ParamKindOrd ;
6
- use rustc_errors:: { pluralize, struct_span_err, DiagnosticId , ErrorReported } ;
6
+ use rustc_errors:: { pluralize, struct_span_err, Applicability , DiagnosticId , ErrorReported } ;
7
7
use rustc_hir as hir;
8
8
use rustc_hir:: def_id:: DefId ;
9
9
use rustc_hir:: { GenericArg , GenericArgs } ;
@@ -368,7 +368,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
368
368
}
369
369
370
370
if position != GenericArgPosition :: Type && !args. bindings . is_empty ( ) {
371
- Self :: prohibit_assoc_ty_binding ( tcx, args. bindings [ 0 ] . span ) ;
371
+ AstConv :: prohibit_assoc_ty_binding ( tcx, args. bindings [ 0 ] . span ) ;
372
372
}
373
373
374
374
let explicit_late_bound =
@@ -393,7 +393,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
393
393
}
394
394
395
395
if silent {
396
- return Err ( true ) ;
396
+ return Err ( ( 0i32 , None ) ) ;
397
397
}
398
398
399
399
// Unfortunately lifetime and type parameter mismatches are typically styled
@@ -442,58 +442,100 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
442
442
for span in spans {
443
443
err. span_label ( span, label. as_str ( ) ) ;
444
444
}
445
- err. emit ( ) ;
446
445
447
- Err ( true )
446
+ assert_ne ! ( bound, provided) ;
447
+ Err ( ( bound as i32 - provided as i32 , Some ( err) ) )
448
448
} ;
449
449
450
- let mut arg_count_correct = Ok ( ( ) ) ;
451
450
let mut unexpected_spans = vec ! [ ] ;
452
451
452
+ let mut lifetime_count_correct = Ok ( ( ) ) ;
453
453
if !infer_lifetimes || arg_counts. lifetimes > param_counts. lifetimes {
454
- arg_count_correct = check_kind_count (
454
+ lifetime_count_correct = check_kind_count (
455
455
"lifetime" ,
456
456
param_counts. lifetimes ,
457
457
param_counts. lifetimes ,
458
458
arg_counts. lifetimes ,
459
459
0 ,
460
460
& mut unexpected_spans,
461
461
explicit_late_bound == ExplicitLateBound :: Yes ,
462
- )
463
- . and ( arg_count_correct) ;
462
+ ) ;
464
463
}
464
+
465
465
// FIXME(const_generics:defaults)
466
+ let mut const_count_correct = Ok ( ( ) ) ;
466
467
if !infer_args || arg_counts. consts > param_counts. consts {
467
- arg_count_correct = check_kind_count (
468
+ const_count_correct = check_kind_count (
468
469
"const" ,
469
470
param_counts. consts ,
470
471
param_counts. consts ,
471
472
arg_counts. consts ,
472
473
arg_counts. lifetimes + arg_counts. types ,
473
474
& mut unexpected_spans,
474
475
false ,
475
- )
476
- . and ( arg_count_correct) ;
476
+ ) ;
477
477
}
478
+
478
479
// Note that type errors are currently be emitted *after* const errors.
480
+ let mut type_count_correct = Ok ( ( ) ) ;
479
481
if !infer_args || arg_counts. types > param_counts. types - defaults. types - has_self as usize
480
482
{
481
- arg_count_correct = check_kind_count (
483
+ type_count_correct = check_kind_count (
482
484
"type" ,
483
485
param_counts. types - defaults. types - has_self as usize ,
484
486
param_counts. types - has_self as usize ,
485
487
arg_counts. types ,
486
488
arg_counts. lifetimes ,
487
489
& mut unexpected_spans,
488
490
false ,
489
- )
490
- . and ( arg_count_correct) ;
491
+ ) ;
491
492
}
492
493
494
+ // Emit a help message if it's possible that a type could be surrounded in braces
495
+ if let Err ( ( c_mismatch, Some ( ref mut _const_err) ) ) = const_count_correct {
496
+ if let Err ( ( _, Some ( ref mut type_err) ) ) = type_count_correct {
497
+ let possible_matches = args. args [ arg_counts. lifetimes ..]
498
+ . iter ( )
499
+ . filter ( |arg| {
500
+ matches ! (
501
+ arg,
502
+ GenericArg :: Type ( hir:: Ty { kind: hir:: TyKind :: Path { .. } , .. } )
503
+ )
504
+ } )
505
+ . take ( c_mismatch. max ( 0 ) as usize ) ;
506
+ for arg in possible_matches {
507
+ let suggestions = vec ! [
508
+ ( arg. span( ) . shrink_to_lo( ) , String :: from( "{ " ) ) ,
509
+ ( arg. span( ) . shrink_to_hi( ) , String :: from( " }" ) ) ,
510
+ ] ;
511
+ type_err. multipart_suggestion (
512
+ "If this generic argument was intended as a const parameter, \
513
+ try surrounding it with braces:",
514
+ suggestions,
515
+ Applicability :: MaybeIncorrect ,
516
+ ) ;
517
+ }
518
+ }
519
+ }
520
+
521
+ let emit_correct =
522
+ |correct : Result < ( ) , ( _ , Option < rustc_errors:: DiagnosticBuilder < ' _ > > ) > | match correct {
523
+ Ok ( ( ) ) => Ok ( ( ) ) ,
524
+ Err ( ( _, None ) ) => Err ( ( ) ) ,
525
+ Err ( ( _, Some ( mut err) ) ) => {
526
+ err. emit ( ) ;
527
+ Err ( ( ) )
528
+ }
529
+ } ;
530
+
531
+ let arg_count_correct = emit_correct ( lifetime_count_correct)
532
+ . and ( emit_correct ( const_count_correct) )
533
+ . and ( emit_correct ( type_count_correct) ) ;
534
+
493
535
GenericArgCountResult {
494
536
explicit_late_bound,
495
- correct : arg_count_correct. map_err ( |reported_err | GenericArgCountMismatch {
496
- reported : if reported_err { Some ( ErrorReported ) } else { None } ,
537
+ correct : arg_count_correct. map_err ( |( ) | GenericArgCountMismatch {
538
+ reported : Some ( ErrorReported ) ,
497
539
invalid_args : unexpected_spans,
498
540
} ) ,
499
541
}
0 commit comments