dotnet / arcade

Tools that provide common build infrastructure for multiple .NET Foundation projects.
MIT License
671 stars 347 forks source link

GenAPI doesn't handle named tuples correctly #8792

Open jozkee opened 2 years ago

jozkee commented 2 years ago

Repro steps:

cd ./src/libraries/System.Security.Cryptography.Cose/src
dotnet msbuild /t:GenerateReferenceAssemblySource

Result: ref file ends up with errors:

namespace System.Security.Cryptography.Cose
{
    public readonly partial struct CoseHeaderLabel : System.IEquatable<System.Security.Cryptography.Cose.CoseHeaderLabel>
    {
+        private readonly object _dummy;
+        private readonly int _dummyPrimitive;
        public CoseHeaderLabel(int label) { throw null; }
        public CoseHeaderLabel(string label) { throw null; }
        public static System.Security.Cryptography.Cose.CoseHeaderLabel Algorithm { get { throw null; } }
        public static System.Security.Cryptography.Cose.CoseHeaderLabel ContentType { get { throw null; } }
        public static System.Security.Cryptography.Cose.CoseHeaderLabel CounterSignature { get { throw null; } }
        public static System.Security.Cryptography.Cose.CoseHeaderLabel Critical { get { throw null; } }
        public static System.Security.Cryptography.Cose.CoseHeaderLabel IV { get { throw null; } }
        public static System.Security.Cryptography.Cose.CoseHeaderLabel KeyIdentifier { get { throw null; } }
        public static System.Security.Cryptography.Cose.CoseHeaderLabel PartialIV { get { throw null; } }
        public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? obj) { throw null; }
        public bool Equals(System.Security.Cryptography.Cose.CoseHeaderLabel other) { throw null; }
        public override int GetHashCode() { throw null; }
        public static bool operator ==(System.Security.Cryptography.Cose.CoseHeaderLabel left, System.Security.Cryptography.Cose.CoseHeaderLabel right) { throw null; }
        public static bool operator !=(System.Security.Cryptography.Cose.CoseHeaderLabel left, System.Security.Cryptography.Cose.CoseHeaderLabel right) { throw null; }
    }
-    public sealed partial class CoseHeaderMap : System.Collections.Generic.IEnumerable<(System.Security.Cryptography.Cose.CoseHeaderLabel Label, System.ReadOnlyMemory<byte> EncodedValue)>, System.Collections.IEnumerable
+    public sealed partial class CoseHeaderMap : System.Collections.Generic.IEnumerable<(System.Security.Cryptography.Cose.CoseHeaderLabel, System.ReadOnlyMemory<byte>)>, System.Collections.IEnumerable
    {
        public CoseHeaderMap() { }
        public bool IsReadOnly { get { throw null; } }
        public System.ReadOnlyMemory<byte> GetEncodedValue(System.Security.Cryptography.Cose.CoseHeaderLabel label) { throw null; }
        public System.Security.Cryptography.Cose.CoseHeaderMap.Enumerator GetEnumerator() { throw null; }
        public System.ReadOnlySpan<byte> GetValueAsBytes(System.Security.Cryptography.Cose.CoseHeaderLabel label) { throw null; }
        public int GetValueAsInt32(System.Security.Cryptography.Cose.CoseHeaderLabel label) { throw null; }
        public string GetValueAsString(System.Security.Cryptography.Cose.CoseHeaderLabel label) { throw null; }
        public void Remove(System.Security.Cryptography.Cose.CoseHeaderLabel label) { }
        public void SetEncodedValue(System.Security.Cryptography.Cose.CoseHeaderLabel label, System.ReadOnlySpan<byte> encodedValue) { }
        public void SetValue(System.Security.Cryptography.Cose.CoseHeaderLabel label, int value) { }
        public void SetValue(System.Security.Cryptography.Cose.CoseHeaderLabel label, System.ReadOnlySpan<byte> value) { }
        public void SetValue(System.Security.Cryptography.Cose.CoseHeaderLabel label, string value) { }
-        System.Collections.Generic.IEnumerator<(System.Security.Cryptography.Cose.CoseHeaderLabel Label, System.ReadOnlyMemory<byte> EncodedValue)> System.Collections.Generic.IEnumerable<(System.Security.Cryptography.Cose.CoseHeaderLabel Label, System.ReadOnlyMemory<System.Byte> EncodedValue)>.GetEnumerator() { throw null; }
+        System.Collections.Generic.IEnumerator<(System.Security.Cryptography.Cose.CoseHeaderLabel Label, System.ReadOnlyMemory<byte> EncodedValue)> System.Collections.Generic.IEnumerable<(System.Security.Cryptography.Cose.CoseHeaderLabelLabel,System.ReadOnlyMemory<System.Byte>EncodedValue)>.GetEnumerator() { throw null; }
        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { throw null; }
        public bool TryGetEncodedValue(System.Security.Cryptography.Cose.CoseHeaderLabel label, out System.ReadOnlyMemory<byte> encodedValue) { throw null; }
-        public partial struct Enumerator : System.Collections.Generic.IEnumerator<(System.Security.Cryptography.Cose.CoseHeaderLabel Label, System.ReadOnlyMemory<byte> EncodedValue)>, System.Collections.IEnumerator, System.IDisposable
+        public partial struct Enumerator : System.Collections.Generic.IEnumerator<(System.Security.Cryptography.Cose.CoseHeaderLabel, System.ReadOnlyMemory<byte>)>, System.Collections.IEnumerator, System.IDisposable
        {
+            private object _dummy;
+            private int _dummyPrimitive;
            public readonly (System.Security.Cryptography.Cose.CoseHeaderLabel Label, System.ReadOnlyMemory<byte> EncodedValue) Current { get { throw null; } }
            object System.Collections.IEnumerator.Current { get { throw null; } }
            public void Dispose() { }
            public bool MoveNext() { throw null; }
            public void Reset() { }
        }
    }
}

