#pragma warning disable 168 using System; using System.Collections; using System.Reflection; namespace LibA { extension LibA1 : IDisposable { public void Dispose() { } public static int operator<=>(Self lhs, Self rhs) { return 0; } } } namespace Tests { class Generics { struct StructA : IDisposable { int mA = 123; public void Dispose() { } } class ClassA : IDisposable, LibA.IVal { int LibA.IVal.Val { get { return 123; } set { } } void IDisposable.Dispose() { } } class ClassB : IDisposable, LibA.IVal { public int Val { get { return 234; } set { } } public void Dispose() { } } class Singleton where T : Singleton { public static T mInstance; protected this() { mInstance = (T)this; } } class ClassC : Singleton { } class ClassD { public static int operator<=>(Self lhs, Self rhs) { return 0; } } static void DoDispose(mut T val) where T : IDisposable { val.Dispose(); } struct Disposer { static void UseDispose(IDisposable disp) { } static void DoDisposeA(mut T val) where T : IDisposable { val.Dispose(); UseDispose(val); } static void DoDisposeB(mut T val) where T : IDisposable { val.Dispose(); } } [Test] public static void TestGenericDelegates() { delegate void(String v) dlg = scope => StrMethod; CallGenericDelegate(dlg); CallGenericDelegate(scope => StrMethod); } public static void CallGenericDelegate(delegate void(T v) dlg) { } public static void StrMethod(String v) { } public static int MethodA(T val) where T : var { return 1; } public static int MethodA(T val) where T : struct { return 2; } public static int MethodA(T val) where T : enum { int val2 = (int)val; T val3 = 0; return 3; } public static int MethodA(T val) where T : interface { return 4; } public struct Entry { public static int operator<=>(Entry lhs, Entry rhs) { return 0; } } public static void Alloc0() where T : new, delete, IDisposable { alloctype(T) val = new T(); val.Dispose(); delete val; } public static void Alloc1() where T : new, delete, IDisposable, Object { alloctype(T) val = new T(); T val2 = val; val.Dispose(); delete val; } public static void Alloc2() where T : new, IDisposable, struct { alloctype(T) val = new T(); T* val2 = val; val2.Dispose(); delete val; } public static void Alloc3() where T : new, IDisposable, struct* { T val2 = default; if (val2 != null) val2.Dispose(); delete val2; } public class ClassE { public static Self Instance = new ClassE() ~ delete _; public int CreateSystem() { return 999; } } public void TestCast(T val) where T : class where TI : interface { TI iface = val as TI; } public void MethodA(List list) { } public void MethodA(Span list) { } public void MethodB() { List list = null; MethodA(list); } public static void MethodC() { } public static void MethodD(delegate void() dlg) { } public static void MethodD(delegate void(T1) dlg) { } static T2 MethodE(T val) where T : concrete, IEnumerable where T2 : operator T2 + T2 { T2 total = default; for (var v in val) { total += v; } return total; } static int MethodF(IEnumerable val) { return 0; } static void MethodG() where T : TBase { T val = default; TBase valBase = val; } public static TResult Sum(this T it, TDlg dlg) where T: concrete, IEnumerable where TDlg: delegate TResult(TElem) where TResult: operator TResult + TResult { var result = default(TResult); for(var elem in it) result += dlg(elem); return result; } struct DoublingEnumerator : IEnumerator where TElem : operator TElem + TElem where TEnum : concrete, IEnumerator { TEnum mEnum; public this(TEnum e) { mEnum = e; } public Result GetNext() mut { switch (mEnum.GetNext()) { case .Ok(let val): return .Ok(val + val); case .Err: return .Err; } } } static DoublingEnumerator GetDoublingEnumerator(this TCollection it) where TCollection: concrete, IEnumerable where TElem : operator TElem + TElem { return .(it.GetEnumerator()); } class ClassF { } class ClassG : ClassF { } public static void TestGen(T val) where T : IEnumerable where TItem : var { } public static void TestPreGen() { List a = default; TestGen(a); } public static TOut Conv(TIn val) where TOut : operator explicit TIn { return (TOut)val; } static void MethodH(T val) where T2 : List { } static void MethodI(T val) where comptype(typeof(T2)) : List { } class ClassH { public class Inner { } } class OuterB { public class Inner { public class MoreInner { public static Inner sVal; public static Inner.MoreInner sVal2; } } public static Inner.MoreInner sVal; } class OuterA { public typealias AliasA = OuterB; public typealias AliasB = OuterB; public class Inner { public class MoreInner { public static Inner sVal; public static Inner.MoreInner sVal2; } public class MoreInnerB { } } public class InnerB { } public static OuterA.Inner sVal; public static Inner sVal2; public static AliasA.Inner sVal3; public static OuterA.InnerB sVal4; public static Inner.MoreInnerB sVal5; } class OuterC { static void Do() { OuterA.AliasA.Inner val1 = scope OuterB.Inner(); OuterA.AliasB.Inner val1b = scope OuterB.Inner(); OuterA.AliasA.Inner.MoreInner val2 = scope OuterB.Inner.MoreInner(); OuterB.Inner.MoreInner val3 = OuterB.sVal; System.Collections.Dictionary dict; OuterA.Inner.MoreInnerB val4 = OuterA.sVal5; } } [Test] public static void TestBasics() { Alloc2(); Alloc3(); MethodD(scope => MethodC); List list = scope .(); list.Sort(); List floatList = scope .() {1, 2, 3}; ClassA ca = scope .(); ClassB cb = scope .(); Test.Assert(LibA.LibA0.GetVal(ca) == 123); Test.Assert(LibA.LibA0.GetVal(cb) == 234); LibA.LibA0.Dispose(ca); LibA.LibA0.Dispose(cb); LibA.LibA0.Alloc(); LibA.LibA0.Alloc(); IDisposable iDisp = null; Test.Assert(MethodA("") == 1); Test.Assert(MethodA(1.2f) == 2); Test.Assert(MethodA(TypeCode.Boolean) == 3); Test.Assert(MethodA(iDisp) == 4); ClassC cc = scope .(); Test.Assert(ClassC.mInstance == cc); LibA.LibA1 la1 = scope .(); LibA.LibA1 la1b = scope .(); LibA.LibA2.DoDispose(la1); Test.Assert(!LibA.LibA2.DoDispose2(la1)); Test.Assert(la1 == la1b); Test.Assert(!LibA.LibA2.CheckEq(la1, la1b)); ClassD cd = scope .(); ClassD cd2 = scope .(); Test.Assert(LibA.LibA2.CheckEq(cd, cd2)); Test.Assert(ClassE.Instance.CreateSystem() == 999); /*IEnumerable ie = floatList; Test.Assert( [IgnoreErrors(true)] { Test.Assert(MethodE(ie) == 8); true } == false);*/ Test.Assert(MethodE(floatList) == 6); Test.Assert(MethodF(floatList) == 0); Test.Assert(floatList.Sum((x) => x * 2) == 12); var e = floatList.GetDoublingEnumerator(); Test.Assert(e.GetNext().Value == 2); Test.Assert(e.GetNext().Value == 4); Test.Assert(e.GetNext().Value == 6); Test.Assert( [IgnoreErrors(true)] { MethodG(); true } == false); MethodG(); Test.Assert(Conv(12.34f) == 12); Test.Assert(Conv(12.34f) == 12); //MethodH(scope List()); var specializedType = typeof(Dictionary.Enumerator) as SpecializedGenericType; Test.Assert(specializedType.UnspecializedType == typeof(Dictionary<,>.Enumerator)); var t = typeof(Array2<>); t = typeof(ClassH<,>.Inner<>); } } class ConstGenerics { public static float GetSum(float[TCount] vals) where TCount : const int { float total = 0; for (int i < vals.Count) total += vals[i]; return total; } static int CheckString(T str) where T : const String { const bool eq = str == "Abc"; return T.Length; } [Test] public static void TestBasics() { float[5] fVals = .(10, 20, 30, 40, 50); float totals = GetSum(fVals); Test.Assert(totals == 10+20+30+40+50); } public static mixin TransformArray(Input[InputSize] array, delegate void(Input, ref Output) predicate) where InputSize : const int where Output : new, class { Output[2] output = default; for (int i = 0; i < array.Count; i++) { output[i] = scope:mixin Output(); predicate(array[i], ref output[i]); } output } class Foo { public static T value; public class Inner where Foo : Object { public static T value2; } } [Test] public static void TestSizedArrays() { int[2] arr = .(2, 4); delegate void(int, ref String) toString = scope (i, str) => { i.ToString(str); }; List l2 = scope .(); l2.Add(TransformArray!(arr, toString)); Test.Assert(l2.Front[0] == "2"); Test.Assert(l2.Front[1] == "4"); int len = CheckString("Abc"); Test.Assert(len == 3); len = CheckString<"Abcd">("Abcd"); Test.Assert(len == 4); int val = 123; bool b = Foo.value < val; b = Foo.value > val; b = Foo.Inner.value2 < 1.2f; b = Foo.Inner.value2 > 2.3f; } } }