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 support for multiple internal metadata view interfaces defined from multiple assemblies #93

Merged
merged 4 commits into from
Jul 2, 2018

Conversation

AArnott
Copy link
Member

@AArnott AArnott commented May 8, 2018

This fixes our metadata view code gen so that when implementing internal interfaces, we generate a new dynamic assembly each time a request comes in that requires a unique set of skip visiblity check attributes. When a request comes in that coincides with the set of skip check attributes of a dynamic assembly we've already opened, we reuse that one to keep the dynamic assembly count to a minimum.

Fixes #91

This worksaround the CLR limitation that IgnoresAccessChecksToAttribute attributes are only observed once then cached, preventing any later-added attributes from being noticed.

Fixes #91
We generate a new dynamic assembly for each unique set of skip visiblity checks now, which is the minimum we can get away with given the CLR limitations.
@AArnott AArnott self-assigned this May 8, 2018
@AArnott AArnott requested review from javierdlg and ZoeyR May 8, 2018 06:06
@AArnott
Copy link
Member Author

AArnott commented May 8, 2018

CC: @davidwrighton

@codecov-io
Copy link

codecov-io commented May 8, 2018

Codecov Report

Merging #93 into master will decrease coverage by 0.01%.
The diff coverage is 92.85%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master      #93      +/-   ##
==========================================
- Coverage   85.79%   85.78%   -0.02%     
==========================================
  Files          67       67              
  Lines        5598     5613      +15     
  Branches      869      871       +2     
==========================================
+ Hits         4803     4815      +12     
- Misses        558      559       +1     
- Partials      237      239       +2
Impacted Files Coverage Δ
....Composition/Reflection/SkipClrVisibilityChecks.cs 96.22% <100%> (-3.78%) ⬇️
...Composition/Configuration/MetadataViewGenerator.cs 98.26% <89.47%> (-1.74%) ⬇️
...soft.VisualStudio.Composition/ReflectionHelpers.cs 58.39% <0%> (+0.36%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 0fe39dd...b970746. Read the comment docs.

var result = ImmutableHashSet<AssemblyName>.Empty
.Add(typeInfo.Assembly.GetName());

// If this type has a base type defined in another assembly that is also internal

Choose a reason for hiding this comment

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

Did you mean to leave the commented code here?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, since it really feels like it should be here, and I want it to remind me to ask the CLR folks why I don't need visibility into transitive assemblies when I only ask to skip visibility checks for the first assembly.

Copy link
Member

Choose a reason for hiding this comment

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

Because what's happening there is that access checks are only done on the metadata as written. For instance, A derives from B derives from C. As written, A only knows about B, so the access check from A is only to see if it can access B. For access to C, the only access check is that B is allowed to access C. These rules are straightforward as long as no techniques are used to skirt around access checks, but when you do, you can see surprises like this.

Copy link
Member Author

Choose a reason for hiding this comment

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

OK, thanks. If A defines a member that my proxy implements, evidently that doesn't require C's visibility into A. I guess if A defines a member with a Type that is internal to A, at that point C couldn't implement it without an explicit skip visibility check for A. Yes?

// because the CLR will not honor any additions to that set once the first generated type is closed.
// So maintain a dictionary to point at dynamic modules based on the set of skip visiblity check assemblies they were generated with.
var skipVisibilityCheckAssemblies = SkipClrVisibilityChecks.GetSkipVisibilityChecksRequirements(viewType);
if (!TransparentProxyModuleBuilderByVisibilityCheck.TryGetValue(skipVisibilityCheckAssemblies, out ModuleBuilder moduleBuilder))

Choose a reason for hiding this comment

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

If the type is public, do you still need to do this? (i.e when skipVisibilityCheckAssemblies is ImmutableHashSet<AssemblyName>.Empty

Copy link
Member Author

Choose a reason for hiding this comment

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

When the set is empty, we still need a dynamic assembly to generate into. Our lookup dictionary needs an entry for the empty set as well so we don't end up special casing empty sets -- we execute the same code regardless of the size of the set.

@AArnott AArnott added this to the 16.0 milestone Jun 7, 2018
Copy link
Contributor

@ZoeyR ZoeyR left a comment

Choose a reason for hiding this comment

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

Looks good to me. Although I think we should hold off on merging until #99 gets merged.

@AArnott AArnott merged commit abf21ae into master Jul 2, 2018
@AArnott AArnott deleted the dev/andarno/issue91 branch July 2, 2018 19:41
AArnott added a commit that referenced this pull request Jun 7, 2022
Embed PDBs for all local builds

This ensures that if you build a dll and copy it somewhere, then build again, you haven't lost the ability to debug the original dll because it carries the pdb with it wherever it goes.
We do not embed the pdb in the official builds however because the official builds will archive the pdb so it isn't lost, and it would unnecessarily bloat the assembly.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Internal interface metadata view proxy generation fails after first assembly
5 participants