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

Do not offer to remove cast if it will cause the compiler to warn about it. #43492

Merged
merged 3 commits into from
Apr 22, 2020

Conversation

CyrusNajmabadi
Copy link
Member

Fixes #40414

@CyrusNajmabadi CyrusNajmabadi requested review from a team as code owners April 19, 2020 22:18
default:
return false;
}
}
Copy link
Member Author

Choose a reason for hiding this comment

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

same impl as VB. moved to common location so C#/VB compilers can reference this, as can IDE.

@@ -50,6 +52,10 @@ internal CommonConversion(bool exists, bool isIdentity, bool isNumeric, bool isR
/// </summary>
public bool IsIdentity => (_conversionKind & ConversionKind.IsIdentity) == ConversionKind.IsIdentity;
/// <summary>
/// Returns true if the conversion is an nullable conversion.
/// </summary>
public bool IsNullable => (_conversionKind & ConversionKind.IsNullable) == ConversionKind.IsNullable;
Copy link
Member Author

Choose a reason for hiding this comment

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

this seems safe to add to the common layer. Both VB and C# have htis concept and it seems identical from my reading. Namely:

c#:

Implicit nullable conversions

Predefined implicit conversions that operate on non-nullable value types can also be used with nullable forms of those types. For each of the predefined implicit identity and numeric conversions that convert from a non-nullable value type S to a non-nullable value type T, the following implicit nullable conversions exist:

  • An implicit conversion from S? to T?.
  • An implicit conversion from S to T?.

Evaluation of an implicit nullable conversion based on an underlying conversion from S to T proceeds as follows:

  • If the nullable conversion is from S? to T?:

    • If the source value is null (HasValue property is false), the result is the null value of type T?.
    • Otherwise, the conversion is evaluated as an unwrapping from S? to S, followed by the underlying conversion from S to T, followed by a wrapping (Nullable types) from T to T?.
  • If the nullable conversion is from S to T?, the conversion is evaluated as the underlying conversion from S to T followed by a wrapping from T to T?.

(and the corresponding explicit version of this)

VB:

A value type T can convert to and from the nullable version of the type, T?. The conversion from T? to T throws a System.InvalidOperationException exception if the value being converted is Nothing. Also, T? has a conversion to a type S if T has an intrinsic conversion to S. And if S is a value type, then the following intrinsic conversions exist between T? and S?:

  • A conversion of the same classification (narrowing or widening) from T? to S?.
  • A conversion of the same classification (narrowing or widening) from T to S?.
  • A narrowing conversion from S? to T.

Case Else
Return False
End Select
End Function
Copy link
Member Author

Choose a reason for hiding this comment

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

removed in favor of the identical common version.

@CyrusNajmabadi
Copy link
Member Author

@dotnet/roslyn-compiler @jcouv @333fred could i get eyes here? Thanks!

@@ -22,6 +22,7 @@ Microsoft.CodeAnalysis.ITypeSymbol.IsNativeIntegerType.get -> bool
Microsoft.CodeAnalysis.InitializationContext
Microsoft.CodeAnalysis.InitializationContext.CancellationToken.get -> System.Threading.CancellationToken
Microsoft.CodeAnalysis.InitializationContext.RegisterForSyntaxNotifications(Microsoft.CodeAnalysis.SyntaxReceiverCreator receiverCreator) -> void
Microsoft.CodeAnalysis.Operations.CommonConversion.IsNullable.get -> bool
Copy link
Member

Choose a reason for hiding this comment

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

Tagging @jaredpar @gafter @333fred as FYI for public API change

/// <summary>
/// Checks if a type is considered a "built-in integral" by CLR.
/// </summary>
public static bool IsIntegralType(this SpecialType specialType)
Copy link
Member

Choose a reason for hiding this comment

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

IsIntegralType [](start = 27, length = 14)

Please add a compiler test that will fail once this change is merged with the native ints feature. That way we'll be reminded/forced to add logic here.

Copy link
Member

Choose a reason for hiding this comment

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

Hum, I got confused. Native ints have been merged already.
Tagging @cston to confirm whether this method should handle them.


In reply to: 412454952 [](ancestors = 412454952)

Copy link
Member

Choose a reason for hiding this comment

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

I reviewed this method before merging the native integers feature, and didn't find a caller that might have a native integer type.


In reply to: 412468506 [](ancestors = 412468506,412454952)

@@ -486,4 +487,7 @@
<ItemGroup Condition="'$(DefaultLanguageSourceExtension)' != '' AND '$(BuildingInsideVisualStudio)' != 'true'">
<ExpectedCompile Include="$(MSBuildThisFileDirectory)**\*$(DefaultLanguageSourceExtension)" />
</ItemGroup>
<ItemGroup>
Copy link
Member

Choose a reason for hiding this comment

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

What does this do?

Copy link
Member Author

Choose a reason for hiding this comment

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

basically, it gives us a folder in the UI where this linked file goes. it seems needed because we have our own file called SpecialTypeExtensions, and we want to link in yours.

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.

Compiler change LGTM Thanks (iteration 3)

Copy link
Member

@333fred 333fred left a comment

Choose a reason for hiding this comment

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

Compiler changes LGTM (commit 3)

@CyrusNajmabadi
Copy link
Member Author

Thanks all!

@CyrusNajmabadi CyrusNajmabadi merged commit 8f4fdad into dotnet:master Apr 22, 2020
@ghost ghost added this to the Next milestone Apr 22, 2020
@CyrusNajmabadi CyrusNajmabadi deleted the orWideningCastCheck branch April 22, 2020 04:28
@@ -315,6 +320,227 @@ public static bool IsUnnecessaryAsCast(BinaryExpressionSyntax cast, SemanticMode
return false;
}

private static bool CastRemovalWouldCauseSignExtensionWarning(ExpressionSyntax expression, SemanticModel semanticModel, CancellationToken cancellationToken)
{
// Logic copied from DiagnosticsPass_Warnings.CheckForBitwiseOrSignExtend. Including comments.
Copy link
Contributor

Choose a reason for hiding this comment

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

Would it be possible to move this logic to a shared helper class in a separate file in compiler layer, so it can be linked into this project instead of cloned? I am concerned this would diverge pretty soon and introduce bugs.

Copy link
Contributor

Choose a reason for hiding this comment

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

I understand this has lot of customer logic specific to the analyzer, but it would be good if at least the core logic that can possibly be shared is shared. Please let me know if you have already done so for everything possible, in which case it is fine.

Copy link
Member Author

Choose a reason for hiding this comment

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

  1. Unfortunately, the compiler logic is all built on compiler internals (i.e. bound nodes).
  2. i did have to tweak some things. for example, our function says: would this be an issue if the cast was removed. the compiler version obviously is written analyzing the actual expression witht the cast.

I am concerned this would diverge pretty soon and introduce bugs.

So i looked, and this hasn't changed in the compiler layer since we went open source. it's effectively a very very old holdover from the native compiler. So i'm not really concerned about that.

Please let me know if you have already done so for everything possible, in which case it is fine.

I tried to share as much as i could. all the helper extensions are shared. but the core logic that does this specific check is still a copy :-/

@sharwell sharwell modified the milestones: Next, temp, 16.7.P1 Apr 28, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Invalid IDE0004 diagnostic
6 participants