@@ -30,11 +30,12 @@ use require_c_abi_if_variadic;
3030use util:: common:: ErrorReported ;
3131use util:: nodemap:: { FxHashSet , FxHashMap } ;
3232use errors:: { FatalError , DiagnosticId } ;
33+ use lint;
3334
3435use std:: iter;
3536use syntax:: ast;
3637use syntax:: feature_gate:: { GateIssue , emit_feature_err} ;
37- use syntax_pos:: Span ;
38+ use syntax_pos:: { Span , MultiSpan } ;
3839
3940pub trait AstConv < ' gcx , ' tcx > {
4041 fn tcx < ' a > ( & ' a self ) -> TyCtxt < ' a , ' gcx , ' tcx > ;
@@ -172,21 +173,164 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
172173 -> & ' tcx Substs < ' tcx >
173174 {
174175
175- let ( substs, assoc_bindings) =
176- item_segment . with_generic_args ( |generic_args| {
177- self . create_substs_for_ast_path (
178- span ,
179- def_id ,
180- generic_args ,
181- item_segment . infer_types ,
182- None )
183- } ) ;
176+ let ( substs, assoc_bindings) = item_segment . with_generic_args ( |generic_args| {
177+ self . create_substs_for_ast_path (
178+ span ,
179+ def_id ,
180+ generic_args ,
181+ item_segment . infer_types ,
182+ None ,
183+ )
184+ } ) ;
184185
185- assoc_bindings. first ( ) . map ( |b| self . prohibit_projection ( b. span ) ) ;
186+ assoc_bindings. first ( ) . map ( |b| Self :: prohibit_assoc_ty_binding ( self . tcx ( ) , b. span ) ) ;
186187
187188 substs
188189 }
189190
191+ /// Check that the correct number of generic arguments have been provided.
192+ /// This is used both for type declarations and function calls.
193+ pub fn check_generic_arg_count (
194+ tcx : TyCtxt ,
195+ span : Span ,
196+ def : & ty:: Generics ,
197+ args : & hir:: GenericArgs ,
198+ is_declaration : bool ,
199+ is_method_call : bool ,
200+ has_self : bool ,
201+ infer_types : bool ,
202+ ) -> bool {
203+ // At this stage we are guaranteed that the generic arguments are in the correct order, e.g.
204+ // that lifetimes will proceed types. So it suffices to check the number of each generic
205+ // arguments in order to validate them with respect to the generic parameters.
206+ let param_counts = def. own_counts ( ) ;
207+ let arg_counts = args. own_counts ( ) ;
208+ let infer_lifetimes = !is_declaration && arg_counts. lifetimes == 0 ;
209+
210+ let mut defaults: ty:: GenericParamCount = Default :: default ( ) ;
211+ for param in & def. params {
212+ match param. kind {
213+ GenericParamDefKind :: Lifetime => { }
214+ GenericParamDefKind :: Type { has_default, .. } => {
215+ defaults. types += has_default as usize
216+ }
217+ } ;
218+ }
219+
220+ if !is_declaration && !args. bindings . is_empty ( ) {
221+ AstConv :: prohibit_assoc_ty_binding ( tcx, args. bindings [ 0 ] . span ) ;
222+ }
223+
224+ // Prohibit explicit lifetime arguments if late-bound lifetime parameters are present.
225+ if !infer_lifetimes {
226+ if let Some ( span_late) = def. has_late_bound_regions {
227+ let msg = "cannot specify lifetime arguments explicitly \
228+ if late bound lifetime parameters are present";
229+ let note = "the late bound lifetime parameter is introduced here" ;
230+ let span = args. args [ 0 ] . span ( ) ;
231+ if !is_method_call && arg_counts. lifetimes != param_counts. lifetimes {
232+ let mut err = tcx. sess . struct_span_err ( span, msg) ;
233+ err. span_note ( span_late, note) ;
234+ err. emit ( ) ;
235+ return true ;
236+ } else {
237+ let mut multispan = MultiSpan :: from_span ( span) ;
238+ multispan. push_span_label ( span_late, note. to_string ( ) ) ;
239+ tcx. lint_node ( lint:: builtin:: LATE_BOUND_LIFETIME_ARGUMENTS ,
240+ args. args [ 0 ] . id ( ) , multispan, msg) ;
241+ return false ;
242+ }
243+ }
244+ }
245+
246+ let check_kind_count = |error_code_less : & str ,
247+ error_code_more : & str ,
248+ kind,
249+ required,
250+ permitted,
251+ provided| {
252+ // We enforce the following: `required` <= `provided` <= `permitted`.
253+ // For kinds without defaults (i.e. lifetimes), `required == permitted`.
254+ // For other kinds (i.e. types), `permitted` may be greater than `required`.
255+ if required <= provided && provided <= permitted {
256+ return false ;
257+ }
258+
259+ // Unfortunately lifetime and type parameter mismatches are typically styled
260+ // differently in diagnostics, which means we have a few cases to consider here.
261+ let ( bound, quantifier, suppress_error) = if required != permitted {
262+ if provided < required {
263+ ( required, "at least " , false )
264+ } else { // provided > permitted
265+ ( permitted, "at most " , true )
266+ }
267+ } else {
268+ ( required, "" , false )
269+ } ;
270+ let label = if required == permitted && provided > permitted {
271+ let diff = provided - permitted;
272+ format ! (
273+ "{}unexpected {} argument{}" ,
274+ if diff != 1 { format!( "{} " , diff) } else { String :: new( ) } ,
275+ kind,
276+ if diff != 1 { "s" } else { "" } ,
277+ )
278+ } else {
279+ format ! (
280+ "expected {}{} {} argument{}" ,
281+ quantifier,
282+ bound,
283+ kind,
284+ if required != 1 { "s" } else { "" } ,
285+ )
286+ } ;
287+
288+ tcx. sess . struct_span_err_with_code (
289+ span,
290+ & format ! (
291+ "wrong number of {} arguments: expected {}{}, found {}" ,
292+ kind,
293+ quantifier,
294+ bound,
295+ provided,
296+ ) ,
297+ DiagnosticId :: Error ( {
298+ if provided <= permitted {
299+ error_code_less
300+ } else {
301+ error_code_more
302+ }
303+ } . into ( ) )
304+ ) . span_label ( span, label) . emit ( ) ;
305+
306+ suppress_error
307+ } ;
308+
309+ if !infer_lifetimes || arg_counts. lifetimes > param_counts. lifetimes {
310+ check_kind_count (
311+ "E0107" ,
312+ "E0107" ,
313+ "lifetime" ,
314+ param_counts. lifetimes ,
315+ param_counts. lifetimes ,
316+ arg_counts. lifetimes ,
317+ ) ;
318+ }
319+ if !infer_types
320+ || arg_counts. types > param_counts. types - defaults. types - has_self as usize {
321+ check_kind_count (
322+ "E0243" ,
323+ "E0244" , // FIXME: E0243 and E0244 should be unified.
324+ "type" ,
325+ param_counts. types - defaults. types - has_self as usize ,
326+ param_counts. types - has_self as usize ,
327+ arg_counts. types ,
328+ )
329+ } else {
330+ false
331+ }
332+ }
333+
190334 /// Creates the relevant generic argument substitutions
191335 /// corresponding to a set of generic parameters.
192336 pub fn create_substs_for_generic_args < ' a , ' b , A , P , I > (
@@ -355,7 +499,16 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
355499 assert_eq ! ( generic_params. has_self, self_ty. is_some( ) ) ;
356500
357501 let has_self = generic_params. has_self ;
358- check_generic_arg_count ( tcx, span, & generic_params, & generic_args, has_self, infer_types) ;
502+ Self :: check_generic_arg_count (
503+ self . tcx ( ) ,
504+ span,
505+ & generic_params,
506+ & generic_args,
507+ true , // `is_declaration`
508+ false , // `is_method_call` (irrelevant here)
509+ has_self,
510+ infer_types,
511+ ) ;
359512
360513 let is_object = self_ty. map_or ( false , |ty| ty. sty == TRAIT_OBJECT_DUMMY_SELF ) ;
361514 let default_needs_object_self = |param : & ty:: GenericParamDef | {
@@ -548,7 +701,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
548701 trait_def_id,
549702 self_ty,
550703 trait_segment) ;
551- assoc_bindings. first ( ) . map ( |b| self . prohibit_projection ( b. span ) ) ;
704+ assoc_bindings. first ( ) . map ( |b| AstConv :: prohibit_assoc_ty_binding ( self . tcx ( ) , b. span ) ) ;
552705 ty:: TraitRef :: new ( trait_def_id, substs)
553706 }
554707
@@ -1113,15 +1266,15 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
11131266 }
11141267 }
11151268 for binding in & generic_args. bindings {
1116- self . prohibit_projection ( binding. span ) ;
1269+ Self :: prohibit_assoc_ty_binding ( self . tcx ( ) , binding. span ) ;
11171270 break ;
11181271 }
11191272 } )
11201273 }
11211274 }
11221275
1123- pub fn prohibit_projection ( & self , span : Span ) {
1124- let mut err = struct_span_err ! ( self . tcx( ) . sess, span, E0229 ,
1276+ pub fn prohibit_assoc_ty_binding ( tcx : TyCtxt , span : Span ) {
1277+ let mut err = struct_span_err ! ( tcx. sess, span, E0229 ,
11251278 "associated type bindings are not allowed here" ) ;
11261279 err. span_label ( span, "associated type not allowed here" ) . emit ( ) ;
11271280 }
@@ -1497,109 +1650,6 @@ fn split_auto_traits<'a, 'b, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
14971650 ( auto_traits, trait_bounds)
14981651}
14991652
1500- pub fn check_generic_arg_count (
1501- tcx : TyCtxt ,
1502- span : Span ,
1503- def : & ty:: Generics ,
1504- args : & hir:: GenericArgs ,
1505- has_self : bool ,
1506- infer_types : bool ,
1507- ) {
1508- // At this stage we are guaranteed that the generic arguments are in the correct order, e.g.
1509- // that lifetimes will proceed types. So it suffices to check the number of each generic
1510- // arguments in order to validate them with respect to the generic parameters.
1511- let param_counts = def. own_counts ( ) ;
1512- let arg_counts = args. own_counts ( ) ;
1513-
1514- let mut defaults: ty:: GenericParamCount = Default :: default ( ) ;
1515- for param in & def. params {
1516- match param. kind {
1517- GenericParamDefKind :: Lifetime => { }
1518- GenericParamDefKind :: Type { has_default, .. } => defaults. types += has_default as usize ,
1519- } ;
1520- }
1521-
1522- let check_kind_count = |error_code_less : & str ,
1523- error_code_more : & str ,
1524- kind,
1525- required,
1526- permitted,
1527- provided| {
1528- // We enforce the following: `required` <= `provided` <= `permitted`.
1529- // For kinds without defaults (i.e. lifetimes), `required == permitted`.
1530- // For other kinds (i.e. types), `permitted` may be greater than `required`.
1531- if required <= provided && provided <= permitted {
1532- return ;
1533- }
1534-
1535- // Unfortunately lifetime and type parameter mismatches are typically styled
1536- // differently in diagnostics, which means we have a few cases to consider here.
1537- let ( bound, quantifier) = if required != permitted {
1538- if provided < required {
1539- ( required, "at least " )
1540- } else { // provided > permitted
1541- ( permitted, "at most " )
1542- }
1543- } else {
1544- ( required, "" )
1545- } ;
1546- let label = if required == permitted && provided > permitted {
1547- let diff = provided - permitted;
1548- format ! (
1549- "{}unexpected {} argument{}" ,
1550- if diff != 1 { format!( "{} " , diff) } else { String :: new( ) } ,
1551- kind,
1552- if diff != 1 { "s" } else { "" } ,
1553- )
1554- } else {
1555- format ! (
1556- "expected {}{} {} argument{}" ,
1557- quantifier,
1558- bound,
1559- kind,
1560- if required != 1 { "s" } else { "" } ,
1561- )
1562- } ;
1563-
1564- tcx. sess . struct_span_err_with_code (
1565- span,
1566- & format ! (
1567- "wrong number of {} arguments: expected {}{}, found {}" ,
1568- kind,
1569- quantifier,
1570- bound,
1571- provided,
1572- ) ,
1573- DiagnosticId :: Error ( {
1574- if provided <= permitted {
1575- error_code_less
1576- } else {
1577- error_code_more
1578- }
1579- } . into ( ) )
1580- ) . span_label ( span, label) . emit ( ) ;
1581- } ;
1582-
1583- check_kind_count (
1584- "E0107" ,
1585- "E0107" ,
1586- "lifetime" ,
1587- param_counts. lifetimes ,
1588- param_counts. lifetimes ,
1589- arg_counts. lifetimes ,
1590- ) ;
1591- if !infer_types || arg_counts. types > param_counts. types - defaults. types - has_self as usize {
1592- check_kind_count (
1593- "E0243" ,
1594- "E0244" , // FIXME: E0243 and E0244 should be unified.
1595- "type" ,
1596- param_counts. types - defaults. types - has_self as usize ,
1597- param_counts. types - has_self as usize ,
1598- arg_counts. types ,
1599- ) ;
1600- }
1601- }
1602-
16031653// A helper struct for conveniently grouping a set of bounds which we pass to
16041654// and return from functions in multiple places.
16051655#[ derive( PartialEq , Eq , Clone , Debug ) ]
0 commit comments