Note that sometimes doesn't remember the names

    public sealed partial class CoseHeaderMap : System.Collections.Generic.IEnumerable<(System.Security.Cryptography.Cose.CoseHeaderLabel, System.ReadOnlyMemory<byte>)>, System.Collections.IEnumerable
        public partial struct Enumerator : System.Collections.Generic.IEnumerator<(System.Security.Cryptography.Cose.CoseHeaderLabel, System.ReadOnlyMemory<byte>)>, System.Collections.IEnumerator, System.IDisposable

In other place it does but it formats it incorrectly

        System.Collections.Generic.IEnumerator<(System.Security.Cryptography.Cose.CoseHeaderLabel Label, System.ReadOnlyMemory<byte> EncodedValue)> System.Collections.Generic.IEnumerable<(System.Security.Cryptography.Cose.CoseHeaderLabelLabel,System.ReadOnlyMemory<System.Byte>EncodedValue)>.GetEnumerator() { throw null; }

And adds _dummy and _dummyPrimitive fields for some reason.

ghost commented 2 years ago

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

Issue Details
Repro steps: ``` cd ./src/libraries/System.Security.Cryptography.Cose/src dotnet msbuild /t:GenerateReferenceAssemblySource ``` Result: ref file ends up with errors: ```diff namespace System.Security.Cryptography.Cose { public readonly partial struct CoseHeaderLabel : System.IEquatable { + private readonly object _dummy; + private readonly int _dummyPrimitive; public CoseHeaderLabel(int label) { throw null; } public CoseHeaderLabel(string label) { throw null; } public static System.Security.Cryptography.Cose.CoseHeaderLabel Algorithm { get { throw null; } } public static System.Security.Cryptography.Cose.CoseHeaderLabel ContentType { get { throw null; } } public static System.Security.Cryptography.Cose.CoseHeaderLabel CounterSignature { get { throw null; } } public static System.Security.Cryptography.Cose.CoseHeaderLabel Critical { get { throw null; } } public static System.Security.Cryptography.Cose.CoseHeaderLabel IV { get { throw null; } } public static System.Security.Cryptography.Cose.CoseHeaderLabel KeyIdentifier { get { throw null; } } public static System.Security.Cryptography.Cose.CoseHeaderLabel PartialIV { get { throw null; } } public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? obj) { throw null; } public bool Equals(System.Security.Cryptography.Cose.CoseHeaderLabel other) { throw null; } public override int GetHashCode() { throw null; } public static bool operator ==(System.Security.Cryptography.Cose.CoseHeaderLabel left, System.Security.Cryptography.Cose.CoseHeaderLabel right) { throw null; } public static bool operator !=(System.Security.Cryptography.Cose.CoseHeaderLabel left, System.Security.Cryptography.Cose.CoseHeaderLabel right) { throw null; } } - public sealed partial class CoseHeaderMap : System.Collections.Generic.IEnumerable<(System.Security.Cryptography.Cose.CoseHeaderLabel Label, System.ReadOnlyMemory EncodedValue)>, System.Collections.IEnumerable + public sealed partial class CoseHeaderMap : System.Collections.Generic.IEnumerable<(System.Security.Cryptography.Cose.CoseHeaderLabel, System.ReadOnlyMemory)>, System.Collections.IEnumerable { public CoseHeaderMap() { } public bool IsReadOnly { get { throw null; } } public System.ReadOnlyMemory GetEncodedValue(System.Security.Cryptography.Cose.CoseHeaderLabel label) { throw null; } public System.Security.Cryptography.Cose.CoseHeaderMap.Enumerator GetEnumerator() { throw null; } public System.ReadOnlySpan GetValueAsBytes(System.Security.Cryptography.Cose.CoseHeaderLabel label) { throw null; } public int GetValueAsInt32(System.Security.Cryptography.Cose.CoseHeaderLabel label) { throw null; } public string GetValueAsString(System.Security.Cryptography.Cose.CoseHeaderLabel label) { throw null; } public void Remove(System.Security.Cryptography.Cose.CoseHeaderLabel label) { } public void SetEncodedValue(System.Security.Cryptography.Cose.CoseHeaderLabel label, System.ReadOnlySpan encodedValue) { } public void SetValue(System.Security.Cryptography.Cose.CoseHeaderLabel label, int value) { } public void SetValue(System.Security.Cryptography.Cose.CoseHeaderLabel label, System.ReadOnlySpan value) { } public void SetValue(System.Security.Cryptography.Cose.CoseHeaderLabel label, string value) { } - System.Collections.Generic.IEnumerator<(System.Security.Cryptography.Cose.CoseHeaderLabel Label, System.ReadOnlyMemory EncodedValue)> System.Collections.Generic.IEnumerable<(System.Security.Cryptography.Cose.CoseHeaderLabel Label, System.ReadOnlyMemory EncodedValue)>.GetEnumerator() { throw null; } + System.Collections.Generic.IEnumerator<(System.Security.Cryptography.Cose.CoseHeaderLabel Label, System.ReadOnlyMemory EncodedValue)> System.Collections.Generic.IEnumerable<(System.Security.Cryptography.Cose.CoseHeaderLabelLabel,System.ReadOnlyMemoryEncodedValue)>.GetEnumerator() { throw null; } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { throw null; } public bool TryGetEncodedValue(System.Security.Cryptography.Cose.CoseHeaderLabel label, out System.ReadOnlyMemory encodedValue) { throw null; } - public partial struct Enumerator : System.Collections.Generic.IEnumerator<(System.Security.Cryptography.Cose.CoseHeaderLabel Label, System.ReadOnlyMemory EncodedValue)>, System.Collections.IEnumerator, System.IDisposable + public partial struct Enumerator : System.Collections.Generic.IEnumerator<(System.Security.Cryptography.Cose.CoseHeaderLabel, System.ReadOnlyMemory)>, System.Collections.IEnumerator, System.IDisposable { + private object _dummy; + private int _dummyPrimitive; public readonly (System.Security.Cryptography.Cose.CoseHeaderLabel Label, System.ReadOnlyMemory EncodedValue) Current { get { throw null; } } object System.Collections.IEnumerator.Current { get { throw null; } } public void Dispose() { } public bool MoveNext() { throw null; } public void Reset() { } } } } ``` Note that sometimes doesn't remember the names ``` public sealed partial class CoseHeaderMap : System.Collections.Generic.IEnumerable<(System.Security.Cryptography.Cose.CoseHeaderLabel, System.ReadOnlyMemory)>, System.Collections.IEnumerable public partial struct Enumerator : System.Collections.Generic.IEnumerator<(System.Security.Cryptography.Cose.CoseHeaderLabel, System.ReadOnlyMemory)>, System.Collections.IEnumerator, System.IDisposable ``` In other place it does but it formats it incorrectly ``` System.Collections.Generic.IEnumerator<(System.Security.Cryptography.Cose.CoseHeaderLabel Label, System.ReadOnlyMemory EncodedValue)> System.Collections.Generic.IEnumerable<(System.Security.Cryptography.Cose.CoseHeaderLabelLabel,System.ReadOnlyMemoryEncodedValue)>.GetEnumerator() { throw null; } ``` And adds _dummy and _dummyPrimitive fields for some reason.
Author: Jozkee
Assignees: -
Labels: `area-System.Security`, `untriaged`
Milestone: -
ghost commented 2 years ago

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

