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

Bugfixes for ConvertSwitchStatementToExpression #38007

Merged
merged 11 commits into from
Oct 3, 2019
Merged

Conversation

alrz
Copy link
Contributor

@alrz alrz commented Aug 15, 2019

Fixes #37949 (leave open for offering the fix instead of bail out)
Fixes #37950 (will be resolved on the compiler side)
Fixes #36876
Fixes #37873
Fixes #37872
Fixes #37907
Fixes #37947
Closes #36877 (duplicate of #37873)

@alrz alrz requested a review from a team as a code owner August 15, 2019 15:11
@jinujoseph jinujoseph added Area-IDE Community The pull request was submitted by a contributor who is not a Microsoft employee. labels Aug 15, 2019
case 0: name = ""1""; break;
case 1: name = ""2""; break;
}
throw new Exception(name);
Copy link
Contributor

Choose a reason for hiding this comment

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

This looks like it will result in non-intuitive behavior. I'd prefer we still support this and refactor it correctly.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This fixes the incorrect behavior by not suggesting the fix. However, for this particular case we can use the initializer value for the last arm expression as suggested in #37949. we can keep it open to track that case.

if (shouldRemoveNextStatement &&
semanticModel.AnalyzeDataFlow(node.GetNextStatement()).DataFlowsIn.Contains(symbol))
{
// Bail out if data flows into the next statement that we want to move
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 bailing, can we just not remove the next statement and leave it outside the switch?

Copy link
Contributor

Choose a reason for hiding this comment

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

Just looking through the AnalyzeSwitchStatement implementation, we're setting shouldRemoveNextStatement always to true if there is no default. That's potentially wrong, especially in the case noted in #37949

Maybe we can check if there is a default that makes sense before assuming we need to remove next?

Copy link
Contributor Author

@alrz alrz Aug 21, 2019

Choose a reason for hiding this comment

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

Instead of bailing, can we just not remove the next statement and leave it outside the switch?

At that point, we must have a viable statement after switch, otherwise this is not an exhaustive switch and we can't offer the fix

Copy link
Contributor

@ryzngard ryzngard left a comment

Choose a reason for hiding this comment

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

#37949 fix still is lacking. I'd rather we fix that or leave open and take another stab in a separate PR.

Everything else looks good to me ✔

@alrz
Copy link
Contributor Author

alrz commented Aug 21, 2019

Should we rebase this bugfix PR to 16.4-preview1 as well?

@jasonmalinowski
Copy link
Member

@alrz Hmm, didn't realize this was out or I would have reviewed it. Don't rebase (the branch is switching around) but I might actually want to get this to go into 16.3...

@jasonmalinowski jasonmalinowski self-assigned this Aug 22, 2019
var declaration = declarator.GetAncestor<StatementSyntax>();
if (declaration.Parent == node.Parent && declarator.Initializer is null)
{
var beforeSwitch = node.GetPreviousStatement() is {} previousStatement
Copy link
Member

Choose a reason for hiding this comment

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

i'd honestly just prefer something like is StatementSyntax previousStatement

Copy link
Contributor Author

@alrz alrz Aug 22, 2019

Choose a reason for hiding this comment

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

is StatementSyntax doesn't scream null check? this is a usage that's been anticipated for recursive patterns afterall.

Copy link
Member

Choose a reason for hiding this comment

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

is StatementSyntax doesn't scream null check?

It does to me. Because it just matches is Whatever which has been in the language forever and does a null check.

If we get a not null pattern in the future i'd also be ok with that. I think that {} works, but just doesn't read well. It makes me feel as if it's missing something and trying to say "i need some props...i just forgot what they were :)"

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 does to me. Because it just matches is Whatever which has been in the language forever

So does is object , perhaps I should quote #37539 (comment) from Cyrus

I agree. I'm actually not a huge fan of is object primarily because, for me, it heavily evokes a type check, when in reality all i'm really trying to convey is the null check in a safe way

I'd agree too.

If we get a not null pattern in the future i'd also be ok with that

Sadly, not null pattern only works when you don't need a variable, you'd need to say
not null and var x to also introduce a variable of a null-checked expression that would err if it's not a reference type - {} doesn't.

I think that {} works, but just doesn't read well. It makes me feel as if it's missing something and trying to say "i need some props...i just forgot what they were :)

There were many requests to have a null-checked var-pattern before C# 8.0 and the answer was to use {}, so I'd say that's pretty idiomatic.

I myself proposed var x? similar to swift's "optional patterns" - but it got superseded by {} which is a completely accidental feature of recursive patterns.

Copy link
Member

Choose a reason for hiding this comment

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

basically, i'd rather wait until we have a good pattern here tbh.

Copy link
Member

Choose a reason for hiding this comment

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

I'm with @CyrusNajmabadi and also detest this pattern: it feels like somebody realized you could use a screwdriver to hammer in a nail, and because we've all decided hammers aren't the new hotness we're all trying to use screwdrivers. :-)

Copy link
Member

Choose a reason for hiding this comment

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

Note: i'm also very amenable to the idea that i'm being curmudgeonly here :) I'm not opposed to us migrating to new patterns and practices (lord knows you can see how often i massively do that to some part of the IDE).

That said, it's sometimes good to have a period were we dip our toes in and decide how we feel as a whole and come to some general consensus on a good balance.

i.e. i like patterns. i like them a lot. BUt i also think they can become unreadable. So finding a good balance on how they can be used is great. But we shouldn't necessarily try to make 100% of all code into a pattern.

This is similar to if we get sequence-expression, and things like return-expressoins. We'd likely be able to make tons and tons of statements into pure expressions. But should we? Probably not. It will really depend on the code and what the team as a whole feels is a good balance between brevity and readability.

So, in this case, i would use another pattern. but know that maybe after a few months to a year, the team may start liking this more and more and it may eventually move back :)

@alrz
Copy link
Contributor Author

alrz commented Aug 22, 2019

#37950 will be resolved on the compiler side, should revert the change here.

@alrz
Copy link
Contributor Author

alrz commented Aug 29, 2019

@CyrusNajmabadi @ryzngard do you have any more comments?

Copy link
Contributor

@ryzngard ryzngard left a comment

Choose a reason for hiding this comment

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

LGTM with plan to resolve #37949 with a different change

@ryzngard
Copy link
Contributor

ryzngard commented Oct 3, 2019

@CyrusNajmabadi can you take another pass?

@CyrusNajmabadi
Copy link
Member

@CyrusNajmabadi can you take another pass?

Sure. Will try to do tonight or tomorrow!

@CyrusNajmabadi
Copy link
Member

LGTM. Thanks for taking care of all of these cases!

{
return input switch
{
1 => 42,// this little piggy went to market
Copy link
Member

Choose a reason for hiding this comment

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

nit. probably want space after the comma.

Copy link
Member

Choose a reason for hiding this comment

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

(super super minor nit)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

that's just me not knowing how trivia works. there is no resource and I should just infer from code. not an easy task for something this subtle.

return dayOfWeek switch
{
DayOfWeek.Monday => ""Monday"",
_ => ""Other"",
Copy link
Member

Choose a reason for hiding this comment

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

nice!

@CyrusNajmabadi
Copy link
Member

@ryzngard I'm good here!

@ryzngard ryzngard merged commit 77db8b1 into dotnet:master Oct 3, 2019
@ryzngard
Copy link
Contributor

ryzngard commented Oct 3, 2019

Thanks for contributing @alrz !

@jinujoseph jinujoseph added this to the 16.4.P3 milestone Oct 3, 2019
@alrz alrz deleted the fix-0066 branch February 8, 2021 06:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment