1
Fork 0

Allow substitutions in rustc_on_unimplemented predicate

This commit is contained in:
Michael Goulet 2021-12-01 18:50:46 -08:00
parent b7cd0f7864
commit f43e3a86a7
2 changed files with 39 additions and 12 deletions

View file

@ -668,6 +668,7 @@ symbols! {
fill, fill,
finish, finish,
flags, flags,
float,
float_to_int_unchecked, float_to_int_unchecked,
floorf32, floorf32,
floorf64, floorf64,
@ -771,6 +772,8 @@ symbols! {
inline_const_pat, inline_const_pat,
inout, inout,
instruction_set, instruction_set,
integer_: "integer",
integral,
intel, intel,
into_future, into_future,
into_iter, into_iter,

View file

@ -62,6 +62,10 @@ impl<'tcx> OnUnimplementedDirective {
let mut errored = false; let mut errored = false;
let mut item_iter = items.iter(); let mut item_iter = items.iter();
let parse_value = |value_str| {
OnUnimplementedFormatString::try_parse(tcx, trait_def_id, value_str, span).map(Some)
};
let condition = if is_root { let condition = if is_root {
None None
} else { } else {
@ -86,7 +90,14 @@ impl<'tcx> OnUnimplementedDirective {
None, None,
) )
})?; })?;
attr::eval_condition(cond, &tcx.sess.parse_sess, Some(tcx.features()), &mut |_| true); attr::eval_condition(cond, &tcx.sess.parse_sess, Some(tcx.features()), &mut |item| {
if let Some(symbol) = item.value_str() {
if parse_value(symbol).is_err() {
errored = true;
}
}
true
});
Some(cond.clone()) Some(cond.clone())
}; };
@ -97,10 +108,6 @@ impl<'tcx> OnUnimplementedDirective {
let mut subcommands = vec![]; let mut subcommands = vec![];
let mut append_const_msg = None; let mut append_const_msg = None;
let parse_value = |value_str| {
OnUnimplementedFormatString::try_parse(tcx, trait_def_id, value_str, span).map(Some)
};
for item in item_iter { for item in item_iter {
if item.has_name(sym::message) && message.is_none() { if item.has_name(sym::message) && message.is_none() {
if let Some(message_) = item.value_str() { if let Some(message_) = item.value_str() {
@ -221,6 +228,9 @@ impl<'tcx> OnUnimplementedDirective {
let mut append_const_msg = None; let mut append_const_msg = None;
info!("evaluate({:?}, trait_ref={:?}, options={:?})", self, trait_ref, options); info!("evaluate({:?}, trait_ref={:?}, options={:?})", self, trait_ref, options);
let options_map: FxHashMap<Symbol, String> =
options.iter().filter_map(|(k, v)| v.as_ref().map(|v| (*k, v.to_owned()))).collect();
for command in self.subcommands.iter().chain(Some(self)).rev() { for command in self.subcommands.iter().chain(Some(self)).rev() {
if let Some(ref condition) = command.condition { if let Some(ref condition) = command.condition {
if !attr::eval_condition( if !attr::eval_condition(
@ -229,7 +239,11 @@ impl<'tcx> OnUnimplementedDirective {
Some(tcx.features()), Some(tcx.features()),
&mut |c| { &mut |c| {
c.ident().map_or(false, |ident| { c.ident().map_or(false, |ident| {
options.contains(&(ident.name, c.value_str().map(|s| s.to_string()))) let value = c.value_str().map(|s| {
OnUnimplementedFormatString(s).format(tcx, trait_ref, &options_map)
});
options.contains(&(ident.name, value))
}) })
}, },
) { ) {
@ -257,13 +271,11 @@ impl<'tcx> OnUnimplementedDirective {
append_const_msg = command.append_const_msg.clone(); append_const_msg = command.append_const_msg.clone();
} }
let options: FxHashMap<Symbol, String> =
options.iter().filter_map(|(k, v)| v.as_ref().map(|v| (*k, v.to_owned()))).collect();
OnUnimplementedNote { OnUnimplementedNote {
label: label.map(|l| l.format(tcx, trait_ref, &options)), label: label.map(|l| l.format(tcx, trait_ref, &options_map)),
message: message.map(|m| m.format(tcx, trait_ref, &options)), message: message.map(|m| m.format(tcx, trait_ref, &options_map)),
note: note.map(|n| n.format(tcx, trait_ref, &options)), note: note.map(|n| n.format(tcx, trait_ref, &options_map)),
enclosing_scope: enclosing_scope.map(|e_s| e_s.format(tcx, trait_ref, &options)), enclosing_scope: enclosing_scope.map(|e_s| e_s.format(tcx, trait_ref, &options_map)),
append_const_msg, append_const_msg,
} }
} }
@ -306,6 +318,12 @@ impl<'tcx> OnUnimplementedFormatString {
Position::ArgumentNamed(s) if s == sym::from_desugaring => (), Position::ArgumentNamed(s) if s == sym::from_desugaring => (),
// `{ItemContext}` is allowed // `{ItemContext}` is allowed
Position::ArgumentNamed(s) if s == sym::ItemContext => (), Position::ArgumentNamed(s) if s == sym::ItemContext => (),
// `{integral}` and `{integer}` and `{float}` are allowed
Position::ArgumentNamed(s)
if s == sym::integral || s == sym::integer_ || s == sym::float =>
{
()
}
// So is `{A}` if A is a type parameter // So is `{A}` if A is a type parameter
Position::ArgumentNamed(s) => { Position::ArgumentNamed(s) => {
match generics.params.iter().find(|param| param.name == s) { match generics.params.iter().find(|param| param.name == s) {
@ -385,6 +403,12 @@ impl<'tcx> OnUnimplementedFormatString {
&empty_string &empty_string
} else if s == sym::ItemContext { } else if s == sym::ItemContext {
&item_context &item_context
} else if s == sym::integral {
"{integral}"
} else if s == sym::integer_ {
"{integer}"
} else if s == sym::float {
"{float}"
} else { } else {
bug!( bug!(
"broken on_unimplemented {:?} for {:?}: \ "broken on_unimplemented {:?} for {:?}: \