@@ -608,6 +608,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
608
608
609
609
pub fn check_crate ( krate : & ast:: Crate , sess : & Session ) {
610
610
maybe_stage_features ( sess, krate) ;
611
+ check_incompatible_features ( sess) ;
611
612
let mut visitor = PostExpansionVisitor { sess, features : & sess. features_untracked ( ) } ;
612
613
613
614
let spans = sess. parse_sess . gated_spans . spans . borrow ( ) ;
@@ -677,3 +678,36 @@ fn maybe_stage_features(sess: &Session, krate: &ast::Crate) {
677
678
}
678
679
}
679
680
}
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