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

IDE0041 Null check can be simplified is shown for Reference Equals of all generic parameters #23581

Closed
Tornhoof opened this issue Dec 5, 2017 · 22 comments
Assignees
Labels
Area-IDE Bug Resolution-Fixed The bug has been fixed and/or the requested behavior has been implemented
Milestone

Comments

@Tornhoof
Copy link

Tornhoof commented Dec 5, 2017

IDE0041 should only be shown if the type is nullable or the generic parameter is constrained to a nullable type.
Executing the codefix will create invalid code.

Version Used:
Visual Studio Enterprise 2017 15.5 RTM
Steps to Reproduce:

  1. Use repro snippet from below
  2. Build
  3. Look at messages

Expected Behavior:
Not shown
Actual Behavior:
Message: IDE0041 Null check can be simplified is shown for the Reference Equals

Repro:

public static void NotNull<T>(T value, string parameterName)
{
    if (ReferenceEquals(value, null)) // IDE0041 not valid here
    {
        throw new ArgumentNullException(parameterName);
    }
}
@Tornhoof Tornhoof changed the title IDE0041Null check can be simplified is shown for the Reference Equals shown for all generic parameters IDE0041 Null check can be simplified is shown for the Reference Equals shown for all generic parameters Dec 5, 2017
@Tornhoof Tornhoof changed the title IDE0041 Null check can be simplified is shown for the Reference Equals shown for all generic parameters IDE0041 Null check can be simplified is shown for Reference Equals of all generic parameters Dec 5, 2017
@gafter gafter added the Area-IDE label Dec 6, 2017
@dpoeschl dpoeschl added the Bug label Dec 20, 2017
@dpoeschl dpoeschl modified the milestones: 15.6, 15.7 Dec 20, 2017
@dpoeschl dpoeschl added the help wanted The issue is "up for grabs" - add a comment if you are interested in working on it label Dec 20, 2017
@jinujoseph jinujoseph added 4 - In Review A fix for the issue is submitted for review. and removed help wanted The issue is "up for grabs" - add a comment if you are interested in working on it labels Feb 14, 2018
@sharwell sharwell added Resolution-Fixed The bug has been fixed and/or the requested behavior has been implemented and removed 4 - In Review A fix for the issue is submitted for review. labels Feb 14, 2018
@Zshazz
Copy link

Zshazz commented Sep 29, 2018

My apologies for asking a question on an old issue, but I have recently run into this on VS Professional 15.8.5. I see that it should have been addressed in 15.7. Is that accurate? If so, there may have been a regression.

The following code still has suggestions for IDE0041 in all places (including the original repro above):

    public sealed class A
    {
        public bool Test<T>(T a) => ReferenceEquals(a, null); // IDE0041 not valid here

        public static void NotNull<T>(T value, string parameterName)
        {
            if (ReferenceEquals(value, null)) // IDE0041 not valid here
            {
                throw new ArgumentNullException(parameterName);
            }
        }
    }

    public class B<T>
    {
        public bool Test(T b) => ReferenceEquals(b, null); // IDE0041 not valid here
    }

@Logopher
Copy link

Logopher commented Oct 2, 2018

I also see this in 15.8.3, with a non-generic reference type.

@Neme12
Copy link
Contributor

Neme12 commented Oct 2, 2018

@sharwell I see it too. Can you reopen this?

@jinujoseph jinujoseph reopened this Oct 3, 2018
@jinujoseph jinujoseph removed the Resolution-Fixed The bug has been fixed and/or the requested behavior has been implemented label Oct 3, 2018
@jinujoseph jinujoseph modified the milestones: 15.7, 16.0 Oct 3, 2018
@Neme12
Copy link
Contributor

Neme12 commented Oct 3, 2018

cc @MaStr11

@MaStr11
Copy link
Contributor

MaStr11 commented Oct 3, 2018

For unconstrained generic parameters, we should offer to simplify to == null (instead of the invalid is null). See the test here:

