Auto merge of #53295 - estebank:on-unimplemented, r=michaelwoerister
Various changes to `rustc_on_unimplemented` - Add `from_method` and `from_desugaring` to formatting options - Change wording of errors slightly
This commit is contained in:
commit
996e26c23f
4 changed files with 38 additions and 26 deletions
|
@ -131,7 +131,7 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedDirective {
|
||||||
parse_error(tcx, item.span,
|
parse_error(tcx, item.span,
|
||||||
"this attribute must have a valid value",
|
"this attribute must have a valid value",
|
||||||
"expected value here",
|
"expected value here",
|
||||||
Some(r#"eg `#[rustc_on_unimplemented = "foo"]`"#));
|
Some(r#"eg `#[rustc_on_unimplemented(message="foo")]`"#));
|
||||||
}
|
}
|
||||||
|
|
||||||
if errored {
|
if errored {
|
||||||
|
@ -170,7 +170,7 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedDirective {
|
||||||
return Err(parse_error(tcx, attr.span,
|
return Err(parse_error(tcx, attr.span,
|
||||||
"`#[rustc_on_unimplemented]` requires a value",
|
"`#[rustc_on_unimplemented]` requires a value",
|
||||||
"value required here",
|
"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);
|
debug!("of_item({:?}/{:?}) = {:?}", trait_def_id, impl_def_id, result);
|
||||||
result
|
result
|
||||||
|
@ -213,10 +213,13 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedDirective {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 {
|
OnUnimplementedNote {
|
||||||
label: label.map(|l| l.format(tcx, trait_ref)),
|
label: label.map(|l| l.format(tcx, trait_ref, &options)),
|
||||||
message: message.map(|m| m.format(tcx, trait_ref)),
|
message: message.map(|m| m.format(tcx, trait_ref, &options)),
|
||||||
note: note.map(|n| n.format(tcx, trait_ref)),
|
note: note.map(|n| n.format(tcx, trait_ref, &options)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -251,6 +254,10 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedFormatString {
|
||||||
Position::ArgumentNamed(s) if s == "Self" => (),
|
Position::ArgumentNamed(s) if s == "Self" => (),
|
||||||
// `{ThisTraitsName}` is allowed
|
// `{ThisTraitsName}` is allowed
|
||||||
Position::ArgumentNamed(s) if s == name => (),
|
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
|
// So is `{A}` if A is a type parameter
|
||||||
Position::ArgumentNamed(s) => match generics.params.iter().find(|param| {
|
Position::ArgumentNamed(s) => match generics.params.iter().find(|param| {
|
||||||
param.name == s
|
param.name == s
|
||||||
|
@ -258,17 +265,14 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedFormatString {
|
||||||
Some(_) => (),
|
Some(_) => (),
|
||||||
None => {
|
None => {
|
||||||
span_err!(tcx.sess, span, E0230,
|
span_err!(tcx.sess, span, E0230,
|
||||||
"there is no parameter \
|
"there is no parameter `{}` on trait `{}`", s, name);
|
||||||
{} on trait {}",
|
|
||||||
s, name);
|
|
||||||
result = Err(ErrorReported);
|
result = Err(ErrorReported);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// `{:1}` and `{}` are not to be used
|
// `{:1}` and `{}` are not to be used
|
||||||
Position::ArgumentIs(_) | Position::ArgumentImplicitlyIs(_) => {
|
Position::ArgumentIs(_) | Position::ArgumentImplicitlyIs(_) => {
|
||||||
span_err!(tcx.sess, span, E0231,
|
span_err!(tcx.sess, span, E0231,
|
||||||
"only named substitution \
|
"only named substitution parameters are allowed");
|
||||||
parameters are allowed");
|
|
||||||
result = Err(ErrorReported);
|
result = Err(ErrorReported);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -280,7 +284,8 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedFormatString {
|
||||||
|
|
||||||
pub fn format(&self,
|
pub fn format(&self,
|
||||||
tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||||
trait_ref: ty::TraitRef<'tcx>)
|
trait_ref: ty::TraitRef<'tcx>,
|
||||||
|
options: &FxHashMap<String, String>)
|
||||||
-> String
|
-> String
|
||||||
{
|
{
|
||||||
let name = tcx.item_name(trait_ref.def_id);
|
let name = tcx.item_name(trait_ref.def_id);
|
||||||
|
@ -296,6 +301,7 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedFormatString {
|
||||||
let name = param.name.to_string();
|
let name = param.name.to_string();
|
||||||
Some((name, value))
|
Some((name, value))
|
||||||
}).collect::<FxHashMap<String, String>>();
|
}).collect::<FxHashMap<String, String>>();
|
||||||
|
let empty_string = String::new();
|
||||||
|
|
||||||
let parser = Parser::new(&self.0, None);
|
let parser = Parser::new(&self.0, None);
|
||||||
parser.map(|p| {
|
parser.map(|p| {
|
||||||
|
@ -308,14 +314,20 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedFormatString {
|
||||||
&trait_str
|
&trait_str
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
bug!("broken on_unimplemented {:?} for {:?}: \
|
if let Some(val) = options.get(s) {
|
||||||
no argument matching {:?}",
|
val
|
||||||
self.0, trait_ref, s)
|
} 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 \
|
bug!("broken on_unimplemented {:?} - bad format arg", self.0)
|
||||||
format arg", self.0)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ error[E0232]: `#[rustc_on_unimplemented]` requires a value
|
||||||
LL | #[rustc_on_unimplemented]
|
LL | #[rustc_on_unimplemented]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ value required here
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^ value required here
|
||||||
|
|
|
|
||||||
= note: eg `#[rustc_on_unimplemented = "foo"]`
|
= note: eg `#[rustc_on_unimplemented(message="foo")]`
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@ trait BadAnnotation1
|
||||||
{}
|
{}
|
||||||
|
|
||||||
#[rustc_on_unimplemented = "Unimplemented trait error on `{Self}` with params `<{A},{B},{C}>`"]
|
#[rustc_on_unimplemented = "Unimplemented trait error on `{Self}` with params `<{A},{B},{C}>`"]
|
||||||
//~^ ERROR there is no parameter C on trait BadAnnotation2
|
//~^ ERROR there is no parameter `C` on trait `BadAnnotation2`
|
||||||
trait BadAnnotation2<A,B>
|
trait BadAnnotation2<A,B>
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
|
|
@ -4,9 +4,9 @@ error[E0232]: `#[rustc_on_unimplemented]` requires a value
|
||||||
LL | #[rustc_on_unimplemented] //~ ERROR `#[rustc_on_unimplemented]` requires a value
|
LL | #[rustc_on_unimplemented] //~ ERROR `#[rustc_on_unimplemented]` requires a value
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ value required here
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^ 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
|
--> $DIR/bad-annotation.rs:30:1
|
||||||
|
|
|
|
||||||
LL | #[rustc_on_unimplemented = "Unimplemented trait error on `{Self}` with params `<{A},{B},{C}>`"]
|
LL | #[rustc_on_unimplemented = "Unimplemented trait error on `{Self}` with params `<{A},{B},{C}>`"]
|
||||||
|
@ -24,7 +24,7 @@ error[E0232]: this attribute must have a valid value
|
||||||
LL | #[rustc_on_unimplemented(lorem="")]
|
LL | #[rustc_on_unimplemented(lorem="")]
|
||||||
| ^^^^^^^^ expected value here
|
| ^^^^^^^^ 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
|
error[E0232]: this attribute must have a valid value
|
||||||
--> $DIR/bad-annotation.rs:44:26
|
--> $DIR/bad-annotation.rs:44:26
|
||||||
|
@ -32,7 +32,7 @@ error[E0232]: this attribute must have a valid value
|
||||||
LL | #[rustc_on_unimplemented(lorem(ipsum(dolor)))]
|
LL | #[rustc_on_unimplemented(lorem(ipsum(dolor)))]
|
||||||
| ^^^^^^^^^^^^^^^^^^^ expected value here
|
| ^^^^^^^^^^^^^^^^^^^ 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
|
error[E0232]: this attribute must have a valid value
|
||||||
--> $DIR/bad-annotation.rs:48:39
|
--> $DIR/bad-annotation.rs:48:39
|
||||||
|
@ -40,7 +40,7 @@ error[E0232]: this attribute must have a valid value
|
||||||
LL | #[rustc_on_unimplemented(message="x", message="y")]
|
LL | #[rustc_on_unimplemented(message="x", message="y")]
|
||||||
| ^^^^^^^^^^^ expected value here
|
| ^^^^^^^^^^^ 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
|
error[E0232]: this attribute must have a valid value
|
||||||
--> $DIR/bad-annotation.rs:52:39
|
--> $DIR/bad-annotation.rs:52:39
|
||||||
|
@ -48,7 +48,7 @@ error[E0232]: this attribute must have a valid value
|
||||||
LL | #[rustc_on_unimplemented(message="x", on(desugared, message="y"))]
|
LL | #[rustc_on_unimplemented(message="x", on(desugared, message="y"))]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected value here
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ 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]`
|
error[E0232]: empty `on`-clause in `#[rustc_on_unimplemented]`
|
||||||
--> $DIR/bad-annotation.rs:56:26
|
--> $DIR/bad-annotation.rs:56:26
|
||||||
|
@ -62,7 +62,7 @@ error[E0232]: this attribute must have a valid value
|
||||||
LL | #[rustc_on_unimplemented(on="x", message="y")]
|
LL | #[rustc_on_unimplemented(on="x", message="y")]
|
||||||
| ^^^^^^ expected value here
|
| ^^^^^^ 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
|
error[E0232]: this attribute must have a valid value
|
||||||
--> $DIR/bad-annotation.rs:67:40
|
--> $DIR/bad-annotation.rs:67:40
|
||||||
|
@ -70,7 +70,7 @@ error[E0232]: this attribute must have a valid value
|
||||||
LL | #[rustc_on_unimplemented(on(desugared, on(desugared, message="x")), message="y")]
|
LL | #[rustc_on_unimplemented(on(desugared, on(desugared, message="x")), message="y")]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected value here
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected value here
|
||||||
|
|
|
|
||||||
= note: eg `#[rustc_on_unimplemented = "foo"]`
|
= note: eg `#[rustc_on_unimplemented(message="foo")]`
|
||||||
|
|
||||||
error: aborting due to 10 previous errors
|
error: aborting due to 10 previous errors
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue