dotnet / runtime

.NET is a cross-platform runtime for cloud, mobile, desktop, and IoT apps.
https://docs.microsoft.com/dotnet/core/
MIT License
14.97k stars 4.66k forks source link

Incorrect trim analysis warning for base method implementing interface #97676

Closed sbomer closed 2 months ago

sbomer commented 7 months ago

When a type provides an interface implementation via a base method, there can be new unexpected trim analysis warnings pointing to the base method. For example:

interface I {
    void M();
}

class Base {
    [RequiresUnreferencedCode("Message")]
    public void M() { }
}

This code is fine on its own, and produces no trim analysis warnings. Now if another piece of code has:

class Derived : Base, I {}

this causes a new warning to appear at Base.M:

interface I {
    void M();
}

class Base {
    [RequiresUnreferencedCode("Message")]
    public void M() { } // warning IL2046: Member 'Base.M()' with 'RequiresUnreferencedCodeAttribute' implements interface member 'I.M()' without 'RequiresUnreferencedCodeAttribute'. 'RequiresUnreferencedCodeAttribute' annotations must match across all interface implementations or overrides.
}

In general, the derived class could be defined in another assembly, leading to trim warnings that "blame" a correctly annotated assembly. The warning should instead point to Derived, similar to what happens if there's a mismatch in the base/interface signatures:

interface I {
    void M();
}

class Base {
    public int M() { }
}

class Derived : Base, I { } // error CS0738: 'Derived' does not implement interface member 'I.M()'. 'Base.M()' cannot implement 'I.M()' because it does not have the matching return type of 'void'.

ILLink, NativeAot, and the ILLink Roslyn analyzer all share the problematic behavior.

ghost commented 7 months ago

Tagging subscribers to this area: @agocke, @MichalStrehovsky, @jkotas See info in area-owners.md if you want to be subscribed.

Issue Details
When a type provides an interface implementation via a base method, there can be new unexpected trim analysis warnings pointing to the base method. For example: ```csharp interface I { void M(); } class Base { [RequiresUnreferencedCode("Message")] public void M() { } } ``` This code is fine on its own, and produces no trim analysis warnings. Now if another piece of code has: ```csharp class Derived : Base, I {} ``` this causes a new warning to appear at Base.M: ```csharp interface I { void M(); } class Base { [RequiresUnreferencedCode("Message")] public void M() { } // warning IL2046: Member 'Base.M()' with 'RequiresUnreferencedCodeAttribute' implements interface member 'I.M()' without 'RequiresUnreferencedCodeAttribute'. 'RequiresUnreferencedCodeAttribute' annotations must match across all interface implementations or overrides. } ``` In general, the derived class could be defined in another assembly, leading to trim warnings that "blame" a correctly annotated assembly. The warning should instead point to `Derived`, similar to what happens if there's a mismatch in the base/interface signatures: ```csharp interface I { void M(); } class Base { public int M() { } } class Derived : Base, I { } // error CS0738: 'Derived' does not implement interface member 'I.M()'. 'Base.M()' cannot implement 'I.M()' because it does not have the matching return type of 'void'. ``` ILLink, NativeAot, and the ILLink Roslyn analyzer all share the problematic behavior.
Author: sbomer
Assignees: -
Labels: `area-TypeSystem-coreclr`, `untriaged`, `area-NativeAOT-coreclr`, `area-Tools-ILLink`
Milestone: -