2
2
3
3
use super :: { find_by_name, mark_used} ;
4
4
5
- use rustc_ast:: ast:: { self , Attribute , MetaItem , MetaItemKind , NestedMetaItem } ;
5
+ use rustc_ast:: ast:: { self , Attribute , Lit , LitKind , MetaItem , MetaItemKind , NestedMetaItem } ;
6
6
use rustc_ast_pretty:: pprust;
7
7
use rustc_errors:: { struct_span_err, Applicability , Handler } ;
8
8
use rustc_feature:: { find_gated_cfg, is_builtin_attr_name, Features , GatedCfg } ;
@@ -11,6 +11,7 @@ use rustc_session::parse::{feature_err, ParseSess};
11
11
use rustc_span:: hygiene:: Transparency ;
12
12
use rustc_span:: { symbol:: sym, symbol:: Symbol , Span } ;
13
13
use std:: num:: NonZeroU32 ;
14
+ use version_check:: Version ;
14
15
15
16
pub fn is_builtin_attr ( attr : & Attribute ) -> bool {
16
17
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> {
568
569
569
570
/// Tests if a cfg-pattern matches the cfg set
570
571
pub 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) ;
576
574
let error = |span, msg| {
577
575
sess. span_diagnostic . span_err ( span, msg) ;
578
576
true
@@ -603,6 +601,13 @@ pub fn cfg_matches(cfg: &ast::MetaItem, sess: &ParseSess, features: Option<&Feat
603
601
} )
604
602
}
605
603
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
+
606
611
fn gate_cfg ( gated_cfg : & GatedCfg , cfg_span : Span , sess : & ParseSess , features : & Features ) {
607
612
let ( cfg, feature, has_feature) = gated_cfg;
608
613
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
616
621
pub fn eval_condition (
617
622
cfg : & ast:: MetaItem ,
618
623
sess : & ParseSess ,
624
+ features : Option < & Features > ,
619
625
eval : & mut impl FnMut ( & ast:: MetaItem ) -> bool ,
620
626
) -> bool {
621
627
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
+ }
622
659
ast:: MetaItemKind :: List ( ref mis) => {
623
660
for mi in mis. iter ( ) {
624
661
if !mi. is_meta_item ( ) {
@@ -634,12 +671,12 @@ pub fn eval_condition(
634
671
// The unwraps below may look dangerous, but we've already asserted
635
672
// that they won't fail with the loop above.
636
673
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 ) ) ,
643
680
sym:: not => {
644
681
if mis. len ( ) != 1 {
645
682
struct_span_err ! (
@@ -652,7 +689,7 @@ pub fn eval_condition(
652
689
return false ;
653
690
}
654
691
655
- !eval_condition ( mis[ 0 ] . meta_item ( ) . unwrap ( ) , sess, eval)
692
+ !eval_condition ( mis[ 0 ] . meta_item ( ) . unwrap ( ) , sess, features , eval)
656
693
}
657
694
_ => {
658
695
struct_span_err ! (
0 commit comments