diff options
author | Michal Strehovský <MichalStrehovsky@users.noreply.github.com> | 2017-03-09 00:46:28 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-03-09 00:46:28 +0300 |
commit | 2a2a698372eaa8d1e4259a642b6f0f843994c649 (patch) | |
tree | db3902a4d241fa3640f7903650c610da1edaa98a /tests/src/Simple/Generics/Generics.cs | |
parent | 351923c42cf27a953887da33c63cacf2d00ae04e (diff) |
Fix vtable stability issue with shared code (#2921)
Pull request #2096 made sure that lazily built vtables of `Foo<X>` and
`Foo<Y>` contain the same entries if their canonical forms are the same,
but didn't make sure the order of the entries is the same. This can lead
to bugs at runtime where the wrong slot is used to dispatch a virtual
method call. To make sure the vtables look the same, we need to also
sort the vtable.
Diffstat (limited to 'tests/src/Simple/Generics/Generics.cs')
-rw-r--r-- | tests/src/Simple/Generics/Generics.cs | 42 |
1 files changed, 38 insertions, 4 deletions
diff --git a/tests/src/Simple/Generics/Generics.cs b/tests/src/Simple/Generics/Generics.cs index 918ff7046..3fc509356 100644 --- a/tests/src/Simple/Generics/Generics.cs +++ b/tests/src/Simple/Generics/Generics.cs @@ -511,7 +511,7 @@ class Program class C1 { } class C2 { } - class Base<T> where T : class + class Base1<T> where T : class { public virtual T As(object o) { @@ -519,7 +519,7 @@ class Program } } - class Derived<T> : Base<T> where T : class + class Derived1<T> : Base1<T> where T : class { public T AsToo(object o) { @@ -527,14 +527,48 @@ class Program } } + class Base2<T> + { + public virtual string Method1() => "Base2.Method1"; + public virtual string Method2() => "Base2.Method2"; + } + + class Derived2<T> : Base2<T> + { + public override string Method1() => "Derived2.Method1"; + public override string Method2() => "Derived2.Method2"; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + private static string TestMethod1FromSharedCode<T>(Base2<T> o) => o.Method1(); + + [MethodImpl(MethodImplOptions.NoInlining)] + private static string TestMethod2FromSharedCode<T>(Base2<T> o) => o.Method2(); + public static void Run() { C1 c1 = new C1(); - if (new Derived<C1>().As(c1) != c1) + if (new Derived1<C1>().As(c1) != c1) throw new Exception(); C2 c2 = new C2(); - if (new Derived<C2>().AsToo(c2) != c2) + if (new Derived1<C2>().AsToo(c2) != c2) + throw new Exception(); + + // Also test the stability of the vtables. + Base2<string> b1 = new Derived2<string>(); + if (b1.Method1() != "Derived2.Method1") + throw new Exception(); + Base2<object> b2 = new Derived2<object>(); + if (b2.Method2() != "Derived2.Method2") + throw new Exception(); + if (TestMethod1FromSharedCode(b2) != "Derived2.Method1") + throw new Exception(); + if (TestMethod1FromSharedCode(b1) != "Derived2.Method1") + throw new Exception(); + if (TestMethod2FromSharedCode(b2) != "Derived2.Method2") + throw new Exception(); + if (TestMethod2FromSharedCode(b1) != "Derived2.Method2") throw new Exception(); } } |