@@ -22,6 +22,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
2222 sess : & Session ,
2323 arg : & GenericArg < ' _ > ,
2424 kind : & ' static str ,
25+ possible_ordering_error : bool ,
2526 help : Option < & str > ,
2627 ) {
2728 let mut err = struct_span_err ! (
@@ -48,8 +49,23 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
4849 GenericArg :: Const ( _) => ParamKindOrd :: Const { unordered } ,
4950 } ;
5051
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+
5167 // 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 {
5369 let ( first, last) =
5470 if kind_ord < arg_ord { ( kind, arg. descr ( ) ) } else { ( arg. descr ( ) , kind) } ;
5571 err. note ( & format ! ( "{} arguments must be provided before {} arguments" , first, last) ) ;
@@ -153,8 +169,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
153169 // Check whether this segment takes generic arguments and the user has provided any.
154170 let ( generic_args, infer_args) = args_for_def_id ( def_id) ;
155171
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 ( ) ;
158174
159175 // If we encounter a type or const when we expect a lifetime, we infer the lifetimes.
160176 // 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 {
221237 GenericParamDefKind :: Const => {
222238 ParamKindOrd :: Const {
223239 unordered : tcx
224- . sess
225- . features_untracked ( )
240+ . features ( )
226241 . const_generics ,
227242 }
228243 }
@@ -242,6 +257,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
242257 tcx. sess ,
243258 arg,
244259 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+ } ) ,
245267 Some ( & format ! (
246268 "reorder the arguments: {}: `<{}>`" ,
247269 param_types_present
@@ -293,7 +315,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
293315 assert_eq ! ( kind, "lifetime" ) ;
294316 let provided =
295317 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 ) ;
297319 }
298320
299321 break ;
@@ -351,6 +373,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
351373 // that lifetimes will proceed types. So it suffices to check the number of each generic
352374 // arguments in order to validate them with respect to the generic parameters.
353375 let param_counts = def. own_counts ( ) ;
376+ let named_type_param_count = param_counts. types - has_self as usize ;
354377 let arg_counts = args. own_counts ( ) ;
355378 let infer_lifetimes = position != GenericArgPosition :: Type && arg_counts. lifetimes == 0 ;
356379
@@ -389,11 +412,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
389412 // For kinds without defaults (e.g.., lifetimes), `required == permitted`.
390413 // For other kinds (i.e., types), `permitted` may be greater than `required`.
391414 if required <= provided && provided <= permitted {
392- return Ok ( ( ) ) ;
415+ return true ;
393416 }
394417
395418 if silent {
396- return Err ( ( 0i32 , None ) ) ;
419+ return false ;
397420 }
398421
399422 // Unfortunately lifetime and type parameter mismatches are typically styled
@@ -409,25 +432,26 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
409432 ( required, "" )
410433 } ;
411434
412- let ( spans, label ) = if provided > permitted {
435+ let ( spans, labels ) = if provided > permitted {
413436 // In the case when the user has provided too many arguments,
414437 // 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]
416440 . iter ( )
417- . map ( |arg| arg. span ( ) )
418- . collect ( ) ;
441+ . map ( |arg| ( arg. span ( ) , format ! ( "unexpected {} argument" , arg . short_descr ( ) ) ) )
442+ . unzip ( ) ;
419443 unexpected_spans. extend ( spans. clone ( ) ) ;
420- ( spans, format ! ( "unexpected {} argument" , kind ) )
444+ ( spans, labels )
421445 } else {
422446 (
423447 vec ! [ span] ,
424- format ! (
448+ vec ! [ format!(
425449 "expected {}{} {} argument{}" ,
426450 quantifier,
427451 bound,
428452 kind,
429453 pluralize!( bound) ,
430- ) ,
454+ ) ] ,
431455 )
432456 } ;
433457
@@ -439,12 +463,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
439463 ) ,
440464 DiagnosticId :: Error ( "E0107" . into ( ) ) ,
441465 ) ;
442- for span in spans {
466+ for ( span, label ) in spans. into_iter ( ) . zip ( labels ) {
443467 err. span_label ( span, label. as_str ( ) ) ;
444468 }
445-
446- assert_ne ! ( bound, provided) ;
447- Err ( ( bound as i32 - provided as i32 , Some ( err) ) )
469+ err. emit ( ) ;
470+ false
448471 } ;
449472
450473 let mut unexpected_spans = vec ! [ ] ;
@@ -459,75 +482,38 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
459482 explicit_late_bound == ExplicitLateBound :: Yes ,
460483 ) ;
461484
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+ } ;
472492
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 ,
479502 arg_counts. lifetimes ,
480503 & mut unexpected_spans,
481504 false ,
482505 ) ;
483506
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-
525507 GenericArgCountResult {
526508 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+ } ,
531517 }
532518 }
533519
0 commit comments