@@ -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 ;
14+ use rustc_session:: { lint:: builtin:: LATE_BOUND_LIFETIME_ARGUMENTS , Session } ;
1515use rustc_span:: { symbol:: kw, MultiSpan , Span } ;
1616
1717use smallvec:: SmallVec ;
@@ -20,72 +20,62 @@ 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- tcx : TyCtxt < ' _ > ,
23+ sess : & Session ,
2424 arg : & GenericArg < ' _ > ,
25- param : & GenericParamDef ,
25+ kind : & ' static str ,
2626 possible_ordering_error : bool ,
2727 help : Option < & str > ,
2828 ) {
29- let sess = tcx. sess ;
3029 let mut err = struct_span_err ! (
3130 sess,
3231 arg. span( ) ,
3332 E0747 ,
3433 "{} provided when a {} was expected" ,
3534 arg. descr( ) ,
36- param . kind. descr ( ) ,
35+ kind,
3736 ) ;
3837
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 {
4049 if let GenericArg :: Type ( hir:: Ty { kind : hir:: TyKind :: Infer , .. } ) = arg {
4150 err. help ( "const arguments cannot yet be inferred with `_`" ) ;
4251 }
4352 }
4453
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, \
5769 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+ ) ;
7773 }
7874
79- let kind_ord = param. kind . to_ord ( tcx) ;
80- let arg_ord = arg. to_ord ( & tcx. features ( ) ) ;
81-
8275 // This note is only true when generic parameters are strictly ordered by their kind.
8376 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) } ;
8979 err. note ( & format ! ( "{} arguments must be provided before {} arguments" , first, last) ) ;
9080 if let Some ( help) = help {
9181 err. help ( help) ;
@@ -213,7 +203,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
213203 // We expected a lifetime argument, but got a type or const
214204 // argument. That means we're inferring the lifetimes.
215205 substs. push ( ctx. inferred_kind ( None , param, infer_args) ) ;
216- force_infer_lt = Some ( ( arg, param ) ) ;
206+ force_infer_lt = Some ( arg) ;
217207 params. next ( ) ;
218208 }
219209 ( GenericArg :: Lifetime ( _) , _, ExplicitLateBound :: Yes ) => {
@@ -223,7 +213,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
223213 // ignore it.
224214 args. next ( ) ;
225215 }
226- ( _, _ , _) => {
216+ ( _, kind , _) => {
227217 // We expected one kind of parameter, but the user provided
228218 // another. This is an error. However, if we already know that
229219 // the arguments don't match up with the parameters, we won't issue
@@ -266,9 +256,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
266256 param_types_present. dedup ( ) ;
267257
268258 Self :: generic_arg_mismatch_err (
269- tcx,
259+ tcx. sess ,
270260 arg,
271- param ,
261+ kind . descr ( ) ,
272262 !args_iter. clone ( ) . is_sorted_by_key ( |arg| match arg {
273263 GenericArg :: Lifetime ( _) => ParamKindOrd :: Lifetime ,
274264 GenericArg :: Type ( _) => ParamKindOrd :: Type ,
@@ -325,9 +315,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
325315 {
326316 let kind = arg. descr ( ) ;
327317 assert_eq ! ( kind, "lifetime" ) ;
328- let ( provided_arg , param ) =
318+ let provided =
329319 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 ) ;
331321 }
332322
333323 break ;
0 commit comments