Skip to content
Open
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
4 changes: 3 additions & 1 deletion compiler/rustc_error_codes/src/error_codes/E0636.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
#### Note: this error code is no longer emitted by the compiler.

The same feature is enabled multiple times with `#![feature]` attributes

Erroneous code example:

```compile_fail,E0636
```
#![allow(stable_features)]
#![feature(rust1)]
#![feature(rust1)] // error: the feature `rust1` has already been enabled
Expand Down
11 changes: 11 additions & 0 deletions compiler/rustc_lint_defs/src/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ declare_lint_pass! {
DEPRECATED_IN_FUTURE,
DEPRECATED_SAFE_2024,
DEPRECATED_WHERE_CLAUSE_LOCATION,
DUPLICATE_FEATURES,
DUPLICATE_MACRO_ATTRIBUTES,
ELIDED_LIFETIMES_IN_ASSOCIATED_CONSTANT,
ELIDED_LIFETIMES_IN_PATHS,
Expand Down Expand Up @@ -1098,6 +1099,16 @@ declare_lint! {
"unused features found in crate-level `#[feature]` directives"
}

declare_lint! {
/// The `duplicate_features` lint detects duplicate features found in
/// crate-level [`feature` attributes].
///
/// [`feature` attributes]: https://doc.rust-lang.org/nightly/unstable-book/
pub DUPLICATE_FEATURES,
Warn,
"duplicate features found in crate-level `#[feature]` directives"
}

declare_lint! {
/// The `stable_features` lint detects a [`feature` attribute] that
/// has since been made stable.
Expand Down
14 changes: 6 additions & 8 deletions compiler/rustc_passes/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1012,14 +1012,6 @@ pub(crate) struct ImpliedFeatureNotExist {
pub implied_by: Symbol,
}

#[derive(Diagnostic)]
#[diag("the feature `{$feature}` has already been enabled", code = E0636)]
pub(crate) struct DuplicateFeatureErr {
#[primary_span]
pub span: Span,
pub feature: Symbol,
}

#[derive(Diagnostic)]
#[diag(
"attributes `#[rustc_const_unstable]`, `#[rustc_const_stable]` and `#[rustc_const_stable_indirect]` require the function or method to be `const`"
Expand Down Expand Up @@ -1169,6 +1161,12 @@ pub(crate) struct ProcMacroBadSig {
pub kind: ProcMacroKind,
}

#[derive(LintDiagnostic)]
#[diag("the feature `{$feature}` has already been enabled")]
pub(crate) struct DuplicateFeature {
pub feature: Symbol,
}

#[derive(LintDiagnostic)]
#[diag(
"the feature `{$feature}` has been stable since {$since} and no longer requires an attribute to enable"
Expand Down
13 changes: 11 additions & 2 deletions compiler/rustc_passes/src/stability.rs
Original file line number Diff line number Diff line change
Expand Up @@ -969,7 +969,7 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) {
}
if !lang_features.insert(gate_name) {
// Warn if the user enables a lang feature multiple times.
tcx.dcx().emit_err(errors::DuplicateFeatureErr { span: *attr_sp, feature: *gate_name });
duplicate_feature_lint(tcx, *attr_sp, *gate_name);
}
}

Expand All @@ -978,7 +978,7 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) {
for EnabledLibFeature { gate_name, attr_sp } in enabled_lib_features {
if remaining_lib_features.contains_key(gate_name) {
// Warn if the user enables a lib feature multiple times.
tcx.dcx().emit_err(errors::DuplicateFeatureErr { span: *attr_sp, feature: *gate_name });
duplicate_feature_lint(tcx, *attr_sp, *gate_name);
}
remaining_lib_features.insert(*gate_name, *attr_sp);
}
Expand Down Expand Up @@ -1160,3 +1160,12 @@ fn unnecessary_stable_feature_lint(
errors::UnnecessaryStableFeature { feature, since },
);
}

