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

Interface properties returning inrefs don't work in C#. #10527

Closed
teo-tsirpanis opened this issue Nov 22, 2020 · 0 comments · Fixed by #10542
Closed

Interface properties returning inrefs don't work in C#. #10527

teo-tsirpanis opened this issue Nov 22, 2020 · 0 comments · Fixed by #10542
Assignees
Labels
Milestone

Comments

@teo-tsirpanis
Copy link
Contributor

Consider this simple F# interface:

type I =
    abstract Property: inref<int>

The equivalent C# interface is this:

public interface I {
    ref readonly int Property { get; }
}

The F# snippet's property is compiled to the following IL:

.property instance int32& Property()
{
  .get instance int32& modreq ([System.Runtime]System.Runtime.InteropServices.InAttribute) I::get_Property()
}

And the C#'s is compiled to this:

.property instance int32& modreq ([System.Runtime]System.Runtime.InteropServices.InAttribute) Property()
{
  .custom instance void [System.Runtime]System.Runtime.CompilerServices.IsReadOnlyAttribute::.ctor()
    = (01 00 00 00 )
  .get instance int32& modreq ([System.Runtime]System.Runtime.InteropServices.InAttribute) I2::get_Property()
}

The F#-compiled IL lacks the IsReadOnlyAttribute and the modreq at the property declaration. C# views it as a read-write property. We can't do anything about the latter, but let's try to apply the attribute ourselves (we shouldn't have):

open System.Runtime.CompilerServices

type I =
    [<IsReadOnly>]
    abstract Property: inref<int>

And now let's use this interface from C#:

class Program
{
    static void Test(I i)
    {
        ref readonly var x1 = ref i.Property;
    }
}

If fails with a mysterious [CS0570] 'I.Property' is not supported by the language in the fifth line.


Two things stood out:

  • The compiler did not emit the IsReadOnlyAttribute and the modreq at the interface's property. Both should be automatically added. Looks like the fixes in Emitting IsReadOnlyAttribute on return arguments of type inref<_> #10022 were not covering all cases.
  • What if the IsReadOnlyAttribute does not exist (like in .NET Standard 2.0 or .NET Framework)? Roslyn generates an internal attribute type and emits that when needed. F#'s compiler tries to find it from anywhere within the assembly's references (even from internal attribute types with the same name), and if it doesn't find it, it doesn't emit it at all. Manually defining an IsReadOnlyAttribute type in the same assembly is ignored.

The bug is reproduced with .NET SDK 5.0.100. inrefs in interface methods are properly compiled like C#.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants