|
2 | 2 | //! propagating default levels lexically from parent to children ast nodes.
|
3 | 3 |
|
4 | 4 | use attr::StabilityLevel;
|
5 |
| -use rustc_attr::{self as attr, ConstStability, Stability}; |
| 5 | +use rustc_attr::{self as attr, ConstStability, Stability, Unstable}; |
6 | 6 | use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
|
7 |
| -use rustc_errors::struct_span_err; |
| 7 | +use rustc_errors::{struct_span_err, Applicability}; |
8 | 8 | use rustc_hir as hir;
|
9 | 9 | use rustc_hir::def::{DefKind, Res};
|
10 | 10 | use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID};
|
@@ -265,6 +265,10 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
|
265 | 265 | }
|
266 | 266 | }
|
267 | 267 |
|
| 268 | + if let Stability { level: Unstable { implied_by: Some(implied_by), .. }, feature } = stab { |
| 269 | + self.index.implications.insert(implied_by, feature); |
| 270 | + } |
| 271 | + |
268 | 272 | self.index.stab_map.insert(def_id, stab);
|
269 | 273 | stab
|
270 | 274 | });
|
@@ -610,6 +614,7 @@ fn stability_index(tcx: TyCtxt<'_>, (): ()) -> Index {
|
610 | 614 | stab_map: Default::default(),
|
611 | 615 | const_stab_map: Default::default(),
|
612 | 616 | depr_map: Default::default(),
|
| 617 | + implications: Default::default(), |
613 | 618 | };
|
614 | 619 |
|
615 | 620 | {
|
@@ -668,6 +673,7 @@ pub(crate) fn provide(providers: &mut Providers) {
|
668 | 673 | *providers = Providers {
|
669 | 674 | check_mod_unstable_api_usage,
|
670 | 675 | stability_index,
|
| 676 | + stability_implications: |tcx, _| tcx.stability().implications.clone(), |
671 | 677 | lookup_stability: |tcx, id| tcx.stability().local_stability(id.expect_local()),
|
672 | 678 | lookup_const_stability: |tcx, id| tcx.stability().local_const_stability(id.expect_local()),
|
673 | 679 | lookup_deprecation_entry: |tcx, id| {
|
@@ -946,11 +952,18 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) {
|
946 | 952 | remaining_lib_features.remove(&sym::libc);
|
947 | 953 | remaining_lib_features.remove(&sym::test);
|
948 | 954 |
|
| 955 | + let mut implications = tcx.stability_implications(rustc_hir::def_id::LOCAL_CRATE).clone(); |
| 956 | + for &cnum in tcx.crates(()) { |
| 957 | + implications.extend(tcx.stability_implications(cnum)); |
| 958 | + } |
| 959 | + |
949 | 960 | let check_features = |remaining_lib_features: &mut FxIndexMap<_, _>, defined_features: &[_]| {
|
950 | 961 | for &(feature, since) in defined_features {
|
951 |
| - if let Some(since) = since { |
952 |
| - if let Some(span) = remaining_lib_features.get(&feature) { |
953 |
| - // Warn if the user has enabled an already-stable lib feature. |
| 962 | + if let Some(since) = since && let Some(span) = remaining_lib_features.get(&feature) { |
| 963 | + // Warn if the user has enabled an already-stable lib feature. |
| 964 | + if let Some(implies) = implications.get(&feature) { |
| 965 | + unnecessary_partially_stable_feature_lint(tcx, *span, feature, *implies, since); |
| 966 | + } else { |
954 | 967 | unnecessary_stable_feature_lint(tcx, *span, feature, since);
|
955 | 968 | }
|
956 | 969 | }
|
@@ -983,12 +996,41 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) {
|
983 | 996 | // don't lint about unused features. We should re-enable this one day!
|
984 | 997 | }
|
985 | 998 |
|
| 999 | +fn unnecessary_partially_stable_feature_lint( |
| 1000 | + tcx: TyCtxt<'_>, |
| 1001 | + span: Span, |
| 1002 | + feature: Symbol, |
| 1003 | + implies: Symbol, |
| 1004 | + since: Symbol, |
| 1005 | +) { |
| 1006 | + tcx.struct_span_lint_hir(lint::builtin::STABLE_FEATURES, hir::CRATE_HIR_ID, span, |lint| { |
| 1007 | + lint.build(&format!( |
| 1008 | + "the feature `{feature}` has been partially stabilized since {since} and is succeeded \ |
| 1009 | + by the feature `{implies}`" |
| 1010 | + )) |
| 1011 | + .span_suggestion( |
| 1012 | + span, |
| 1013 | + &format!( |
| 1014 | + "if you are using features which are still unstable, change to using `{implies}`" |
| 1015 | + ), |
| 1016 | + implies, |
| 1017 | + Applicability::MaybeIncorrect, |
| 1018 | + ) |
| 1019 | + .span_suggestion( |
| 1020 | + tcx.sess.source_map().span_extend_to_line(span), |
| 1021 | + "if you are using features which are now stable, remove this line", |
| 1022 | + "", |
| 1023 | + Applicability::MaybeIncorrect, |
| 1024 | + ) |
| 1025 | + .emit(); |
| 1026 | + }); |
| 1027 | +} |
| 1028 | + |
986 | 1029 | fn unnecessary_stable_feature_lint(tcx: TyCtxt<'_>, span: Span, feature: Symbol, since: Symbol) {
|
987 | 1030 | tcx.struct_span_lint_hir(lint::builtin::STABLE_FEATURES, hir::CRATE_HIR_ID, span, |lint| {
|
988 | 1031 | lint.build(&format!(
|
989 |
| - "the feature `{}` has been stable since {} and no longer requires \ |
990 |
| - an attribute to enable", |
991 |
| - feature, since |
| 1032 | + "the feature `{feature}` has been stable since {since} and no longer requires an \ |
| 1033 | + attribute to enable", |
992 | 1034 | ))
|
993 | 1035 | .emit();
|
994 | 1036 | });
|
|
0 commit comments