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

Incorrect NRT tooltip when doing null check #66854

Open
vsfeedback opened this issue Feb 13, 2023 · 10 comments
Open

Incorrect NRT tooltip when doing null check #66854

vsfeedback opened this issue Feb 13, 2023 · 10 comments
Assignees
Labels
Area-IDE New Language Feature - Nullable Semantic Model Nullable Semantic Model Issues Resolution-By Design The behavior reported in the issue matches the current design

Comments

@vsfeedback
Copy link

This issue has been moved from a ticket on Developer Community.


Consider this code:

#nullable enable

public class Example
{
    private async Task MainAsync()
    {
        var user = new object();

        user.GetHashCode();

        // When hovering over `user`, the tooltip says "'user' may be null here", which is wrong.
        if (user is null)
            throw new InvalidOperationException("Shouldn't happen");
    }
}

When I hover over user in if(user is null), the tooltip says 'user' may be null here, which is incorrect. If I hover over user in user.GethashCode(), the tooltip correctly says 'user' is not null here.

Please let me know if you need any more info 


Original Comments

Feedback Bot on 2/2/2023, 11:56 PM:

(private comment, text removed)

Tracy Wang [MSFT] on 2/3/2023, 01:39 AM:

(private comment, text removed)

Feedback Bot on 2/3/2023, 01:40 AM:

(private comment, text removed)


Original Solutions

(no solutions)

@dotnet-issue-labeler dotnet-issue-labeler bot added Area-IDE untriaged Issues and PRs which have not yet been triaged by a lead labels Feb 13, 2023
@CyrusNajmabadi
Copy link
Member

I believe this is by design. Once you start checking for null again, the compiler assumes you know more than it, and it reverts back to thinking the value is potentially null. @RikkiGibson to confirm and close if so.

@RikkiGibson RikkiGibson added Resolution-By Design The behavior reported in the issue matches the current design New Language Feature - Nullable Semantic Model Nullable Semantic Model Issues labels Feb 13, 2023
@RikkiGibson
Copy link
Contributor

Thanks for filing this issue. Cyrus is correct here. Generally these tooltips use the state of the variable after the expression.

@RikkiGibson RikkiGibson closed this as not planned Won't fix, can't repro, duplicate, stale Feb 13, 2023
@Eli-Black-Work
Copy link

Eli-Black-Work commented Feb 14, 2023

Hi @CyrusNajmabadi and @RikkiGibson, I'm this issue's original reporter 🙂 I'd like to explain my workflow and why this feels confusing to me.

Often, I'll see a null check in our code that seems unnecessary. To begin my investigation, I hover over the variable in the null check and see whether the compiler reports it as nullable or not. If the compiler says that the variable might be null at this point, I end my investigation. If it says it isn't null at this point, I further investigate removing the null check.

The problem is that the compiler always reports that the variable might be null in two places:

This means that when we have code like below, it's impossible to easily tell if the variables might be null or not:

User GetUser()
{
    return new User();
}

// The tooltip on `user` shows it of type User?, even though GetUser() returns a non-null type
var user = GetUser();

// The tooltip on `user` says "'user' may be null here"
if (user is null)
	throw new InvalidOperationException("Shouldn't happen");

When I pointed out to my coworker that the null check wasn't needed, they responded by looking at the tooltip on user in if (user is null) and saying "See, it says 'user may be null at this point', so the null check is needed", which makes me think that this is affecting more people than just me 🙂

@RikkiGibson
Copy link
Contributor

Let's reopen to track down any record of what motivated us to choose the state we did for public API and see if there's any opportunity to improve.

@RikkiGibson RikkiGibson reopened this Feb 14, 2023
@jasonmalinowski
Copy link
Member

I think I've been bitten by this once or twice too. If we can detect this scenario with the public API as it is today it might be easy to tweak the quick info text to either explain this a bit more. ("The compiler doesn't think this can be null, but will assume it can be since you're checking for it", but wordsmithed to something better.)

@jasonmalinowski jasonmalinowski self-assigned this Feb 14, 2023
@jasonmalinowski jasonmalinowski removed the untriaged Issues and PRs which have not yet been triaged by a lead label Feb 14, 2023
@RikkiGibson
Copy link
Contributor

@chsienki @333fred in case they can provide additional context.

@333fred
Copy link
Member

333fred commented Feb 15, 2023

This is extremely similar to the types of problems that #44063 talks about.

@Eli-Black-Work
Copy link

Eli-Black-Work commented Feb 16, 2023

I think the original motivation was probably for this type of code:

User user = GetUser();

if (user is null)
    _service.Start();
else
    _service.Start();

// It's probably reasonable to warn here that `user` might be null
Console.WriteLine(user.Id);

@jasonmalinowski
Copy link
Member

Yeah, the language behavior makes sense; and generally the API behavior also makes sense...it just collides to a confusing behavior here in the IDE. Sure, you can kinda figure it out if you know the language design, but ideally our IDE would be clear to non-language-designers too.

@Eli-Black-Work
Copy link

Possible solution: Have flow analysis mark variables as possibly null starting with the statement after the null check.

Original example:

User GetUser() => new User();

var user = GetUser();

// Flow analysis hasn't marked `user` as possibly null yet, so the tooltip would say "'user' is not null here"
if (user is null)
        //  Starting with this statement, `user` might be null
	throw new InvalidOperationException("Shouldn't happen");

And:

User user = GetUser();

// Tooltip: '"user" is not null here'
if (user is null)
    _service.Start();
else
    _service.Start();

// Warning: '"user" might be null here'
Console.WriteLine(user.Id);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area-IDE New Language Feature - Nullable Semantic Model Nullable Semantic Model Issues Resolution-By Design The behavior reported in the issue matches the current design
Projects
Status: In Queue
Development

No branches or pull requests

6 participants