Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

tuple variant error message is confusing #65386

Closed
4 of 9 tasks
ultrasaurus opened this issue Oct 13, 2019 · 21 comments
Closed
4 of 9 tasks

tuple variant error message is confusing #65386

ultrasaurus opened this issue Oct 13, 2019 · 21 comments
Labels
A-diagnostics Area: Messages for errors, warnings, and lints A-docs Area: documentation for any part of the project, including the compiler, standard library, and tools A-suggestion-diagnostics Area: Suggestions generated by the compiler applied by `cargo fix` C-enhancement Category: An issue proposing an enhancement or a PR with one. D-confusing Diagnostics: Confusing error or lint that should be reworked. D-newcomer-roadblock Diagnostics: Confusing error or lint; hard to understand for new users. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@ultrasaurus
Copy link

ultrasaurus commented Oct 13, 2019

originally described in blog post: https://www.ultrasaurus.com/2019/10/rust-whats-a-tuple-variant/

sample code:

fn get_num() -> Result<i32, &'static str> {
  let result = 4;
  OK(result)
}

error message:

error[E0425]: cannot find function `OK` in this scope
  --> examples/tuple.rs:13:3
   |
13 |   OK(result)
   |   ^^ help: a tuple variant with a similar name exists: `Ok`

Error message suggestions:

General terminology suggestions:

  • stop referring to "tuple-like enum" and "tuple-like struct" and instead come up with a more precise term, such as "named tuple" (or "typed tuple" but I like the former better) which could be declared as a struct or as part of an enum.
  • refer to the struct / enum use of tuples in the book, here: https://doc.rust-lang.org/1.7.0/book/primitive-types.html#tuples link to Tuple structs and create a similar titled sub-section of enum and include a link to that
  • standardize naming of struct and enum and create logical parallel: unit enum / unit struct OR enum unit variant / struct unit variant (I prefer the former with fewer words)
  • when you standardize on the names, consider annotate them here:
enum Message {
    Quit,                                           // unit enum
    ChangeColor(i32, i32, i32),    // tuple enum
    Move { x: i32, y: i32 },              // struct enum
    Write(String),                           // also a tuple enum
}

(by the way, the above example is very good serving as both an introduction to the section content and an easy syntax reference that is quick to find later)

@estebank estebank added A-diagnostics Area: Messages for errors, warnings, and lints A-suggestion-diagnostics Area: Suggestions generated by the compiler applied by `cargo fix` D-confusing Diagnostics: Confusing error or lint that should be reworked. D-newcomer-roadblock Diagnostics: Confusing error or lint; hard to understand for new users. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. A-docs Area: documentation for any part of the project, including the compiler, standard library, and tools labels Oct 13, 2019
@estebank
Copy link
Contributor

Tagging the docs team for the latter half of the ticket.

@Centril
Copy link
Contributor

Centril commented Oct 13, 2019

standardize naming of struct and enum and create logical parallel: unit enum / unit struct OR enum unit variant / struct unit variant (I prefer the former with fewer words)

A "unit enum" suggests an enum with a single variant rather than the unit variant of an enum; I would call this a "enum unit variant", which is albeit more verbose, also more clear.

@ultrasaurus
Copy link
Author

ultrasaurus commented Oct 13, 2019

Missed one suggestion.. the first part of the error message is a bit misleading since it implies that Ok() is a function.

Instead of:

 cannot find function `OK` in this scope

it could be something like this:

 `OK` has not been been previously defined as a function, struct or enum

@ultrasaurus
Copy link
Author

@Centril would it be typical/common for someone create an enum with a single variant? seems like that would be unlikely in normal practice. If so, I would use more words to describe the less common use case, such as "enum with single variant"

@Centril
Copy link
Contributor

Centril commented Oct 13, 2019

No it's not usual but e.g. "tuple enum" still makes a category mistake by conflating the data type itself with its constructors (the variant in this case). I think that paints a misleading mental model of the language, which is avoidable by including an additional word.

@ultrasaurus
Copy link
Author

hmm... I was reading "tuple" in "tuple enum" as an adjective -- a descriptor (to me) doesn't necessarily change the data type.

However, I agree that this is an important clarification (that I missed in early readings of the docs) about the difference between an enum and a struct, where enum variants are all the same type and the equivalent struct syntax creates multiple types. In practice, I wasn't confused, but wasn't really conscious of this nuance in a way I could have spoken about it.

FYI: in case it is useful, I ran into an example of "unit enum" used in the wild: https://users.rust-lang.org/t/what-is-a-unit-variant/18468/2

@estebank
Copy link
Contributor

estebank commented Oct 14, 2019

Looking a bit into this, procuring the Span for std::option::Option::Some is proving to be difficult here because although we have the variant's DefId available in librustc_resolve, where we emit this error, we do not have access to the hir::Map, so we can't get the span that way. Trying to use the definition Ident's Span is also not feasible because everything that comes from std::prelude::v1::* has a DUMMY_SP. I think that the only way to support this would be to delay the resolution error until a later stage where the hir::Map is available to properly display the "Result::Ok defined here" label. On the other hand, we can fix this in a minimally intrusive way today for things defined in the current crate.

@petrochenkov what do you think is the feasibility of having the prelude imports carry correct Spans pointing at the std locations? It seems to me that that approach would be incorrect.

