Skip to content

Commit af11efc

Browse files
authored
Rollup merge of rust-lang#126158 - Urgau:disallow-cfgs, r=petrochenkov
Disallow setting some built-in cfg via set the command-line This PR disallow users from setting some built-in cfg via set the command-line in order to prevent incoherent state, eg. `windows` cfg active but target is Linux based. This implements MCP rust-lang/compiler-team#610, with the caveat that we disallow cfgs no matter if they make sense or not, since I don't think it's useful to allow users to set a cfg that will be set anyway. It also complicates the implementation. ~~In order to not break the world I only included cfgs that didn't seems to be manually set by doing a Github Search and looking at all the results. We may still want to a warn about them in future but this isn't part of this PR.~~ ------ The `unexpected_builtin_cfgs` lint detects builtin cfgs set via the CLI, `--cfg`. *(deny-by-default)* ### Example ```text rustc --cfg unix ``` ```rust,ignore (needs command line option) fn main() {} ``` This will produce: ```text error: unexpected `--cfg unix` flag | = note: config `unix` is only supposed to be controlled by `--target` = note: see <https://github.com/rust-lang/rust/issues/xxxxx> for more information = note: `#[deny(unexpected_builtin_cfgs)]` on by default ``` ### Explanation Setting builtin cfgs can and does produce incoherent behavior, it's better to the use the appropriate `rustc` flag that controls the config. For example setting the `windows` cfg but on Linux based target. ----- r? `@petrochenkov` cc `@jyn514`
2 parents 31f8b70 + 4fc8318 commit af11efc

File tree

43 files changed

+413
-26
lines changed

Some content is hidden

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

43 files changed

+413
-26
lines changed

