Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@333fred
Copy link
Member

@333fred 333fred commented Oct 10, 2025

There are specific scenarios where applicability will remove a symbol from lookup entirely; no error, just silent removal. This introduces a null that consumers were not expecting and caused an NRE. I've handled that NRE here and annotated the API. Fixes https://developercommunity.visualstudio.com/t/NRE-in-Roslyn-v500-225451107/10979295.

There are specific scenarios where applicability will remove a symbol from lookup entirely; no error, just silent removal. This introduces a `null` that consumers were not expecting and caused an NRE. I've handled that NRE here and annotated the API. Fixes https://developercommunity.visualstudio.com/t/NRE-in-Roslyn-v500-225451107/10979295.
@333fred 333fred requested a review from a team as a code owner October 10, 2025 00:42
var code2 = """
namespace N2;

file static class E
Copy link
Member Author

@333fred 333fred Oct 10, 2025

Choose a reason for hiding this comment

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

One such "remove without any errors" scenario is when a file class is out of scope:

https://github.com/333fred/roslyn/blob/1a6213d6fe1b37b01bd8816f5a93d681d070e435/src/Compilers/CSharp/Portable/Binder/Binder_Lookup.cs#L1471-L1475

There are other scenarios in which lookup can return a result with a null symbol, but this proved to be the easiest to replicate as @viceroypenguin gave me a dump where he hit it. #Closed

Copy link
Member

@jcouv jcouv Oct 10, 2025

Choose a reason for hiding this comment

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

Thanks for fixing this. I don't quite understand how the scenario differs from existing InstanceMethodInvocation_VariousScopes_Errors which also has a file-scoped extension (therefore inaccessible) :-/

Update: ah, the receiver is non existent...

@333fred
Copy link
Member Author

333fred commented Oct 10, 2025

@dotnet/roslyn-compiler for review

using System.Globalization;
using System.Linq;
using System.Reflection.Metadata.Ecma335;
using System.Text;
Copy link
Contributor

@AlekseyTs AlekseyTs Oct 10, 2025

Choose a reason for hiding this comment

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

Is this using necessary? #Closed

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, for Encoding.


var parseOptions = TestOptions.Regular.WithLanguageVersion(languageVersion);
var comp = CreateCompilation([
CSharpSyntaxTree.ParseText(code, path: "file1.cs", encoding: Encoding.UTF8, options: parseOptions),
Copy link
Contributor

@AlekseyTs AlekseyTs Oct 10, 2025

Choose a reason for hiding this comment

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

CSharpSyntaxTree.ParseText(code, path: "file1.cs", encoding: Encoding.UTF8, options: parseOptions)

It looks like this can be simplified to (code, "file1.cs"). Similar the next item. #Closed

Copy link
Contributor

Choose a reason for hiding this comment

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

parseOptions can be passed to CreateCompilation.

}
""";

var comp = CreateCompilation([CSharpSyntaxTree.ParseText(code, path: "file1.cs", encoding: Encoding.UTF8), CSharpSyntaxTree.ParseText(code2, path: "file2.cs", encoding: Encoding.UTF8)]);
Copy link
Contributor

@AlekseyTs AlekseyTs Oct 10, 2025

Choose a reason for hiding this comment

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

[CSharpSyntaxTree.ParseText(code, path: "file1.cs", encoding: Encoding.UTF8), CSharpSyntaxTree.ParseText(code2, path: "file2.cs", encoding: Encoding.UTF8)

Similar suggestion to simplify compilation creation code. Encoding.UTF8 is probably not required to reproduce the problem and even if it is, it looks like it is what our test helpers use by default anyway. #Closed

{
Symbol extensionMember = singleLookupResult.Symbol;
Symbol? extensionMember = singleLookupResult.Symbol;
if (extensionMember is null)
Copy link
Contributor

@AlekseyTs AlekseyTs Oct 10, 2025

Choose a reason for hiding this comment

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

extensionMember is null

It is probably preferrable to check that singleLookupResult.Kind is LookupResultKind.Empty. I do not think we expect null symbol otherwise. #Closed

internal SingleLookupResult(LookupResultKind kind, Symbol symbol, DiagnosticInfo error)
internal SingleLookupResult(LookupResultKind kind, Symbol? symbol, DiagnosticInfo? error)
{
this.Kind = kind;
Copy link
Contributor

@AlekseyTs AlekseyTs Oct 10, 2025

Choose a reason for hiding this comment

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

this.Kind = kind;

Consider adding an assert that symbol is not null unless kind is empty. #Closed

@AlekseyTs
Copy link
Contributor

AlekseyTs commented Oct 10, 2025

                scope.Binder.EnumerateAllExtensionMembersInSingleBinder(singleLookupResults, node.Name, arity, options, originalBinder: this, ref discardedUseSiteInfo, ref discardedUseSiteInfo);

I think it would be better long term to filter out empty results in EnumerateAllExtensionMembersInSingleBinder instead of having all existing and future consumers to worry about specially handling this situation. #Closed


Refers to: src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs:10895 in 1a6213d. [](commit_id = 1a6213d, deletion_comment = False)

@AlekseyTs
Copy link
Contributor

AlekseyTs commented Oct 10, 2025

Done with review pass (commit 1) #Closed

@jcouv jcouv self-requested a review October 10, 2025 15:13
@jcouv jcouv added the Feature - Extension Everything The extension everything feature label Oct 10, 2025
foreach (SingleLookupResult singleLookupResult in singleLookupResults)
{
Symbol extensionMember = singleLookupResult.Symbol;
var extensionMember = singleLookupResult.Symbol;
Copy link
Contributor

@AlekseyTs AlekseyTs Oct 10, 2025

Choose a reason for hiding this comment

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

var

Consider reverting change on this line. #Closed

Copy link
Contributor

Choose a reason for hiding this comment

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

I realized that it is probably driven by added nullable annotations

Copy link
Member Author

Choose a reason for hiding this comment

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

Yep, that's the reason.

result.Add(resultOfThisMember);
}

if (candidate is MethodSymbol { IsStatic: false } shadows &&
Copy link
Contributor

@AlekseyTs AlekseyTs Oct 10, 2025

Choose a reason for hiding this comment

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

if (candidate is MethodSymbol { IsStatic: false } shadows &&

It looks like this if belongs inside the if added above #Closed

@AlekseyTs
Copy link
Contributor

AlekseyTs commented Oct 10, 2025

Done with review pass (commit 2) #Closed

Copy link
Contributor

@AlekseyTs AlekseyTs left a comment

Choose a reason for hiding this comment

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

LGTM (commit 3)

@333fred
Copy link
Member Author

333fred commented Oct 10, 2025

@dotnet/roslyn-compiler for a second review.

@jcouv jcouv self-assigned this Oct 10, 2025
Copy link
Member

@jcouv jcouv left a comment

Choose a reason for hiding this comment

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

LGTM Thanks (commit 3)

@333fred 333fred merged commit 16883a5 into dotnet:main Oct 13, 2025
24 checks passed
@333fred 333fred deleted the nre branch October 13, 2025 23:02
@dotnet-policy-service dotnet-policy-service bot added this to the Next milestone Oct 13, 2025
@MaceWindu
Copy link

MaceWindu commented Nov 21, 2025

@333fred could you please tell, which release contains this fix. We still see issue with v10 SDK (10.0.100)

nevermind, will be in december release

@333fred
Copy link
Member Author

333fred commented Dec 17, 2025

/backport to release/dev18.0

@github-actions
Copy link
Contributor

Started backporting to release/dev18.0 (link to workflow run)

@333fred
Copy link
Member Author

333fred commented Dec 17, 2025

@MaceWindu apologies, I got my milestones mixed up and this is not in 10.0.1xx. I'm working on it now.

@github-actions
Copy link
Contributor

@333fred backporting to release/dev18.0 failed, the patch most likely resulted in conflicts. Please backport manually!

git am output
$ git am --3way --empty=keep --ignore-whitespace --keep-non-patch changes.patch

Applying: Handle potential null in extension lookup
Using index info to reconstruct a base tree...
M	src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs
M	src/Compilers/CSharp/Test/Emit3/Semantics/ExtensionTests2.cs
Falling back to patching base and 3-way merge...
Auto-merging src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs
Auto-merging src/Compilers/CSharp/Test/Emit3/Semantics/ExtensionTests2.cs
CONFLICT (content): Merge conflict in src/Compilers/CSharp/Test/Emit3/Semantics/ExtensionTests2.cs
error: Failed to merge in the changes.
hint: Use 'git am --show-current-patch=diff' to see the failed patch
hint: When you have resolved this problem, run "git am --continue".
hint: If you prefer to skip this patch, run "git am --skip" instead.
hint: To restore the original branch and stop patching, run "git am --abort".
hint: Disable this message with "git config set advice.mergeConflict false"
Patch failed at 0001 Handle potential null in extension lookup
Error: The process '/usr/bin/git' failed with exit code 128

Link to workflow output

333fred added a commit to 333fred/roslyn that referenced this pull request Dec 17, 2025
There are specific scenarios where applicability will remove a symbol from lookup entirely; no error, just silent removal. This introduces a `null` that consumers were not expecting and caused an NRE. I've handled that NRE here and annotated the API. Fixes https://developercommunity.visualstudio.com/t/NRE-in-Roslyn-v500-225451107/10979295.

(cherry picked from commit 16883a5)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Area-Compilers Feature - Extension Everything The extension everything feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants