@@ -11,7 +11,7 @@ use rustc_hir::GenericArg;
11
11
use rustc_middle:: ty:: {
12
12
self , subst, subst:: SubstsRef , GenericParamDef , GenericParamDefKind , Ty , TyCtxt ,
13
13
} ;
14
- use rustc_session:: { lint:: builtin:: LATE_BOUND_LIFETIME_ARGUMENTS , Session } ;
14
+ use rustc_session:: lint:: builtin:: LATE_BOUND_LIFETIME_ARGUMENTS ;
15
15
use rustc_span:: { symbol:: kw, MultiSpan , Span } ;
16
16
17
17
use smallvec:: SmallVec ;
@@ -20,62 +20,72 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
20
20
/// Report an error that a generic argument did not match the generic parameter that was
21
21
/// expected.
22
22
fn generic_arg_mismatch_err (
23
- sess : & Session ,
23
+ tcx : TyCtxt < ' _ > ,
24
24
arg : & GenericArg < ' _ > ,
25
- kind : & ' static str ,
25
+ param : & GenericParamDef ,
26
26
possible_ordering_error : bool ,
27
27
help : Option < & str > ,
28
28
) {
29
+ let sess = tcx. sess ;
29
30
let mut err = struct_span_err ! (
30
31
sess,
31
32
arg. span( ) ,
32
33
E0747 ,
33
34
"{} provided when a {} was expected" ,
34
35
arg. descr( ) ,
35
- kind,
36
+ param . kind. descr ( ) ,
36
37
) ;
37
38
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 {
49
40
if let GenericArg :: Type ( hir:: Ty { kind : hir:: TyKind :: Infer , .. } ) = arg {
50
41
err. help ( "const arguments cannot yet be inferred with `_`" ) ;
51
42
}
52
43
}
53
44
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, \
69
57
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
+ _ => { }
73
77
}
74
78
79
+ let kind_ord = param. kind . to_ord ( tcx) ;
80
+ let arg_ord = arg. to_ord ( & tcx. features ( ) ) ;
81
+
75
82
// This note is only true when generic parameters are strictly ordered by their kind.
76
83
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
+ } ;
79
89
err. note ( & format ! ( "{} arguments must be provided before {} arguments" , first, last) ) ;
80
90
if let Some ( help) = help {
81
91
err. help ( help) ;
@@ -203,7 +213,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
203
213
// We expected a lifetime argument, but got a type or const
204
214
// argument. That means we're inferring the lifetimes.
205
215
substs. push ( ctx. inferred_kind ( None , param, infer_args) ) ;
206
- force_infer_lt = Some ( arg) ;
216
+ force_infer_lt = Some ( ( arg, param ) ) ;
207
217
params. next ( ) ;
208
218
}
209
219
( GenericArg :: Lifetime ( _) , _, ExplicitLateBound :: Yes ) => {
@@ -213,7 +223,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
213
223
// ignore it.
214
224
args. next ( ) ;
215
225
}
216
- ( _, kind , _) => {
226
+ ( _, _ , _) => {
217
227
// We expected one kind of parameter, but the user provided
218
228
// another. This is an error. However, if we already know that
219
229
// the arguments don't match up with the parameters, we won't issue
@@ -256,9 +266,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
256
266
param_types_present. dedup ( ) ;
257
267
258
268
Self :: generic_arg_mismatch_err (
259
- tcx. sess ,
269
+ tcx,
260
270
arg,
261
- kind . descr ( ) ,
271
+ param ,
262
272
!args_iter. clone ( ) . is_sorted_by_key ( |arg| match arg {
263
273
GenericArg :: Lifetime ( _) => ParamKindOrd :: Lifetime ,
264
274
GenericArg :: Type ( _) => ParamKindOrd :: Type ,
@@ -315,9 +325,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
315
325
{
316
326
let kind = arg. descr ( ) ;
317
327
assert_eq ! ( kind, "lifetime" ) ;
318
- let provided =
328
+ let ( provided_arg , param ) =
319
329
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 ) ;
321
331
}
322
332
323
333
break ;
0 commit comments