Skip to content

Add hints for the case of confusing enum with its variants #45942

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

Merged
merged 4 commits into from
Nov 24, 2017

Conversation

Menschenkindlein
Copy link
Contributor

A solution for #43871. When one uses an enum in a place that accepts variants (e.g., Option(result) instead of Some(result)), suggest one of this enum's variants.

cc @estebank

@kennytm kennytm added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Nov 12, 2017
@alexcrichton
Copy link
Member

r? @estebank

Copy link
Contributor

@estebank estebank left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks good to me, could you add a couple of ui tests?

of the following variants?\n{}",
variants.iter()
.map(|suggestion| format!("- `{}`",
path_names_to_string(suggestion)))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpick, move indentation one char to the left

(Def::Enum(..), PathSource::TupleStruct) => {
if let Some(variants) = this.collect_enum_variants(def) {
err.note(&format!("did you mean to use one \
of the following variants?\n{}",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpick, move indentation one char to the left

@Menschenkindlein
Copy link
Contributor Author

@estebank Could you, please, give me more guidance? I don't really know where is the place for the ui tests, and how to write them.

@oli-obk
Copy link
Contributor

oli-obk commented Nov 13, 2017

@Menschenkindlein you can add a new file to src/test/ui and follow the error message that you get when running ./x.py test src/test/ui

@estebank
Copy link
Contributor

@Menschenkindlein You can find a bit more of an explanation in COMPILER_TESTS.md, but what you have to do is pretty much what @oli-obk explained. After you've ran ./x.py test src/test/ui, it'll fail (because you don't have an .stderr file in the same place as your new test .rs file). After you run update-all-references.sh you'll have that .stderr file in place so subsequent runs of ./x.py test src/test/ui should succeed.

@Menschenkindlein
Copy link
Contributor Author

I added some tests. It looks like it doesn't work in tests. When I created a separate project and tested the feature, it worked. Somehow it manages to suggest an empty list of variants.

By the way, is it a reasonable idea to add a suggestion of a variant in other places where they can be used, e.g. when they are used as constructors?

@kennytm kennytm added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Nov 22, 2017
@kennytm
Copy link
Member

kennytm commented Nov 22, 2017

Hi @estebank, looks like @Menschenkindlein needs some help from you! 😃

@Menschenkindlein
Copy link
Contributor Author

I assumed that one Def could designate more than one module, and now my code works. But this assumption looks very strange to me. What should I do?

@estebank
Copy link
Contributor

@Menschenkindlein it is slightly odd if you're finding more than one module per Def, but the code so far looks good. Could you try adding some debug!() statements in find_module and run your local build with RUST_LOG=debug ./stage1/bin/rustc file.rs in order to verify that you're indeed ever receiving more than 1 ImportSuggestion?

@Menschenkindlein
Copy link
Contributor Author

Menschenkindlein commented Nov 23, 2017

There indeed were two Option modules. Probably, it was so because of reexports: the same module was found by going from two different paths. But the real bug was that I forgot to "populate" the module in collect_enum_variants. Continuing the search in find_module populated it and unintentionally solved the problem.
Now I added self.populate_module_if_necessary(enum_module) and it works!

@estebank
Copy link
Contributor

Awesome @Menschenkindlein! I really like this feature!

r=me once you've fixed ui/did_you_mean/issue-43871-enum-instead-of-variant.stderr

[00:45:25]  error[E0423]: expected function, found enum `Option`
[00:45:25]    --> $DIR/issue-43871-enum-instead-of-variant.rs:14:13
[00:45:25]     |
[00:45:25]  14 |     let x = Option(1);
[00:45:25]     |             ^^^^^^
[00:45:25]     |
[00:45:25]     = note: did you mean to use one of the following variants?
[00:45:25] -           - `std::prelude::v1::Option::None`
[00:45:25] -           - `std::prelude::v1::Option::Some`
[00:45:25] +           - `std::option::Option::None`
[00:45:25] +           - `std::option::Option::Some`
[00:45:25]  
[00:45:25]  error[E0532]: expected tuple struct/variant, found enum `Option`
[00:45:25]    --> $DIR/issue-43871-enum-instead-of-variant.rs:16:12
[00:45:25]     |
[00:45:25]  16 |     if let Option(_) = x {
[00:45:25]     |            ^^^^^^
[00:45:25]     |
[00:45:25]     = note: did you mean to use one of the following variants?
[00:45:25] -           - `std::prelude::v1::Option::None`
[00:45:25] -           - `std::prelude::v1::Option::Some`
[00:45:25] +           - `std::option::Option::None`
[00:45:25] +           - `std::option::Option::Some`
[00:45:25]  
[00:45:25]  error[E0532]: expected tuple struct/variant, found enum `Example`
[00:45:25]    --> $DIR/issue-43871-enum-instead-of-variant.rs:22:12
[00:45:25]     |
[00:45:25]  22 |     if let Example(_) = y {
[00:45:25]     |            ^^^^^^^
[00:45:25]     |
[00:45:25]     = note: did you mean to use one of the following variants?
[00:45:25]             - `Example::Ex`
[00:45:25]             - `Example::NotEx`
[00:45:25]  
[00:45:25]  error: aborting due to 3 previous errors
[00:45:25]  

@oli-obk
Copy link
Contributor

oli-obk commented Nov 23, 2017

I don't think they are fixable. These are order issues depending on HashMap randomness.

You can turn them into compile-fail tests, since they don't care about order or the full message.

//~ SUGGESTION Option::Some

Should work

@kennytm
Copy link
Member

kennytm commented Nov 23, 2017

If both modules can appear, you could add a custom normalization rule that maps std::prelude::v1::Option to std::option::Option (as long as None always appear above Some).

// normalize-stderr: "std::prelude::v1::Option" -> "std::option::Option"

@Menschenkindlein
Copy link
Contributor Author

I implemented find_module using for_each_child. for_each_child_stable should solve the issue with randomness.

@estebank
Copy link
Contributor

@bors r+

@bors
Copy link
Collaborator

bors commented Nov 23, 2017

📌 Commit a3686c6 has been approved by estebank

@kennytm kennytm added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Nov 23, 2017
@oli-obk
Copy link
Contributor

oli-obk commented Nov 23, 2017

I'm not sure if that solves it. This error is emitted during resolve, right? So we aren't fully resolved yet, thus the paths in find_module can't necessarily find the correct module. I had a similar issue and solved it by storing the information necessary to produce the diagnostic and emit the error after resolve is finished. There's several of these delayed diagnostics in resolve.

@bors
Copy link
Collaborator

bors commented Nov 24, 2017

⌛ Testing commit a3686c6 with merge 9342661...

bors added a commit that referenced this pull request Nov 24, 2017
Add hints for the case of confusing enum with its variants

A solution for #43871. When one uses an enum in a place that accepts variants (e.g., `Option(result)` instead of `Some(result)`), suggest one of this enum's variants.

cc @estebank
@bors
Copy link
Collaborator

bors commented Nov 24, 2017

☀️ Test successful - status-appveyor, status-travis
Approved by: estebank
Pushing 9342661 to master...

@bors bors merged commit a3686c6 into rust-lang:master Nov 24, 2017
@Menschenkindlein
Copy link
Contributor Author

@estebank Thank you for patiently guiding me to the completion of this pull request!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants