Skip to content

Commit 6ccaea1

Browse files
committed
Target modifiers fix for bool flags without value
1 parent 2b4694a commit 6ccaea1

File tree

9 files changed

+184
-49
lines changed

9 files changed

+184
-49
lines changed

compiler/rustc_metadata/messages.ftl

+14-3
Original file line numberDiff line numberDiff line change
@@ -118,12 +118,23 @@ metadata_incompatible_rustc =
118118
119119
metadata_incompatible_target_modifiers =
120120
mixing `{$flag_name_prefixed}` will cause an ABI mismatch in crate `{$local_crate}`
121-
.note = `{$flag_name_prefixed}={$flag_local_value}` in this crate is incompatible with `{$flag_name_prefixed}={$flag_extern_value}` in dependency `{$extern_crate}`
121+
.note = `{$flag_name_prefixed}={$local_value}` in this crate is incompatible with `{$flag_name_prefixed}={$extern_value}` in dependency `{$extern_crate}`
122122
.help = the `{$flag_name_prefixed}` flag modifies the ABI so Rust crates compiled with different values of this flag cannot be used together safely
123-
124123
metadata_incompatible_target_modifiers_help_allow = if you are sure this will not cause problems, you may use `-Cunsafe-allow-abi-mismatch={$flag_name}` to silence this error
125-
metadata_incompatible_target_modifiers_help_fix = set `{$flag_name_prefixed}={$flag_extern_value}` in this crate or `{$flag_name_prefixed}={$flag_local_value}` in `{$extern_crate}`
124+
metadata_incompatible_target_modifiers_help_fix = set `{$flag_name_prefixed}={$extern_value}` in this crate or `{$flag_name_prefixed}={$local_value}` in `{$extern_crate}`
125+
126+
metadata_incompatible_target_modifiers_help_fix_l_missed = set `{$flag_name_prefixed}={$extern_value}` in this crate or unset `{$flag_name_prefixed}` in `{$extern_crate}`
126127
128+
metadata_incompatible_target_modifiers_help_fix_r_missed = unset `{$flag_name_prefixed}` in this crate or set `{$flag_name_prefixed}={$local_value}` in `{$extern_crate}`
129+
130+
metadata_incompatible_target_modifiers_l_missed =
131+
mixing `{$flag_name_prefixed}` will cause an ABI mismatch in crate `{$local_crate}`
132+
.note = unset `{$flag_name_prefixed}` in this crate is incompatible with `{$flag_name_prefixed}={$extern_value}` in dependency `{$extern_crate}`
133+
.help = the `{$flag_name_prefixed}` flag modifies the ABI so Rust crates compiled with different values of this flag cannot be used together safely
134+
metadata_incompatible_target_modifiers_r_missed =
135+
mixing `{$flag_name_prefixed}` will cause an ABI mismatch in crate `{$local_crate}`
136+
.note = `{$flag_name_prefixed}={$local_value}` in this crate is incompatible with unset `{$flag_name_prefixed}` in dependency `{$extern_crate}`
137+
.help = the `{$flag_name_prefixed}` flag modifies the ABI so Rust crates compiled with different values of this flag cannot be used together safely
127138
metadata_incompatible_wasm_link =
128139
`wasm_import_module` is incompatible with other arguments in `#[link]` attributes
129140

compiler/rustc_metadata/src/creader.rs

