dotnet / linker

389 stars 127 forks source link

Type hierarchy overmarks non-public methods on unannotated base types #2813

Open vitek-karas opened 2 years ago

vitek-karas commented 2 years ago
class SuperBase
{
    private void SuperBasePrivateMethod () { } // Is not preserved
}

class Base : SuperBase
{
    private void BasePrivateMethod () { }  // This doesn't need to be preserved, but it is
}

[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.NonPublicMethods)]
class Derived : Base
{
    private void DerivedPrivateMethod () { }  // This needs to be preserved due to the annotation
}

static Derived _instance;

public static void Test()
{
    _instance = new Derived ();
    Type type = _instance.GetType ();

    type.RequiresNonPublicMethods (); // No warning (correct)
    type.BaseType.RequiresNonPublicMethods ();  // WARNS - IL2072 since non-public annotation doesn't propagate to base types
}

Non-public annotations don't propagate to base types (as is visible in the sample above, where the type.BaseType warns. But type hierarchy marking doesn't consider this for the first level base type and it applies the same annotation as for the derived type which is annotated.

If the annotation is specified on the Derived type it should be applied to base but without non-public annotations.

Note that not marking this method is perfectly safe since the annotations data flow correctly handles this - as seen by the code above producing a warning when trying to access the private method on the base type.

vitek-karas commented 2 years ago

https://github.com/dotnet/linker/pull/2814 has a test for this.