@@ -918,20 +918,27 @@ struct Context<'a> {
918918}
919919
920920macro_rules! gate_feature_fn {
921- ( $cx: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr) => { {
922- let ( cx, has_feature, span, name, explain) = ( $cx, $has_feature, $span, $name, $explain) ;
921+ ( $cx: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr, $level: expr) => { {
922+ let ( cx, has_feature, span,
923+ name, explain, level) = ( $cx, $has_feature, $span, $name, $explain, $level) ;
923924 let has_feature: bool = has_feature( & $cx. features) ;
924925 debug!( "gate_feature(feature = {:?}, span = {:?}); has? {}" , name, span, has_feature) ;
925926 if !has_feature && !span. allows_unstable( ) {
926- emit_feature_err( cx. parse_sess, name, span, GateIssue :: Language , explain) ;
927+ leveled_feature_err( cx. parse_sess, name, span, GateIssue :: Language , explain, level)
928+ . emit( ) ;
927929 }
928930 } }
929931}
930932
931933macro_rules! gate_feature {
932934 ( $cx: expr, $feature: ident, $span: expr, $explain: expr) => {
933- gate_feature_fn!( $cx, |x: & Features | x. $feature, $span, stringify!( $feature) , $explain)
934- }
935+ gate_feature_fn!( $cx, |x: & Features | x. $feature, $span,
936+ stringify!( $feature) , $explain, GateStrength :: Hard )
937+ } ;
938+ ( $cx: expr, $feature: ident, $span: expr, $explain: expr, $level: expr) => {
939+ gate_feature_fn!( $cx, |x: & Features | x. $feature, $span,
940+ stringify!( $feature) , $explain, $level)
941+ } ;
935942}
936943
937944impl < ' a > Context < ' a > {
@@ -941,7 +948,7 @@ impl<'a> Context<'a> {
941948 for & ( n, ty, ref gateage) in BUILTIN_ATTRIBUTES {
942949 if name == n {
943950 if let Gated ( _, name, desc, ref has_feature) = * gateage {
944- gate_feature_fn ! ( self , has_feature, attr. span, name, desc) ;
951+ gate_feature_fn ! ( self , has_feature, attr. span, name, desc, GateStrength :: Hard ) ;
945952 }
946953 debug ! ( "check_attribute: {:?} is builtin, {:?}, {:?}" , attr. path, ty, gateage) ;
947954 return ;
@@ -1011,24 +1018,42 @@ pub enum GateIssue {
10111018 Library ( Option < u32 > )
10121019}
10131020
1021+ #[ derive( Debug , Copy , Clone , PartialEq , Eq ) ]
1022+ pub enum GateStrength {
1023+ /// A hard error. (Most feature gates should use this.)
1024+ Hard ,
1025+ /// Only a warning. (Use this only as backwards-compatibility demands.)
1026+ Soft ,
1027+ }
1028+
10141029pub fn emit_feature_err ( sess : & ParseSess , feature : & str , span : Span , issue : GateIssue ,
10151030 explain : & str ) {
10161031 feature_err ( sess, feature, span, issue, explain) . emit ( ) ;
10171032}
10181033
10191034pub fn feature_err < ' a > ( sess : & ' a ParseSess , feature : & str , span : Span , issue : GateIssue ,
10201035 explain : & str ) -> DiagnosticBuilder < ' a > {
1036+ leveled_feature_err ( sess, feature, span, issue, explain, GateStrength :: Hard )
1037+ }
1038+
1039+ fn leveled_feature_err < ' a > ( sess : & ' a ParseSess , feature : & str , span : Span , issue : GateIssue ,
1040+ explain : & str , level : GateStrength ) -> DiagnosticBuilder < ' a > {
10211041 let diag = & sess. span_diagnostic ;
10221042
10231043 let issue = match issue {
10241044 GateIssue :: Language => find_lang_feature_issue ( feature) ,
10251045 GateIssue :: Library ( lib) => lib,
10261046 } ;
10271047
1028- let mut err = if let Some ( n) = issue {
1029- diag . struct_span_err ( span , & format ! ( "{} (see issue #{})" , explain, n) )
1048+ let explanation = if let Some ( n) = issue {
1049+ format ! ( "{} (see issue #{})" , explain, n)
10301050 } else {
1031- diag. struct_span_err ( span, explain)
1051+ explain. to_owned ( )
1052+ } ;
1053+
1054+ let mut err = match level {
1055+ GateStrength :: Hard => diag. struct_span_err ( span, & explanation) ,
1056+ GateStrength :: Soft => diag. struct_span_warn ( span, & explanation) ,
10321057 } ;
10331058
10341059 // #23973: do not suggest `#![feature(...)]` if we are in beta/stable
@@ -1038,7 +1063,15 @@ pub fn feature_err<'a>(sess: &'a ParseSess, feature: &str, span: Span, issue: Ga
10381063 feature) ) ;
10391064 }
10401065
1066+ // If we're on stable and only emitting a "soft" warning, add a note to
1067+ // clarify that the feature isn't "on" (rather than being on but
1068+ // warning-worthy).
1069+ if !sess. unstable_features . is_nightly_build ( ) && level == GateStrength :: Soft {
1070+ err. help ( "a nightly build of the compiler is required to enable this feature" ) ;
1071+ }
1072+
10411073 err
1074+
10421075}
10431076
10441077const EXPLAIN_BOX_SYNTAX : & ' static str =
@@ -1095,6 +1128,12 @@ macro_rules! gate_feature_post {
10951128 if !span. allows_unstable( ) {
10961129 gate_feature!( cx. context, $feature, span, $explain)
10971130 }
1131+ } } ;
1132+ ( $cx: expr, $feature: ident, $span: expr, $explain: expr, $level: expr) => { {
1133+ let ( cx, span) = ( $cx, $span) ;
1134+ if !span. allows_unstable( ) {
1135+ gate_feature!( cx. context, $feature, span, $explain, $level)
1136+ }
10981137 } }
10991138}
11001139
@@ -1239,7 +1278,8 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
12391278 }
12401279 if attr:: contains_name ( & i. attrs [ ..] , "must_use" ) {
12411280 gate_feature_post ! ( & self , fn_must_use, i. span,
1242- "`#[must_use]` on functions is experimental" ) ;
1281+ "`#[must_use]` on functions is experimental" ,
1282+ GateStrength :: Soft ) ;
12431283 }
12441284 }
12451285
0 commit comments