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

Add KeptByAttribute to validate an item was kept due to a specific dependency #3096

Merged
merged 8 commits into from
Nov 7, 2022

Conversation

jtschuster
Copy link
Member

As the first part of solving #3078, we need a system to validate that we are marking items for the correct reasons. The tests we have try to ensure that something can only be kept for a certain reason, but that can be hard to ensure it's not being kept for another reason. For example, sometimes we use typeof(TestType) to mark a type, but that also makes it relevant to variant casting, which can cause parts of TestType to be kept for unintended reasons.

This PR creates the KeptByAttribute which accepts a fully qualified string in Cecil format to indicate depenency provider (the thing that is creating the dependency that marks the item with the attribute), as well as a string representing the DependencyKind to specify the "reason" there was a dependency between the two. It also can accept a System.Type, or a System.Type + name of the member to indicate the dependency provider.

I tried using a DependencyKind parameter itself instead of a string, but ran into build issues. Maybe we could look into using DependencyKind directly in the future.

@mrvoorhe
Copy link
Contributor

mrvoorhe commented Nov 1, 2022

I tried using a DependencyKind parameter itself instead of a string, but ran into build issues. Maybe we could look into using DependencyKind directly in the future.

Would including src/linker/Linker/DependencyInfo.cs in the compilation of Mono.Linker.Tests.Cases.Expectations fix the build issue? After looking at the attribute in use during the test in this PR, the string version of the DependencyKind value is confusing to read. It almost reads as a method name given that other attributes follow the pattern of (string type, string methodName)

@jtschuster
Copy link
Member Author

Would including src/linker/Linker/DependencyInfo.cs in the compilation of Mono.Linker.Tests.Cases.Expectations fix the build issue? After looking at the attribute in use during the test in this PR, the string version of the DependencyKind value is confusing to read. It almost reads as a method name given that other attributes follow the pattern of (string type, string methodName)

Unfortunately no, Mono.Linker.Tests.csproj references Mono.Linker.csproj and Mono.Linker.Tests.Cases.Expectations.csproj, so there is duplicate type error with both having DependencyInfo.cs. I agree that having the string version is not ideal, and I would prefer to use DependencyKind, I just wanted to get a simple working version before investing too much time in making the build work.

@vitek-karas
Copy link
Member

It would not be pretty, but we could define the enum in the tests in different namespace. The code would still look identical, just the usings would be different. It's obviously not ideal (duplication), but it would solve this.
There are ways to handle the compiler's confusion about getting the same type from two different assemblies, but it's probably not worth the trouble here.

Copy link
Member

@sbomer sbomer left a comment

Choose a reason for hiding this comment

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

Thank you!

@@ -22,7 +24,9 @@ public virtual void Foo ()
[KeptBaseType (typeof (B))]
class A : B
{
[Kept]
// Bug: https://github.com/dotnet/linker/issues/3078
Copy link
Member

Choose a reason for hiding this comment

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

What's the bug for this one - just that it isn't treated as a direct call? It might be worth a comment.

@@ -89,8 +89,10 @@ public virtual TestCaseLinkerOptions GetLinkerOptions (NPath inputPath)

public virtual void CustomizeLinker (LinkerDriver linker, LinkerCustomizations customizations)
{
if (_testCaseTypeDefinition.CustomAttributes.Any (attr =>
attr.AttributeType.Name == nameof (DependencyRecordedAttribute))) {
if (!_testCaseTypeDefinition.CustomAttributes.Any (a => a.AttributeType.IsTypeOf<SkipKeptItemsValidationAttribute> ())
Copy link
Member

Choose a reason for hiding this comment

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

Why the check for SkipKeptItemsValidation - isn't it ok to not record dependencies if there are only [Kept] attributes for example?

Copy link
Member Author

Choose a reason for hiding this comment

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

Since the SkipKeptItemsValidation is only on the entry point class, and KeptBy attributes can be anywhere in the assembly, I thought it would be easier, less error prone, and not significantly slower to assume we need a tracer if there's any kept item validation rather than checking every node in the program for a KeptByAttribute and then deciding to use a tracer or not.

{
// public KeptByAttribute (string dependencyProvider, DependencyKind reason) { }
// public KeptByAttribute (Type dependencyProvider, DependencyKind reason) { }
// public KeptByAttribute (Type dependencyProvider, string memberName, DependencyKind reason) { }
Copy link
Member

Choose a reason for hiding this comment

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

nit: update these comments to reflect that they take string not DependencyKind now.

@jtschuster jtschuster enabled auto-merge (squash) November 7, 2022 22:34
@jtschuster jtschuster merged commit dc5e60f into dotnet:main Nov 7, 2022
agocke pushed a commit to dotnet/runtime that referenced this pull request Nov 16, 2022
…pendency (dotnet/linker#3096)

The tests we have in the linker try to ensure that something can only be kept for a certain reason, but it can be hard to ensure it's not being kept for another reason. For example, sometimes we use typeof(TestType) to mark a type, but that also makes it relevant to variant casting, which can cause parts of TestType to be kept for unintended reasons.

This PR creates the KeptByAttribute which accepts a fully qualified string in Cecil format to indicate depenency provider (the thing that is creating the dependency that marks the item with the attribute), as well as a string representing the DependencyKind to specify the "reason" there was a dependency between the two. It also can accept a System.Type, or a System.Type + name of the member to indicate the dependency provider.

Commit migrated from dotnet/linker@dc5e60f
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.

4 participants