-
Notifications
You must be signed in to change notification settings - Fork 4.2k
UseType analyzers/fixers should handle ref types #27246
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
Conversation
|
|
||
|
|
||
| public static TypeSyntax StripRefIfNeeded(this TypeSyntax type) | ||
| => type is RefTypeSyntax refType ? refType.Type : type; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ideally would go in a file/type called TypeSyntaxExtensions. But that's very minor and having this here is fine.
|
So, the StripRef stuff looks fine to me. But what isn't clear is where the original crash was, and why this is fixing it. Could you clarify where that is in teh PR? Thanks! |
| return false; | ||
| } | ||
|
|
||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: extra new line.
|
The crash came from this method (see annotations). protected override bool AssignmentSupportsStylePreference(
SyntaxToken identifier,
TypeSyntax typeName,
ExpressionSyntax initializer,
SemanticModel semanticModel,
OptionSet optionSet,
CancellationToken cancellationToken)
{
...
var declaredType = semanticModel.GetTypeInfo(typeName, cancellationToken).Type; // returns null on `ref var`
if (declaredType != null && declaredType.TypeKind == TypeKind.Dynamic)
{
return false;
}
...
var conversion = semanticModel.GetConversion(expression, cancellationToken);
if (conversion.IsIdentity)
{
var initializerType = semanticModel.GetTypeInfo(expression, cancellationToken).Type;
return declaredType.Equals(initializerType); // throws here
}
return false;
} |
|
@jinujoseph for ask-mode approval for 15.8. Thanks |
|
@jcouv If if (declaredType != null && declaredType.TypeKind == TypeKind.Dynamic)unnecessary? I would expect that the method would either be completely resilient to |
|
@Neme12 There are no tests that currently result in a What I do know, however, is that when the conversion is classified as identity there must have been a types to convert from and to convert to. |
|
I'm ok with this as a spot fix. However, it def concerns me that we may have lurking issues where code assumed that "GetTypeInfo" on a TypeSyntax would always be non-null. But, for now, i think this change is fine :) |
|
@CyrusNajmabadi I'm happy to add a null check for safety. I'm just not comfortable removing one at this moment. |
|
@jinujoseph for ask-mode approval for 15.8. Thanks |
|
Approved to merge for 15.8.Preview3 |
Customer scenario
Use a
ref varin a local declaration or foreach loop.In 15.7, you would get a gold bar for an analyzer crash.
With this fix, the UseExplicitType and UseImplicitType analyzers and fixers can handle ref types (ie. only fix the type portion, leaving the
refalone).Bugs this fixes
Fixes #27221
Risk
Performance impact
Low. The core of this change is to strip the
refin a few places in the analysis logic.Is this a regression from a previous update?
No.
Root cause analysis
The bug exists since C# 7.2 (VS 2017 version 15.5) which introduced ref locals. It was compounded by
foreach refloops in C# 7.3 (15.7).How was the bug found?
Reported by customer.
Tagging @CyrusNajmabadi @dotnet/roslyn-ide for review. Thanks