Skip to content

Add new API Compilation.IsAssignableTo(fromType, toType)#26719

Closed
gafter wants to merge 10 commits intodotnet:masterfrom
gafter:master-9461
Closed

Add new API Compilation.IsAssignableTo(fromType, toType)#26719
gafter wants to merge 10 commits intodotnet:masterfrom
gafter:master-9461

Conversation

@gafter
Copy link
Copy Markdown
Member

@gafter gafter commented May 8, 2018

We also remove the similar internal method from ISemanticFactsService
Fixes #9461

/cc @CyrusNajmabadi for preliminary review

We also remove the similar internal method from ISemanticFactsService
Fixes dotnet#9461
@gafter gafter added Concept-API This issue involves adding, removing, clarification, or modification of an API. Area-Compilers Feature Request PR For Personal Review Only The PR doesn’t require anyone other than the developer to review it. labels May 8, 2018
@gafter gafter added this to the 15.8 milestone May 8, 2018
@gafter gafter self-assigned this May 8, 2018
@gafter gafter requested review from a team as code owners May 8, 2018 16:00
@CyrusNajmabadi
Copy link
Copy Markdown
Contributor

Code change looks fine. But as per the issue discussion, i would want an exhaustive matrix here. i.e. have every type of type on the rows, and every type of type on hte columns, and check them all against each other (with expected positive/negative cases filled in for each intersection).

If that reveals no problems, then this seems fine to me :)

@JohanLarsson
Copy link
Copy Markdown

There is an extension method opportunity here.

fromType.IsAssignableTo(toType, compilation)

^ reads natural to me.

If there is a way to dig out the compilation from the type symbol to avoid passing in compilation it would be sweet.

/// Returns true if there is an implicit (C#) or widening (VB) conversion from
/// <paramref name="fromType"/> to <paramref name="toType"/>.
/// </summary>
public abstract bool IsAssignableTo(ITypeSymbol fromType, ITypeSymbol toType);
Copy link
Copy Markdown
Contributor

@AlekseyTs AlekseyTs May 8, 2018

Choose a reason for hiding this comment

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

IsAssignableTo [](start = 29, length = 14)

The name sounds very similar to a well known API Type.IsAssignableFrom, but according to the doc comment doesn't quite match the behavior. This could be a source of big confusion for consumers and as a result a source of misuse of the API. #Resolved

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Consider renaming to "IsSafeToConvertTo", "SafeConversionExists",or something similar.


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

Copy link
Copy Markdown

@JohanLarsson JohanLarsson May 8, 2018

Choose a reason for hiding this comment

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

I like IsAssignableTo, short & clear. #Resolved

Copy link
Copy Markdown
Contributor

@AlekseyTs AlekseyTs May 8, 2018

Choose a reason for hiding this comment

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

Also the fact that in VB a widening conversion is not a requirement for things to be assignable should be taken into consideration when choosing the name of this API #Resolved

Copy link
Copy Markdown
Contributor

@CyrusNajmabadi CyrusNajmabadi May 8, 2018

Choose a reason for hiding this comment

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

@AlekseyTs can you give some examples? it would be super helpful for getting everyone understanding this space better. Thanks! #Resolved

Copy link
Copy Markdown
Contributor

@CyrusNajmabadi CyrusNajmabadi May 8, 2018

Choose a reason for hiding this comment

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

What does that mean though? In particular, what do you define "implicit" as. And i'm with Aleksey, what does this mean in VB? #Resolved

Copy link
Copy Markdown
Contributor

@CyrusNajmabadi CyrusNajmabadi May 8, 2018

Choose a reason for hiding this comment

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

I'm willing to look through the links, but it would be useful to have primary use cases where the feature can describe precisely the sort of question it is trying to ask (in a non-self referential fashion). i.e. we shouldn't say "teh feature is trying to know if it's an implicit conversion". We should say "teh feature is trying to decide if applying the conversion at runtime would succeed or not". #Resolved

Copy link
Copy Markdown
Contributor

@CyrusNajmabadi CyrusNajmabadi May 8, 2018

Choose a reason for hiding this comment

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

For example, VB says this: "Implicit conversions occur without any special syntax". Is it true then that .isWidening is the right impl to answer that question? To me, it looks like no. For example:

If permissive semantics are being used, all widening and narrowing conversions (in other words, all conversions) may occur implicitly.

#Resolved

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

There are places in C# where non-implicit conversions occur implicitly (e.g. in a foreach loop). I'll make sure the doc comments are clear.


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

Copy link
Copy Markdown
Member Author

@gafter gafter May 9, 2018

Choose a reason for hiding this comment

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

Since we now have a team for deciding public CodeAnalysis API changes, I'll submit this question to that group. (and point them to this thread for context)


In reply to: 186923887 [](ancestors = 186923887,186879526)

/// Returns true if there is an implicit conversion from
/// <paramref name="fromType"/> to <paramref name="toType"/>.
/// </summary>
public override bool IsAssignableTo(ITypeSymbol fromType, ITypeSymbol toType)
Copy link
Copy Markdown
Contributor

@AlekseyTs AlekseyTs May 8, 2018

Choose a reason for hiding this comment

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

public override bool IsAssignableTo(ITypeSymbol fromType, ITypeSymbol toType) [](start = 8, length = 77)

Consider moving this method next to the ClassifyConversion that is calls. #ByDesign

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I'd prefer to keep it in the region that correctly describes its place in the hierarchy.


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

