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

GenAPI needs to account for ref fields #63751

Closed
jaredpar opened this issue Jan 13, 2022 · 10 comments · Fixed by dotnet/arcade#9487
Closed

GenAPI needs to account for ref fields #63751

jaredpar opened this issue Jan 13, 2022 · 10 comments · Fixed by dotnet/arcade#9487

Comments

@jaredpar
Copy link
Member

jaredpar commented Jan 13, 2022

Support for ref fields is being added in .NET 7 / C# 11.0. This will impact reference assembly generation as ref fields impact how C# consumes types that contain them.

Ideally a ref field in a reference assembly would just appear as a normal field of the same type would appear but with the ref modifier. However a ref field represents a change to the metadata format and that can cause issues with tool chains that are not updated to understand this metadata change. A concrete example is C++/CLI which will likely error if it consumes a ref field.

This means it's advantageous if ref fields can be omitted from reference assemblies in our core libraries. That removes an ask on the C++/CLI team in the short term and possibly avoids issues in other toolsets.

The semantics of how we need to describe a ref field in a reference assembly are described in the ref field proposal. In short though when omitting ref we need to be careful to maintain the other properties it conveys:

  • The containing type can never be considered unmanaged
  • The type of the field, sans ref, is still important for generic expansion calculations

A method for achieving that is as follows:

// Impl assembly 
ref struct S<T> {
    ref T _field;
}

// Ref assembly 
ref struct S<T> {
    object _o; // force managed 
    T _f; // maintain generic expansion protections
}
@dotnet-issue-labeler dotnet-issue-labeler bot added area-System.Reflection untriaged New issue has not been triaged by the area owner labels Jan 13, 2022
@ghost
Copy link

ghost commented Jan 13, 2022

Tagging subscribers to this area: @dotnet/area-system-reflection
See info in area-owners.md if you want to be subscribed.

Issue Details

Support for ref fields is being added in .NET 7 / C# 11.0. This will impact reference assembly generation as ref fields impact how C# consumes types that contain them.

Ideally a ref field in a reference assembly would just appear as a normal field of the same type would appear but with the ref modifier. However a ref field represents a change to the metadata format and that can cause issues with tool chains that are not updated to understand this metadata change. A concrete example is C++/CLI which will likely error if it consumes a ref field.

This means it's advantageous if ref fields can be omitted from reference assemblies in our core libraries. That removes an ask on the C++/CLI team in the short term and possibly avoids issues in other toolsets.

The semantics of how we need to describe a ref field in a reference assembly are described in the ref field proposal. In short though when omitting ref we need to be careful to maintain the other properties it conveys:

  • The containing type can never be considered unmanaged
  • The type of the field, sans ref, is still important for generic expansion calculations

A method for achieving that is as follows:

// Impl assembly 
ref struct S<T> {
    ref T _field;
}

// Ref assembly 
ref struct S<T> {
    object _o; // force unmanaged 
    T _f; // maintain generic expansion protections
}
Author: jaredpar
Assignees: -
Labels:

area-System.Reflection, untriaged

Milestone: -

@AaronRobinsonMSFT AaronRobinsonMSFT added this to the 7.0.0 milestone Jan 13, 2022
@AaronRobinsonMSFT
Copy link
Member

@jkoritzinsky and @elinor-fung We should make sure the DllImport source generator is updated to understand this.

@jkoritzinsky
Copy link
Member

jkoritzinsky commented Jan 13, 2022

I already pre-confirmed with @jaredpar that Roslyn will treat structs with ref fields as "not unmanaged", so as long as GenAPI produces accurate ref assemblies, DllImportGenerator will be fine. (Once we make the switch to unmanaged==blittable)

@ghost
Copy link

ghost commented Jan 13, 2022

Tagging subscribers to this area: @dotnet/area-infrastructure-libraries
See info in area-owners.md if you want to be subscribed.

Issue Details

Support for ref fields is being added in .NET 7 / C# 11.0. This will impact reference assembly generation as ref fields impact how C# consumes types that contain them.

Ideally a ref field in a reference assembly would just appear as a normal field of the same type would appear but with the ref modifier. However a ref field represents a change to the metadata format and that can cause issues with tool chains that are not updated to understand this metadata change. A concrete example is C++/CLI which will likely error if it consumes a ref field.

This means it's advantageous if ref fields can be omitted from reference assemblies in our core libraries. That removes an ask on the C++/CLI team in the short term and possibly avoids issues in other toolsets.

The semantics of how we need to describe a ref field in a reference assembly are described in the ref field proposal. In short though when omitting ref we need to be careful to maintain the other properties it conveys:

  • The containing type can never be considered unmanaged
  • The type of the field, sans ref, is still important for generic expansion calculations

A method for achieving that is as follows:

// Impl assembly 
ref struct S<T> {
    ref T _field;
}

// Ref assembly 
ref struct S<T> {
    object _o; // force unmanaged 
    T _f; // maintain generic expansion protections
}
Author: jaredpar
Assignees: -
Labels:

area-Infrastructure-libraries, untriaged

Milestone: 7.0.0

@safern
Copy link
Member

safern commented Jan 13, 2022

FYI: @ericstj @carlossanlop

@safern safern removed the untriaged New issue has not been triaged by the area owner label Jan 13, 2022
@ericstj
Copy link
Member

ericstj commented Jan 13, 2022

We use reference assemblies for inbox libraries, but not for our packages. This would mean that the use of ref fields in packages would still have this problem since they would expose the implementation assemblies. Those are even more likely to be used on older compiler toolchains.

Additionally ASP.NET and WinForms do not use GenAPI to produce their reference assemblies. They use /refout. Does /refout perform this transformation?

I suppose this transformation is only needed for any public structs that intend to have ref fields (public or private I would imagine). Are we aware of any structs that are planning to do this?

From a compatibility perspective, I suppose it might be breaking to add a ref field to an existing struct since it would prevent it from being unmanaged, but I suppose that can happen today and we likely don't have an API compat rule for it.

@jaredpar
Copy link
Member Author

I suppose this transformation is only needed for any public structs that intend to have ref fields (public or private I would imagine). Are we aware of any structs that are planning to do this?

A number of types are likely: Span<T>, TypedReference, etc ... Essentially any ref struct that is using ByReference<T> today will be converted to a ref field.

They use /refout. Does /refout perform this transformation?

Undecided but most likely the C# compiler will expose it directly as a ref field. The biggest motivation for not doing ref is avoiding toolchains critical to shipping that may not accept it. As far as I understand that doesn't intersect with /refout.

@ericstj
Copy link
Member

ericstj commented Jan 14, 2022

I see. Your examples seem to be cases where the ref field was private/internal. I don't suppose we'd want to transform a public ref field. Presumably we won't have any of those?

@ericstj
Copy link
Member

ericstj commented Jan 14, 2022

@jaredpar
Copy link
Member Author

I see. Your examples seem to be cases where the ref field was private/internal. I don't suppose we'd want to transform a public ref field.

Correct

Presumably we won't have any of those?

There aren't any instances of ref fields in the BCL that are expected to be public that I am aware of.

@ghost ghost locked as resolved and limited conversation to collaborators Jul 3, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants