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

C# 12: Inline array support. #15328

Draft
wants to merge 12 commits into
base: main
Choose a base branch
from

Conversation

michaelnebel
Copy link
Contributor

@michaelnebel michaelnebel commented Jan 15, 2024

In this PR we make support for inline arrays.
The code sample below contains the declaration of the inline array type MyInlineArray, which can contain 10 elements.
Inline arrays are declared using structs decorated with the InlineArray attribute.

[System.Runtime.CompilerServices.InlineArray(10)]
public struct MyInlineArray
{
    private int myInlineArrayElements;
}

public class Program
{
    public static void Main(string[] args)
    {
        var arr = new MyInlineArray();
        for (int i = 0; i < 10; i++)
        {
            arr[i] = i + 1;
        }
    }
}

Microsoft has a short description of the new language feature here and the more detailed feature specification can be seen here.

Whenever a struct is decorated with the InlineArray it is possible to access the array using a (single dimensional index). Roslyn enforces that when a struct is decorated with the InlineArray attribute it is only allowed to contain a single instance field, which is used to determine the element type of the array.
Inline arrays doesn't behave fully ordinary arrays. That is, the above inline array can't be used as int[] array. There only exist implicit conversion Span and ReadOnlySpan and we can't do the same kind of type equivalence and replacement.
To that end, we have decided to introduce a new type kind to denote inline arrays as they don't behave like structs nor arrays. However, accessing the array behaves like accessing an ordinary array and we are using the existing functionality here.
With these design decisions, it turns our that

  • We can easily identify inline arrays and their element type in QL.
  • The dataflow library works out of the box for inline arrays.

@github-actions github-actions bot added the C# label Jan 15, 2024
@michaelnebel michaelnebel force-pushed the csharp/inlinearrays branch 2 times, most recently from 6a62494 to 8734b3b Compare January 16, 2024 10:47
@michaelnebel michaelnebel force-pushed the csharp/inlinearrays branch 2 times, most recently from 1e3ee37 to aa0255c Compare January 16, 2024 14:33
@michaelnebel michaelnebel changed the title C#: Extract structs representing inline arrays as arrays. C# 12: Inline array support. Jan 17, 2024
Copy link
Contributor

@tamasvajk tamasvajk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have you considered implementing InlineArrayType with pure QL changes? One could identify relevant structs by looking at their attributes in QL.

How do we represent inline arrays in MaD rows? Can we use .Element with inline array types?

@michaelnebel
Copy link
Contributor Author

michaelnebel commented Jan 17, 2024

Have you considered implementing InlineArrayType with pure QL changes? One could identify relevant structs by looking at their attributes in QL.

How do we represent inline arrays in MaD rows? Can we use .Element with inline array types?

Yes, I thought about doing that as well, but the nature of an inline array is very different from a struct and it is my impression that the inline array implementation is just a "hack" that is put on structs, so I wanted to keep it separate.
Do you have a strong opinion one way or the other?

I expect that .Element will work as array read and stores are based on ArrayAccess (which we have ensured in the extractor implementation), but I will check. It is my impression that the intention with inline arrays are to mostly do very local performance optimisations and not as such as expose these via an API.

@tamasvajk
Copy link
Contributor

Do you have a strong opinion one way or the other?

I don't have a strong opinion. I tend to avoid DB changes if possible, just because it's cumbersome to add the stats, write downgrade scripts, ... But those are already done in this case, so I don't have a clear preference. At the same time, I think the below could get us pretty far without the added DB structure.

class InlineArrayType extends ValueType {
  Attribute a;
  Field f;
  int length;

  InlineArrayType() {
    a = this.(Attributable).getAnAttribute() and
    a.getType().hasFullyQualifiedName("System.Runtime.CompilerServices", "InlineArrayAttribute") and
    length = a.getArgument(0).getValue().toInt() and
    f = this.getAField()
  }

  Type getElementType() { result = f.getType() }

  ...
}

@michaelnebel
Copy link
Contributor Author

Do you have a strong opinion one way or the other?

I don't have a strong opinion. I tend to avoid DB changes if possible, just because it's cumbersome to add the stats, write downgrade scripts, ... But those are already done in this case, so I don't have a clear preference. At the same time, I think the below could get us pretty far without the added DB structure.

class InlineArrayType extends ValueType {
  Attribute a;
  Field f;
  int length;

  InlineArrayType() {
    a = this.(Attributable).getAnAttribute() and
    a.getType().hasFullyQualifiedName("System.Runtime.CompilerServices", "InlineArrayAttribute") and
    length = a.getArgument(0).getValue().toInt() and
    f = this.getAField()
  }

  Type getElementType() { result = f.getType() }

  ...
}

This is an excellent point for avoiding to add the extra relation. I will try out something like this, but I would prefer that we introduce the new type kind.

@michaelnebel michaelnebel force-pushed the csharp/inlinearrays branch 2 times, most recently from 620b109 to 34df0d4 Compare January 17, 2024 14:06
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 this pull request may close these issues.

None yet

2 participants