|
1 | 1 | //! List of the unstable feature gates.
|
2 | 2 |
|
| 3 | +use std::path::Path; |
| 4 | + |
3 | 5 | use rustc_data_structures::fx::FxHashSet;
|
4 | 6 | use rustc_span::symbol::{sym, Symbol};
|
5 | 7 | use rustc_span::Span;
|
@@ -649,6 +651,60 @@ declare_features! (
|
649 | 651 | // -------------------------------------------------------------------------
|
650 | 652 | );
|
651 | 653 |
|
| 654 | +impl Features { |
| 655 | + pub fn dump_feature_usage_metrics(&self, metrics_dir: &Path) { |
| 656 | + #[derive(serde::Serialize)] |
| 657 | + struct LibFeature { |
| 658 | + symbol: String, |
| 659 | + } |
| 660 | + |
| 661 | + #[derive(serde::Serialize)] |
| 662 | + struct LangFeature { |
| 663 | + symbol: String, |
| 664 | + since: Option<String>, |
| 665 | + } |
| 666 | + |
| 667 | + #[derive(serde::Serialize)] |
| 668 | + struct FeatureUsage { |
| 669 | + lib_features: Vec<LibFeature>, |
| 670 | + lang_features: Vec<LangFeature>, |
| 671 | + } |
| 672 | + |
| 673 | + // TODO (DECIDE): How fine grained do we want to track feature usage? |
| 674 | + // Jane Preference: i want to track usage for code that gets used, not code |
| 675 | + // that is in development, but I don't know how we'd hook into this for code |
| 676 | + // that doesn't participate in the crates.io ecosystem, those crates won't even |
| 677 | + // necessarily have releases or versioning norms that match other crates, so we |
| 678 | + // may have to just track per compilation and aggressively collapse metrics to |
| 679 | + // avoid unnecessary disk usage. |
| 680 | + // TODO avoid filename collisions between runs |
| 681 | + let feature_metrics_file = metrics_dir.join("unstable_feature_usage.json"); |
| 682 | + let Ok(feature_metrics_file) = std::fs::File::create(feature_metrics_file) else { |
| 683 | + return; |
| 684 | + }; |
| 685 | + let feature_metrics_file = std::io::BufWriter::new(feature_metrics_file); |
| 686 | + |
| 687 | + let lib_features = self |
| 688 | + .declared_lib_features |
| 689 | + .iter() |
| 690 | + .map(|(symbol, _)| LibFeature { symbol: symbol.to_string() }) |
| 691 | + .collect(); |
| 692 | + |
| 693 | + let lang_features = self |
| 694 | + .declared_lang_features |
| 695 | + .iter() |
| 696 | + .map(|(symbol, _, since)| LangFeature { |
| 697 | + symbol: symbol.to_string(), |
| 698 | + since: since.map(|since| since.to_string()), |
| 699 | + }) |
| 700 | + .collect(); |
| 701 | + |
| 702 | + let feature_usage = FeatureUsage { lib_features, lang_features }; |
| 703 | + |
| 704 | + let _ = serde_json::to_writer(feature_metrics_file, &feature_usage); |
| 705 | + } |
| 706 | +} |
| 707 | + |
652 | 708 | /// Some features are not allowed to be used together at the same time, if
|
653 | 709 | /// the two are present, produce an error.
|
654 | 710 | ///
|
|
0 commit comments