Rollup merge of #138483 - azhogin:azhogin/target-modifiers-bool-fix, r=fee1-dead
Target modifiers fix for bool flags without value Fixed support of boolean flags without values: `-Zbool-flag` is now consistent with `-Zbool-flag=true` in another crate. When flag is explicitly set to default value, target modifier will not be set in crate metainfo (`-Zflag=false` when `false` is a default value for the flag). Improved error notification when target modifier flag is absent in a crate ("-Zflag unset"). Example: ``` note: `-Zreg-struct-return=true` in this crate is incompatible with unset `-Zreg-struct-return` in dependency `default_reg_struct_return` ```
This commit is contained in:
commit
7eb27a9cf9
9 changed files with 184 additions and 49 deletions
|
@ -118,12 +118,23 @@ metadata_incompatible_rustc =
|
|||
|
||||
metadata_incompatible_target_modifiers =
|
||||
mixing `{$flag_name_prefixed}` will cause an ABI mismatch in crate `{$local_crate}`
|
||||
.note = `{$flag_name_prefixed}={$flag_local_value}` in this crate is incompatible with `{$flag_name_prefixed}={$flag_extern_value}` in dependency `{$extern_crate}`
|
||||
.note = `{$flag_name_prefixed}={$local_value}` in this crate is incompatible with `{$flag_name_prefixed}={$extern_value}` in dependency `{$extern_crate}`
|
||||
.help = the `{$flag_name_prefixed}` flag modifies the ABI so Rust crates compiled with different values of this flag cannot be used together safely
|
||||
|
||||
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
|
||||
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}`
|
||||
metadata_incompatible_target_modifiers_help_fix = set `{$flag_name_prefixed}={$extern_value}` in this crate or `{$flag_name_prefixed}={$local_value}` in `{$extern_crate}`
|
||||
|
||||
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}`
|
||||
|
||||
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}`
|
||||
|
||||
metadata_incompatible_target_modifiers_l_missed =
|
||||
mixing `{$flag_name_prefixed}` will cause an ABI mismatch in crate `{$local_crate}`
|
||||
.note = unset `{$flag_name_prefixed}` in this crate is incompatible with `{$flag_name_prefixed}={$extern_value}` in dependency `{$extern_crate}`
|
||||
.help = the `{$flag_name_prefixed}` flag modifies the ABI so Rust crates compiled with different values of this flag cannot be used together safely
|
||||
metadata_incompatible_target_modifiers_r_missed =
|
||||
mixing `{$flag_name_prefixed}` will cause an ABI mismatch in crate `{$local_crate}`
|
||||
.note = `{$flag_name_prefixed}={$local_value}` in this crate is incompatible with unset `{$flag_name_prefixed}` in dependency `{$extern_crate}`
|
||||
.help = the `{$flag_name_prefixed}` flag modifies the ABI so Rust crates compiled with different values of this flag cannot be used together safely
|
||||
metadata_incompatible_wasm_link =
|
||||
`wasm_import_module` is incompatible with other arguments in `#[link]` attributes
|
||||
|
||||
|
|
|
@ -358,30 +358,58 @@ impl CStore {
|
|||
) {
|
||||
let span = krate.spans.inner_span.shrink_to_lo();
|
||||
let allowed_flag_mismatches = &tcx.sess.opts.cg.unsafe_allow_abi_mismatch;
|
||||
let name = tcx.crate_name(LOCAL_CRATE);
|
||||
let local_crate = tcx.crate_name(LOCAL_CRATE);
|
||||
let tmod_extender = |tmod: &TargetModifier| (tmod.extend(), tmod.clone());
|
||||
let report_diff = |prefix: &String,
|
||||
opt_name: &String,
|
||||
flag_local_value: &String,
|
||||
flag_extern_value: &String| {
|
||||
flag_local_value: Option<&String>,
|
||||
flag_extern_value: Option<&String>| {
|
||||
if allowed_flag_mismatches.contains(&opt_name) {
|
||||
return;
|
||||
}
|
||||
tcx.dcx().emit_err(errors::IncompatibleTargetModifiers {
|
||||
span,
|
||||
extern_crate: data.name(),
|
||||
local_crate: name,
|
||||
flag_name: opt_name.clone(),
|
||||
flag_name_prefixed: format!("-{}{}", prefix, opt_name),
|
||||
flag_local_value: flag_local_value.to_string(),
|
||||
flag_extern_value: flag_extern_value.to_string(),
|
||||
});
|
||||
let extern_crate = data.name();
|
||||
let flag_name = opt_name.clone();
|
||||
let flag_name_prefixed = format!("-{}{}", prefix, opt_name);
|
||||
|
||||
match (flag_local_value, flag_extern_value) {
|
||||
(Some(local_value), Some(extern_value)) => {
|
||||
tcx.dcx().emit_err(errors::IncompatibleTargetModifiers {
|
||||
span,
|
||||
extern_crate,
|
||||
local_crate,
|
||||
flag_name,
|
||||
flag_name_prefixed,
|
||||
local_value: local_value.to_string(),
|
||||
extern_value: extern_value.to_string(),
|
||||
})
|
||||
}
|
||||
(None, Some(extern_value)) => {
|
||||
tcx.dcx().emit_err(errors::IncompatibleTargetModifiersLMissed {
|
||||
span,
|
||||
extern_crate,
|
||||
local_crate,
|
||||
flag_name,
|
||||
flag_name_prefixed,
|
||||
extern_value: extern_value.to_string(),
|
||||
})
|
||||
}
|
||||
(Some(local_value), None) => {
|
||||
tcx.dcx().emit_err(errors::IncompatibleTargetModifiersRMissed {
|
||||
span,
|
||||
extern_crate,
|
||||
local_crate,
|
||||
flag_name,
|
||||
flag_name_prefixed,
|
||||
local_value: local_value.to_string(),
|
||||
})
|
||||
}
|
||||
(None, None) => panic!("Incorrect target modifiers report_diff(None, None)"),
|
||||
};
|
||||
};
|
||||
let mut it1 = mods.iter().map(tmod_extender);
|
||||
let mut it2 = dep_mods.iter().map(tmod_extender);
|
||||
let mut left_name_val: Option<(ExtendedTargetModifierInfo, TargetModifier)> = None;
|
||||
let mut right_name_val: Option<(ExtendedTargetModifierInfo, TargetModifier)> = None;
|
||||
let no_val = "*".to_string();
|
||||
loop {
|
||||
left_name_val = left_name_val.or_else(|| it1.next());
|
||||
right_name_val = right_name_val.or_else(|| it2.next());
|
||||
|
@ -389,26 +417,31 @@ impl CStore {
|
|||
(Some(l), Some(r)) => match l.1.opt.cmp(&r.1.opt) {
|
||||
cmp::Ordering::Equal => {
|
||||
if l.0.tech_value != r.0.tech_value {
|
||||
report_diff(&l.0.prefix, &l.0.name, &l.1.value_name, &r.1.value_name);
|
||||
report_diff(
|
||||
&l.0.prefix,
|
||||
&l.0.name,
|
||||
Some(&l.1.value_name),
|
||||
Some(&r.1.value_name),
|
||||
);
|
||||
}
|
||||
left_name_val = None;
|
||||
right_name_val = None;
|
||||
}
|
||||
cmp::Ordering::Greater => {
|
||||
report_diff(&r.0.prefix, &r.0.name, &no_val, &r.1.value_name);
|
||||
report_diff(&r.0.prefix, &r.0.name, None, Some(&r.1.value_name));
|
||||
right_name_val = None;
|
||||
}
|
||||
cmp::Ordering::Less => {
|
||||
report_diff(&l.0.prefix, &l.0.name, &l.1.value_name, &no_val);
|
||||
report_diff(&l.0.prefix, &l.0.name, Some(&l.1.value_name), None);
|
||||
left_name_val = None;
|
||||
}
|
||||
},
|
||||
(Some(l), None) => {
|
||||
report_diff(&l.0.prefix, &l.0.name, &l.1.value_name, &no_val);
|
||||
report_diff(&l.0.prefix, &l.0.name, Some(&l.1.value_name), None);
|
||||
left_name_val = None;
|
||||
}
|
||||
(None, Some(r)) => {
|
||||
report_diff(&r.0.prefix, &r.0.name, &no_val, &r.1.value_name);
|
||||
report_diff(&r.0.prefix, &r.0.name, None, Some(&r.1.value_name));
|
||||
right_name_val = None;
|
||||
}
|
||||
(None, None) => break,
|
||||
|
|
|
@ -759,8 +759,40 @@ pub struct IncompatibleTargetModifiers {
|
|||
pub local_crate: Symbol,
|
||||
pub flag_name: String,
|
||||
pub flag_name_prefixed: String,
|
||||
pub flag_local_value: String,
|
||||
pub flag_extern_value: String,
|
||||
pub local_value: String,
|
||||
pub extern_value: String,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(metadata_incompatible_target_modifiers_l_missed)]
|
||||
#[help]
|
||||
#[note]
|
||||
#[help(metadata_incompatible_target_modifiers_help_fix_l_missed)]
|
||||
#[help(metadata_incompatible_target_modifiers_help_allow)]
|
||||
pub struct IncompatibleTargetModifiersLMissed {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub extern_crate: Symbol,
|
||||
pub local_crate: Symbol,
|
||||
pub flag_name: String,
|
||||
pub flag_name_prefixed: String,
|
||||
pub extern_value: String,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(metadata_incompatible_target_modifiers_r_missed)]
|
||||
#[help]
|
||||
#[note]
|
||||
#[help(metadata_incompatible_target_modifiers_help_fix_r_missed)]
|
||||
#[help(metadata_incompatible_target_modifiers_help_allow)]
|
||||
pub struct IncompatibleTargetModifiersRMissed {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub extern_crate: Symbol,
|
||||
pub local_crate: Symbol,
|
||||
pub flag_name: String,
|
||||
pub flag_name_prefixed: String,
|
||||
pub local_value: String,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
|
|
|
@ -94,45 +94,49 @@ fn tmod_push_impl(
|
|||
tmod_vals: &BTreeMap<OptionsTargetModifiers, String>,
|
||||
tmods: &mut Vec<TargetModifier>,
|
||||
) {
|
||||
tmods.push(TargetModifier { opt, value_name: tmod_vals.get(&opt).cloned().unwrap_or_default() })
|
||||
if let Some(v) = tmod_vals.get(&opt) {
|
||||
tmods.push(TargetModifier { opt, value_name: v.clone() })
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! tmod_push {
|
||||
($struct_name:ident, $tmod_enum_name:ident, $opt_name:ident, $mods:expr, $tmod_vals:expr) => {
|
||||
tmod_push_impl(
|
||||
OptionsTargetModifiers::$struct_name($tmod_enum_name::$opt_name),
|
||||
$tmod_vals,
|
||||
$mods,
|
||||
);
|
||||
($struct_name:ident, $tmod_enum_name:ident, $opt_name:ident, $opt_expr:expr, $init:expr, $mods:expr, $tmod_vals:expr) => {
|
||||
if *$opt_expr != $init {
|
||||
tmod_push_impl(
|
||||
OptionsTargetModifiers::$struct_name($tmod_enum_name::$opt_name),
|
||||
$tmod_vals,
|
||||
$mods,
|
||||
);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! gather_tmods {
|
||||
($struct_name:ident, $tmod_enum_name:ident, $opt_name:ident, $opt_expr:expr, $mods:expr, $tmod_vals:expr,
|
||||
($struct_name:ident, $tmod_enum_name:ident, $opt_name:ident, $opt_expr:expr, $init:expr, $mods:expr, $tmod_vals:expr,
|
||||
[SUBSTRUCT], [TARGET_MODIFIER]) => {
|
||||
compile_error!("SUBSTRUCT can't be target modifier");
|
||||
};
|
||||
($struct_name:ident, $tmod_enum_name:ident, $opt_name:ident, $opt_expr:expr, $mods:expr, $tmod_vals:expr,
|
||||
($struct_name:ident, $tmod_enum_name:ident, $opt_name:ident, $opt_expr:expr, $init:expr, $mods:expr, $tmod_vals:expr,
|
||||
[UNTRACKED], [TARGET_MODIFIER]) => {
|
||||
tmod_push!($struct_name, $tmod_enum_name, $opt_name, $mods, $tmod_vals)
|
||||
tmod_push!($struct_name, $tmod_enum_name, $opt_name, $opt_expr, $init, $mods, $tmod_vals)
|
||||
};
|
||||
($struct_name:ident, $tmod_enum_name:ident, $opt_name:ident, $opt_expr:expr, $mods:expr, $tmod_vals:expr,
|
||||
($struct_name:ident, $tmod_enum_name:ident, $opt_name:ident, $opt_expr:expr, $init:expr, $mods:expr, $tmod_vals:expr,
|
||||
[TRACKED], [TARGET_MODIFIER]) => {
|
||||
tmod_push!($struct_name, $tmod_enum_name, $opt_name, $mods, $tmod_vals)
|
||||
tmod_push!($struct_name, $tmod_enum_name, $opt_name, $opt_expr, $init, $mods, $tmod_vals)
|
||||
};
|
||||
($struct_name:ident, $tmod_enum_name:ident, $opt_name:ident, $opt_expr:expr, $mods:expr, $tmod_vals:expr,
|
||||
($struct_name:ident, $tmod_enum_name:ident, $opt_name:ident, $opt_expr:expr, $init:expr, $mods:expr, $tmod_vals:expr,
|
||||
[TRACKED_NO_CRATE_HASH], [TARGET_MODIFIER]) => {
|
||||
tmod_push!($struct_name, $tmod_enum_name, $opt_name, $mods, $tmod_vals)
|
||||
tmod_push!($struct_name, $tmod_enum_name, $opt_name, $opt_expr, $init, $mods, $tmod_vals)
|
||||
};
|
||||
($struct_name:ident, $tmod_enum_name:ident, $opt_name:ident, $opt_expr:expr, $mods:expr, $tmod_vals:expr,
|
||||
($struct_name:ident, $tmod_enum_name:ident, $opt_name:ident, $opt_expr:expr, $init:expr, $mods:expr, $tmod_vals:expr,
|
||||
[SUBSTRUCT], []) => {
|
||||
$opt_expr.gather_target_modifiers($mods, $tmod_vals);
|
||||
};
|
||||
($struct_name:ident, $tmod_enum_name:ident, $opt_name:ident, $opt_expr:expr, $mods:expr, $tmod_vals:expr,
|
||||
($struct_name:ident, $tmod_enum_name:ident, $opt_name:ident, $opt_expr:expr, $init:expr, $mods:expr, $tmod_vals:expr,
|
||||
[UNTRACKED], []) => {{}};
|
||||
($struct_name:ident, $tmod_enum_name:ident, $opt_name:ident, $opt_expr:expr, $mods:expr, $tmod_vals:expr,
|
||||
($struct_name:ident, $tmod_enum_name:ident, $opt_name:ident, $opt_expr:expr, $init:expr, $mods:expr, $tmod_vals:expr,
|
||||
[TRACKED], []) => {{}};
|
||||
($struct_name:ident, $tmod_enum_name:ident, $opt_name:ident, $opt_expr:expr, $mods:expr, $tmod_vals:expr,
|
||||
($struct_name:ident, $tmod_enum_name:ident, $opt_name:ident, $opt_expr:expr, $init:expr, $mods:expr, $tmod_vals:expr,
|
||||
[TRACKED_NO_CRATE_HASH], []) => {{}};
|
||||
}
|
||||
|
||||
|
@ -474,7 +478,8 @@ macro_rules! tmod_enum {
|
|||
$($pout)*
|
||||
Self::$opt => {
|
||||
let mut parsed : $t = Default::default();
|
||||
parse::$parse(&mut parsed, Some($puser_value));
|
||||
let val = if $puser_value.is_empty() { None } else { Some($puser_value) };
|
||||
parse::$parse(&mut parsed, val);
|
||||
ExtendedTargetModifierInfo {
|
||||
prefix: $prefix.to_string(),
|
||||
name: stringify!($opt).to_string().replace('_', "-"),
|
||||
|
@ -569,7 +574,7 @@ macro_rules! options {
|
|||
_tmod_vals: &BTreeMap<OptionsTargetModifiers, String>,
|
||||
) {
|
||||
$({
|
||||
gather_tmods!($struct_name, $tmod_enum_name, $opt, &self.$opt, _mods, _tmod_vals,
|
||||
gather_tmods!($struct_name, $tmod_enum_name, $opt, &self.$opt, $init, _mods, _tmod_vals,
|
||||
[$dep_tracking_marker], [$($tmod),*]);
|
||||
})*
|
||||
}
|
||||
|
@ -681,10 +686,9 @@ fn build_options<O: Default>(
|
|||
),
|
||||
}
|
||||
}
|
||||
if let Some(tmod) = *tmod
|
||||
&& let Some(value) = value
|
||||
{
|
||||
target_modifiers.insert(tmod, value.to_string());
|
||||
if let Some(tmod) = *tmod {
|
||||
let v = value.map_or(String::new(), ToOwned::to_owned);
|
||||
target_modifiers.insert(tmod, v);
|
||||
}
|
||||
}
|
||||
None => early_dcx.early_fatal(format!("unknown {outputname} option: `{key}`")),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue