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 crash when compiling internal attribute constructor #42192

Merged
merged 3 commits into from
Mar 16, 2020

Conversation

khyperia
Copy link
Contributor

@khyperia khyperia commented Mar 5, 2020

Fixes #38444

Updated version of #38873, with a different fix (that I think is more correct - this code pattern matches the one for struct fields). Still though, I'm not 100% sure this is the right fix, feedback would be appreciated if not!

@khyperia khyperia requested a review from a team as a code owner March 5, 2020 10:44
foreach (var method in this.GetMethodsToEmit())
{
Debug.Assert((object)method != null);
if (method.ShouldInclude(context))
if (isAttribute || method.ShouldInclude(context))
Copy link
Contributor

Choose a reason for hiding this comment

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

isAttribute [](start = 20, length = 11)

It feels unfortunate that we are going to include all attribute constructors unconditionally. Also, I am curious what other scenarios we are missing when a declaration that isn't included by default is referenced by some other API that is included. However, building a NoPia-like tracking feels like an overkill just to get the attributes case working.

foreach (var method in this.GetMethodsToEmit())
{
Debug.Assert((object)method != null);
if (method.ShouldInclude(context))
if (isAttribute || method.ShouldInclude(context))
Copy link
Contributor

@AlekseyTs AlekseyTs Mar 5, 2020

Choose a reason for hiding this comment

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

isAttribute [](start = 20, length = 11)

isAttribute [](start = 20, length = 11)

It looks like we are including all methods, not just instance constructors #Closed

using System;
internal class SomeAttribute : Attribute
{
internal SomeAttribute()
Copy link
Contributor

@AlekseyTs AlekseyTs Mar 5, 2020

Choose a reason for hiding this comment

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

internal SomeAttribute() [](start = 4, length = 24)

Please add a regular internal method and verify that it is not emitted. #Closed

@AlekseyTs
Copy link
Contributor

AlekseyTs commented Mar 5, 2020

Done with review pass (iteration 1) #Closed

@@ -661,10 +661,13 @@ IEnumerable<Cci.IMethodDefinition> Cci.ITypeDefinition.GetMethods(EmitContext co
{
CheckDefinitionInvariant();

// All constructors in attributes should be emitted
bool isAttribute = DeclaringCompilation.IsAttributeType(this);
Copy link
Contributor

@AlekseyTs AlekseyTs Mar 5, 2020

Choose a reason for hiding this comment

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

bool isAttribute = DeclaringCompilation.IsAttributeType(this); [](start = 11, length = 63)

We probably should avoid calculating this when nothing is going to be filtered out anyway. #Closed

Copy link
Contributor Author

Choose a reason for hiding this comment

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

What's the best code pattern to do something like this? I feel like Lazy with a lambda is too heavyweight, and a bool hasComputedIsAttribute; bool isAttribute; is kind of gross (so I want confirmation before doing that). (Or did you mean something else by that? Not computing if context.IncludePrivateMembers is true or something like that?)

Copy link
Contributor

Choose a reason for hiding this comment

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

Or did you mean something else by that? Not computing if context.IncludePrivateMembers is true or something like that?)

Yes, something like that. Do not calculate if ShouldInclude doesn't filter anything out.


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

Copy link
Contributor

Choose a reason for hiding this comment

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

I would also rename the local to something like alwaysIncludeConstructors it will cause less confusion once its value is conditionally calculated. The type doesn't stop to be an attribute no matter what ShouldInclude does.


In reply to: 389016262 [](ancestors = 389016262,388878100)

@khyperia khyperia force-pushed the internal-attribute-refout branch from 6a02ba9 to 0a812dc Compare March 6, 2020 12:31
@AlekseyTs
Copy link
Contributor

AlekseyTs commented Mar 6, 2020

@khyperia Please do not rewrite commits that undergo review process. Do not force push into the PR branches until review process is complete. This prevents people from doing incremental review and often messes up comment tracking. Simply make necessary changes in new commits and push. Commits can easily be squashed on merge, or you can rebase right before merging. Thanks. #Closed

@@ -676,7 +679,7 @@ IEnumerable<Cci.IMethodDefinition> Cci.ITypeDefinition.GetMethods(EmitContext co
{
foreach (var m in generated)
{
if (m.ShouldInclude(context))
if ((isAttribute && m.IsConstructor) || m.ShouldInclude(context))
Copy link
Contributor

@AlekseyTs AlekseyTs Mar 6, 2020

Choose a reason for hiding this comment

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

IsConstructor [](start = 42, length = 13)

Can we use the same way to perform the constructor check here and above? #Closed

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Surprisingly, no - in the "normal" (not generated) method case, method is a MethodSymbol, but in the generated method case, m is a Cci.IMethodDefinition. It doesn't seem like there's a common API between them to check if it's a constructor.

@khyperia
Copy link
Contributor Author

khyperia commented Mar 6, 2020

Please do not rewrite commits that undergo review process

Sorry about that, different projects have different github practices, I forgot what Roslyn used 😢

{
}

internal void F()
Copy link
Contributor

@AlekseyTs AlekseyTs Mar 6, 2020

Choose a reason for hiding this comment

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

internal void F() [](start = 4, length = 17)

Please also add a test with a static constructor. #Closed

Copy link
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 (iteration 2)

@AlekseyTs
Copy link
Contributor

@jcouv, @dotnet/roslyn-compiler For the second sign-off.

Copy link
Member

@agocke agocke left a comment

Choose a reason for hiding this comment

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

LGTM, thanks!

@AlekseyTs
Copy link
Contributor

@jcouv Could you please take a look at this PR. Are you Ok with the impact for the feature?

@AlekseyTs AlekseyTs requested a review from jcouv March 11, 2020 20:59
@jaredpar jaredpar added the Community The pull request was submitted by a contributor who is not a Microsoft employee. label Mar 13, 2020
@jcouv
Copy link
Member

jcouv commented Mar 13, 2020

Sorry, I'd missed the ping. I'll take a look today.

@jcouv jcouv self-assigned this Mar 13, 2020
@jcouv
Copy link
Member

jcouv commented Mar 13, 2020

Are you Ok with the impact for the feature?

Yes, it's okay.

@khyperia Thanks for the fix. Could you also update the refout doc as part of this PR to document the additional rule? https://github.com/dotnet/roslyn/blob/master/docs/features/refout.md

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 Thanks (iteration 2) modulo updating the refout doc.

@AlekseyTs
Copy link
Contributor

@khyperia Once you update the doc, would you mind if we squash commits during the merge?

@khyperia
Copy link
Contributor Author

@AlekseyTs Please do!

@AlekseyTs
Copy link
Contributor

@jcouv If changes to the doc are fine, could you please merge this PR using "Squash and merge" mode?

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 Thanks (iteration 3). Will wait for green CI and will merge/squash.

@jcouv jcouv merged commit 2b86338 into dotnet:master Mar 16, 2020
@ghost ghost added this to the Next milestone Mar 16, 2020
@jcouv
Copy link
Member

jcouv commented Mar 16, 2020

Thanks @khyperia! I hope you're doing well :-)

@khyperia khyperia deleted the internal-attribute-refout branch March 16, 2020 20:25
@sharwell sharwell modified the milestones: Next, 16.6.P2 Mar 17, 2020
khyperia added a commit to Unity-Technologies/roslyn that referenced this pull request Mar 23, 2020
* Fix crash when compiling internal attribute constructor

* PR feedback

* Add new rule to refout.md
khyperia added a commit to Unity-Technologies/roslyn that referenced this pull request Mar 24, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area-Compilers Community The pull request was submitted by a contributor who is not a Microsoft employee.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Using /refout causes "FATAL UNHANDLED EXCEPTION: System.Collections.Generic.KeyNotFoundException"
6 participants