Skip to content

Commit 65f6d33

Browse files
committed
Auto merge of rust-lang#94096 - cjgillot:ensure-stability, r=lcnr
Ensure stability directives are checked in all cases Split off rust-lang#93017 Stability and deprecation were not checked in all cases, for instance if a type error happened. This PR moves the check earlier in the pipeline to ensure the errors are emitted in all cases. r? `@lcnr`
2 parents 8fa5d74 + c680d39 commit 65f6d33

File tree

133 files changed

+497
-477
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

133 files changed

+497
-477
lines changed

compiler/rustc_ast_passes/src/feature_gate.rs

+25
Original file line numberDiff line numberDiff line change
@@ -420,6 +420,31 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
420420
}
421421
}
422422
}
423+
424+
// Emit errors for non-staged-api crates.
425+
if !self.features.staged_api {
426+
if attr.has_name(sym::rustc_deprecated)
427+
|| attr.has_name(sym::unstable)
428+
|| attr.has_name(sym::stable)
429+
|| attr.has_name(sym::rustc_const_unstable)
430+
|| attr.has_name(sym::rustc_const_stable)
431+
{
432+
struct_span_err!(
433+
self.sess,
434+
attr.span,
435+
E0734,
436+
"stability attributes may not be used outside of the standard library",
437+
)
438+
.emit();
439+
}
440+
} else {
441+
if attr.has_name(sym::deprecated) {
442+
self.sess
443+
.struct_span_err(attr.span, "`#[deprecated]` cannot be used in staged API")
444+
.span_label(attr.span, "use `#[rustc_deprecated]` instead")
445+
.emit();
446+
}
447+
}
423448
}
424449

