diff --git a/BREAKING-CHANGES.md b/BREAKING-CHANGES.md index b6be1bfaa..9b693a182 100644 --- a/BREAKING-CHANGES.md +++ b/BREAKING-CHANGES.md @@ -58,6 +58,7 @@ read first. | loud | the target frameworks | `net7.0;netstandard2.0` | `netstandard2.0;net8.0;net10.0` | | **silent** | `abs(x) = c` for a negative `c` | a set of non-solutions | the empty set | | loud | implicit `List` to `Entity` | made a `FiniteSet`, and made three `params` overloads uncallable | removed | +| loud | implicit `Entity[]` to `Entity` | made a `FiniteSet`, discarding order and repeats | removed | | **silent** | a `MathS.Settings` scope across an `await`, or inside a task | lost, or somebody else's | follows the call | --- @@ -101,12 +102,12 @@ the built assemblies: present in `net8.0` and `net10.0`, absent from `netstandar ## Types and members -### The implicit conversion from `List` is removed +### The implicit conversions from a collection are removed `Entity` had two implicit conversions from a collection, both building a `FiniteSet`: ```csharp -public static implicit operator Entity(Entity[] elements); +public static implicit operator Entity(Entity[] elements); // removed public static implicit operator Entity(List elements); // removed ``` @@ -144,12 +145,24 @@ Write one of these instead: ```csharp Entity set = new FiniteSet(new List { 1, 2, 3 }); Entity set = new List { 1, 2, 3 }.ToSet(); -Entity set = new Entity[] { 1, 2, 3 }; // the array conversion is unchanged ``` -The `Entity[]` conversion is kept: an array argument binds to the `params` overload in its normal -form by an identity conversion, which beats the alternatives outright, so it never produced the -ambiguity. +**The conversion from `Entity[]` is gone as well.** It was kept at first, on the narrow +ground that it never produced the ambiguity — an array binds to the `params` overload in its +normal form by an identity conversion, which wins outright. That was true and beside the +point. An array carries an order and can repeat an element; a set has neither, so the +conversion silently discarded part of what it was handed, and an implicit conversion that +loses information is the wrong shape regardless of which overloads it happens to break. +Set types are built explicitly nearly everywhere for this reason. + +```csharp +Entity set = new Entity[] { 1, 2, 3 }; // no longer compiles either +Entity set = new FiniteSet(1, 2, 3); // say it +Entity set = new Entity[] { 1, 2, 3 }.ToSet(); +``` + +Only one place in the whole repository relied on it, which was the test pinning it. + ### A settings scope belongs to the call, not to the thread `MathS.Settings` values were held in `[ThreadStatic]` fields — fourteen of them. A scope diff --git a/Sources/AngouriMath/Core/Entity/Omni/Entity.Set.cs b/Sources/AngouriMath/Core/Entity/Omni/Entity.Set.cs index ba2bb62c9..2a266bba2 100644 --- a/Sources/AngouriMath/Core/Entity/Omni/Entity.Set.cs +++ b/Sources/AngouriMath/Core/Entity/Omni/Entity.Set.cs @@ -82,7 +82,6 @@ public bool Contains(Entity entity) #pragma warning disable CS1591 public static implicit operator Entity(Domain domain) => Set.SpecialSet.Create(domain); public static implicit operator Entity((Entity left, Entity right) interval) => new Interval(interval.left, true, interval.right, true); - public static implicit operator Entity(Entity[] elements) => new FiniteSet(elements); #pragma warning restore CS1591 } diff --git a/Sources/Tests/UnitTests/Common/ListArgumentOverloadTest.cs b/Sources/Tests/UnitTests/Common/ListArgumentOverloadTest.cs index cb6854b17..ec111f9df 100644 --- a/Sources/Tests/UnitTests/Common/ListArgumentOverloadTest.cs +++ b/Sources/Tests/UnitTests/Common/ListArgumentOverloadTest.cs @@ -8,6 +8,7 @@ using System.Collections.Generic; using AngouriMath; using AngouriMath.Core; +using AngouriMath.Extensions; using Xunit; namespace AngouriMath.Tests.Common @@ -59,14 +60,21 @@ public void ArrayAndVariadicFormsStillBind() } /// - /// The conversion from an array is deliberately kept, so an array in an - /// Entity position is still a set. + /// An array in an Entity position is no longer a set. Both conversions are + /// gone: an array carries an order and repeats, a set has neither, so the conversion + /// silently discarded part of what it was handed — and it is the one that made the + /// overloads above ambiguous in the first place. Building a set says so instead. /// + /// + /// This compiling is what says the conversion has not come back; the assertion is + /// only that the explicit forms mean what they used to. + /// [Fact] - public void ArrayStillConvertsToASet() + public void AnArrayIsBuiltIntoASetExplicitly() { - Entity set = new Entity[] { 1, 2, 3 }; - Assert.Equal(new Entity.Set.FiniteSet(1, 2, 3), set); + var elements = new Entity[] { 1, 2, 3 }; + Assert.Equal(new Entity.Set.FiniteSet(1, 2, 3), new Entity.Set.FiniteSet(elements)); + Assert.Equal(new Entity.Set.FiniteSet(1, 2, 3), elements.ToSet()); } } } diff --git a/Sources/Tests/UnitTests/Common/PublicApi.txt b/Sources/Tests/UnitTests/Common/PublicApi.txt index 33e85f487..60378c567 100644 --- a/Sources/Tests/UnitTests/Common/PublicApi.txt +++ b/Sources/Tests/UnitTests/Common/PublicApi.txt @@ -2126,7 +2126,6 @@ AngouriMath.Entity.op_ExclusiveOr(AngouriMath.Entity, AngouriMath.Entity) : Ango AngouriMath.Entity.op_GreaterThan(AngouriMath.Entity, AngouriMath.Entity) : AngouriMath.Entity AngouriMath.Entity.op_GreaterThanOrEqual(AngouriMath.Entity, AngouriMath.Entity) : AngouriMath.Entity AngouriMath.Entity.op_Implicit(AngouriMath.Core.Domain) : AngouriMath.Entity -AngouriMath.Entity.op_Implicit(AngouriMath.Entity[]) : AngouriMath.Entity AngouriMath.Entity.op_Implicit(PeterO.Numbers.EDecimal) : AngouriMath.Entity AngouriMath.Entity.op_Implicit(PeterO.Numbers.EInteger) : AngouriMath.Entity AngouriMath.Entity.op_Implicit(PeterO.Numbers.ERational) : AngouriMath.Entity