mirror of
https://github.com/danbulant/Cosmos
synced 2026-05-20 21:08:51 +00:00
943 lines
20 KiB
C#
943 lines
20 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Runtime.CompilerServices;
|
|
|
|
public partial class Tests
|
|
{
|
|
|
|
struct TestStruct
|
|
{
|
|
public int i;
|
|
public int j;
|
|
|
|
public TestStruct(int i, int j)
|
|
{
|
|
this.i = i;
|
|
this.j = j;
|
|
}
|
|
}
|
|
|
|
public static int test_1_nullable_unbox()
|
|
{
|
|
return Unbox<int?>(1).Value;
|
|
}
|
|
|
|
public static int test_1_nullable_unbox_null()
|
|
{
|
|
return Unbox<int?>(null).HasValue ? 0 : 1;
|
|
}
|
|
|
|
public static int test_1_nullable_box()
|
|
{
|
|
return (int)Box<int?>(1);
|
|
}
|
|
|
|
public static int test_1_nullable_box_null()
|
|
{
|
|
return Box<int?>(null) == null ? 1 : 0;
|
|
}
|
|
|
|
public static int test_1_isinst_nullable()
|
|
{
|
|
object o = 1;
|
|
return (o is int?) ? 1 : 0;
|
|
}
|
|
|
|
public static int test_1_nullable_unbox_vtype()
|
|
{
|
|
return Unbox<TestStruct?>(new TestStruct(1, 2)).Value.i;
|
|
}
|
|
|
|
public static int test_1_nullable_unbox_null_vtype()
|
|
{
|
|
return Unbox<TestStruct?>(null).HasValue ? 0 : 1;
|
|
}
|
|
|
|
public static int test_1_nullable_box_vtype()
|
|
{
|
|
return ((TestStruct)(Box<TestStruct?>(new TestStruct(1, 2)))).i;
|
|
}
|
|
|
|
public static int test_1_nullable_box_null_vtype()
|
|
{
|
|
return Box<TestStruct?>(null) == null ? 1 : 0;
|
|
}
|
|
|
|
public static int test_1_isinst_nullable_vtype()
|
|
{
|
|
object o = new TestStruct(1, 2);
|
|
return (o is TestStruct?) ? 1 : 0;
|
|
}
|
|
|
|
public static int test_0_nullable_normal_unbox()
|
|
{
|
|
int? i = 5;
|
|
|
|
object o = i;
|
|
// This uses unbox instead of unbox_any
|
|
int? j = (int?)o;
|
|
|
|
if (j != 5)
|
|
return 1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
public static void stelem_any<T>(T[] arr, T elem)
|
|
{
|
|
arr[0] = elem;
|
|
}
|
|
|
|
public static T ldelem_any<T>(T[] arr)
|
|
{
|
|
return arr[0];
|
|
}
|
|
|
|
public static int test_1_ldelem_stelem_any_int()
|
|
{
|
|
int[] arr = new int[3];
|
|
stelem_any(arr, 1);
|
|
|
|
return ldelem_any(arr);
|
|
}
|
|
|
|
public static T return_ref<T>(ref T t)
|
|
{
|
|
return t;
|
|
}
|
|
|
|
public static T ldelema_any<T>(T[] arr)
|
|
{
|
|
return return_ref<T>(ref arr[0]);
|
|
}
|
|
|
|
public static int test_0_ldelema()
|
|
{
|
|
string[] arr = new string[1];
|
|
|
|
arr[0] = "Hello";
|
|
|
|
if (ldelema_any<string>(arr) == "Hello")
|
|
return 0;
|
|
else
|
|
return 1;
|
|
}
|
|
|
|
public static T[,] newarr_multi<T>()
|
|
{
|
|
return new T[1, 1];
|
|
}
|
|
|
|
public static int test_0_newarr_multi_dim()
|
|
{
|
|
return newarr_multi<string>().GetType() == typeof(string[,]) ? 0 : 1;
|
|
}
|
|
|
|
interface ITest
|
|
{
|
|
void Foo<T>();
|
|
}
|
|
|
|
public static int test_0_iface_call_null_bug_77442()
|
|
{
|
|
ITest test = null;
|
|
|
|
try
|
|
{
|
|
test.Foo<int>();
|
|
}
|
|
catch (NullReferenceException)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
public static int test_18_ldobj_stobj_generics()
|
|
{
|
|
GenericClass<int> t = new GenericClass<int>();
|
|
int i = 5;
|
|
int j = 6;
|
|
return t.ldobj_stobj(ref i, ref j) + i + j;
|
|
}
|
|
|
|
public static int test_5_ldelem_stelem_generics()
|
|
{
|
|
GenericClass<TestStruct> t = new GenericClass<TestStruct>();
|
|
|
|
TestStruct s = new TestStruct(5, 5);
|
|
return t.ldelem_stelem(s).i;
|
|
}
|
|
|
|
public static int test_0_constrained_vtype_box()
|
|
{
|
|
GenericClass<TestStruct> t = new GenericClass<TestStruct>();
|
|
|
|
return t.toString(new TestStruct()) == "Tests+TestStruct" ? 0 : 1;
|
|
}
|
|
|
|
public static int test_0_constrained_vtype()
|
|
{
|
|
GenericClass<int> t = new GenericClass<int>();
|
|
|
|
return t.toString(1234) == "1234" ? 0 : 1;
|
|
}
|
|
|
|
public static int test_0_constrained_reftype()
|
|
{
|
|
GenericClass<String> t = new GenericClass<String>();
|
|
|
|
return t.toString("1234") == "1234" ? 0 : 1;
|
|
}
|
|
|
|
public static int test_0_box_brtrue_optimizations()
|
|
{
|
|
if (IsNull<int>(5))
|
|
return 1;
|
|
|
|
if (!IsNull<object>(null))
|
|
return 1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
public static int test_0_generic_get_value_optimization_int()
|
|
{
|
|
int[] x = new int[] { 100, 200 };
|
|
|
|
if (GenericClass<int>.Z(x, 0) != 100)
|
|
return 2;
|
|
|
|
if (GenericClass<int>.Z(x, 1) != 200)
|
|
return 3;
|
|
|
|
return 0;
|
|
}
|
|
|
|
public static int test_0_generic_get_value_optimization_vtype()
|
|
{
|
|
TestStruct[] arr = new TestStruct[] { new TestStruct(100, 200), new TestStruct(300, 400) };
|
|
IEnumerator<TestStruct> enumerator = GenericClass<TestStruct>.Y(arr);
|
|
TestStruct s;
|
|
int sum = 0;
|
|
while (enumerator.MoveNext())
|
|
{
|
|
s = enumerator.Current;
|
|
sum += s.i + s.j;
|
|
}
|
|
|
|
if (sum != 1000)
|
|
return 1;
|
|
|
|
s = GenericClass<TestStruct>.Z(arr, 0);
|
|
if (s.i != 100 || s.j != 200)
|
|
return 2;
|
|
|
|
s = GenericClass<TestStruct>.Z(arr, 1);
|
|
if (s.i != 300 || s.j != 400)
|
|
return 3;
|
|
|
|
return 0;
|
|
}
|
|
|
|
public static int test_0_nullable_ldflda()
|
|
{
|
|
return GenericClass<string>.BIsAClazz == false ? 0 : 1;
|
|
}
|
|
|
|
public struct GenericStruct<T>
|
|
{
|
|
public T t;
|
|
|
|
public GenericStruct(T t)
|
|
{
|
|
this.t = t;
|
|
}
|
|
}
|
|
|
|
public class GenericClass<T>
|
|
{
|
|
public T t;
|
|
|
|
public GenericClass(T t)
|
|
{
|
|
this.t = t;
|
|
}
|
|
|
|
public GenericClass()
|
|
{
|
|
}
|
|
|
|
public T ldobj_stobj(ref T t1, ref T t2)
|
|
{
|
|
t1 = t2;
|
|
T t = t1;
|
|
|
|
return t;
|
|
}
|
|
|
|
public T ldelem_stelem(T t)
|
|
{
|
|
T[] arr = new T[10];
|
|
arr[0] = t;
|
|
|
|
return arr[0];
|
|
}
|
|
|
|
public String toString(T t)
|
|
{
|
|
return t.ToString();
|
|
}
|
|
|
|
public static IEnumerator<T> Y(IEnumerable<T> x)
|
|
{
|
|
return x.GetEnumerator();
|
|
}
|
|
|
|
public static T Z(IList<T> x, int index)
|
|
{
|
|
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
|
|
{
|
|
public GenericStruct<int> struct_field;
|
|
public GenericClass<int> class_field;
|
|
}
|
|
|
|
public static int test_0_ldfld_stfld_mro()
|
|
{
|
|
MRO m = new MRO();
|
|
GenericStruct<int> s = new GenericStruct<int>(5);
|
|
// This generates stfld
|
|
m.struct_field = s;
|
|
|
|
// This generates ldflda
|
|
if (m.struct_field.t != 5)
|
|
return 1;
|
|
|
|
// This generates ldfld
|
|
GenericStruct<int> s2 = m.struct_field;
|
|
if (s2.t != 5)
|
|
return 2;
|
|
|
|
if (m.struct_field.t != 5)
|
|
return 3;
|
|
|
|
m.class_field = new GenericClass<int>(5);
|
|
if (m.class_field.t != 5)
|
|
return 4;
|
|
|
|
return 0;
|
|
}
|
|
|
|
// FIXME:
|
|
public static int test_0_generic_virtual_call_on_vtype_unbox()
|
|
{
|
|
object o = new Object();
|
|
IFoo h = new Handler(o);
|
|
|
|
if (h.Bar<object>() != o)
|
|
return 1;
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
public static int test_0_box_brtrue_opt()
|
|
{
|
|
Foo<int> f = new Foo<int>(5);
|
|
|
|
f[123] = 5;
|
|
|
|
return 0;
|
|
}
|
|
|
|
public static int test_0_box_brtrue_opt_regress_81102()
|
|
{
|
|
if (new Foo<int>(5).ToString() == "null")
|
|
return 0;
|
|
else
|
|
return 1;
|
|
}
|
|
|
|
struct GenericsS
|
|
{
|
|
public int i;
|
|
}
|
|
|
|
public static int test_0_ldloca_initobj_opt()
|
|
{
|
|
if (new Foo<GenericsS>(new GenericsS()).get_default().i != 0)
|
|
return 1;
|
|
if (new Foo<object>(null).get_default() != null)
|
|
return 2;
|
|
return 0;
|
|
}
|
|
|
|
|
|
public static int test_0_ldvirtftn_generic_method()
|
|
{
|
|
new Tests().ldvirtftn<string>();
|
|
|
|
return the_type == typeof(string) ? 0 : 1;
|
|
}
|
|
|
|
public static int test_0_throw_dead_this()
|
|
{
|
|
new Foo<string>("").throw_dead_this();
|
|
return 0;
|
|
}
|
|
|
|
struct GenericsS<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<GenericsS<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>
|
|
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
|
|
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 GenericsFooStruct
|
|
{
|
|
}
|
|
|
|
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<GenericsFooStruct>(null))
|
|
return 1;
|
|
if (new Tests().IsNull2<GenericsFooStruct>(new GenericsFooStruct()))
|
|
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>()
|
|
{
|
|
Foo<T> binding = new Foo<T>(default(T));
|
|
|
|
binding.GenericEvent += event_handler;
|
|
binding.fire();
|
|
}
|
|
|
|
public virtual void event_handler<T>(Foo<T> sender)
|
|
{
|
|
the_type = typeof(T);
|
|
}
|
|
|
|
public interface IFoo
|
|
{
|
|
void NonGeneric();
|
|
object Bar<T>();
|
|
}
|
|
|
|
public class Foo<T1> : IFoo
|
|
{
|
|
public Foo(T1 t1)
|
|
{
|
|
m_t1 = t1;
|
|
}
|
|
|
|
public override string ToString()
|
|
{
|
|
return Bar(m_t1 == null ? "null" : "null");
|
|
}
|
|
|
|
public String Bar(String s)
|
|
{
|
|
return s;
|
|
}
|
|
|
|
public int this[T1 key]
|
|
{
|
|
set
|
|
{
|
|
if (key == null)
|
|
throw new ArgumentNullException("key");
|
|
}
|
|
}
|
|
|
|
public void throw_dead_this()
|
|
{
|
|
try
|
|
{
|
|
new SomeClass().ThrowAnException();
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
}
|
|
|
|
public T1 get_default()
|
|
{
|
|
return default(T1);
|
|
}
|
|
|
|
readonly T1 m_t1;
|
|
|
|
public delegate void GenericEventHandler(Foo<T1> sender);
|
|
|
|
public event GenericEventHandler GenericEvent;
|
|
|
|
public void fire()
|
|
{
|
|
GenericEvent(this);
|
|
}
|
|
|
|
public static int count1, count2, count3, count4;
|
|
|
|
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;
|
|
}
|
|
}
|
|
|
|
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;
|
|
}
|
|
}
|
|
|
|
static bool IsNull<T>(T t)
|
|
{
|
|
if (t == null)
|
|
return true;
|
|
else
|
|
return false;
|
|
}
|
|
|
|
static object Box<T>(T t)
|
|
{
|
|
return t;
|
|
}
|
|
|
|
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);
|
|
}
|
|
}
|
|
|
|
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;
|
|
}
|
|
}
|