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