@@ -112,8 +112,8 @@ macro_rules! declare_features {
112112// was set. This is most important for knowing when a particular feature became
113113// stable (active).
114114//
115- // NB: The featureck.py script parses this information directly out of the source
116- // so take care when modifying it.
115+ // NB: tools/tidy/src/features.rs parses this information directly out of the
116+ // source, so take care when modifying it.
117117
118118declare_features ! (
119119 ( active, asm, "1.0.0" , Some ( 29722 ) ) ,
@@ -372,6 +372,9 @@ declare_features! (
372372
373373 // #[doc(cfg(...))]
374374 ( active, doc_cfg, "1.21.0" , Some ( 43781 ) ) ,
375+
376+ // allow `#[must_use]` on functions (RFC 1940)
377+ ( active, fn_must_use, "1.21.0" , Some ( 43302 ) ) ,
375378) ;
376379
377380declare_features ! (
@@ -915,20 +918,27 @@ struct Context<'a> {
915918}
916919
917920macro_rules! gate_feature_fn {
918- ( $cx: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr) => { {
919- 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) ;
920924 let has_feature: bool = has_feature( & $cx. features) ;
921925 debug!( "gate_feature(feature = {:?}, span = {:?}); has? {}" , name, span, has_feature) ;
922926 if !has_feature && !span. allows_unstable( ) {
923- 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( ) ;
924929 }
925930 } }
926931}
927932
928933macro_rules! gate_feature {
929934 ( $cx: expr, $feature: ident, $span: expr, $explain: expr) => {
930- gate_feature_fn!( $cx, |x: & Features | x. $feature, $span, stringify!( $feature) , $explain)
931- }
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+ } ;
932942}
933943
934944impl < ' a > Context < ' a > {
@@ -938,7 +948,7 @@ impl<'a> Context<'a> {
938948 for & ( n, ty, ref gateage) in BUILTIN_ATTRIBUTES {
939949 if name == n {
940950 if let Gated ( _, name, desc, ref has_feature) = * gateage {
941- gate_feature_fn ! ( self , has_feature, attr. span, name, desc) ;
951+ gate_feature_fn ! ( self , has_feature, attr. span, name, desc, GateStrength :: Hard ) ;
942952 }
943953 debug ! ( "check_attribute: {:?} is builtin, {:?}, {:?}" , attr. path, ty, gateage) ;
944954 return ;
@@ -1008,24 +1018,42 @@ pub enum GateIssue {
10081018 Library ( Option < u32 > )
10091019}
10101020
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+
10111029pub fn emit_feature_err ( sess : & ParseSess , feature : & str , span : Span , issue : GateIssue ,
10121030 explain : & str ) {
10131031 feature_err ( sess, feature, span, issue, explain) . emit ( ) ;
10141032}
10151033
10161034pub fn feature_err < ' a > ( sess : & ' a ParseSess , feature : & str , span : Span , issue : GateIssue ,
1017- explain : & str ) -> DiagnosticBuilder < ' a > {
1035+ 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 > {
10181041 let diag = & sess. span_diagnostic ;
10191042
10201043 let issue = match issue {
10211044 GateIssue :: Language => find_lang_feature_issue ( feature) ,
10221045 GateIssue :: Library ( lib) => lib,
10231046 } ;
10241047
1025- let mut err = if let Some ( n) = issue {
1026- diag . struct_span_err ( span , & format ! ( "{} (see issue #{})" , explain, n) )
1048+ let explanation = if let Some ( n) = issue {
1049+ format ! ( "{} (see issue #{})" , explain, n)
10271050 } else {
1028- 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) ,
10291057 } ;
10301058
10311059 // #23973: do not suggest `#![feature(...)]` if we are in beta/stable
@@ -1035,7 +1063,15 @@ pub fn feature_err<'a>(sess: &'a ParseSess, feature: &str, span: Span, issue: Ga
10351063 feature) ) ;
10361064 }
10371065
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+
10381073 err
1074+
10391075}
10401076
10411077const EXPLAIN_BOX_SYNTAX : & ' static str =
@@ -1092,6 +1128,12 @@ macro_rules! gate_feature_post {
10921128 if !span. allows_unstable( ) {
10931129 gate_feature!( cx. context, $feature, span, $explain)
10941130 }
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+ }
10951137 } }
10961138}
10971139
@@ -1234,6 +1276,11 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
12341276 function may change over time, for now \
12351277 a top-level `fn main()` is required") ;
12361278 }
1279+ if attr:: contains_name ( & i. attrs [ ..] , "must_use" ) {
1280+ gate_feature_post ! ( & self , fn_must_use, i. span,
1281+ "`#[must_use]` on functions is experimental" ,
1282+ GateStrength :: Soft ) ;
1283+ }
12371284 }
12381285
12391286 ast:: ItemKind :: Struct ( ..) => {
@@ -1271,7 +1318,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
12711318 and possibly buggy") ;
12721319 }
12731320
1274- ast:: ItemKind :: Impl ( _, polarity, defaultness, _, _, _, _ ) => {
1321+ ast:: ItemKind :: Impl ( _, polarity, defaultness, _, _, _, ref impl_items ) => {
12751322 if polarity == ast:: ImplPolarity :: Negative {
12761323 gate_feature_post ! ( & self , optin_builtin_traits,
12771324 i. span,
@@ -1284,6 +1331,16 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
12841331 i. span,
12851332 "specialization is unstable" ) ;
12861333 }
1334+
1335+ for impl_item in impl_items {
1336+ if let ast:: ImplItemKind :: Method ( ..) = impl_item. node {
1337+ if attr:: contains_name ( & impl_item. attrs [ ..] , "must_use" ) {
1338+ gate_feature_post ! ( & self , fn_must_use, impl_item. span,
1339+ "`#[must_use]` on methods is experimental" ,
1340+ GateStrength :: Soft ) ;
1341+ }
1342+ }
1343+ }
12871344 }
12881345
12891346 ast:: ItemKind :: MacroDef ( ast:: MacroDef { legacy : false , .. } ) => {
0 commit comments