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

IDE0066 incorrectly handles nullable value types #37950

Closed
stephentoub opened this issue Aug 13, 2019 · 12 comments · Fixed by #38007
Closed

IDE0066 incorrectly handles nullable value types #37950

stephentoub opened this issue Aug 13, 2019 · 12 comments · Fixed by #38007
Assignees
Labels
Area-IDE Bug IDE-CodeStyle Built-in analyzers, fixes, and refactorings Resolution-Fixed The bug has been fixed and/or the requested behavior has been implemented
Milestone

Comments

@stephentoub
Copy link
Member

Version Used:
3.3.0-beta3-19406-05+a1905991543bed104f7f7f0842aca2b65d263b87

Steps to Reproduce:

class Program
{
    public static void Main() { }

    public static bool? GetBool(string name)
    {
        switch (name)
        {
            case "a": return true;
            case "b": return false;
            default: return null;
        }
    }
}

Expected Behavior:
IDE0066 refactors this into something that compiles, e.g.

class Program
{
    public static void Main() { }

    public static bool? GetBool(string name)
    {
        return name switch
        {
            "a" => true,
            "b" => false,
            _ => (bool?)null,
        };
    }
}

Actual Behavior:
IDE0066 refactors this into the following code that doesn't compile:

class Program
{
    public static void Main() { }

    public static bool? GetBool(string name)
    {
        return name switch
        {
            "a" => true,
            "b" => false,
            _ => null,
        };
    }
}

This fails with the error "error CS0037: Cannot convert null to 'bool' because it is a non-nullable value type".

@alrz
Copy link
Contributor

alrz commented Aug 13, 2019

Fixed in #37052

@alrz
Copy link
Contributor

alrz commented Aug 13, 2019

note that this would be still an issue if there is no target-type until dotnet/csharplang#33 is implemented, but we wont suggest 0066 in those cases at the moment.

@stephentoub
Copy link
Member Author

Fixed in #37052

VS says my tools are from a190599, and according to git log, that includes fbdb480. Am I misinterpreting?

@alrz
Copy link
Contributor

alrz commented Aug 13, 2019

perhaps I am. According to the feature spec dotnet/csharplang#2389 I expect this to work - there's no natural type but all arms are implicitly convertible to the target type.

Edit: I do see why this happens though. The compiler yields bool as the best common type - excluding typeless expressions - but doesn't check if all expressions can be successfully converted. The same with (even different) reference types could work because best type algorithm would fail in the first place and if it's not, null can be seamlessly converted. My question is that if this is the intended behavior for the switch expression regarding nullable value types?

cc @gafter

@jinujoseph jinujoseph added Area-IDE Bug help wanted The issue is "up for grabs" - add a comment if you are interested in working on it IDE-CodeStyle Built-in analyzers, fixes, and refactorings labels Aug 13, 2019
@jinujoseph jinujoseph added this to the 16.3 milestone Aug 13, 2019
@alrz
Copy link
Contributor

alrz commented Aug 22, 2019

The fix for IDE is in review #38007, in case this is the intended behavior.

@gafter
Copy link
Member

gafter commented Aug 22, 2019

Th problem is that there is a common type according to the current spec/implementation - because only two switch arms have expressions with types, and those are the same type. The spec and implementation should be amended to require that all arms are convertible to that common type in order for it to be considered the natural type of the switch.

@gafter gafter removed the help wanted The issue is "up for grabs" - add a comment if you are interested in working on it label Aug 22, 2019
@alrz
Copy link
Contributor

alrz commented Aug 22, 2019

The spec and implementation should be amended to require that all arms are convertible to that common type in order for it to be considered the natural type of the switch.

I'll note that dotnet/csharplang#33 will address this issue by taking null into account in the best-type inference, thought it is probably an unintuitive behavior at the moment.

@gafter
Copy link
Member

gafter commented Aug 22, 2019

Yes, but the switch expression must take lambdas, method groups, and other typeless things into account too.

@alrz
Copy link
Contributor

alrz commented Aug 22, 2019

So if I understand correctly, "nullable-enhanced common type" would not help with the following

(int?, int) t = b switch { true => (null, 1), false => (1, 2) };

but it should actually work because there's no natural type for the switch expression.

@gafter
Copy link
Member

gafter commented Aug 22, 2019

I think that's right. However, it should work whether or not there is a natural type for the switch expression.

@gafter
Copy link
Member

gafter commented Aug 22, 2019

I am going to aim to fix the compiler behavior in 16.4.

@gafter
Copy link
Member

gafter commented Aug 22, 2019

Compiler part moved to #38226

@gafter gafter removed their assignment Aug 22, 2019
@jinujoseph jinujoseph modified the milestones: 16.3, 16.4 Sep 27, 2019
ryzngard added a commit that referenced this issue Oct 3, 2019
Bugfixes for ConvertSwitchStatementToExpression

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)
@jinujoseph jinujoseph modified the milestones: 16.4, 16.4.P3 Oct 3, 2019
@sharwell sharwell added the Resolution-Fixed The bug has been fixed and/or the requested behavior has been implemented label Nov 25, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area-IDE Bug IDE-CodeStyle Built-in analyzers, fixes, and refactorings Resolution-Fixed The bug has been fixed and/or the requested behavior has been implemented
Projects
Archived in project
Development

Successfully merging a pull request may close this issue.

7 participants