Skip to content

Commit ce20e15

Browse files
committed
Auto merge of #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. ------ The `explicit_builtin_cfgs_in_flags` lint detects builtin cfgs set via the `--cfg` flag. *(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: manually setting a built-in cfg can and does create incoherent behaviours = note: `#[deny(explicit_builtin_cfgs_in_flags)]` on by default ``` ### Explanation Setting builtin cfgs can and does produce incoherent behaviour, 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` try-job: aarch64-apple try-job: test-various try-job: armhf-gnu try-job: x86_64-msvc try-job: x86_64-mingw try-job: i686-msvc try-job: i686-mingw try-job: x86_64-gnu-llvm-17 try-job: dist-various-1
2 parents 8d00669 + c0c57b3 commit ce20e15

File tree

45 files changed

+467
-80
lines changed

Some content is hidden

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

45 files changed

+467
-80
lines changed

Diff for: 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 {

Diff for: compiler/rustc_lint/messages.ftl

+4
Original file line numberDiff line numberDiff line change
@@ -775,6 +775,10 @@ lint_undropped_manually_drops = calls to `std::mem::drop` with `std::mem::Manual
775775
.label = argument has type `{$arg_ty}`
776776
.suggestion = use `std::mem::ManuallyDrop::into_inner` to get the inner value
777777
778+
lint_unexpected_builtin_cfg = unexpected `--cfg {$cfg}` flag
779+
.controlled_by = config `{$cfg_name}` is only supposed to be controlled by `{$controlled_by}`
780+
.incoherent = manually setting a built-in cfg can and does create incoherent behaviors
781+
778782
lint_unexpected_cfg_add_build_rs_println = or consider adding `{$build_rs_println}` to the top of the `build.rs`
779783
lint_unexpected_cfg_add_cargo_feature = consider using a Cargo feature instead
780784
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}

Diff for: compiler/rustc_lint/src/context.rs

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

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

Diff for: compiler/rustc_lint/src/context/diagnostics.rs

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

Diff for: compiler/rustc_lint/src/early.rs

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

Diff for: compiler/rustc_lint/src/lints.rs

+10
Original file line numberDiff line numberDiff line change
@@ -2379,6 +2379,16 @@ pub mod unexpected_cfg_value {
23792379
}
23802380
}
23812381

2382+
#[derive(LintDiagnostic)]
2383+
#[diag(lint_unexpected_builtin_cfg)]
2384+
#[note(lint_controlled_by)]
2385+
#[note(lint_incoherent)]
2386+
pub struct UnexpectedBuiltinCfg {
2387+
pub(crate) cfg: String,
2388+
pub(crate) cfg_name: Symbol,
2389+
pub(crate) controlled_by: &'static str,
2390+
}
2391+
23822392
#[derive(LintDiagnostic)]
23832393
#[diag(lint_macro_use_deprecated)]
23842394
#[help]

Diff for: compiler/rustc_lint_defs/src/builtin.rs

+34
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ declare_lint_pass! {
4242
DUPLICATE_MACRO_ATTRIBUTES,
4343
ELIDED_LIFETIMES_IN_ASSOCIATED_CONSTANT,
4444
ELIDED_LIFETIMES_IN_PATHS,
45+
EXPLICIT_BUILTIN_CFGS_IN_FLAGS,
4546
EXPORTED_PRIVATE_DEPENDENCIES,
4647
FFI_UNWIND_CALLS,
4748
FORBIDDEN_LINT_GROUPS,
@@ -3288,6 +3289,39 @@ declare_lint! {
32883289
"detects unexpected names and values in `#[cfg]` conditions",
32893290
}
32903291

