Skip to content

Include [UnscopedRef] parameter attributes in synthesized delegate types#66035

Merged
cston merged 7 commits intodotnet:release/dev17.5from
cston:63565
Jan 6, 2023
Merged

Include [UnscopedRef] parameter attributes in synthesized delegate types#66035
cston merged 7 commits intodotnet:release/dev17.5from
cston:63565

Conversation

@cston
Copy link
Copy Markdown
Contributor

@cston cston commented Dec 16, 2022

Fixes #63565

VSO bug #1715794

@ghost ghost added the Area-Compilers label Dec 16, 2022
@cston cston force-pushed the 63565 branch 3 times, most recently from 33e6860 to 1a661f6 Compare December 16, 2022 22:30
@cston cston marked this pull request as ready for review December 16, 2022 22:30
@cston cston requested a review from a team as a code owner December 16, 2022 22:30
internal sealed override DeclarationScope EffectiveScope => _scope;

internal sealed override bool HasUnscopedRefAttribute => false;
internal abstract override bool HasUnscopedRefAttribute { get; }
Copy link
Copy Markdown
Member

@jjonescz jjonescz Dec 19, 2022

Choose a reason for hiding this comment

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

internal abstract override bool HasUnscopedRefAttribute { get; }

Why not remove this property instead? It's inherited exactly as written from ParameterSymbol. #Closed

case WellKnownMember.System_Runtime_CompilerServices_AsyncStateMachineAttribute__ctor:
case WellKnownMember.System_Runtime_CompilerServices_IteratorStateMachineAttribute__ctor:
case WellKnownMember.System_Runtime_CompilerServices_AsyncIteratorStateMachineAttribute__ctor:
case WellKnownMember.System_Diagnostics_CodeAnalysis_UnscopedRefAttribute__ctor:
Copy link
Copy Markdown
Contributor

@AlekseyTs AlekseyTs Dec 19, 2022

Choose a reason for hiding this comment

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

WellKnownMember.System_Diagnostics_CodeAnalysis_UnscopedRefAttribute__ctor

I am curious what scenarios does this enable. Is presence of the attribute not important for consumers? #Closed

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.

It looks like we are not testing effect of this change. Also, I think that, unless we have a compelling scenario that we would like to enable, it might be better to detect the lack of the API and report an error instead of silently dropping the attribute. We already do this for default value and param array synthesized attributes.

