@@ -11,7 +11,7 @@ use rustc_hir::GenericArg;
1111use rustc_middle:: ty:: {
1212 self , subst, subst:: SubstsRef , GenericParamDef , GenericParamDefKind , Ty , TyCtxt ,
1313} ;
14- use rustc_session:: { lint:: builtin:: LATE_BOUND_LIFETIME_ARGUMENTS , Session } ;
14+ use rustc_session:: lint:: builtin:: LATE_BOUND_LIFETIME_ARGUMENTS ;
1515use rustc_span:: { symbol:: kw, MultiSpan , Span } ;
1616
1717use smallvec:: SmallVec ;
@@ -20,62 +20,72 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
2020 /// Report an error that a generic argument did not match the generic parameter that was
2121 /// expected.
2222 fn generic_arg_mismatch_err (
23- sess : & Session ,
23+ tcx : TyCtxt < ' _ > ,
2424 arg : & GenericArg < ' _ > ,
25- kind : & ' static str ,
25+ param : & GenericParamDef ,
2626 possible_ordering_error : bool ,
2727 help : Option < & str > ,
2828 ) {
29+ let sess = tcx. sess ;
2930 let mut err = struct_span_err ! (
3031 sess,
3132 arg. span( ) ,
3233 E0747 ,
3334 "{} provided when a {} was expected" ,
3435 arg. descr( ) ,
35- kind,
36+ param . kind. descr ( ) ,
3637 ) ;
3738
38- let unordered = sess. features_untracked ( ) . const_generics ;
39- let kind_ord = match kind {
40- "lifetime" => ParamKindOrd :: Lifetime ,
41- "type" => ParamKindOrd :: Type ,
42- "constant" => ParamKindOrd :: Const { unordered } ,
43- // It's more concise to match on the string representation, though it means
44- // the match is non-exhaustive.
45- _ => bug ! ( "invalid generic parameter kind {}" , kind) ,
46- } ;
47-
48- if let ParamKindOrd :: Const { .. } = kind_ord {
39+ if let GenericParamDefKind :: Const { .. } = param. kind {
4940 if let GenericArg :: Type ( hir:: Ty { kind : hir:: TyKind :: Infer , .. } ) = arg {
5041 err. help ( "const arguments cannot yet be inferred with `_`" ) ;
5142 }
5243 }
5344
54- let arg_ord = match arg {
55- GenericArg :: Lifetime ( _) => ParamKindOrd :: Lifetime ,
56- GenericArg :: Type ( _) => ParamKindOrd :: Type ,
57- GenericArg :: Const ( _) => ParamKindOrd :: Const { unordered } ,
58- } ;
59-
60- if matches ! ( arg, GenericArg :: Type ( hir:: Ty { kind: hir:: TyKind :: Path { .. } , .. } ) )
61- && matches ! ( kind_ord, ParamKindOrd :: Const { .. } )
62- {
63- let suggestions = vec ! [
64- ( arg. span( ) . shrink_to_lo( ) , String :: from( "{ " ) ) ,
65- ( arg. span( ) . shrink_to_hi( ) , String :: from( " }" ) ) ,
66- ] ;
67- err. multipart_suggestion (
68- "if this generic argument was intended as a const parameter, \
45+ // Specific suggestion set for diagnostics
46+ match ( arg, & param. kind ) {
47+ (
48+ GenericArg :: Type ( hir:: Ty { kind : hir:: TyKind :: Path { .. } , .. } ) ,
49+ GenericParamDefKind :: Const { .. } ,
50+ ) => {
51+ let suggestions = vec ! [
52+ ( arg. span( ) . shrink_to_lo( ) , String :: from( "{ " ) ) ,
53+ ( arg. span( ) . shrink_to_hi( ) , String :: from( " }" ) ) ,
54+ ] ;
55+ err. multipart_suggestion (
56+ "if this generic argument was intended as a const parameter, \
6957 try surrounding it with braces:",
70- suggestions,
71- Applicability :: MaybeIncorrect ,
72- ) ;
58+ suggestions,
59+ Applicability :: MaybeIncorrect ,
60+ ) ;
61+ }
62+ (
63+ GenericArg :: Type ( hir:: Ty { kind : hir:: TyKind :: Array ( _, len) , .. } ) ,
64+ GenericParamDefKind :: Const { .. } ,
65+ ) if tcx. type_of ( param. def_id ) == tcx. types . usize => {
66+ let snippet = sess. source_map ( ) . span_to_snippet ( tcx. hir ( ) . span ( len. hir_id ) ) ;
67+ if let Ok ( snippet) = snippet {
68+ err. span_suggestion (
69+ arg. span ( ) ,
70+ "array type provided where a `usize` was expected, try" ,
71+ format ! ( "{{ {} }}" , snippet) ,
72+ Applicability :: MaybeIncorrect ,
73+ ) ;
74+ }
75+ }
76+ _ => { }
7377 }
7478
79+ let kind_ord = param. kind . to_ord ( tcx) ;
80+ let arg_ord = arg. to_ord ( & tcx. features ( ) ) ;
81+
7582 // This note is only true when generic parameters are strictly ordered by their kind.
7683 if possible_ordering_error && kind_ord. cmp ( & arg_ord) != core:: cmp:: Ordering :: Equal {
77- let ( first, last) =
78- if kind_ord < arg_ord { ( kind, arg. descr ( ) ) } else { ( arg. descr ( ) , kind) } ;
84+ let ( first, last) = if kind_ord < arg_ord {
85+ ( param. kind . descr ( ) , arg. descr ( ) )
86+ } else {
87+ ( arg. descr ( ) , param. kind . descr ( ) )
88+ } ;
7989 err. note ( & format ! ( "{} arguments must be provided before {} arguments" , first, last) ) ;
8090 if let Some ( help) = help {
8191 err. help ( help) ;
@@ -203,7 +213,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
203213 // We expected a lifetime argument, but got a type or const
204214 // argument. That means we're inferring the lifetimes.
205215 substs. push ( ctx. inferred_kind ( None , param, infer_args) ) ;
206- force_infer_lt = Some ( arg) ;
216+ force_infer_lt = Some ( ( arg, param ) ) ;
207217 params. next ( ) ;
208218 }
209219 ( GenericArg :: Lifetime ( _) , _, ExplicitLateBound :: Yes ) => {
@@ -213,7 +223,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
213223 // ignore it.
214224 args. next ( ) ;
215225 }
216- ( _, kind , _) => {
226+ ( _, _ , _) => {
217227 // We expected one kind of parameter, but the user provided
218228 // another. This is an error. However, if we already know that
219229 // the arguments don't match up with the parameters, we won't issue
@@ -256,9 +266,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
256266 param_types_present. dedup ( ) ;
257267
258268 Self :: generic_arg_mismatch_err (
259- tcx. sess ,
269+ tcx,
260270 arg,
261- kind . descr ( ) ,
271+ param ,
262272 !args_iter. clone ( ) . is_sorted_by_key ( |arg| match arg {
263273 GenericArg :: Lifetime ( _) => ParamKindOrd :: Lifetime ,
264274 GenericArg :: Type ( _) => ParamKindOrd :: Type ,
@@ -315,9 +325,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
315325 {
316326 let kind = arg. descr ( ) ;
317327 assert_eq ! ( kind, "lifetime" ) ;
318- let provided =
328+ let ( provided_arg , param ) =
319329 force_infer_lt. expect ( "lifetimes ought to have been inferred" ) ;
320- Self :: generic_arg_mismatch_err ( tcx. sess , provided , kind , false , None ) ;
330+ Self :: generic_arg_mismatch_err ( tcx, provided_arg , param , false , None ) ;
321331 }
322332
323333 break ;
0 commit comments