Rollup merge of #152164 - mu001999-contrib:lint/unused_features, r=JonathanBrouwer

Lint unused features

*[View all comments](https://triagebot.infra.rust-lang.org/gh-comments/rust-lang/rust/pull/152164)*

Fixes rust-lang/rust#44232
Fixes rust-lang/rust#151752

---

This PR records used features through query side effect, then reports unsued features finally.
This commit is contained in:
Jonathan Brouwer
2026-03-04 19:30:36 +01:00
committed by GitHub
111 changed files with 386 additions and 141 deletions
+5 -1
View File
@@ -338,7 +338,11 @@ pub fn run_compiler(at_args: &[String], callbacks: &mut (dyn Callbacks + Send))
}
}
Some(Linker::codegen_and_build_linker(tcx, &*compiler.codegen_backend))
let linker = Linker::codegen_and_build_linker(tcx, &*compiler.codegen_backend);
tcx.report_unused_features();
Some(linker)
});
// Linking is done outside the `compiler.enter()` so that the
-2
View File
@@ -7,9 +7,7 @@
#![allow(rustc::direct_use_of_rustc_type_ir)]
#![cfg_attr(bootstrap, feature(assert_matches))]
#![feature(associated_type_defaults)]
#![feature(box_patterns)]
#![feature(default_field_values)]
#![feature(error_reporter)]
#![feature(macro_metavar_expr_concat)]
#![feature(negative_impls)]
#![feature(never_type)]
+1 -1
View File
@@ -1330,7 +1330,7 @@ pub struct BuiltinAttribute {
safety: AttributeSafety::Normal,
template: template!(NameValueStr: "name"),
duplicates: ErrorFollowing,
gate: Gated{
gate: Gated {
feature: sym::rustc_attrs,
message: "use of an internal attribute",
check: Features::rustc_attrs,
+1 -1
View File
@@ -137,5 +137,5 @@ pub fn find_feature_issue(feature: Symbol, issue: GateIssue) -> Option<NonZero<u
pub use removed::REMOVED_LANG_FEATURES;
pub use unstable::{
DEPENDENT_FEATURES, EnabledLangFeature, EnabledLibFeature, Features, INCOMPATIBLE_FEATURES,
UNSTABLE_LANG_FEATURES,
TRACK_FEATURE, UNSTABLE_LANG_FEATURES,
};
+14 -2
View File
@@ -3,11 +3,18 @@
use std::path::PathBuf;
use std::time::{SystemTime, UNIX_EPOCH};
use rustc_data_structures::AtomicRef;
use rustc_data_structures::fx::FxHashSet;
use rustc_span::{Span, Symbol, sym};
use super::{Feature, to_nonzero};
fn default_track_feature(_: Symbol) {}
/// Recording used features in the dependency graph so incremental can
/// replay used features when needed.
pub static TRACK_FEATURE: AtomicRef<fn(Symbol)> = AtomicRef::new(&(default_track_feature as _));
#[derive(PartialEq)]
enum FeatureStatus {
Default,
@@ -103,7 +110,12 @@ pub fn enabled_features_iter_stable_order(
/// Is the given feature enabled (via `#[feature(...)]`)?
pub fn enabled(&self, feature: Symbol) -> bool {
self.enabled_features.contains(&feature)
if self.enabled_features.contains(&feature) {
TRACK_FEATURE(feature);
true
} else {
false
}
}
}
@@ -124,7 +136,7 @@ macro_rules! declare_features {
impl Features {
$(
pub fn $feature(&self) -> bool {
self.enabled_features.contains(&sym::$feature)
self.enabled(sym::$feature)
}
)*
+22 -1
View File
@@ -12,8 +12,9 @@
use std::fmt;
use rustc_errors::DiagInner;
use rustc_middle::dep_graph::TaskDepsRef;
use rustc_middle::dep_graph::{DepNodeIndex, QuerySideEffect, TaskDepsRef};
use rustc_middle::ty::tls;
use rustc_span::Symbol;
fn track_span_parent(def_id: rustc_span::def_id::LocalDefId) {
tls::with_context_opt(|icx| {
@@ -51,6 +52,25 @@ fn track_diagnostic<R>(diagnostic: DiagInner, f: &mut dyn FnMut(DiagInner) -> R)
})
}
fn track_feature(feature: Symbol) {
tls::with_context_opt(|icx| {
let Some(icx) = icx else {
return;
};
let tcx = icx.tcx;
if let Some(dep_node_index) = tcx.sess.used_features.lock().get(&feature).copied() {
tcx.dep_graph.read_index(DepNodeIndex::from_u32(dep_node_index));
} else {
let dep_node_index = tcx
.dep_graph
.encode_side_effect(tcx, QuerySideEffect::CheckFeature { symbol: feature });
tcx.sess.used_features.lock().insert(feature, dep_node_index.as_u32());
tcx.dep_graph.read_index(dep_node_index);
}
})
}
/// This is a callback from `rustc_hir` as it cannot access the implicit state
/// in `rustc_middle` otherwise.
fn def_id_debug(def_id: rustc_hir::def_id::DefId, f: &mut fmt::Formatter<'_>) -> fmt::Result {
@@ -70,4 +90,5 @@ pub fn setup_callbacks() {
rustc_span::SPAN_TRACK.swap(&(track_span_parent as fn(_)));
rustc_hir::def_id::DEF_ID_DEBUG.swap(&(def_id_debug as fn(_, &mut fmt::Formatter<'_>) -> _));
rustc_errors::TRACK_DIAGNOSTIC.swap(&(track_diagnostic as _));
rustc_feature::TRACK_FEATURE.swap(&(track_feature as _));
}
-5
View File
@@ -1088,11 +1088,6 @@
/// crate-level [`feature` attributes].
///
/// [`feature` attributes]: https://doc.rust-lang.org/nightly/unstable-book/
///
/// Note: This lint is currently not functional, see [issue #44232] for
/// more details.
///
/// [issue #44232]: https://github.com/rust-lang/rust/issues/44232
pub UNUSED_FEATURES,
Warn,
"unused features found in crate-level `#[feature]` directives"
+48 -24
View File
@@ -17,6 +17,7 @@
use rustc_macros::{Decodable, Encodable};
use rustc_serialize::opaque::{FileEncodeResult, FileEncoder};
use rustc_session::Session;
use rustc_span::Symbol;
use tracing::{debug, instrument};
#[cfg(debug_assertions)]
use {super::debug::EdgeFilter, std::env};
@@ -45,6 +46,11 @@ pub enum QuerySideEffect {
/// the query as green, as that query will have the side
/// effect dep node as a dependency.
Diagnostic(DiagInner),
/// Records the feature used during query execution.
/// This feature will be inserted into `sess.used_features`
/// if we mark the query as green, as that query will have
/// the side effect dep node as a dependency.
CheckFeature { symbol: Symbol },
}
#[derive(Clone)]
pub struct DepGraph {
@@ -514,29 +520,40 @@ pub fn read_index(&self, dep_node_index: DepNodeIndex) {
}
}
/// This encodes a diagnostic by creating a node with an unique index and associating
/// `diagnostic` with it, for use in the next session.
/// This encodes a side effect by creating a node with an unique index and associating
/// it with the node, for use in the next session.
#[inline]
pub fn record_diagnostic<'tcx>(&self, tcx: TyCtxt<'tcx>, diagnostic: &DiagInner) {
if let Some(ref data) = self.data {
read_deps(|task_deps| match task_deps {
TaskDepsRef::EvalAlways | TaskDepsRef::Ignore => return,
TaskDepsRef::Forbid | TaskDepsRef::Allow(..) => {
self.read_index(data.encode_diagnostic(tcx, diagnostic));
let dep_node_index = data
.encode_side_effect(tcx, QuerySideEffect::Diagnostic(diagnostic.clone()));
self.read_index(dep_node_index);
}
})
}
}
/// This forces a diagnostic node green by running its side effect. `prev_index` would
/// refer to a node created used `encode_diagnostic` in the previous session.
/// This forces a side effect node green by running its side effect. `prev_index` would
/// refer to a node created used `encode_side_effect` in the previous session.
#[inline]
pub fn force_diagnostic_node<'tcx>(
pub fn force_side_effect<'tcx>(&self, tcx: TyCtxt<'tcx>, prev_index: SerializedDepNodeIndex) {
if let Some(ref data) = self.data {
data.force_side_effect(tcx, prev_index);
}
}
#[inline]
pub fn encode_side_effect<'tcx>(
&self,
tcx: TyCtxt<'tcx>,
prev_index: SerializedDepNodeIndex,
) {
side_effect: QuerySideEffect,
) -> DepNodeIndex {
if let Some(ref data) = self.data {
data.force_diagnostic_node(tcx, prev_index);
data.encode_side_effect(tcx, side_effect)
} else {
self.next_virtual_depnode_index()
}
}
@@ -673,10 +690,14 @@ pub fn mark_debug_loaded_from_disk(&self, dep_node: DepNode) {
self.debug_loaded_from_disk.lock().insert(dep_node);
}
/// This encodes a diagnostic by creating a node with an unique index and associating
/// `diagnostic` with it, for use in the next session.
/// This encodes a side effect by creating a node with an unique index and associating
/// it with the node, for use in the next session.
#[inline]
fn encode_diagnostic<'tcx>(&self, tcx: TyCtxt<'tcx>, diagnostic: &DiagInner) -> DepNodeIndex {
fn encode_side_effect<'tcx>(
&self,
tcx: TyCtxt<'tcx>,
side_effect: QuerySideEffect,
) -> DepNodeIndex {
// Use `send_new` so we get an unique index, even though the dep node is not.
let dep_node_index = self.current.encoder.send_new(
DepNode {
@@ -684,28 +705,21 @@ fn encode_diagnostic<'tcx>(&self, tcx: TyCtxt<'tcx>, diagnostic: &DiagInner) ->
key_fingerprint: PackedFingerprint::from(Fingerprint::ZERO),
},
Fingerprint::ZERO,
// We want the side effect node to always be red so it will be forced and emit the
// diagnostic.
// We want the side effect node to always be red so it will be forced and run the
// side effect.
std::iter::once(DepNodeIndex::FOREVER_RED_NODE).collect(),
);
let side_effect = QuerySideEffect::Diagnostic(diagnostic.clone());
tcx.store_side_effect(dep_node_index, side_effect);
dep_node_index
}
/// This forces a diagnostic node green by running its side effect. `prev_index` would
/// refer to a node created used `encode_diagnostic` in the previous session.
/// This forces a side effect node green by running its side effect. `prev_index` would
/// refer to a node created used `encode_side_effect` in the previous session.
#[inline]
fn force_diagnostic_node<'tcx>(&self, tcx: TyCtxt<'tcx>, prev_index: SerializedDepNodeIndex) {
fn force_side_effect<'tcx>(&self, tcx: TyCtxt<'tcx>, prev_index: SerializedDepNodeIndex) {
with_deps(TaskDepsRef::Ignore, || {
let side_effect = tcx.load_side_effect(prev_index).unwrap();
match &side_effect {
QuerySideEffect::Diagnostic(diagnostic) => {
tcx.dcx().emit_diagnostic(diagnostic.clone());
}
}
// Use `send_and_color` as `promote_node_and_deps_to_current` expects all
// green dependencies. `send_and_color` will also prevent multiple nodes
// being encoded for concurrent calls.
@@ -720,6 +734,16 @@ fn force_diagnostic_node<'tcx>(&self, tcx: TyCtxt<'tcx>, prev_index: SerializedD
std::iter::once(DepNodeIndex::FOREVER_RED_NODE).collect(),
true,
);
match &side_effect {
QuerySideEffect::Diagnostic(diagnostic) => {
tcx.dcx().emit_diagnostic(diagnostic.clone());
}
QuerySideEffect::CheckFeature { symbol } => {
tcx.sess.used_features.lock().insert(*symbol, dep_node_index.as_u32());
}
}
// This will just overwrite the same value for concurrent calls.
tcx.store_side_effect(dep_node_index, side_effect);
})
+31 -1
View File
@@ -36,7 +36,7 @@
use rustc_hir::intravisit::VisitorExt;
use rustc_hir::lang_items::LangItem;
use rustc_hir::limit::Limit;
use rustc_hir::{self as hir, HirId, Node, TraitCandidate, find_attr};
use rustc_hir::{self as hir, CRATE_HIR_ID, HirId, Node, TraitCandidate, find_attr};
use rustc_index::IndexVec;
use rustc_serialize::opaque::{FileEncodeResult, FileEncoder};
use rustc_session::Session;
@@ -1688,6 +1688,36 @@ pub fn finish(self) {
self.sess.dcx().emit_fatal(crate::error::FailedWritingFile { path: &path, error });
}
}
pub fn report_unused_features(self) {
// Collect first to avoid holding the lock while linting.
let used_features = self.sess.used_features.lock();
let unused_features = self
.features()
.enabled_features_iter_stable_order()
.filter(|(f, _)| {
!used_features.contains_key(f)
// FIXME: `restricted_std` is used to tell a standard library built
// for a platform that it doesn't know how to support. But it
// could only gate a private mod (see `__restricted_std_workaround`)
// with `cfg(not(restricted_std))`, so it cannot be recorded as used
// in downstream crates. It should never be linted, but should we
// hack this in the linter to ignore it?
&& f.as_str() != "restricted_std"
})
.collect::<Vec<_>>();
for (feature, span) in unused_features {
self.node_span_lint(
rustc_session::lint::builtin::UNUSED_FEATURES,
CRATE_HIR_ID,
span,
|lint| {
lint.primary_message(format!("feature `{}` is declared but not used", feature));
},
);
}
}
}
macro_rules! nop_lift {
@@ -40,7 +40,7 @@ pub(crate) fn SideEffect<'tcx>() -> DepKindVTable<'tcx> {
is_eval_always: false,
key_fingerprint_style: KeyFingerprintStyle::Unit,
force_from_dep_node_fn: Some(|tcx, _, prev_index| {
tcx.dep_graph.force_diagnostic_node(tcx, prev_index);
tcx.dep_graph.force_side_effect(tcx, prev_index);
true
}),
promote_from_disk_fn: None,
+6
View File
@@ -166,6 +166,11 @@ pub struct Session {
/// Used by `-Zmir-opt-bisect-limit` to assign an index to each
/// optimization-pass execution candidate during this compilation.
pub mir_opt_bisect_eval_count: AtomicUsize,
/// Enabled features that are used in the current compilation.
///
/// The value is the `DepNodeIndex` of the node encodes the used feature.
pub used_features: Lock<FxHashMap<Symbol, u32>>,
}
#[derive(Clone, Copy)]
@@ -1096,6 +1101,7 @@ pub fn build_session(
replaced_intrinsics: FxHashSet::default(), // filled by `run_compiler`
thin_lto_supported: true, // filled by `run_compiler`
mir_opt_bisect_eval_count: AtomicUsize::new(0),
used_features: Lock::default(),
};
validate_commandline_args_with_session_available(&sess);
-1
View File
@@ -1,6 +1,5 @@
#![feature(allocator_api)]
#![feature(binary_heap_pop_if)]
#![feature(btree_merge)]
#![feature(const_heap)]
#![feature(deque_extend_front)]
#![feature(iter_array_chunks)]
+5 -1
View File
@@ -1521,7 +1521,11 @@ pub const fn algebraic_rem(self, rhs: f16) -> f16 {
// Functions in this module fall into `core_float_math`
// #[unstable(feature = "core_float_math", issue = "137578")]
#[cfg(not(test))]
#[doc(test(attr(feature(cfg_target_has_reliable_f16_f128), expect(internal_features))))]
#[doc(test(attr(
feature(cfg_target_has_reliable_f16_f128),
expect(internal_features),
allow(unused_features)
)))]
impl f16 {
/// Returns the largest integer less than or equal to `self`.
///
+1
View File
@@ -393,6 +393,7 @@ pub mod consts {
pub const LN_10: f32 = 2.30258509299404568401799145468436421_f32;
}
#[doc(test(attr(allow(unused_features))))]
impl f32 {
/// The radix or base of the internal representation of `f32`.
#[stable(feature = "assoc_int_consts", since = "1.43.0")]
+1
View File
@@ -393,6 +393,7 @@ pub mod consts {
pub const LN_10: f64 = 2.30258509299404568401799145468436421_f64;
}
#[doc(test(attr(allow(unused_features))))]
impl f64 {
/// The radix or base of the internal representation of `f64`.
#[stable(feature = "assoc_int_consts", since = "1.43.0")]
-1
View File
@@ -50,7 +50,6 @@
#![feature(f16)]
#![feature(f128)]
#![feature(float_algebraic)]
#![feature(float_bits_const)]
#![feature(float_exact_integer_constants)]
#![feature(float_gamma)]
#![feature(float_minimum_maximum)]
+1
View File
@@ -16,6 +16,7 @@
use crate::sys::cmath;
#[cfg(not(test))]
#[doc(test(attr(allow(unused_features))))]
impl f16 {
/// Raises a number to a floating point power.
///
+2
View File
@@ -1381,6 +1381,7 @@ impl Output {
/// # Examples
///
/// ```
/// # #![allow(unused_features)]
/// #![feature(exit_status_error)]
/// # #[cfg(all(unix, not(target_os = "android"), not(all(target_vendor = "apple", not(target_os = "macos")))))] {
/// use std::process::Command;
@@ -1960,6 +1961,7 @@ impl crate::sealed::Sealed for ExitStatusError {}
pub struct ExitStatusError(imp::ExitStatusError);
#[unstable(feature = "exit_status_error", issue = "84908")]
#[doc(test(attr(allow(unused_features))))]
impl ExitStatusError {
/// Reports the exit code, if applicable, from an `ExitStatusError`.
///
+2
View File
@@ -43,6 +43,8 @@
clippy::collapsible_match,
// We are not implementing queries here so it's fine
rustc::potential_query_instability,
// FIXME: Unused features should be removed in the future
unused_features,
)]
#![warn(
rust_2018_idioms,
@@ -10,7 +10,7 @@
feature = "sysroot-abi",
feature(proc_macro_internals, proc_macro_diagnostic, proc_macro_span)
)]
#![allow(internal_features)]
#![allow(internal_features, unused_features)]
#![cfg_attr(feature = "in-rust-tree", feature(rustc_private))]
#[cfg(feature = "in-rust-tree")]
@@ -18,7 +18,8 @@
internal_features,
clippy::disallowed_types,
clippy::print_stderr,
unused_crate_dependencies
unused_crate_dependencies,
unused_features
)]
#![deny(deprecated_safe, clippy::undocumented_unsafe_blocks)]
+1 -1
View File
@@ -1,5 +1,5 @@
#![feature(f16)]
#![feature(cfg_target_has_reliable_f16_f128)]
#![cfg_attr(target_has_reliable_f16, feature(f16))]
#![expect(internal_features)] // reliable_f16_f128
mod traits;
@@ -9,7 +9,6 @@
//@ ignore-backends: gcc
#![feature(rustc_attrs)]
#![feature(stmt_expr_attributes)]
#![allow(dead_code)]
#![crate_type = "rlib"]
@@ -9,7 +9,6 @@
//@ ignore-backends: gcc
#![feature(rustc_attrs)]
#![feature(stmt_expr_attributes)]
#![allow(dead_code)]
#![crate_type = "rlib"]
+1 -1
View File
@@ -8,7 +8,7 @@
//@ build-pass (FIXME(62277): could be check-pass?)
//@ ignore-backends: gcc
#![feature(panic_unwind)]
#![cfg_attr(cfail1, feature(panic_unwind))]
// Turn the panic_unwind crate from an explicit into an implicit query:
#[cfg(cfail1)]
@@ -7,7 +7,6 @@
//@ ignore-backends: gcc
#![feature(rustc_attrs)]
#![feature(stmt_expr_attributes)]
#![allow(dead_code)]
#![crate_type = "rlib"]
@@ -9,7 +9,6 @@
#![crate_type = "rlib"]
#![feature(rustc_attrs)]
#![feature(stmt_expr_attributes)]
#![allow(dead_code)]
#![rustc_partition_reused(module="struct_point-fn_calls_methods_in_same_impl", cfg="cfail2")]
@@ -7,7 +7,6 @@
//@ ignore-backends: gcc
#![feature(rustc_attrs)]
#![feature(stmt_expr_attributes)]
#![allow(dead_code)]
#![crate_type = "rlib"]
@@ -9,7 +9,6 @@
#![crate_type = "rlib"]
#![feature(rustc_attrs)]
#![feature(stmt_expr_attributes)]
#![allow(dead_code)]
#![rustc_partition_reused(module="struct_point-fn_read_field", cfg="cfail2")]
@@ -7,7 +7,6 @@
#![crate_type = "rlib"]
#![feature(rustc_attrs)]
#![feature(stmt_expr_attributes)]
#![allow(dead_code)]
#![rustc_partition_codegened(module="struct_point-point", cfg="cfail2")]
@@ -7,7 +7,6 @@
#![crate_type = "rlib"]
#![feature(rustc_attrs)]
#![feature(stmt_expr_attributes)]
#![allow(dead_code)]
// These are expected to require codegen.
+41
View File
@@ -0,0 +1,41 @@
//@ revisions: rpass cfail
//@ ignore-backends: gcc
#![deny(unused_features)]
// Used language features
#![feature(box_patterns)]
#![feature(decl_macro)]
#![cfg_attr(all(), feature(rustc_attrs))]
// Used library features
#![feature(error_iter)]
//[cfail]~^ ERROR feature `error_iter` is declared but not used
#![cfg_attr(all(), feature(allocator_api))]
//[cfail]~^ ERROR feature `allocator_api` is declared but not used
pub fn use_box_patterns(b: Box<i32>) -> i32 {
let box x = b;
x
}
macro m() {}
pub fn use_decl_macro() {
m!();
}
#[rustc_dummy]
pub fn use_rustc_attrs() {}
#[cfg(rpass)]
pub fn use_error_iter(e: &(dyn std::error::Error + 'static)) {
for _ in e.sources() {}
}
#[cfg(rpass)]
pub fn use_allocator_api() {
use std::alloc::Global;
let _ = Vec::<i32>::new_in(Global);
}
fn main() {}
@@ -6,7 +6,6 @@
//@ ignore-remote
#![feature(rustc_private)]
#![feature(ascii_char, ascii_char_variants)]
extern crate rustc_driver;
extern crate rustc_hir;
@@ -6,7 +6,6 @@
//@ ignore-remote
#![feature(rustc_private)]
#![feature(ascii_char, ascii_char_variants)]
extern crate rustc_hir;
extern crate rustc_middle;
-1
View File
@@ -5,7 +5,6 @@
//@ aux-build:helper.rs
//@ no-prefer-dynamic
#![feature(allocator_api)]
extern crate custom;
extern crate custom_as_global;
@@ -9,7 +9,6 @@
// for `ByRef`. The right answer was to consider the result ambiguous
// until more type information was available.
#![feature(lang_items)]
#![no_implicit_prelude]
use std::marker::Sized;
@@ -8,7 +8,6 @@
// for `ByRef`. The right answer was to consider the result ambiguous
// until more type information was available.
#![feature(lang_items)]
#![no_implicit_prelude]
use std::marker::Sized;
@@ -5,7 +5,7 @@
// please consider modifying miri's async drop test at
// `src/tools/miri/tests/pass/async-drop.rs`.
#![feature(async_drop, impl_trait_in_assoc_type)]
#![feature(async_drop)]
#![allow(incomplete_features, dead_code)]
//@ edition: 2021
-1
View File
@@ -18,7 +18,6 @@
//@ needs-unwind
//@ aux-build: line-tables-only-helper.rs
#![feature(backtrace_frames)]
extern crate line_tables_only_helper;
@@ -7,7 +7,7 @@
//@ [borrowck] check-fail
#![allow(dropping_references)]
#![feature(super_let, stmt_expr_attributes)]
#![feature(super_let)]
use std::convert::identity;
-1
View File
@@ -3,7 +3,6 @@
#![allow(unused_mut)]
#![allow(unused_variables)]
#![deny(non_snake_case)]
#![feature(stmt_expr_attributes)]
fn main() {
let a = 413;
-1
View File
@@ -1,6 +1,5 @@
//@ run-pass
#![feature(generic_const_exprs)]
#![feature(transmute_generic_consts)]
#![allow(incomplete_features)]
fn ident<const W: usize, const H: usize>(v: [[u32; H]; W]) -> [[u32; H]; W] {
-1
View File
@@ -1,7 +1,6 @@
//@ run-pass
#![feature(core_intrinsics)]
#![feature(const_type_name)]
#![allow(dead_code)]
const fn type_name_wrapper<T>(_: &T) -> &'static str {
+1 -1
View File
@@ -1,6 +1,6 @@
//@ run-pass
#![feature(ptr_internals, test)]
#![feature(test)]
extern crate test;
use test::black_box as b; // prevent promotion of the argument and const-propagation of the result
-1
View File
@@ -1,7 +1,6 @@
//@ ignore-backends: gcc
//@ run-pass
#![feature(try_trait_v2)]
#![feature(const_trait_impl)]
#![feature(const_try)]
@@ -1,6 +1,6 @@
//@ run-pass
#![expect(incomplete_features)]
#![feature(contracts, cfg_contract_checks, contracts_internals, core_intrinsics)]
#![feature(contracts, contracts_internals, core_intrinsics)]
extern crate core;
+1 -1
View File
@@ -3,7 +3,7 @@
//@ revisions: default nomiropt
//@[nomiropt]compile-flags: -Z mir-opt-level=0
#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
#![feature(coroutines, coroutine_trait)]
use std::ops::{CoroutineState, Coroutine};
use std::pin::Pin;
@@ -1,6 +1,6 @@
//@ run-rustfix
#![feature(coroutines, gen_blocks, stmt_expr_attributes)]
#![feature(coroutines, stmt_expr_attributes)]
fn main() {
let _ = #[coroutine] || yield;
@@ -1,6 +1,6 @@
//@ run-rustfix
#![feature(coroutines, gen_blocks, stmt_expr_attributes)]
#![feature(coroutines, stmt_expr_attributes)]
fn main() {
let _ = || yield;
+1 -1
View File
@@ -3,7 +3,7 @@
//@[next] compile-flags: -Znext-solver
//@ run-pass
#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
#![feature(coroutines)]
#![allow(dropping_copy_types)]
use std::marker::PhantomPinned;
@@ -2,7 +2,6 @@
//@ run-pass
#![feature(gen_blocks)]
#![feature(optimize_attribute)]
#![feature(stmt_expr_attributes)]
#![feature(async_iterator)]
#![allow(dead_code)]
+1 -1
View File
@@ -1,6 +1,6 @@
//@ run-pass
#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
#![feature(coroutines, coroutine_trait)]
use std::ops::Coroutine;
+1 -1
View File
@@ -2,7 +2,7 @@
//@ aux-build:xcrate.rs
#![feature(coroutines, coroutine_trait)]
#![feature(coroutine_trait)]
extern crate xcrate;
-1
View File
@@ -7,7 +7,6 @@
//@ ignore-windows
// Tests EIIs with default implementations.
// When there's no explicit declaration, the default should be called from the declaring crate.
#![feature(extern_item_impls)]
extern crate decl_with_default;
@@ -23,7 +23,6 @@
// ```
// This is a simple test to make sure that we can unwind through these,
// and that this wrapper function effectively doesn't show up in the trace.
#![feature(extern_item_impls)]
extern crate decl_with_default_panics;
-1
View File
@@ -9,7 +9,6 @@
// Tests EIIs with default implementations.
// When an explicit implementation is given in one dependency, and the declaration is in another,
// the explicit implementation is preferred.
#![feature(extern_item_impls)]
extern crate decl_with_default;
extern crate impl1;
@@ -6,7 +6,6 @@
// FIXME: linking on windows (speciifcally mingw) not yet supported, see tracking issue #125418
//@ ignore-windows
// Tests whether calling EIIs works with the declaration in another crate.
#![feature(extern_item_impls)]
extern crate codegen_cross_crate_other_crate as codegen;
-1
View File
@@ -5,7 +5,6 @@
// FIXME: linking on windows (specifically mingw) not yet supported, see tracking issue #125418
//@ ignore-windows
// Tests whether re-exports work.
#![feature(extern_item_impls)]
extern crate other_crate_privacy1 as codegen;
-1
View File
@@ -1,5 +1,4 @@
//@ run-pass
#![feature(lang_items)]
#![no_std]
extern crate std as other;
@@ -22,7 +22,6 @@
//@ [future_feature] compile-flags: -Z unstable-options
#![cfg_attr(future_feature, feature(explicit_extern_abis))]
#![cfg_attr(current_feature, feature(explicit_extern_abis))]
extern "C" fn _foo() {}
//[current]~^ WARN `extern` declarations without an explicit ABI are deprecated
@@ -1,5 +1,5 @@
warning: `extern` declarations without an explicit ABI are deprecated
--> $DIR/feature-gate-explicit-extern-abis.rs:27:1
--> $DIR/feature-gate-explicit-extern-abis.rs:26:1
|
LL | extern fn _foo() {}
| ^^^^^^ help: explicitly specify the "C" ABI: `extern "C"`
@@ -7,13 +7,13 @@ LL | extern fn _foo() {}
= note: `#[warn(missing_abi)]` on by default
warning: `extern` declarations without an explicit ABI are deprecated
--> $DIR/feature-gate-explicit-extern-abis.rs:33:8
--> $DIR/feature-gate-explicit-extern-abis.rs:32:8
|
LL | unsafe extern fn _bar() {}
| ^^^^^^ help: explicitly specify the "C" ABI: `extern "C"`
warning: `extern` declarations without an explicit ABI are deprecated
--> $DIR/feature-gate-explicit-extern-abis.rs:39:8
--> $DIR/feature-gate-explicit-extern-abis.rs:38:8
|
LL | unsafe extern {}
| ^^^^^^ help: explicitly specify the "C" ABI: `extern "C"`
@@ -22,7 +22,6 @@
//@ [future_feature] compile-flags: -Z unstable-options
#![cfg_attr(future_feature, feature(explicit_extern_abis))]
#![cfg_attr(current_feature, feature(explicit_extern_abis))]
extern "C" fn _foo() {}
//[current]~^ WARN `extern` declarations without an explicit ABI are deprecated
@@ -1,5 +1,5 @@
warning: `extern` declarations without an explicit ABI are deprecated
--> $DIR/feature-gate-explicit-extern-abis.rs:27:1
--> $DIR/feature-gate-explicit-extern-abis.rs:26:1
|
LL | extern fn _foo() {}
| ^^^^^^ help: explicitly specify the "C" ABI: `extern "C"`
@@ -7,13 +7,13 @@ LL | extern fn _foo() {}
= note: `#[warn(missing_abi)]` on by default
warning: `extern` declarations without an explicit ABI are deprecated
--> $DIR/feature-gate-explicit-extern-abis.rs:33:8
--> $DIR/feature-gate-explicit-extern-abis.rs:32:8
|
LL | unsafe extern fn _bar() {}
| ^^^^^^ help: explicitly specify the "C" ABI: `extern "C"`
warning: `extern` declarations without an explicit ABI are deprecated
--> $DIR/feature-gate-explicit-extern-abis.rs:39:8
--> $DIR/feature-gate-explicit-extern-abis.rs:38:8
|
LL | unsafe extern {}
| ^^^^^^ help: explicitly specify the "C" ABI: `extern "C"`
@@ -22,7 +22,6 @@
//@ [future_feature] compile-flags: -Z unstable-options
#![cfg_attr(future_feature, feature(explicit_extern_abis))]
#![cfg_attr(current_feature, feature(explicit_extern_abis))]
extern "C" fn _foo() {}
//[current]~^ WARN `extern` declarations without an explicit ABI are deprecated
@@ -1,5 +1,5 @@
warning: `extern` declarations without an explicit ABI are deprecated
--> $DIR/feature-gate-explicit-extern-abis.rs:27:1
--> $DIR/feature-gate-explicit-extern-abis.rs:26:1
|
LL | extern fn _foo() {}
| ^^^^^^ help: explicitly specify the "C" ABI: `extern "C"`
@@ -7,13 +7,13 @@ LL | extern fn _foo() {}
= note: `#[warn(missing_abi)]` on by default
warning: `extern` declarations without an explicit ABI are deprecated
--> $DIR/feature-gate-explicit-extern-abis.rs:33:8
--> $DIR/feature-gate-explicit-extern-abis.rs:32:8
|
LL | unsafe extern fn _bar() {}
| ^^^^^^ help: explicitly specify the "C" ABI: `extern "C"`
warning: `extern` declarations without an explicit ABI are deprecated
--> $DIR/feature-gate-explicit-extern-abis.rs:39:8
--> $DIR/feature-gate-explicit-extern-abis.rs:38:8
|
LL | unsafe extern {}
| ^^^^^^ help: explicitly specify the "C" ABI: `extern "C"`
@@ -1,5 +1,5 @@
error: `extern` declarations without an explicit ABI are disallowed
--> $DIR/feature-gate-explicit-extern-abis.rs:27:1
--> $DIR/feature-gate-explicit-extern-abis.rs:26:1
|
LL | extern fn _foo() {}
| ^^^^^^ help: specify an ABI: `extern "<abi>"`
@@ -7,7 +7,7 @@ LL | extern fn _foo() {}
= help: prior to Rust 2024, a default ABI was inferred
error: `extern` declarations without an explicit ABI are disallowed
--> $DIR/feature-gate-explicit-extern-abis.rs:33:8
--> $DIR/feature-gate-explicit-extern-abis.rs:32:8
|
LL | unsafe extern fn _bar() {}
| ^^^^^^ help: specify an ABI: `extern "<abi>"`
@@ -15,7 +15,7 @@ LL | unsafe extern fn _bar() {}
= help: prior to Rust 2024, a default ABI was inferred
error: `extern` declarations without an explicit ABI are disallowed
--> $DIR/feature-gate-explicit-extern-abis.rs:39:8
--> $DIR/feature-gate-explicit-extern-abis.rs:38:8
|
LL | unsafe extern {}
| ^^^^^^ help: specify an ABI: `extern "<abi>"`
@@ -22,7 +22,6 @@
//@ [future_feature] compile-flags: -Z unstable-options
#![cfg_attr(future_feature, feature(explicit_extern_abis))]
#![cfg_attr(current_feature, feature(explicit_extern_abis))]
extern fn _foo() {}
//[current]~^ WARN `extern` declarations without an explicit ABI are deprecated
-2
View File
@@ -6,8 +6,6 @@
// This tests the float classification functions, for regular runtime code and for const evaluation.
#![feature(f16)]
#![feature(f128)]
use std::num::FpCategory::*;
+3 -2
View File
@@ -3,9 +3,10 @@
// This tests the float classification functions, for regular runtime code and for const evaluation.
#![feature(f16)]
#![feature(f128)]
#![feature(cfg_target_has_reliable_f16_f128)]
#![cfg_attr(target_has_reliable_f16, feature(f16))]
#![cfg_attr(target_has_reliable_f128, feature(f128))]
#![allow(unused_macro_rules)]
// expect the unexpected (`target_has_reliable_*` are not "known" configs since they are unstable)
#![expect(unexpected_cfgs)]
-1
View File
@@ -4,7 +4,6 @@
//@ ignore-emscripten no no_std executables
//@ ignore-wasm different `main` convention
#![feature(lang_items)]
#![no_std]
#![no_main]
@@ -6,8 +6,8 @@
#![allow(unreachable_patterns)]
#![feature(cfg_target_has_reliable_f16_f128)]
#![feature(f128)]
#![feature(f16)]
#![cfg_attr(target_has_reliable_f16, feature(f16))]
#![cfg_attr(target_has_reliable_f128, feature(f128))]
macro_rules! yes {
($scrutinee:expr, $($t:tt)+) => {
-1
View File
@@ -3,7 +3,6 @@
//@ aux-build:xcrate.rs
#![feature(decl_macro)]
extern crate xcrate;
+1 -2
View File
@@ -1,7 +1,6 @@
//@ run-pass
#![feature(fn_traits,
step_trait,
#![feature(step_trait,
unboxed_closures,
)]
+1 -1
View File
@@ -1,6 +1,6 @@
//@ run-pass
#![feature(core_intrinsics, rustc_attrs)]
#![feature(rustc_attrs)]
#[cfg(any(
target_os = "aix",
-1
View File
@@ -4,7 +4,6 @@
//@ run-pass
//@ needs-unwind
#![feature(io_error_uncategorized)]
use std::fmt;
use std::io::{self, Error, Write};
@@ -15,7 +15,7 @@
#![allow(incomplete_features)]
#![feature(raw_dylib_elf)]
#![feature(native_link_modifiers_as_needed)]
#![cfg_attr(not(no_modifier), feature(native_link_modifiers_as_needed))]
#[cfg_attr(
as_needed,
@@ -1,6 +1,5 @@
//@ run-pass
#![feature(stmt_expr_attributes)]
#![deny(unused_parens)]
// Tests that lint attributes on statements/expressions are
-1
View File
@@ -4,6 +4,5 @@
#![allow(stable_features)]
// FIXME(#44232) we should warn that this isn't used.
#![feature(rust1)]
fn main() {}
@@ -2,7 +2,7 @@
//@ edition:2021
#![deny(unused_qualifications)]
#![deny(unused_imports)]
#![feature(coroutines, coroutine_trait)]
#![feature(coroutine_trait)]
use std::ops::{
Coroutine,
@@ -2,7 +2,7 @@
//@ edition:2021
#![deny(unused_qualifications)]
#![deny(unused_imports)]
#![feature(coroutines, coroutine_trait)]
#![feature(coroutine_trait)]
use std::ops::{
Coroutine,
@@ -0,0 +1,25 @@
#![crate_type = "lib"]
#![deny(unused_features)]
// Unused language features
#![feature(coroutines)]
//~^ ERROR feature `coroutines` is declared but not used
#![feature(coroutine_clone)]
//~^ ERROR feature `coroutine_clone` is declared but not used
#![feature(stmt_expr_attributes)]
//~^ ERROR feature `stmt_expr_attributes` is declared but not used
#![feature(asm_unwind)]
//~^ ERROR feature `asm_unwind` is declared but not used
// Enabled via cfg_attr, unused
#![cfg_attr(all(), feature(negative_impls))]
//~^ ERROR feature `negative_impls` is declared but not used
// Not enabled via cfg_attr, so should not warn even if unused
#![cfg_attr(any(), feature(never_type))]
macro_rules! use_asm_unwind {
() => {
unsafe { std::arch::asm!("", options(may_unwind)) };
}
}
@@ -0,0 +1,38 @@
error: feature `coroutines` is declared but not used
--> $DIR/unused-language-features.rs:5:12
|
LL | #![feature(coroutines)]
| ^^^^^^^^^^
|
note: the lint level is defined here
--> $DIR/unused-language-features.rs:2:9
|
LL | #![deny(unused_features)]
| ^^^^^^^^^^^^^^^
error: feature `coroutine_clone` is declared but not used
--> $DIR/unused-language-features.rs:7:12
|
LL | #![feature(coroutine_clone)]
| ^^^^^^^^^^^^^^^
error: feature `stmt_expr_attributes` is declared but not used
--> $DIR/unused-language-features.rs:9:12
|
LL | #![feature(stmt_expr_attributes)]
| ^^^^^^^^^^^^^^^^^^^^
error: feature `asm_unwind` is declared but not used
--> $DIR/unused-language-features.rs:11:12
|
LL | #![feature(asm_unwind)]
| ^^^^^^^^^^
error: feature `negative_impls` is declared but not used
--> $DIR/unused-language-features.rs:15:28
|
LL | #![cfg_attr(all(), feature(negative_impls))]
| ^^^^^^^^^^^^^^
error: aborting due to 5 previous errors
@@ -0,0 +1,13 @@
#![crate_type = "lib"]
#![deny(unused_features)]
// Unused library features
#![feature(step_trait)]
//~^ ERROR feature `step_trait` is declared but not used
#![feature(is_sorted)]
//~^ ERROR feature `is_sorted` is declared but not used
//~^^ WARN the feature `is_sorted` has been stable since 1.82.0 and no longer requires an attribute to enable
// Enabled via cfg_attr, unused
#![cfg_attr(all(), feature(slice_ptr_get))]
//~^ ERROR feature `slice_ptr_get` is declared but not used
@@ -0,0 +1,34 @@
warning: the feature `is_sorted` has been stable since 1.82.0 and no longer requires an attribute to enable
--> $DIR/unused-library-features.rs:7:12
|
LL | #![feature(is_sorted)]
| ^^^^^^^^^
|
= note: `#[warn(stable_features)]` on by default
error: feature `step_trait` is declared but not used
--> $DIR/unused-library-features.rs:5:12
|
LL | #![feature(step_trait)]
| ^^^^^^^^^^
|
note: the lint level is defined here
--> $DIR/unused-library-features.rs:2:9
|
LL | #![deny(unused_features)]
| ^^^^^^^^^^^^^^^
error: feature `is_sorted` is declared but not used
--> $DIR/unused-library-features.rs:7:12
|
LL | #![feature(is_sorted)]
| ^^^^^^^^^
error: feature `slice_ptr_get` is declared but not used
--> $DIR/unused-library-features.rs:12:28
|
LL | #![cfg_attr(all(), feature(slice_ptr_get))]
| ^^^^^^^^^^^^^
error: aborting due to 3 previous errors; 1 warning emitted
@@ -0,0 +1,22 @@
//@ check-pass
#![crate_type = "lib"]
#![deny(unused_features)]
// Used language features
#![feature(box_patterns)]
#![feature(decl_macro)]
#![cfg_attr(all(), feature(rustc_attrs))]
pub fn use_box_patterns(b: Box<i32>) -> i32 {
let box x = b;
x
}
macro m() {}
pub fn use_decl_macro() {
m!();
}
#[rustc_dummy]
pub fn use_rustc_attrs() {}
@@ -0,0 +1,17 @@
//@ check-pass
#![crate_type = "lib"]
#![deny(unused_features)]
// Used library features
#![feature(error_iter)]
#![cfg_attr(all(), feature(allocator_api))]
pub fn use_error_iter(e: &(dyn std::error::Error + 'static)) {
for _ in e.sources() {}
}
pub fn use_allocator_api() {
use std::alloc::Global;
let _ = Vec::<i32>::new_in(Global);
}
@@ -1,6 +1,6 @@
//@ run-rustfix
#![allow(dead_code, path_statements)]
#![allow(dead_code, path_statements, unused_features)]
#![deny(unused_attributes, unused_must_use)]
#![feature(asm_experimental_arch, stmt_expr_attributes, trait_alias)]
@@ -1,6 +1,6 @@
//@ run-rustfix
#![allow(dead_code, path_statements)]
#![allow(dead_code, path_statements, unused_features)]
#![deny(unused_attributes, unused_must_use)]
#![feature(asm_experimental_arch, stmt_expr_attributes, trait_alias)]
-1
View File
@@ -3,7 +3,6 @@
// Test that this doesn't abort during AST lowering. In #96847 it did abort
// because the attribute was being lowered twice.
#![feature(stmt_expr_attributes)]
#![feature(lang_items)]
fn main() {
+1 -1
View File
@@ -1,5 +1,5 @@
error[E0522]: definition of an unknown lang item: `foo`
--> $DIR/issue-96847.rs:11:9
--> $DIR/issue-96847.rs:10:9
|
LL | #![lang="foo"]
| ^^^^^^^^^^^^^^ definition of unknown lang item `foo`
@@ -6,7 +6,6 @@
// This test captures the behavior of macro-generating-macros with fragment
// specifiers across edition boundaries.
#![feature(macro_metavar_expr)]
#![allow(incomplete_features)]
extern crate metavar_2018;
@@ -5,7 +5,7 @@
//@ needs-unwind Asserting on contents of error message
#![allow(path_statements, unused_allocation)]
#![feature(core_intrinsics, generic_assert)]
#![feature(generic_assert)]
macro_rules! test {
(
@@ -4,7 +4,7 @@
//@ run-pass
//@ needs-unwind Asserting on contents of error message
#![feature(core_intrinsics, generic_assert)]
#![feature(generic_assert)]
extern crate common;
@@ -3,7 +3,6 @@
//@ compile-flags: --test -Zpanic_abort_tests
//@ run-pass
#![feature(core_intrinsics, generic_assert)]
#[should_panic(expected = "Custom user message")]
#[test]
@@ -3,7 +3,7 @@
//@ run-pass
//@ needs-unwind Asserting on contents of error message
#![feature(core_intrinsics, generic_assert)]
#![feature(generic_assert)]
extern crate common;
@@ -4,7 +4,7 @@
// ignore-tidy-linelength
//@ run-pass
#![feature(core_intrinsics, generic_assert)]
#![feature(generic_assert)]
use std::fmt::{Debug, Formatter};
-2
View File
@@ -9,12 +9,10 @@
#![feature(const_trait_impl)]
#![feature(coroutines)]
#![feature(decl_macro)]
#![feature(explicit_tail_calls)]
#![feature(more_qualified_paths)]
#![feature(never_patterns)]
#![feature(trait_alias)]
#![feature(try_blocks)]
#![feature(type_ascription)]
#![feature(yeet_expr)]
#![deny(unused_macros)]
+2 -2
View File
@@ -3,8 +3,8 @@
// Makes sure we use `==` (not bitwise) semantics for float comparison.
#![feature(cfg_target_has_reliable_f16_f128)]
#![feature(f128)]
#![feature(f16)]
#![cfg_attr(target_has_reliable_f16, feature(f16))]
#![cfg_attr(target_has_reliable_f128, feature(f128))]
#[cfg(target_has_reliable_f16)]
fn check_f16() {
@@ -1,7 +1,6 @@
//@ run-pass
//@ check-run-results
#![feature(supertrait_item_shadowing)]
#![allow(dead_code)]
mod out_of_scope {
+1 -1
View File
@@ -2,7 +2,7 @@
#![allow(path_statements)]
#![allow(dead_code)]
#![feature(coroutines, coroutine_trait)]
#![feature(coroutines)]
struct WithDrop;

Some files were not shown because too many files have changed in this diff Show More