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 IOperation APIs for object and collection initializers #20689

Merged

Conversation

mavasani
Copy link
Contributor

@mavasani mavasani commented Jul 6, 2017

See #18781 (comment) for the final design.

Fixes #18781

@@ -1329,6 +1329,10 @@
<Field Name="Expanded" Type="bool"/>
<Field Name="ArgsToParamsOpt" Type="ImmutableArray&lt;int&gt;" Null="allow"/>
<Field Name="ResultKind" PropertyOverrides="true" Type="LookupResultKind"/>

<!-- BinderOpt and UseSetterForDefaultArgumentGeneration are added as a temporary solution for IOperation implementation and should probably be removed in the future -->
Copy link
Contributor Author

@mavasani mavasani Jul 6, 2017

Choose a reason for hiding this comment

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

Copy link
Member

Choose a reason for hiding this comment

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

Thanks for the context.
Do we have an issue tracking removing this in the future?


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

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Filed #20787

@mavasani
Copy link
Contributor Author

mavasani commented Jul 6, 2017

Also tagging @dotnet/analyzer-ioperation for review #Resolved

@CyrusNajmabadi
Copy link
Member

CyrusNajmabadi commented Jul 7, 2017

👍 #Resolved

@jinujoseph
Copy link
Contributor

jinujoseph commented Jul 7, 2017

cc/ @dotnet/roslyn-compiler #Resolved

@mavasani
Copy link
Contributor Author

mavasani commented Jul 10, 2017

Ping.. need compiler signoff on the PR. #Resolved

