}
}
+static gboolean
+method_is_reabstracted (guint16 flags)
+{
+ if ((flags & METHOD_ATTRIBUTE_ABSTRACT && flags & METHOD_ATTRIBUTE_FINAL))
+ return TRUE;
+ return FALSE;
+}
+
/*
* Return the number of virtual methods.
* Even for interfaces we can't simply return the number of methods as all CLR types are allowed to have static methods.
mcount = mono_class_get_method_count (klass);
for (i = 0; i < mcount; ++i) {
flags = klass->methods [i]->flags;
- if (flags & METHOD_ATTRIBUTE_VIRTUAL)
+ if ((flags & METHOD_ATTRIBUTE_VIRTUAL)) {
+ if (method_is_reabstracted (flags))
+ continue;
++vcount;
+ }
}
} else {
int first_idx = mono_class_get_first_method_idx (klass);
for (i = 0; i < mcount; ++i) {
flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, first_idx + i, MONO_METHOD_FLAGS);
- if (flags & METHOD_ATTRIBUTE_VIRTUAL)
+ if ((flags & METHOD_ATTRIBUTE_VIRTUAL)) {
+ if (method_is_reabstracted (flags))
+ continue;
++vcount;
+ }
}
}
return vcount;
// it can happen (for injected generic array interfaces) that the same slot is
// processed multiple times (those interfaces have overlapping slots), and it
// will not always be the first pass the one that fills the slot.
+ // Now it is okay to implement a class that is not abstract and implements a interface that has an abstract method because it's reabstracted
if (!mono_class_is_abstract (klass)) {
for (i = 0; i < klass->interface_offsets_count; i++) {
int ic_offset;
if (im->flags & METHOD_ATTRIBUTE_STATIC)
continue;
+ if (im->is_reabstracted == 1)
+ continue;
TRACE_INTERFACE_VTABLE (printf (" [class is not abstract, checking slot %d for interface '%s'.'%s', method %s, slot check is %d]\n",
im_slot, ic->name_space, ic->name, im->name, (vtable [im_slot] == NULL)));
g_assert (cur_slot <= max_vtsize);
/* Ensure that all vtable slots are filled with concrete instance methods */
+ // Now it is okay to implement a class that is not abstract and implements a interface that has an abstract method because it's reabstracted
if (!mono_class_is_abstract (klass)) {
for (i = 0; i < cur_slot; ++i) {
if (vtable [i] == NULL || (vtable [i]->flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_STATIC))) {
+ if (vtable [i]->is_reabstracted == 1)
+ continue;
char *type_name = mono_type_get_full_name (klass);
char *method_name = vtable [i] ? mono_method_full_name (vtable [i], TRUE) : g_strdup ("none");
mono_class_set_type_load_failure (klass, "Type %s has invalid vtable method slot %d with method %s", type_name, i, method_name);
/*Only assign slots to virtual methods as interfaces are allowed to have static methods.*/
for (i = 0; i < count; ++i) {
if (methods [i]->flags & METHOD_ATTRIBUTE_VIRTUAL)
+ {
+ if (method_is_reabstracted (methods[i]->flags)) {
+ methods [i]->is_reabstracted = 1;
+ continue;
+ }
methods [i]->slot = slot++;
+ }
}
}
unsigned int is_inflated:1; /* whether we're a MonoMethodInflated */
unsigned int skip_visibility:1; /* whenever to skip JIT visibility checks */
unsigned int verification_success:1; /* whether this method has been verified successfully.*/
+ unsigned int is_reabstracted:1; /* whenever this is a reabstraction of another interface */
signed int slot : 16;
/*
// FIXME: for internal callers maybe it makes sense to do this check at the call site, not
// here?
if (mono_method_has_no_body (method)) {
- mono_error_set_bad_image (error, img, "Method has no body");
+ if (method->is_reabstracted == 1)
+ mono_error_set_generic_error (error, "System", "EntryPointNotFoundException", "%s", method->name);
+ else
+ mono_error_set_bad_image (error, img, "Method has no body");
return NULL;
}
dim-sealed.il \
dim-protected-accessibility1.il \
dim-protected-accessibility2.il \
+ dim-reabstraction.il \
+ dim-reabstraction-generics.il \
twopassvariance.il \
tailcall-generic-cast-conservestack-il.il \
tailcall-generic-cast-nocrash-il.il \
--- /dev/null
+
+// Microsoft (R) .NET Framework IL Disassembler. Version 4.6.1055.0
+// Copyright (c) Microsoft Corporation. All rights reserved.
+
+
+
+// Metadata version: v4.0.30319
+.assembly extern mscorlib
+{
+ .ver 4:0:0:0
+ .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
+}
+.assembly 'dim-reabstraction-generics'
+{
+ .custom instance void class [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::'.ctor'(int32) = (01 00 08 00 00 00 00 00 ) // ........
+
+ .custom instance void class [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::'.ctor'() = (
+ 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78 // ....T..WrapNonEx
+ 63 65 70 74 69 6F 6E 54 68 72 6F 77 73 01 ) // ceptionThrows.
+
+ .custom instance void class [mscorlib]System.Diagnostics.DebuggableAttribute::'.ctor'(valuetype [mscorlib]System.Diagnostics.DebuggableAttribute/DebuggingModes) = (01 00 07 01 00 00 00 00 ) // ........
+
+ .hash algorithm 0x00008004
+ .ver 0:0:0:0
+}
+.module 'dim-reabstraction-generics.exe' // GUID = {198880C7-E25B-497F-AE09-6C555BBBAB42}
+
+
+ .class interface public auto ansi abstract I1`1<T>
+ {
+
+ // method line 1
+ .method public virtual hidebysig newslot abstract
+ instance default int32 M1 () cil managed
+ {
+ // Method begins at RVA 0x0
+ } // end of method I1`1::M1
+
+ // method line 2
+ .method public virtual hidebysig newslot
+ instance default int32 M2 () cil managed
+ {
+ // Method begins at RVA 0x2050
+ // Code size 7 (0x7)
+ .maxstack 1
+ .locals init (
+ int32 V_0)
+ IL_0000: nop
+ IL_0001: ldc.i4.0
+ IL_0002: stloc.0
+ IL_0003: br.s IL_0005
+
+ IL_0005: ldloc.0
+ IL_0006: ret
+ } // end of method I1`1::M2
+
+ } // end of class I1`1
+
+ .class interface public auto ansi abstract I2`1<T>
+ implements class I1`1<!0> {
+
+ // method line 3
+ .method private final virtual hidebysig abstract
+ instance default int32 'I1<T>.M1' () cil managed
+ {
+ // Method begins at RVA 0x0
+ } // end of method I2`1::I1<T>.M1
+
+ // method line 4
+ .method public virtual hidebysig newslot
+ instance default int32 M2 () cil managed
+ {
+ // Method begins at RVA 0x2064
+ // Code size 11 (0xb)
+ .maxstack 1
+ .locals init (
+ int32 V_0)
+ IL_0000: nop
+ IL_0001: ldc.i4 200
+ IL_0006: stloc.0
+ IL_0007: br.s IL_0009
+
+ IL_0009: ldloc.0
+ IL_000a: ret
+ } // end of method I2`1::M2
+
+ } // end of class I2`1
+
+ .class private auto ansi beforefieldinit Test1
+ extends [mscorlib]System.Object
+ implements class I2`1<int32>, class I1`1<int32> {
+
+ // method line 5
+ .method private static hidebysig
+ default int32 Main () cil managed
+ {
+ // Method begins at RVA 0x207c
+ .entrypoint
+ // Code size 54 (0x36)
+ .maxstack 2
+ .locals init (
+ class I1`1<int32> V_0,
+ bool V_1,
+ int32 V_2,
+ bool V_3)
+ IL_0000: nop
+ IL_0001: newobj instance void class Test1::'.ctor'()
+ IL_0006: stloc.0
+ IL_0007: ldloc.0
+ IL_0008: callvirt instance int32 class I1`1<int32>::M1()
+ IL_000d: ldc.i4.s 0x64
+ IL_000f: ceq
+ IL_0011: ldc.i4.0
+ IL_0012: ceq
+ IL_0014: stloc.1
+ IL_0015: ldloc.1
+ IL_0016: brfalse.s IL_001d
+
+ IL_0018: nop
+ IL_0019: ldc.i4.m1
+ IL_001a: stloc.2
+ IL_001b: br.s IL_0034
+
+ IL_001d: ldloc.0
+ IL_001e: callvirt instance int32 class I1`1<int32>::M2()
+ IL_0023: ldc.i4.0
+ IL_0024: cgt.un
+ IL_0026: stloc.3
+ IL_0027: ldloc.3
+ IL_0028: brfalse.s IL_0030
+
+ IL_002a: nop
+ IL_002b: ldc.i4.s 0xfffffffe
+ IL_002d: stloc.2
+ IL_002e: br.s IL_0034
+
+ IL_0030: ldc.i4.0
+ IL_0031: stloc.2
+ IL_0032: br.s IL_0034
+
+ IL_0034: ldloc.2
+ IL_0035: ret
+ } // end of method Test1::Main
+
+ // method line 6
+ .method private final virtual hidebysig newslot
+ instance default int32 'I1<System.Int32>.M1' () cil managed
+ {
+ // Method begins at RVA 0x20c0
+ .override method instance int32 class I1`1<int32>::M1()
+ // Code size 8 (0x8)
+ .maxstack 1
+ .locals init (
+ int32 V_0)
+ IL_0000: nop
+ IL_0001: ldc.i4.s 0x64
+ IL_0003: stloc.0
+ IL_0004: br.s IL_0006
+
+ IL_0006: ldloc.0
+ IL_0007: ret
+ } // end of method Test1::I1<System.Int32>.M1
+
+ // method line 7
+ .method public hidebysig specialname rtspecialname
+ instance default void '.ctor' () cil managed
+ {
+ // Method begins at RVA 0x20d4
+ // Code size 8 (0x8)
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: call instance void object::'.ctor'()
+ IL_0006: nop
+ IL_0007: ret
+ } // end of method Test1::.ctor
+
+ } // end of class Test1
+
--- /dev/null
+
+// Microsoft (R) .NET Framework IL Disassembler. Version 4.6.1055.0
+// Copyright (c) Microsoft Corporation. All rights reserved.
+
+
+
+// Metadata version: v4.0.30319
+.assembly extern mscorlib
+{
+ .ver 4:0:0:0
+ .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
+}
+.assembly 'reabstraction'
+{
+ .custom instance void class [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::'.ctor'(int32) = (01 00 08 00 00 00 00 00 ) // ........
+
+ .custom instance void class [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::'.ctor'() = (
+ 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78 // ....T..WrapNonEx
+ 63 65 70 74 69 6F 6E 54 68 72 6F 77 73 01 ) // ceptionThrows.
+
+ .custom instance void class [mscorlib]System.Diagnostics.DebuggableAttribute::'.ctor'(valuetype [mscorlib]System.Diagnostics.DebuggableAttribute/DebuggingModes) = (01 00 07 01 00 00 00 00 ) // ........
+
+ .hash algorithm 0x00008004
+ .ver 0:0:0:0
+}
+.module reabstraction.exe // GUID = {874DD85D-9771-40F1-A6BB-D80FDAA9CF69}
+
+
+ .class interface public auto ansi abstract I1
+ {
+
+ // method line 1
+ .method public virtual hidebysig newslot abstract
+ instance default int32 M1 () cil managed
+ {
+ // Method begins at RVA 0x0
+ } // end of method I1::M1
+
+ // method line 2
+ .method public virtual hidebysig newslot
+ instance default int32 M2 () cil managed
+ {
+ // Method begins at RVA 0x2050
+ // Code size 7 (0x7)
+ .maxstack 1
+ .locals init (
+ int32 V_0)
+ IL_0000: nop
+ IL_0001: ldc.i4.0
+ IL_0002: stloc.0
+ IL_0003: br.s IL_0005
+
+ IL_0005: ldloc.0
+ IL_0006: ret
+ } // end of method I1::M2
+
+ } // end of class I1
+
+ .class interface public auto ansi abstract I2
+ implements I1 {
+
+ // method line 3
+ .method private final virtual hidebysig abstract
+ instance default int32 I1.M1 () cil managed
+ {
+ // Method begins at RVA 0x0
+ } // end of method I2::I1.M1
+
+ // method line 4
+ .method public virtual hidebysig newslot
+ instance default int32 M2 () cil managed
+ {
+ // Method begins at RVA 0x2064
+ // Code size 11 (0xb)
+ .maxstack 1
+ .locals init (
+ int32 V_0)
+ IL_0000: nop
+ IL_0001: ldc.i4 200
+ IL_0006: stloc.0
+ IL_0007: br.s IL_0009
+
+ IL_0009: ldloc.0
+ IL_000a: ret
+ } // end of method I2::M2
+
+ } // end of class I2
+
+ .class private auto ansi beforefieldinit Test1
+ extends [mscorlib]System.Object
+ implements I2, I1 {
+
+ // method line 5
+ .method private static hidebysig
+ default int32 Main () cil managed
+ {
+ // Method begins at RVA 0x207c
+ .entrypoint
+ // Code size 59 (0x3b)
+ .maxstack 2
+ .locals init (
+ class I1 V_0,
+ bool V_1,
+ int32 V_2,
+ bool V_3)
+ IL_0000: nop
+ IL_0001: newobj instance void class Test1::'.ctor'()
+ IL_0006: stloc.0
+ IL_0007: ldloc.0
+ IL_0008: callvirt instance int32 class I1::M1()
+ IL_000d: ldc.i4.s 0x64
+ IL_000f: ceq
+ IL_0011: ldc.i4.0
+ IL_0012: ceq
+ IL_0014: stloc.1
+ IL_0015: ldloc.1
+ IL_0016: brfalse.s IL_001c
+
+ IL_0018: ldc.i4.m1
+ IL_0019: stloc.2
+ IL_001a: br.s IL_0039
+
+ IL_001c: ldloc.0
+ IL_001d: callvirt instance int32 class I1::M2()
+ IL_0022: ldc.i4 0
+ IL_0027: ceq
+ IL_0029: ldc.i4.0
+ IL_002a: ceq
+ IL_002c: stloc.3
+ IL_002d: ldloc.3
+ IL_002e: brfalse.s IL_0035
+
+ IL_0030: ldc.i4.s 0xfffffffe
+ IL_0032: stloc.2
+ IL_0033: br.s IL_0039
+
+ IL_0035: ldc.i4.0
+ IL_0036: stloc.2
+ IL_0037: br.s IL_0039
+
+ IL_0039: ldloc.2
+ IL_003a: ret
+ } // end of method Test1::Main
+
+ // method line 6
+ .method private final virtual hidebysig newslot
+ instance default int32 I1.M1 () cil managed
+ {
+ // Method begins at RVA 0x20c4
+ .override class I1::M1
+ // Code size 8 (0x8)
+ .maxstack 1
+ .locals init (
+ int32 V_0)
+ IL_0000: nop
+ IL_0001: ldc.i4.s 0x64
+ IL_0003: stloc.0
+ IL_0004: br.s IL_0006
+
+ IL_0006: ldloc.0
+ IL_0007: ret
+ } // end of method Test1::I1.M1
+
+ // method line 7
+ .method public hidebysig specialname rtspecialname
+ instance default void '.ctor' () cil managed
+ {
+ // Method begins at RVA 0x20d8
+ // Code size 8 (0x8)
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: call instance void object::'.ctor'()
+ IL_0006: nop
+ IL_0007: ret
+ } // end of method Test1::.ctor
+
+ } // end of class Test1
+