diff --git a/CHANGELOG.md b/CHANGELOG.md index bbc4e26..5f208d9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,8 @@ section is the GitHub release's notes. - Analyzers: CMTK0006 now warns when a constructor sets a member only on another object it creates, `new Order(...) { Id = id }` or `other with { Id = id }`, which it took as setting its own. In a build that treats warnings as errors, that can report code that built before ([CMTK0006](https://github.com/CaffeinatedCoder/CodoMetis.TypeKit/blob/main/src/CodoMetis.TypeKit.Analyzers/README.md#cmtk0006)). - EF Core: a query filter that orders values your context holds without a lambda, as in `HasQueryFilter(o => o.Priority == Limits.Max())`, builds again; EF works it out in memory by your `CompareTo`. With a lambda, EF orders those values in the database, and the filter still fails ([Queries](https://github.com/CaffeinatedCoder/CodoMetis.TypeKit/blob/main/src/CodoMetis.TypeKit.EntityFrameworkCore/README.md#queries)). - Analyzers: CMTK0005 now also warns at `Array.CreateInstance(typeof(OrderId), n)`, `Array.CreateInstanceFromArrayType(typeof(OrderId[]), n)` and `ArrayPool.Rent(n)`, which create default slots as `new OrderId[n]` does. In a build that treats warnings as errors, that can report code that built before ([CMTK0005](https://github.com/CaffeinatedCoder/CodoMetis.TypeKit/blob/main/src/CodoMetis.TypeKit.Analyzers/README.md#cmtk0005)). +- Generators: an overload of a generated member that C# tells apart by its type parameters, or by a parameter that is `ref`, `in` or `out` where the generated one's isn't (or the other way round), is now kept beside the generated member, on a value object, a closed set or a base of either, where the build failed with CMTK1011: a `Parse(string, IFormatProvider?)`, a `From(in int)`, a `TryParse` whose last parameter isn't `out` ([Write your own members](https://github.com/CaffeinatedCoder/CodoMetis.TypeKit/blob/main/src/CodoMetis.TypeKit.Generators/README.md#write-your-own-members)). +- Generators: a generic `ToString()`, or a generic or by-`in` `CompareTo(TSelf)`, is no longer taken for the one you may write: a value object printed what a record prints (`Level { Value = 3 }`), a closed set its type name, and the ordering was marked hand-written, so EF Core refused to order by it. A generic or by-reference overload of `TryFrom`, `Revalidate`, `CompareTo(object)`, `Equals`, `GetHashCode` or `PrintMembers` is kept beside the generated member, where the build failed with CMTK1011 or CMTK1008 ([Write your own members](https://github.com/CaffeinatedCoder/CodoMetis.TypeKit/blob/main/src/CodoMetis.TypeKit.Generators/README.md#write-your-own-members)). ### Fixed diff --git a/design/aspects.md b/design/aspects.md index dc7ef6a..d03456c 100644 --- a/design/aspects.md +++ b/design/aspects.md @@ -184,6 +184,18 @@ members of a generated name or signature and its `IParsable` are CMTK1011, its `sealed` `ToString()` is the seam and one not sealed is CMTK1011 (#205). Not refused: an interface's `==`, which the record's own replaces anyway, and `INumberBase`'s UTF-8 bridges. + - **A signature is what C# overloads by (#226).** A hand-written method matches a generated one only with no type + parameters, as the generated one has none, and with each parameter by reference where the generated one's is + `out` and by value where it is by value. A generic `Parse(string, IFormatProvider?)`, a `From(in int)` + and a `TryParse` whose last parameter is by value were CMTK1011, on the type, a base record and a closed set, + though Metalama introduces the generated member beside each (measured 2026-10-31). `ref` or `in` against `out` is + no overload in C# (CS0663), and nullability none at all, so both stay CMTK1011. + The other checks by name and parameters, the seams and what a record synthesizes, read only a method without + type parameters whose parameters are all by value (`ValueObjectDeclaration.IsByValueAndNotGeneric`), as every + generated member but `TryParse` and `TryFormat` is: a generic `ToString()` was taken for the seam, so + the value object printed what a record prints and a closed set its type name, a generic or by-`in` + `CompareTo(TSelf)` marked the ordering hand-written, and a generic or by-reference `TryFrom`, `Revalidate`, + `CompareTo(object)`, `Equals`, `GetHashCode` or `PrintMembers` was CMTK1011 or CMTK1008. - **Equality over a base record is generated (decided 2026-10-14, [decision 75](adr/0075-equality-over-base-record-generated.md)).** A derived record's synthesized equality calls the base's, which compares the base's fields and whatever the base declares. A base comparing by reference made two value objects holding 42 unequal diff --git a/src/CodoMetis.TypeKit.Generators/ClosedSetTypes.cs b/src/CodoMetis.TypeKit.Generators/ClosedSetTypes.cs index 6deb354..f152439 100644 --- a/src/CodoMetis.TypeKit.Generators/ClosedSetTypes.cs +++ b/src/CodoMetis.TypeKit.Generators/ClosedSetTypes.cs @@ -203,8 +203,9 @@ private static string WithoutComments(string text) /// public static IReadOnlyList GeneratedMembersDeclaredByHand(INamedType set, IReadOnlyList members) { - var text = TypeFactory.GetType(SpecialType.String); - var boolean = TypeFactory.GetType(SpecialType.Boolean); + (IType, bool) text = (TypeFactory.GetType(SpecialType.String), false); + (IType, bool) boolean = (TypeFactory.GetType(SpecialType.Boolean), false); + (IType, bool) result = (set, true); var parsable = TypeFactory.GetNamedType(typeof(IParsable<>)).WithTypeArguments(set); var memberNames = new HashSet(members.Select(member => member.ToDisplayString())); var generatedNames = GeneratedNames(set); @@ -222,7 +223,7 @@ .. bases.SelectMany(type => type.Fields.Concat(type.Properties).Concat( .Where(member => member is { IsImplicitlyDeclared: false, IsExplicitInterfaceImplementation: false } && member.Accessibility != Accessibility.Private && generatedNames.Contains(member.Name)) .Select(member => $"{member.ToDisplayString()} in its base type {type.ToDisplayString()}")), .. Declared(type => type.Methods.Where(method => IsOwn(method) && method.Name == "Parse" && (SameParameters(method, text) || SameParameters(method, text, boolean)))), - .. Declared(type => type.Methods.Where(method => IsOwn(method) && method.Name == "TryParse" && (SameParameters(method, text, set) || SameParameters(method, text, boolean, set)))), + .. Declared(type => type.Methods.Where(method => IsOwn(method) && method.Name == "TryParse" && (SameParameters(method, text, result) || SameParameters(method, text, boolean, result)))), .. Declared(type => type.Methods.Where(method => IsOwn(method) && IsGeneratedMatch(method, members.Count))), .. ValueObjectDeclaration.ImplementationsOf(set, [TypeFactory.GetNamedType(typeof(IClosedSet<>))]), .. set.ImplementedInterfaces.Where(implemented => implemented.Equals(parsable)).Select(implemented => $"the interface {implemented.ToDisplayString()}"), @@ -243,10 +244,15 @@ .. set.Attributes.Where(attribute => attribute.Type.Equals(TypeFactory.GetNamedT private static bool IsOwn(IMethod method) => method is { IsImplicitlyDeclared: false, IsExplicitInterfaceImplementation: false }; - /// Parameter types equal, nullability aside: Metalama refuses to introduce a method beside one of the same signature. - private static bool SameParameters(IMethod method, params IType[] types) => - method.Parameters.Count == types.Length - && method.Parameters.Select(parameter => parameter.Type.ToNonNullable()).Zip(types, (declared, expected) => declared.Equals(expected.ToNonNullable())).All(same => same); + /// + /// Parameter types equal, nullability aside, and each by reference where the generated one is out, in a + /// method without type parameters: Metalama refuses to introduce a method beside one of the same signature. A + /// generic Parse<T>(string) or a TryParse(string?, TSelf) is another method (#226). + /// + private static bool SameParameters(IMethod method, params (IType Type, bool Out)[] parameters) => + method.TypeParameters.Count == 0 + && method.Parameters.Count == parameters.Length + && method.Parameters.Zip(parameters, (declared, expected) => declared.Type.ToNonNullable().Equals(expected.Type.ToNonNullable()) && declared.RefKind != RefKind.None == expected.Out).All(same => same); /// The generated Match<TResult>: one Func<TResult> per member. private static bool IsGeneratedMatch(IMethod method, int memberCount) => diff --git a/src/CodoMetis.TypeKit.Generators/README.md b/src/CodoMetis.TypeKit.Generators/README.md index 3a248e8..53f439c 100644 --- a/src/CodoMetis.TypeKit.Generators/README.md +++ b/src/CodoMetis.TypeKit.Generators/README.md @@ -239,6 +239,14 @@ covers: `MaxValue` would stand in for the generated one, and generic code calling `T.MaxValue` would reach it. The error names the base. +An overload of a generated member is yours, and the generated one sits beside it. C# tells two methods +apart by their type parameters and by whether a parameter is `ref`, `in` or `out`, so a +`Parse(string, IFormatProvider?)`, a `From(in int value)` or a `TryParse` whose last parameter +isn't `out` is kept, on the value object or a base record. A `ref` or `in` where the generated member has +`out` is the same method to C#, as a different nullability is, so it fails the build like the member itself. +The same goes for the members you may write: a generic `ToString()` or a `CompareTo(in TSelf)` isn't +the one that's kept, so the generated `ToString()` and ordering are still there. + Two explicit implementations in an interface are fine, because a value object loses nothing by replacing them. A record's own `==` and `!=` replace an interface's, generated or not. And .NET's `INumberBase` formats and parses UTF-8 through the UTF-16 members, which every .NET number @@ -462,8 +470,8 @@ public sealed partial class OrderStatus : IClosedSet, IParsable(string name)`, is kept too. Any other generated member written by hand fails the build (CMTK1011), in the set or in a class it derives from. - **A base class's `ToString()`.** A `sealed` one is kept, since C# keeps it in every derived class. One that isn't sealed fails the build (CMTK1011), because the generated `ToString()` would replace diff --git a/src/CodoMetis.TypeKit.Generators/ValueObjectComparableAspect.cs b/src/CodoMetis.TypeKit.Generators/ValueObjectComparableAspect.cs index 4427a63..8f30166 100644 --- a/src/CodoMetis.TypeKit.Generators/ValueObjectComparableAspect.cs +++ b/src/CodoMetis.TypeKit.Generators/ValueObjectComparableAspect.cs @@ -143,7 +143,7 @@ private static IEnumerable HandWrittenComparisonMembers(INamedType targe { foreach (var method in target.Methods) { - if (method.IsExplicitInterfaceImplementation) continue; + if (method.IsExplicitInterfaceImplementation || !ValueObjectDeclaration.IsByValueAndNotGeneric(method)) continue; var isObjectOverload = method is { Name: nameof(IComparable.CompareTo), Parameters: [{ Type.SpecialType: SpecialType.Object }] }; var isOrderingOperator = method.OperatorKind is OperatorKind.LessThan or OperatorKind.GreaterThan @@ -162,7 +162,7 @@ private static IEnumerable HandWrittenComparisonMembers(INamedType targe foreach (var method in type.Methods) { if (method is { IsStatic: false, IsExplicitInterfaceImplementation: false, Name: nameof(IComparable.CompareTo), Parameters: [{ } other] } - && ValueObjectDeclaration.IsHandWritten(method) + && ValueObjectDeclaration.IsByValueAndNotGeneric(method) && ValueObjectDeclaration.IsHandWritten(method) && (other.Type.SpecialType == SpecialType.Object || other.Type.ToNonNullable().Equals(target))) yield return $"{method.ToDisplayString()} in its base type {type.ToDisplayString()}"; } @@ -176,6 +176,7 @@ private static IEnumerable HandWrittenComparisonMembers(INamedType targe /// The seam: a CompareTo(TSelf) the type declares itself, which the generated one then leaves in place. private static bool DeclaresCompareTo(INamedType target) => target.Methods.Any(method => method is { IsImplicitlyDeclared: false, IsExplicitInterfaceImplementation: false, Name: nameof(IComparable.CompareTo) } + && ValueObjectDeclaration.IsByValueAndNotGeneric(method) && method.Parameters is [var other] && other.Type.Equals(target)); diff --git a/src/CodoMetis.TypeKit.Generators/ValueObjectContractAspect.cs b/src/CodoMetis.TypeKit.Generators/ValueObjectContractAspect.cs index c5f440a..ab795e8 100644 --- a/src/CodoMetis.TypeKit.Generators/ValueObjectContractAspect.cs +++ b/src/CodoMetis.TypeKit.Generators/ValueObjectContractAspect.cs @@ -101,7 +101,7 @@ private static void IntroduceEquality(IAspectBuilder builder, INamed if (type.Equals(direct) || !ExplicitlyImplementsEquatableBetween(direct, type, equatable.MakeGenericInstance(type))) continue; // One the value object declares itself implements the interface already, as C# maps it. - if (builder.Target.Methods.Any(method => method is { Name: nameof(Equals), Parameters: [{ } other] } && other.Type.ToNonNullable().Equals(type))) continue; + if (builder.Target.Methods.Any(method => method is { Name: nameof(Equals), Parameters: [{ } other] } && other.Type.ToNonNullable().Equals(type) && ValueObjectDeclaration.IsByValueAndNotGeneric(method))) continue; var hidden = type; builder.IntroduceMethod( diff --git a/src/CodoMetis.TypeKit.Generators/ValueObjectDeclaration.cs b/src/CodoMetis.TypeKit.Generators/ValueObjectDeclaration.cs index 7dbd478..a240322 100644 --- a/src/CodoMetis.TypeKit.Generators/ValueObjectDeclaration.cs +++ b/src/CodoMetis.TypeKit.Generators/ValueObjectDeclaration.cs @@ -54,7 +54,7 @@ public static bool DeclaresToString(INamedType type) => } private static bool IsHandWrittenToString(IMethod method) => - method is { Name: nameof(ToString), IsStatic: false, IsExplicitInterfaceImplementation: false, Parameters.Count: 0 } && IsHandWritten(method); + method is { Name: nameof(ToString), IsStatic: false, IsExplicitInterfaceImplementation: false, Parameters.Count: 0 } && IsByValueAndNotGeneric(method) && IsHandWritten(method); /// /// A value object and the records it derives from, left out. A struct has @@ -210,12 +210,15 @@ IEnumerable Declared(Func> find) => if (kind == ValueObjectKind.Plain) { - found.AddRange(Declared(type => MethodsWithSignature(type, "From", valueType))); + found.AddRange(Declared(type => MethodsWithSignature(type, "From", (valueType, false)))); found.AddRange(Declared(type => MembersNamed(type, methods: false, "From"))); } - var stringType = TypeFactory.GetType(SpecialType.String); - var provider = TypeFactory.GetType(typeof(IFormatProvider)); + // A generated method's parameters, and whether each is out: an overload that takes one by value where the + // generated one takes it by reference, or the other way round, is another method (#226). + (IType, bool) stringType = (TypeFactory.GetType(SpecialType.String), false); + (IType, bool) provider = (TypeFactory.GetType(typeof(IFormatProvider)), false); + (IType, bool) result = (target, true); // ValueObjectParsableAspect and, where parsing is generated, ValueObjectTypeConverterAspect. var parse = ValueObjectParsableAspect.ResolveStrategy(valueType); @@ -223,7 +226,7 @@ IEnumerable Declared(Func> find) => if (parse != ValueParseStrategy.Unsupported) { found.AddRange(Declared(type => MethodsWithSignature(type, "Parse", stringType, provider))); - found.AddRange(Declared(type => MethodsWithSignature(type, "TryParse", stringType, provider, target))); + found.AddRange(Declared(type => MethodsWithSignature(type, "TryParse", stringType, provider, result))); found.AddRange(Declared(type => MembersNamed(type, $"{target.Name}TypeConverter"))); generatedInterfaces.Add(TypeFactory.GetNamedType(typeof(IParsable<>))); @@ -231,18 +234,18 @@ IEnumerable Declared(Func> find) => { generatedInterfaces.Add(TypeFactory.GetNamedType(typeof(ISpanParsable<>))); - var span = TypeFactory.GetType(typeof(ReadOnlySpan)); + (IType, bool) span = (TypeFactory.GetType(typeof(ReadOnlySpan)), false); found.AddRange(Declared(type => MethodsWithSignature(type, "Parse", span, provider))); - found.AddRange(Declared(type => MethodsWithSignature(type, "TryParse", span, provider, target))); + found.AddRange(Declared(type => MethodsWithSignature(type, "TryParse", span, provider, result))); } if (ValueObjectParsableAspect.SupportsUtf8(valueType)) { generatedInterfaces.Add(TypeFactory.GetNamedType(typeof(IUtf8SpanParsable<>))); - var utf8 = TypeFactory.GetType(typeof(ReadOnlySpan)); + (IType, bool) utf8 = (TypeFactory.GetType(typeof(ReadOnlySpan)), false); found.AddRange(Declared(type => MethodsWithSignature(type, "Parse", utf8, provider))); - found.AddRange(Declared(type => MethodsWithSignature(type, "TryParse", utf8, provider, target))); + found.AddRange(Declared(type => MethodsWithSignature(type, "TryParse", utf8, provider, result))); } } @@ -254,13 +257,13 @@ IEnumerable Declared(Func> find) => if (ValueObjectFormattableAspect.ResolveStrategy(valueType) == ValueFormatStrategy.SpanFormattable) { - found.AddRange(Declared(type => MethodsWithSignature(type, nameof(ISpanFormattable.TryFormat), TypeFactory.GetType(typeof(Span)), TypeFactory.GetType(SpecialType.Int32), TypeFactory.GetType(typeof(ReadOnlySpan)), provider))); + found.AddRange(Declared(type => MethodsWithSignature(type, nameof(ISpanFormattable.TryFormat), (TypeFactory.GetType(typeof(Span)), false), (TypeFactory.GetType(SpecialType.Int32), true), (TypeFactory.GetType(typeof(ReadOnlySpan)), false), provider))); generatedInterfaces.Add(TypeFactory.GetNamedType(typeof(ISpanFormattable))); } if (ValueObjectFormattableAspect.SupportsUtf8(valueType)) { - found.AddRange(Declared(type => MethodsWithSignature(type, nameof(IUtf8SpanFormattable.TryFormat), TypeFactory.GetType(typeof(Span)), TypeFactory.GetType(SpecialType.Int32), TypeFactory.GetType(typeof(ReadOnlySpan)), provider))); + found.AddRange(Declared(type => MethodsWithSignature(type, nameof(IUtf8SpanFormattable.TryFormat), (TypeFactory.GetType(typeof(Span)), false), (TypeFactory.GetType(SpecialType.Int32), true), (TypeFactory.GetType(typeof(ReadOnlySpan)), false), provider))); generatedInterfaces.Add(TypeFactory.GetNamedType(typeof(IUtf8SpanFormattable))); } } @@ -436,7 +439,7 @@ public static IReadOnlyList InheritedSeams(INamedType target, INamedType kind != ValueObjectKind.Validated ? [] : [.. SelfAndBases(target).Skip(1).SelectMany(type => type.Methods - .Where(method => IsHandWritten(method) && !method.IsExplicitInterfaceImplementation + .Where(method => IsHandWritten(method) && !method.IsExplicitInterfaceImplementation && IsByValueAndNotGeneric(method) && (method is { Name: "TryFrom", IsStatic: true, Parameters: [{ } value] } && value.Type.ToNonNullable().Equals(valueType.ToNonNullable()) || method is { Name: "Revalidate", IsStatic: false, Parameters.Count: 0 })) .Select(method => $"{method.ToDisplayString()} in its base type {type.ToDisplayString()}"))]; @@ -510,7 +513,7 @@ public static IReadOnlyList PrintMembersDeclaredByHand(INamedType target return [ .. SelfAndBases(target).SelectMany(type => type.Methods - .Where(method => method is { Name: "PrintMembers", IsStatic: false, Parameters: [{ } builder] } && builder.Type.Equals(stringBuilder) && IsHandWritten(method)) + .Where(method => method is { Name: "PrintMembers", IsStatic: false, Parameters: [{ } builder] } && builder.Type.Equals(stringBuilder) && IsByValueAndNotGeneric(method) && IsHandWritten(method)) .Select(method => Describe(method) + (type.Equals(target) ? "" : $" in its base type {type.ToDisplayString()}"))) ]; } @@ -537,7 +540,7 @@ public static IReadOnlyList EqualityDeclaredByHand(INamedType target) return [ .. target.Methods - .Where(method => method is { IsStatic: false, IsImplicitlyDeclared: false } + .Where(method => method is { IsStatic: false, IsImplicitlyDeclared: false } && IsByValueAndNotGeneric(method) && (method.IsExplicitInterfaceImplementation ? method.ExplicitInterfaceImplementations.Any(implemented => implemented.DeclaringType.Definition.Equals(equatable)) : (method is { Name: nameof(Equals), Parameters: [{ } other] } && ownTypes.Any(type => other.Type.ToNonNullable().Equals(type))) @@ -565,7 +568,7 @@ public static IReadOnlyList InheritedEquality(INamedType target) return [ .. SelfAndBases(target).Skip(1).SelectMany(type => type.Methods - .Where(method => method is { IsStatic: false } && IsHandWritten(method) + .Where(method => method is { IsStatic: false } && IsByValueAndNotGeneric(method) && IsHandWritten(method) && (method.IsExplicitInterfaceImplementation ? method.ExplicitInterfaceImplementations.Any(implemented => implemented.DeclaringType.Definition.Equals(equatable)) : (method is { Name: nameof(Equals), Parameters: [{ } other] } && other.Type.Equals(type)) @@ -646,6 +649,15 @@ internal static string Describe(IMember member) internal static bool IsHandWritten(IMember member) => !member.IsImplicitlyDeclared && !member.Attributes.Any(attribute => attribute.Type.Equals(TypeFactory.GetNamedType(typeof(CompilerGeneratedAttribute)))); + /// + /// A method without type parameters whose parameters are all by value, as every generated method is but + /// TryParse and TryFormat (): C# overloads by arity and by a + /// parameter's ref kind, so a generic CompareTo<T>(object?) or a TryFrom(in int) is another + /// method, which the generated one sits beside, and no seam (#226). + /// + internal static bool IsByValueAndNotGeneric(IMethod method) => + method.TypeParameters.Count == 0 && method.Parameters.All(parameter => parameter.RefKind == RefKind.None); + /// Non-implicit members of with one of , of any kind. private static IEnumerable MembersNamed(INamedType target, params string[] names) => MembersNamed(target, methods: true, names); @@ -678,11 +690,18 @@ internal static IEnumerable MembersNamed(INamedType target, bool methods /// whatever they return: a generated member with that signature is either refused by Metalama or /// skipped in favour of the hand-written one. /// - private static IEnumerable MethodsWithSignature(INamedType target, string name, params IType[] parameters) => + /// + /// The signature C# overloads by (#226): no type parameters, as the generated method has none, and each + /// parameter by reference where the generated one is out, by value where it is by value. A generic + /// Parse<TFormat>(string, IFormatProvider?), a From(in int) and a TryParse whose + /// last parameter is by value are other methods, which the generated ones sit beside. ref or in + /// against out is no overload in C# (CS0663), so it is the same method, as nullability is. + /// + private static IEnumerable MethodsWithSignature(INamedType target, string name, params (IType Type, bool Out)[] parameters) => target.Methods - .Where(method => method is { IsImplicitlyDeclared: false, IsExplicitInterfaceImplementation: false } + .Where(method => method is { IsImplicitlyDeclared: false, IsExplicitInterfaceImplementation: false, TypeParameters.Count: 0 } && method.Name == name && method.Parameters.Count == parameters.Length - && method.Parameters.Select(parameter => parameter.Type).Zip(parameters, (declared, expected) => declared.Equals(expected)).All(same => same)) + && method.Parameters.Zip(parameters, (declared, expected) => declared.Type.Equals(expected.Type) && declared.RefKind != RefKind.None == expected.Out).All(same => same)) .Select(method => method.ToDisplayString()); } diff --git a/test/CodoMetis.TypeKit.Generators.Probes/Probes.cs b/test/CodoMetis.TypeKit.Generators.Probes/Probes.cs index e4c3c36..45ef516 100644 --- a/test/CodoMetis.TypeKit.Generators.Probes/Probes.cs +++ b/test/CodoMetis.TypeKit.Generators.Probes/Probes.cs @@ -186,6 +186,23 @@ public override void Write(System.Text.Json.Utf8JsonWriter writer, ProbeSpanText /// public abstract record ProbeRecordBase; +/// +/// A base record in another assembly whose methods share a generated member's name and parameter types, but are +/// other methods to C#: a generic Parse, a From that takes its value by in, and a +/// TryParse whose last parameter is by value. The generated members sit beside them (#226). +/// +public abstract record ProbeOverloadingRecord +{ + /// A generic overload, never the generated Parse. + public static TSelf Parse(string text, IFormatProvider? provider) => throw new NotSupportedException("hand-written"); + + /// An overload by in, never the generated From. + public static TSelf From(in int value) => throw new NotSupportedException("hand-written"); + + /// An overload whose last parameter is by value, never the generated TryParse. + public static bool TryParse(string? text, IFormatProvider? provider, TSelf fallback) => throw new NotSupportedException("hand-written"); +} + /// /// A base record in another assembly for the test assembly's value objects, whose sealed /// ToString() is the formatting seam: C# keeps it in every derived record. diff --git a/test/CodoMetis.TypeKit.Generators.Tests/BuildOutcomeTests.cs b/test/CodoMetis.TypeKit.Generators.Tests/BuildOutcomeTests.cs index 5c81867..a726059 100644 --- a/test/CodoMetis.TypeKit.Generators.Tests/BuildOutcomeTests.cs +++ b/test/CodoMetis.TypeKit.Generators.Tests/BuildOutcomeTests.cs @@ -183,6 +183,8 @@ public void A_member_name_the_generators_take_is_refused_with_the_reason(string [InlineData("SetOverParsingBase", "ParsingSetBase.Parse(string) in its base type ParsingSetBase")] [InlineData("SetOverIgnoreCaseParsingBase", "IgnoreCaseParsingSetBase.Parse(string, bool) in its base type IgnoreCaseParsingSetBase")] [InlineData("SetOverTryParsingBase", "TryParsingSetBase.TryParse(string?, bool, out SetOverTryParsingBase) in its base type TryParsingSetBase")] + [InlineData("SetWithTryParseByRef", "SetWithTryParseByRef.TryParse(string?, ref SetWithTryParseByRef)")] + [InlineData("SetOverTryParsingByRefBase", "TryParsingByRefSetBase.TryParse(string?, bool, ref SetOverTryParsingByRefBase) in its base type TryParsingByRefSetBase")] [InlineData("SetOverMatchingBase", "MatchingSetBase.Match(Func) in its base type MatchingSetBase")] [InlineData("SetOverParsableBase", "the interface IParsable in its base type ParsableSetBase")] [InlineData("SetOverAllListingBase", "AllListingSetBase.All in its base type AllListingSetBase")] @@ -338,6 +340,10 @@ public void A_part_a_source_generator_adds_does_not_count() => [InlineData("HandWrittenParse", "HandWrittenParse.Parse(string, IFormatProvider?)")] [InlineData("HandWrittenParseOverASet", "HandWrittenParseOverASet.Parse(string, IFormatProvider?)")] [InlineData("HandWrittenFormat", "HandWrittenFormat.ToString(string?, IFormatProvider?)")] + [InlineData("TryParseByRef", "TryParseByRef.TryParse(string?, IFormatProvider?, ref TryParseByRef)")] + [InlineData("TryParseByIn", "TryParseByIn.TryParse(string?, IFormatProvider?, in TryParseByIn)")] + [InlineData("ParseOfOtherNullability", "ParseOfOtherNullability.Parse(string?, IFormatProvider)")] + [InlineData("TryFormatByRef", "TryFormatByRef.TryFormat(Span, ref int, ReadOnlySpan, IFormatProvider?)")] [InlineData("HandWrittenMinValue", "HandWrittenMinValue.MinValue")] [InlineData("HandWrittenJsonConverter", "the attribute JsonConverter")] [InlineData("HandWrittenTypeConverter", "the attribute TypeConverter")] @@ -495,6 +501,7 @@ public void One_Create_over_a_base_record_is_not_refused(string type) => [InlineData("CMTK1011", "InheritsPublicFormatting", "PublicFormattingBase.ToString(string?, IFormatProvider?) in its base type PublicFormattingBase")] [InlineData("CMTK1008", "InheritsPublicObjectOrder", "PublicObjectOrderBase.CompareTo(object?) in its base type PublicObjectOrderBase")] [InlineData("CMTK1011", "InheritsPublicParsing", "PublicParsingBase.Parse(string, IFormatProvider?) in its base type PublicParsingBase")] + [InlineData("CMTK1011", "InheritsTryParseByRef", "TryParseByRefBase.TryParse(string?, IFormatProvider?, ref InheritsTryParseByRef) in its base type TryParseByRefBase")] [InlineData("CMTK1011", "InheritsMinMaxNames", "MinMaxNamesBase.MinValue in its base type MinMaxNamesBase")] [InlineData("CMTK1011", "InheritsValueName", "ValueNameBase.Value in its base type ValueNameBase")] [InlineData("CMTK1011", "InheritsFromName", "FromNameBase.From(int) in its base type FromNameBase")] @@ -1043,6 +1050,27 @@ public static Result Create(string value) => public string ToString(string? format, System.IFormatProvider? provider) => ""; } + // No overload in C#: ref or in against the generated out (CS0663), and another nullability (#226). + public readonly partial record struct TryParseByRef : IValue + { + public static bool TryParse(string? s, System.IFormatProvider? provider, ref TryParseByRef result) => throw new System.NotSupportedException(); + } + + public readonly partial record struct TryParseByIn : IValue + { + public static bool TryParse(string? s, System.IFormatProvider? provider, in TryParseByIn result) => throw new System.NotSupportedException(); + } + + public readonly partial record struct ParseOfOtherNullability : IValue + { + public static ParseOfOtherNullability Parse(string? s, System.IFormatProvider provider) => throw new System.NotSupportedException(); + } + + public readonly partial record struct TryFormatByRef : IValue + { + public bool TryFormat(System.Span destination, ref int charsWritten, System.ReadOnlySpan format, System.IFormatProvider? provider) => false; + } + public readonly partial record struct HandWrittenMinValue : IValue { public static int MinValue => 0; @@ -1511,6 +1539,13 @@ public abstract record PublicParsingBase : System.IParsable where public sealed partial record InheritsPublicParsing : PublicParsingBase, IValue; + public abstract record TryParseByRefBase + { + public static bool TryParse(string? s, System.IFormatProvider? provider, ref TSelf result) => throw new System.NotSupportedException(); + } + + public sealed partial record InheritsTryParseByRef : TryParseByRefBase, IValue; + public abstract record MinMaxNamesBase where TSelf : MinMaxNamesBase { public static TSelf MinValue => throw new System.NotSupportedException(); @@ -2042,6 +2077,9 @@ public abstract class OpenToStringSetBase { public override string ToString() => public sealed partial class SetOverIgnoreCaseParsingBase : IgnoreCaseParsingSetBase, IClosedSet { public static readonly SetOverIgnoreCaseParsingBase A = new(); } public abstract class TryParsingSetBase { public static bool TryParse(string? name, bool ignoreCase, out TSelf member) => throw new System.NotSupportedException(); } public sealed partial class SetOverTryParsingBase : TryParsingSetBase, IClosedSet { public static readonly SetOverTryParsingBase A = new(); } + public sealed partial class SetWithTryParseByRef : IClosedSet { public static readonly SetWithTryParseByRef A = new(); public static bool TryParse(string? name, ref SetWithTryParseByRef member) => throw new System.NotSupportedException(); } + public abstract class TryParsingByRefSetBase { public static bool TryParse(string? name, bool ignoreCase, ref TSelf member) => throw new System.NotSupportedException(); } + public sealed partial class SetOverTryParsingByRefBase : TryParsingByRefSetBase, IClosedSet { public static readonly SetOverTryParsingByRefBase A = new(); } public abstract class MatchingSetBase { public TResult Match(System.Func only) => only(); } public sealed partial class SetOverMatchingBase : MatchingSetBase, IClosedSet { public static readonly SetOverMatchingBase A = new(); } public abstract class ParsableSetBase : System.IParsable where TSelf : ParsableSetBase diff --git a/test/CodoMetis.TypeKit.Generators.Tests/FabricTests.cs b/test/CodoMetis.TypeKit.Generators.Tests/FabricTests.cs index a288162..b3c1664 100644 --- a/test/CodoMetis.TypeKit.Generators.Tests/FabricTests.cs +++ b/test/CodoMetis.TypeKit.Generators.Tests/FabricTests.cs @@ -44,7 +44,8 @@ public void Every_declared_value_object_is_generated(Type type) type.GetInterfaces().ShouldContain(typeof(IValueObject<,>).MakeGenericType(type, underlying)); type.GetProperty("Value", BindingFlags.Public | BindingFlags.Instance).ShouldNotBeNull().PropertyType.ShouldBe(underlying); - type.GetMethod(plain ? "From" : "TryFrom", BindingFlags.Public | BindingFlags.Static).ShouldNotBeNull(); + // By its signature: a value object may declare an overload of it, generic or by reference (#226). + type.GetMethod(plain ? "From" : "TryFrom", 0, BindingFlags.Public | BindingFlags.Static, [underlying]).ShouldNotBeNull(); } /// diff --git a/test/CodoMetis.TypeKit.Generators.Tests/GeneratedSurface.verified.txt b/test/CodoMetis.TypeKit.Generators.Tests/GeneratedSurface.verified.txt index 67b03ee..ec5946d 100644 --- a/test/CodoMetis.TypeKit.Generators.Tests/GeneratedSurface.verified.txt +++ b/test/CodoMetis.TypeKit.Generators.Tests/GeneratedSurface.verified.txt @@ -100,7 +100,7 @@ ProbeArticle ProbeArticleFault Description : String Kind : FaultKind - Match(Func, Func) : TResult + Match(Func, Func) : TResult Name : String QualifiedName : String ToString() : String @@ -166,7 +166,7 @@ ProbeCode ProbeConcurrencyFault Description : String Kind : FaultKind - Match(Func, Func, Func) : TResult + Match(Func, Func, Func) : TResult Name : String QualifiedName : String ToString() : String @@ -700,7 +700,7 @@ ProbeIsbn extension static ProbeIsbnExtensions.GetValue(ProbeIsbn) : ProbeIsbnText extension static ProbeIsbnExtensions.ValueOrNull(ProbeIsbn?) : ProbeIsbnText ProbeKeyword - Match(Func, Func) : TResult + Match(Func, Func) : TResult Name : String QualifiedName : String ToString() : String @@ -719,7 +719,7 @@ ProbeKeyword static TryParse(String, out ProbeKeyword) : Boolean ProbeKindlessFault Kind : FaultKind - Match(Func, Func) : TResult + Match(Func, Func) : TResult Name : String QualifiedName : String ToString() : String @@ -781,7 +781,7 @@ ProbeLabel extension static ProbeLabelExtensions.GetValue(ProbeLabel) : String extension static ProbeLabelExtensions.ValueOrNull(ProbeLabel) : String ProbeLabelled - Match(Func, Func) : TResult + Match(Func, Func) : TResult Name : String QualifiedName : String ToString() : String @@ -799,7 +799,7 @@ ProbeLabelled static TryParse(String, Boolean, out ProbeLabelled) : Boolean static TryParse(String, out ProbeLabelled) : Boolean ProbeLevel - Match(Func, Func) : TResult + Match(Func, Func) : TResult Name : String QualifiedName : String ToString() : String @@ -946,7 +946,7 @@ ProbeName extension static ProbeNameExtensions.GetValue(ProbeName) : String extension static ProbeNameExtensions.ValueOrNull(ProbeName?) : String ProbeOrder.Status - Match(Func) : TResult + Match(Func) : TResult Name : String QualifiedName : String ToString() : String @@ -966,7 +966,7 @@ ProbeOrder.Status ProbeOrderFault Description : String Kind : FaultKind - Match(Func, Func, Func) : TResult + Match(Func, Func, Func) : TResult Name : String QualifiedName : String ToString() : String @@ -1129,7 +1129,7 @@ ProbePin ProbePriority Label : String Match(Action, Action, Action) : Void - Match(Func, Func, Func) : TResult + Match(Func, Func, Func) : TResult Name : String QualifiedName : String Rank : Int32 @@ -1284,7 +1284,7 @@ ProbeSecret extension static ProbeSecretExtensions.GetValue(ProbeSecret) : String extension static ProbeSecretExtensions.ValueOrNull(ProbeSecret) : String ProbeShipment.Status - Match(Func) : TResult + Match(Func) : TResult Name : String QualifiedName : String ToString() : String @@ -1360,7 +1360,7 @@ ProbeSpan extension static ProbeSpanExtensions.GetValue(ProbeSpan) : ProbeSpanText extension static ProbeSpanExtensions.ValueOrNull(ProbeSpan?) : ProbeSpanText ProbeSplit - Match(Func, Func) : TResult + Match(Func, Func) : TResult Name : String QualifiedName : String ToString() : String @@ -1378,7 +1378,7 @@ ProbeSplit static TryParse(String, Boolean, out ProbeSplit) : Boolean static TryParse(String, out ProbeSplit) : Boolean ProbeStatus - Match(Func, Func, Func) : TResult + Match(Func, Func, Func) : TResult Name : String QualifiedName : String ToString() : String @@ -1396,7 +1396,7 @@ ProbeStatus static TryParse(String, Boolean, out ProbeStatus) : Boolean static TryParse(String, out ProbeStatus) : Boolean ProbeTier - Match(Func, Func) : TResult + Match(Func, Func) : TResult Name : String Perk : String QualifiedName : String @@ -1585,6 +1585,112 @@ ProbeWeekday extension static ProbeWeekdayExtensions.GetValue(ProbeWeekday) : DayOfWeek extension static ProbeWeekdayExtensions.ValueOrNull(ProbeWeekday?) : DayOfWeek? # CodoMetis.TypeKit.Generators.Tests +CompareToOverloadedByArity + CompareTo(CompareToOverloadedByArity) : Int32 + CompareTo(Object) : Int32 + CompareTo(CompareToOverloadedByArity) : Int32 + Equals(CompareToOverloadedByArity) : Boolean + Equals(Object) : Boolean + GetHashCode() : Int32 + ToString() : String + ToString(String, IFormatProvider) : String + TryFormat(Span, out Int32, ReadOnlySpan, IFormatProvider) : Boolean + TryFormat(Span, out Int32, ReadOnlySpan, IFormatProvider) : Boolean + Value : Int32 + attribute CompilerGeneratedAttribute + attribute GeneratedValueObjectAttribute + attribute JsonConverterAttribute + attribute TypeConverterAttribute + implements IComparable + implements IComparable + implements IComparisonOperators + implements IConvertible + implements IEqualityOperators + implements IEquatable + implements IFormattable + implements IMinMaxValue + implements IParsable + implements IPlainValueObject + implements ISpanFormattable + implements ISpanParsable + implements IUtf8SpanFormattable + implements IUtf8SpanParsable + implements IValue + implements IValueObject + implements IValueObjectMaterializer + nested CompareToOverloadedByArityJsonConverter : JsonConverter, IStoredJsonConverterSource + nested CompareToOverloadedByArityTypeConverter : TypeConverter + new() + static From(Int32) : CompareToOverloadedByArity + static MaxValue : CompareToOverloadedByArity + static MinValue : CompareToOverloadedByArity + static Parse(ReadOnlySpan, IFormatProvider) : CompareToOverloadedByArity + static Parse(ReadOnlySpan, IFormatProvider) : CompareToOverloadedByArity + static Parse(String, IFormatProvider) : CompareToOverloadedByArity + static TryParse(ReadOnlySpan, IFormatProvider, out CompareToOverloadedByArity) : Boolean + static TryParse(ReadOnlySpan, IFormatProvider, out CompareToOverloadedByArity) : Boolean + static TryParse(String, IFormatProvider, out CompareToOverloadedByArity) : Boolean + static op_Equality(CompareToOverloadedByArity, CompareToOverloadedByArity) : Boolean + static op_GreaterThan(CompareToOverloadedByArity, CompareToOverloadedByArity) : Boolean + static op_GreaterThanOrEqual(CompareToOverloadedByArity, CompareToOverloadedByArity) : Boolean + static op_Inequality(CompareToOverloadedByArity, CompareToOverloadedByArity) : Boolean + static op_LessThan(CompareToOverloadedByArity, CompareToOverloadedByArity) : Boolean + static op_LessThanOrEqual(CompareToOverloadedByArity, CompareToOverloadedByArity) : Boolean + extension static CompareToOverloadedByArityExtensions.GetValue(CompareToOverloadedByArity) : Int32 + extension static CompareToOverloadedByArityExtensions.ValueOrNull(CompareToOverloadedByArity?) : Int32? +CompareToOverloadedByIn + CompareTo(CompareToOverloadedByIn) : Int32 + CompareTo(Object) : Int32 + CompareTo(in CompareToOverloadedByIn) : Int32 + Equals(CompareToOverloadedByIn) : Boolean + Equals(Object) : Boolean + GetHashCode() : Int32 + ToString() : String + ToString(String, IFormatProvider) : String + TryFormat(Span, out Int32, ReadOnlySpan, IFormatProvider) : Boolean + TryFormat(Span, out Int32, ReadOnlySpan, IFormatProvider) : Boolean + Value : Int32 + attribute CompilerGeneratedAttribute + attribute GeneratedValueObjectAttribute + attribute JsonConverterAttribute + attribute TypeConverterAttribute + implements IComparable + implements IComparable + implements IComparisonOperators + implements IConvertible + implements IEqualityOperators + implements IEquatable + implements IFormattable + implements IMinMaxValue + implements IParsable + implements IPlainValueObject + implements ISpanFormattable + implements ISpanParsable + implements IUtf8SpanFormattable + implements IUtf8SpanParsable + implements IValue + implements IValueObject + implements IValueObjectMaterializer + nested CompareToOverloadedByInJsonConverter : JsonConverter, IStoredJsonConverterSource + nested CompareToOverloadedByInTypeConverter : TypeConverter + new() + static From(Int32) : CompareToOverloadedByIn + static MaxValue : CompareToOverloadedByIn + static MinValue : CompareToOverloadedByIn + static Parse(ReadOnlySpan, IFormatProvider) : CompareToOverloadedByIn + static Parse(ReadOnlySpan, IFormatProvider) : CompareToOverloadedByIn + static Parse(String, IFormatProvider) : CompareToOverloadedByIn + static TryParse(ReadOnlySpan, IFormatProvider, out CompareToOverloadedByIn) : Boolean + static TryParse(ReadOnlySpan, IFormatProvider, out CompareToOverloadedByIn) : Boolean + static TryParse(String, IFormatProvider, out CompareToOverloadedByIn) : Boolean + static op_Equality(CompareToOverloadedByIn, CompareToOverloadedByIn) : Boolean + static op_GreaterThan(CompareToOverloadedByIn, CompareToOverloadedByIn) : Boolean + static op_GreaterThanOrEqual(CompareToOverloadedByIn, CompareToOverloadedByIn) : Boolean + static op_Inequality(CompareToOverloadedByIn, CompareToOverloadedByIn) : Boolean + static op_LessThan(CompareToOverloadedByIn, CompareToOverloadedByIn) : Boolean + static op_LessThanOrEqual(CompareToOverloadedByIn, CompareToOverloadedByIn) : Boolean + extension static CompareToOverloadedByInExtensions.GetValue(CompareToOverloadedByIn) : Int32 + extension static CompareToOverloadedByInExtensions.ValueOrNull(CompareToOverloadedByIn?) : Int32? DefaultedAddress Equals(DefaultedAddress) : Boolean Equals(Object) : Boolean @@ -1670,7 +1776,7 @@ DefaultedVersion extension static DefaultedVersionExtensions.GetValue(DefaultedVersion) : Version extension static DefaultedVersionExtensions.ValueOrNull(DefaultedVersion?) : Version DocumentKind - Match(Func, Func) : TResult + Match(Func, Func) : TResult Name : String QualifiedName : String ToString() : String @@ -1688,7 +1794,7 @@ DocumentKind static TryParse(String, Boolean, out DocumentKind) : Boolean static TryParse(String, out DocumentKind) : Boolean EarlyAllStatus - Match(Func) : TResult + Match(Func) : TResult Name : String QualifiedName : String ToString() : String @@ -1706,7 +1812,7 @@ EarlyAllStatus static TryParse(String, Boolean, out EarlyAllStatus) : Boolean static TryParse(String, out EarlyAllStatus) : Boolean EarlyIgnoreCaseParseStatus - Match(Func) : TResult + Match(Func) : TResult Name : String QualifiedName : String ToString() : String @@ -1724,7 +1830,7 @@ EarlyIgnoreCaseParseStatus static TryParse(String, Boolean, out EarlyIgnoreCaseParseStatus) : Boolean static TryParse(String, out EarlyIgnoreCaseParseStatus) : Boolean EarlyIgnoreCaseTryParseStatus - Match(Func) : TResult + Match(Func) : TResult Name : String QualifiedName : String ToString() : String @@ -1742,7 +1848,7 @@ EarlyIgnoreCaseTryParseStatus static TryParse(String, Boolean, out EarlyIgnoreCaseTryParseStatus) : Boolean static TryParse(String, out EarlyIgnoreCaseTryParseStatus) : Boolean EarlyJsonKeyStatus - Match(Func) : TResult + Match(Func) : TResult Name : String QualifiedName : String ToString() : String @@ -1760,7 +1866,7 @@ EarlyJsonKeyStatus static TryParse(String, Boolean, out EarlyJsonKeyStatus) : Boolean static TryParse(String, out EarlyJsonKeyStatus) : Boolean EarlyJsonStatus - Match(Func) : TResult + Match(Func) : TResult Name : String QualifiedName : String ToString() : String @@ -1778,7 +1884,7 @@ EarlyJsonStatus static TryParse(String, Boolean, out EarlyJsonStatus) : Boolean static TryParse(String, out EarlyJsonStatus) : Boolean EarlyParsableStatus - Match(Func) : TResult + Match(Func) : TResult Name : String QualifiedName : String ToString() : String @@ -1796,7 +1902,7 @@ EarlyParsableStatus static TryParse(String, Boolean, out EarlyParsableStatus) : Boolean static TryParse(String, out EarlyParsableStatus) : Boolean EarlyParseStatus - Match(Func) : TResult + Match(Func) : TResult Name : String QualifiedName : String ToString() : String @@ -1814,7 +1920,7 @@ EarlyParseStatus static TryParse(String, Boolean, out EarlyParseStatus) : Boolean static TryParse(String, out EarlyParseStatus) : Boolean EarlyTryParseStatus - Match(Func) : TResult + Match(Func) : TResult Name : String QualifiedName : String ToString() : String @@ -1831,8 +1937,386 @@ EarlyTryParseStatus static Parse(String, Boolean) : EarlyTryParseStatus static TryParse(String, Boolean, out EarlyTryParseStatus) : Boolean static TryParse(String, out EarlyTryParseStatus) : Boolean +EqualityOverloadedByArity + CompareTo(EqualityOverloadedByArity) : Int32 + CompareTo(Object) : Int32 + Equals(EqualityOverloadedByArity) : Boolean + Equals(Object) : Boolean + Equals(EqualityOverloadedByArity) : Boolean + GetHashCode() : Int32 + GetHashCode() : Int32 + ToString() : String + ToString(String, IFormatProvider) : String + TryFormat(Span, out Int32, ReadOnlySpan, IFormatProvider) : Boolean + TryFormat(Span, out Int32, ReadOnlySpan, IFormatProvider) : Boolean + Value : Int32 + attribute CompilerGeneratedAttribute + attribute GeneratedValueObjectAttribute + attribute JsonConverterAttribute + attribute TypeConverterAttribute + implements IComparable + implements IComparable + implements IComparisonOperators + implements IConvertible + implements IEqualityOperators + implements IEquatable + implements IFormattable + implements IMinMaxValue + implements IParsable + implements IPlainValueObject + implements ISpanFormattable + implements ISpanParsable + implements IUtf8SpanFormattable + implements IUtf8SpanParsable + implements IValue + implements IValueObject + implements IValueObjectMaterializer + nested EqualityOverloadedByArityJsonConverter : JsonConverter, IStoredJsonConverterSource + nested EqualityOverloadedByArityTypeConverter : TypeConverter + new() + static From(Int32) : EqualityOverloadedByArity + static MaxValue : EqualityOverloadedByArity + static MinValue : EqualityOverloadedByArity + static Parse(ReadOnlySpan, IFormatProvider) : EqualityOverloadedByArity + static Parse(ReadOnlySpan, IFormatProvider) : EqualityOverloadedByArity + static Parse(String, IFormatProvider) : EqualityOverloadedByArity + static TryParse(ReadOnlySpan, IFormatProvider, out EqualityOverloadedByArity) : Boolean + static TryParse(ReadOnlySpan, IFormatProvider, out EqualityOverloadedByArity) : Boolean + static TryParse(String, IFormatProvider, out EqualityOverloadedByArity) : Boolean + static op_Equality(EqualityOverloadedByArity, EqualityOverloadedByArity) : Boolean + static op_GreaterThan(EqualityOverloadedByArity, EqualityOverloadedByArity) : Boolean + static op_GreaterThanOrEqual(EqualityOverloadedByArity, EqualityOverloadedByArity) : Boolean + static op_Inequality(EqualityOverloadedByArity, EqualityOverloadedByArity) : Boolean + static op_LessThan(EqualityOverloadedByArity, EqualityOverloadedByArity) : Boolean + static op_LessThanOrEqual(EqualityOverloadedByArity, EqualityOverloadedByArity) : Boolean + extension static EqualityOverloadedByArityExtensions.GetValue(EqualityOverloadedByArity) : Int32 + extension static EqualityOverloadedByArityExtensions.ValueOrNull(EqualityOverloadedByArity?) : Int32? +EqualsOverloadOverADeeperExplicitEquality + $() : EqualsOverloadOverADeeperExplicitEquality + CompareTo(EqualsOverloadOverADeeperExplicitEquality) : Int32 + CompareTo(Object) : Int32 + Equals(EqualsOverloadOverADeeperExplicitEquality) : Boolean + Equals(LocalBetweenRecord) : Boolean + Equals(LocalExplicitEqualityRecord) : Boolean + Equals(Object) : Boolean + Equals(LocalExplicitEqualityRecord) : Boolean + GetHashCode() : Int32 + ToString() : String + ToString(String, IFormatProvider) : String + TryFormat(Span, out Int32, ReadOnlySpan, IFormatProvider) : Boolean + TryFormat(Span, out Int32, ReadOnlySpan, IFormatProvider) : Boolean + Value : Int32 + attribute CompilerGeneratedAttribute + attribute GeneratedValueObjectAttribute + attribute JsonConverterAttribute + attribute TypeConverterAttribute + implements IComparable + implements IComparable + implements IComparisonOperators + implements IConvertible + implements IEqualityOperators + implements IEquatable + implements IEquatable + implements IEquatable + implements IFormattable + implements IMinMaxValue + implements IParsable + implements IPlainValueObject + implements IReimplementedEquatable + implements IReimplementedEquatable + implements ISpanFormattable + implements ISpanParsable + implements IUtf8SpanFormattable + implements IUtf8SpanParsable + implements IValue + implements IValueObject + implements IValueObjectMaterializer + nested EqualsOverloadOverADeeperExplicitEqualityJsonConverter : JsonConverter, IStoredJsonConverterSource + nested EqualsOverloadOverADeeperExplicitEqualityTypeConverter : TypeConverter + static From(Int32) : EqualsOverloadOverADeeperExplicitEquality + static MaxValue : EqualsOverloadOverADeeperExplicitEquality + static MinValue : EqualsOverloadOverADeeperExplicitEquality + static Parse(ReadOnlySpan, IFormatProvider) : EqualsOverloadOverADeeperExplicitEquality + static Parse(ReadOnlySpan, IFormatProvider) : EqualsOverloadOverADeeperExplicitEquality + static Parse(String, IFormatProvider) : EqualsOverloadOverADeeperExplicitEquality + static TryParse(ReadOnlySpan, IFormatProvider, out EqualsOverloadOverADeeperExplicitEquality) : Boolean + static TryParse(ReadOnlySpan, IFormatProvider, out EqualsOverloadOverADeeperExplicitEquality) : Boolean + static TryParse(String, IFormatProvider, out EqualsOverloadOverADeeperExplicitEquality) : Boolean + static op_Equality(EqualsOverloadOverADeeperExplicitEquality, EqualsOverloadOverADeeperExplicitEquality) : Boolean + static op_GreaterThan(EqualsOverloadOverADeeperExplicitEquality, EqualsOverloadOverADeeperExplicitEquality) : Boolean + static op_GreaterThanOrEqual(EqualsOverloadOverADeeperExplicitEquality, EqualsOverloadOverADeeperExplicitEquality) : Boolean + static op_Inequality(EqualsOverloadOverADeeperExplicitEquality, EqualsOverloadOverADeeperExplicitEquality) : Boolean + static op_LessThan(EqualsOverloadOverADeeperExplicitEquality, EqualsOverloadOverADeeperExplicitEquality) : Boolean + static op_LessThanOrEqual(EqualsOverloadOverADeeperExplicitEquality, EqualsOverloadOverADeeperExplicitEquality) : Boolean + extension static EqualsOverloadOverADeeperExplicitEqualityExtensions.GetValue(EqualsOverloadOverADeeperExplicitEquality) : Int32 + extension static EqualsOverloadOverADeeperExplicitEqualityExtensions.ValueOrNull(EqualsOverloadOverADeeperExplicitEquality) : Int32? +FormatOverloadedByArity + CompareTo(FormatOverloadedByArity) : Int32 + CompareTo(Object) : Int32 + Equals(FormatOverloadedByArity) : Boolean + Equals(Object) : Boolean + GetHashCode() : Int32 + ToString() : String + ToString(String, IFormatProvider) : String + ToString(String, IFormatProvider) : String + TryFormat(Span, out Int32, ReadOnlySpan, IFormatProvider) : Boolean + TryFormat(Span, out Int32, ReadOnlySpan, IFormatProvider) : Boolean + Value : Int32 + attribute CompilerGeneratedAttribute + attribute GeneratedValueObjectAttribute + attribute JsonConverterAttribute + attribute TypeConverterAttribute + implements IComparable + implements IComparable + implements IComparisonOperators + implements IConvertible + implements IEqualityOperators + implements IEquatable + implements IFormattable + implements IMinMaxValue + implements IParsable + implements IPlainValueObject + implements ISpanFormattable + implements ISpanParsable + implements IUtf8SpanFormattable + implements IUtf8SpanParsable + implements IValue + implements IValueObject + implements IValueObjectMaterializer + nested FormatOverloadedByArityJsonConverter : JsonConverter, IStoredJsonConverterSource + nested FormatOverloadedByArityTypeConverter : TypeConverter + new() + static From(Int32) : FormatOverloadedByArity + static MaxValue : FormatOverloadedByArity + static MinValue : FormatOverloadedByArity + static Parse(ReadOnlySpan, IFormatProvider) : FormatOverloadedByArity + static Parse(ReadOnlySpan, IFormatProvider) : FormatOverloadedByArity + static Parse(String, IFormatProvider) : FormatOverloadedByArity + static TryParse(ReadOnlySpan, IFormatProvider, out FormatOverloadedByArity) : Boolean + static TryParse(ReadOnlySpan, IFormatProvider, out FormatOverloadedByArity) : Boolean + static TryParse(String, IFormatProvider, out FormatOverloadedByArity) : Boolean + static op_Equality(FormatOverloadedByArity, FormatOverloadedByArity) : Boolean + static op_GreaterThan(FormatOverloadedByArity, FormatOverloadedByArity) : Boolean + static op_GreaterThanOrEqual(FormatOverloadedByArity, FormatOverloadedByArity) : Boolean + static op_Inequality(FormatOverloadedByArity, FormatOverloadedByArity) : Boolean + static op_LessThan(FormatOverloadedByArity, FormatOverloadedByArity) : Boolean + static op_LessThanOrEqual(FormatOverloadedByArity, FormatOverloadedByArity) : Boolean + extension static FormatOverloadedByArityExtensions.GetValue(FormatOverloadedByArity) : Int32 + extension static FormatOverloadedByArityExtensions.ValueOrNull(FormatOverloadedByArity?) : Int32? +FormatOverloadedByIn + CompareTo(FormatOverloadedByIn) : Int32 + CompareTo(Object) : Int32 + Equals(FormatOverloadedByIn) : Boolean + Equals(Object) : Boolean + GetHashCode() : Int32 + ToString() : String + ToString(String, IFormatProvider) : String + ToString(in String, IFormatProvider) : String + TryFormat(Span, out Int32, ReadOnlySpan, IFormatProvider) : Boolean + TryFormat(Span, out Int32, ReadOnlySpan, IFormatProvider) : Boolean + Value : Int32 + attribute CompilerGeneratedAttribute + attribute GeneratedValueObjectAttribute + attribute JsonConverterAttribute + attribute TypeConverterAttribute + implements IComparable + implements IComparable + implements IComparisonOperators + implements IConvertible + implements IEqualityOperators + implements IEquatable + implements IFormattable + implements IMinMaxValue + implements IParsable + implements IPlainValueObject + implements ISpanFormattable + implements ISpanParsable + implements IUtf8SpanFormattable + implements IUtf8SpanParsable + implements IValue + implements IValueObject + implements IValueObjectMaterializer + nested FormatOverloadedByInJsonConverter : JsonConverter, IStoredJsonConverterSource + nested FormatOverloadedByInTypeConverter : TypeConverter + new() + static From(Int32) : FormatOverloadedByIn + static MaxValue : FormatOverloadedByIn + static MinValue : FormatOverloadedByIn + static Parse(ReadOnlySpan, IFormatProvider) : FormatOverloadedByIn + static Parse(ReadOnlySpan, IFormatProvider) : FormatOverloadedByIn + static Parse(String, IFormatProvider) : FormatOverloadedByIn + static TryParse(ReadOnlySpan, IFormatProvider, out FormatOverloadedByIn) : Boolean + static TryParse(ReadOnlySpan, IFormatProvider, out FormatOverloadedByIn) : Boolean + static TryParse(String, IFormatProvider, out FormatOverloadedByIn) : Boolean + static op_Equality(FormatOverloadedByIn, FormatOverloadedByIn) : Boolean + static op_GreaterThan(FormatOverloadedByIn, FormatOverloadedByIn) : Boolean + static op_GreaterThanOrEqual(FormatOverloadedByIn, FormatOverloadedByIn) : Boolean + static op_Inequality(FormatOverloadedByIn, FormatOverloadedByIn) : Boolean + static op_LessThan(FormatOverloadedByIn, FormatOverloadedByIn) : Boolean + static op_LessThanOrEqual(FormatOverloadedByIn, FormatOverloadedByIn) : Boolean + extension static FormatOverloadedByInExtensions.GetValue(FormatOverloadedByIn) : Int32 + extension static FormatOverloadedByInExtensions.ValueOrNull(FormatOverloadedByIn?) : Int32? +FromOverloadedByArity + CompareTo(FromOverloadedByArity) : Int32 + CompareTo(Object) : Int32 + Equals(FromOverloadedByArity) : Boolean + Equals(Object) : Boolean + GetHashCode() : Int32 + ToString() : String + ToString(String, IFormatProvider) : String + TryFormat(Span, out Int32, ReadOnlySpan, IFormatProvider) : Boolean + TryFormat(Span, out Int32, ReadOnlySpan, IFormatProvider) : Boolean + Value : Int32 + attribute CompilerGeneratedAttribute + attribute GeneratedValueObjectAttribute + attribute JsonConverterAttribute + attribute TypeConverterAttribute + implements IComparable + implements IComparable + implements IComparisonOperators + implements IConvertible + implements IEqualityOperators + implements IEquatable + implements IFormattable + implements IMinMaxValue + implements IParsable + implements IPlainValueObject + implements ISpanFormattable + implements ISpanParsable + implements IUtf8SpanFormattable + implements IUtf8SpanParsable + implements IValue + implements IValueObject + implements IValueObjectMaterializer + nested FromOverloadedByArityJsonConverter : JsonConverter, IStoredJsonConverterSource + nested FromOverloadedByArityTypeConverter : TypeConverter + new() + static From(Int32) : FromOverloadedByArity + static From(Int32) : FromOverloadedByArity + static MaxValue : FromOverloadedByArity + static MinValue : FromOverloadedByArity + static Parse(ReadOnlySpan, IFormatProvider) : FromOverloadedByArity + static Parse(ReadOnlySpan, IFormatProvider) : FromOverloadedByArity + static Parse(String, IFormatProvider) : FromOverloadedByArity + static TryParse(ReadOnlySpan, IFormatProvider, out FromOverloadedByArity) : Boolean + static TryParse(ReadOnlySpan, IFormatProvider, out FromOverloadedByArity) : Boolean + static TryParse(String, IFormatProvider, out FromOverloadedByArity) : Boolean + static op_Equality(FromOverloadedByArity, FromOverloadedByArity) : Boolean + static op_GreaterThan(FromOverloadedByArity, FromOverloadedByArity) : Boolean + static op_GreaterThanOrEqual(FromOverloadedByArity, FromOverloadedByArity) : Boolean + static op_Inequality(FromOverloadedByArity, FromOverloadedByArity) : Boolean + static op_LessThan(FromOverloadedByArity, FromOverloadedByArity) : Boolean + static op_LessThanOrEqual(FromOverloadedByArity, FromOverloadedByArity) : Boolean + extension static FromOverloadedByArityExtensions.GetValue(FromOverloadedByArity) : Int32 + extension static FromOverloadedByArityExtensions.ValueOrNull(FromOverloadedByArity?) : Int32? +FromOverloadedByIn + CompareTo(FromOverloadedByIn) : Int32 + CompareTo(Object) : Int32 + Equals(FromOverloadedByIn) : Boolean + Equals(Object) : Boolean + GetHashCode() : Int32 + ToString() : String + ToString(String, IFormatProvider) : String + TryFormat(Span, out Int32, ReadOnlySpan, IFormatProvider) : Boolean + TryFormat(Span, out Int32, ReadOnlySpan, IFormatProvider) : Boolean + Value : Int32 + attribute CompilerGeneratedAttribute + attribute GeneratedValueObjectAttribute + attribute JsonConverterAttribute + attribute TypeConverterAttribute + implements IComparable + implements IComparable + implements IComparisonOperators + implements IConvertible + implements IEqualityOperators + implements IEquatable + implements IFormattable + implements IMinMaxValue + implements IParsable + implements IPlainValueObject + implements ISpanFormattable + implements ISpanParsable + implements IUtf8SpanFormattable + implements IUtf8SpanParsable + implements IValue + implements IValueObject + implements IValueObjectMaterializer + nested FromOverloadedByInJsonConverter : JsonConverter, IStoredJsonConverterSource + nested FromOverloadedByInTypeConverter : TypeConverter + new() + static From(Int32) : FromOverloadedByIn + static From(in Int32) : FromOverloadedByIn + static MaxValue : FromOverloadedByIn + static MinValue : FromOverloadedByIn + static Parse(ReadOnlySpan, IFormatProvider) : FromOverloadedByIn + static Parse(ReadOnlySpan, IFormatProvider) : FromOverloadedByIn + static Parse(String, IFormatProvider) : FromOverloadedByIn + static TryParse(ReadOnlySpan, IFormatProvider, out FromOverloadedByIn) : Boolean + static TryParse(ReadOnlySpan, IFormatProvider, out FromOverloadedByIn) : Boolean + static TryParse(String, IFormatProvider, out FromOverloadedByIn) : Boolean + static op_Equality(FromOverloadedByIn, FromOverloadedByIn) : Boolean + static op_GreaterThan(FromOverloadedByIn, FromOverloadedByIn) : Boolean + static op_GreaterThanOrEqual(FromOverloadedByIn, FromOverloadedByIn) : Boolean + static op_Inequality(FromOverloadedByIn, FromOverloadedByIn) : Boolean + static op_LessThan(FromOverloadedByIn, FromOverloadedByIn) : Boolean + static op_LessThanOrEqual(FromOverloadedByIn, FromOverloadedByIn) : Boolean + extension static FromOverloadedByInExtensions.GetValue(FromOverloadedByIn) : Int32 + extension static FromOverloadedByInExtensions.ValueOrNull(FromOverloadedByIn?) : Int32? +FromOverloadedByRef + CompareTo(FromOverloadedByRef) : Int32 + CompareTo(Object) : Int32 + Equals(FromOverloadedByRef) : Boolean + Equals(Object) : Boolean + GetHashCode() : Int32 + ToString() : String + ToString(String, IFormatProvider) : String + TryFormat(Span, out Int32, ReadOnlySpan, IFormatProvider) : Boolean + TryFormat(Span, out Int32, ReadOnlySpan, IFormatProvider) : Boolean + Value : Int32 + attribute CompilerGeneratedAttribute + attribute GeneratedValueObjectAttribute + attribute JsonConverterAttribute + attribute TypeConverterAttribute + implements IComparable + implements IComparable + implements IComparisonOperators + implements IConvertible + implements IEqualityOperators + implements IEquatable + implements IFormattable + implements IMinMaxValue + implements IParsable + implements IPlainValueObject + implements ISpanFormattable + implements ISpanParsable + implements IUtf8SpanFormattable + implements IUtf8SpanParsable + implements IValue + implements IValueObject + implements IValueObjectMaterializer + nested FromOverloadedByRefJsonConverter : JsonConverter, IStoredJsonConverterSource + nested FromOverloadedByRefTypeConverter : TypeConverter + new() + static From(Int32) : FromOverloadedByRef + static From(ref Int32) : FromOverloadedByRef + static MaxValue : FromOverloadedByRef + static MinValue : FromOverloadedByRef + static Parse(ReadOnlySpan, IFormatProvider) : FromOverloadedByRef + static Parse(ReadOnlySpan, IFormatProvider) : FromOverloadedByRef + static Parse(String, IFormatProvider) : FromOverloadedByRef + static TryParse(ReadOnlySpan, IFormatProvider, out FromOverloadedByRef) : Boolean + static TryParse(ReadOnlySpan, IFormatProvider, out FromOverloadedByRef) : Boolean + static TryParse(String, IFormatProvider, out FromOverloadedByRef) : Boolean + static op_Equality(FromOverloadedByRef, FromOverloadedByRef) : Boolean + static op_GreaterThan(FromOverloadedByRef, FromOverloadedByRef) : Boolean + static op_GreaterThanOrEqual(FromOverloadedByRef, FromOverloadedByRef) : Boolean + static op_Inequality(FromOverloadedByRef, FromOverloadedByRef) : Boolean + static op_LessThan(FromOverloadedByRef, FromOverloadedByRef) : Boolean + static op_LessThanOrEqual(FromOverloadedByRef, FromOverloadedByRef) : Boolean + extension static FromOverloadedByRefExtensions.GetValue(FromOverloadedByRef) : Int32 + extension static FromOverloadedByRefExtensions.ValueOrNull(FromOverloadedByRef?) : Int32? LocalOrder.Stage - Match(Func, Func) : TResult + Match(Func, Func) : TResult Name : String QualifiedName : String ToString() : String @@ -1850,7 +2334,7 @@ LocalOrder.Stage static TryParse(String, Boolean, out LocalOrder.Stage) : Boolean static TryParse(String, out LocalOrder.Stage) : Boolean LocalStatus - Match(Func, Func, Func) : TResult + Match(Func, Func, Func) : TResult Name : String QualifiedName : String ToString() : String @@ -1952,7 +2436,7 @@ MaskedOverALocalRecord extension static MaskedOverALocalRecordExtensions.GetValue(MaskedOverALocalRecord) : String extension static MaskedOverALocalRecordExtensions.ValueOrNull(MaskedOverALocalRecord) : String MaskedSet - Match(Func, Func) : TResult + Match(Func, Func) : TResult Name : String QualifiedName : String attribute CompilerGeneratedAttribute @@ -1968,6 +2452,60 @@ MaskedSet static Parse(String, Boolean) : MaskedSet static TryParse(String, Boolean, out MaskedSet) : Boolean static TryParse(String, out MaskedSet) : Boolean +ObjectCompareToOverloaded + CompareTo(Object) : Int32 + CompareTo(ObjectCompareToOverloaded) : Int32 + CompareTo(in Object) : Int32 + CompareTo(Object) : Int32 + Equals(Object) : Boolean + Equals(ObjectCompareToOverloaded) : Boolean + GetHashCode() : Int32 + ToString() : String + ToString(String, IFormatProvider) : String + TryFormat(Span, out Int32, ReadOnlySpan, IFormatProvider) : Boolean + TryFormat(Span, out Int32, ReadOnlySpan, IFormatProvider) : Boolean + Value : Int32 + attribute CompilerGeneratedAttribute + attribute GeneratedValueObjectAttribute + attribute JsonConverterAttribute + attribute TypeConverterAttribute + implements IComparable + implements IComparable + implements IComparisonOperators + implements IConvertible + implements IEqualityOperators + implements IEquatable + implements IFormattable + implements IMinMaxValue + implements IParsable + implements IPlainValueObject + implements ISpanFormattable + implements ISpanParsable + implements IUtf8SpanFormattable + implements IUtf8SpanParsable + implements IValue + implements IValueObject + implements IValueObjectMaterializer + nested ObjectCompareToOverloadedJsonConverter : JsonConverter, IStoredJsonConverterSource + nested ObjectCompareToOverloadedTypeConverter : TypeConverter + new() + static From(Int32) : ObjectCompareToOverloaded + static MaxValue : ObjectCompareToOverloaded + static MinValue : ObjectCompareToOverloaded + static Parse(ReadOnlySpan, IFormatProvider) : ObjectCompareToOverloaded + static Parse(ReadOnlySpan, IFormatProvider) : ObjectCompareToOverloaded + static Parse(String, IFormatProvider) : ObjectCompareToOverloaded + static TryParse(ReadOnlySpan, IFormatProvider, out ObjectCompareToOverloaded) : Boolean + static TryParse(ReadOnlySpan, IFormatProvider, out ObjectCompareToOverloaded) : Boolean + static TryParse(String, IFormatProvider, out ObjectCompareToOverloaded) : Boolean + static op_Equality(ObjectCompareToOverloaded, ObjectCompareToOverloaded) : Boolean + static op_GreaterThan(ObjectCompareToOverloaded, ObjectCompareToOverloaded) : Boolean + static op_GreaterThanOrEqual(ObjectCompareToOverloaded, ObjectCompareToOverloaded) : Boolean + static op_Inequality(ObjectCompareToOverloaded, ObjectCompareToOverloaded) : Boolean + static op_LessThan(ObjectCompareToOverloaded, ObjectCompareToOverloaded) : Boolean + static op_LessThanOrEqual(ObjectCompareToOverloaded, ObjectCompareToOverloaded) : Boolean + extension static ObjectCompareToOverloadedExtensions.GetValue(ObjectCompareToOverloaded) : Int32 + extension static ObjectCompareToOverloadedExtensions.ValueOrNull(ObjectCompareToOverloaded?) : Int32? OverABetweenExplicitEqualityRecord $() : OverABetweenExplicitEqualityRecord CompareTo(Object) : Int32 @@ -2084,6 +2622,61 @@ OverADeeperExplicitEqualityRecord static op_LessThanOrEqual(OverADeeperExplicitEqualityRecord, OverADeeperExplicitEqualityRecord) : Boolean extension static OverADeeperExplicitEqualityRecordExtensions.GetValue(OverADeeperExplicitEqualityRecord) : Int32 extension static OverADeeperExplicitEqualityRecordExtensions.ValueOrNull(OverADeeperExplicitEqualityRecord) : Int32? +OverALibraryOverloadingBase + $() : OverALibraryOverloadingBase + CompareTo(Object) : Int32 + CompareTo(OverALibraryOverloadingBase) : Int32 + Equals(Object) : Boolean + Equals(OverALibraryOverloadingBase) : Boolean + Equals(ProbeOverloadingRecord) : Boolean + GetHashCode() : Int32 + ToString() : String + ToString(String, IFormatProvider) : String + TryFormat(Span, out Int32, ReadOnlySpan, IFormatProvider) : Boolean + TryFormat(Span, out Int32, ReadOnlySpan, IFormatProvider) : Boolean + Value : Int32 + attribute CompilerGeneratedAttribute + attribute GeneratedValueObjectAttribute + attribute JsonConverterAttribute + attribute TypeConverterAttribute + implements IComparable + implements IComparable + implements IComparisonOperators + implements IConvertible + implements IEqualityOperators + implements IEquatable + implements IEquatable> + implements IFormattable + implements IMinMaxValue + implements IParsable + implements IPlainValueObject + implements IReimplementedEquatable> + implements ISpanFormattable + implements ISpanParsable + implements IUtf8SpanFormattable + implements IUtf8SpanParsable + implements IValue + implements IValueObject + implements IValueObjectMaterializer + nested OverALibraryOverloadingBaseJsonConverter : JsonConverter, IStoredJsonConverterSource + nested OverALibraryOverloadingBaseTypeConverter : TypeConverter + static From(Int32) : OverALibraryOverloadingBase + static MaxValue : OverALibraryOverloadingBase + static MinValue : OverALibraryOverloadingBase + static Parse(ReadOnlySpan, IFormatProvider) : OverALibraryOverloadingBase + static Parse(ReadOnlySpan, IFormatProvider) : OverALibraryOverloadingBase + static Parse(String, IFormatProvider) : OverALibraryOverloadingBase + static TryParse(ReadOnlySpan, IFormatProvider, out OverALibraryOverloadingBase) : Boolean + static TryParse(ReadOnlySpan, IFormatProvider, out OverALibraryOverloadingBase) : Boolean + static TryParse(String, IFormatProvider, out OverALibraryOverloadingBase) : Boolean + static op_Equality(OverALibraryOverloadingBase, OverALibraryOverloadingBase) : Boolean + static op_GreaterThan(OverALibraryOverloadingBase, OverALibraryOverloadingBase) : Boolean + static op_GreaterThanOrEqual(OverALibraryOverloadingBase, OverALibraryOverloadingBase) : Boolean + static op_Inequality(OverALibraryOverloadingBase, OverALibraryOverloadingBase) : Boolean + static op_LessThan(OverALibraryOverloadingBase, OverALibraryOverloadingBase) : Boolean + static op_LessThanOrEqual(OverALibraryOverloadingBase, OverALibraryOverloadingBase) : Boolean + extension static OverALibraryOverloadingBaseExtensions.GetValue(OverALibraryOverloadingBase) : Int32 + extension static OverALibraryOverloadingBaseExtensions.ValueOrNull(OverALibraryOverloadingBase) : Int32? OverALibraryRecord $() : OverALibraryRecord CompareTo(Object) : Int32 @@ -2345,6 +2938,61 @@ OverAnIdentityRecord static op_LessThanOrEqual(OverAnIdentityRecord, OverAnIdentityRecord) : Boolean extension static OverAnIdentityRecordExtensions.GetValue(OverAnIdentityRecord) : Int32 extension static OverAnIdentityRecordExtensions.ValueOrNull(OverAnIdentityRecord) : Int32? +OverAnOverloadingBase + $() : OverAnOverloadingBase + CompareTo(Object) : Int32 + CompareTo(OverAnOverloadingBase) : Int32 + Equals(Object) : Boolean + Equals(OverAnOverloadingBase) : Boolean + Equals(OverloadingBase) : Boolean + GetHashCode() : Int32 + ToString() : String + ToString(String, IFormatProvider) : String + TryFormat(Span, out Int32, ReadOnlySpan, IFormatProvider) : Boolean + TryFormat(Span, out Int32, ReadOnlySpan, IFormatProvider) : Boolean + Value : Int32 + attribute CompilerGeneratedAttribute + attribute GeneratedValueObjectAttribute + attribute JsonConverterAttribute + attribute TypeConverterAttribute + implements IComparable + implements IComparable + implements IComparisonOperators + implements IConvertible + implements IEqualityOperators + implements IEquatable + implements IEquatable> + implements IFormattable + implements IMinMaxValue + implements IParsable + implements IPlainValueObject + implements IReimplementedEquatable> + implements ISpanFormattable + implements ISpanParsable + implements IUtf8SpanFormattable + implements IUtf8SpanParsable + implements IValue + implements IValueObject + implements IValueObjectMaterializer + nested OverAnOverloadingBaseJsonConverter : JsonConverter, IStoredJsonConverterSource + nested OverAnOverloadingBaseTypeConverter : TypeConverter + static From(Int32) : OverAnOverloadingBase + static MaxValue : OverAnOverloadingBase + static MinValue : OverAnOverloadingBase + static Parse(ReadOnlySpan, IFormatProvider) : OverAnOverloadingBase + static Parse(ReadOnlySpan, IFormatProvider) : OverAnOverloadingBase + static Parse(String, IFormatProvider) : OverAnOverloadingBase + static TryParse(ReadOnlySpan, IFormatProvider, out OverAnOverloadingBase) : Boolean + static TryParse(ReadOnlySpan, IFormatProvider, out OverAnOverloadingBase) : Boolean + static TryParse(String, IFormatProvider, out OverAnOverloadingBase) : Boolean + static op_Equality(OverAnOverloadingBase, OverAnOverloadingBase) : Boolean + static op_GreaterThan(OverAnOverloadingBase, OverAnOverloadingBase) : Boolean + static op_GreaterThanOrEqual(OverAnOverloadingBase, OverAnOverloadingBase) : Boolean + static op_Inequality(OverAnOverloadingBase, OverAnOverloadingBase) : Boolean + static op_LessThan(OverAnOverloadingBase, OverAnOverloadingBase) : Boolean + static op_LessThanOrEqual(OverAnOverloadingBase, OverAnOverloadingBase) : Boolean + extension static OverAnOverloadingBaseExtensions.GetValue(OverAnOverloadingBase) : Int32 + extension static OverAnOverloadingBaseExtensions.ValueOrNull(OverAnOverloadingBase) : Int32? OverByte CompareTo(Object) : Int32 CompareTo(OverByte) : Int32 @@ -3274,6 +3922,29 @@ OverVersion static op_LessThanOrEqual(OverVersion, OverVersion) : Boolean extension static OverVersionExtensions.GetValue(OverVersion) : Version extension static OverVersionExtensions.ValueOrNull(OverVersion?) : Version +OverloadingSet + Match(Func, Func) : TResult + Name : String + QualifiedName : String + ToString() : String + attribute CompilerGeneratedAttribute + attribute GeneratedClosedSetAttribute + attribute JsonConverterAttribute + attribute TypeConverterAttribute + implements IClosedSet + implements IParsable + nested OverloadingSetJsonConverter : JsonConverter + nested OverloadingSetTypeConverter : TypeConverter + static All : IReadOnlyList + static Parse(String) : OverloadingSet + static Parse(String, Boolean) : OverloadingSet + static Parse(String) : OverloadingSet + static Parse(String, Boolean) : OverloadingSet + static TryParse(String, Boolean, OverloadingSet) : Boolean + static TryParse(String, Boolean, out OverloadingSet) : Boolean + static TryParse(String, OverloadingSet) : Boolean + static TryParse(String, out OverloadingSet) : Boolean + static TryParse(String, out OverloadingSet) : Boolean ParityByte CompareTo(Object) : Int32 CompareTo(ParityByte) : Int32 @@ -3843,6 +4514,257 @@ ParityUShort static op_LessThanOrEqual(ParityUShort, ParityUShort) : Boolean extension static ParityUShortExtensions.GetValue(ParityUShort) : UInt16 extension static ParityUShortExtensions.ValueOrNull(ParityUShort?) : UInt16? +ParseOverloadedByArity + CompareTo(Object) : Int32 + CompareTo(ParseOverloadedByArity) : Int32 + Equals(Object) : Boolean + Equals(ParseOverloadedByArity) : Boolean + GetHashCode() : Int32 + ToString() : String + ToString(String, IFormatProvider) : String + TryFormat(Span, out Int32, ReadOnlySpan, IFormatProvider) : Boolean + TryFormat(Span, out Int32, ReadOnlySpan, IFormatProvider) : Boolean + Value : Int32 + attribute CompilerGeneratedAttribute + attribute GeneratedValueObjectAttribute + attribute JsonConverterAttribute + attribute TypeConverterAttribute + implements IComparable + implements IComparable + implements IComparisonOperators + implements IConvertible + implements IEqualityOperators + implements IEquatable + implements IFormattable + implements IMinMaxValue + implements IParsable + implements IPlainValueObject + implements ISpanFormattable + implements ISpanParsable + implements IUtf8SpanFormattable + implements IUtf8SpanParsable + implements IValue + implements IValueObject + implements IValueObjectMaterializer + nested ParseOverloadedByArityJsonConverter : JsonConverter, IStoredJsonConverterSource + nested ParseOverloadedByArityTypeConverter : TypeConverter + new() + static From(Int32) : ParseOverloadedByArity + static MaxValue : ParseOverloadedByArity + static MinValue : ParseOverloadedByArity + static Parse(ReadOnlySpan, IFormatProvider) : ParseOverloadedByArity + static Parse(ReadOnlySpan, IFormatProvider) : ParseOverloadedByArity + static Parse(String, IFormatProvider) : ParseOverloadedByArity + static Parse(String, IFormatProvider) : ParseOverloadedByArity + static TryParse(ReadOnlySpan, IFormatProvider, out ParseOverloadedByArity) : Boolean + static TryParse(ReadOnlySpan, IFormatProvider, out ParseOverloadedByArity) : Boolean + static TryParse(String, IFormatProvider, out ParseOverloadedByArity) : Boolean + static op_Equality(ParseOverloadedByArity, ParseOverloadedByArity) : Boolean + static op_GreaterThan(ParseOverloadedByArity, ParseOverloadedByArity) : Boolean + static op_GreaterThanOrEqual(ParseOverloadedByArity, ParseOverloadedByArity) : Boolean + static op_Inequality(ParseOverloadedByArity, ParseOverloadedByArity) : Boolean + static op_LessThan(ParseOverloadedByArity, ParseOverloadedByArity) : Boolean + static op_LessThanOrEqual(ParseOverloadedByArity, ParseOverloadedByArity) : Boolean + extension static ParseOverloadedByArityExtensions.GetValue(ParseOverloadedByArity) : Int32 + extension static ParseOverloadedByArityExtensions.ValueOrNull(ParseOverloadedByArity?) : Int32? +ParseOverloadedInARecordClass + $() : ParseOverloadedInARecordClass + CompareTo(Object) : Int32 + CompareTo(ParseOverloadedInARecordClass) : Int32 + Equals(Object) : Boolean + Equals(ParseOverloadedInARecordClass) : Boolean + GetHashCode() : Int32 + ToString() : String + ToString(String, IFormatProvider) : String + TryFormat(Span, out Int32, ReadOnlySpan, IFormatProvider) : Boolean + TryFormat(Span, out Int32, ReadOnlySpan, IFormatProvider) : Boolean + Value : Int32 + attribute CompilerGeneratedAttribute + attribute GeneratedValueObjectAttribute + attribute JsonConverterAttribute + attribute TypeConverterAttribute + implements IComparable + implements IComparable + implements IComparisonOperators + implements IConvertible + implements IEqualityOperators + implements IEquatable + implements IFormattable + implements IMinMaxValue + implements IParsable + implements IPlainValueObject + implements ISpanFormattable + implements ISpanParsable + implements IUtf8SpanFormattable + implements IUtf8SpanParsable + implements IValue + implements IValueObject + implements IValueObjectMaterializer + nested ParseOverloadedInARecordClassJsonConverter : JsonConverter, IStoredJsonConverterSource + nested ParseOverloadedInARecordClassTypeConverter : TypeConverter + static From(Int32) : ParseOverloadedInARecordClass + static MaxValue : ParseOverloadedInARecordClass + static MinValue : ParseOverloadedInARecordClass + static Parse(ReadOnlySpan, IFormatProvider) : ParseOverloadedInARecordClass + static Parse(ReadOnlySpan, IFormatProvider) : ParseOverloadedInARecordClass + static Parse(String, IFormatProvider) : ParseOverloadedInARecordClass + static Parse(String, IFormatProvider) : ParseOverloadedInARecordClass + static TryParse(ReadOnlySpan, IFormatProvider, out ParseOverloadedInARecordClass) : Boolean + static TryParse(ReadOnlySpan, IFormatProvider, out ParseOverloadedInARecordClass) : Boolean + static TryParse(String, IFormatProvider, out ParseOverloadedInARecordClass) : Boolean + static op_Equality(ParseOverloadedInARecordClass, ParseOverloadedInARecordClass) : Boolean + static op_GreaterThan(ParseOverloadedInARecordClass, ParseOverloadedInARecordClass) : Boolean + static op_GreaterThanOrEqual(ParseOverloadedInARecordClass, ParseOverloadedInARecordClass) : Boolean + static op_Inequality(ParseOverloadedInARecordClass, ParseOverloadedInARecordClass) : Boolean + static op_LessThan(ParseOverloadedInARecordClass, ParseOverloadedInARecordClass) : Boolean + static op_LessThanOrEqual(ParseOverloadedInARecordClass, ParseOverloadedInARecordClass) : Boolean + extension static ParseOverloadedInARecordClassExtensions.GetValue(ParseOverloadedInARecordClass) : Int32 + extension static ParseOverloadedInARecordClassExtensions.ValueOrNull(ParseOverloadedInARecordClass) : Int32? +PlainOverASeamOverloadingBase + $() : PlainOverASeamOverloadingBase + CompareTo(Object) : Int32 + CompareTo(PlainOverASeamOverloadingBase) : Int32 + Equals(Object) : Boolean + Equals(PlainOverASeamOverloadingBase) : Boolean + Equals(SeamOverloadingBase) : Boolean + GetHashCode() : Int32 + ToString() : String + ToString(String, IFormatProvider) : String + TryFormat(Span, out Int32, ReadOnlySpan, IFormatProvider) : Boolean + TryFormat(Span, out Int32, ReadOnlySpan, IFormatProvider) : Boolean + Value : Int32 + attribute CompilerGeneratedAttribute + attribute GeneratedValueObjectAttribute + attribute JsonConverterAttribute + attribute TypeConverterAttribute + implements IComparable + implements IComparable + implements IComparisonOperators + implements IConvertible + implements IEqualityOperators + implements IEquatable + implements IEquatable> + implements IFormattable + implements IMinMaxValue + implements IParsable + implements IPlainValueObject + implements IReimplementedEquatable> + implements ISpanFormattable + implements ISpanParsable + implements IUtf8SpanFormattable + implements IUtf8SpanParsable + implements IValue + implements IValueObject + implements IValueObjectMaterializer + nested PlainOverASeamOverloadingBaseJsonConverter : JsonConverter, IStoredJsonConverterSource + nested PlainOverASeamOverloadingBaseTypeConverter : TypeConverter + static From(Int32) : PlainOverASeamOverloadingBase + static MaxValue : PlainOverASeamOverloadingBase + static MinValue : PlainOverASeamOverloadingBase + static Parse(ReadOnlySpan, IFormatProvider) : PlainOverASeamOverloadingBase + static Parse(ReadOnlySpan, IFormatProvider) : PlainOverASeamOverloadingBase + static Parse(String, IFormatProvider) : PlainOverASeamOverloadingBase + static TryParse(ReadOnlySpan, IFormatProvider, out PlainOverASeamOverloadingBase) : Boolean + static TryParse(ReadOnlySpan, IFormatProvider, out PlainOverASeamOverloadingBase) : Boolean + static TryParse(String, IFormatProvider, out PlainOverASeamOverloadingBase) : Boolean + static op_Equality(PlainOverASeamOverloadingBase, PlainOverASeamOverloadingBase) : Boolean + static op_GreaterThan(PlainOverASeamOverloadingBase, PlainOverASeamOverloadingBase) : Boolean + static op_GreaterThanOrEqual(PlainOverASeamOverloadingBase, PlainOverASeamOverloadingBase) : Boolean + static op_Inequality(PlainOverASeamOverloadingBase, PlainOverASeamOverloadingBase) : Boolean + static op_LessThan(PlainOverASeamOverloadingBase, PlainOverASeamOverloadingBase) : Boolean + static op_LessThanOrEqual(PlainOverASeamOverloadingBase, PlainOverASeamOverloadingBase) : Boolean + extension static PlainOverASeamOverloadingBaseExtensions.GetValue(PlainOverASeamOverloadingBase) : Int32 + extension static PlainOverASeamOverloadingBaseExtensions.ValueOrNull(PlainOverASeamOverloadingBase) : Int32? +PrintMembersOverloadedByArity + $() : PrintMembersOverloadedByArity + CompareTo(Object) : Int32 + CompareTo(PrintMembersOverloadedByArity) : Int32 + Equals(Object) : Boolean + Equals(PrintMembersOverloadedByArity) : Boolean + GetHashCode() : Int32 + PrintMembers(StringBuilder) : Boolean + ToString() : String + ToString(String, IFormatProvider) : String + TryFormat(Span, out Int32, ReadOnlySpan, IFormatProvider) : Boolean + TryFormat(Span, out Int32, ReadOnlySpan, IFormatProvider) : Boolean + Value : Int32 + attribute CompilerGeneratedAttribute + attribute GeneratedValueObjectAttribute + attribute JsonConverterAttribute + attribute TypeConverterAttribute + implements IComparable + implements IComparable + implements IComparisonOperators + implements IConvertible + implements IEqualityOperators + implements IEquatable + implements IFormattable + implements IMinMaxValue + implements IParsable + implements IPlainValueObject + implements ISpanFormattable + implements ISpanParsable + implements IUtf8SpanFormattable + implements IUtf8SpanParsable + implements IValue + implements IValueObject + implements IValueObjectMaterializer + nested PrintMembersOverloadedByArityJsonConverter : JsonConverter, IStoredJsonConverterSource + nested PrintMembersOverloadedByArityTypeConverter : TypeConverter + static From(Int32) : PrintMembersOverloadedByArity + static MaxValue : PrintMembersOverloadedByArity + static MinValue : PrintMembersOverloadedByArity + static Parse(ReadOnlySpan, IFormatProvider) : PrintMembersOverloadedByArity + static Parse(ReadOnlySpan, IFormatProvider) : PrintMembersOverloadedByArity + static Parse(String, IFormatProvider) : PrintMembersOverloadedByArity + static TryParse(ReadOnlySpan, IFormatProvider, out PrintMembersOverloadedByArity) : Boolean + static TryParse(ReadOnlySpan, IFormatProvider, out PrintMembersOverloadedByArity) : Boolean + static TryParse(String, IFormatProvider, out PrintMembersOverloadedByArity) : Boolean + static op_Equality(PrintMembersOverloadedByArity, PrintMembersOverloadedByArity) : Boolean + static op_GreaterThan(PrintMembersOverloadedByArity, PrintMembersOverloadedByArity) : Boolean + static op_GreaterThanOrEqual(PrintMembersOverloadedByArity, PrintMembersOverloadedByArity) : Boolean + static op_Inequality(PrintMembersOverloadedByArity, PrintMembersOverloadedByArity) : Boolean + static op_LessThan(PrintMembersOverloadedByArity, PrintMembersOverloadedByArity) : Boolean + static op_LessThanOrEqual(PrintMembersOverloadedByArity, PrintMembersOverloadedByArity) : Boolean + extension static PrintMembersOverloadedByArityExtensions.GetValue(PrintMembersOverloadedByArity) : Int32 + extension static PrintMembersOverloadedByArityExtensions.ValueOrNull(PrintMembersOverloadedByArity) : Int32? +SetOverAnOverloadingBase + Match(Func, Func) : TResult + Name : String + QualifiedName : String + ToString() : String + attribute CompilerGeneratedAttribute + attribute GeneratedClosedSetAttribute + attribute JsonConverterAttribute + attribute TypeConverterAttribute + implements IClosedSet + implements IParsable + nested SetOverAnOverloadingBaseJsonConverter : JsonConverter + nested SetOverAnOverloadingBaseTypeConverter : TypeConverter + static All : IReadOnlyList + static Parse(String) : SetOverAnOverloadingBase + static Parse(String, Boolean) : SetOverAnOverloadingBase + static TryParse(String, Boolean, out SetOverAnOverloadingBase) : Boolean + static TryParse(String, out SetOverAnOverloadingBase) : Boolean +SetWithAGenericToString + Match(Func) : TResult + Name : String + QualifiedName : String + ToString() : String + ToString() : String + attribute CompilerGeneratedAttribute + attribute GeneratedClosedSetAttribute + attribute JsonConverterAttribute + attribute TypeConverterAttribute + implements IClosedSet + implements IParsable + nested SetWithAGenericToStringJsonConverter : JsonConverter + nested SetWithAGenericToStringTypeConverter : TypeConverter + static All : IReadOnlyList + static Parse(String) : SetWithAGenericToString + static Parse(String, Boolean) : SetWithAGenericToString + static TryParse(String, Boolean, out SetWithAGenericToString) : Boolean + static TryParse(String, out SetWithAGenericToString) : Boolean ShippableStatus Equals(Object) : Boolean Equals(ShippableStatus) : Boolean @@ -3874,6 +4796,60 @@ ShippableStatus static op_Inequality(ShippableStatus, ShippableStatus) : Boolean extension static ShippableStatusExtensions.GetValue(ShippableStatus) : LocalStatus extension static ShippableStatusExtensions.ValueOrNull(ShippableStatus?) : LocalStatus +SpanParseOverloaded + CompareTo(Object) : Int32 + CompareTo(SpanParseOverloaded) : Int32 + Equals(Object) : Boolean + Equals(SpanParseOverloaded) : Boolean + GetHashCode() : Int32 + ToString() : String + ToString(String, IFormatProvider) : String + TryFormat(Span, out Int32, ReadOnlySpan, IFormatProvider) : Boolean + TryFormat(Span, out Int32, ReadOnlySpan, IFormatProvider) : Boolean + Value : Int32 + attribute CompilerGeneratedAttribute + attribute GeneratedValueObjectAttribute + attribute JsonConverterAttribute + attribute TypeConverterAttribute + implements IComparable + implements IComparable + implements IComparisonOperators + implements IConvertible + implements IEqualityOperators + implements IEquatable + implements IFormattable + implements IMinMaxValue + implements IParsable + implements IPlainValueObject + implements ISpanFormattable + implements ISpanParsable + implements IUtf8SpanFormattable + implements IUtf8SpanParsable + implements IValue + implements IValueObject + implements IValueObjectMaterializer + nested SpanParseOverloadedJsonConverter : JsonConverter, IStoredJsonConverterSource + nested SpanParseOverloadedTypeConverter : TypeConverter + new() + static From(Int32) : SpanParseOverloaded + static MaxValue : SpanParseOverloaded + static MinValue : SpanParseOverloaded + static Parse(ReadOnlySpan, IFormatProvider) : SpanParseOverloaded + static Parse(ReadOnlySpan, IFormatProvider) : SpanParseOverloaded + static Parse(String, IFormatProvider) : SpanParseOverloaded + static Parse(ReadOnlySpan, IFormatProvider) : SpanParseOverloaded + static TryParse(ReadOnlySpan, IFormatProvider, out SpanParseOverloaded) : Boolean + static TryParse(ReadOnlySpan, IFormatProvider, SpanParseOverloaded) : Boolean + static TryParse(ReadOnlySpan, IFormatProvider, out SpanParseOverloaded) : Boolean + static TryParse(String, IFormatProvider, out SpanParseOverloaded) : Boolean + static op_Equality(SpanParseOverloaded, SpanParseOverloaded) : Boolean + static op_GreaterThan(SpanParseOverloaded, SpanParseOverloaded) : Boolean + static op_GreaterThanOrEqual(SpanParseOverloaded, SpanParseOverloaded) : Boolean + static op_Inequality(SpanParseOverloaded, SpanParseOverloaded) : Boolean + static op_LessThan(SpanParseOverloaded, SpanParseOverloaded) : Boolean + static op_LessThanOrEqual(SpanParseOverloaded, SpanParseOverloaded) : Boolean + extension static SpanParseOverloadedExtensions.GetValue(SpanParseOverloaded) : Int32 + extension static SpanParseOverloadedExtensions.ValueOrNull(SpanParseOverloaded?) : Int32? StageOfOrder Equals(Object) : Boolean Equals(StageOfOrder) : Boolean @@ -4215,3 +5191,368 @@ ThrowingSku static op_Inequality(ThrowingSku, ThrowingSku) : Boolean extension static ThrowingSkuExtensions.GetValue(ThrowingSku) : ProbeSkuText extension static ThrowingSkuExtensions.ValueOrNull(ThrowingSku?) : ProbeSkuText +ToStringOverloadedByArity + CompareTo(Object) : Int32 + CompareTo(ToStringOverloadedByArity) : Int32 + Equals(Object) : Boolean + Equals(ToStringOverloadedByArity) : Boolean + GetHashCode() : Int32 + ToString() : String + ToString(String, IFormatProvider) : String + ToString() : String + Value : String + attribute CompilerGeneratedAttribute + attribute GeneratedValueObjectAttribute + attribute JsonConverterAttribute + attribute TypeConverterAttribute + implements IComparable + implements IComparable + implements IComparisonOperators + implements IConvertible + implements IEqualityOperators + implements IEquatable + implements IFormattable + implements IParsable + implements IPlainValueObject + implements ISpanParsable + implements IValue + implements IValueObject + implements IValueObjectMaterializer + nested ToStringOverloadedByArityJsonConverter : JsonConverter, IStoredJsonConverterSource + nested ToStringOverloadedByArityTypeConverter : TypeConverter + new() + static From(String) : ToStringOverloadedByArity + static Parse(ReadOnlySpan, IFormatProvider) : ToStringOverloadedByArity + static Parse(String, IFormatProvider) : ToStringOverloadedByArity + static TryParse(ReadOnlySpan, IFormatProvider, out ToStringOverloadedByArity) : Boolean + static TryParse(String, IFormatProvider, out ToStringOverloadedByArity) : Boolean + static op_Equality(ToStringOverloadedByArity, ToStringOverloadedByArity) : Boolean + static op_GreaterThan(ToStringOverloadedByArity, ToStringOverloadedByArity) : Boolean + static op_GreaterThanOrEqual(ToStringOverloadedByArity, ToStringOverloadedByArity) : Boolean + static op_Inequality(ToStringOverloadedByArity, ToStringOverloadedByArity) : Boolean + static op_LessThan(ToStringOverloadedByArity, ToStringOverloadedByArity) : Boolean + static op_LessThanOrEqual(ToStringOverloadedByArity, ToStringOverloadedByArity) : Boolean + extension static ToStringOverloadedByArityExtensions.GetValue(ToStringOverloadedByArity) : String + extension static ToStringOverloadedByArityExtensions.ValueOrNull(ToStringOverloadedByArity?) : String +TryFormatOverloaded + CompareTo(Object) : Int32 + CompareTo(TryFormatOverloaded) : Int32 + Equals(Object) : Boolean + Equals(TryFormatOverloaded) : Boolean + GetHashCode() : Int32 + ToString() : String + ToString(String, IFormatProvider) : String + TryFormat(Span, Int32, ReadOnlySpan, IFormatProvider) : Boolean + TryFormat(Span, out Int32, ReadOnlySpan, IFormatProvider) : Boolean + TryFormat(Span, Int32, ReadOnlySpan, IFormatProvider) : Boolean + TryFormat(Span, out Int32, ReadOnlySpan, IFormatProvider) : Boolean + TryFormat(Span, out Int32, ReadOnlySpan, IFormatProvider) : Boolean + Value : Int32 + attribute CompilerGeneratedAttribute + attribute GeneratedValueObjectAttribute + attribute JsonConverterAttribute + attribute TypeConverterAttribute + implements IComparable + implements IComparable + implements IComparisonOperators + implements IConvertible + implements IEqualityOperators + implements IEquatable + implements IFormattable + implements IMinMaxValue + implements IParsable + implements IPlainValueObject + implements ISpanFormattable + implements ISpanParsable + implements IUtf8SpanFormattable + implements IUtf8SpanParsable + implements IValue + implements IValueObject + implements IValueObjectMaterializer + nested TryFormatOverloadedJsonConverter : JsonConverter, IStoredJsonConverterSource + nested TryFormatOverloadedTypeConverter : TypeConverter + new() + static From(Int32) : TryFormatOverloaded + static MaxValue : TryFormatOverloaded + static MinValue : TryFormatOverloaded + static Parse(ReadOnlySpan, IFormatProvider) : TryFormatOverloaded + static Parse(ReadOnlySpan, IFormatProvider) : TryFormatOverloaded + static Parse(String, IFormatProvider) : TryFormatOverloaded + static TryParse(ReadOnlySpan, IFormatProvider, out TryFormatOverloaded) : Boolean + static TryParse(ReadOnlySpan, IFormatProvider, out TryFormatOverloaded) : Boolean + static TryParse(String, IFormatProvider, out TryFormatOverloaded) : Boolean + static op_Equality(TryFormatOverloaded, TryFormatOverloaded) : Boolean + static op_GreaterThan(TryFormatOverloaded, TryFormatOverloaded) : Boolean + static op_GreaterThanOrEqual(TryFormatOverloaded, TryFormatOverloaded) : Boolean + static op_Inequality(TryFormatOverloaded, TryFormatOverloaded) : Boolean + static op_LessThan(TryFormatOverloaded, TryFormatOverloaded) : Boolean + static op_LessThanOrEqual(TryFormatOverloaded, TryFormatOverloaded) : Boolean + extension static TryFormatOverloadedExtensions.GetValue(TryFormatOverloaded) : Int32 + extension static TryFormatOverloadedExtensions.ValueOrNull(TryFormatOverloaded?) : Int32? +TryFromOverloaded + CompareTo(Object) : Int32 + CompareTo(TryFromOverloaded) : Int32 + Equals(Object) : Boolean + Equals(TryFromOverloaded) : Boolean + GetHashCode() : Int32 + Revalidate() : Result + ToString() : String + ToString(String, IFormatProvider) : String + TryFormat(Span, out Int32, ReadOnlySpan, IFormatProvider) : Boolean + TryFormat(Span, out Int32, ReadOnlySpan, IFormatProvider) : Boolean + Value : Int32 + attribute CompilerGeneratedAttribute + attribute GeneratedValueObjectAttribute + attribute JsonConverterAttribute + attribute TypeConverterAttribute + implements IComparable + implements IComparable + implements IComparisonOperators + implements IConvertible + implements IEqualityOperators + implements IEquatable + implements IFormattable + implements IParsable + implements ISpanFormattable + implements ISpanParsable + implements IUtf8SpanFormattable + implements IUtf8SpanParsable + implements IValidatedValue + implements IValueObject + implements IValueObjectMaterializer + nested TryFromOverloadedJsonConverter : JsonConverter, IStoredJsonConverterSource + nested TryFromOverloadedTypeConverter : TypeConverter + new() + static Create(Int32) : Result + static FromKnownGood(Int32, String) : TryFromOverloaded + static Parse(ReadOnlySpan, IFormatProvider) : TryFromOverloaded + static Parse(ReadOnlySpan, IFormatProvider) : TryFromOverloaded + static Parse(String, IFormatProvider) : TryFromOverloaded + static TryFrom(Int32) : Option + static TryFrom(in Int32) : Option + static TryFrom(Int32) : Option + static TryParse(ReadOnlySpan, IFormatProvider, out TryFromOverloaded) : Boolean + static TryParse(ReadOnlySpan, IFormatProvider, out TryFromOverloaded) : Boolean + static TryParse(String, IFormatProvider, out TryFromOverloaded) : Boolean + static op_Equality(TryFromOverloaded, TryFromOverloaded) : Boolean + static op_GreaterThan(TryFromOverloaded, TryFromOverloaded) : Boolean + static op_GreaterThanOrEqual(TryFromOverloaded, TryFromOverloaded) : Boolean + static op_Inequality(TryFromOverloaded, TryFromOverloaded) : Boolean + static op_LessThan(TryFromOverloaded, TryFromOverloaded) : Boolean + static op_LessThanOrEqual(TryFromOverloaded, TryFromOverloaded) : Boolean + extension static TryFromOverloadedExtensions.GetValue(TryFromOverloaded) : Int32 + extension static TryFromOverloadedExtensions.ValueOrNull(TryFromOverloaded?) : Int32? +TryParseOverloadedByArity + CompareTo(Object) : Int32 + CompareTo(TryParseOverloadedByArity) : Int32 + Equals(Object) : Boolean + Equals(TryParseOverloadedByArity) : Boolean + GetHashCode() : Int32 + ToString() : String + ToString(String, IFormatProvider) : String + TryFormat(Span, out Int32, ReadOnlySpan, IFormatProvider) : Boolean + TryFormat(Span, out Int32, ReadOnlySpan, IFormatProvider) : Boolean + Value : Int32 + attribute CompilerGeneratedAttribute + attribute GeneratedValueObjectAttribute + attribute JsonConverterAttribute + attribute TypeConverterAttribute + implements IComparable + implements IComparable + implements IComparisonOperators + implements IConvertible + implements IEqualityOperators + implements IEquatable + implements IFormattable + implements IMinMaxValue + implements IParsable + implements IPlainValueObject + implements ISpanFormattable + implements ISpanParsable + implements IUtf8SpanFormattable + implements IUtf8SpanParsable + implements IValue + implements IValueObject + implements IValueObjectMaterializer + nested TryParseOverloadedByArityJsonConverter : JsonConverter, IStoredJsonConverterSource + nested TryParseOverloadedByArityTypeConverter : TypeConverter + new() + static From(Int32) : TryParseOverloadedByArity + static MaxValue : TryParseOverloadedByArity + static MinValue : TryParseOverloadedByArity + static Parse(ReadOnlySpan, IFormatProvider) : TryParseOverloadedByArity + static Parse(ReadOnlySpan, IFormatProvider) : TryParseOverloadedByArity + static Parse(String, IFormatProvider) : TryParseOverloadedByArity + static TryParse(ReadOnlySpan, IFormatProvider, out TryParseOverloadedByArity) : Boolean + static TryParse(ReadOnlySpan, IFormatProvider, out TryParseOverloadedByArity) : Boolean + static TryParse(String, IFormatProvider, out TryParseOverloadedByArity) : Boolean + static TryParse(String, IFormatProvider, out TryParseOverloadedByArity) : Boolean + static op_Equality(TryParseOverloadedByArity, TryParseOverloadedByArity) : Boolean + static op_GreaterThan(TryParseOverloadedByArity, TryParseOverloadedByArity) : Boolean + static op_GreaterThanOrEqual(TryParseOverloadedByArity, TryParseOverloadedByArity) : Boolean + static op_Inequality(TryParseOverloadedByArity, TryParseOverloadedByArity) : Boolean + static op_LessThan(TryParseOverloadedByArity, TryParseOverloadedByArity) : Boolean + static op_LessThanOrEqual(TryParseOverloadedByArity, TryParseOverloadedByArity) : Boolean + extension static TryParseOverloadedByArityExtensions.GetValue(TryParseOverloadedByArity) : Int32 + extension static TryParseOverloadedByArityExtensions.ValueOrNull(TryParseOverloadedByArity?) : Int32? +TryParseOverloadedByValue + CompareTo(Object) : Int32 + CompareTo(TryParseOverloadedByValue) : Int32 + Equals(Object) : Boolean + Equals(TryParseOverloadedByValue) : Boolean + GetHashCode() : Int32 + ToString() : String + ToString(String, IFormatProvider) : String + TryFormat(Span, out Int32, ReadOnlySpan, IFormatProvider) : Boolean + TryFormat(Span, out Int32, ReadOnlySpan, IFormatProvider) : Boolean + Value : Int32 + attribute CompilerGeneratedAttribute + attribute GeneratedValueObjectAttribute + attribute JsonConverterAttribute + attribute TypeConverterAttribute + implements IComparable + implements IComparable + implements IComparisonOperators + implements IConvertible + implements IEqualityOperators + implements IEquatable + implements IFormattable + implements IMinMaxValue + implements IParsable + implements IPlainValueObject + implements ISpanFormattable + implements ISpanParsable + implements IUtf8SpanFormattable + implements IUtf8SpanParsable + implements IValue + implements IValueObject + implements IValueObjectMaterializer + nested TryParseOverloadedByValueJsonConverter : JsonConverter, IStoredJsonConverterSource + nested TryParseOverloadedByValueTypeConverter : TypeConverter + new() + static From(Int32) : TryParseOverloadedByValue + static MaxValue : TryParseOverloadedByValue + static MinValue : TryParseOverloadedByValue + static Parse(ReadOnlySpan, IFormatProvider) : TryParseOverloadedByValue + static Parse(ReadOnlySpan, IFormatProvider) : TryParseOverloadedByValue + static Parse(String, IFormatProvider) : TryParseOverloadedByValue + static TryParse(ReadOnlySpan, IFormatProvider, out TryParseOverloadedByValue) : Boolean + static TryParse(ReadOnlySpan, IFormatProvider, out TryParseOverloadedByValue) : Boolean + static TryParse(String, IFormatProvider, TryParseOverloadedByValue) : Boolean + static TryParse(String, IFormatProvider, out TryParseOverloadedByValue) : Boolean + static op_Equality(TryParseOverloadedByValue, TryParseOverloadedByValue) : Boolean + static op_GreaterThan(TryParseOverloadedByValue, TryParseOverloadedByValue) : Boolean + static op_GreaterThanOrEqual(TryParseOverloadedByValue, TryParseOverloadedByValue) : Boolean + static op_Inequality(TryParseOverloadedByValue, TryParseOverloadedByValue) : Boolean + static op_LessThan(TryParseOverloadedByValue, TryParseOverloadedByValue) : Boolean + static op_LessThanOrEqual(TryParseOverloadedByValue, TryParseOverloadedByValue) : Boolean + extension static TryParseOverloadedByValueExtensions.GetValue(TryParseOverloadedByValue) : Int32 + extension static TryParseOverloadedByValueExtensions.ValueOrNull(TryParseOverloadedByValue?) : Int32? +Utf8ParseOverloaded + CompareTo(Object) : Int32 + CompareTo(Utf8ParseOverloaded) : Int32 + Equals(Object) : Boolean + Equals(Utf8ParseOverloaded) : Boolean + GetHashCode() : Int32 + ToString() : String + ToString(String, IFormatProvider) : String + TryFormat(Span, out Int32, ReadOnlySpan, IFormatProvider) : Boolean + TryFormat(Span, out Int32, ReadOnlySpan, IFormatProvider) : Boolean + Value : Int32 + attribute CompilerGeneratedAttribute + attribute GeneratedValueObjectAttribute + attribute JsonConverterAttribute + attribute TypeConverterAttribute + implements IComparable + implements IComparable + implements IComparisonOperators + implements IConvertible + implements IEqualityOperators + implements IEquatable + implements IFormattable + implements IMinMaxValue + implements IParsable + implements IPlainValueObject + implements ISpanFormattable + implements ISpanParsable + implements IUtf8SpanFormattable + implements IUtf8SpanParsable + implements IValue + implements IValueObject + implements IValueObjectMaterializer + nested Utf8ParseOverloadedJsonConverter : JsonConverter, IStoredJsonConverterSource + nested Utf8ParseOverloadedTypeConverter : TypeConverter + new() + static From(Int32) : Utf8ParseOverloaded + static MaxValue : Utf8ParseOverloaded + static MinValue : Utf8ParseOverloaded + static Parse(ReadOnlySpan, IFormatProvider) : Utf8ParseOverloaded + static Parse(ReadOnlySpan, IFormatProvider) : Utf8ParseOverloaded + static Parse(String, IFormatProvider) : Utf8ParseOverloaded + static Parse(ReadOnlySpan, IFormatProvider) : Utf8ParseOverloaded + static TryParse(ReadOnlySpan, IFormatProvider, Utf8ParseOverloaded) : Boolean + static TryParse(ReadOnlySpan, IFormatProvider, out Utf8ParseOverloaded) : Boolean + static TryParse(ReadOnlySpan, IFormatProvider, out Utf8ParseOverloaded) : Boolean + static TryParse(String, IFormatProvider, out Utf8ParseOverloaded) : Boolean + static op_Equality(Utf8ParseOverloaded, Utf8ParseOverloaded) : Boolean + static op_GreaterThan(Utf8ParseOverloaded, Utf8ParseOverloaded) : Boolean + static op_GreaterThanOrEqual(Utf8ParseOverloaded, Utf8ParseOverloaded) : Boolean + static op_Inequality(Utf8ParseOverloaded, Utf8ParseOverloaded) : Boolean + static op_LessThan(Utf8ParseOverloaded, Utf8ParseOverloaded) : Boolean + static op_LessThanOrEqual(Utf8ParseOverloaded, Utf8ParseOverloaded) : Boolean + extension static Utf8ParseOverloadedExtensions.GetValue(Utf8ParseOverloaded) : Int32 + extension static Utf8ParseOverloadedExtensions.ValueOrNull(Utf8ParseOverloaded?) : Int32? +ValidatedOverASeamOverloadingBase + $() : ValidatedOverASeamOverloadingBase + CompareTo(Object) : Int32 + CompareTo(ValidatedOverASeamOverloadingBase) : Int32 + Equals(Object) : Boolean + Equals(SeamOverloadingBase) : Boolean + Equals(ValidatedOverASeamOverloadingBase) : Boolean + GetHashCode() : Int32 + Revalidate() : Result + ToString() : String + ToString(String, IFormatProvider) : String + TryFormat(Span, out Int32, ReadOnlySpan, IFormatProvider) : Boolean + TryFormat(Span, out Int32, ReadOnlySpan, IFormatProvider) : Boolean + Value : Int32 + attribute CompilerGeneratedAttribute + attribute GeneratedValueObjectAttribute + attribute JsonConverterAttribute + attribute TypeConverterAttribute + implements IComparable + implements IComparable + implements IComparisonOperators + implements IConvertible + implements IEqualityOperators + implements IEquatable> + implements IEquatable + implements IFormattable + implements IParsable + implements IReimplementedEquatable> + implements ISpanFormattable + implements ISpanParsable + implements IUtf8SpanFormattable + implements IUtf8SpanParsable + implements IValidatedValue + implements IValueObject + implements IValueObjectMaterializer + nested ValidatedOverASeamOverloadingBaseJsonConverter : JsonConverter, IStoredJsonConverterSource + nested ValidatedOverASeamOverloadingBaseTypeConverter : TypeConverter + static Create(Int32) : Result + static FromKnownGood(Int32, String) : ValidatedOverASeamOverloadingBase + static Parse(ReadOnlySpan, IFormatProvider) : ValidatedOverASeamOverloadingBase + static Parse(ReadOnlySpan, IFormatProvider) : ValidatedOverASeamOverloadingBase + static Parse(String, IFormatProvider) : ValidatedOverASeamOverloadingBase + static TryFrom(Int32) : Option + static TryParse(ReadOnlySpan, IFormatProvider, out ValidatedOverASeamOverloadingBase) : Boolean + static TryParse(ReadOnlySpan, IFormatProvider, out ValidatedOverASeamOverloadingBase) : Boolean + static TryParse(String, IFormatProvider, out ValidatedOverASeamOverloadingBase) : Boolean + static op_Equality(ValidatedOverASeamOverloadingBase, ValidatedOverASeamOverloadingBase) : Boolean + static op_GreaterThan(ValidatedOverASeamOverloadingBase, ValidatedOverASeamOverloadingBase) : Boolean + static op_GreaterThanOrEqual(ValidatedOverASeamOverloadingBase, ValidatedOverASeamOverloadingBase) : Boolean + static op_Inequality(ValidatedOverASeamOverloadingBase, ValidatedOverASeamOverloadingBase) : Boolean + static op_LessThan(ValidatedOverASeamOverloadingBase, ValidatedOverASeamOverloadingBase) : Boolean + static op_LessThanOrEqual(ValidatedOverASeamOverloadingBase, ValidatedOverASeamOverloadingBase) : Boolean + extension static ValidatedOverASeamOverloadingBaseExtensions.GetValue(ValidatedOverASeamOverloadingBase) : Int32 + extension static ValidatedOverASeamOverloadingBaseExtensions.ValueOrNull(ValidatedOverASeamOverloadingBase) : Int32? diff --git a/test/CodoMetis.TypeKit.Generators.Tests/GeneratedSurfaceTests.cs b/test/CodoMetis.TypeKit.Generators.Tests/GeneratedSurfaceTests.cs index 391ccc8..cac93cc 100644 --- a/test/CodoMetis.TypeKit.Generators.Tests/GeneratedSurfaceTests.cs +++ b/test/CodoMetis.TypeKit.Generators.Tests/GeneratedSurfaceTests.cs @@ -104,7 +104,7 @@ private static IEnumerable Members(Type type) yield return $"{Static(property.GetMethod!)}{property.Name} : {Display(property.PropertyType)}"; foreach (var method in type.GetMethods(flags).Where(method => !method.IsSpecialName || method.Name.StartsWith("op_", StringComparison.Ordinal))) - yield return $"{Static(method)}{method.Name}({Parameters(method)}) : {Display(method.ReturnType)}"; + yield return $"{Static(method)}{method.Name}{TypeParameters(method)}({Parameters(method)}) : {Display(method.ReturnType)}"; } /// @@ -116,8 +116,18 @@ private static bool IsDeclared(CustomAttributeData attribute) => private static string Static(MethodBase method) => method.IsStatic ? "static " : ""; + /// + /// A generic method's type parameters, and each parameter's ref kind: a hand-written overload that differs from a + /// generated member only by these sits beside it (#226), and the two read as one line without them. + /// + private static string TypeParameters(MethodInfo method) => + method.IsGenericMethodDefinition ? $"<{string.Join(", ", method.GetGenericArguments().Select(Display))}>" : ""; + private static string Parameters(MethodBase method) => - string.Join(", ", method.GetParameters().Select(parameter => (parameter.IsOut ? "out " : "") + Display(parameter.ParameterType))); + string.Join(", ", method.GetParameters().Select(parameter => RefKind(parameter) + Display(parameter.ParameterType))); + + private static string RefKind(ParameterInfo parameter) => + !parameter.ParameterType.IsByRef ? "" : parameter.IsOut ? "out " : parameter.IsIn ? "in " : "ref "; private static string Display(Type type) { diff --git a/test/CodoMetis.TypeKit.Generators.Tests/OverloadTests.cs b/test/CodoMetis.TypeKit.Generators.Tests/OverloadTests.cs new file mode 100644 index 0000000..29b6cce --- /dev/null +++ b/test/CodoMetis.TypeKit.Generators.Tests/OverloadTests.cs @@ -0,0 +1,451 @@ +using System.Text; +using CodoMetis.TypeKit.ClosedSets; +using CodoMetis.TypeKit.Generators.Probes; +using CodoMetis.TypeKit.ValueObjects; + +namespace CodoMetis.TypeKit.Generators.Tests; + +// What a value object or a closed set declares beside a generated member: a method of the same name and +// parameter types that C# still tells apart, by its type parameters or by a parameter's ref kind. Each was +// refused as the generated member written by hand (CMTK1011, #226); each is another method, and the generated +// one sits beside it. A ref kind against out (ref, in), and nullability, are no overload, and stay refused +// (BuildOutcomeTests). Every hand-written overload here throws, so a call that reached one fails. + +/// Picks a hand-written generic overload. +public sealed class OverloadFormat; + +/// A generic From. +public readonly partial record struct FromOverloadedByArity : IValue +{ + /// Hand-written. + public static FromOverloadedByArity From(int value) => throw new NotSupportedException("hand-written"); +} + +/// A From by in. +public readonly partial record struct FromOverloadedByIn : IValue +{ + /// Hand-written. + public static FromOverloadedByIn From(in int value) => throw new NotSupportedException("hand-written"); +} + +/// A From by ref. +public readonly partial record struct FromOverloadedByRef : IValue +{ + /// Hand-written. + public static FromOverloadedByRef From(ref int value) => throw new NotSupportedException("hand-written"); +} + +/// A generic Parse over text, the issue's scenario. +public readonly partial record struct ParseOverloadedByArity : IValue +{ + /// Hand-written. + public static ParseOverloadedByArity Parse(string text, IFormatProvider? provider) where TFormat : class => throw new NotSupportedException("hand-written"); +} + +/// A generic TryParse over text. +public readonly partial record struct TryParseOverloadedByArity : IValue +{ + /// Hand-written. + public static bool TryParse(string? text, IFormatProvider? provider, out TryParseOverloadedByArity result) => throw new NotSupportedException("hand-written"); +} + +/// A TryParse over text whose last parameter is by value. +public readonly partial record struct TryParseOverloadedByValue : IValue +{ + /// Hand-written. + public static bool TryParse(string? text, IFormatProvider? provider, TryParseOverloadedByValue fallback) => throw new NotSupportedException("hand-written"); +} + +/// A generic Parse and a by-value TryParse over a span. +public readonly partial record struct SpanParseOverloaded : IValue +{ + /// Hand-written. + public static SpanParseOverloaded Parse(ReadOnlySpan text, IFormatProvider? provider) => throw new NotSupportedException("hand-written"); + + /// Hand-written. + public static bool TryParse(ReadOnlySpan text, IFormatProvider? provider, SpanParseOverloaded fallback) => throw new NotSupportedException("hand-written"); +} + +/// A generic Parse and a by-value TryParse over UTF-8. +public readonly partial record struct Utf8ParseOverloaded : IValue +{ + /// Hand-written. + public static Utf8ParseOverloaded Parse(ReadOnlySpan text, IFormatProvider? provider) => throw new NotSupportedException("hand-written"); + + /// Hand-written. + public static bool TryParse(ReadOnlySpan text, IFormatProvider? provider, Utf8ParseOverloaded fallback) => throw new NotSupportedException("hand-written"); +} + +/// A generic ToString(string?, IFormatProvider?). +public readonly partial record struct FormatOverloadedByArity : IValue +{ + /// Hand-written. + public string ToString(string? format, IFormatProvider? provider) => throw new NotSupportedException("hand-written"); +} + +/// A ToString(string?, IFormatProvider?) whose format is by in. +public readonly partial record struct FormatOverloadedByIn : IValue +{ + /// Hand-written. + public string ToString(in string? format, IFormatProvider? provider) => throw new NotSupportedException("hand-written"); +} + +/// A generic TryFormat, and one whose count is by value, for both the generated TryFormats. +public readonly partial record struct TryFormatOverloaded : IValue +{ + /// Hand-written. + public bool TryFormat(Span destination, out int charsWritten, ReadOnlySpan format, IFormatProvider? provider) => throw new NotSupportedException("hand-written"); + + /// Hand-written. + public bool TryFormat(Span destination, int charsWritten, ReadOnlySpan format, IFormatProvider? provider) => throw new NotSupportedException("hand-written"); + + /// Hand-written. + public bool TryFormat(Span destination, int bytesWritten, ReadOnlySpan format, IFormatProvider? provider) => throw new NotSupportedException("hand-written"); +} + +/// A record class with a generic Parse. +public sealed partial record ParseOverloadedInARecordClass : IValue +{ + /// Hand-written. + public static ParseOverloadedInARecordClass Parse(string text, IFormatProvider? provider) => throw new NotSupportedException("hand-written"); +} + +/// A base record in this assembly whose methods are overloads of the generated ones. +public abstract record OverloadingBase +{ + /// Hand-written. + public static TSelf From(int value) => throw new NotSupportedException("hand-written"); + + /// Hand-written. + public static TSelf From(in int value) => throw new NotSupportedException("hand-written"); + + /// Hand-written. + public static TSelf Parse(string text, IFormatProvider? provider) => throw new NotSupportedException("hand-written"); + + /// Hand-written. + public static bool TryParse(string? text, IFormatProvider? provider, TSelf fallback) => throw new NotSupportedException("hand-written"); + + /// Hand-written. + public static TSelf Parse(ReadOnlySpan text, IFormatProvider? provider) => throw new NotSupportedException("hand-written"); + + /// Hand-written. + public static bool TryParse(ReadOnlySpan text, IFormatProvider? provider, TSelf fallback) => throw new NotSupportedException("hand-written"); + + /// Hand-written. + public string ToString(string? format, IFormatProvider? provider) => throw new NotSupportedException("hand-written"); + + /// Hand-written. + public bool TryFormat(Span destination, out int charsWritten, ReadOnlySpan format, IFormatProvider? provider) => throw new NotSupportedException("hand-written"); +} + +/// Over a base record in this assembly with an overload of each generated member. +public sealed partial record OverAnOverloadingBase : OverloadingBase, IValue; + +/// Over a base record in another assembly with overloads of Parse, From and TryParse. +public sealed partial record OverALibraryOverloadingBase : ProbeOverloadingRecord, IValue; + +/// A closed set with a generic Parse of each form, a generic TryParse, and by-value ones. +public sealed partial class OverloadingSet : IClosedSet +{ + /// The first member. + public static readonly OverloadingSet First = new(); + + /// The second member. + public static readonly OverloadingSet Second = new(); + + /// Hand-written. + public static OverloadingSet Parse(string name) => throw new NotSupportedException("hand-written"); + + /// Hand-written. + public static OverloadingSet Parse(string name, bool ignoreCase) => throw new NotSupportedException("hand-written"); + + /// Hand-written. + public static bool TryParse(string? name, out OverloadingSet member) => throw new NotSupportedException("hand-written"); + + /// Hand-written. + public static bool TryParse(string? name, OverloadingSet fallback) => throw new NotSupportedException("hand-written"); + + /// Hand-written. + public static bool TryParse(string? name, bool ignoreCase, OverloadingSet fallback) => throw new NotSupportedException("hand-written"); +} + +/// A base class of a closed set whose Parse and TryParse are overloads of the generated ones. +public abstract class OverloadingSetBase +{ + /// Hand-written. + public static TSelf Parse(string name) => throw new NotSupportedException("hand-written"); + + /// Hand-written. + public static bool TryParse(string? name, bool ignoreCase, TSelf fallback) => throw new NotSupportedException("hand-written"); +} + +/// A closed set over a base class with overloads of the generated Parse and TryParse. +public sealed partial class SetOverAnOverloadingBase : OverloadingSetBase, IClosedSet +{ + /// The first member. + public static readonly SetOverAnOverloadingBase First = new(); + + /// The second member. + public static readonly SetOverAnOverloadingBase Second = new(); +} + +// The seams and the members a record synthesizes, by the same rule: a generic or by-reference overload of +// ToString(), CompareTo, TryFrom, Revalidate, Equals, GetHashCode or PrintMembers is another method. A generic +// ToString() was taken for the seam, and the value object printed what a record prints; a generic or by-in +// CompareTo(TSelf) for the ordering seam, which marks the ordering hand-written; the rest were refused. + +/// A fault for the validated value objects below. +public enum OverloadFault +{ + /// Below zero. + Negative +} + +/// A generic ToString(), which is no seam. +public readonly partial record struct ToStringOverloadedByArity : IValue +{ + /// Hand-written. + public string ToString() => throw new NotSupportedException("hand-written"); +} + +/// A generic CompareTo(TSelf), which is no seam. +public readonly partial record struct CompareToOverloadedByArity : IValue +{ + /// Hand-written. + public int CompareTo(CompareToOverloadedByArity other) => throw new NotSupportedException("hand-written"); +} + +/// A CompareTo(TSelf) by in, which is no seam. +public readonly partial record struct CompareToOverloadedByIn : IValue +{ + /// Hand-written. + public int CompareTo(in CompareToOverloadedByIn other) => throw new NotSupportedException("hand-written"); +} + +/// A generic CompareTo(object?) and one by in. +public readonly partial record struct ObjectCompareToOverloaded : IValue +{ + /// Hand-written. + public int CompareTo(object? other) => throw new NotSupportedException("hand-written"); + + /// Hand-written. + public int CompareTo(in object? other) => throw new NotSupportedException("hand-written"); +} + +/// A generic Equals(TSelf) and GetHashCode(), which are not its equality. +public readonly partial record struct EqualityOverloadedByArity : IValue +{ + /// Hand-written. + public bool Equals(EqualityOverloadedByArity other) => throw new NotSupportedException("hand-written"); + + /// Hand-written. + public int GetHashCode() => throw new NotSupportedException("hand-written"); +} + +/// A record class with a generic PrintMembers, which its synthesized ToString() never calls. +public sealed partial record PrintMembersOverloadedByArity : IValue +{ + /// Hand-written. + public bool PrintMembers(StringBuilder builder) => throw new NotSupportedException("hand-written"); +} + +/// A generic TryFrom and one by in, beside the generated TryFrom(int). +public readonly partial record struct TryFromOverloaded : IValidatedValue +{ + /// Zero or more. + public static Result Create(int value) => value < 0 ? Result.Error(OverloadFault.Negative) : new TryFromOverloaded(value); + + /// Hand-written. + public static Option TryFrom(int value) => throw new NotSupportedException("hand-written"); + + /// Hand-written. + public static Option TryFrom(in int value) => throw new NotSupportedException("hand-written"); +} + +/// A base record whose seams, equality and ToString() are overloads of the generated ones. +public abstract record SeamOverloadingBase where TSelf : notnull +{ + /// Hand-written. + public static Option TryFrom(int value) => throw new NotSupportedException("hand-written"); + + /// Hand-written. + public static Option TryFrom(in int value) => throw new NotSupportedException("hand-written"); + + /// Hand-written. + public Result Revalidate() => throw new NotSupportedException("hand-written"); + + /// Hand-written. + public int CompareTo(object? other) => throw new NotSupportedException("hand-written"); + + /// Hand-written. + public int CompareTo(TSelf? other) => throw new NotSupportedException("hand-written"); + + /// Hand-written. + public string ToString() => throw new NotSupportedException("hand-written"); + + /// Hand-written. + public bool Equals(SeamOverloadingBase? other) => throw new NotSupportedException("hand-written"); + + /// Hand-written. + public int GetHashCode() => throw new NotSupportedException("hand-written"); +} + +/// A plain value object over a base record whose seams are overloads. +public sealed partial record PlainOverASeamOverloadingBase : SeamOverloadingBase, IValue; + +/// A validated value object over a base record whose TryFrom and Revalidate are overloads. +public sealed partial record ValidatedOverASeamOverloadingBase : SeamOverloadingBase, IValidatedValue +{ + /// Zero or more. + public static Result Create(int value) => value < 0 ? Result.Error(OverloadFault.Negative) : new ValidatedOverASeamOverloadingBase(value); +} + +// CMTK1023 names the base's equality, which the generated one does not call. +#pragma warning disable CMTK1023 +/// +/// Two levels above an explicit IEquatable by reference, with a generic Equals of that base's type: the +/// value object implements the base's interface again all the same, since the generic one implements nothing. +/// +public sealed partial record EqualsOverloadOverADeeperExplicitEquality : LocalBetweenRecord, IValue +{ + /// Hand-written. + public bool Equals(LocalExplicitEqualityRecord? other) => throw new NotSupportedException("hand-written"); +} +#pragma warning restore CMTK1023 + +/// A closed set with a generic ToString(), which is no seam. +public sealed partial class SetWithAGenericToString : IClosedSet +{ + /// The first member. + public static readonly SetWithAGenericToString First = new(); + + /// Hand-written. + public string ToString() => throw new NotSupportedException("hand-written"); +} + +/// +/// The generated members beside a hand-written overload of each, on the type, on a base record of this assembly +/// and of another, and on a closed set and its base class (#226). Refusals are build errors and live in +/// . +/// +public sealed class OverloadTests +{ + public static TheoryData, object> Generated => new() + { + { "From(int)", () => FromOverloadedByArity.From(7).Value, 7 }, + { "From(in int)", () => FromOverloadedByIn.From(7).Value, 7 }, + { "From(ref int)", () => FromOverloadedByRef.From(7).Value, 7 }, + { "Parse(string, IFormatProvider?)", () => ParseOverloadedByArity.Parse("7", null).Value, 7 }, + { "TryParse(string?, IFormatProvider?, out T)", () => TryParseOverloadedByArity.TryParse("7", null, out var parsed) ? parsed.Value : -1, 7 }, + { "TryParse(string?, IFormatProvider?, T)", () => TryParseOverloadedByValue.TryParse("7", null, out var parsed) ? parsed.Value : -1, 7 }, + { "Parse(ReadOnlySpan, IFormatProvider?)", () => SpanParseOverloaded.Parse("7".AsSpan(), null).Value, 7 }, + { "TryParse(ReadOnlySpan, IFormatProvider?, T)", () => SpanParseOverloaded.TryParse("7".AsSpan(), null, out var parsed) ? parsed.Value : -1, 7 }, + { "Parse(ReadOnlySpan, IFormatProvider?)", () => Utf8ParseOverloaded.Parse("7"u8, null).Value, 7 }, + { "TryParse(ReadOnlySpan, IFormatProvider?, T)", () => Utf8ParseOverloaded.TryParse("7"u8, null, out var parsed) ? parsed.Value : -1, 7 }, + { "IParsable.Parse beside Parse", () => ParseThroughInterface("7"), ParseOverloadedByArity.From(7) }, + { "ToString(string?, IFormatProvider?)", () => FormatOverloadedByArity.From(7).ToString("D3", null), "007" }, + { "ToString(in string?, IFormatProvider?)", () => FormatOverloadedByIn.From(7).ToString("D3", null), "007" }, + { "interpolation beside ToString(string?, IFormatProvider?)", () => $"{FormatOverloadedByArity.From(7):D3}", "007" }, + { "TryFormat(Span, out int, ...) and TryFormat(Span, int, ...)", () => Format(TryFormatOverloaded.From(7)), "007" }, + { "TryFormat(Span, int, ...)", () => FormatUtf8(TryFormatOverloaded.From(7)), "007" }, + { "a record class's Parse(string, IFormatProvider?)", () => ParseOverloadedInARecordClass.Parse("7", null).Value, 7 }, + { "a base record's From(int) and From(in int)", () => OverAnOverloadingBase.From(7).Value, 7 }, + { "a base record's Parse(string, IFormatProvider?)", () => OverAnOverloadingBase.Parse("7", null).Value, 7 }, + { "a base record's TryParse(string?, IFormatProvider?, T)", () => OverAnOverloadingBase.TryParse("7", null, out var parsed) ? parsed.Value : -1, 7 }, + { "a base record's Parse(ReadOnlySpan, IFormatProvider?)", () => OverAnOverloadingBase.Parse("7".AsSpan(), null).Value, 7 }, + { "a base record's TryParse(ReadOnlySpan, IFormatProvider?, T)", () => OverAnOverloadingBase.TryParse("7"u8, null, out var parsed) ? parsed.Value : -1, 7 }, + { "a base record's ToString(string?, IFormatProvider?)", () => OverAnOverloadingBase.From(7).ToString("D3", null), "007" }, + { "a base record's TryFormat(Span, out int, ...)", () => Format(OverAnOverloadingBase.From(7)), "007" }, + { "another assembly's From(in int)", () => OverALibraryOverloadingBase.From(7).Value, 7 }, + { "another assembly's Parse(string, IFormatProvider?)", () => OverALibraryOverloadingBase.Parse("7", null).Value, 7 }, + { "another assembly's TryParse(string?, IFormatProvider?, T)", () => OverALibraryOverloadingBase.TryParse("7", null, out var parsed) ? parsed.Value : -1, 7 }, + { "a set's Parse(string)", () => OverloadingSet.Parse("Second"), OverloadingSet.Second }, + { "a set's Parse(string, bool)", () => OverloadingSet.Parse("second", ignoreCase: true), OverloadingSet.Second }, + { "a set's TryParse(string?, out T) and TryParse(string?, T)", () => OverloadingSet.TryParse("Second", out var member) ? member : OverloadingSet.First, OverloadingSet.Second }, + { "a set's TryParse(string?, bool, T)", () => OverloadingSet.TryParse("second", ignoreCase: true, out var member) ? member : OverloadingSet.First, OverloadingSet.Second }, + { "a set's IParsable.Parse beside Parse(string)", () => ParseThroughInterface("Second"), OverloadingSet.Second }, + { "a set's base class's Parse(string)", () => SetOverAnOverloadingBase.Parse("Second"), SetOverAnOverloadingBase.Second }, + { "a set's base class's TryParse(string?, bool, T)", () => SetOverAnOverloadingBase.TryParse("second", ignoreCase: true, out var member) ? member : SetOverAnOverloadingBase.First, SetOverAnOverloadingBase.Second }, + { "ToString() beside ToString()", () => ToStringOverloadedByArity.From("a").ToString(), "a" }, + { "interpolation beside ToString()", () => $"{ToStringOverloadedByArity.From("a")}", "a" }, + { "CompareTo(T) beside CompareTo(T)", () => Math.Sign(CompareToOverloadedByArity.From(1).CompareTo(CompareToOverloadedByArity.From(2))), -1 }, + { "IComparable beside CompareTo(T)", () => Math.Sign(((IComparable)CompareToOverloadedByArity.From(1)).CompareTo(CompareToOverloadedByArity.From(2))), -1 }, + { "CompareTo(T) beside CompareTo(in T)", () => Math.Sign(CompareToOverloadedByIn.From(1).CompareTo(CompareToOverloadedByIn.From(2))), -1 }, + { "IComparable beside CompareTo(in T)", () => Math.Sign(((IComparable)CompareToOverloadedByIn.From(1)).CompareTo(CompareToOverloadedByIn.From(2))), -1 }, + { "CompareTo(object) beside CompareTo(object?) and CompareTo(in object?)", () => Math.Sign(((IComparable)ObjectCompareToOverloaded.From(1)).CompareTo(ObjectCompareToOverloaded.From(2))), -1 }, + { "< beside CompareTo(object?)", () => ObjectCompareToOverloaded.From(1) < ObjectCompareToOverloaded.From(2), true }, + { "Equals(T) beside Equals(T)", () => EqualityOverloadedByArity.From(1).Equals(EqualityOverloadedByArity.From(1)), true }, + { "GetHashCode() beside GetHashCode()", () => EqualityOverloadedByArity.From(1).GetHashCode() == EqualityOverloadedByArity.From(1).GetHashCode(), true }, + { "ToString() beside PrintMembers(StringBuilder)", () => PrintMembersOverloadedByArity.From(1).ToString(), "1" }, + { "TryFrom(int) beside TryFrom(int) and TryFrom(in int)", () => TryFromOverloaded.TryFrom(1).IsSome() && TryFromOverloaded.TryFrom(-1).IsNone(), true }, + { "a base record's TryFrom(int) and TryFrom(in int)", () => ValidatedOverASeamOverloadingBase.TryFrom(1).IsSome() && ValidatedOverASeamOverloadingBase.TryFrom(-1).IsNone(), true }, + { "a base record's Revalidate()", () => ValidatedOverASeamOverloadingBase.FromKnownGood(1).Revalidate().TryGetValue(out _, out _), true }, + { "a base record's CompareTo(object?) and CompareTo(TSelf?)", () => PlainOverASeamOverloadingBase.From(1) < PlainOverASeamOverloadingBase.From(2), true }, + { "a base record's ToString()", () => PlainOverASeamOverloadingBase.From(1).ToString(), "1" }, + { "a base record's Equals(TBase?) and GetHashCode()", () => new HashSet> { PlainOverASeamOverloadingBase.From(1), PlainOverASeamOverloadingBase.From(1) }.Count, 1 }, + { "a deeper base's IEquatable beside Equals(TBase?)", () => new HashSet { EqualsOverloadOverADeeperExplicitEquality.From(42), EqualsOverloadOverADeeperExplicitEquality.From(42) }.Count, 1 }, + { "a set's ToString() beside ToString()", () => $"{SetWithAGenericToString.First}", "First" }, + }; + + /// + /// Each generated member is there beside the hand-written overload, and a call that names neither type arguments + /// nor a ref kind reaches the generated one. + /// + [Theory] + [MemberData(nameof(Generated))] + public void The_generated_member_sits_beside_a_hand_written_overload(string overload, Func generated, object expected) => + generated().ShouldBe(expected, overload); + + public static TheoryData HandWritten => new() + { + { "From(int)", () => FromOverloadedByArity.From(7) }, + { "From(in int)", () => FromOverloadedByIn.From(in Seven) }, + { "Parse(string, IFormatProvider?)", () => ParseOverloadedByArity.Parse("7", null) }, + { "TryParse(string?, IFormatProvider?, T)", () => TryParseOverloadedByValue.TryParse("7", null, TryParseOverloadedByValue.From(1)) }, + { "ToString(string?, IFormatProvider?)", () => FormatOverloadedByArity.From(7).ToString("D3", null) }, + { "TryFormat(Span, int, ...)", () => TryFormatOverloaded.From(7).TryFormat(new char[8], 0, "", null) }, + { "a base record's Parse(string, IFormatProvider?)", () => OverAnOverloadingBase.Parse("7", null) }, + { "another assembly's From(in int)", () => OverALibraryOverloadingBase.From(in Seven) }, + { "a set's Parse(string)", () => OverloadingSet.Parse("Second") }, + { "a set's TryParse(string?, T)", () => OverloadingSet.TryParse("Second", OverloadingSet.First) }, + { "ToString()", () => ToStringOverloadedByArity.From("a").ToString() }, + { "CompareTo(in T)", () => CompareToOverloadedByIn.From(1).CompareTo(in OneByIn) }, + { "TryFrom(int)", () => _ = TryFromOverloaded.TryFrom(1) }, + { "a set's ToString()", () => SetWithAGenericToString.First.ToString() }, + }; + + /// The hand-written overload is kept, and a call that names its type arguments or its ref kind reaches it. + [Theory] + [MemberData(nameof(HandWritten))] + public void The_hand_written_overload_is_kept(string overload, Action handWritten) => + Should.Throw(handWritten, overload).Message.ShouldBe("hand-written"); + + public static TheoryData NotHandWrittenOrdering => [typeof(CompareToOverloadedByArity), typeof(CompareToOverloadedByIn), typeof(PlainOverASeamOverloadingBase)]; + + /// + /// A generic or by-in CompareTo(TSelf) is no seam, so the ordering is the generated one and is not marked + /// hand-written: the EF Core satellite refuses to order by a column whose value object is marked. + /// + [Theory] + [MemberData(nameof(NotHandWrittenOrdering))] + public void An_overload_of_CompareTo_does_not_mark_the_ordering_hand_written(Type type) => + type.IsDefined(typeof(CodoMetis.TypeKit.CompilerServices.HandWrittenOrderingAttribute), inherit: false).ShouldBeFalse(); + + private static readonly int Seven = 7; + + private static readonly CompareToOverloadedByIn OneByIn = CompareToOverloadedByIn.From(1); + + private static T ParseThroughInterface(string text) where T : IParsable => T.Parse(text, null); + + private static string Format(T value) where T : ISpanFormattable + { + Span buffer = stackalloc char[16]; + return value.TryFormat(buffer, out var written, "D3", null) ? new string(buffer[..written]) : ""; + } + + private static string FormatUtf8(T value) where T : IUtf8SpanFormattable + { + Span buffer = stackalloc byte[16]; + return value.TryFormat(buffer, out var written, "D3", null) ? Encoding.UTF8.GetString(buffer[..written]) : ""; + } +} diff --git a/test/oracles/claims.json b/test/oracles/claims.json index ded2e7f..41773fc 100644 --- a/test/oracles/claims.json +++ b/test/oracles/claims.json @@ -1280,6 +1280,50 @@ "BuildOutcomeTests" ] }, + { + "id": "C22-an-overload-in-a-closed-set", + "source": "src/CodoMetis.TypeKit.Generators/README.md#closed-sets", + "quote": "**An overload of a generated method with another signature**, such as `Parse(int rank)` or a generic `Parse(string name)`, is kept too.", + "claim": "A closed set's hand-written overload of Parse or TryParse with another signature, generic or by value where the generated one is out, is kept beside the generated one, in the set or its base class.", + "oracle": "claim", + "surfaces": [ + "IClosedSet.*" + ], + "heldBy": [ + "OverloadTests", + "BuildOutcomeTests" + ] + }, + { + "id": "C22-an-overload-of-a-generated-member", + "source": "src/CodoMetis.TypeKit.Generators/README.md#write-your-own-members", + "quote": "C# tells two methods apart by their type parameters and by whether a parameter is `ref`, `in` or `out`, so a `Parse(string, IFormatProvider?)`, a `From(in int value)` or a `TryParse` whose last parameter isn't `out` is kept, on the value object or a base record. A `ref` or `in` where the generated member has `out` is the same method to C#, as a different nullability is, so it fails the build like the member itself.", + "claim": "A hand-written overload of a generated member that differs by its type parameters or by a ref kind against a by-value parameter is kept beside the generated member, on the value object or a base record; ref or in against out, or another nullability, fails the build with CMTK1011.", + "oracle": "claim", + "surfaces": [ + "IPlainValueObject.*", + "IValidatedValue.*" + ], + "heldBy": [ + "OverloadTests", + "BuildOutcomeTests" + ] + }, + { + "id": "C22-an-overload-of-a-seam", + "source": "src/CodoMetis.TypeKit.Generators/README.md#write-your-own-members", + "quote": "The same goes for the members you may write: a generic `ToString()` or a `CompareTo(in TSelf)` isn't the one that's kept, so the generated `ToString()` and ordering are still there.", + "claim": "A generic or by-reference overload of ToString() or CompareTo(TSelf) is no seam: the generated ToString() and ordering are introduced beside it, and the ordering is not marked hand-written.", + "oracle": "claim", + "surfaces": [ + "IPlainValueObject.*", + "IValidatedValue.*", + "IClosedSet.*" + ], + "heldBy": [ + "OverloadTests" + ] + }, { "id": "C22-closed-set-named-as-generated-member", "source": "src/CodoMetis.TypeKit.Generators/README.md#build-errors",