@@ -608,6 +608,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
608608
609609pub fn check_crate ( krate : & ast:: Crate , sess : & Session ) {
610610 maybe_stage_features ( sess, krate) ;
611+ check_incompatible_features ( sess) ;
611612 let mut visitor = PostExpansionVisitor { sess, features : & sess. features_untracked ( ) } ;
612613
613614 let spans = sess. parse_sess . gated_spans . spans . borrow ( ) ;
@@ -677,3 +678,36 @@ fn maybe_stage_features(sess: &Session, krate: &ast::Crate) {
677678 }
678679 }
679680}
681+
682+ fn check_incompatible_features ( sess : & Session ) {
683+ let features = sess. features_untracked ( ) ;
684+
685+ let declared_features = features
686+ . declared_lang_features
687+ . iter ( )
688+ . copied ( )
689+ . map ( |( name, span, _) | ( name, span) )
690+ . chain ( features. declared_lib_features . iter ( ) . copied ( ) ) ;
691+
692+ for ( f1, f2) in rustc_feature:: INCOMPATIBLE_FEATURES
693+ . iter ( )
694+ . filter ( |& & ( f1, f2) | features. enabled ( f1) && features. enabled ( f2) )
695+ {
696+ if let Some ( ( f1_name, f1_span) ) = declared_features. clone ( ) . find ( |( name, _) | name == f1) {
697+ if let Some ( ( f2_name, f2_span) ) = declared_features. clone ( ) . find ( |( name, _) | name == f2)
698+ {
699+ let spans = vec ! [ f1_span, f2_span] ;
700+ sess. struct_span_err (
701+ spans. clone ( ) ,
702+ & format ! (
703+ "features `{}` and `{}` are incompatible, using them at the same time \
704+ is not allowed",
705+ f1_name, f2_name
706+ ) ,
707+ )
708+ . help ( "remove one of these features" )
709+ . emit ( ) ;
710+ }
711+ }
712+ }
713+ }
0 commit comments