fn duplicate_feature_lint(tcx: TyCtxt<'_>, span: Span, feature: Symbol) {
tcx.emit_node_span_lint(
lint::builtin::DUPLICATE_FEATURES,
hir::CRATE_HIR_ID,
span,
errors::DuplicateFeature { feature },
);
}
1 change: 1 addition & 0 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1073,6 +1073,7 @@ symbols! {
include_bytes,
include_str,
inclusive_range_syntax,
incomplete_features,
index,
index_mut,
infer_outlives_requirements,
Expand Down
2 changes: 1 addition & 1 deletion library/alloc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@
#![doc(
html_playground_url = "https://play.rust-lang.org/",
issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/",
test(no_crate_inject, attr(allow(unused_variables), deny(warnings)))
test(no_crate_inject, attr(allow(unused_variables, duplicate_features), deny(warnings)))
)]
#![doc(auto_cfg(hide(no_global_oom_handling, no_rc, no_sync, target_has_atomic = "ptr")))]
#![doc(rust_logo)]
Expand Down
2 changes: 1 addition & 1 deletion library/core/src/alloc/global.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use crate::{cmp, ptr};
///
/// # Example
///
/// ```
/// ```standalone_crate
/// use std::alloc::{GlobalAlloc, Layout};
/// use std::cell::UnsafeCell;
/// use std::ptr::null_mut;
Expand Down
2 changes: 1 addition & 1 deletion library/core/src/hint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -514,7 +514,7 @@ pub const fn black_box<T>(dummy: T) -> T {
/// macro_rules! make_error {
/// ($($args:expr),*) => {
/// core::hint::must_use({
/// let error = $crate::make_error(core::format_args!($($args),*));
/// let error = make_error(core::format_args!($($args),*));
/// error
/// })
/// };
Expand Down
4 changes: 3 additions & 1 deletion library/core/src/intrinsics/mir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,9 @@
//!
//! # Examples
//!
//! ```rust
#![cfg_attr(panic = "unwind", doc = "```rust")]
// This test can't support panic=abort because it generates an UnwindContinue MIR terminator.
#![cfg_attr(panic = "abort", doc = "```ignore")]
//! #![feature(core_intrinsics, custom_mir)]
//! #![allow(internal_features)]
//! #![allow(unused_assignments)]
Expand Down
2 changes: 1 addition & 1 deletion library/core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
html_playground_url = "https://play.rust-lang.org/",
issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/",
test(no_crate_inject, attr(deny(warnings))),
test(attr(allow(dead_code, deprecated, unused_variables, unused_mut)))
test(attr(allow(dead_code, deprecated, unused_variables, unused_mut, duplicate_features)))
)]
#![doc(rust_logo)]
#![doc(auto_cfg(hide(
Expand Down
2 changes: 1 addition & 1 deletion library/core/src/range.rs
Original file line number Diff line number Diff line change
Expand Up @@ -572,7 +572,7 @@ impl<T> const From<legacy::RangeFrom<T>> for RangeFrom<T> {
///
/// The `..=last` syntax is a `RangeToInclusive`:
///
/// ```
/// ```standalone_crate
/// #![feature(new_range_api)]
/// #![feature(new_range)]
/// assert_eq!((..=5), std::range::RangeToInclusive{ last: 5 });
Expand Down
3 changes: 3 additions & 0 deletions src/librustdoc/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,9 @@ pub(crate) fn create_config(
rustc_lint::builtin::RENAMED_AND_REMOVED_LINTS.name.to_string(),
rustc_lint::builtin::UNKNOWN_LINTS.name.to_string(),
rustc_lint::builtin::UNEXPECTED_CFGS.name.to_string(),
rustc_lint::builtin::DUPLICATE_FEATURES.name.to_string(),
rustc_lint::builtin::UNUSED_FEATURES.name.to_string(),
rustc_lint::builtin::STABLE_FEATURES.name.to_string(),
// this lint is needed to support `#[expect]` attributes
rustc_lint::builtin::UNFULFILLED_LINT_EXPECTATIONS.name.to_string(),
];
Expand Down
8 changes: 5 additions & 3 deletions src/librustdoc/doctest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ use rustc_span::edition::Edition;
use rustc_span::{FileName, RemapPathScopeComponents, Span};
use rustc_target::spec::{Target, TargetTuple};
use tempfile::{Builder as TempFileBuilder, TempDir};
use tracing::debug;
use tracing::{debug, info};

use self::rust::HirCollector;
use crate::config::{MergeDoctests, Options as RustdocOptions, OutputFormat};
Expand Down Expand Up @@ -692,7 +692,7 @@ fn run_test(
compiler.stderr(Stdio::piped());
}

debug!("compiler invocation for doctest: {compiler:?}");
info!("compiler invocation for doctest: {compiler:?}");

let mut child = match compiler.spawn() {
Ok(child) => child,
Expand Down Expand Up @@ -759,7 +759,7 @@ fn run_test(
runner_compiler.stderr(Stdio::inherit());
}
runner_compiler.arg("--error-format=short");
debug!("compiler invocation for doctest runner: {runner_compiler:?}");
info!("compiler invocation for doctest runner: {runner_compiler:?}");

let status = if !status.success() {
status
Expand Down Expand Up @@ -859,6 +859,8 @@ fn run_test(
cmd.current_dir(run_directory);
}

info!("running doctest executable: {cmd:?}");

let result = if doctest.is_multiple_tests() || rustdoc_options.no_capture {
cmd.status().map(|status| process::Output {
status,
Expand Down
5 changes: 4 additions & 1 deletion src/librustdoc/doctest/make.rs
Original file line number Diff line number Diff line change
Expand Up @@ -555,7 +555,10 @@ fn parse_source(
// consider it only as a crate-level attribute.
if attr.has_name(sym::allow)
&& let Some(list) = attr.meta_item_list()
&& list.iter().any(|sub_attr| sub_attr.has_name(sym::internal_features))
&& list.iter().any(|sub_attr| {
sub_attr.has_name(sym::internal_features)
|| sub_attr.has_name(sym::incomplete_features)
})
{
push_to_s(&mut info.crate_attrs, source, attr.span, &mut prev_span_hi);
} else {
Expand Down
1 change: 0 additions & 1 deletion tests/rustdoc-html/assoc/assoc-type-bindings-20646.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

// https://github.com/rust-lang/rust/issues/20646
#![crate_name="issue_20646"]
#![feature(associated_types)]

extern crate issue_20646;

Expand Down
1 change: 0 additions & 1 deletion tests/rustdoc-html/doc-cfg/doc-cfg.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#![feature(doc_cfg)]
#![feature(target_feature, cfg_target_feature)]

//@ has doc_cfg/struct.Portable.html
//@ !has - '//*[@id="main-content"]/*[@class="item-info"]/*[@class="stab portability"]' ''
Expand Down
2 changes: 0 additions & 2 deletions tests/rustdoc-ui/issues/issue-79494.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
//@ only-64bit

#![feature(const_transmute)]

pub const ZST: &[u8] = unsafe { std::mem::transmute(1usize) };
//~^ ERROR transmuting from 8-byte type to 16-byte type
2 changes: 1 addition & 1 deletion tests/rustdoc-ui/issues/issue-79494.stderr
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
error[E0080]: transmuting from 8-byte type to 16-byte type: `usize` -> `&[u8]`
--> $DIR/issue-79494.rs:5:33
--> $DIR/issue-79494.rs:3:33
|
LL | pub const ZST: &[u8] = unsafe { std::mem::transmute(1usize) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `ZST` failed here
Expand Down
4 changes: 3 additions & 1 deletion tests/rustdoc-ui/rustc-check-passes.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
//@ check-pass

#![feature(rustdoc_internals)]
#![feature(rustdoc_internals)] //~ ERROR
#![feature(rustdoc_internals)] //~ WARN duplicate

pub fn foo() {}
9 changes: 5 additions & 4 deletions tests/rustdoc-ui/rustc-check-passes.stderr
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
error[E0636]: the feature `rustdoc_internals` has already been enabled
--> $DIR/rustc-check-passes.rs:2:12
warning: the feature `rustdoc_internals` has already been enabled
--> $DIR/rustc-check-passes.rs:4:12
|
LL | #![feature(rustdoc_internals)]
| ^^^^^^^^^^^^^^^^^
|
= note: `#[warn(duplicate_features)]` on by default

error: aborting due to 1 previous error
warning: 1 warning emitted

For more information about this error, try `rustc --explain E0636`.
6 changes: 4 additions & 2 deletions tests/ui/feature-gates/duplicate-features.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
//@ check-pass

#![allow(stable_features)]

#![feature(rust1)]
#![feature(rust1)] //~ ERROR the feature `rust1` has already been enabled
#![feature(rust1)] //~ WARN the feature `rust1` has already been enabled

#![feature(if_let)]
#![feature(if_let)] //~ ERROR the feature `if_let` has already been enabled
#![feature(if_let)] //~ WARN the feature `if_let` has already been enabled

fn main() {}
13 changes: 7 additions & 6 deletions tests/ui/feature-gates/duplicate-features.stderr
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
error[E0636]: the feature `if_let` has already been enabled
--> $DIR/duplicate-features.rs:7:12
warning: the feature `if_let` has already been enabled
--> $DIR/duplicate-features.rs:9:12
|
LL | #![feature(if_let)]
| ^^^^^^
|
= note: `#[warn(duplicate_features)]` on by default

error[E0636]: the feature `rust1` has already been enabled
--> $DIR/duplicate-features.rs:4:12
warning: the feature `rust1` has already been enabled
--> $DIR/duplicate-features.rs:6:12
|
LL | #![feature(rust1)]
| ^^^^^

error: aborting due to 2 previous errors
warning: 2 warnings emitted

For more information about this error, try `rustc --explain E0636`.
Loading