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

PreviewFeatures - Handle an error case where GetOverriddenMembers() returns null for an indexer #5596

Merged
merged 1 commit into from
Oct 7, 2021

Conversation

tannergooding
Copy link
Member

@tannergooding tannergooding commented Oct 4, 2021

Customer Impact

The Requires Preview Features Analyzer (CA2252) encounters an unhandled exception in some scenarios when null symbols are evaluated. This was discovered while @tannergooding was consuming preview features in the TerraFX project and an indexer property was evaluated.

Severity Code Description Project File Line Suppression State Detail Description
Error AD0001 Analyzer 'Microsoft.NetCore.Analyzers.Runtime.DetectPreviewFeatureAnalyzer' threw an exception of type 'System.ArgumentNullException' with message 'Value cannot be null.
Parameter name: key'.
Exception occurred with following context:
Compilation: TerraFX.Samples.DirectX
IOperation: PropertyReference
SyntaxTree: C:\Users\tagoo\Source\repos\terrafx.interop.windows\samples\DirectX\D3D12\HelloTriangle12.cs
SyntaxNode: psoDesc.RTVFormats[0] [ElementAccessExpressionSyntax]@[5006..5027) (110,12)-(110,33)

Fix

Defensive code was added to bail from symbol analysis if the symbol is null.

Testing

Additional test coverage was added for indexer properties. Another test gap of ref T properties was identified during this testing, and another test was added for that scenario; the test passed without the fix herein. The fix was also validated against the TerraFX project scenarios.

Risks

Very low. Addition of defensive code to prevent an unhandled exception. The code path could never have resulted in a diagnostic being reported for a null symbol, so behavior is otherwise unchanged.

@tannergooding tannergooding requested a review from a team as a code owner October 4, 2021 16:02
@tannergooding
Copy link
Member Author

It's not quite clear why the type is marked IsOverriden but GetOverriddenMembers returns null, it seems like possibly a deeper issue in dotnet/roslyn.

In particular, Roslyn has this logic for IsOverridden

        // Has to be metadata virtual and cannot be a destructor.  
        // Must either lack the newslot flag or be an explicit override (i.e. via the MethodImpl table).
        //
        // The IsExplicitClassOverride case is based on LangImporter::DefineMethodImplementations in the native compiler.
        // ECMA-335 
        // 10.3.1 Introducing a virtual method
        // If the definition is not marked newslot, the definition creates a new virtual method only 
        // if there is not virtual method of the same name and signature inherited from a base class.
        //
        // This means that a virtual method without NewSlot flag in a type that doesn't have a base
        // is a new virtual method and doesn't override anything.
        public override bool IsOverride =>
            !this._containingType.IsInterface &&
            this.IsMetadataVirtual() && !this.IsDestructor &&
            ((!this.IsMetadataNewSlot() && (object)_containingType.BaseTypeNoUseSiteDiagnostics != null) || this.IsExplicitClassOverride);

and a virtual indexer emits:

.method public hidebysig specialname newslot virtual 
        instance int32 get_Item (
            int32 index
        ) cil managed 

while an overriding indexer emits:

.method public hidebysig specialname virtual 
        instance int32 get_Item (
            int32 index
        ) cil managed 

So everything looks like it should line up here.

@@ -533,5 +533,99 @@ class Derived: Program
test.ExpectedDiagnostics.Add(VerifyCS.Diagnostic(DetectPreviewFeatureAnalyzer.OverridesPreviewMethodRule).WithLocation(1).WithArguments("AProperty", "Program.AProperty"));
await test.RunAsync();
}

[Fact]
public async Task TestRefProperty()
Copy link
Member Author

Choose a reason for hiding this comment

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

Just noting that ref T Property isn't a bug case here; I initially thought it might have been however and there was no coverage for it.

@tannergooding
Copy link
Member Author

CC. @buyaa-n

Copy link
Member

@buyaa-n buyaa-n left a comment

Choose a reason for hiding this comment

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

LGTM, Isn't it need to be fixed in 6.0? Then please target release/6.0.1xx
CC @jeffhandley for approval

@buyaa-n buyaa-n requested a review from jmarolf October 6, 2021 03:51
@tannergooding
Copy link
Member Author

Then please target release/6.0.1xx

Does this not have the same general backport policies as dotnet/runtime?

@jmarolf
Copy link
Contributor

jmarolf commented Oct 6, 2021

Does this not have the same general backport policies as dotnet/runtime?

I assume you would need Tactics approval @tannergooding. main is .NET 7. merging into release/6.0.1xx will auto-merge to main. There is no need to do dual checkins

@jeffhandley
Copy link
Member

I'll send it for tactics approval tomorrow. I already gave Steve the heads-up it would be coming.

@tannergooding tannergooding changed the base branch from main to release/6.0.1xx October 6, 2021 15:23
@tannergooding
Copy link
Member Author

Retargeted against release/6.0.1xx

@jeffhandley
Copy link
Member

Tactics approved via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants