Handle a vtable layout corner case.
authorRodrigo Kumpera <kumpera@gmail.com>
Wed, 1 Jun 2011 17:55:30 +0000 (14:55 -0300)
committerRodrigo Kumpera <kumpera@gmail.com>
Wed, 1 Jun 2011 18:01:32 +0000 (15:01 -0300)
class.c (mono_class_inflate_generic_method_full_checked): Don't
inflate a method if the provided context won't change it.
This change, in particular, avoid inflating a generic method
of a non-generic class if the context has class only vars.

This fixes #696593 as the above was causing the vtable of
Class3 ending up with an inflated Class1::Method<> that
comes from inflated Class2<object> parent.
Then the parent override pass would collect a non-inflated
Class1::Method<> overide that would then not match the one
on the vtable causing Class3 to have an abstract method on
its vtable and thus failing to load.

Big explanation means tricky change, might break tons of stuff.

mono/metadata/class.c

index 49fa24f0423db9bc52a542feae8534f0d6fead14..9a59ec0bfce0e4c55369d44fe80b5e93c032ebcc 100644 (file)
@@ -900,7 +900,16 @@ mono_class_inflate_generic_method_full_checked (MonoMethod *method, MonoClass *k
                method = imethod->declaring;
        }
 
-       if (!method->is_generic && !method->klass->generic_container)
+       /*
+        * A method only needs to be inflated if the context has argument for which it is
+        * parametric. Eg:
+        * 
+        * class Foo<T> { void Bar(); } - doesn't need to be inflated if only mvars' are supplied
+        * class Foo { void Bar<T> (); } - doesn't need to be if only vars' are supplied
+        * 
+        */
+       if (!((method->is_generic && context->method_inst) || 
+               (method->klass->generic_container && context->class_inst)))
                return method;
 
        /*