From ef1de519ff286a21e220d5839a6a5d468d296773 Mon Sep 17 00:00:00 2001 From: Leo Testard Date: Mon, 4 Apr 2016 17:08:41 +0200 Subject: [PATCH] Generate the features structure and arrays with new macros. This is more readable, safer, and allows for a much more efficient parsing. --- src/libsyntax/ext/expand.rs | 14 +- src/libsyntax/feature_gate.rs | 601 +++++++++++----------------------- 2 files changed, 195 insertions(+), 420 deletions(-) diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index cd7b0fcfb00..bc8d5cd7703 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -1345,14 +1345,14 @@ impl<'feat> ExpansionConfig<'feat> { } feature_tests! { - fn enable_quotes = allow_quote, - fn enable_asm = allow_asm, - fn enable_log_syntax = allow_log_syntax, - fn enable_concat_idents = allow_concat_idents, - fn enable_trace_macros = allow_trace_macros, + fn enable_quotes = quote, + fn enable_asm = asm, + fn enable_log_syntax = log_syntax, + fn enable_concat_idents = concat_idents, + fn enable_trace_macros = trace_macros, fn enable_allow_internal_unstable = allow_internal_unstable, - fn enable_custom_derive = allow_custom_derive, - fn enable_pushpop_unsafe = allow_pushpop_unsafe, + fn enable_custom_derive = custom_derive, + fn enable_pushpop_unsafe = pushpop_unsafe, } } diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 7b0a0f39b24..e281e30dbc2 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -22,7 +22,6 @@ //! gate usage is added, *do not remove it again* even once the feature //! becomes stable. -use self::Status::*; use self::AttributeType::*; use self::AttributeGate::*; @@ -40,16 +39,57 @@ use parse::token::InternedString; use std::ascii::AsciiExt; use std::cmp; -enum Status { - /// Represents an active feature that is currently being implemented or - /// currently being considered for addition/removal. - Active, +macro_rules! setter { + ($field: ident) => {{ + fn f(features: &mut Features) -> &mut bool { + &mut features.$field + } + f as fn(&mut Features) -> &mut bool + }} +} - /// Represents a feature which has since been removed (it was once Active) - Removed, +macro_rules! declare_features { + ($((active, $feature: ident, $ver: expr, $issue: expr)),+) => { + /// Represents active features that are currently being implemented or + /// currently being considered for addition/removal. + const ACTIVE_FEATURES: &'static [(&'static str, &'static str, + Option, fn(&mut Features) -> &mut bool)] = &[ + $((stringify!($feature), $ver, $issue, setter!($feature))),+ + ]; - /// This language feature has since been Accepted (it was once Active) - Accepted, + /// A set of features to be used by later passes. + pub struct Features { + /// spans of #![feature] attrs for stable language features. for error reporting + pub declared_stable_lang_features: Vec, + /// #![feature] attrs for non-language (library) features + pub declared_lib_features: Vec<(InternedString, Span)>, + $(pub $feature: bool),+ + } + + impl Features { + pub fn new() -> Features { + Features { + declared_stable_lang_features: Vec::new(), + declared_lib_features: Vec::new(), + $($feature: false),+ + } + } + } + }; + + ($((removed, $feature: ident, $ver: expr, $issue: expr)),+) => { + /// Represents features which has since been removed (it was once Active) + const REMOVED_FEATURES: &'static [(&'static str, &'static str, Option)] = &[ + $((stringify!($feature), $ver, $issue)),+ + ]; + }; + + ($((accepted, $feature: ident, $ver: expr, $issue: expr)),+) => { + /// Those language feature has since been Accepted (it was once Active) + const ACCEPTED_FEATURES: &'static [(&'static str, &'static str, Option)] = &[ + $((stringify!($feature), $ver, $issue)),+ + ]; + } } // If you change this list without updating src/doc/reference.md, @cmr will be sad @@ -57,120 +97,88 @@ enum Status { // The version numbers here correspond to the version in which the current status // was set. This is most important for knowing when a particular feature became // stable (active). -// NB: The tidy tool parses this information directly out of the source so take -// care when modifying it. -const KNOWN_FEATURES: &'static [(&'static str, &'static str, Option, Status)] = &[ - ("globs", "1.0.0", None, Accepted), - ("macro_rules", "1.0.0", None, Accepted), - ("struct_variant", "1.0.0", None, Accepted), - ("asm", "1.0.0", Some(29722), Active), - ("managed_boxes", "1.0.0", None, Removed), - ("non_ascii_idents", "1.0.0", Some(28979), Active), - ("thread_local", "1.0.0", Some(29594), Active), - ("link_args", "1.0.0", Some(29596), Active), - ("plugin_registrar", "1.0.0", Some(29597), Active), - ("log_syntax", "1.0.0", Some(29598), Active), - ("trace_macros", "1.0.0", Some(29598), Active), - ("concat_idents", "1.0.0", Some(29599), Active), +// NB: The featureck.py script parses this information directly out of the source +// so take care when modifying it. + +declare_features! ( + (active, asm, "1.0.0", Some(29722)), + (active, concat_idents, "1.0.0", Some(29599)), + (active, link_args, "1.0.0", Some(29596)), + (active, log_syntax, "1.0.0", Some(29598)), + (active, non_ascii_idents, "1.0.0", Some(28979)), + (active, plugin_registrar, "1.0.0", Some(29597)), + (active, thread_local, "1.0.0", Some(29594)), + (active, trace_macros, "1.0.0", Some(29598)), // rustc internal, for now: - ("intrinsics", "1.0.0", None, Active), - ("lang_items", "1.0.0", None, Active), + (active, intrinsics, "1.0.0", None), + (active, lang_items, "1.0.0", None), - ("simd", "1.0.0", Some(27731), Active), - ("default_type_params", "1.0.0", None, Accepted), - ("quote", "1.0.0", Some(29601), Active), - ("link_llvm_intrinsics", "1.0.0", Some(29602), Active), - ("linkage", "1.0.0", Some(29603), Active), - ("struct_inherit", "1.0.0", None, Removed), + (active, link_llvm_intrinsics, "1.0.0", Some(29602)), + (active, linkage, "1.0.0", Some(29603)), + (active, quote, "1.0.0", Some(29601)), + (active, simd, "1.0.0", Some(27731)), - ("quad_precision_float", "1.0.0", None, Removed), // rustc internal - ("rustc_diagnostic_macros", "1.0.0", None, Active), - ("unboxed_closures", "1.0.0", Some(29625), Active), - ("reflect", "1.0.0", Some(27749), Active), - ("import_shadowing", "1.0.0", None, Removed), - ("advanced_slice_patterns", "1.0.0", Some(23121), Active), - ("tuple_indexing", "1.0.0", None, Accepted), - ("associated_types", "1.0.0", None, Accepted), - ("visible_private_types", "1.0.0", None, Removed), - ("slicing_syntax", "1.0.0", None, Accepted), - ("box_syntax", "1.0.0", Some(27779), Active), - ("placement_in_syntax", "1.0.0", Some(27779), Active), + (active, rustc_diagnostic_macros, "1.0.0", None), + (active, advanced_slice_patterns, "1.0.0", Some(23121)), + (active, box_syntax, "1.0.0", Some(27779)), + (active, placement_in_syntax, "1.0.0", Some(27779)), + (active, reflect, "1.0.0", Some(27749)), + (active, unboxed_closures, "1.0.0", Some(29625)), // rustc internal. - ("pushpop_unsafe", "1.2.0", None, Active), + (active, pushpop_unsafe, "1.2.0", None), - ("on_unimplemented", "1.0.0", Some(29628), Active), - ("simd_ffi", "1.0.0", Some(27731), Active), - ("allocator", "1.0.0", Some(27389), Active), - ("needs_allocator", "1.4.0", Some(27389), Active), - ("linked_from", "1.3.0", Some(29629), Active), - - ("if_let", "1.0.0", None, Accepted), - ("while_let", "1.0.0", None, Accepted), - - ("plugin", "1.0.0", Some(29597), Active), - ("start", "1.0.0", Some(29633), Active), - ("main", "1.0.0", Some(29634), Active), - - ("fundamental", "1.0.0", Some(29635), Active), - - // A temporary feature gate used to enable parser extensions needed - // to bootstrap fix for #5723. - ("issue_5723_bootstrap", "1.0.0", None, Accepted), - - ("structural_match", "1.8.0", Some(31434), Active), - - // A way to temporarily opt out of opt in copy. This will *never* be accepted. - ("opt_out_copy", "1.0.0", None, Removed), + (active, allocator, "1.0.0", Some(27389)), + (active, fundamental, "1.0.0", Some(29635)), + (active, linked_from, "1.3.0", Some(29629)), + (active, main, "1.0.0", Some(29634)), + (active, needs_allocator, "1.4.0", Some(27389)), + (active, on_unimplemented, "1.0.0", Some(29628)), + (active, plugin, "1.0.0", Some(29597)), + (active, simd_ffi, "1.0.0", Some(27731)), + (active, start, "1.0.0", Some(29633)), + (active, structural_match, "1.8.0", Some(31434)), // OIBIT specific features - ("optin_builtin_traits", "1.0.0", Some(13231), Active), + (active, optin_builtin_traits, "1.0.0", Some(13231)), // macro reexport needs more discussion and stabilization - ("macro_reexport", "1.0.0", Some(29638), Active), - - // These are used to test this portion of the compiler, they don't actually - // mean anything - ("test_accepted_feature", "1.0.0", None, Accepted), - ("test_removed_feature", "1.0.0", None, Removed), + (active, macro_reexport, "1.0.0", Some(29638)), // Allows use of #[staged_api] // rustc internal - ("staged_api", "1.0.0", None, Active), + (active, staged_api, "1.0.0", None), // Allows using items which are missing stability attributes // rustc internal - ("unmarked_api", "1.0.0", None, Active), - - // Allows using #![no_std] - ("no_std", "1.0.0", None, Accepted), + (active, unmarked_api, "1.0.0", None), // Allows using #![no_core] - ("no_core", "1.3.0", Some(29639), Active), + (active, no_core, "1.3.0", Some(29639)), // Allows using `box` in patterns; RFC 469 - ("box_patterns", "1.0.0", Some(29641), Active), + (active, box_patterns, "1.0.0", Some(29641)), // Allows using the unsafe_no_drop_flag attribute (unlikely to // switch to Accepted; see RFC 320) - ("unsafe_no_drop_flag", "1.0.0", None, Active), + (active, unsafe_no_drop_flag, "1.0.0", None), // Allows using the unsafe_destructor_blind_to_params attribute; // RFC 1238 - ("dropck_parametricity", "1.3.0", Some(28498), Active), + (active, dropck_parametricity, "1.3.0", Some(28498)), // Allows the use of custom attributes; RFC 572 - ("custom_attribute", "1.0.0", Some(29642), Active), + (active, custom_attribute, "1.0.0", Some(29642)), // Allows the use of #[derive(Anything)] as sugar for // #[derive_Anything]. - ("custom_derive", "1.0.0", Some(29644), Active), + (active, custom_derive, "1.0.0", Some(29644)), // Allows the use of rustc_* attributes; RFC 572 - ("rustc_attrs", "1.0.0", Some(29642), Active), + (active, rustc_attrs, "1.0.0", Some(29642)), // Allows the use of #[allow_internal_unstable]. This is an // attribute on macro_rules! and can't use the attribute handling @@ -178,100 +186,128 @@ const KNOWN_FEATURES: &'static [(&'static str, &'static str, Option, Status // macros disappear). // // rustc internal - ("allow_internal_unstable", "1.0.0", None, Active), + (active, allow_internal_unstable, "1.0.0", None), // #23121. Array patterns have some hazards yet. - ("slice_patterns", "1.0.0", Some(23121), Active), - - // Allows use of unary negate on unsigned integers, e.g. -e for e: u8 - ("negate_unsigned", "1.0.0", Some(29645), Removed), + (active, slice_patterns, "1.0.0", Some(23121)), // Allows the definition of associated constants in `trait` or `impl` // blocks. - ("associated_consts", "1.0.0", Some(29646), Active), + (active, associated_consts, "1.0.0", Some(29646)), // Allows the definition of `const fn` functions. - ("const_fn", "1.2.0", Some(24111), Active), + (active, const_fn, "1.2.0", Some(24111)), // Allows indexing into constant arrays. - ("const_indexing", "1.4.0", Some(29947), Active), + (active, const_indexing, "1.4.0", Some(29947)), // Allows using #[prelude_import] on glob `use` items. // // rustc internal - ("prelude_import", "1.2.0", None, Active), + (active, prelude_import, "1.2.0", None), // Allows the definition recursive static items. - ("static_recursion", "1.3.0", Some(29719), Active), + (active, static_recursion, "1.3.0", Some(29719)), // Allows default type parameters to influence type inference. - ("default_type_parameter_fallback", "1.3.0", Some(27336), Active), + (active, default_type_parameter_fallback, "1.3.0", Some(27336)), // Allows associated type defaults - ("associated_type_defaults", "1.2.0", Some(29661), Active), + (active, associated_type_defaults, "1.2.0", Some(29661)), // Allows macros to appear in the type position. - ("type_macros", "1.3.0", Some(27245), Active), + (active, type_macros, "1.3.0", Some(27245)), // allow `repr(simd)`, and importing the various simd intrinsics - ("repr_simd", "1.4.0", Some(27731), Active), + (active, repr_simd, "1.4.0", Some(27731)), // Allows cfg(target_feature = "..."). - ("cfg_target_feature", "1.4.0", Some(29717), Active), + (active, cfg_target_feature, "1.4.0", Some(29717)), // allow `extern "platform-intrinsic" { ... }` - ("platform_intrinsics", "1.4.0", Some(27731), Active), + (active, platform_intrinsics, "1.4.0", Some(27731)), // allow `#[unwind]` // rust runtime internal - ("unwind_attributes", "1.4.0", None, Active), + (active, unwind_attributes, "1.4.0", None), // allow the use of `#[naked]` on functions. - ("naked_functions", "1.9.0", Some(32408), Active), - - // allow empty structs and enum variants with braces - ("braced_empty_structs", "1.8.0", Some(29720), Accepted), - - // allow overloading augmented assignment operations like `a += b` - ("augmented_assignments", "1.8.0", Some(28235), Accepted), + (active, naked_functions, "1.9.0", Some(32408)), // allow `#[no_debug]` - ("no_debug", "1.5.0", Some(29721), Active), + (active, no_debug, "1.5.0", Some(29721)), // allow `#[omit_gdb_pretty_printer_section]` // rustc internal. - ("omit_gdb_pretty_printer_section", "1.5.0", None, Active), + (active, omit_gdb_pretty_printer_section, "1.5.0", None), // Allows cfg(target_vendor = "..."). - ("cfg_target_vendor", "1.5.0", Some(29718), Active), + (active, cfg_target_vendor, "1.5.0", Some(29718)), // Allow attributes on expressions and non-item statements - ("stmt_expr_attributes", "1.6.0", Some(15701), Active), - - // Allows `#[deprecated]` attribute - ("deprecated", "1.9.0", Some(29935), Accepted), + (active, stmt_expr_attributes, "1.6.0", Some(15701)), // allow using type ascription in expressions - ("type_ascription", "1.6.0", Some(23416), Active), + (active, type_ascription, "1.6.0", Some(23416)), // Allows cfg(target_thread_local) - ("cfg_target_thread_local", "1.7.0", Some(29594), Active), + (active, cfg_target_thread_local, "1.7.0", Some(29594)), // rustc internal - ("abi_vectorcall", "1.7.0", None, Active), + (active, abi_vectorcall, "1.7.0", None), // a...b and ...b - ("inclusive_range_syntax", "1.7.0", Some(28237), Active), + (active, inclusive_range_syntax, "1.7.0", Some(28237)), // `expr?` - ("question_mark", "1.9.0", Some(31436), Active), + (active, question_mark, "1.9.0", Some(31436)), // impl specialization (RFC 1210) - ("specialization", "1.7.0", Some(31844), Active), + (active, specialization, "1.7.0", Some(31844)), // pub(restricted) visibilities (RFC 1422) - ("pub_restricted", "1.9.0", Some(32409), Active), -]; + (active, pub_restricted, "1.9.0", Some(32409)) +); + +declare_features! ( + (removed, import_shadowing, "1.0.0", None), + (removed, managed_boxes, "1.0.0", None), + // Allows use of unary negate on unsigned integers, e.g. -e for e: u8 + (removed, negate_unsigned, "1.0.0", Some(29645)), + // A way to temporarily opt out of opt in copy. This will *never* be accepted. + (removed, opt_out_copy, "1.0.0", None), + (removed, quad_precision_float, "1.0.0", None), + (removed, struct_inherit, "1.0.0", None), + (removed, test_removed_feature, "1.0.0", None), + (removed, visible_private_types, "1.0.0", None) +); + +declare_features! ( + (accepted, associated_types, "1.0.0", None), + // allow overloading augmented assignment operations like `a += b` + (accepted, augmented_assignments, "1.8.0", Some(28235)), + // allow empty structs and enum variants with braces + (accepted, braced_empty_structs, "1.8.0", Some(29720)), + (accepted, default_type_params, "1.0.0", None), + (accepted, globs, "1.0.0", None), + (accepted, if_let, "1.0.0", None), + // A temporary feature gate used to enable parser extensions needed + // to bootstrap fix for #5723. + (accepted, issue_5723_bootstrap, "1.0.0", None), + (accepted, macro_rules, "1.0.0", None), + // Allows using #![no_std] + (accepted, no_std, "1.0.0", None), + (accepted, slicing_syntax, "1.0.0", None), + (accepted, struct_variant, "1.0.0", None), + // These are used to test this portion of the compiler, they don't actually + // mean anything + (accepted, test_accepted_feature, "1.0.0", None), + (accepted, tuple_indexing, "1.0.0", None), + (accepted, while_let, "1.0.0", None), + // Allows `#[deprecated]` attribute + (accepted, deprecated, "1.9.0", Some(29935)) +); + // (changing above list without updating src/doc/reference.md makes @cmr sad) #[derive(PartialEq, Copy, Clone, Debug)] @@ -471,7 +507,7 @@ pub const KNOWN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeGat ("naked", Whitelisted, Gated("naked_functions", "the `#[naked]` attribute \ is an experimental feature", - cfg_fn!(naked))), + cfg_fn!(naked_functions))), ("export_name", Whitelisted, Ungated), ("inline", Whitelisted, Ungated), ("link", Whitelisted, Ungated), @@ -618,177 +654,6 @@ impl GatedCfg { } } -/// A set of features to be used by later passes. -pub struct Features { - pub unboxed_closures: bool, - pub rustc_diagnostic_macros: bool, - pub allow_quote: bool, - pub allow_asm: bool, - pub allow_log_syntax: bool, - pub allow_concat_idents: bool, - pub allow_trace_macros: bool, - pub allow_internal_unstable: bool, - pub allow_custom_derive: bool, - pub allow_placement_in: bool, - pub allow_box: bool, - pub allow_pushpop_unsafe: bool, - pub allow_inclusive_range: bool, - pub simd_ffi: bool, - pub unmarked_api: bool, - /// spans of #![feature] attrs for stable language features. for error reporting - pub declared_stable_lang_features: Vec, - /// #![feature] attrs for non-language (library) features - pub declared_lib_features: Vec<(InternedString, Span)>, - pub const_fn: bool, - pub const_indexing: bool, - pub static_recursion: bool, - pub default_type_parameter_fallback: bool, - pub rustc_attrs: bool, - pub type_macros: bool, - pub cfg_target_feature: bool, - pub cfg_target_vendor: bool, - pub cfg_target_thread_local: bool, - pub staged_api: bool, - pub stmt_expr_attributes: bool, - pub deprecated: bool, - pub question_mark: bool, - pub specialization: bool, - pub pub_restricted: bool, - pub structural_match: bool, - pub plugin: bool, - pub lang_items: bool, - pub linkage: bool, - pub thread_local: bool, - pub on_unimplemented: bool, - pub allocator: bool, - pub needs_allocator: bool, - pub fundamental: bool, - pub linked_from: bool, - pub naked: bool, - pub no_debug: bool, - pub omit_gdb_pretty_printer_section: bool, - pub dropck_parametricity: bool, - pub unwind_attributes: bool, - pub prelude_import: bool, - pub reflect: bool, - pub no_core: bool, - pub unsafe_no_drop_flag: bool, - pub custom_derive: bool, - pub custom_attribute: bool, - pub asm: bool, - pub log_syntax: bool, - pub trace_macros: bool, - pub concat_idents: bool, - pub box_syntax: bool, - pub placement_in_syntax: bool, - pub non_ascii_idents: bool, - pub macro_reexport: bool, - pub link_args: bool, - pub intrinsics: bool, - pub platform_intrinsics: bool, - pub abi_vectorcall: bool, - pub plugin_registrar: bool, - pub start: bool, - pub main: bool, - pub simd: bool, - pub repr_simd: bool, - pub optin_builtin_traits: bool, - pub link_llvm_intrinsics: bool, - pub type_ascription: bool, - pub inclusive_range_syntax: bool, - pub advanced_slice_patterns: bool, - pub slice_patterns: bool, - pub box_patterns: bool, - pub associated_consts: bool, - pub associated_type_defaults: bool -} - -impl Features { - pub fn new() -> Features { - Features { - unboxed_closures: false, - rustc_diagnostic_macros: false, - allow_quote: false, - allow_asm: false, - allow_log_syntax: false, - allow_concat_idents: false, - allow_trace_macros: false, - allow_internal_unstable: false, - allow_custom_derive: false, - allow_placement_in: false, - allow_box: false, - allow_pushpop_unsafe: false, - allow_inclusive_range: false, - simd_ffi: false, - unmarked_api: false, - declared_stable_lang_features: Vec::new(), - declared_lib_features: Vec::new(), - const_fn: false, - const_indexing: false, - static_recursion: false, - default_type_parameter_fallback: false, - rustc_attrs: false, - type_macros: false, - cfg_target_feature: false, - cfg_target_vendor: false, - cfg_target_thread_local: false, - staged_api: false, - stmt_expr_attributes: false, - deprecated: false, - question_mark: false, - specialization: false, - pub_restricted: false, - structural_match: false, - plugin: false, - lang_items: false, - linkage: false, - thread_local: false, - on_unimplemented: false, - allocator: false, - needs_allocator: false, - fundamental: false, - linked_from: false, - naked: false, - no_debug: false, - omit_gdb_pretty_printer_section: false, - dropck_parametricity: false, - unwind_attributes: false, - prelude_import: false, - reflect: false, - no_core: false, - unsafe_no_drop_flag: false, - custom_derive: false, - custom_attribute: false, - asm: false, - log_syntax: false, - trace_macros: false, - concat_idents: false, - box_syntax: false, - placement_in_syntax: false, - non_ascii_idents: false, - macro_reexport: false, - link_args: false, - intrinsics: false, - platform_intrinsics: false, - abi_vectorcall: false, - plugin_registrar: false, - start: false, - main: false, - simd: false, - repr_simd: false, - optin_builtin_traits: false, - link_llvm_intrinsics: false, - type_ascription: false, - inclusive_range_syntax: false, - advanced_slice_patterns: false, - slice_patterns: false, - box_patterns: false, - associated_consts: false, - associated_type_defaults: false, - } - } -} - const EXPLAIN_BOX_SYNTAX: &'static str = "box expression syntax is experimental; you can call `Box::new` instead."; @@ -802,21 +667,21 @@ const EXPLAIN_STMT_ATTR_SYNTAX: &'static str = "attributes on non-item statements and expressions are experimental."; pub fn check_for_box_syntax(f: Option<&Features>, diag: &Handler, span: Span) { - if let Some(&Features { allow_box: true, .. }) = f { + if let Some(&Features { box_syntax: true, .. }) = f { return; } emit_feature_err(diag, "box_syntax", span, GateIssue::Language, EXPLAIN_BOX_SYNTAX); } pub fn check_for_placement_in(f: Option<&Features>, diag: &Handler, span: Span) { - if let Some(&Features { allow_placement_in: true, .. }) = f { + if let Some(&Features { placement_in_syntax: true, .. }) = f { return; } emit_feature_err(diag, "placement_in_syntax", span, GateIssue::Language, EXPLAIN_PLACEMENT_IN); } pub fn check_for_pushpop_syntax(f: Option<&Features>, diag: &Handler, span: Span) { - if let Some(&Features { allow_pushpop_unsafe: true, .. }) = f { + if let Some(&Features { pushpop_unsafe: true, .. }) = f { return; } emit_feature_err(diag, "pushpop_unsafe", span, GateIssue::Language, EXPLAIN_PUSHPOP_UNSAFE); @@ -895,15 +760,17 @@ impl<'a> Context<'a> { } fn find_lang_feature_issue(feature: &str) -> Option { - let info = KNOWN_FEATURES.iter() - .find(|t| t.0 == feature) - .unwrap(); - let issue = info.2; - if let Active = info.3 { + if let Some(info) = ACTIVE_FEATURES.iter().find(|t| t.0 == feature) { + let issue = info.2; // FIXME (#28244): enforce that active features have issue numbers // assert!(issue.is_some()) + issue + } else { + // search in Accepted or Removed features + ACCEPTED_FEATURES.iter().chain(REMOVED_FEATURES.iter()) + .find(|t| t.0 == feature) + .unwrap().2 } - issue } pub enum GateIssue { @@ -1317,9 +1184,7 @@ fn check_crate_inner(cm: &CodeMap, span_handler: &Handler, -> Features where F: FnOnce(&mut Context, &ast::Crate) { - let mut accepted_features = Vec::new(); - let mut unknown_features = Vec::new(); - let mut enabled_features = Vec::new(); + let mut features = Features::new(); for attr in &krate.attrs { if !attr.check_name("feature") { @@ -1342,115 +1207,25 @@ fn check_crate_inner(cm: &CodeMap, span_handler: &Handler, continue } }; - match KNOWN_FEATURES.iter() - .find(|& &(n, _, _, _)| name == n) { - Some(&(name, _, _, Active)) => { - enabled_features.push(name); - } - Some(&(_, _, _, Removed)) => { - span_handler.span_err(mi.span, "feature has been removed"); - } - Some(&(_, _, _, Accepted)) => { - accepted_features.push(mi.span); - } - None => { - unknown_features.push((name, mi.span)); - } + if let Some(&(_, _, _, setter)) = ACTIVE_FEATURES.iter() + .find(|& &(n, _, _, _)| name == n) { + *(setter(&mut features)) = true; + } + else if let Some(&(_, _, _)) = REMOVED_FEATURES.iter() + .find(|& &(n, _, _)| name == n) { + span_handler.span_err(mi.span, "feature has been removed"); + } + else if let Some(&(_, _, _)) = ACCEPTED_FEATURES.iter() + .find(|& &(n, _, _)| name == n) { + features.declared_stable_lang_features.push(mi.span); + } else { + features.declared_lib_features.push((name, mi.span)); } } } } } - let has_feature = |feature: &str| -> bool { - enabled_features.iter().any(|&n| n == feature) - }; - - // FIXME (pnkfelix): Before adding the 99th entry below, change it - // to a single-pass (instead of N calls to `.has_feature`). - - let features = Features { - unboxed_closures: has_feature("unboxed_closures"), - rustc_diagnostic_macros: has_feature("rustc_diagnostic_macros"), - allow_quote: has_feature("quote"), - allow_asm: has_feature("asm"), - allow_log_syntax: has_feature("log_syntax"), - allow_concat_idents: has_feature("concat_idents"), - allow_trace_macros: has_feature("trace_macros"), - allow_internal_unstable: has_feature("allow_internal_unstable"), - allow_custom_derive: has_feature("custom_derive"), - allow_placement_in: has_feature("placement_in_syntax"), - allow_box: has_feature("box_syntax"), - allow_pushpop_unsafe: has_feature("pushpop_unsafe"), - allow_inclusive_range: has_feature("inclusive_range_syntax"), - simd_ffi: has_feature("simd_ffi"), - unmarked_api: has_feature("unmarked_api"), - declared_stable_lang_features: accepted_features, - declared_lib_features: unknown_features, - const_fn: has_feature("const_fn"), - const_indexing: has_feature("const_indexing"), - static_recursion: has_feature("static_recursion"), - default_type_parameter_fallback: has_feature("default_type_parameter_fallback"), - rustc_attrs: has_feature("rustc_attrs"), - type_macros: has_feature("type_macros"), - cfg_target_feature: has_feature("cfg_target_feature"), - cfg_target_vendor: has_feature("cfg_target_vendor"), - cfg_target_thread_local: has_feature("cfg_target_thread_local"), - staged_api: has_feature("staged_api"), - stmt_expr_attributes: has_feature("stmt_expr_attributes"), - deprecated: has_feature("deprecated"), - question_mark: has_feature("question_mark"), - specialization: has_feature("specialization"), - pub_restricted: has_feature("pub_restricted"), - structural_match: has_feature("bool"), - plugin: has_feature("plugin"), - lang_items: has_feature("lang_items"), - linkage: has_feature("linkage"), - thread_local: has_feature("thread_local"), - on_unimplemented: has_feature("on_unimplemented"), - allocator: has_feature("allocator"), - needs_allocator: has_feature("needs_allocator"), - fundamental: has_feature("fundamental"), - linked_from: has_feature("linked_from"), - naked: has_feature("naked"), - no_debug: has_feature("no_debug"), - omit_gdb_pretty_printer_section: has_feature("omit_gdb_pretty_printer_section"), - dropck_parametricity: has_feature("dropck_parametricity"), - unwind_attributes: has_feature("unwind_attributes"), - prelude_import: has_feature("prelude_import"), - reflect: has_feature("reflect"), - no_core: has_feature("no_core"), - unsafe_no_drop_flag: has_feature("unsafe_no_drop_flag"), - custom_derive: has_feature("custom_derive"), - custom_attribute: has_feature("custom_attribute"), - asm: has_feature("asm"), - log_syntax: has_feature("log_syntax"), - trace_macros: has_feature("trace_macros"), - concat_idents: has_feature("concat_idents"), - box_syntax: has_feature("box_syntax"), - placement_in_syntax: has_feature("placement_in_syntax"), - non_ascii_idents: has_feature("non_ascii_idents"), - macro_reexport: has_feature("macro_reexport"), - link_args: has_feature("link_args"), - intrinsics: has_feature("intrinsics"), - platform_intrinsics: has_feature("platform_intrinsics"), - abi_vectorcall: has_feature("abi_vectorcall"), - plugin_registrar: has_feature("plugin_registrar"), - start: has_feature("start"), - main: has_feature("main"), - simd: has_feature("simd"), - repr_simd: has_feature("repr_simd"), - optin_builtin_traits: has_feature("optin_builtin_traits"), - link_llvm_intrinsics: has_feature("link_llvm_intrinsics"), - type_ascription: has_feature("type_ascription"), - inclusive_range_syntax: has_feature("inclusive_range_syntax"), - advanced_slice_patterns: has_feature("advanced_slice_patterns"), - slice_patterns: has_feature("slice_patterns"), - box_patterns: has_feature("box_patterns"), - associated_consts: has_feature("associated_consts"), - associated_type_defaults: has_feature("associated_type_defaults"), - }; - let mut cx = Context { features: features, span_handler: span_handler,