Use g_assertion_message instead of exit to kill an iOS app.
[mono.git] / mono / mini / generics.cs
index 1780be65f0381ffbdf8bda2fea6246d8c6ee6ba7..19282df514e273e5f2da45e6208e835255b34b58 100644 (file)
@@ -1,5 +1,7 @@
 using System;
 using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.CompilerServices;
 
 class Tests {
 
@@ -31,9 +33,9 @@ class Tests {
                }
        }
 
-       static int Main ()
+       static int Main (string[] args)
        {
-               return TestDriver.RunTests (typeof (Tests));
+               return TestDriver.RunTests (typeof (Tests), args);
        }
 
        public static int test_1_nullable_unbox ()
@@ -204,6 +206,7 @@ class Tests {
                return 0;
        }
 
+       [Category ("!FULLAOT")]
        public static int test_0_generic_get_value_optimization_int () {
                int[] x = new int[] {100, 200};
 
@@ -240,6 +243,10 @@ class Tests {
                return 0;
        }
 
+       public static int test_0_nullable_ldflda () {
+               return GenericClass<string>.BIsAClazz == false ? 0 : 1;
+       }
+
        public struct GenericStruct<T> {
                public T t;
 
@@ -285,6 +292,15 @@ class Tests {
                {
                        return x [index];
                }
+
+        protected static T NullB = default(T);       
+        private static Nullable<bool>  _BIsA = null;
+        public static bool BIsAClazz {
+            get {
+                _BIsA = false;
+                return _BIsA.Value;
+            }
+        }
        }
 
        public class MRO : MarshalByRefObject {
@@ -317,9 +333,11 @@ class Tests {
                return 0;
        }
 
+       // FIXME:
+       [Category ("!FULLAOT")]
     public static int test_0_generic_virtual_call_on_vtype_unbox () {
                object o = new Object ();
-        IMyHandler h = new Handler(o);
+        IFoo h = new Handler(o);
 
         if (h.Bar<object> () != o)
                        return 1;
@@ -383,6 +401,338 @@ class Tests {
                return the_type == typeof (string) ? 0 : 1;
        }
 
+       public static int test_0_throw_dead_this () {
+        new Foo<string> ("").throw_dead_this ();
+               return 0;
+       }
+
+       struct S<T> {}
+
+       public static int test_0_inline_infinite_polymorphic_recursion () {
+           f<int>(0);
+
+                  return 0;
+       }
+
+       private static void f<T>(int i) {
+               if(i==42) f<S<T>>(i);
+       }
+
+       // This cannot be made to work with full-aot, since there it is impossible to
+       // statically determine that Foo<string>.Bar <int> is needed, the code only
+       // references IFoo.Bar<int>
+       [Category ("!FULLAOT")]
+       public static int test_0_generic_virtual_on_interfaces () {
+               Foo<string>.count1 = 0;
+               Foo<string>.count2 = 0;
+               Foo<string>.count3 = 0;
+
+               IFoo f = new Foo<string> ("");
+               for (int i = 0; i < 1000; ++i) {
+                       f.Bar <int> ();
+                       f.Bar <string> ();
+                       f.NonGeneric ();
+               }
+
+               if (Foo<string>.count1 != 1000)
+                       return 1;
+               if (Foo<string>.count2 != 1000)
+                       return 2;
+               if (Foo<string>.count3 != 1000)
+                       return 3;
+
+               VirtualInterfaceCallFromGenericMethod<long> (f);
+
+               return 0;
+       }
+
+       public static int test_0_generic_virtual_on_interfaces_ref () {
+               Foo<string>.count1 = 0;
+               Foo<string>.count2 = 0;
+               Foo<string>.count3 = 0;
+               Foo<string>.count4 = 0;
+
+               IFoo f = new Foo<string> ("");
+               for (int i = 0; i < 1000; ++i) {
+                       f.Bar <string> ();
+                       f.Bar <object> ();
+                       f.NonGeneric ();
+               }
+
+               if (Foo<string>.count2 != 1000)
+                       return 2;
+               if (Foo<string>.count3 != 1000)
+                       return 3;
+               if (Foo<string>.count4 != 1000)
+                       return 4;
+
+               return 0;
+       }
+
+       //repro for #505375
+       [Category ("!FULLAOT")]
+       public static int test_2_cprop_bug () {
+               int idx = 0;
+               int a = 1;
+               var cmp = System.Collections.Generic.Comparer<int>.Default ;
+               if (cmp.Compare (a, 0) > 0)
+                       a = 0;
+               do { idx++; } while (cmp.Compare (idx - 1, a) == 0);
+               return idx;
+       }
+
+       enum MyEnumUlong : ulong {
+               Value_2 = 2
+       }
+
+       public static int test_0_regress_550964_constrained_enum_long () {
+        MyEnumUlong a = MyEnumUlong.Value_2;
+        MyEnumUlong b = MyEnumUlong.Value_2;
+
+        return Pan (a, b) ? 0 : 1;
+       }
+
+    static bool Pan<T> (T a, T b)
+    {
+        return a.Equals (b);
+    }
+
+       public class XElement {
+               public string Value {
+                       get; set;
+               }
+       }
+
+       public static int test_0_fullaot_linq () {
+               var allWords = new XElement [] { new XElement { Value = "one" } };
+               var filteredWords = allWords.Where(kw => kw.Value.StartsWith("T"));
+               return filteredWords.Count ();
+       }
+
+       public static int test_0_fullaot_comparer_t () {
+               var l = new SortedList <TimeSpan, int> ();
+               return l.Count;
+       }
+
+       public static int test_0_fullaot_comparer_t_2 () {
+               var l = new Dictionary <TimeSpan, int> ();
+               return l.Count;
+       }
+
+       static void enumerate<T> (IEnumerable<T> arr) {
+               foreach (var o in arr)
+                       ;
+               int c = ((ICollection<T>)arr).Count;
+       }
+
+       /* Test that treating arrays as generic collections works with full-aot */
+       public static int test_0_fullaot_array_wrappers () {
+               Tests[] arr = new Tests [10];
+               enumerate<Tests> (arr);
+               return 0;
+       }
+
+       static int cctor_count = 0;
+
+    public abstract class Beta<TChanged> 
+    {          
+        static Beta()
+        {
+                       cctor_count ++;
+        }
+    }   
+    
+    public class Gamma<T> : Beta<T> 
+    {   
+        static Gamma()
+        {
+        }
+    }
+
+       // #519336    
+       public static int test_2_generic_class_init_gshared_ctor () {
+               new Gamma<object>();
+               new Gamma<string>();
+
+               return cctor_count;
+       }
+
+       static int cctor_count2 = 0;
+
+       class ServiceController<T> {
+               static ServiceController () {
+                       cctor_count2 ++;
+               }
+
+               public ServiceController () {
+               }
+       }
+
+       static ServiceController<T> Create<T>() {
+               return new ServiceController<T>();
+       }
+
+       // #631409
+       public static int test_2_generic_class_init_gshared_ctor_from_gshared () {
+               Create<object> ();
+               Create<string> ();
+
+               return cctor_count2;
+       }
+
+       public static Type get_type<T> () {
+               return typeof (T);
+       }
+
+       public static int test_0_gshared_delegate_rgctx () {
+               Func<Type> t = new Func<Type> (get_type<string>);
+
+               if (t () == typeof (string))
+                       return 0;
+               else
+                       return 1;
+       }
+
+       // Creating a delegate from a generic method from gshared code
+       public static int test_0_gshared_delegate_from_gshared () {
+               if (gshared_delegate_from_gshared <object> () != 0)
+                       return 1;
+               if (gshared_delegate_from_gshared <string> () != 0)
+                       return 2;
+               return 0;
+       }
+
+       public static int gshared_delegate_from_gshared <T> () {
+               Func<Type> t = new Func<Type> (get_type<T>);
+
+               return t () == typeof (T) ? 0 : 1;
+       }
+
+       public static int test_0_marshalbyref_call_from_gshared_virt_elim () {
+               /* Calling a virtual method from gshared code which is changed to a nonvirt call */
+               Class1<object> o = new Class1<object> ();
+               o.Do (new Class2<object> ());
+               return 0;
+       }
+
+       class Pair<TKey, TValue> {
+               public static KeyValuePair<TKey, TValue> make_pair (TKey key, TValue value)
+                       {
+                               return new KeyValuePair<TKey, TValue> (key, value);
+                       }
+
+               public delegate TRet Transform<TRet> (TKey key, TValue value);
+       }
+
+       public static int test_0_bug_620864 () {
+               var d = new Pair<string, Type>.Transform<KeyValuePair<string, Type>> (Pair<string, Type>.make_pair);
+
+               var p = d ("FOO", typeof (int));
+               if (p.Key != "FOO" || p.Value != typeof (int))
+                       return 1;
+
+               return 0;
+       }
+
+
+       struct RecStruct<T> {
+               public void foo (RecStruct<RecStruct<T>> baz) {
+               }
+       }
+
+       public static int test_0_infinite_generic_recursion () {
+               // Check that the AOT compile can deal with infinite generic recursion through
+               // parameter types
+               RecStruct<int> bla;
+
+               return 0;
+       }
+
+       struct FooStruct {
+       }
+
+       bool IsNull2 <T> (object value) where T : struct {
+               T? item = (T?) value;
+
+               if (item.HasValue)
+                       return false;
+
+               return true;
+       }
+
+       public static int test_0_full_aot_nullable_unbox_from_gshared_code () {
+               if (!new Tests ().IsNull2<FooStruct> (null))
+                       return 1;
+               if (new Tests ().IsNull2<FooStruct> (new FooStruct ()))
+                       return 2;
+               return 0;
+       }
+
+       public static int test_0_partial_sharing () {
+               if (PartialShared1 (new List<string> (), 1) != typeof (string))
+                       return 1;
+               if (PartialShared1 (new List<Tests> (), 1) != typeof (Tests))
+                       return 2;
+               if (PartialShared2 (new List<string> (), 1) != typeof (int))
+                       return 3;
+               if (PartialShared2 (new List<Tests> (), 1) != typeof (int))
+                       return 4;
+               return 0;
+       }
+
+       public static int test_6_partial_sharing_linq () {
+               var messages = new List<Message> ();
+
+               messages.Add (new Message () { MessageID = 5 });
+               messages.Add (new Message () { MessageID = 6 });
+
+               return messages.Max(i => i.MessageID);
+       }
+
+       public static int test_0_partial_shared_method_in_nonshared_class () {
+               var c = new Class1<double> ();
+               return (c.Foo<string> (5).GetType () == typeof (Class1<string>)) ? 0 : 1;
+       }
+
+       class Message {
+               public int MessageID {
+                       get; set;
+               }
+       }
+
+       public static Type PartialShared1<T, K> (List<T> list, K k) {
+               return typeof (T);
+       }
+
+       public static Type PartialShared2<T, K> (List<T> list, K k) {
+               return typeof (K);
+       }
+
+    public class Class1<T> {
+               public virtual void Do (Class2<T> t) {
+                       t.Foo ();
+               }
+
+               public virtual object Foo<U> (T t) {
+                       return new Class1<U> ();
+               }
+       }
+
+       public interface IFace1<T> {
+               void Foo ();
+       }
+
+       public class Class2<T> : MarshalByRefObject, IFace1<T> {
+               public void Foo () {
+               }
+       }
+
+
+
+       public static void VirtualInterfaceCallFromGenericMethod <T> (IFoo f) {
+               f.Bar <T> ();
+       }
+
        public static Type the_type;
 
        public void ldvirtftn<T> () {
@@ -396,7 +746,12 @@ class Tests {
                the_type = typeof (T);
        }
 
-       public class Foo<T1>
+       public interface IFoo {
+               void NonGeneric ();
+               object Bar<T>();
+       }
+
+       public class Foo<T1> : IFoo
        {
                public Foo(T1 t1)
                {
@@ -419,6 +774,14 @@ class Tests {
                        }
                }
 
+               public void throw_dead_this () {
+                       try {
+                               new SomeClass().ThrowAnException();
+                       }
+                       catch {
+                       }
+               }
+
                public T1 get_default () {
                        return default (T1);
                }
@@ -433,19 +796,39 @@ class Tests {
                        GenericEvent (this);
                }
 
-       }
+               public static int count1, count2, count3, count4;
 
-       public interface IMyHandler {
-               object Bar<T>();
+               public void NonGeneric () {
+                       count3 ++;
+               }
+
+               public object Bar <T> () {
+                       if (typeof (T) == typeof (int))
+                               count1 ++;
+                       else if (typeof (T) == typeof (string))
+                               count2 ++;
+                       else if (typeof (T) == typeof (object))
+                               count4 ++;
+                       return null;
+               }
        }
 
-       struct Handler : IMyHandler {
+       public class SomeClass {
+               public void ThrowAnException() {
+                       throw new Exception ("Something went wrong");
+               }
+       }               
+
+       struct Handler : IFoo {
                object o;
 
                public Handler(object o) {
                        this.o = o;
                }
 
+               public void NonGeneric () {
+               }
+
                public object Bar<T>() {
                        return o;
                }
@@ -467,4 +850,134 @@ class Tests {
        static T Unbox <T> (object o) {
                return (T) o;
        }
+
+       interface IDefaultRetriever
+       {
+               T GetDefault<T>();
+       }
+
+       class DefaultRetriever : IDefaultRetriever
+       {
+               [MethodImpl(MethodImplOptions.Synchronized)]
+               public T GetDefault<T>()
+               {
+                       return default(T);
+               }
+       }
+
+       [Category ("!FULLAOT")]
+       public static int test_0_regress_668095_synchronized_gshared () {
+               return DoSomething (new DefaultRetriever ());
+       }
+
+    static int DoSomething(IDefaultRetriever foo) {
+               int result = foo.GetDefault<int>();
+               return result;
+       }
+
+       class Response {
+       }
+
+       public static int test_0_687865_isinst_with_cache_wrapper () {
+               object o = new object ();
+               if (o is Action<IEnumerable<Response>>)
+                       return 1;
+               else
+                       return 0;
+       }
+
+       enum DocType {
+               One,
+               Two,
+               Three
+       }
+
+       class Doc {
+               public string Name {
+                       get; set;
+               }
+
+               public DocType Type {
+                       get; set;
+               }
+       }
+
+       // #2155
+       public static int test_0_fullaot_sflda_cctor () {
+               List<Doc> documents = new List<Doc>();
+               documents.Add(new Doc { Name = "Doc1", Type = DocType.One } );
+               documents.Add(new Doc { Name = "Doc2", Type = DocType.Two } );
+               documents.Add(new Doc { Name = "Doc3", Type = DocType.Three } );
+               documents.Add(new Doc { Name = "Doc4", Type = DocType.One } );
+               documents.Add(new Doc { Name = "Doc5", Type = DocType.Two } );
+               documents.Add(new Doc { Name = "Doc6", Type = DocType.Three } );
+               documents.Add(new Doc { Name = "Doc7", Type = DocType.One } );
+               documents.Add(new Doc { Name = "Doc8", Type = DocType.Two } );
+               documents.Add(new Doc { Name = "Doc9", Type = DocType.Three } );
+
+               List<DocType> categories = documents.Select(d=>d.Type).Distinct().ToList<DocType>().OrderBy(d => d).ToList();
+               foreach(DocType cat in categories) {
+                       List<Doc> catDocs = documents.Where(d => d.Type == cat).OrderBy(d => d.Name).ToList<Doc>();
+               }
+               return 0;
+       }
+
+       class A { }
+
+    static List<A> sources = new List<A>();
+
+       // #6112
+    public static int test_0_fullaot_imt () {
+        sources.Add(null);
+        sources.Add(null);
+
+        int a = sources.Count;
+        var enumerator = sources.GetEnumerator() as IEnumerator<object>;
+
+        while (enumerator.MoveNext())
+        {
+            object o = enumerator.Current;
+        }
+
+               return 0;
+       }
+
+       struct Record : Foo2<Record>.IRecord {
+               int counter;
+               int Foo2<Record>.IRecord.DoSomething () {
+                       return counter++;
+               }
+       }
+
+       class Foo2<T> where T : Foo2<T>.IRecord {
+               public interface IRecord {
+                       int DoSomething ();
+               }
+
+               public static int Extract (T[] t) {
+                       return t[0].DoSomething ();
+               }
+       }
+
+       class Foo3<T> where T : IComparable {
+               public static int CompareTo (T[] t) {
+                       // This is a constrained call to Enum.CompareTo ()
+                       return t[0].CompareTo (t [0]);
+               }
+       }
+
+       public static int test_1_regress_constrained_iface_call_7571 () {
+        var r = new Record [10];
+        Foo2<Record>.Extract (r);
+               return Foo2<Record>.Extract (r);
+       }
+
+       enum ConstrainedEnum {
+               Val = 1
+       }
+
+       public static int test_0_regress_constrained_iface_call_enum () {
+               var r = new ConstrainedEnum [10];
+               return Foo3<ConstrainedEnum>.CompareTo (r);
+       }
 }