compiler/rustc_builtin_macros/src/format.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -555,7 +555,7 @@ fn make_format_args(
555555
};
556556
let arg_name = args.explicit_args()[index].kind.ident().unwrap();
557557
ecx.buffered_early_lint.push(BufferedEarlyLint {
558-
span: arg_name.span.into(),
558+
span: Some(arg_name.span.into()),
559559
node_id: rustc_ast::CRATE_NODE_ID,
560560
lint_id: LintId::of(NAMED_ARGUMENTS_USED_POSITIONALLY),
561561
diagnostic: BuiltinLintDiag::NamedArgumentUsedPositionally {

compiler/rustc_lint/messages.ftl

+4
Original file line numberDiff line numberDiff line change
@@ -745,6 +745,10 @@ lint_undropped_manually_drops = calls to `std::mem::drop` with `std::mem::Manual
745745
.label = argument has type `{$arg_ty}`
746746
.suggestion = use `std::mem::ManuallyDrop::into_inner` to get the inner value
747747
748+
lint_unexpected_builtin_cfg = unexpected `--cfg {$cfg}` flag
749+
.controlled_by = config `{$cfg_name}` is only supposed to be controlled by `{$controlled_by}`
750+
.incoherent = manually setting a built-in cfg does create incoherent behaviors
751+
748752
lint_unexpected_cfg_add_build_rs_println = or consider adding `{$build_rs_println}` to the top of the `build.rs`
749753
lint_unexpected_cfg_add_cargo_feature = consider using a Cargo feature instead
750754
lint_unexpected_cfg_add_cargo_toml_lint_cfg = or consider adding in `Cargo.toml` the `check-cfg` lint config for the lint:{$cargo_toml_lint_cfg}

compiler/rustc_lint/src/context.rs

+16-2
Original file line numberDiff line numberDiff line change
@@ -532,7 +532,7 @@ pub struct EarlyContext<'a> {
532532
}
533533

534534
impl EarlyContext<'_> {
535-
/// Emit a lint at the appropriate level, with an optional associated span and an existing
535+
/// Emit a lint at the appropriate level, with an associated span and an existing
536536
/// diagnostic.
537537
///
538538
/// [`lint_level`]: rustc_middle::lint::lint_level#decorate-signature
@@ -543,7 +543,21 @@ impl EarlyContext<'_> {
543543
span: MultiSpan,
544544
diagnostic: BuiltinLintDiag,
545545
) {
546-
self.opt_span_lint(lint, Some(span), |diag| {
546+
self.opt_span_lint_with_diagnostics(lint, Some(span), diagnostic);
547+
}
548+
549+
/// Emit a lint at the appropriate level, with an optional associated span and an existing
550+
/// diagnostic.
551+
///
552+
/// [`lint_level`]: rustc_middle::lint::lint_level#decorate-signature
553+
#[rustc_lint_diagnostics]
554+
pub fn opt_span_lint_with_diagnostics(
555+
&self,
556+
lint: &'static Lint,
557+
span: Option<MultiSpan>,
558+
diagnostic: BuiltinLintDiag,
559+
) {
560+
self.opt_span_lint(lint, span, |diag| {
547561
diagnostics::decorate_lint(self.sess(), diagnostic, diag);
548562
});
549563
}

compiler/rustc_lint/src/context/diagnostics.rs

+3
Original file line numberDiff line numberDiff line change
@@ -437,5 +437,8 @@ pub(super) fn decorate_lint(sess: &Session, diagnostic: BuiltinLintDiag, diag: &
437437
BuiltinLintDiag::OutOfScopeMacroCalls { path } => {
438438
lints::OutOfScopeMacroCalls { path }.decorate_lint(diag)
439439
}
440+
BuiltinLintDiag::UnexpectedBuiltinCfg { cfg, cfg_name, controlled_by } => {
441+
lints::UnexpectedBuiltinCfg { cfg, cfg_name, controlled_by }.decorate_lint(diag)
442+
}
440443
}
441444
}

compiler/rustc_lint/src/early.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ impl<'a, T: EarlyLintPass> EarlyContextAndPass<'a, T> {
4646
fn inlined_check_id(&mut self, id: ast::NodeId) {
4747
for early_lint in self.context.buffered.take(id) {
4848
let BufferedEarlyLint { span, node_id: _, lint_id, diagnostic } = early_lint;
49-
self.context.span_lint_with_diagnostics(lint_id.lint, span, diagnostic);
49+
self.context.opt_span_lint_with_diagnostics(lint_id.lint, span, diagnostic);
5050
}
5151
}
5252

compiler/rustc_lint/src/lints.rs

+10
Original file line numberDiff line numberDiff line change
@@ -2321,6 +2321,16 @@ pub mod unexpected_cfg_value {
23212321
}
23222322
}
23232323

2324+
#[derive(LintDiagnostic)]
2325+
#[diag(lint_unexpected_builtin_cfg)]
2326+
#[note(lint_controlled_by)]
2327+
#[note(lint_incoherent)]
2328+
pub struct UnexpectedBuiltinCfg {
2329+
pub(crate) cfg: String,
2330+
pub(crate) cfg_name: Symbol,
2331+
pub(crate) controlled_by: &'static str,
2332+
}
2333+
23242334
#[derive(LintDiagnostic)]
23252335
#[diag(lint_macro_use_deprecated)]
23262336
#[help]

compiler/rustc_lint_defs/src/builtin.rs

+34
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ declare_lint_pass! {
105105
UNCONDITIONAL_RECURSION,
106106
UNCOVERED_PARAM_IN_PROJECTION,
107107
UNDEFINED_NAKED_FUNCTION_ABI,
108+
UNEXPECTED_BUILTIN_CFGS,
108109
UNEXPECTED_CFGS,
109110
UNFULFILLED_LINT_EXPECTATIONS,
110111
UNINHABITED_STATIC,
@@ -3269,6 +3270,39 @@ declare_lint! {
32693270
"detects unexpected names and values in `#[cfg]` conditions",
32703271
}
32713272

3273+
declare_lint! {
3274+
/// The `unexpected_builtin_cfgs` lint detects builtin cfgs set via the `--cfg` flag.
3275+
///
3276+
/// ### Example
3277+
///
3278+
/// ```text
3279+
/// rustc --cfg unix
3280+
/// ```
3281+
///
3282+
/// ```rust,ignore (needs command line option)
3283+
/// fn main() {}
3284+
/// ```
3285+
///
3286+
/// This will produce:
3287+
///
3288+
/// ```text
3289+
/// error: unexpected `--cfg unix` flag
3290+
/// |
3291+
/// = note: config `unix` is only supposed to be controlled by `--target`
3292+
/// = note: manually setting a built-in cfg does create incoherent behaviors
3293+
/// = note: `#[deny(unexpected_builtin_cfgs)]` on by default
3294+
/// ```
3295+
///
3296+
/// ### Explanation
3297+
///
3298+
/// Setting builtin cfgs can and does produce incoherent behavior, it's better to the use
3299+
/// the appropriate `rustc` flag that controls the config. For example setting the `windows`
3300+
/// cfg but on Linux based target.
3301+
pub UNEXPECTED_BUILTIN_CFGS,
3302+
Deny,
3303+
"detects builtin cfgs set via the `--cfg`"
3304+
}
3305+
32723306
declare_lint! {
32733307
/// The `repr_transparent_external_private_fields` lint
32743308
/// detects types marked `#[repr(transparent)]` that (transitively)

compiler/rustc_lint_defs/src/lib.rs

+7-2
Original file line numberDiff line numberDiff line change
@@ -747,14 +747,19 @@ pub enum BuiltinLintDiag {
747747
OutOfScopeMacroCalls {
748748
path: String,
749749
},
750+
UnexpectedBuiltinCfg {
751+
cfg: String,
752+
cfg_name: Symbol,
753+
controlled_by: &'static str,
754+
},
750755
}
751756

752757
/// Lints that are buffered up early on in the `Session` before the
753758
/// `LintLevels` is calculated.
754759
#[derive(Debug)]
755760
pub struct BufferedEarlyLint {
756761
/// The span of code that we are linting on.
757-
pub span: MultiSpan,
762+
pub span: Option<MultiSpan>,
758763

759764
/// The `NodeId` of the AST node that generated the lint.
760765
pub node_id: NodeId,
@@ -792,7 +797,7 @@ impl LintBuffer {
792797
self.add_early_lint(BufferedEarlyLint {
793798
lint_id: LintId::of(lint),
794799
node_id,
795-
span: span.into(),
800+
span: Some(span.into()),
796801
diagnostic,
797802
});
798803
}

compiler/rustc_session/src/config.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -1301,7 +1301,10 @@ pub(crate) const fn default_lib_output() -> CrateType {
13011301
}
13021302

13031303
pub fn build_configuration(sess: &Session, mut user_cfg: Cfg) -> Cfg {
1304-
// Combine the configuration requested by the session (command line) with
1304+
// First disallow some configuration given on the command line
1305+
cfg::disallow_cfgs(sess, &user_cfg);
1306+
1307+
// Then combine the configuration requested by the session (command line) with
13051308
// some default and generated configuration items.
13061309
user_cfg.extend(cfg::default_configuration(sess));
13071310
user_cfg

compiler/rustc_session/src/config/cfg.rs

+65
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,13 @@
1717
//! - Add the activation logic in [`default_configuration`]
1818
//! - Add the cfg to [`CheckCfg::fill_well_known`] (and related files),
1919
//! so that the compiler can know the cfg is expected
20+
//! - Add the cfg in [`disallow_cfgs`] to disallow users from setting it via `--cfg`
2021
//! - Add the feature gating in `compiler/rustc_feature/src/builtin_attrs.rs`
2122
23+
use rustc_ast::ast;
2224
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
25+
use rustc_lint_defs::builtin::UNEXPECTED_BUILTIN_CFGS;
26+
use rustc_lint_defs::BuiltinLintDiag;
2327
use rustc_span::symbol::{sym, Symbol};
2428
use rustc_target::abi::Align;
2529
use rustc_target::spec::{PanicStrategy, RelocModel, SanitizerSet};
@@ -83,6 +87,67 @@ impl<'a, T: Eq + Hash + Copy + 'a> Extend<&'a T> for ExpectedValues<T> {
8387
}
8488
}
8589

90+
/// Disallow builtin cfgs from the CLI.
91+
pub(crate) fn disallow_cfgs(sess: &Session, user_cfgs: &Cfg) {
92+
let disallow = |cfg: &(Symbol, Option<Symbol>), controlled_by| {
93+
let cfg_name = cfg.0;
94+
let cfg = if let Some(value) = cfg.1 {
95+
format!(r#"{}="{}""#, cfg_name, value)
96+
} else {
97+
format!("{}", cfg_name)
98+
};
99+
sess.psess.opt_span_buffer_lint(
100+
UNEXPECTED_BUILTIN_CFGS,
101+
None,
102+
ast::CRATE_NODE_ID,
103+
BuiltinLintDiag::UnexpectedBuiltinCfg { cfg, cfg_name, controlled_by },
104+
)
105+
};
106+
107+
// We want to restrict setting builtin cfgs that will produce incoherent behavior
108+
// between the cfg and the rustc cli flag that sets it.
109+
//
110+
// The tests are in tests/ui/cfg/disallowed-cli-cfgs.rs.
111+
112+
// By-default all builtin cfgs are disallowed, only those are allowed:
113+
// - test: as it makes sense to the have the `test` cfg active without the builtin
114+
// test harness. See Cargo `harness = false` config.
115+
//
116+
// Cargo `--cfg test`: https://github.com/rust-lang/cargo/blob/bc89bffa5987d4af8f71011c7557119b39e44a65/src/cargo/core/compiler/mod.rs#L1124
117+
118+
for cfg in user_cfgs {
119+
match cfg {
120+
(sym::overflow_checks, None) => disallow(cfg, "-C overflow-checks"),
121+
(sym::debug_assertions, None) => disallow(cfg, "-C debug-assertions"),
122+
(sym::ub_checks, None) => disallow(cfg, "-Z ub-checks"),
123+
(sym::sanitize, None | Some(_)) => disallow(cfg, "-Z sanitizer"),
124+
(
125+
sym::sanitizer_cfi_generalize_pointers | sym::sanitizer_cfi_normalize_integers,
126+
None | Some(_),
127+
) => disallow(cfg, "-Z sanitizer=cfi"),
128+
(sym::proc_macro, None) => disallow(cfg, "--crate-type proc-macro"),
129+
(sym::panic, Some(sym::abort | sym::unwind)) => disallow(cfg, "-C panic"),
130+
(sym::target_feature, Some(_)) => disallow(cfg, "-C target-feature"),
131+
(sym::unix, None)
132+
| (sym::windows, None)
133+
| (sym::relocation_model, Some(_))
134+
| (sym::target_abi, None | Some(_))
135+
| (sym::target_arch, Some(_))
136+
| (sym::target_endian, Some(_))
137+
| (sym::target_env, None | Some(_))
138+
| (sym::target_family, Some(_))
139+
| (sym::target_os, Some(_))
140+
| (sym::target_pointer_width, Some(_))
141+
| (sym::target_vendor, None | Some(_))
142+
| (sym::target_has_atomic, Some(_))
143+
| (sym::target_has_atomic_equal_alignment, Some(_))
144+
| (sym::target_has_atomic_load_store, Some(_))
145+
| (sym::target_thread_local, None) => disallow(cfg, "--target"),
146+
_ => {}
147+
}
148+
}
149+
}
150+
86151
/// Generate the default configs for a given session
87152
pub(crate) fn default_configuration(sess: &Session) -> Cfg {
88153
let mut ret = Cfg::default();

compiler/rustc_session/src/parse.rs

+11-1
Original file line numberDiff line numberDiff line change
@@ -306,10 +306,20 @@ impl ParseSess {
306306
span: impl Into<MultiSpan>,
307307
node_id: NodeId,
308308
diagnostic: BuiltinLintDiag,
309+
) {
310+
self.opt_span_buffer_lint(lint, Some(span.into()), node_id, diagnostic)
311+
}
312+
313+
pub fn opt_span_buffer_lint(
314+
&self,
315+
lint: &'static Lint,
316+
span: Option<MultiSpan>,
317+
node_id: NodeId,
318+
diagnostic: BuiltinLintDiag,
309319
) {
310320
self.buffered_lints.with_lock(|buffered_lints| {
311321
buffered_lints.push(BufferedEarlyLint {
312-
span: span.into(),
322+
span,
313323
node_id,
314324
lint_id: LintId::of(lint),
315325
diagnostic,

tests/codegen/aarch64-struct-align-128.rs

+7-7
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
// Test that structs aligned to 128 bits are passed with the correct ABI on aarch64.
22

3-
//@ revisions:linux darwin windows
3+
//@ revisions: linux darwin win
44
//@[linux] compile-flags: --target aarch64-unknown-linux-gnu
55
//@[darwin] compile-flags: --target aarch64-apple-darwin
6-
//@[windows] compile-flags: --target aarch64-pc-windows-msvc
6+
//@[win] compile-flags: --target aarch64-pc-windows-msvc
77
//@[linux] needs-llvm-components: aarch64
88
//@[darwin] needs-llvm-components: aarch64
9-
//@[windows] needs-llvm-components: aarch64
9+
//@[win] needs-llvm-components: aarch64
1010

1111
#![feature(no_core, lang_items)]
1212
#![crate_type = "lib"]
@@ -41,7 +41,7 @@ pub struct Wrapped8 {
4141
extern "C" {
4242
// linux: declare void @test_8([2 x i64], [2 x i64], [2 x i64])
4343
// darwin: declare void @test_8([2 x i64], [2 x i64], [2 x i64])
44-
// windows: declare void @test_8([2 x i64], [2 x i64], [2 x i64])
44+
// win: declare void @test_8([2 x i64], [2 x i64], [2 x i64])
4545
fn test_8(a: Align8, b: Transparent8, c: Wrapped8);
4646
}
4747

@@ -71,7 +71,7 @@ pub struct Wrapped16 {
7171
extern "C" {
7272
// linux: declare void @test_16([2 x i64], [2 x i64], i128)
7373
// darwin: declare void @test_16(i128, i128, i128)
74-
// windows: declare void @test_16(i128, i128, i128)
74+
// win: declare void @test_16(i128, i128, i128)
7575
fn test_16(a: Align16, b: Transparent16, c: Wrapped16);
7676
}
7777

@@ -96,7 +96,7 @@ pub struct WrappedI128 {
9696
extern "C" {
9797
// linux: declare void @test_i128(i128, i128, i128)
9898
// darwin: declare void @test_i128(i128, i128, i128)
99-
// windows: declare void @test_i128(i128, i128, i128)
99+
// win: declare void @test_i128(i128, i128, i128)
100100
fn test_i128(a: I128, b: TransparentI128, c: WrappedI128);
101101
}
102102

@@ -123,7 +123,7 @@ pub struct WrappedPacked {
123123
extern "C" {
124124
// linux: declare void @test_packed([2 x i64], [2 x i64], [2 x i64])
125125
// darwin: declare void @test_packed([2 x i64], [2 x i64], [2 x i64])
126-
// windows: declare void @test_packed([2 x i64], [2 x i64], [2 x i64])
126+
// win: declare void @test_packed([2 x i64], [2 x i64], [2 x i64])
127127
fn test_packed(a: Packed, b: TransparentPacked, c: WrappedPacked);
128128
}
129129

tests/codegen/default-requires-uwtable.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
//@ revisions: WINDOWS ANDROID
1+
//@ revisions: WINDOWS_ ANDROID_
22
//@ compile-flags: -C panic=abort -Copt-level=0
3-
//@ [WINDOWS] compile-flags: --target=x86_64-pc-windows-msvc
4-
//@ [WINDOWS] needs-llvm-components: x86
5-
//@ [ANDROID] compile-flags: --target=armv7-linux-androideabi
6-
//@ [ANDROID] needs-llvm-components: arm
3+
//@ [WINDOWS_] compile-flags: --target=x86_64-pc-windows-msvc
4+
//@ [WINDOWS_] needs-llvm-components: x86
5+
//@ [ANDROID_] compile-flags: --target=armv7-linux-androideabi
6+
//@ [ANDROID_] needs-llvm-components: arm
77

88
#![feature(no_core, lang_items)]
99
#![crate_type = "lib"]

tests/codegen/repr/transparent-sysv64.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
//@ revisions: linux apple windows
1+
//@ revisions: linux apple win
22
//@ compile-flags: -O -C no-prepopulate-passes
33

44
//@[linux] compile-flags: --target x86_64-unknown-linux-gnu
55
//@[linux] needs-llvm-components: x86
66
//@[apple] compile-flags: --target x86_64-apple-darwin
77
//@[apple] needs-llvm-components: x86
8-
//@[windows] compile-flags: --target x86_64-pc-windows-msvc
9-
//@[windows] needs-llvm-components: x86
8+
//@[win] compile-flags: --target x86_64-pc-windows-msvc
9+
//@[win] needs-llvm-components: x86
1010

1111
#![feature(no_core, lang_items)]
1212
#![crate_type = "lib"]

tests/debuginfo/thread-names.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
//@ compile-flags:-g
2-
//@ revisions: macos windows
2+
//@ revisions: macos win
33
// We can't set the main thread name on Linux because it renames the process (#97191)
44
//@[macos] only-macos
5-
//@[windows] only-windows
5+
//@[win] only-windows
66
//@ ignore-sgx
77
//@ ignore-windows-gnu
88

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
//@ check-pass
2+
//@ compile-flags: --cfg unix -Aunexpected_builtin_cfgs
3+
4+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
error: unexpected `--cfg debug_assertions` flag
2+
|
3+
= note: config `debug_assertions` is only supposed to be controlled by `-C debug-assertions`
4+
= note: manually setting a built-in cfg does create incoherent behaviors
5+
= note: `#[deny(unexpected_builtin_cfgs)]` on by default
6+
7+
error: aborting due to 1 previous error
8+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
error: unexpected `--cfg overflow_checks` flag
2+
|
3+
= note: config `overflow_checks` is only supposed to be controlled by `-C overflow-checks`
4+
= note: manually setting a built-in cfg does create incoherent behaviors
5+
= note: `#[deny(unexpected_builtin_cfgs)]` on by default
6+
7+
error: aborting due to 1 previous error
8+

0 commit comments

Comments
 (0)