Implementing multiple variants of the same erorr message


#1

I’m trying to improve diagnostic for E0599. For methods of traits it gives a seemingly self-contradictory message:

error[E0599]: no method named unwrap found for type std::result::Result<_, Foo> in the current scope –> src/main.rs:4:13
|
4 | Err(Foo).unwrap()
| ^^^^^^
|
= note: the method unwrap exists but the following trait bounds were not satisfied:
Foo : std::fmt::Debug

I would like to split into 3 different phrases:

  1. If it’s a method and there is only one bound:

    Method unwrap cannot be called on Result<_, Foo>, because Foo does not implement std::fmt::Debug in the current scope.

  2. If there are multiple bounds, or the issue is with associated types or other non-methods:

    "{item} {name} of type {ty} cannot be used in the
    current scope, because the following trait bounds
    are not satisfied: {list}"

  3. Current wording as-is

I’ve ran into couple of problems with this:

  • Each struct_span_err requires a unique error code. Is it OK to create a two new error codes just to tweak the wording?

  • How do I update the tests? I’ve tried ./src/test/ui/update-references.sh build/x86_64-apple-darwin/test/ui/ $(find src/librustc_typeck/ -name '*.rs'), but nothing changes.


Lessons from the Impl Period
#2

In Diesel, there was a trait that exported a method .into(). When this trait was not in scope, it would think that the Into::into of stdlib was being called and complain about the wrong number of parameters, which was confusing.

The name has changed since then, but taking also account the possibility that an overlapping method of a trait that is not in the scope may improve UX even further. (On the other hand, it might clutter up the error message.)

I’m thinking of something like: Or, did you mean to call this another method of trait T? In that case, the trait must be in the scope:use T``.


#3

I think picking up of wrong method/wrong number of arguments is handled elsewhere, so out of scope for this one.

Also note from github that there’s a fourth case, where type is generic and missing bounds: https://github.com/rust-lang/rust/issues/21673


#4

Bump. Can somebody help me with these?

  • Each struct_span_err requires a unique error code. Is it OK to create a two new error codes just to tweak the wording?

  • How do I update the tests? I’ve tried ./src/test/ui/update-references.sh build/x86_64-apple-darwin/test/ui/ $(find src/librustc_typeck/ -name '*.rs'), but nothing changes.


#5

Instead of using the struct_span_err!() macro, you can use the struct_span_err method of sess, which lets you create a DiagnosticBuilder without an error code. Not knowing what file you’re modifying, I can’t be more specific on where to find sess (it should be available through the tcx, many times that being self).

You have to first run the tests for them to fail ./x.py test src/test/ui --stage 1 and then run that script ./src/test/ui/update-references.sh build/x86_64-apple-darwin/test/ui.


#6

I find this constraint somewhat annoying. Usually what people do is to make a helper function that takes a string argument or other details, so that you funnel everything through one call.