@@ -112,8 +112,8 @@ macro_rules! declare_features {
112
112
// was set. This is most important for knowing when a particular feature became
113
113
// stable (active).
114
114
//
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.
117
117
118
118
declare_features ! (
119
119
( active, asm, "1.0.0" , Some ( 29722 ) ) ,
@@ -372,6 +372,9 @@ declare_features! (
372
372
373
373
// #[doc(cfg(...))]
374
374
( 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 ) ) ,
375
378
) ;
376
379
377
380
declare_features ! (
@@ -915,20 +918,27 @@ struct Context<'a> {
915
918
}
916
919
917
920
macro_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) ;
920
924
let has_feature: bool = has_feature( & $cx. features) ;
921
925
debug!( "gate_feature(feature = {:?}, span = {:?}); has? {}" , name, span, has_feature) ;
922
926
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( ) ;
924
929
}
925
930
} }
926
931
}
927
932
928
933
macro_rules! gate_feature {
929
934
( $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
+ } ;
932
942
}
933
943
934
944
impl < ' a > Context < ' a > {
@@ -938,7 +948,7 @@ impl<'a> Context<'a> {
938
948
for & ( n, ty, ref gateage) in BUILTIN_ATTRIBUTES {
939
949
if name == n {
940
950
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 ) ;
942
952
}
943
953
debug ! ( "check_attribute: {:?} is builtin, {:?}, {:?}" , attr. path, ty, gateage) ;
944
954
return ;
@@ -1008,24 +1018,42 @@ pub enum GateIssue {
1008
1018
Library ( Option < u32 > )
1009
1019
}
1010
1020
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
+
1011
1029
pub fn emit_feature_err ( sess : & ParseSess , feature : & str , span : Span , issue : GateIssue ,
1012
1030
explain : & str ) {
1013
1031
feature_err ( sess, feature, span, issue, explain) . emit ( ) ;
1014
1032
}
1015
1033
1016
1034
pub 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 > {
1018
1041
let diag = & sess. span_diagnostic ;
1019
1042
1020
1043
let issue = match issue {
1021
1044
GateIssue :: Language => find_lang_feature_issue ( feature) ,
1022
1045
GateIssue :: Library ( lib) => lib,
1023
1046
} ;
1024
1047
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)
1027
1050
} 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) ,
1029
1057
} ;
1030
1058
1031
1059
// #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
1035
1063
feature) ) ;
1036
1064
}
1037
1065
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
+
1038
1073
err
1074
+
1039
1075
}
1040
1076
1041
1077
const EXPLAIN_BOX_SYNTAX : & ' static str =
@@ -1092,6 +1128,12 @@ macro_rules! gate_feature_post {
1092
1128
if !span. allows_unstable( ) {
1093
1129
gate_feature!( cx. context, $feature, span, $explain)
1094
1130
}
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
+ }
1095
1137
} }
1096
1138
}
1097
1139
@@ -1234,6 +1276,11 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
1234
1276
function may change over time, for now \
1235
1277
a top-level `fn main()` is required") ;
1236
1278
}
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
+ }
1237
1284
}
1238
1285
1239
1286
ast:: ItemKind :: Struct ( ..) => {
@@ -1271,7 +1318,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
1271
1318
and possibly buggy") ;
1272
1319
}
1273
1320
1274
- ast:: ItemKind :: Impl ( _, polarity, defaultness, _, _, _, _ ) => {
1321
+ ast:: ItemKind :: Impl ( _, polarity, defaultness, _, _, _, ref impl_items ) => {
1275
1322
if polarity == ast:: ImplPolarity :: Negative {
1276
1323
gate_feature_post ! ( & self , optin_builtin_traits,
1277
1324
i. span,
@@ -1284,6 +1331,16 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
1284
1331
i. span,
1285
1332
"specialization is unstable" ) ;
1286
1333
}
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
+ }
1287
1344
}
1288
1345
1289
1346
ast:: ItemKind :: MacroDef ( ast:: MacroDef { legacy : false , .. } ) => {
0 commit comments