tmandry added a commit to tmandry/rust that referenced this issue Oct 15, 2019
Bring attention to suggestions when the only difference is capitalization

CC rust-lang#65386.
@petrochenkov
Copy link
Contributor

@estebank

what do you think is the feasibility of having the prelude imports carry correct Spans pointing at the std locations?

It's more about spans for all extern items than about spans from std prelude specifically.
I tried to do that in #63149, but backed out the change due to some non-reproducible order in diagnostics. (Perhaps it's already fixed?)
The dummy spans are used instead of actual spans in fn build_reduced_graph_for_external_crate_res.

@petrochenkov
Copy link
Contributor

From a quick look I don't like what this issue suggests in general, we have some pretty stable terminology in place and it's used consistently.
Perhaps it needs to be better described in docs / glossary.

@estebank
Copy link
Contributor

non-reproducible order in diagnostics. (Perhaps it's already fixed?)

If you can point me in the right direction to use the original spans, I can take a look at the non-deterministic output.

we have some pretty stable terminology in place and it's used consistently.

Even if we don't change the terminology at all (and I think there is room for tweaks targeting newcomers to reduce confusion), the addition of better spans will make acquiring understanding of what the different concepts mean much easier.

@petrochenkov
Copy link
Contributor

@estebank

If you can point me in the right direction to use the original spans, I can take a look at the non-deterministic output.

petrochenkov@cab814b

@ultrasaurus
Copy link
Author

we have some pretty stable terminology in place and it's used consistently.

"tuple variant" is not a stable or consistent term (except where context is given that people are talking about an enum). Stand-alone in an error message, it is pretty meaningless.

cc @petrochenkov

@petrochenkov
Copy link
Contributor

Well, it is indeed stable and consistent.
"Variant" is a same thing as "enum variant", but without tautology (we don't have other variants in the language beside enum variants), and "tuple struct/variant" is a name for structs and variants defined with parentheses and introduced pretty early in the book - https://doc.rust-lang.org/nightly/book/ch05-01-defining-structs.html#using-tuple-structs-without-named-fields-to-create-different-types.

@petrochenkov
Copy link
Contributor

To clarify, I'm certainly not against showing examples with spans and perhaps improving documentation, only against inventing a new terminology instead of the already established one.

@estebank
Copy link
Contributor

@ultrasaurus would this output have been enough for you understand what was happening?

Screen Shot 2019-10-16 at 1 01 28 PM

@ultrasaurus
Copy link
Author

@estebank that would have definitely helped!

If you can put some kind of break between the code from diff files, I think that would be more readable.

Just in case it's nearby, the "cannot find function..." seems to conflict with "similarly named tuple variant".... would it be possible to change to "cannot find function or enum tuple variant..." at the top of your screenshot.

Thanks for your attention to this detail!

@estebank
Copy link
Contributor

Screen Shot 2019-10-16 at 9 34 14 PM

The change made the PR size balloon in size, but I do think that this error and all others that were changed are now more accurate.

@ultrasaurus
Copy link
Author

This is great!

It would have helped me if "tuple variant" had the word "enum" near it. Would it be correct to say "enum tuple variant" ?

Not intending to be nit-picky, just providing feedback. The given context should provide enough breadcrumbs for a novice :)

@Centril
Copy link
Contributor

Centril commented Oct 17, 2019

Would it be correct to say "enum tuple variant" ?

Yeah it's correct. It just has some redundancy because a tuple variant always belongs to an enum. That said, redundancy can be useful.

@estebank
Copy link
Contributor

Googling "tuple variant rust" leads me to believe that not mentioning it could be a stumbling block for a newcomer:


Screen Shot 2019-10-17 at 10 38 34 AM


vs "enum tuple variant rust":


Screen Shot 2019-10-17 at 10 39 44 AM


That being said, I'm tempted at tackling that in a more methodical way with [t-doc].

Centril added a commit to Centril/rust that referenced this issue Oct 27, 2019
Point at local similarly named element and tweak references to variants

Partially address rust-lang#65386.
bors added a commit that referenced this issue Oct 28, 2019
Point at local similarly named element and tweak references to variants

Partially address #65386.
@JohnTitor JohnTitor added the C-enhancement Category: An issue proposing an enhancement or a PR with one. label Dec 8, 2019
bors added a commit that referenced this issue Jan 11, 2020
Point at the span for the definition of crate foreign ADTs

Follow up to #65421. Partially addresses #65386. Blocked on #53081.
@Dylan-DPC
Copy link
Member

It appears that this error message is no longer confusing and should be fine to close this issue. If there are any improvements, it will be better in a new issue.

@Dylan-DPC Dylan-DPC closed this as not planned Won't fix, can't repro, duplicate, stale May 23, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-diagnostics Area: Messages for errors, warnings, and lints A-docs Area: documentation for any part of the project, including the compiler, standard library, and tools A-suggestion-diagnostics Area: Suggestions generated by the compiler applied by `cargo fix` C-enhancement Category: An issue proposing an enhancement or a PR with one. D-confusing Diagnostics: Confusing error or lint that should be reworked. D-newcomer-roadblock Diagnostics: Confusing error or lint; hard to understand for new users. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

6 participants