3292+
declare_lint! {
3293+
/// The `explicit_builtin_cfgs_in_flags` lint detects builtin cfgs set via the `--cfg` flag.
3294+
///
3295+
/// ### Example
3296+
///
3297+
/// ```text
3298+
/// rustc --cfg unix
3299+
/// ```
3300+
///
3301+
/// ```rust,ignore (needs command line option)
3302+
/// fn main() {}
3303+
/// ```
3304+
///
3305+
/// This will produce:
3306+
///
3307+
/// ```text
3308+
/// error: unexpected `--cfg unix` flag
3309+
/// |
3310+
/// = note: config `unix` is only supposed to be controlled by `--target`
3311+
/// = note: manually setting a built-in cfg can and does create incoherent behaviors
3312+
/// = note: `#[deny(explicit_builtin_cfgs_in_flags)]` on by default
3313+
/// ```
3314+
///
3315+
/// ### Explanation
3316+
///
3317+
/// Setting builtin cfgs can and does produce incoherent behavior, it's better to the use
3318+
/// the appropriate `rustc` flag that controls the config. For example setting the `windows`
3319+
/// cfg but on Linux based target.
3320+
pub EXPLICIT_BUILTIN_CFGS_IN_FLAGS,
3321+
Deny,
3322+
"detects builtin cfgs set via the `--cfg`"
3323+
}
3324+
32913325
declare_lint! {
32923326
/// The `repr_transparent_external_private_fields` lint
32933327
/// detects types marked `#[repr(transparent)]` that (transitively)

Diff for: compiler/rustc_lint_defs/src/lib.rs

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

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

758763
/// The `NodeId` of the AST node that generated the lint.
759764
pub node_id: NodeId,
@@ -791,7 +796,7 @@ impl LintBuffer {
791796
self.add_early_lint(BufferedEarlyLint {
792797
lint_id: LintId::of(lint),
793798
node_id,
794-
span: span.into(),
799+
span: Some(span.into()),
795800
diagnostic,
796801
});
797802
}

Diff for: compiler/rustc_session/src/config.rs

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

13061306
pub fn build_configuration(sess: &Session, mut user_cfg: Cfg) -> Cfg {
1307-
// Combine the configuration requested by the session (command line) with
1307+
// First disallow some configuration given on the command line
1308+
cfg::disallow_cfgs(sess, &user_cfg);
1309+
1310+
// Then combine the configuration requested by the session (command line) with
13081311
// some default and generated configuration items.
13091312
user_cfg.extend(cfg::default_configuration(sess));
13101313
user_cfg

Diff for: compiler/rustc_session/src/config/cfg.rs

+65
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,16 @@
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
2223
use std::hash::Hash;
2324
use std::iter;
2425

26+
use rustc_ast::ast;
2527
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
28+
use rustc_lint_defs::builtin::EXPLICIT_BUILTIN_CFGS_IN_FLAGS;
29+
use rustc_lint_defs::BuiltinLintDiag;
2630
use rustc_span::symbol::{sym, Symbol};
2731
use rustc_target::abi::Align;
2832
use rustc_target::spec::{PanicStrategy, RelocModel, SanitizerSet, Target, TargetTriple, TARGETS};
@@ -82,6 +86,67 @@ impl<'a, T: Eq + Hash + Copy + 'a> Extend<&'a T> for ExpectedValues<T> {
8286
}
8387
}
8488

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

Diff for: 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,

Diff for: tests/assembly/x86-return-float.rs

+27-27
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@
88
// Force frame pointers to make ASM more consistent between targets
99
//@ compile-flags: -O -C force-frame-pointers
1010
//@ filecheck-flags: --implicit-check-not fld --implicit-check-not fst
11-
//@ revisions: unix windows
12-
//@[unix] ignore-windows
13-
//@[windows] only-windows
11+
//@ revisions: normal win
12+
//@[normal] ignore-windows
13+
//@[win] only-windows
1414

1515
#![crate_type = "lib"]
1616
#![feature(f16, f128)]
@@ -190,10 +190,10 @@ pub unsafe fn call_f64_f64(x: &mut (f64, f64)) {
190190
}
191191
// CHECK: movl {{.*}}(%ebp), %[[PTR:.*]]
192192
// CHECK: calll {{()|_}}get_f64_f64
193-
// unix: movsd [[#%d,OFFSET:]](%ebp), %[[VAL1:.*]]
194-
// unix-NEXT: movsd [[#%d,OFFSET+8]](%ebp), %[[VAL2:.*]]
195-
// windows: movsd (%esp), %[[VAL1:.*]]
196-
// windows-NEXT: movsd 8(%esp), %[[VAL2:.*]]
193+
// normal: movsd [[#%d,OFFSET:]](%ebp), %[[VAL1:.*]]
194+
// normal-NEXT: movsd [[#%d,OFFSET+8]](%ebp), %[[VAL2:.*]]
195+
// win: movsd (%esp), %[[VAL1:.*]]
196+
// win-NEXT: movsd 8(%esp), %[[VAL2:.*]]
197197
// CHECK-NEXT: movsd %[[VAL1]], (%[[PTR]])
198198
// CHECK-NEXT: movsd %[[VAL2]], 8(%[[PTR]])
199199
*x = get_f64_f64();
@@ -207,13 +207,13 @@ pub unsafe fn call_f32_f64(x: &mut (f32, f64)) {
207207
}
208208
// CHECK: movl {{.*}}(%ebp), %[[PTR:.*]]
209209
// CHECK: calll {{()|_}}get_f32_f64
210-
// unix: movss [[#%d,OFFSET:]](%ebp), %[[VAL1:.*]]
211-
// unix-NEXT: movsd [[#%d,OFFSET+4]](%ebp), %[[VAL2:.*]]
212-
// windows: movss (%esp), %[[VAL1:.*]]
213-
// windows-NEXT: movsd 8(%esp), %[[VAL2:.*]]
210+
// normal: movss [[#%d,OFFSET:]](%ebp), %[[VAL1:.*]]
211+
// normal-NEXT: movsd [[#%d,OFFSET+4]](%ebp), %[[VAL2:.*]]
212+
// win: movss (%esp), %[[VAL1:.*]]
213+
// win-NEXT: movsd 8(%esp), %[[VAL2:.*]]
214214
// CHECK-NEXT: movss %[[VAL1]], (%[[PTR]])
215-
// unix-NEXT: movsd %[[VAL2]], 4(%[[PTR]])
216-
// windows-NEXT: movsd %[[VAL2]], 8(%[[PTR]])
215+
// normal-NEXT: movsd %[[VAL2]], 4(%[[PTR]])
216+
// win-NEXT: movsd %[[VAL2]], 8(%[[PTR]])
217217
*x = get_f32_f64();
218218
}
219219

