Refresh System.Runtime ref from System.Private.CoreLib in Coreclr#26264
Conversation
This also includes an update to the genapi tool that includes the necessary private fields in structs to enable the compiler to do correctness checks. See https://github.com/dotnet/corefx/issues/6185.
| [System.Runtime.CompilerServices.AsyncMethodBuilderAttribute(typeof(System.Runtime.CompilerServices.AsyncValueTaskMethodBuilder<>))] | ||
| public readonly partial struct ValueTask<TResult> : System.IEquatable<System.Threading.Tasks.ValueTask<TResult>> | ||
| { | ||
| internal readonly TResult _result; |
There was a problem hiding this comment.
Should all the fields be private?
There was a problem hiding this comment.
I noticed a couple of these as well, I don't know why they showed up as internal but I will investigate.
There was a problem hiding this comment.
The reason this and a couple others are internal instead of private is because for any non-public fields that are generic I just blindly include those unchanged. For now I will keep them like this so they correctly show the usage of generic parameters. If you feel there is a reason to switch them I can.
There was a problem hiding this comment.
Same in Nullable<T> - internal T value . I think that is ok.
In reply to: 161028771 [](ancestors = 161028771)
| public virtual bool IsAsync { get { throw null; } } | ||
| public override long Length { get { throw null; } } | ||
| public string Name { get { throw null; } } | ||
| public virtual string Name { get { throw null; } } |
There was a problem hiding this comment.
There is a bunch of unrelated changes like this one. Are they all intentional?
There was a problem hiding this comment.
Yes these are intentional. They are essentially refreshing based on what is in System.Private.CoreLib implementation. A number of changes to the API never made it to the ref.
| public static System.ReadOnlySpan<T> DangerousCreate(object obj, ref T objectData, int length) { throw null; } | ||
| [System.ComponentModel.EditorBrowsableAttribute((System.ComponentModel.EditorBrowsableState)(1))] | ||
| [System.ObsoleteAttribute("Equals() on ReadOnlySpan will always throw an exception. Use == instead.")] | ||
| [System.ObsoleteAttribute("Equals() on Span will always throw an exception. Use == instead.")] |
There was a problem hiding this comment.
The original message looks right. This looks like a bug in the implementation.
There was a problem hiding this comment.
This just updated to what is in the implementation. We could definitely update both to be consistent with ReadOnlySpan.
| } | ||
| public partial struct GCHandle | ||
| { | ||
| private object _dummy; |
There was a problem hiding this comment.
I think this should be int. GCHandle does not have instance object fields.
There was a problem hiding this comment.
this might be a side-effect of me not filtering out statics while doing the contains reference check. I will regenerate once I update the tool.
There was a problem hiding this comment.
@jkotas the GCHandle holds a IntPtr which in turn holds a void* so based on our logic I would expect this to have an object dummy field. Is there something I'm missing?
There was a problem hiding this comment.
void* should be treated as int, not as object.
There was a problem hiding this comment.
OK with that change we get a bunch of updates. Can you have a look over 9288c49 to ensure they look as expected?
| } | ||
| public partial struct Boolean : System.IComparable, System.IComparable<bool>, System.IConvertible, System.IEquatable<bool> | ||
| { | ||
| private object _dummy; |
There was a problem hiding this comment.
Why Boolean contains an object field?
The real one only contains a bool. #Closed
There was a problem hiding this comment.
Just pushed a change that fixes this. #Closed
| } | ||
| public partial struct Char : System.IComparable, System.IComparable<char>, System.IConvertible, System.IEquatable<char> | ||
| { | ||
| private object _dummy; |
There was a problem hiding this comment.
Same as Boolean - why object? #Closed
There was a problem hiding this comment.
Was an issue in detecting a reference type, just fixed. #Closed
| } | ||
| public partial struct IntPtr : System.IEquatable<System.IntPtr>, System.Runtime.Serialization.ISerializable | ||
| { | ||
| private object _dummy; |
There was a problem hiding this comment.
Should be int or IntPtr. #Closed
| [System.CLSCompliantAttribute(false)] | ||
| public partial struct UIntPtr : System.IEquatable<System.UIntPtr>, System.Runtime.Serialization.ISerializable | ||
| { | ||
| private object _dummy; |
There was a problem hiding this comment.
should be int or UIntPtr #Closed
| public override bool Equals(object obj) { throw null; } | ||
| public bool Equals(System.RuntimeTypeHandle handle) { throw null; } | ||
| public override int GetHashCode() { throw null; } | ||
| [System.CLSCompliantAttribute(false)] |
There was a problem hiding this comment.
You can delete this unnecessary CLSCompliantAttribute attribute. I have deleted it in the implementation already.
| { | ||
| public readonly partial struct CancellationToken | ||
| { | ||
| private readonly object _dummy; |
There was a problem hiding this comment.
👍 This one was causing particularly annoying bug reports.
|
…f Span Remove unnecessary CLSCompliant(false) on GetModuleHandle
925866d to
c58e40f
Compare
| } | ||
| public readonly ref partial struct Span<T> | ||
| { | ||
| private readonly int _dummy; |
There was a problem hiding this comment.
I think .NET implementation contains an object. And even the fast implementation technically may contain an object reference.
We do not consider any generic struct as unmanaged right now, regardless of fields, but might in the future.
I think Span/ReadOnlySpan should be considered object-containing
There was a problem hiding this comment.
I think Span/ReadOnlySpan should be considered object-containing
I agree. It is not something that the tool can figure out from CoreLib metadata because of Span is treated as intrinsic by the runtime. Types like these will need exceptions.
BTW: It is a bit odd that the primitive types like Int64 has 32-bit fields now. I won't be surprised if we find that it broke something somewhere and we need similar exceptions for them.
There was a problem hiding this comment.
On the other hand - even if we see all the fields we would consider fast span unmanaged. (since we do not see or understand the hidden byref)
And other ones - like TypedReference were always considered unmanaged.
I guess the object inside the slow spans would be the only reason to make the spans managed. - Just to conservatively match the implementations.
In reply to: 161045136 [](ancestors = 161045136)
There was a problem hiding this comment.
Yeah - I had that concern about primitives as well. Maybe it would be safer if they are self-containing, like all their implementations?
In reply to: 161048209 [](ancestors = 161048209)
There was a problem hiding this comment.
I.E. - intcontains an int dummy, bool contains a bool, and so on ...
In reply to: 161049185 [](ancestors = 161049185,161048209)
There was a problem hiding this comment.
And other ones - like TypedReference were always considered unmanaged.
While it actually contains managed references because of it is treated as intrinsic by the runtime...
This highlights that this has number of false positives and false negatives.
Would it make sense to relax C# to let you take pointer of anything, and demote the current error for taking pointer of "managed type" to just a warning?
There was a problem hiding this comment.
Possibly. I do not know the exact rationale for not allowing pointers to managed structs. It was the case since v1.0
Perhaps to reduce chances of heap corruption when one dereferences garbage...
In reply to: 161052501 [](ancestors = 161052501)
There was a problem hiding this comment.
Latest update fixes primitive types to have matching field types and manually marks Span and ReadOnlySpan as having an object type.
There was a problem hiding this comment.
Are there any other special types we need to manually fix?
There was a problem hiding this comment.
I think this is all that is needed.
The old-style ref-likes like TypedReference should stay as they are. At least for compat reasons.
In reply to: 161073853 [](ancestors = 161073853)
It was replaced by Once the pattern-based fixed statement in C# is figured out, we will add it back in the right form: |
|
Re: |
| public bool TryCopyTo(System.Span<T> destination) { throw null; } | ||
| public ref partial struct Enumerator | ||
| { | ||
| private int _dummy; |
There was a problem hiding this comment.
The Enumerator struct contains Span field. It should be treated same way as Span and have object field.
This applies to all structs with Span fields.
There was a problem hiding this comment.
I should probably update the tool to special case Span and ReadOnlySpan.
There was a problem hiding this comment.
Perhaps it is easier to hack the tool so that it thinks Span/ReadonlySpan actually contain an extra private object _dummy ?
There was a problem hiding this comment.
I'm going to teach the tool to recognize "ByReference" as hold a reference.
There was a problem hiding this comment.
That could add an object into TypedReference.
It is technically breaking. TypedReference* It is a very corner case and maybe fragile/broken anyways, so I am not sure how much we care.
There was a problem hiding this comment.
The rule dotnet/buildtools@4b80362 produced the expected output
6ef9545.
TypedReference didn't change because it only contains an IntPtr not a ByReference.
| public bool TryCopyTo(System.Span<T> destination) { throw null; } | ||
| public ref partial struct Enumerator | ||
| { | ||
| private int _dummy; |
|
test Linux x64 Release Build |
| } | ||
| public readonly ref partial struct ReadOnlySpan<T> | ||
| { | ||
| private readonly object _dummy; //Manually set to object because tools don't know it is special |
There was a problem hiding this comment.
object , there are no fields of type T in Span.
There was a problem hiding this comment.
It is similar to the ImmutableArray<T> - T is the element type, but the struct is just an indirection to some other storage, it does not contain any instances directly.
There was a problem hiding this comment.
I have the changed for ImmutableArray locally and my tool generates internal T[] array; for it as it is generic underneath.
There was a problem hiding this comment.
Either T[] or object would work since T[] is not T and is not a struct that contains instance field of type T .
There was a problem hiding this comment.
Basically arrays are just reference types for this purpose.
This make Span and ReadOnlySpan have a reference and thus generates a private object field for the compiler to do the correct checks.
ece948d to
6ef9545
Compare
…ntimeFromCoreCLR Refresh System.Runtime ref from System.Private.CoreLib in Coreclr Commit migrated from dotnet/corefx@c84ed43
This also includes an update to the genapi tool that includes the
necessary private fields in structs to enable the compiler to
do correctness checks.
See https://github.com/dotnet/corefx/issues/6185.
The ref was generated with the updated changes in dotnet/buildtools#1859.
PTAL @jkotas @VSadov @jaredpar @gafter
Note that some of the updates are just a refresh from what is in the System.Private.CoreLib and not about the fields in structs.