{
if (field.HasUnscopedRefAttribute)
{
return false;
Copy link
Copy Markdown
Member

@jjonescz jjonescz Dec 19, 2022

Choose a reason for hiding this comment

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

return false;

Have we considered synthesizing generic templates similarly to what we did with default parameter values recently? For example, synthesizing delegate like delegate void <>f__AnonymousDelegate0<T>([UnscopedRef] ref T x). #Closed

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

[UnscopedRef] parameters should be uncommon, so perhaps we should hold off making that change for now.

AddSynthesizedAttribute(ref attributes, compilation.TrySynthesizeAttribute(WellKnownMember.System_ParamArrayAttribute__ctor));
}

if (this.HasUnscopedRefAttribute && this.ContainingSymbol is SynthesizedDelegateInvokeMethod)
Copy link
Copy Markdown
Contributor

@AlekseyTs AlekseyTs Dec 19, 2022

Choose a reason for hiding this comment

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

this.ContainingSymbol is SynthesizedDelegateInvokeMetho

Consider unifying this check with the previous if #Closed

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Left as is for now, but switched the order of the two if statements to avoid a conflict with the main branch.


[Fact]
[WorkItem(63565, "https://github.com/dotnet/roslyn/issues/63565")]
public void SynthesizedDelegateTypes_UnscopedRefAttribute_01()
Copy link
Copy Markdown
Contributor

@AlekseyTs AlekseyTs Dec 19, 2022

Choose a reason for hiding this comment

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

SynthesizedDelegateTypes_UnscopedRefAttribute_01

It feels like we should verify that the attribute is present on the delegate parameter. #Closed

@AlekseyTs
Copy link
Copy Markdown
Contributor

Done with review pass (commit 1)

@cston cston changed the base branch from main to release/dev17.5 January 4, 2023 18:46
{
Binder.AddUseSiteDiagnosticForSynthesizedAttribute(
Compilation,
checkWellKnownMemberAvailable(
Copy link
Copy Markdown
Member

@jjonescz jjonescz Jan 5, 2023

Choose a reason for hiding this comment

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

checkWellKnownMemberAvailable

Why not use the Binder.AddUseSiteDiagnosticForSynthesizedAttribute method? #Closed

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Updated, thanks. (I'm not sure why I'd overlooked AddUseSiteDiagnosticForSynthesizedAttribute previously.)

<>f__AnonymousDelegate0
<>F{00000015}`3[System.Int32,System.Int32,System.Int32]
""");
verifier.VerifyTypeIL("<>f__AnonymousDelegate1",
Copy link
Copy Markdown
Contributor

@AlekseyTs AlekseyTs Jan 5, 2023

Choose a reason for hiding this comment

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

f__AnonymousDelegate1

Is f__AnonymousDelegate0 not interesting? #Closed

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

f__AnonymousDelegate0 is inferred from a method group without [UnscopedRef].

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.

It looks like we are using the attribute on different parameters (first and the second)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Sorry, I'd overlooked the differently named delegate type before <>f__AnonymousDelegate0. Added <>f__AnonymousDelegate0.

comp = CreateCompilation(sourceB, references: new[] { refA }, targetFramework: TargetFramework.Net60);
comp.VerifyEmitDiagnostics(
// (6,17): error CS0656: Missing compiler required member 'System.Diagnostics.CodeAnalysis.UnscopedRefAttribute..ctor'
// var d = A.F;
Copy link
Copy Markdown
Contributor

@AlekseyTs AlekseyTs Jan 5, 2023

Choose a reason for hiding this comment

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

var d = A.F;

Are we testing this scenario for a lambda? Note, it is possible to get in a situation when user is able to apply the attribute in source successfully, but compiler fails to locate the type. We should test this scenario as well (MakeMemberMissing should help) #Closed


comp = CreateCompilation(sourceB, references: new[] { refA }, targetFramework: TargetFramework.Net60);
comp.VerifyEmitDiagnostics(
// (6,17): error CS0656: Missing compiler required member 'System.Diagnostics.CodeAnalysis.UnscopedRefAttribute..ctor'
Copy link
Copy Markdown
Contributor

@AlekseyTs AlekseyTs Jan 5, 2023

Choose a reason for hiding this comment

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

System.Diagnostics.CodeAnalysis.UnscopedRefAttribute..ctor

It doesn't look like we are testing scenario when type is present, but constructor is missing. MakeMemberMissing should help. #Closed

var d1 = F1;
var d2 = F2;
var d3 = F3;
var d4 = ([UnscopedRef] ref int x, ref int y) => ref x;
Copy link
Copy Markdown
Contributor

@AlekseyTs AlekseyTs Jan 5, 2023

Choose a reason for hiding this comment

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

([UnscopedRef] ref int x, ref int y) => ref x;

It might be good to separate method group scenarios and lambda scenarios, to make sure they are properly handled on their own. #Closed

@AlekseyTs
Copy link
Copy Markdown
Contributor

Done with review pass (commit 6)

Copy link
Copy Markdown
Contributor

@AlekseyTs AlekseyTs left a comment

Choose a reason for hiding this comment

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

LGTM (commit 7)

@cston
Copy link
Copy Markdown
Contributor Author

cston commented Jan 6, 2023

/azp run

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 2 pipeline(s).

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.

Implicitly typed lambdas with [UnscopedRef] don't match their own anonymous delegate types

3 participants