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

give some suggestion for returning anonymous enum #100988

Closed
wants to merge 1 commit into from

Conversation

LYF1999
Copy link
Contributor

@LYF1999 LYF1999 commented Aug 25, 2022

give some suggestion for returning anonymous enum

fn foo<'a>() -> i32 | Vec<i32> | &str | &'a String | Foo {
                         ^ help: consider using enum as return type: `SomeEnum`
   = note: enum SomeEnum<'lifetime,'a>{
               I32(i32)
               Vec(Vec<...>)
               StrRef(&'lifetime str)
               StringRef(&'a String)
               Foo(Foo)
           }

fix #100741
r? @estebank

@rustbot rustbot added the T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. label Aug 25, 2022
@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Aug 25, 2022
@LYF1999
Copy link
Contributor Author

LYF1999 commented Aug 25, 2022

should we create a crate for some util functions like to_camel_case?

@rust-log-analyzer

This comment has been minimized.

"SomeEnum",
Applicability::HasPlaceholders,
)
.note(suggestion_code);
Copy link
Contributor

Choose a reason for hiding this comment

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

Instead of the note with the enum, we could instead use a multipart_suggestion and pass in the span for the space right at the start of the item, so that the output can be

error: anonymous enums are not supported
  --> $DIR/issue-100741-return-anonymous-enum.rs:3:17
   |
LL | fn foo<'a>() -> i32 | Vec<i32> | &str | &'a String | Foo {
   |                     ^          ^      ^            ^ not supported in types
   |
help: consider using enum as return type
   |
LL + enum SomeEnum<'lifetime,'a>{
LL +     I32(i32)
LL +     Vec(Vec<i32>)
LL +     StrRef(&'lifetime str)
LL +     StringRef(&'a String)
LL +     Foo(Foo)
LL + }
LL ~ fn foo<'a>() -> SomeEnum<'_, 'a> {
   |

err.span_suggestion(
span,
"consider using enum as return type",
"SomeEnum",
Copy link
Contributor

Choose a reason for hiding this comment

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

You need to account for the lifetimes that were mentioned. In the test included, this would end up being '_, 'a.


if let Some(_args) = &seg.args {
ty_string.push('<');
ty_string.push_str("...");
Copy link
Contributor

Choose a reason for hiding this comment

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

Why don't we print the whole type?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

it's more complicated, for example Vec<impl Send> | Vec<(i32, i64)>. We can not make a enum variant name for these type.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

As you propose, we can use Variant{N} as the variant name

let mut ty_string = String::new();

if let Some(seg) = path.segments.iter().last() {
name.push_str(seg.ident.name.as_str());
Copy link
Contributor

Choose a reason for hiding this comment

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

It feels like the only thing we need here is the name and for ty_string format!("{ty}") is enough, after folding the anon lifetimes to be named as 'lifetime, in way similar to what is done here:

fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
// because late-bound regions affect subtyping, we can't
// erase the bound/free distinction, but we can replace
// all free regions with 'erased.
//
// Note that we *CAN* replace early-bound regions -- the
// type system never "sees" those, they get substituted
// away. In codegen, they will always be erased to 'erased
// whenever a substitution occurs.
match *r {
ty::ReLateBound(..) => r,
_ => self.tcx.lifetimes.re_erased,
}
}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

emmm, the TyKind in rustc_ast doesn't implement Display, if it's nesscery to implement Display, I will submit a new pull request to do that.

Copy link
Contributor

Choose a reason for hiding this comment

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

I'm fairly certain there's a way to pprint TyKind, but it isn't through Display directly 🤔

None
}
}
_ => None,
Copy link
Contributor

Choose a reason for hiding this comment

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

This wouldn't work for something like -> [i32; 10] | Vec<i32>, right?

If you don't want to support every TyKind, you can at least provide a Variant{N} name so that the suggested enum makes syntactic sense.

Comment on lines +203 to +205
let mut tys = vec![];
let lo = self.token.span;
loop {
Copy link
Contributor

Choose a reason for hiding this comment

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

The issue with this that we shouldn't recover this only for return types, we should be doing this further down, in parse_ty_common, maybe adding another argument to it to explicitly state what should be coming after it (to support things like let foo: A | B = ...;).

u.next().is_some()
}

pub fn to_camel_case(s: &str) -> String {
Copy link
Contributor

Choose a reason for hiding this comment

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

fn to_camel_case(s: &str) -> String {

Copy link
Contributor Author

Choose a reason for hiding this comment

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

but it's in crate rustc_lint. I think it's weird to make rustc_parse depend rustc_lint. Should we create a crate rustc_utils for these functions like to_camel_case

Copy link
Contributor

Choose a reason for hiding this comment

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

We could move this to a shared dependency of the two, like rustc_errors.

@LYF1999 LYF1999 marked this pull request as draft September 22, 2022 07:30
@estebank estebank 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 10, 2022
@bors
Copy link
Contributor

bors commented Jan 26, 2023

☔ The latest upstream changes (presumably #107314) made this pull request unmergeable. Please resolve the merge conflicts.

@Noratrieb
Copy link
Member

any updates here? we have to be very careful to not recover on the happy path as to not cause further regressions

@LYF1999
Copy link
Contributor Author

LYF1999 commented Mar 14, 2023

sorry, I am not working on it currently

@bors
Copy link
Contributor

bors commented May 2, 2023

☔ The latest upstream changes (presumably #109128) made this pull request unmergeable. Please resolve the merge conflicts.

@Dylan-DPC
Copy link
Member

Closing this as inactive. Feel free to reöpen this pr or create a new pr if you get the time to work on this. Thanks

@Dylan-DPC Dylan-DPC closed this May 15, 2023
@Dylan-DPC Dylan-DPC added S-inactive Status: Inactive and waiting on the author. This is often applied to closed PRs. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels May 15, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-inactive Status: Inactive and waiting on the author. This is often applied to closed PRs. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Parse and reject "typescript-style" anonymous enums
8 participants