oleg-st / InlineMethod.Fody

Inline methods in compile time
MIT License
14 stars 2 forks source link

Inline across projects? #6

Closed WalkerCodeRanger closed 3 months ago

WalkerCodeRanger commented 3 months ago

I thought I saw it inline between two separate projects at first, but I now can't get it to happen. For example, I have project A with a method marked [Inline]. Inside of project A I see calls to it get inlined. In project B that depends on project A calls to it do not get inlined even though Fody and InlineMethod.Fody NuGets are both referenced by it.

oleg-st commented 3 months ago

Could you provide the repro solution?

WalkerCodeRanger commented 3 months ago

Using InlineMethod.Fody 0.7.2 and Fody 6.8.1 on .NET 8.

In project A:

using System.Threading;
using InlineMethod;

public static class Example
{
    [Inline]
    public static bool IsCached(in bool cached) => Volatile.Read(in cached);

    public static T? ReadIfCached<T>(in bool cached, in T value)
        // This call is inlined
        => IsCached(in cached) ? value : default;
}

In project B:

public class ExampleTests
{
    private bool cached;

    public void Caller()
    {
        // This call is not inlined
        Example.IsCached(in cached);
    }
}

As noted in the code comments, the call to Example.IsCached from project B is not inlined. One thing I noticed while looking at the IL/disassembly that may be relevant. It looks like project A IL does not have the [Inline] attribute. I'm guessing the attribute is being stripped out by the Fody IL weaving. But that means when project B is compiled, it will not have any idea which methods in project A should be inlined.

I think you may need to split the InlineMethod.Fody project into two assemblies or even two NuGet packages. One that has the attribute and can be referenced by a project and one that has the rewrites and is <PrivateAssets>all</PrivateAssets>.

oleg-st commented 3 months ago

I didn't intend to export the Inline attribute outside of a library that uses InlineMethod, so as not to require users to install Fody and InlineMethod.Fody for using the library.

WalkerCodeRanger commented 3 months ago

That is why I am suggesting that create a new InlineMethod package that contains only the InlineAttribute and the InlineBehavior enum. Then InlineMethod.Fody would reference InlineMethod. That way, those who used a library wouldn't have to install Fody unless they wanted to get the inlining behavior, but a library could still be published with the [Inline] attributes in it.

oleg-st commented 3 months ago

Then InlineMethod will be a public dependency of the library

oleg-st commented 3 months ago

In 0.7.3 added the ability to export an inline attribute and import references from another module during inlining. You can try [Inline(export: true)] in project A and use Fody and InlineMethod.Fody in both projects.

WalkerCodeRanger commented 3 months ago

That API is fine and I have tested 0.7.3 and the basic functionality works.