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

Fix analyzer failure where incorrect SemanticModel is used #91764

Merged
merged 4 commits into from
Mar 14, 2024

Conversation

davidwrighton
Copy link
Member

Go get the appropriate semantic model when we happen to end up with a different SyntaxTree for the implementation of a property we are recursively analyzing. This is quite slow, but isn't very common.

Fixes #90356

@ghost
Copy link

ghost commented Sep 7, 2023

Tagging subscribers to this area: @hoyosjs
See info in area-owners.md if you want to be subscribed.

Issue Details

Go get the appropriate semantic model when we happen to end up with a different SyntaxTree for the implementation of a property we are recursively analyzing. This is quite slow, but isn't very common.

Fixes #90356

Author: davidwrighton
Assignees: -
Labels:

area-Infrastructure-coreclr

Milestone: -

@davidwrighton
Copy link
Member Author

@agocke, @VSadov could one of you take a look at this and confirm that this is basically a sensible idea?

@@ -293,6 +293,12 @@ private static INamedTypeSymbol[][] DecomposePropertySymbolForIsSupportedGroups_
if (propertyDefiningSyntax is PropertyDeclarationSyntax propertyDeclaration
&& propertyDeclaration.ExpressionBody is ArrowExpressionClauseSyntax arrowExpression)
{
if (model.SyntaxTree != arrowExpression.SyntaxTree)
Copy link
Member

Choose a reason for hiding this comment

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

I think this problem is actually caused by the DeclaringSyntaxReferences[0] call above. I think the only way you can get into this situation (property syntax is in a different syntax tree) is if you have a partial property with multiple definitions. When you grab [0] you might not be looking at the right one. I think you may want to iterate through the syntax references and match up the appropriate tree.

This broadly assumes that I know what this method is doing.

Can you broadly describe what's going on here?

Copy link
Member Author

Choose a reason for hiding this comment

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

So, what this code is doing is finding a statement like...

if (SomeProperty)
{
Sse3.DoSomethingIntrinsic
}

and trying to check to see if SomeProperty is implemented by a property accessor like...

public bool SomeProperty => Sse3.IsSupported;

So, what we're doing here is a bit of interprocedural analysis. When this analyzer was written, it so happened that just using whatever SemanticModel we had lying around worked just fine, but at some point this started detecting that the SemanticModel wasn't associated with the syntax tree which implemented the property. Given that we only get to this logic when we've already found an ArrowExpressionClauseSyntax, I don't think this is a partial property problem, but perhaps there was some refactoring so that we had a new case where the property was implemented via a different SyntaxTree. (I don't know why we have multiple syntax trees, in Roslyn, I expect you know more about this than I do.)

Copy link
Member

@agocke agocke Sep 7, 2023

Choose a reason for hiding this comment

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

I see, so the problem is that you're trying to jump from definition to definition, and using the same semantic model, which may not be attached to the same tree.

In that case, this can work, but inter-procedural analaysis in Roslyn is always pretty fishy. It kind of sounds like you want something like the linker/AOT capability analyzer -- SomeProperty provides some capability, and only inside the check is that capability valid.

We haven't yet generalized this analysis to define arbitrary capabilities and checks, but this is on the table for .NET 9. + @sbomer

So, with this existing code... I think it's fine. Nothing jumps out at me as fundamentally wrong with this approach. However, only looking at the first Declaration is still a bug. Properties can be partial, meaning they can have multiple declarations, and you need to check them all. You should enumerate each one and run this logic for all of them. Also, there's the special-casing of ArrowExpression which is nasty, but that's a whole separate problem (you probably want the IOperation tree instead of the syntax tree).

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah, I'm not saying any of this analysis is pretty... or clean. Just that it works for System.Private.CoreLib, which is all that is necessary (This is a System.Private.CoreLib specific analyzer). I don't see what there is to fix around the ArrowExpression and only the first declaration. Could you provide an example of how we could have a property with multiple definitions which is implemented via an arrow expression? I'm not aware of any way to write that. The logic here requires all relevant properties to be implemented via arrow expressions, just to simplify the analysis.

Copy link
Member

@agocke agocke Sep 8, 2023

Choose a reason for hiding this comment

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

provide an example

Sorry, I assumed dotnet/csharplang#6420 was going to make it into C# 12, but it looks like it didn't make the cut. So partial properties are not yet legal.

If the feature does make it into a future release, the code would look like https://sharplab.io/#v2:EYLgtghglgdgNAExAagD4AEBMBGAsAKHQGYACABwgCcAXKCAGxKxIGESBvAk7p0imuo2AB7YYwCyATwAKlYWQCmNSRxIBzBdQDcJAL5cexJgBYS4gBQBKDge7789gkf60GTTKxv4evclVdCohIycorKJAC8AHwk1JQArgpaBLpAA

You could potentially use the for loop for future proofing, but it won't make a difference right now.

@davidwrighton davidwrighton merged commit 2e8a852 into dotnet:main Mar 14, 2024
169 of 178 checks passed
@github-actions github-actions bot locked and limited conversation to collaborators Apr 14, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

IntrinsicsInSystemPrivateCoreLibAnalyzer throwing ArgumentException
3 participants