Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow library features to be marked internal as well #115623

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions compiler/rustc_attr/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ attr_incorrect_repr_format_generic =
attr_incorrect_repr_format_packed_one_or_zero_arg =
incorrect `repr(packed)` attribute format: `packed` takes exactly one parenthesized argument, or no parentheses at all

attr_internal_no_args =
`is_internal` should not have any arguments

attr_invalid_issue_string =
`issue` must be a non-zero numeric string or "none"
.must_not_be_zero = `issue` must not be "0", use "none" instead
Expand Down
10 changes: 10 additions & 0 deletions compiler/rustc_attr/src/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,8 @@ pub enum StabilityLevel {
/// Relevant `rust-lang/rust` issue.
issue: Option<NonZeroU32>,
is_soft: bool,
/// If the feature is internal
is_internal: bool,
/// If part of a feature is stabilized and a new feature is added for the remaining parts,
/// then the `implied_by` attribute is used to indicate which now-stable feature previously
/// contained a item.
Expand Down Expand Up @@ -461,6 +463,7 @@ fn parse_unstability(sess: &Session, attr: &Attribute) -> Option<(Symbol, Stabil
let mut issue = None;
let mut issue_num = None;
let mut is_soft = false;
let mut is_internal = false;
let mut implied_by = None;
for meta in metas {
let Some(mi) = meta.meta_item() else {
Expand Down Expand Up @@ -515,6 +518,12 @@ fn parse_unstability(sess: &Session, attr: &Attribute) -> Option<(Symbol, Stabil
}
is_soft = true;
}
sym::is_internal => {
if !mi.is_word() {
sess.emit_err(session_diagnostics::InternalNoArgs { span: mi.span });
}
is_internal = true;
}
sym::implied_by => {
if !insert_or_error(mi, &mut implied_by) {
return None;
Expand Down Expand Up @@ -545,6 +554,7 @@ fn parse_unstability(sess: &Session, attr: &Attribute) -> Option<(Symbol, Stabil
issue: issue_num,
is_soft,
implied_by,
is_internal,
};
Some((feature, level))
}
Expand Down
7 changes: 7 additions & 0 deletions compiler/rustc_attr/src/session_diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -386,6 +386,13 @@ pub(crate) struct SoftNoArgs {
pub span: Span,
}

#[derive(Diagnostic)]
#[diag(attr_internal_no_args)]
pub(crate) struct InternalNoArgs {
#[primary_span]
pub span: Span,
}

#[derive(Diagnostic)]
#[diag(attr_unknown_version_literal)]
pub(crate) struct UnknownVersionLiteral {
Expand Down
32 changes: 29 additions & 3 deletions compiler/rustc_lint/src/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ use rustc_errors::{Applicability, DecorateLint, MultiSpan};
use rustc_feature::{deprecated_attributes, AttributeGate, BuiltinAttribute, GateIssue, Stability};
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID};
use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, LOCAL_CRATE};
use rustc_hir::intravisit::FnKind as HirFnKind;
use rustc_hir::{Body, FnDecl, GenericParamKind, Node, PatKind, PredicateOrigin};
use rustc_middle::lint::in_external_macro;
Expand Down Expand Up @@ -2246,10 +2246,15 @@ declare_lint! {

declare_lint_pass!(
/// Check for used feature gates in `INCOMPLETE_FEATURES` in `rustc_feature/src/active.rs`.
IncompleteInternalFeatures => [INCOMPLETE_FEATURES, INTERNAL_FEATURES]
IncompleteInternalLangFeatures => [INCOMPLETE_FEATURES, INTERNAL_FEATURES]
);

impl EarlyLintPass for IncompleteInternalFeatures {
declare_lint_pass!(
/// Check for used library features declared as `unstable(is_internal)`.
InternalLibFeatures => []
);

impl EarlyLintPass for IncompleteInternalLangFeatures {
fn check_crate(&mut self, cx: &EarlyContext<'_>, _: &ast::Crate) {
let features = cx.builder.features();
features
Expand Down Expand Up @@ -2281,6 +2286,27 @@ impl EarlyLintPass for IncompleteInternalFeatures {
}
}

// Needs to be a late pass because we need the list of parent crates
impl<'tcx> LateLintPass<'tcx> for InternalLibFeatures {
fn check_crate(&mut self, cx: &LateContext<'tcx>) {
let features = cx.tcx.features();
for cnum in [LOCAL_CRATE].into_iter().chain(cx.tcx.crates(()).iter().copied()) {
let crate_features = cx.tcx.lib_features(cnum);
for &(name, span) in &features.declared_lib_features {
if let Some((is_unstable, _)) = crate_features.unstable.get(&name) {
if *is_unstable {
cx.emit_spanned_lint(
INTERNAL_FEATURES,
span,
BuiltinInternalFeatures { name, note: None },
);
}
}
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should all this method go in rustc_passes::stability::check_unused_or_stable_features?

}
}

const HAS_MIN_FEATURES: &[Symbol] = &[sym::specialization];

declare_lint! {
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_lint/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -171,12 +171,12 @@ early_lint_methods!(
SpecialModuleName: SpecialModuleName,
AnonymousParameters: AnonymousParameters,
EllipsisInclusiveRangePatterns: EllipsisInclusiveRangePatterns::default(),
IncompleteInternalLangFeatures: IncompleteInternalLangFeatures,
NonCamelCaseTypes: NonCamelCaseTypes,
DeprecatedAttr: DeprecatedAttr::new(),
WhileTrue: WhileTrue,
NonAsciiIdents: NonAsciiIdents,
HiddenUnicodeCodepoints: HiddenUnicodeCodepoints,
IncompleteInternalFeatures: IncompleteInternalFeatures,
RedundantSemicolons: RedundantSemicolons,
UnusedDocComment: UnusedDocComment,
UnexpectedCfgs: UnexpectedCfgs,
Expand All @@ -200,6 +200,7 @@ late_lint_methods!(
BoxPointers: BoxPointers,
PathStatements: PathStatements,
LetUnderscore: LetUnderscore,
InternalLibFeatures: InternalLibFeatures,
InvalidReferenceCasting: InvalidReferenceCasting::default(),
// Depends on referenced function signatures in expressions
UnusedResults: UnusedResults,
Expand Down
16 changes: 14 additions & 2 deletions compiler/rustc_metadata/src/rmeta/decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ use rustc_index::{Idx, IndexVec};
use rustc_middle::metadata::ModChild;
use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile;
use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo};
use rustc_middle::middle::lib_features::LibFeatures;
use rustc_middle::mir::interpret::{AllocDecodingSession, AllocDecodingState};
use rustc_middle::ty::codec::TyDecoder;
use rustc_middle::ty::fast_reject::SimplifiedType;
Expand Down Expand Up @@ -1007,8 +1008,19 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
}

/// Iterates over all the stability attributes in the given crate.
fn get_lib_features(self, tcx: TyCtxt<'tcx>) -> &'tcx [(Symbol, Option<Symbol>)] {
tcx.arena.alloc_from_iter(self.root.lib_features.decode(self))
fn get_lib_features(self, _tcx: TyCtxt<'tcx>) -> LibFeatures {
let mut features = LibFeatures::default();
for (symbol, stability) in self.root.lib_features.decode(self) {
match stability {
FeatureStability::AcceptedSince(since) => {
features.stable.insert(symbol, (since, DUMMY_SP));
}
FeatureStability::Unstable(internal) => {
features.unstable.insert(symbol, (internal, DUMMY_SP));
}
}
}
features
}

/// Iterates over the stability implications in the given crate (when a `#[unstable]` attribute
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,7 @@ provide! { tcx, def_id, other, cdata,
module_children => {
tcx.arena.alloc_from_iter(cdata.get_module_children(def_id.index, tcx.sess))
}
defined_lib_features => { cdata.get_lib_features(tcx) }
lib_features => { cdata.get_lib_features(tcx) }
stability_implications => {
cdata.get_stability_implications(tcx).iter().copied().collect()
}
Expand Down
5 changes: 3 additions & 2 deletions compiler/rustc_metadata/src/rmeta/encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ use rustc_middle::middle::dependency_format::Linkage;
use rustc_middle::middle::exported_symbols::{
metadata_symbol_name, ExportedSymbol, SymbolExportInfo,
};
use rustc_middle::middle::lib_features::FeatureStability;
use rustc_middle::mir::interpret;
use rustc_middle::query::LocalCrate;
use rustc_middle::query::Providers;
Expand Down Expand Up @@ -1871,10 +1872,10 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
self.lazy_array(deps.iter().map(|(_, dep)| dep))
}

fn encode_lib_features(&mut self) -> LazyArray<(Symbol, Option<Symbol>)> {
fn encode_lib_features(&mut self) -> LazyArray<(Symbol, FeatureStability)> {
empty_proc_macro!(self);
let tcx = self.tcx;
let lib_features = tcx.lib_features(());
let lib_features = tcx.lib_features(LOCAL_CRATE);
self.lazy_array(lib_features.to_vec())
}

Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_metadata/src/rmeta/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use decoder::Metadata;
use def_path_hash_map::DefPathHashMapRef;
use rustc_data_structures::fx::FxHashMap;
use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile;
use rustc_middle::middle::lib_features::FeatureStability;
use table::TableBuilder;

use rustc_ast as ast;
Expand Down Expand Up @@ -264,7 +265,7 @@ pub(crate) struct CrateRoot {

crate_deps: LazyArray<CrateDep>,
dylib_dependency_formats: LazyArray<Option<LinkagePreference>>,
lib_features: LazyArray<(Symbol, Option<Symbol>)>,
lib_features: LazyArray<(Symbol, FeatureStability)>,
stability_implications: LazyArray<(Symbol, Symbol)>,
lang_items: LazyArray<(DefIndex, LangItem)>,
lang_items_missing: LazyArray<LangItem>,
Expand Down
21 changes: 16 additions & 5 deletions compiler/rustc_middle/src/middle/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,31 @@ pub mod lib_features {
use rustc_data_structures::fx::FxHashMap;
use rustc_span::{symbol::Symbol, Span};

#[derive(HashStable, Debug)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[derive(HashStable, TyEncodable, TyDecodable)]
pub enum FeatureStability {
AcceptedSince(Symbol),
Unstable(bool),
}

#[derive(HashStable, Debug, Default)]
pub struct LibFeatures {
/// A map from feature to stabilisation version.
pub stable: FxHashMap<Symbol, (Symbol, Span)>,
pub unstable: FxHashMap<Symbol, Span>,
pub unstable: FxHashMap<Symbol, (bool, Span)>,
}

impl LibFeatures {
pub fn to_vec(&self) -> Vec<(Symbol, Option<Symbol>)> {
pub fn to_vec(&self) -> Vec<(Symbol, FeatureStability)> {
let mut all_features: Vec<_> = self
.stable
.iter()
.map(|(f, (s, _))| (*f, Some(*s)))
.chain(self.unstable.keys().map(|f| (*f, None)))
.map(|(f, (s, _))| (*f, FeatureStability::AcceptedSince(*s)))
.chain(
self.unstable
.iter()
.map(|(f, (internal, _))| (*f, FeatureStability::Unstable(*internal))),
)
.collect();
all_features.sort_unstable_by(|a, b| a.0.as_str().partial_cmp(b.0.as_str()).unwrap());
all_features
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/middle/stability.rs
Original file line number Diff line number Diff line change
Expand Up @@ -440,7 +440,7 @@ impl<'tcx> TyCtxt<'tcx> {

match stability {
Some(Stability {
level: attr::Unstable { reason, issue, is_soft, implied_by },
level: attr::Unstable { reason, issue, is_soft, implied_by, is_internal: _ },
feature,
..
}) => {
Expand Down
7 changes: 2 additions & 5 deletions compiler/rustc_middle/src/query/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1744,13 +1744,10 @@ rustc_queries! {
desc { |tcx| "computing crate imported by `{}`", tcx.def_path_str(def_id) }
}

query lib_features(_: ()) -> &'tcx LibFeatures {
arena_cache
desc { "calculating the lib features map" }
}
query defined_lib_features(_: CrateNum) -> &'tcx [(Symbol, Option<Symbol>)] {
query lib_features(_: CrateNum) -> &'tcx LibFeatures {
desc { "calculating the lib features defined in a crate" }
separate_provide_extern
arena_cache
}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I consolidated this into one query -- it's not necessarily a requirement of this PR to do so, so if that's not desirable, I could revert it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is useful. Could you extract it in a standalone query? Or even a standalone PR, as there may be discussion on this PR.

query stability_implications(_: CrateNum) -> &'tcx FxHashMap<Symbol, Symbol> {
arena_cache
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_middle/src/ty/parameterized.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ trivially_parameterized_over_tcx! {
crate::middle::codegen_fn_attrs::CodegenFnAttrs,
crate::middle::debugger_visualizer::DebuggerVisualizerFile,
crate::middle::exported_symbols::SymbolExportInfo,
crate::middle::lib_features::FeatureStability,
crate::middle::resolve_bound_vars::ObjectLifetimeDefault,
crate::mir::ConstQualifs,
ty::AssocItemContainer,
Expand Down
Loading