425450
fn visit_item(&mut self, i: &'a ast::Item) {

compiler/rustc_expand/src/config.rs

+3
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,7 @@ fn get_features(
167167
if let Some(Feature { since, .. }) = ACCEPTED_FEATURES.iter().find(|f| name == f.name) {
168168
let since = Some(Symbol::intern(since));
169169
features.declared_lang_features.push((name, mi.span(), since));
170+
features.active_features.insert(name);
170171
continue;
171172
}
172173

@@ -187,10 +188,12 @@ fn get_features(
187188
if let Some(f) = ACTIVE_FEATURES.iter().find(|f| name == f.name) {
188189
f.set(&mut features, mi.span());
189190
features.declared_lang_features.push((name, mi.span(), None));
191+
features.active_features.insert(name);
190192
continue;
191193
}
192194

193195
features.declared_lib_features.push((name, mi.span()));
196+
features.active_features.insert(name);
194197
}
195198
}
196199

compiler/rustc_feature/src/active.rs

+8
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
33
use super::{to_nonzero, Feature, State};
44

5+
use rustc_data_structures::fx::FxHashSet;
56
use rustc_span::edition::Edition;
67
use rustc_span::symbol::{sym, Symbol};
78
use rustc_span::Span;
@@ -47,6 +48,8 @@ macro_rules! declare_features {
4748
pub declared_lang_features: Vec<(Symbol, Span, Option<Symbol>)>,
4849
/// `#![feature]` attrs for non-language (library) features.
4950
pub declared_lib_features: Vec<(Symbol, Span)>,
51+
/// Features enabled for this crate.
52+
pub active_features: FxHashSet<Symbol>,
5053
$(
5154
$(#[doc = $doc])*
5255
pub $feature: bool
@@ -58,6 +61,11 @@ macro_rules! declare_features {
5861
$(f(stringify!($feature), self.$feature);)+
5962
}
6063

64+
/// Is the given feature active?
65+
pub fn active(&self, feature: Symbol) -> bool {
66+
self.active_features.contains(&feature)
67+
}
68+
6169
/// Is the given feature enabled?
6270
///
6371
/// Panics if the symbol doesn't correspond to a declared feature.

compiler/rustc_interface/src/passes.rs

+6-5
Original file line numberDiff line numberDiff line change
@@ -921,12 +921,18 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> {
921921
tcx.ensure().check_mod_const_bodies(module);
922922
});
923923
},
924+
{
925+
sess.time("unused_lib_feature_checking", || {
926+
rustc_passes::stability::check_unused_or_stable_features(tcx)
927+
});
928+
},
924929
{
925930
// We force these querie to run,
926931
// since they might not otherwise get called.
927932
// This marks the corresponding crate-level attributes
928933
// as used, and ensures that their values are valid.
929934
tcx.ensure().limits(());
935+
tcx.ensure().stability_index(());
930936
}
931937
);
932938
});
@@ -998,11 +1004,6 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> {
9981004
tcx.hir()
9991005
.par_for_each_module(|module| tcx.ensure().check_mod_deathness(module));
10001006
},
1001-
{
1002-
sess.time("unused_lib_feature_checking", || {
1003-
rustc_passes::stability::check_unused_or_stable_features(tcx)
1004-
});
1005-
},
10061007
{
10071008
sess.time("lint_checking", || {
10081009
rustc_lint::check_crate(tcx, || {

compiler/rustc_middle/src/middle/stability.rs

+3-9
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,12 @@ pub use self::StabilityLevel::*;
66
use crate::ty::{self, DefIdTree, TyCtxt};
77
use rustc_ast::NodeId;
88
use rustc_attr::{self as attr, ConstStability, Deprecation, Stability};
9-
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
9+
use rustc_data_structures::fx::FxHashMap;
1010
use rustc_errors::{Applicability, Diagnostic};
1111
use rustc_feature::GateIssue;
1212
use rustc_hir as hir;
1313
use rustc_hir::def::DefKind;
14-
use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, CRATE_DEF_INDEX};
14+
use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_INDEX};
1515
use rustc_hir::{self, HirId};
1616
use rustc_middle::ty::print::with_no_trimmed_paths;
1717
use rustc_session::lint::builtin::{DEPRECATED, DEPRECATED_IN_FUTURE, SOFT_UNSTABLE};
@@ -63,12 +63,6 @@ pub struct Index {
6363
pub stab_map: FxHashMap<LocalDefId, Stability>,
6464
pub const_stab_map: FxHashMap<LocalDefId, ConstStability>,
6565
pub depr_map: FxHashMap<LocalDefId, DeprecationEntry>,
66-
67-
/// Maps for each crate whether it is part of the staged API.
68-
pub staged_api: FxHashMap<CrateNum, bool>,
69-
70-
/// Features enabled for this crate.
71-
pub active_features: FxHashSet<Symbol>,
7266
}
7367

7468
impl Index {
@@ -423,7 +417,7 @@ impl<'tcx> TyCtxt<'tcx> {
423417
debug!("stability: skipping span={:?} since it is internal", span);
424418
return EvalResult::Allow;
425419
}
426-
if self.stability().active_features.contains(&feature) {
420+
if self.features().active(feature) {
427421
return EvalResult::Allow;
428422
}
429423

compiler/rustc_middle/src/ty/context.rs

-5
Original file line numberDiff line numberDiff line change
@@ -2999,11 +2999,6 @@ pub fn provide(providers: &mut ty::query::Providers) {
29992999
tcx.arena.alloc(tcx.resolutions(()).glob_map.get(&id).cloned().unwrap_or_default())
30003000
};
30013001

3002-
providers.lookup_stability = |tcx, id| tcx.stability().local_stability(id.expect_local());
3003-
providers.lookup_const_stability =
3004-
|tcx, id| tcx.stability().local_const_stability(id.expect_local());
3005-
providers.lookup_deprecation_entry =
3006-
|tcx, id| tcx.stability().local_deprecation_entry(id.expect_local());
30073002
providers.extern_mod_stmt_cnum =
30083003
|tcx, id| tcx.resolutions(()).extern_crate_map.get(&id).cloned();
30093004
providers.output_filenames = |tcx, ()| &tcx.output_filenames;

compiler/rustc_passes/src/stability.rs

+27-80
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
//! A pass that annotates every item and method with its stability level,
22
//! propagating default levels lexically from parent to children ast nodes.
33
4-
use rustc_ast::Attribute;
54
use rustc_attr::{self as attr, ConstStability, Stability};
6-
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
5+
use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
76
use rustc_errors::struct_span_err;
87
use rustc_hir as hir;
98
use rustc_hir::def::{DefKind, Res};
10-
use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, CRATE_DEF_INDEX, LOCAL_CRATE};
9+
use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, CRATE_DEF_INDEX};
1110
use rustc_hir::hir_id::CRATE_HIR_ID;
1211
use rustc_hir::intravisit::{self, Visitor};
1312
use rustc_hir::{FieldDef, Generics, HirId, Item, TraitRef, Ty, TyKind, Variant};
@@ -113,12 +112,8 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
113112
{
114113
let attrs = self.tcx.get_attrs(def_id.to_def_id());
115114
debug!("annotate(id = {:?}, attrs = {:?})", def_id, attrs);
116-
let mut did_error = false;
117-
if !self.tcx.features().staged_api {
118-
did_error = self.forbid_staged_api_attrs(def_id, attrs, inherit_deprecation.clone());
119-
}
120115

121-
let depr = if did_error { None } else { attr::find_deprecation(&self.tcx.sess, attrs) };
116+
let depr = attr::find_deprecation(&self.tcx.sess, attrs);
122117
let mut is_deprecated = false;
123118
if let Some((depr, span)) = &depr {
124119
is_deprecated = true;
@@ -148,16 +143,15 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
148143
}
149144
}
150145

151-
if self.tcx.features().staged_api {
152-
if let Some(a) = attrs.iter().find(|a| a.has_name(sym::deprecated)) {
153-
self.tcx
154-
.sess
155-
.struct_span_err(a.span, "`#[deprecated]` cannot be used in staged API")
156-
.span_label(a.span, "use `#[rustc_deprecated]` instead")
157-
.span_label(item_sp, "")
158-
.emit();
146+
if !self.tcx.features().staged_api {
147+
// Propagate unstability. This can happen even for non-staged-api crates in case
148+
// -Zforce-unstable-if-unmarked is set.
149+
if let Some(stab) = self.parent_stab {
150+
if inherit_deprecation.yes() && stab.level.is_unstable() {
151+
self.index.stab_map.insert(def_id, stab);
152+
}
159153
}
160-
} else {
154+
161155
self.recurse_with_stability_attrs(
162156
depr.map(|(d, _)| DeprecationEntry::local(d, def_id)),
163157
None,
@@ -329,47 +323,6 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
329323
self.parent_const_stab = orig_parent_const_stab;
330324
}
331325
}
332-
333-
// returns true if an error occurred, used to suppress some spurious errors
334-
fn forbid_staged_api_attrs(
335-
&mut self,
336-
def_id: LocalDefId,
337-
attrs: &[Attribute],
338-
inherit_deprecation: InheritDeprecation,
339-
) -> bool {
340-
// Emit errors for non-staged-api crates.
341-
let unstable_attrs = [
342-
sym::unstable,
343-
sym::stable,
344-
sym::rustc_deprecated,
345-
sym::rustc_const_unstable,
346-
sym::rustc_const_stable,
347-
];
348-
let mut has_error = false;
349-
for attr in attrs {
350-
let name = attr.name_or_empty();
351-
if unstable_attrs.contains(&name) {
352-
struct_span_err!(
353-
self.tcx.sess,
354-
attr.span,
355-
E0734,
356-
"stability attributes may not be used outside of the standard library",
357-
)
358-
.emit();
359-
has_error = true;
360-
}
361-
}
362-
363-
// Propagate unstability. This can happen even for non-staged-api crates in case
364-
// -Zforce-unstable-if-unmarked is set.
365-
if let Some(stab) = self.parent_stab {
366-
if inherit_deprecation.yes() && stab.level.is_unstable() {
367-
self.index.stab_map.insert(def_id, stab);
368-
}
369-
}
370-
371-
has_error
372-
}
373326
}
374327

375328
impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
@@ -654,28 +607,12 @@ impl<'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'tcx> {
654607
}
655608

656609
fn stability_index(tcx: TyCtxt<'_>, (): ()) -> Index {
657-
let is_staged_api =
658-
tcx.sess.opts.debugging_opts.force_unstable_if_unmarked || tcx.features().staged_api;
659-
let mut staged_api = FxHashMap::default();
660-
staged_api.insert(LOCAL_CRATE, is_staged_api);
661610
let mut index = Index {
662-
staged_api,
663611
stab_map: Default::default(),
664612
const_stab_map: Default::default(),
665613
depr_map: Default::default(),
666-
active_features: Default::default(),
667614
};
668615

669-
let active_lib_features = &tcx.features().declared_lib_features;
670-
let active_lang_features = &tcx.features().declared_lang_features;
671-
672-
// Put the active features into a map for quick lookup.
673-
index.active_features = active_lib_features
674-
.iter()
675-
.map(|&(s, ..)| s)
676-
.chain(active_lang_features.iter().map(|&(s, ..)| s))
677-
.collect();
678-
679616
{
680617
let mut annotator = Annotator {
681618
tcx,
@@ -728,7 +665,16 @@ fn check_mod_unstable_api_usage(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
728665
}
729666

730667
pub(crate) fn provide(providers: &mut Providers) {
731-
*providers = Providers { check_mod_unstable_api_usage, stability_index, ..*providers };
668+
*providers = Providers {
669+
check_mod_unstable_api_usage,
670+
stability_index,
671+
lookup_stability: |tcx, id| tcx.stability().local_stability(id.expect_local()),
672+
lookup_const_stability: |tcx, id| tcx.stability().local_const_stability(id.expect_local()),
673+
lookup_deprecation_entry: |tcx, id| {
674+
tcx.stability().local_deprecation_entry(id.expect_local())
675+
},
676+
..*providers
677+
};
732678
}
733679

734680
struct Checker<'tcx> {
@@ -884,9 +830,10 @@ impl<'tcx> Visitor<'tcx> for CheckTraitImplStable<'tcx> {
884830
/// were expected to be library features), and the list of features used from
885831
/// libraries, identify activated features that don't exist and error about them.
886832
pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) {
887-
let access_levels = &tcx.privacy_access_levels(());
888-
889-
if tcx.stability().staged_api[&LOCAL_CRATE] {
833+
let is_staged_api =
834+
tcx.sess.opts.debugging_opts.force_unstable_if_unmarked || tcx.features().staged_api;
835+
if is_staged_api {
836+
let access_levels = &tcx.privacy_access_levels(());
890837
let mut missing = MissingStabilityAnnotations { tcx, access_levels };
891838
missing.check_missing_stability(CRATE_DEF_ID, tcx.hir().span(CRATE_HIR_ID));
892839
tcx.hir().walk_toplevel_module(&mut missing);
@@ -907,7 +854,7 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) {
907854
}
908855

909856
let declared_lib_features = &tcx.features().declared_lib_features;
910-
let mut remaining_lib_features = FxHashMap::default();
857+
let mut remaining_lib_features = FxIndexMap::default();
911858
for (feature, span) in declared_lib_features {
912859
if !tcx.sess.opts.unstable_features.is_nightly_build() {
913860
struct_span_err!(
@@ -934,7 +881,7 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) {
934881
remaining_lib_features.remove(&sym::libc);
935882
remaining_lib_features.remove(&sym::test);
936883

937-
let check_features = |remaining_lib_features: &mut FxHashMap<_, _>, defined_features: &[_]| {
884+
let check_features = |remaining_lib_features: &mut FxIndexMap<_, _>, defined_features: &[_]| {
938885
for &(feature, since) in defined_features {
939886
if let Some(since) = since {
940887
if let Some(span) = remaining_lib_features.get(&feature) {

src/test/ui/alloc-error/alloc-error-handler-bad-signature-1.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// compile-flags:-C panic=abort
22

3-
#![feature(alloc_error_handler, panic_handler)]
3+
#![feature(alloc_error_handler)]
44
#![no_std]
55
#![no_main]
66

src/test/ui/alloc-error/alloc-error-handler-bad-signature-2.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// compile-flags:-C panic=abort
22

3-
#![feature(alloc_error_handler, panic_handler)]
3+
#![feature(alloc_error_handler)]
44
#![no_std]
55
#![no_main]
66

src/test/ui/alloc-error/alloc-error-handler-bad-signature-3.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// compile-flags:-C panic=abort
22

3-
#![feature(alloc_error_handler, panic_handler)]
3+
#![feature(alloc_error_handler)]
44
#![no_std]
55
#![no_main]
66

src/test/ui/asm/naked-functions.rs

-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
// ignore-wasm32
55

66
#![feature(naked_functions)]
7-
#![feature(or_patterns)]
87
#![feature(asm_const, asm_sym, asm_unwind)]
98
#![crate_type = "lib"]
109

0 commit comments

Comments
 (0)