[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseIsNullCheck)]
public async Task TestValueParameterTypeIsUnconstrainedGeneric()
{
await TestInRegularAndScriptAsync(
@"
class C
{
public static void NotNull<T>(T value)
{
if ([||]ReferenceEquals(value, null))
{
return;
}
}
}
", @"
class C
{
public static void NotNull<T>(T value)
{
if (value == null)
{
return;
}
}
}

This behavior was discussed on the PR that fixed this issue:
#24173 (comment)

It seems that IDE0041 is properly reported, but the CodeAction to do the fix does nothing:

2018-10-03 12_23_20-window

This might already be fixed by @CyrusNajmabadi in commit Fix conflict between fixers that was preventing one from showing up. 856932a#diff-f2c45bae9d7dfdbb5253223b6ecfdb48

because if I add the code from above to a test in master MaStr11@77c29cd the test is green (it does the right thing, without any other changes). @CyrusNajmabadi Can you confirm that the current behavior in 15.8.5 is already fixed in master?

PS: It seems the special caseing (== null instead of is null) can be removed soon because #25995 is merged and fixes dotnet/csharplang#1284.

@Neme12
Copy link
Contributor

Neme12 commented Oct 3, 2018

This might already be fixed by @CyrusNajmabadi in commit Fix conflict between fixers that was preventing one from showing up. 856932a#diff-f2c45bae9d7dfdbb5253223b6ecfdb48

You're right, I just checked and this is fixed in master. Although it's a little weird that the code fix title says "Use 'is null' check". In my opinion it should say "Use '== null' check" here.

image

PS: It seems the special caseing (== null instead of is null) can be removed soon because #25995 is merged and fixes dotnet/csharplang#1284.

I'm assuming that the language feature would only be enabled for C# 8. If that's the case, this logic cannot be removed. It still has to work this way if somebody has LangVersion set to 7.3 or below.

@MaStr11
Copy link
Contributor

MaStr11 commented Oct 3, 2018

Thanks for checking, that it is fixed in master. I couldn't check it myself because I have trouble getting my Roslyn experimental hive working (once more).

In my opinion it should say "Use '== null' check" here.

That's right. I think we did so because this is temporary until C# 8 is released and it's an edge case that doesn't come up that often. The title already distinguishes between is null and not is null and could be extended to also support == and !=.

var title = negated ? GetIsNotNullTitle() : GetIsNullTitle();

I'm assuming that the language feature would only be enabled for C# 8. If that's the case, this logic cannot be removed. It still has to work this way if somebody has LangVersion set to 7.3 or below.

Right.

@Neme12
Copy link
Contributor

Neme12 commented Oct 3, 2018

I think we did so because this is temporary until C# 8 is released

It is "sort of" temporary. C# 7 will not change and many users will (as always) continue using projects that have to support building in VS 2017, or even 2015 and avoid using C# 8 for a few years. It would be nice if the title was fixed, because this special case is not going to get removed any time soon.

@sharwell sharwell added the Resolution-Fixed The bug has been fixed and/or the requested behavior has been implemented label Oct 3, 2018
@sharwell sharwell removed this from the 16.0 milestone Oct 3, 2018
@sharwell sharwell added this to the 15.7 milestone Oct 3, 2018
@sharwell sharwell removed the Resolution-Fixed The bug has been fixed and/or the requested behavior has been implemented label Oct 3, 2018
@sharwell
Copy link
Member

sharwell commented Oct 3, 2018

Closing this as the original bug was still fixed as described. Regressions can be opened as a new issue. Otherwise it makes a mess of the history and links between PRs and issues.

@sharwell sharwell closed this as completed Oct 3, 2018
@sharwell sharwell added the Resolution-Fixed The bug has been fixed and/or the requested behavior has been implemented label Oct 3, 2018
@sharwell
Copy link
Member

sharwell commented Oct 3, 2018

PS: It seems the special caseing (== null instead of is null) can be removed soon ...

I believe this would need a check for the LangVersion property of the project, but that's pretty normal by now.

You're right, I just checked and this is fixed in master.

Based on this, I don't think we need to create a new issue, but we can if people want.

@CyrusNajmabadi
Copy link
Member

I'm fine with this case having a slightly incorrect title. :)

@CyrusNajmabadi
Copy link
Member

@CyrusNajmabadi Can you confirm that the current behavior in 15.8.5 is already fixed in master?

It works for me in master. So things seem fine :)

@NN---
Copy link

NN--- commented Oct 22, 2018

Still not fixed in 15.8.7:

Several samples:

		public T Value
		{
			get
			{
				var some = this as Some;
				Code.AssertState(!ReferenceEquals(some, null), "Option has no value."); // IDE0041
				return some.Value;
			}
		}
		public bool Equals(Option<T> other)
		{
			if (other == null)
				return false;

			var thisSome  = this as Some;
			var otherSome = other as Some;

			if (ReferenceEquals(thisSome, null)) // IDE0041
				return ReferenceEquals(otherSome, null); // IDE0041

			if (ReferenceEquals(otherSome, null)) // IDE0041
				return false;

			return EqualityComparer<T>.Default.Equals(Value, other.Value);
		}

@TheBeardedLlama
Copy link

Yep I'm getting the same

Looks like we need a new issue and a proper explanation of the situation

@Neme12
Copy link
Contributor

Neme12 commented Oct 23, 2018

What is Some? Can you please make a full code example?

@NN---
Copy link

NN--- commented Oct 23, 2018

https://github.com/rsdn/CodeJam/blob/af4d33847cf71e6b8f0d8e11b1d5a9edd0d76ad9/Main/src/Structures/Option/Option%601.cs

You can open CodeJam.sln in this project and see all these warnings .

@jmarolf
Copy link
Contributor

jmarolf commented Oct 23, 2018

I believe this is fixed in 15.9

@abelbraaksma
Copy link

abelbraaksma commented Nov 15, 2018

I believe this is fixed in 15.9

Nope, just tested 15.9.0 and it is still the same. Also, the auto-correction of the suggested fix does nothing, it leaves the code untouched, even for the simplest cases. It currently says "is null" and not "== null".

image

Edit: it seems that negation of the message doesn't work either, it doesn't say "is not null", nor "!= null":

image

And considering the discussion above, I am not sure whether replacing it with null == other is actually the preferred edit here, but I have to admit that I am not aware of the full set of changes of C# 8, let alone whether changing this would hamper if the same code gets compiled with C# 7 as well.

@jmarolf
Copy link
Contributor

jmarolf commented Nov 15, 2018

@abelbraaksma the correct thing is to do nothing here. At least we do not apply the codefix. We should update the bug to say that the problem is the codefix being offered at all. Looks like someone added some logic so it wasn't applied anymore

@jmarolf jmarolf reopened this Nov 15, 2018
@jmarolf
Copy link
Contributor

jmarolf commented Nov 15, 2018

@CyrusNajmabadi looks like this was regressed in 15.9

@CyrusNajmabadi
Copy link
Member

Works for me on the latest bits:

image

I can see the fix isn't in 15.9: https://github.com/dotnet/roslyn/blob/dev15.9.x/src/Features/Core/Portable/UseIsNullCheck/AbstractUseIsNullForReferenceEqualsCodeFixProvider.cs

Specifically, it's missing these lines:

private static bool IsSupportedDiagnostic(Diagnostic diagnostic)
=> diagnostic.Properties[UseIsNullConstants.Kind] == UseIsNullConstants.ReferenceEqualsKey;

So this is simply a case of #29458 not being included in 15.9 for some reason.

@jmarolf I don't know how i can help here. The bug has been fixed. Roslyn has just chosen to not release it yet. Let me know if you need any more info. Thanks!

@CyrusNajmabadi
Copy link
Member

Closing out. Have validated this is working in the 16.x line.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area-IDE Bug Resolution-Fixed The bug has been fixed and/or the requested behavior has been implemented
Projects
None yet
Development

No branches or pull requests