Issue Details
Repro steps: ``` cd ./src/libraries/System.Security.Cryptography.Cose/src dotnet msbuild /t:GenerateReferenceAssemblySource ``` Result: ref file ends up with errors: ```diff namespace System.Security.Cryptography.Cose { public readonly partial struct CoseHeaderLabel : System.IEquatable { + private readonly object _dummy; + private readonly int _dummyPrimitive; public CoseHeaderLabel(int label) { throw null; } public CoseHeaderLabel(string label) { throw null; } public static System.Security.Cryptography.Cose.CoseHeaderLabel Algorithm { get { throw null; } } public static System.Security.Cryptography.Cose.CoseHeaderLabel ContentType { get { throw null; } } public static System.Security.Cryptography.Cose.CoseHeaderLabel CounterSignature { get { throw null; } } public static System.Security.Cryptography.Cose.CoseHeaderLabel Critical { get { throw null; } } public static System.Security.Cryptography.Cose.CoseHeaderLabel IV { get { throw null; } } public static System.Security.Cryptography.Cose.CoseHeaderLabel KeyIdentifier { get { throw null; } } public static System.Security.Cryptography.Cose.CoseHeaderLabel PartialIV { get { throw null; } } public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? obj) { throw null; } public bool Equals(System.Security.Cryptography.Cose.CoseHeaderLabel other) { throw null; } public override int GetHashCode() { throw null; } public static bool operator ==(System.Security.Cryptography.Cose.CoseHeaderLabel left, System.Security.Cryptography.Cose.CoseHeaderLabel right) { throw null; } public static bool operator !=(System.Security.Cryptography.Cose.CoseHeaderLabel left, System.Security.Cryptography.Cose.CoseHeaderLabel right) { throw null; } } - public sealed partial class CoseHeaderMap : System.Collections.Generic.IEnumerable<(System.Security.Cryptography.Cose.CoseHeaderLabel Label, System.ReadOnlyMemory EncodedValue)>, System.Collections.IEnumerable + public sealed partial class CoseHeaderMap : System.Collections.Generic.IEnumerable<(System.Security.Cryptography.Cose.CoseHeaderLabel, System.ReadOnlyMemory)>, System.Collections.IEnumerable { public CoseHeaderMap() { } public bool IsReadOnly { get { throw null; } } public System.ReadOnlyMemory GetEncodedValue(System.Security.Cryptography.Cose.CoseHeaderLabel label) { throw null; } public System.Security.Cryptography.Cose.CoseHeaderMap.Enumerator GetEnumerator() { throw null; } public System.ReadOnlySpan GetValueAsBytes(System.Security.Cryptography.Cose.CoseHeaderLabel label) { throw null; } public int GetValueAsInt32(System.Security.Cryptography.Cose.CoseHeaderLabel label) { throw null; } public string GetValueAsString(System.Security.Cryptography.Cose.CoseHeaderLabel label) { throw null; } public void Remove(System.Security.Cryptography.Cose.CoseHeaderLabel label) { } public void SetEncodedValue(System.Security.Cryptography.Cose.CoseHeaderLabel label, System.ReadOnlySpan encodedValue) { } public void SetValue(System.Security.Cryptography.Cose.CoseHeaderLabel label, int value) { } public void SetValue(System.Security.Cryptography.Cose.CoseHeaderLabel label, System.ReadOnlySpan value) { } public void SetValue(System.Security.Cryptography.Cose.CoseHeaderLabel label, string value) { } - System.Collections.Generic.IEnumerator<(System.Security.Cryptography.Cose.CoseHeaderLabel Label, System.ReadOnlyMemory EncodedValue)> System.Collections.Generic.IEnumerable<(System.Security.Cryptography.Cose.CoseHeaderLabel Label, System.ReadOnlyMemory EncodedValue)>.GetEnumerator() { throw null; } + System.Collections.Generic.IEnumerator<(System.Security.Cryptography.Cose.CoseHeaderLabel Label, System.ReadOnlyMemory EncodedValue)> System.Collections.Generic.IEnumerable<(System.Security.Cryptography.Cose.CoseHeaderLabelLabel,System.ReadOnlyMemoryEncodedValue)>.GetEnumerator() { throw null; } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { throw null; } public bool TryGetEncodedValue(System.Security.Cryptography.Cose.CoseHeaderLabel label, out System.ReadOnlyMemory encodedValue) { throw null; } - public partial struct Enumerator : System.Collections.Generic.IEnumerator<(System.Security.Cryptography.Cose.CoseHeaderLabel Label, System.ReadOnlyMemory EncodedValue)>, System.Collections.IEnumerator, System.IDisposable + public partial struct Enumerator : System.Collections.Generic.IEnumerator<(System.Security.Cryptography.Cose.CoseHeaderLabel, System.ReadOnlyMemory)>, System.Collections.IEnumerator, System.IDisposable { + private object _dummy; + private int _dummyPrimitive; public readonly (System.Security.Cryptography.Cose.CoseHeaderLabel Label, System.ReadOnlyMemory EncodedValue) Current { get { throw null; } } object System.Collections.IEnumerator.Current { get { throw null; } } public void Dispose() { } public bool MoveNext() { throw null; } public void Reset() { } } } } ``` Note that sometimes doesn't remember the names ``` public sealed partial class CoseHeaderMap : System.Collections.Generic.IEnumerable<(System.Security.Cryptography.Cose.CoseHeaderLabel, System.ReadOnlyMemory)>, System.Collections.IEnumerable public partial struct Enumerator : System.Collections.Generic.IEnumerator<(System.Security.Cryptography.Cose.CoseHeaderLabel, System.ReadOnlyMemory)>, System.Collections.IEnumerator, System.IDisposable ``` In other place it does but it formats it incorrectly ``` System.Collections.Generic.IEnumerator<(System.Security.Cryptography.Cose.CoseHeaderLabel Label, System.ReadOnlyMemory EncodedValue)> System.Collections.Generic.IEnumerable<(System.Security.Cryptography.Cose.CoseHeaderLabelLabel,System.ReadOnlyMemoryEncodedValue)>.GetEnumerator() { throw null; } ``` And adds _dummy and _dummyPrimitive fields for some reason.
Author: Jozkee
Assignees: -
Labels: `area-Infrastructure-libraries`, `untriaged`
Milestone: -
bartonjs commented 2 years ago

_dummy and _dummyPrimitive are important, you should let it add them :smile:

ViktorHofer commented 2 years ago

cc @ericstj @tannergooding

ericstj commented 2 years ago

As @bartonjs mentions the _dummy fileds are intentional and important. Those represent characteristics of the private members that are important for the compiler without actually exposing those private members.

Formatting of tuples this was first introduced in https://github.com/dotnet/arcade/commit/0f4c9a79c5c5a20dfb76f91f9f401b68473f2cd1 cc @pakrym

Likely we haven't yet exposed much public API with tuples and there are some cases that were missed there. @Jozkee would you be interested in debugging and proposing a fix?