@@ -23,6 +23,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
2323 sess : & Session ,
2424 arg : & GenericArg < ' _ > ,
2525 kind : & ' static str ,
26+ possible_ordering_error : bool ,
2627 help : Option < & str > ,
2728 ) {
2829 let mut err = struct_span_err ! (
@@ -49,8 +50,23 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
4950 GenericArg :: Const ( _) => ParamKindOrd :: Const { unordered } ,
5051 } ;
5152
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+
5268 // 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 {
5470 let ( first, last) =
5571 if kind_ord < arg_ord { ( kind, arg. descr ( ) ) } else { ( arg. descr ( ) , kind) } ;
5672 err. note ( & format ! ( "{} arguments must be provided before {} arguments" , first, last) ) ;
@@ -148,8 +164,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
148164 // Check whether this segment takes generic arguments and the user has provided any.
149165 let ( generic_args, infer_args) = ctx. args_for_def_id ( def_id) ;
150166
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 ( ) ;
153169
154170 // If we encounter a type or const when we expect a lifetime, we infer the lifetimes.
155171 // 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 {
216232 GenericParamDefKind :: Const => {
217233 ParamKindOrd :: Const {
218234 unordered : tcx
219- . sess
220- . features_untracked ( )
235+ . features ( )
221236 . const_generics ,
222237 }
223238 }
@@ -237,6 +252,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
237252 tcx. sess ,
238253 arg,
239254 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+ } ) ,
240262 Some ( & format ! (
241263 "reorder the arguments: {}: `<{}>`" ,
242264 param_types_present
@@ -288,7 +310,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
288310 assert_eq ! ( kind, "lifetime" ) ;
289311 let provided =
290312 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 ) ;
292314 }
293315
294316 break ;
@@ -346,6 +368,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
346368 // that lifetimes will proceed types. So it suffices to check the number of each generic
347369 // arguments in order to validate them with respect to the generic parameters.
348370 let param_counts = def. own_counts ( ) ;
371+ let named_type_param_count = param_counts. types - has_self as usize ;
349372 let arg_counts = args. own_counts ( ) ;
350373 let infer_lifetimes = position != GenericArgPosition :: Type && arg_counts. lifetimes == 0 ;
351374
@@ -384,11 +407,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
384407 // For kinds without defaults (e.g.., lifetimes), `required == permitted`.
385408 // For other kinds (i.e., types), `permitted` may be greater than `required`.
386409 if required <= provided && provided <= permitted {
387- return Ok ( ( ) ) ;
410+ return true ;
388411 }
389412
390413 if silent {
391- return Err ( ( 0i32 , None ) ) ;
414+ return false ;
392415 }
393416
394417 // Unfortunately lifetime and type parameter mismatches are typically styled
@@ -404,25 +427,26 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
404427 ( required, "" )
405428 } ;
406429
407- let ( spans, label ) = if required == permitted && provided > permitted {
430+ let ( spans, labels ) = if provided > permitted {
408431 // In the case when the user has provided too many arguments,
409432 // 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]
411435 . iter ( )
412- . map ( |arg| arg. span ( ) )
413- . collect ( ) ;
436+ . map ( |arg| ( arg. span ( ) , format ! ( "unexpected {} argument" , arg . short_descr ( ) ) ) )
437+ . unzip ( ) ;
414438 unexpected_spans. extend ( spans. clone ( ) ) ;
415- ( spans, format ! ( "unexpected {} argument" , kind ) )
439+ ( spans, labels )
416440 } else {
417441 (
418442 vec ! [ span] ,
419- format ! (
443+ vec ! [ format!(
420444 "expected {}{} {} argument{}" ,
421445 quantifier,
422446 bound,
423447 kind,
424448 pluralize!( bound) ,
425- ) ,
449+ ) ] ,
426450 )
427451 } ;
428452
@@ -434,105 +458,57 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
434458 ) ,
435459 DiagnosticId :: Error ( "E0107" . into ( ) ) ,
436460 ) ;
437- for span in spans {
461+ for ( span, label ) in spans. into_iter ( ) . zip ( labels ) {
438462 err. span_label ( span, label. as_str ( ) ) ;
439463 }
440-
441- assert_ne ! ( bound, provided) ;
442- Err ( ( bound as i32 - provided as i32 , Some ( err) ) )
464+ err. emit ( ) ;
465+ false
443466 } ;
444467
445468 let mut unexpected_spans = vec ! [ ] ;
446469
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+ ) ;
515479
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+ } ;
525487
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+ ) ;
529501
530502 GenericArgCountResult {
531503 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+ } ,
536512 }
537513 }
538514
0 commit comments