{
case SymbolKind.Field:
var field = (FieldSymbol)boundObjectInitializerMember.MemberSymbol;
return new LazyFieldReferenceExpression(field, instance, field, isInvalid, syntax, type, constantValue);
Copy link
Member

Choose a reason for hiding this comment

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

Is the second field parameter necessary for LazyFieldReferenceExpression? (Are the two parameter values ever different?) Same question for LazyEventReferenceExpression and LazyPropertyReferenceExpression.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Seems like it is redundant and there are more than one Operation types with such redundant parameters. I have added this to the list of comments to be addressed in the operation node generator: #20204 (comment)

Tagging @heejaechang as an FYI

return DeriveArguments(boundObjectInitializerMember.HasErrors,
boundObjectInitializerMember.BinderOpt,
property,
property.SetMethod,
Copy link
Member

Choose a reason for hiding this comment

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

CreateBoundIndexerAccessOperation() uses GetOwnOrInheritedSetMethod(). Are there cases where that will give a different accessor here? If so, consider extracting a helper method that can be used by the factory methods.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks, will change to use that method here as well.

boundMember.Type,
hasErrors);
binderOpt: this,
useSetterForDefaultArgumentGeneration: true,
Copy link
Member

Choose a reason for hiding this comment

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

useSetterForDefaultArgumentGeneration [](start = 16, length = 37)

Is there any case where useSetterForDefaultArgumentGeneration is false?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This code path is while binding left of object member initializer, so it should always invoke the setter.

Copy link
Member

Choose a reason for hiding this comment

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

I'm suggesting useSetterForDefaultArgumentGeneration should not exist if it is always true. I could not find code that could set it to false, but we should double-check.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sure, let me make that change.

@@ -237,7 +247,7 @@ private IInvocationExpression CreateBoundCallOperation(BoundCall boundCall)
boundCall.ReceiverOpt != null &&
(boundCall.Method.IsVirtual || boundCall.Method.IsAbstract || boundCall.Method.IsOverride) &&
!boundCall.ReceiverOpt.SuppressVirtualCalls;
Lazy<ImmutableArray<IArgument>> argumentsInEvaluationOrder = new Lazy<ImmutableArray<IArgument>>(() => DeriveArguments(boundCall, boundCall.BinderOpt, boundCall.Method, boundCall.Method, boundCall.Arguments, boundCall.ArgumentNamesOpt, boundCall.ArgsToParamsOpt, boundCall.ArgumentRefKindsOpt, boundCall.Method.Parameters, boundCall.Expanded, boundCall.Syntax, boundCall.InvokedAsExtensionMethod));
Lazy<ImmutableArray<IArgument>> argumentsInEvaluationOrder = new Lazy<ImmutableArray<IArgument>>(() => DeriveArguments(boundCall.HasErrors, boundCall.BinderOpt, boundCall.Method, boundCall.Method, boundCall.Arguments, boundCall.ArgumentNamesOpt, boundCall.ArgsToParamsOpt, boundCall.ArgumentRefKindsOpt, boundCall.Method.Parameters, boundCall.Expanded, boundCall.Syntax, boundCall.InvokedAsExtensionMethod));
Copy link
Member

@jcouv jcouv Jul 10, 2017

Choose a reason for hiding this comment

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

Break line #Resolved


private IMemberReferenceExpression CreateBoundObjectInitializerMemberOperation(BoundObjectInitializerMember boundObjectInitializerMember)
{
Lazy<IOperation> instance = new Lazy<IOperation>(() => new InstanceReferenceExpression(InstanceReferenceKind.Implicit, boundObjectInitializerMember.HasErrors, syntax: boundObjectInitializerMember.Syntax, type: boundObjectInitializerMember.MemberSymbol.ContainingType, constantValue: default(Optional<object>)));
Copy link
Member

Choose a reason for hiding this comment

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

break line
In general, we don't have a strict limit, but I'm confused why some code above (for example, call to DeriveArguments) is on multiple lines (good, readable), but some other lines are crazy long...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I will add break lines for the couple of cases here. The formatting is not consistent across this file, so I have added a comment to #20204 (comment). Tagging @heejaechang as an FYI, we should address this in the operation node generator.

@@ -73,7 +73,7 @@ internal static IArgument CreateArgumentOperation(ArgumentKind kind, IParameterS
// Note this check doesn't cover all scenarios. For example, when a parameter is a generic type but the type of the type argument
// is undefined.
if ((object)optionalParametersMethod == null
|| boundNode.HasAnyErrors
|| hasErrors
Copy link
Member

Choose a reason for hiding this comment

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

It looks like callers are now passing boundNode.HasErrors rather than boundNode.HasAnyErrors. I'm not sure what the implications are but was that change intentional?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'll change it to HasAnyErrors at all call sites, it was not an intentional change.

Copy link
Member

Choose a reason for hiding this comment

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

Requiring callers to pass HasAnyErrors seems error prone. Is it possible to revert to passing in the BoundNode instead?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, that seems better.

var expectedDiagnostics = new DiagnosticDescription[] {
// CS1061: 'MyList<string>' does not contain a definition for 'Add' and no extension method 'Add' accepting a first argument of type 'MyList<string>' could be found (are you missing a using directive or an assembly reference?)
// var coll = /*<bind>*/new MyList<string> { "str" }/*</bind>*/;
Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, @"""str""").WithArguments("MyList<string>", "Add").WithLocation(7, 51)
Copy link
Member

Choose a reason for hiding this comment

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

The location was dropped from the comment, here and in other cases below.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Operation unit test generator doesn't seem to include the diagnostic location in the generated comment for expected diagnostics. Filed #20788 to track updating the generator.

/// <summary>
/// Add method invoked on collection. Might be null for dynamic invocation.
/// </summary>
IMethodSymbol AddMethod { get; }
Copy link
Member

Choose a reason for hiding this comment

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

It looks like AddMethod is always null for dynamic invocation. Consider changing comment from Might be null ....

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sure.

End Function

Private Function CreateBoundCollectionElementInitializerOperation(boundExpression As BoundExpression) As IOperation
If (boundExpression.Kind <> BoundKind.Call) Then
Copy link
Member

Choose a reason for hiding this comment

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

Parentheses are not needed.


public override void VisitCollectionElementInitializerExpression(ICollectionElementInitializerExpression operation)
{
var addMethod = operation.AddMethod;
Copy link
Member

@jcouv jcouv Jul 10, 2017

Choose a reason for hiding this comment

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

Two unused locals #Resolved

Copy link
Member

Choose a reason for hiding this comment

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

The behavior of this override and a few above doesn't add anything to the base behavior. They can be removed.


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

@jcouv
Copy link
Member

jcouv commented Jul 10, 2017

        var ctor = operation.Constructor;

Unused local #Resolved


Refers to: src/Test/Utilities/Portable/Compilation/TestOperationWalker.cs:414 in 827341b. [](commit_id = 827341b, deletion_comment = False)

@jcouv
Copy link
Member

jcouv commented Jul 10, 2017

        var text = operation.Text;

Seems a recurring pattern (unused local, override only calls base). Am I missing something? #Resolved


Refers to: src/Test/Utilities/Portable/Compilation/TestOperationWalker.cs:397 in 827341b. [](commit_id = 827341b, deletion_comment = False)

Left: IOperation: (OperationKind.None) (Syntax: 'Property2')
Right: IConversionExpression (ConversionKind.Invalid, Implicit) (OperationKind.ConversionExpression, Type: B, IsInvalid) (Syntax: '1')
ILiteralExpression (Text: 1) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 1) (Syntax: '1')
Initializer: IObjectOrCollectionInitializerExpression (OperationKind.ObjectOrCollectionInitializerExpression, Type: F, IsInvalid) (Syntax: '{ Property2 = 1 }')
Copy link
Member

@jcouv jcouv Jul 10, 2017

Choose a reason for hiding this comment

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

Nit: I raised this question earlier, but I don't remember if it was answered. Do we know why some indents are 2 spaces, but others are 4? #Resolved

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Some formatting will be fixed by Jinu's PR, but probably not this issue.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Filed #20789 to track the indenting issues.

@mavasani
Copy link
Contributor Author

mavasani commented Jul 10, 2017

I believe @genlu wrote this walker as a checker that runs on any code and verifies no crashes on accessing properties off operation nodes. #Resolved

@mavasani
Copy link
Contributor Author

mavasani commented Jul 11, 2017

@jcouv @cston - addressed your feedback. #Resolved

@cston
Copy link
Member

cston commented Jul 11, 2017

LGTM

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.

LGTM

@mavasani
Copy link
Contributor Author

windows_debug_unit32_prtest failed due to flaky test failure tracked by #14592

@mavasani
Copy link
Contributor Author

@dotnet-bot retest windows_debug_unit32_prtest please

@mavasani
Copy link
Contributor Author

windows_debug_unit64_prtest failed due to flaky test #20370

@mavasani
Copy link
Contributor Author

@dotnet-bot retest windows_debug_unit64_prtest please

@mavasani
Copy link
Contributor Author

@dotnet-bot retest windows_debug_vs-integration_prtest please

@mavasani
Copy link
Contributor Author

@dotnet-bot retest windows_release_vs-integration_prtest please

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.

6 participants