parse_error(tcx, item.span,
"this attribute must have a valid value",
"expected value here",
- Some(r#"eg `#[rustc_on_unimplemented = "foo"]`"#));
+ Some(r#"eg `#[rustc_on_unimplemented(message="foo")]`"#));
}
if errored {
return Err(parse_error(tcx, attr.span,
"`#[rustc_on_unimplemented]` requires a value",
"value required here",
- Some(r#"eg `#[rustc_on_unimplemented = "foo"]`"#)));
+ Some(r#"eg `#[rustc_on_unimplemented(message="foo")]`"#)));
};
debug!("of_item({:?}/{:?}) = {:?}", trait_def_id, impl_def_id, result);
result
}
}
+ let options: FxHashMap<String, String> = options.into_iter()
+ .filter_map(|(k, v)| v.as_ref().map(|v| (k.to_owned(), v.to_owned())))
+ .collect();
OnUnimplementedNote {
- label: label.map(|l| l.format(tcx, trait_ref)),
- message: message.map(|m| m.format(tcx, trait_ref)),
- note: note.map(|n| n.format(tcx, trait_ref)),
+ label: label.map(|l| l.format(tcx, trait_ref, &options)),
+ message: message.map(|m| m.format(tcx, trait_ref, &options)),
+ note: note.map(|n| n.format(tcx, trait_ref, &options)),
}
}
}
Position::ArgumentNamed(s) if s == "Self" => (),
// `{ThisTraitsName}` is allowed
Position::ArgumentNamed(s) if s == name => (),
+ // `{from_method}` is allowed
+ Position::ArgumentNamed(s) if s == "from_method" => (),
+ // `{from_desugaring}` is allowed
+ Position::ArgumentNamed(s) if s == "from_desugaring" => (),
// So is `{A}` if A is a type parameter
Position::ArgumentNamed(s) => match generics.params.iter().find(|param| {
param.name == s
Some(_) => (),
None => {
span_err!(tcx.sess, span, E0230,
- "there is no parameter \
- {} on trait {}",
- s, name);
+ "there is no parameter `{}` on trait `{}`", s, name);
result = Err(ErrorReported);
}
},
// `{:1}` and `{}` are not to be used
Position::ArgumentIs(_) | Position::ArgumentImplicitlyIs(_) => {
span_err!(tcx.sess, span, E0231,
- "only named substitution \
- parameters are allowed");
+ "only named substitution parameters are allowed");
result = Err(ErrorReported);
}
}
pub fn format(&self,
tcx: TyCtxt<'a, 'gcx, 'tcx>,
- trait_ref: ty::TraitRef<'tcx>)
+ trait_ref: ty::TraitRef<'tcx>,
+ options: &FxHashMap<String, String>)
-> String
{
let name = tcx.item_name(trait_ref.def_id);
let name = param.name.to_string();
Some((name, value))
}).collect::<FxHashMap<String, String>>();
+ let empty_string = String::new();
let parser = Parser::new(&self.0, None);
parser.map(|p| {
&trait_str
}
None => {
- bug!("broken on_unimplemented {:?} for {:?}: \
- no argument matching {:?}",
- self.0, trait_ref, s)
+ if let Some(val) = options.get(s) {
+ val
+ } else if s == "from_desugaring" || s == "from_method" {
+ // don't break messages using these two arguments incorrectly
+ &empty_string
+ } else {
+ bug!("broken on_unimplemented {:?} for {:?}: \
+ no argument matching {:?}",
+ self.0, trait_ref, s)
+ }
}
},
_ => {
- bug!("broken on_unimplemented {:?} - bad \
- format arg", self.0)
+ bug!("broken on_unimplemented {:?} - bad format arg", self.0)
}
}
}
LL | #[rustc_on_unimplemented] //~ ERROR `#[rustc_on_unimplemented]` requires a value
| ^^^^^^^^^^^^^^^^^^^^^^^^^ value required here
|
- = note: eg `#[rustc_on_unimplemented = "foo"]`
+ = note: eg `#[rustc_on_unimplemented(message="foo")]`
-error[E0230]: there is no parameter C on trait BadAnnotation2
+error[E0230]: there is no parameter `C` on trait `BadAnnotation2`
--> $DIR/bad-annotation.rs:30:1
|
LL | #[rustc_on_unimplemented = "Unimplemented trait error on `{Self}` with params `<{A},{B},{C}>`"]
LL | #[rustc_on_unimplemented(lorem="")]
| ^^^^^^^^ expected value here
|
- = note: eg `#[rustc_on_unimplemented = "foo"]`
+ = note: eg `#[rustc_on_unimplemented(message="foo")]`
error[E0232]: this attribute must have a valid value
--> $DIR/bad-annotation.rs:44:26
LL | #[rustc_on_unimplemented(lorem(ipsum(dolor)))]
| ^^^^^^^^^^^^^^^^^^^ expected value here
|
- = note: eg `#[rustc_on_unimplemented = "foo"]`
+ = note: eg `#[rustc_on_unimplemented(message="foo")]`
error[E0232]: this attribute must have a valid value
--> $DIR/bad-annotation.rs:48:39
LL | #[rustc_on_unimplemented(message="x", message="y")]
| ^^^^^^^^^^^ expected value here
|
- = note: eg `#[rustc_on_unimplemented = "foo"]`
+ = note: eg `#[rustc_on_unimplemented(message="foo")]`
error[E0232]: this attribute must have a valid value
--> $DIR/bad-annotation.rs:52:39
LL | #[rustc_on_unimplemented(message="x", on(desugared, message="y"))]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected value here
|
- = note: eg `#[rustc_on_unimplemented = "foo"]`
+ = note: eg `#[rustc_on_unimplemented(message="foo")]`
error[E0232]: empty `on`-clause in `#[rustc_on_unimplemented]`
--> $DIR/bad-annotation.rs:56:26
LL | #[rustc_on_unimplemented(on="x", message="y")]
| ^^^^^^ expected value here
|
- = note: eg `#[rustc_on_unimplemented = "foo"]`
+ = note: eg `#[rustc_on_unimplemented(message="foo")]`
error[E0232]: this attribute must have a valid value
--> $DIR/bad-annotation.rs:67:40
LL | #[rustc_on_unimplemented(on(desugared, on(desugared, message="x")), message="y")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected value here
|
- = note: eg `#[rustc_on_unimplemented = "foo"]`
+ = note: eg `#[rustc_on_unimplemented(message="foo")]`
error: aborting due to 10 previous errors