Skip to content

ILC fails to detect and trim some dependency cycles (interface -> attribute -> [DAM] -> type impl -> new()) #112029

@Sergio0694

Description

@Sergio0694

Description

Found a possible miss by ILC when working on microsoft/CsWinRT#1907. This causes IReferenceArray<T> to be kept, which then produces a bunch of IL3050 warnings when I try to publish the Microsoft Store with a preview of CsWinRT from that PR. We can rework IReferenceArray<T> to be more AOT friendly, but this feels also feels like something that ILC should be able to handle.

cc. @MichalStrehovsky @sbomer

Reproduction Steps

using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;

namespace NaotTrimmingDamTest
{
    internal class Program
    {
        static void Main()
        {
            Console.WriteLine(M(new object()));
        }

        [MethodImpl(MethodImplOptions.NoInlining)]
        public static bool M(object obj)
        {
            Type type = obj.GetType();

            return type.IsGenericType && type.GetGenericTypeDefinition() == typeof(IFoo<>);
        }
    }

    [Keep(typeof(ABI.NaotTrimmingDamTest.IFoo<>))]
    internal interface IFoo<T>
    {
    }

    public sealed class KeepAttribute : Attribute
    {
        public KeepAttribute([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] Type type)
        {
        }
    }
}

namespace ABI.NaotTrimmingDamTest
{
    internal sealed class IFoo<T> : global::NaotTrimmingDamTest.IFoo<T>
    {
        public static object Create()
        {
            return new IFoo<T>();
        }
    }
}

Expected behavior

  • All IFoo<T> types should be completely trimmed.
  • I also expect M to be optimized to just return false, basically.
  • KeepAttribute should also be removed.

There is no type that can possibly be instantiated, that implements IFoo<T>.

Actual behavior

Image

Both IFoo<T> types and [Keep] are kept. Not sure if M is being optimized (don't see the codegen from here).

Additional context

I tried changing the Create method to this:

public static object Create()
{
    if (!RuntimeFeature.IsDynamicCodeCompiled)
    {
        throw new NotSupportedException("");
    }

    return new IFoo<T>();
}

Thinking maybe if this just throws on AOT, ILC will see the type never being constructed and will trim. Nope, no changes.

Regression?

No.

Configuration

  • .NET 9.0.102

Metadata

Metadata

Assignees

No one assigned

    Labels

    area-NativeAOT-coreclrin-prThere is an active PR which will close this issue when it is mergedpartner-impactThis issue impacts a partner who needs to be kept updatedtrimming-for-aot`EnableAggressiveTrimming=true` used for running tests with AOT

    Type

    No type

    Projects

    Status

    No status

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions