Skip to content

Commit 908d92f

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

File tree

9 files changed

+117
-40
lines changed

9 files changed

+117
-40
lines changed

compiler/rustc_metadata/messages.ftl

+2-2
Original file line numberDiff line numberDiff line change
@@ -118,11 +118,11 @@ 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 = `{$local_descr}` in this crate is incompatible with `{$extern_descr}` 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
123123
124124
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}`
125+
metadata_incompatible_target_modifiers_help_fix = set `{$extern_descr}` in this crate or `{$local_descr}` in `{$extern_crate}`
126126
127127
metadata_incompatible_wasm_link =
128128
`wasm_import_module` is incompatible with other arguments in `#[link]` attributes

compiler/rustc_metadata/src/creader.rs

+28-10
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,23 @@ impl CStore {
349349
}
350350
}
351351

352+
// For correct notification of target modifier flag state in errors
353+
// Example:
354+
// `-Zbool-flag unset`,
355+
// `-Zbool-flag` when flag is set without value,
356+
// `-Zbool-flag=false/true` when flag is set with value
357+
fn target_modifier_val_descr(prefix: &String, name: &String, value: Option<&String>) -> String {
358+
if let Some(v) = value {
359+
if v.is_empty() {
360+
format!("-{}{}", prefix, name)
361+
} else {
362+
format!("-{}{}={}", prefix, name, v)
363+
}
364+
} else {
365+
format!("-{}{} unset", prefix, name)
366+
}
367+
}
368+
352369
fn report_target_modifiers_extended(
353370
tcx: TyCtxt<'_>,
354371
krate: &Crate,
@@ -362,53 +379,54 @@ impl CStore {
362379
let tmod_extender = |tmod: &TargetModifier| (tmod.extend(), tmod.clone());
363380
let report_diff = |prefix: &String,
364381
opt_name: &String,
365-
flag_local_value: &String,
366-
flag_extern_value: &String| {
382+
flag_local_value: Option<&String>,
383+
flag_extern_value: Option<&String>| {
367384
if allowed_flag_mismatches.contains(&opt_name) {
368385
return;
369386
}
387+
let local_descr = Self::target_modifier_val_descr(prefix, opt_name, flag_local_value);
388+
let extern_descr = Self::target_modifier_val_descr(prefix, opt_name, flag_extern_value);
370389
tcx.dcx().emit_err(errors::IncompatibleTargetModifiers {
371390
span,
372391
extern_crate: data.name(),
373392
local_crate: name,
374393
flag_name: opt_name.clone(),
375394
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(),
395+
local_descr,
396+
extern_descr,
378397
});
379398
};
380399
let mut it1 = mods.iter().map(tmod_extender);
381400
let mut it2 = dep_mods.iter().map(tmod_extender);
382401
let mut left_name_val: Option<(ExtendedTargetModifierInfo, TargetModifier)> = None;
383402
let mut right_name_val: Option<(ExtendedTargetModifierInfo, TargetModifier)> = None;
384-
let no_val = "*".to_string();
385403
loop {
386404
left_name_val = left_name_val.or_else(|| it1.next());
387405
right_name_val = right_name_val.or_else(|| it2.next());
388406
match (&left_name_val, &right_name_val) {
389407
(Some(l), Some(r)) => match l.1.opt.cmp(&r.1.opt) {
390408
cmp::Ordering::Equal => {
391409
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);
410+
report_diff(&l.0.prefix, &l.0.name, Some(&l.1.value_name), Some(&r.1.value_name));
393411
}
394412
left_name_val = None;
395413
right_name_val = None;
396414
}
397415
cmp::Ordering::Greater => {
398-
report_diff(&r.0.prefix, &r.0.name, &no_val, &r.1.value_name);
416+
report_diff(&r.0.prefix, &r.0.name, None, Some(&r.1.value_name));
399417
right_name_val = None;
400418
}
401419
cmp::Ordering::Less => {
402-
report_diff(&l.0.prefix, &l.0.name, &l.1.value_name, &no_val);
420+
report_diff(&l.0.prefix, &l.0.name, Some(&l.1.value_name), None);
403421
left_name_val = None;
404422
}
405423
},
406424
(Some(l), None) => {
407-
report_diff(&l.0.prefix, &l.0.name, &l.1.value_name, &no_val);
425+
report_diff(&l.0.prefix, &l.0.name, Some(&l.1.value_name), None);
408426
left_name_val = None;
409427
}
410428
(None, Some(r)) => {
411-
report_diff(&r.0.prefix, &r.0.name, &no_val, &r.1.value_name);
429+
report_diff(&r.0.prefix, &r.0.name, None, Some(&r.1.value_name));
412430
right_name_val = None;
413431
}
414432
(None, None) => break,

compiler/rustc_metadata/src/errors.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -759,8 +759,8 @@ 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_descr: String,
763+
pub extern_descr: String,
764764
}
765765

766766
#[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 = if let Some(v) = value { v.to_string() } else { String::new() };
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 `-Zreg-struct-return unset` in dependency `default_reg_struct_return`
9+
= help: set `-Zreg-struct-return unset` in this crate or `-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: `-Zreg-struct-return unset` 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 `-Zreg-struct-return unset` 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: `-Zreg-struct-return unset` 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 `-Zreg-struct-return unset` 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)