22
33use super :: { find_by_name, mark_used} ;
44
5- use rustc_ast:: ast:: { self , Attribute , MetaItem , MetaItemKind , NestedMetaItem } ;
5+ use rustc_ast:: ast:: { self , Attribute , Lit , LitKind , MetaItem , MetaItemKind , NestedMetaItem } ;
66use rustc_ast_pretty:: pprust;
77use rustc_errors:: { struct_span_err, Applicability , Handler } ;
88use rustc_feature:: { find_gated_cfg, is_builtin_attr_name, Features , GatedCfg } ;
@@ -11,6 +11,7 @@ use rustc_session::parse::{feature_err, ParseSess};
1111use rustc_span:: hygiene:: Transparency ;
1212use rustc_span:: { symbol:: sym, symbol:: Symbol , Span } ;
1313use std:: num:: NonZeroU32 ;
14+ use version_check:: Version ;
1415
1516pub fn is_builtin_attr ( attr : & Attribute ) -> bool {
1617 attr. is_doc_comment ( ) || attr. ident ( ) . filter ( |ident| is_builtin_attr_name ( ident. name ) ) . is_some ( )
@@ -568,11 +569,8 @@ pub fn find_crate_name(attrs: &[Attribute]) -> Option<Symbol> {
568569
569570/// Tests if a cfg-pattern matches the cfg set
570571pub fn cfg_matches ( cfg : & ast:: MetaItem , sess : & ParseSess , features : Option < & Features > ) -> bool {
571- eval_condition ( cfg, sess, & mut |cfg| {
572- let gate = find_gated_cfg ( |sym| cfg. check_name ( sym) ) ;
573- if let ( Some ( feats) , Some ( gated_cfg) ) = ( features, gate) {
574- gate_cfg ( & gated_cfg, cfg. span , sess, feats) ;
575- }
572+ eval_condition ( cfg, sess, features, & mut |cfg| {
573+ try_gate_cfg ( cfg, sess, features) ;
576574 let error = |span, msg| {
577575 sess. span_diagnostic . span_err ( span, msg) ;
578576 true
@@ -603,6 +601,13 @@ pub fn cfg_matches(cfg: &ast::MetaItem, sess: &ParseSess, features: Option<&Feat
603601 } )
604602}
605603
604+ fn try_gate_cfg ( cfg : & ast:: MetaItem , sess : & ParseSess , features : Option < & Features > ) {
605+ let gate = find_gated_cfg ( |sym| cfg. check_name ( sym) ) ;
606+ if let ( Some ( feats) , Some ( gated_cfg) ) = ( features, gate) {
607+ gate_cfg ( & gated_cfg, cfg. span , sess, feats) ;
608+ }
609+ }
610+
606611fn gate_cfg ( gated_cfg : & GatedCfg , cfg_span : Span , sess : & ParseSess , features : & Features ) {
607612 let ( cfg, feature, has_feature) = gated_cfg;
608613 if !has_feature ( features) && !cfg_span. allows_unstable ( * feature) {
@@ -616,9 +621,41 @@ fn gate_cfg(gated_cfg: &GatedCfg, cfg_span: Span, sess: &ParseSess, features: &F
616621pub fn eval_condition (
617622 cfg : & ast:: MetaItem ,
618623 sess : & ParseSess ,
624+ features : Option < & Features > ,
619625 eval : & mut impl FnMut ( & ast:: MetaItem ) -> bool ,
620626) -> bool {
621627 match cfg. kind {
628+ ast:: MetaItemKind :: List ( ref mis) if cfg. name_or_empty ( ) == sym:: version => {
629+ try_gate_cfg ( cfg, sess, features) ;
630+ let ( min_version, span) = match & mis[ ..] {
631+ [ NestedMetaItem :: Literal ( Lit { kind : LitKind :: Str ( sym, ..) , span, .. } ) ] => {
632+ ( sym, span)
633+ }
634+ [ NestedMetaItem :: Literal ( Lit { span, .. } )
635+ | NestedMetaItem :: MetaItem ( MetaItem { span, .. } ) ] => {
636+ sess. span_diagnostic
637+ . struct_span_err ( * span, & * format ! ( "expected a version literal" ) )
638+ . emit ( ) ;
639+ return false ;
640+ }
641+ [ ..] => {
642+ sess. span_diagnostic
643+ . struct_span_err ( cfg. span , "expected single version literal" )
644+ . emit ( ) ;
645+ return false ;
646+ }
647+ } ;
648+ let min_version = match Version :: parse ( & min_version. as_str ( ) ) {
649+ Some ( ver) => ver,
650+ None => {
651+ sess. span_diagnostic . struct_span_err ( * span, "invalid version literal" ) . emit ( ) ;
652+ return false ;
653+ }
654+ } ;
655+ let version = Version :: parse ( env ! ( "CFG_VERSION" ) ) . unwrap ( ) ;
656+
657+ version >= min_version
658+ }
622659 ast:: MetaItemKind :: List ( ref mis) => {
623660 for mi in mis. iter ( ) {
624661 if !mi. is_meta_item ( ) {
@@ -634,12 +671,12 @@ pub fn eval_condition(
634671 // The unwraps below may look dangerous, but we've already asserted
635672 // that they won't fail with the loop above.
636673 match cfg. name_or_empty ( ) {
637- sym:: any => {
638- mis . iter ( ) . any ( |mi| eval_condition ( mi . meta_item ( ) . unwrap ( ) , sess , eval ) )
639- }
640- sym:: all => {
641- mis . iter ( ) . all ( |mi| eval_condition ( mi . meta_item ( ) . unwrap ( ) , sess , eval ) )
642- }
674+ sym:: any => mis
675+ . iter ( )
676+ . any ( |mi| eval_condition ( mi . meta_item ( ) . unwrap ( ) , sess , features , eval ) ) ,
677+ sym:: all => mis
678+ . iter ( )
679+ . all ( |mi| eval_condition ( mi . meta_item ( ) . unwrap ( ) , sess , features , eval ) ) ,
643680 sym:: not => {
644681 if mis. len ( ) != 1 {
645682 struct_span_err ! (
@@ -652,7 +689,7 @@ pub fn eval_condition(
652689 return false ;
653690 }
654691
655- !eval_condition ( mis[ 0 ] . meta_item ( ) . unwrap ( ) , sess, eval)
692+ !eval_condition ( mis[ 0 ] . meta_item ( ) . unwrap ( ) , sess, features , eval)
656693 }
657694 _ => {
658695 struct_span_err ! (
0 commit comments