@@ -11,7 +11,6 @@ use syntax::print::pprust;
1111use rustc:: lint;
1212use rustc:: lint:: builtin:: { BuiltinLintDiagnostics , NESTED_IMPL_TRAIT } ;
1313use rustc:: session:: Session ;
14- use rustc_data_structures:: fx:: FxHashMap ;
1514use syntax:: ast:: * ;
1615use syntax:: attr;
1716use syntax:: source_map:: Spanned ;
@@ -21,7 +20,7 @@ use syntax::visit::{self, Visitor};
2120use syntax:: { span_err, struct_span_err, walk_list} ;
2221use syntax_ext:: proc_macro_decls:: is_proc_macro_attr;
2322use syntax_pos:: { Span , MultiSpan } ;
24- use errors:: { Applicability , FatalError } ;
23+ use errors:: Applicability ;
2524use log:: debug;
2625
2726#[ derive( Copy , Clone , Debug ) ]
@@ -346,104 +345,65 @@ impl<'a> AstValidator<'a> {
346345 }
347346}
348347
349- enum GenericPosition {
350- Param ,
351- Arg ,
352- }
353-
354348fn validate_generics_order < ' a > (
355- sess : & Session ,
356349 handler : & errors:: Handler ,
357350 generics : impl Iterator <
358- Item = (
359- ParamKindOrd ,
360- Option < & ' a [ GenericBound ] > ,
361- Span ,
362- Option < String >
363- ) ,
351+ Item = ( ParamKindOrd , Option < & ' a [ GenericBound ] > , Span , Option < String > ) ,
364352 > ,
365- pos : GenericPosition ,
366353 span : Span ,
367354) {
368- let mut max_param: Option < ParamKindOrd > = None ;
369- let mut out_of_order = FxHashMap :: default ( ) ;
370- let mut param_idents = vec ! [ ] ;
371- let mut found_type = false ;
372- let mut found_const = false ;
373-
374- for ( kind, bounds, span, ident) in generics {
375- if let Some ( ident) = ident {
376- param_idents. push ( ( kind, bounds, param_idents. len ( ) , ident) ) ;
377- }
378- let max_param = & mut max_param;
379- match max_param {
380- Some ( max_param) if * max_param > kind => {
381- let entry = out_of_order. entry ( kind) . or_insert ( ( * max_param, vec ! [ ] ) ) ;
382- entry. 1 . push ( span) ;
383- }
384- Some ( _) | None => * max_param = Some ( kind) ,
355+ let mut lifetimes = vec ! [ ] ;
356+ let mut type_args = vec ! [ ] ;
357+ let mut const_args = vec ! [ ] ;
358+ let mut out_of_order = false ;
359+
360+ for ( kind, bounds, _span, ident) in generics {
361+ let ident = match ident {
362+ Some ( ident) => ident,
363+ None => return ,
385364 } ;
386365 match kind {
387- ParamKindOrd :: Type => found_type = true ,
388- ParamKindOrd :: Const => found_const = true ,
389- _ => { }
366+ ParamKindOrd :: Lifetime => {
367+ lifetimes. push ( ( ident, bounds) ) ;
368+ out_of_order |= type_args. len ( ) > 0 || const_args. len ( ) > 0 ;
369+ }
370+ ParamKindOrd :: Type => {
371+ type_args. push ( ( ident, bounds) ) ;
372+ out_of_order |= const_args. len ( ) > 0 ;
373+ }
374+ ParamKindOrd :: Const => {
375+ const_args. push ( ( ident, bounds) ) ;
376+ }
390377 }
391378 }
379+ if !out_of_order {
380+ return ;
381+ }
392382
393383 let mut ordered_params = "<" . to_string ( ) ;
394- if !out_of_order. is_empty ( ) {
395- param_idents. sort_by_key ( |& ( po, _, i, _) | ( po, i) ) ;
396- let mut first = true ;
397- for ( _, bounds, _, ident) in param_idents {
398- if !first {
399- ordered_params += ", " ;
400- }
401- ordered_params += & ident;
402- if let Some ( bounds) = bounds {
403- if !bounds. is_empty ( ) {
404- ordered_params += ": " ;
405- ordered_params += & pprust:: bounds_to_string ( & bounds) ;
406- }
384+ let mut first = true ;
385+ for ( ident, bounds) in lifetimes. iter ( ) . chain ( type_args. iter ( ) ) . chain ( const_args. iter ( ) ) {
386+ if !first {
387+ ordered_params += ", " ;
388+ }
389+ ordered_params += & ident;
390+ if let Some ( bounds) = bounds {
391+ if !bounds. is_empty ( ) {
392+ ordered_params += ": " ;
393+ ordered_params += & pprust:: bounds_to_string ( & bounds) ;
407394 }
408- first = false ;
409395 }
396+ first = false ;
410397 }
411398 ordered_params += ">" ;
412399
413- let pos_str = match pos {
414- GenericPosition :: Param => "parameter" ,
415- GenericPosition :: Arg => "argument" ,
416- } ;
417-
418- for ( param_ord, ( max_param, spans) ) in & out_of_order {
419- let mut err = handler. struct_span_err ( spans. clone ( ) ,
420- & format ! (
421- "{} {pos}s must be declared prior to {} {pos}s" ,
422- param_ord,
423- max_param,
424- pos = pos_str,
425- ) ) ;
426- if let GenericPosition :: Param = pos {
427- err. span_suggestion (
428- span,
429- & format ! (
430- "reorder the {}s: lifetimes, then types{}" ,
431- pos_str,
432- if sess. features_untracked( ) . const_generics { ", then consts" } else { "" } ,
433- ) ,
434- ordered_params. clone ( ) ,
435- Applicability :: MachineApplicable ,
436- ) ;
437- }
438- err. emit ( ) ;
439- }
440-
441- // FIXME(const_generics): we shouldn't have to abort here at all, but we currently get ICEs
442- // if we don't. Const parameters and type parameters can currently conflict if they
443- // are out-of-order.
444- if !out_of_order. is_empty ( ) && found_type && found_const {
445- FatalError . raise ( ) ;
446- }
400+ handler. struct_span_err ( span, "incorrect parameter order" )
401+ . span_suggestion (
402+ span,
403+ "reorder the parameters" ,
404+ ordered_params. clone ( ) ,
405+ Applicability :: MachineApplicable ,
406+ ) . emit ( ) ;
447407}
448408
449409impl < ' a > Visitor < ' a > for AstValidator < ' a > {
@@ -703,21 +663,9 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
703663 fn visit_generic_args ( & mut self , _: Span , generic_args : & ' a GenericArgs ) {
704664 match * generic_args {
705665 GenericArgs :: AngleBracketed ( ref data) => {
706- walk_list ! ( self , visit_generic_arg, & data. args) ;
707- validate_generics_order (
708- self . session ,
709- self . err_handler ( ) ,
710- data. args . iter ( ) . map ( |arg| {
711- ( match arg {
712- GenericArg :: Lifetime ( ..) => ParamKindOrd :: Lifetime ,
713- GenericArg :: Type ( ..) => ParamKindOrd :: Type ,
714- GenericArg :: Const ( ..) => ParamKindOrd :: Const ,
715- } , None , arg. span ( ) , None )
716- } ) ,
717- GenericPosition :: Arg ,
718- generic_args. span ( ) ,
719- ) ;
720-
666+ walk_list ! ( self , visit_lifetime, & data. lifetimes) ;
667+ walk_list ! ( self , visit_ty, & data. types) ;
668+ walk_list ! ( self , visit_anon_const, & data. const_args) ;
721669 // Type bindings such as `Item=impl Debug` in `Iterator<Item=Debug>`
722670 // are allowed to contain nested `impl Trait`.
723671 self . with_impl_trait ( None , |this| {
@@ -750,7 +698,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
750698 }
751699
752700 validate_generics_order (
753- self . session ,
754701 self . err_handler ( ) ,
755702 generics. params . iter ( ) . map ( |param| {
756703 let ident = Some ( param. ident . to_string ( ) ) ;
@@ -764,7 +711,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
764711 } ;
765712 ( kind, Some ( & * param. bounds ) , param. ident . span , ident)
766713 } ) ,
767- GenericPosition :: Param ,
768714 generics. span ,
769715 ) ;
770716
0 commit comments