@@ -225,10 +225,10 @@ pub unsafe fn call_f64_f32(x: &mut (f64, f32)) {
225225
}
226226
// CHECK: movl {{.*}}(%ebp), %[[PTR:.*]]
227227
// CHECK: calll {{()|_}}get_f64_f32
228-
// unix: movsd [[#%d,OFFSET:]](%ebp), %[[VAL1:.*]]
229-
// unix-NEXT: movss [[#%d,OFFSET+8]](%ebp), %[[VAL2:.*]]
230-
// windows: movsd (%esp), %[[VAL1:.*]]
231-
// windows-NEXT: movss 8(%esp), %[[VAL2:.*]]
228+
// normal: movsd [[#%d,OFFSET:]](%ebp), %[[VAL1:.*]]
229+
// normal-NEXT: movss [[#%d,OFFSET+8]](%ebp), %[[VAL2:.*]]
230+
// win: movsd (%esp), %[[VAL1:.*]]
231+
// win-NEXT: movss 8(%esp), %[[VAL2:.*]]
232232
// CHECK-NEXT: movsd %[[VAL1]], (%[[PTR]])
233233
// CHECK-NEXT: movss %[[VAL2]], 8(%[[PTR]])
234234
*x = get_f64_f32();
@@ -257,10 +257,10 @@ pub unsafe fn call_f64_other(x: &mut (f64, usize)) {
257257
}
258258
// CHECK: movl {{.*}}(%ebp), %[[PTR:.*]]
259259
// CHECK: calll {{()|_}}get_f64_other
260-
// unix: movsd [[#%d,OFFSET:]](%ebp), %[[VAL1:.*]]
261-
// unix-NEXT: movl [[#%d,OFFSET+8]](%ebp), %[[VAL2:.*]]
262-
// windows: movsd (%esp), %[[VAL1:.*]]
263-
// windows-NEXT: movl 8(%esp), %[[VAL2:.*]]
260+
// normal: movsd [[#%d,OFFSET:]](%ebp), %[[VAL1:.*]]
261+
// normal-NEXT: movl [[#%d,OFFSET+8]](%ebp), %[[VAL2:.*]]
262+
// win: movsd (%esp), %[[VAL1:.*]]
263+
// win-NEXT: movl 8(%esp), %[[VAL2:.*]]
264264
// CHECK-NEXT: movsd %[[VAL1]], (%[[PTR]])
265265
// CHECK-NEXT: movl %[[VAL2]], 8(%[[PTR]])
266266
*x = get_f64_other();
@@ -289,13 +289,13 @@ pub unsafe fn call_other_f64(x: &mut (usize, f64)) {
289289
}
290290
// CHECK: movl {{.*}}(%ebp), %[[PTR:.*]]
291291
// CHECK: calll {{()|_}}get_other_f64
292-
// unix: movl [[#%d,OFFSET:]](%ebp), %[[VAL1:.*]]
293-
// unix-NEXT: movsd [[#%d,OFFSET+4]](%ebp), %[[VAL2:.*]]
294-
// windows: movl (%esp), %[[VAL1:.*]]
295-
// windows-NEXT: movsd 8(%esp), %[[VAL2:.*]]
292+
// normal: movl [[#%d,OFFSET:]](%ebp), %[[VAL1:.*]]
293+
// normal-NEXT: movsd [[#%d,OFFSET+4]](%ebp), %[[VAL2:.*]]
294+
// win: movl (%esp), %[[VAL1:.*]]
295+
// win-NEXT: movsd 8(%esp), %[[VAL2:.*]]
296296
// CHECK-NEXT: movl %[[VAL1]], (%[[PTR]])
297-
// unix-NEXT: movsd %[[VAL2]], 4(%[[PTR]])
298-
// windows-NEXT: movsd %[[VAL2]], 8(%[[PTR]])
297+
// normal-NEXT: movsd %[[VAL2]], 4(%[[PTR]])
298+
// win-NEXT: movsd %[[VAL2]], 8(%[[PTR]])
299299
*x = get_other_f64();
300300
}
301301

0 commit comments

Comments
 (0)