+51-18
Original file line numberDiff line numberDiff line change
@@ -358,57 +358,90 @@ impl CStore {
358358
) {
359359
let span = krate.spans.inner_span.shrink_to_lo();
360360
let allowed_flag_mismatches = &tcx.sess.opts.cg.unsafe_allow_abi_mismatch;
361-
let name = tcx.crate_name(LOCAL_CRATE);
361+
let local_crate = tcx.crate_name(LOCAL_CRATE);
362362
let tmod_extender = |tmod: &TargetModifier| (tmod.extend(), tmod.clone());
363363
let report_diff = |prefix: &String,
364364
opt_name: &String,
365-
flag_local_value: &String,
366-
flag_extern_value: &String| {
365+
flag_local_value: Option<&String>,
366+
flag_extern_value: Option<&String>| {
367367
if allowed_flag_mismatches.contains(&opt_name) {
368368
return;
369369
}
370-
tcx.dcx().emit_err(errors::IncompatibleTargetModifiers {
371-
span,
372-
extern_crate: data.name(),
373-
local_crate: name,
374-
flag_name: opt_name.clone(),
375-
flag_name_prefixed: format!("-{}{}", prefix, opt_name),
376-
flag_local_value: flag_local_value.to_string(),
377-
flag_extern_value: flag_extern_value.to_string(),
378-
});
370+
let extern_crate = data.name();
371+
let flag_name = opt_name.clone();
372+
let flag_name_prefixed = format!("-{}{}", prefix, opt_name);
373+
374+
match (flag_local_value, flag_extern_value) {
375+
(Some(local_value), Some(extern_value)) => {
376+
tcx.dcx().emit_err(errors::IncompatibleTargetModifiers {
377+
span,
378+
extern_crate,
379+
local_crate,
380+
flag_name,
381+
flag_name_prefixed,
382+
local_value: local_value.to_string(),
383+
extern_value: extern_value.to_string(),
384+
})
385+
}
386+
(None, Some(extern_value)) => {
387+
tcx.dcx().emit_err(errors::IncompatibleTargetModifiersLMissed {
388+
span,
389+
extern_crate,
390+
local_crate,
391+
flag_name,
392+
flag_name_prefixed,
393+
extern_value: extern_value.to_string(),
394+
})
395+
}
396+
(Some(local_value), None) => {
397+
tcx.dcx().emit_err(errors::IncompatibleTargetModifiersRMissed {
398+
span,
399+
extern_crate,
400+
local_crate,
401+
flag_name,
402+
flag_name_prefixed,
403+
local_value: local_value.to_string(),
404+
})
405+
}
406+
(None, None) => panic!("Incorrect target modifiers report_diff(None, None)"),
407+
};
379408
};
380409
let mut it1 = mods.iter().map(tmod_extender);
381410
let mut it2 = dep_mods.iter().map(tmod_extender);
382411
let mut left_name_val: Option<(ExtendedTargetModifierInfo, TargetModifier)> = None;
383412
let mut right_name_val: Option<(ExtendedTargetModifierInfo, TargetModifier)> = None;
384-
let no_val = "*".to_string();
385413
loop {
386414
left_name_val = left_name_val.or_else(|| it1.next());
387415
right_name_val = right_name_val.or_else(|| it2.next());
388416
match (&left_name_val, &right_name_val) {
389417
(Some(l), Some(r)) => match l.1.opt.cmp(&r.1.opt) {
390418
cmp::Ordering::Equal => {
391419
if l.0.tech_value != r.0.tech_value {
392-
report_diff(&l.0.prefix, &l.0.name, &l.1.value_name, &r.1.value_name);
420+
report_diff(
421+
&l.0.prefix,
422+
&l.0.name,
423+
Some(&l.1.value_name),
424+
Some(&r.1.value_name),
425+
);
393426
}
394427
left_name_val = None;
395428
right_name_val = None;
396429
}
397430
cmp::Ordering::Greater => {
398-
report_diff(&r.0.prefix, &r.0.name, &no_val, &r.1.value_name);
431+
report_diff(&r.0.prefix, &r.0.name, None, Some(&r.1.value_name));
399432
right_name_val = None;
400433
}
401434
cmp::Ordering::Less => {
402-
report_diff(&l.0.prefix, &l.0.name, &l.1.value_name, &no_val);
435+
report_diff(&l.0.prefix, &l.0.name, Some(&l.1.value_name), None);
403436
left_name_val = None;
404437
}
405438
},
406439
(Some(l), None) => {
407-
report_diff(&l.0.prefix, &l.0.name, &l.1.value_name, &no_val);
440+
report_diff(&l.0.prefix, &l.0.name, Some(&l.1.value_name), None);
408441
left_name_val = None;
409442
}
410443
(None, Some(r)) => {
411-
report_diff(&r.0.prefix, &r.0.name, &no_val, &r.1.value_name);
444+
report_diff(&r.0.prefix, &r.0.name, None, Some(&r.1.value_name));
412445
right_name_val = None;
413446
}
414447
(None, None) => break,

compiler/rustc_metadata/src/errors.rs

+34-2
Original file line numberDiff line numberDiff line change
@@ -759,8 +759,40 @@ pub struct IncompatibleTargetModifiers {
759759
pub local_crate: Symbol,
760760
pub flag_name: String,
761761
pub flag_name_prefixed: String,
762-
pub flag_local_value: String,
763-
pub flag_extern_value: String,
762+
pub local_value: String,
763+
pub extern_value: String,
764+
}
765+
766+
#[derive(Diagnostic)]
767+
#[diag(metadata_incompatible_target_modifiers_l_missed)]
768+
#[help]
769+
#[note]
770+
#[help(metadata_incompatible_target_modifiers_help_fix_l_missed)]
771+
#[help(metadata_incompatible_target_modifiers_help_allow)]
772+
pub struct IncompatibleTargetModifiersLMissed {
773+
#[primary_span]
774+
pub span: Span,
775+
pub extern_crate: Symbol,
776+
pub local_crate: Symbol,
777+
pub flag_name: String,
778+
pub flag_name_prefixed: String,
779+
pub extern_value: String,
780+
}
781+
782+
#[derive(Diagnostic)]
783+
#[diag(metadata_incompatible_target_modifiers_r_missed)]
784+
#[help]
785+
#[note]
786+
#[help(metadata_incompatible_target_modifiers_help_fix_r_missed)]
787+
#[help(metadata_incompatible_target_modifiers_help_allow)]
788+
pub struct IncompatibleTargetModifiersRMissed {
789+
#[primary_span]
790+
pub span: Span,
791+
pub extern_crate: Symbol,
792+
pub local_crate: Symbol,
793+
pub flag_name: String,
794+
pub flag_name_prefixed: String,
795+
pub local_value: String,
764796
}
765797

766798
#[derive(Diagnostic)]

compiler/rustc_session/src/options.rs

+28-24
Original file line numberDiff line numberDiff line change
@@ -94,45 +94,49 @@ fn tmod_push_impl(
9494
tmod_vals: &BTreeMap<OptionsTargetModifiers, String>,
9595
tmods: &mut Vec<TargetModifier>,
9696
) {
97-
tmods.push(TargetModifier { opt, value_name: tmod_vals.get(&opt).cloned().unwrap_or_default() })
97+
if let Some(v) = tmod_vals.get(&opt) {
98+
tmods.push(TargetModifier { opt, value_name: v.clone() })
99+
}
98100
}
99101

100102
macro_rules! tmod_push {
101-
($struct_name:ident, $tmod_enum_name:ident, $opt_name:ident, $mods:expr, $tmod_vals:expr) => {
102-
tmod_push_impl(
103-
OptionsTargetModifiers::$struct_name($tmod_enum_name::$opt_name),
104-
$tmod_vals,
105-
$mods,
106-
);
103+
($struct_name:ident, $tmod_enum_name:ident, $opt_name:ident, $opt_expr:expr, $init:expr, $mods:expr, $tmod_vals:expr) => {
104+
if *$opt_expr != $init {
105+
tmod_push_impl(
106+
OptionsTargetModifiers::$struct_name($tmod_enum_name::$opt_name),
107+
$tmod_vals,
108+
$mods,
109+
);
110+
}
107111
};
108112
}
109113

110114
macro_rules! gather_tmods {
111-
($struct_name:ident, $tmod_enum_name:ident, $opt_name:ident, $opt_expr:expr, $mods:expr, $tmod_vals:expr,
115+
($struct_name:ident, $tmod_enum_name:ident, $opt_name:ident, $opt_expr:expr, $init:expr, $mods:expr, $tmod_vals:expr,
112116
[SUBSTRUCT], [TARGET_MODIFIER]) => {
113117
compile_error!("SUBSTRUCT can't be target modifier");
114118
};
115-
($struct_name:ident, $tmod_enum_name:ident, $opt_name:ident, $opt_expr:expr, $mods:expr, $tmod_vals:expr,
119+
($struct_name:ident, $tmod_enum_name:ident, $opt_name:ident, $opt_expr:expr, $init:expr, $mods:expr, $tmod_vals:expr,
116120
[UNTRACKED], [TARGET_MODIFIER]) => {
117-
tmod_push!($struct_name, $tmod_enum_name, $opt_name, $mods, $tmod_vals)
121+
tmod_push!($struct_name, $tmod_enum_name, $opt_name, $opt_expr, $init, $mods, $tmod_vals)
118122
};
119-
($struct_name:ident, $tmod_enum_name:ident, $opt_name:ident, $opt_expr:expr, $mods:expr, $tmod_vals:expr,
123+
($struct_name:ident, $tmod_enum_name:ident, $opt_name:ident, $opt_expr:expr, $init:expr, $mods:expr, $tmod_vals:expr,
120124
[TRACKED], [TARGET_MODIFIER]) => {
121-
tmod_push!($struct_name, $tmod_enum_name, $opt_name, $mods, $tmod_vals)
125+
tmod_push!($struct_name, $tmod_enum_name, $opt_name, $opt_expr, $init, $mods, $tmod_vals)
122126
};
123-
($struct_name:ident, $tmod_enum_name:ident, $opt_name:ident, $opt_expr:expr, $mods:expr, $tmod_vals:expr,
127+
($struct_name:ident, $tmod_enum_name:ident, $opt_name:ident, $opt_expr:expr, $init:expr, $mods:expr, $tmod_vals:expr,
124128
[TRACKED_NO_CRATE_HASH], [TARGET_MODIFIER]) => {
125-
tmod_push!($struct_name, $tmod_enum_name, $opt_name, $mods, $tmod_vals)
129+
tmod_push!($struct_name, $tmod_enum_name, $opt_name, $opt_expr, $init, $mods, $tmod_vals)
126130
};
127-
($struct_name:ident, $tmod_enum_name:ident, $opt_name:ident, $opt_expr:expr, $mods:expr, $tmod_vals:expr,
131+
($struct_name:ident, $tmod_enum_name:ident, $opt_name:ident, $opt_expr:expr, $init:expr, $mods:expr, $tmod_vals:expr,
128132
[SUBSTRUCT], []) => {
129133
$opt_expr.gather_target_modifiers($mods, $tmod_vals);
130134
};
131-
($struct_name:ident, $tmod_enum_name:ident, $opt_name:ident, $opt_expr:expr, $mods:expr, $tmod_vals:expr,
135+
($struct_name:ident, $tmod_enum_name:ident, $opt_name:ident, $opt_expr:expr, $init:expr, $mods:expr, $tmod_vals:expr,
132136
[UNTRACKED], []) => {{}};
133-
($struct_name:ident, $tmod_enum_name:ident, $opt_name:ident, $opt_expr:expr, $mods:expr, $tmod_vals:expr,
137+
($struct_name:ident, $tmod_enum_name:ident, $opt_name:ident, $opt_expr:expr, $init:expr, $mods:expr, $tmod_vals:expr,
134138
[TRACKED], []) => {{}};
135-
($struct_name:ident, $tmod_enum_name:ident, $opt_name:ident, $opt_expr:expr, $mods:expr, $tmod_vals:expr,
139+
($struct_name:ident, $tmod_enum_name:ident, $opt_name:ident, $opt_expr:expr, $init:expr, $mods:expr, $tmod_vals:expr,
136140
[TRACKED_NO_CRATE_HASH], []) => {{}};
137141
}
138142

@@ -474,7 +478,8 @@ macro_rules! tmod_enum {
474478
$($pout)*
475479
Self::$opt => {
476480
let mut parsed : $t = Default::default();
477-
parse::$parse(&mut parsed, Some($puser_value));
481+
let val = if $puser_value.is_empty() { None } else { Some($puser_value) };
482+
parse::$parse(&mut parsed, val);
478483
ExtendedTargetModifierInfo {
479484
prefix: $prefix.to_string(),
480485
name: stringify!($opt).to_string().replace('_', "-"),
@@ -569,7 +574,7 @@ macro_rules! options {
569574
_tmod_vals: &BTreeMap<OptionsTargetModifiers, String>,
570575
) {
571576
$({
572-
gather_tmods!($struct_name, $tmod_enum_name, $opt, &self.$opt, _mods, _tmod_vals,
577+
gather_tmods!($struct_name, $tmod_enum_name, $opt, &self.$opt, $init, _mods, _tmod_vals,
573578
[$dep_tracking_marker], [$($tmod),*]);
574579
})*
575580
}
@@ -681,10 +686,9 @@ fn build_options<O: Default>(
681686
),
682687
}
683688
}
684-
if let Some(tmod) = *tmod
685-
&& let Some(value) = value
686-
{
687-
target_modifiers.insert(tmod, value.to_string());
689+
if let Some(tmod) = *tmod {
690+
let v = value.map_or(String::new(), ToOwned::to_owned);
691+
target_modifiers.insert(tmod, v);
688692
}
689693
}
690694
None => early_dcx.early_fatal(format!("unknown {outputname} option: `{key}`")),
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
//@ no-prefer-dynamic
2+
//@ compile-flags: --target i686-unknown-linux-gnu -Zreg-struct-return=true
3+
//@ needs-llvm-components: x86
4+
5+
#![feature(no_core)]
6+
#![crate_type = "rlib"]
7+
#![no_core]

tests/ui/target_modifiers/defaults_check.error.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ LL | #![feature(no_core)]
55
| ^
66
|
77
= help: the `-Zreg-struct-return` flag modifies the ABI so Rust crates compiled with different values of this flag cannot be used together safely
8-
= note: `-Zreg-struct-return=true` in this crate is incompatible with `-Zreg-struct-return=` in dependency `default_reg_struct_return`
9-
= help: set `-Zreg-struct-return=` in this crate or `-Zreg-struct-return=true` in `default_reg_struct_return`
8+
= note: `-Zreg-struct-return=true` in this crate is incompatible with unset `-Zreg-struct-return` in dependency `default_reg_struct_return`
9+
= help: unset `-Zreg-struct-return` in this crate or set `-Zreg-struct-return=true` in `default_reg_struct_return`
1010
= help: if you are sure this will not cause problems, you may use `-Cunsafe-allow-abi-mismatch=reg-struct-return` to silence this error
1111

1212
error: aborting due to 1 previous error
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
error: mixing `-Zreg-struct-return` will cause an ABI mismatch in crate `no_value_bool`
2+
--> $DIR/no_value_bool.rs:16:1
3+
|
4+
LL | #![feature(no_core)]
5+
| ^
6+
|
7+
= help: the `-Zreg-struct-return` flag modifies the ABI so Rust crates compiled with different values of this flag cannot be used together safely
8+
= note: unset `-Zreg-struct-return` in this crate is incompatible with `-Zreg-struct-return=true` in dependency `enabled_reg_struct_return`
9+
= help: set `-Zreg-struct-return=true` in this crate or unset `-Zreg-struct-return` in `enabled_reg_struct_return`
10+
= help: if you are sure this will not cause problems, you may use `-Cunsafe-allow-abi-mismatch=reg-struct-return` to silence this error
11+
12+
error: aborting due to 1 previous error
13+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
error: mixing `-Zreg-struct-return` will cause an ABI mismatch in crate `no_value_bool`
2+
--> $DIR/no_value_bool.rs:16:1
3+
|
4+
LL | #![feature(no_core)]
5+
| ^
6+
|
7+
= help: the `-Zreg-struct-return` flag modifies the ABI so Rust crates compiled with different values of this flag cannot be used together safely
8+
= note: unset `-Zreg-struct-return` in this crate is incompatible with `-Zreg-struct-return=true` in dependency `enabled_reg_struct_return`
9+
= help: set `-Zreg-struct-return=true` in this crate or unset `-Zreg-struct-return` in `enabled_reg_struct_return`
10+
= help: if you are sure this will not cause problems, you may use `-Cunsafe-allow-abi-mismatch=reg-struct-return` to silence this error
11+
12+
error: aborting due to 1 previous error
13+
+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Tests that bool target modifier value (true) in dependency crate is ok linked
2+
// with the -Zflag specified without value (-Zflag=true is consistent with -Zflag)
3+
4+
//@ aux-build:enabled_reg_struct_return.rs
5+
//@ compile-flags: --target i686-unknown-linux-gnu -Cpanic=abort
6+
//@ needs-llvm-components: x86
7+
8+
//@ revisions: ok ok_explicit error error_explicit
9+
//@[ok] compile-flags: -Zreg-struct-return
10+
//@[ok_explicit] compile-flags: -Zreg-struct-return=true
11+
//@[error] compile-flags:
12+
//@[error_explicit] compile-flags: -Zreg-struct-return=false
13+
//@[ok] check-pass
14+
//@[ok_explicit] check-pass
15+
16+
#![feature(no_core)]
17+
//[error]~^ ERROR mixing `-Zreg-struct-return` will cause an ABI mismatch in crate `no_value_bool`
18+
//[error_explicit]~^^ ERROR mixing `-Zreg-struct-return` will cause an ABI mismatch in crate `no_value_bool`
19+
#![crate_type = "rlib"]
20+
#![no_core]
21+
22+
extern crate enabled_reg_struct_return;

0 commit comments

Comments
 (0)