''' Returns true if there is a widening conversion from
''' <paramref name="fromType"/> to <paramref name="toType"/>.
''' </summary>
Public Overrides Function IsAssignableTo(fromType As ITypeSymbol, toType As ITypeSymbol) As Boolean
Copy link
Copy Markdown
Contributor

@AlekseyTs AlekseyTs May 8, 2018

Choose a reason for hiding this comment

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

Public Overrides Function IsAssignableTo(fromType As ITypeSymbol, toType As ITypeSymbol) As Boolean [](start = 8, length = 99)

Same suggestion as for C# #ByDesign

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

This region properly classifies the method.


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

// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.34011
// Runtime Version:4.0.30319.42000
Copy link
Copy Markdown
Contributor

@AlekseyTs AlekseyTs May 8, 2018

Choose a reason for hiding this comment

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

This file doesn't have any meaningful changes, consider reverting #Resolved

@AlekseyTs
Copy link
Copy Markdown
Contributor

Done with review pass (iteration 1)

@CyrusNajmabadi
Copy link
Copy Markdown
Contributor

@dotnet/analyzer-ioperation @333fred @mavasani If this gets added to the core Compilation API, can we add this to CommonConversion in IOperation as well?

@mavasani
Copy link
Copy Markdown
Contributor

mavasani commented May 8, 2018

This is a super helpful API - I think we have more than 10 such operation/symbol analyzers in FxCop analyzers package that need C# and VB implementations just to get this functionality. I will file a separate issue to track adding IOperation support for this.

@gafter
Copy link
Copy Markdown
Member Author

gafter commented May 9, 2018

This PR is pending review and suggestions by the CodeAnalysis API team, half of which are at Build now. Until they are back this is on hold.

@gafter
Copy link
Copy Markdown
Member Author

gafter commented May 14, 2018

I renamed it to IsImplicitConversion but I think HasImplicitConversion would be more grammatically correct.

/// either <paramref name="fromType"/> or <paramref name="toType"/> is null, or
/// if no such conversion exists.
/// </summary>
public abstract bool HasImplicitConversion(ITypeSymbol fromType, ITypeSymbol toType);
Copy link
Copy Markdown
Contributor

@CyrusNajmabadi CyrusNajmabadi May 15, 2018

Choose a reason for hiding this comment

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

So, i'm on the fence about this entire PR :) mainly because of how many different ways it seems to be able to determine this sort of thing. i.e. we have:

CommonCompilation.HasImplicitConversion, then we have:
CSharpCompilation/BasicComplation.ClassifyConversion, then we have
IOperation.IConversionOperation/CommonConversion

My main issue is that it feels like this doesn't go far enough. For example, what if i wanted ot ask "Is there a reference conversion between these two types?" Now i'm back where i started.

Please don't shoot me, but i think my preference here would be that instead of having this API we take the following two steps:

  1. Move a ClassifyCommonConversion call down to Compilation (and have it return a CommonConversion).
  2. Add 'IsImplicit' to CommonConversion and document (like here) that it means 'implicit' for C# and 'widening' for VB.

This would seem to solve the motivating scenario, as someone could call compilation.ClassifyCommonConversion(...).IsImplicit, but it would also still expose all the rest of hte information while being consistent with teh types/shapes we use elsewhere for talking about this stuff.

With this, we could still have HasImplicitConversion. But it could just be an extension method on Compilation, that called hte ClassifyCommonConversion helper.

Thoughts, @gafter? This PR feels a bit too "one-off" to me. I think we should go for a more generalized approach that fits in better with the shape of our API elsewhere. #Resolved

Copy link
Copy Markdown
Member Author

@gafter gafter May 15, 2018

Choose a reason for hiding this comment

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

I think this is a great suggestion. I will investigate more. #Resolved

Copy link
Copy Markdown
Contributor

@mavasani mavasani May 15, 2018

Choose a reason for hiding this comment

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

+1 #Resolved

Copy link
Copy Markdown
Contributor

@CyrusNajmabadi CyrusNajmabadi May 15, 2018

Choose a reason for hiding this comment

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

Note: one unfortunate issue here is with naming. We can't actually have "ClassifyConversion" on Compilatoin as that would now shadow the extensions we have for the language specific ClassifyConversion extensions. Hence why it would be called ClassifyCommonConversion instead. But i feel like that's not too bad, especially given the different types of results actually returned. #Resolved

Copy link
Copy Markdown
Contributor

@CyrusNajmabadi CyrusNajmabadi left a comment

Choose a reason for hiding this comment

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

In terms of exposing the HasImplicitConversoin method, i think this PR is fine. However... i've given feedback that i think overall we could still answer that questoin in a more general and cleaner fashion. Thanks!

@gafter
Copy link
Copy Markdown
Member Author

gafter commented May 17, 2018

@CyrusNajmabadi Please have a look at this revised proposed API. What do you think?

namespace Microsoft.CodeAnalysis.Test.Utilities
{
public static class CompilationExtensions
public static class CompilationExtensions2
Copy link
Copy Markdown
Member

@333fred 333fred May 17, 2018

Choose a reason for hiding this comment

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

Rather than 2, can we do TestCompilationExtensions? Suffixing 2 feels wrong. #Resolved

Copy link
Copy Markdown
Member

@333fred 333fred May 17, 2018

Choose a reason for hiding this comment

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

Or CompilationTestExtensions #Resolved

@gafter
Copy link
Copy Markdown
Member Author

gafter commented May 24, 2018

Review of approved API moved to #27093

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Area-Compilers Concept-API This issue involves adding, removing, clarification, or modification of an API. Feature Request PR For Personal Review Only The PR doesn’t require anyone other than the developer to review it.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants