Closed michaldobrodenka closed 1 year ago
I couldn't figure out the best area label to add to this issue. If you have write-permissions please help me learn by adding exactly one area label.
smallest example csproj
Only when ClassA is abstract!
cc: @trylek - maybe that's what you've fixed recently?
/cc @lambdageek @vargaz
*** Vtable for class 'ClassB' at "AFTER INHERITING PARENT VTABLE" (size 7) Packed interface table for class ClassB has size 1 [000][UUID 622][SLOT 004][SIZE 002] interface IDefault Interface flags: (0,F)(1,F)(2,F)(3,F)(4,F)(5,F)(6,F)(7,F)(8,F)(9,F)(10,F)(11,F)(12,F)(13,F)(14,F)(15,F)(16,F)(17,F)(18,F)(19,F)(20,F)(21,F)(22,F)(23,F)(24,F)(25,F)(26,F)(27,F)(28,F)(29,F)(30,F)(31,F)(32,F)(33,F)(34,F)(35,F)(36,F)(37,F)(38,F)(39,F)(40,F)(41,F)(42,F)(43,F)(44,F)(45,F)(46,F)(47,F)(48,F)(49,F)(50,F)(51,F)(52,F)(53,F)(54,F)(55,F)(56,F)(57,F)(58,F)(59,F)(60,F)(61,F)(62,F)(63,F)(64,F)(65,F)(66,F)(67,F)(68,F)(69,F)(70,F)(71,F)(72,F)(73,F)(74,F)(75,F)(76,F)(77,F)(78,F)(79,F)(80,F)(81,F)(82,F)(83,F)(84,F)(85,F)(86,F)(87,F)(88,F)(89,F)(90,F)(91,F)(92,F)(93,F)(94,F)(95,F)(96,F)(97,F)(98,F)(99,F)(100,F)(101,F)(102,F)(103,F)(104,F)(105,F)(106,F)(107,F)(108,F)(109,F)(110,F)(111,F)(112,F)(113,F)(114,F)(115,F)(116,F)(117,F)(118,F)(119,F)(120,F)(121,F)(122,F)(123,F)(124,F)(125,F)(126,F)(127,F)(128,F)(129,F)(130,F)(131,F)(132,F)(133,F)(134,F)(135,F)(136,F)(137,F)(138,F)(139,F)(140,F)(141,F)(142,F)(143,F)(144,F)(145,F)(146,F)(147,F)(148,F)(149,F)(150,F)(151,F)(152,F)(153,F)(154,F)(155,F)(156,F)(157,F)(158,F)(159,F)(160,F)(161,F)(162,F)(163,F)(164,F)(165,F)(166,F)(167,F)(168,F)(169,F)(170,F)(171,F)(172,F)(173,F)(174,F)(175,F)(176,F)(177,F)(178,F)(179,F)(180,F)(181,F)(182,F)(183,F)(184,F)(185,F)(186,F)(187,F)(188,F)(189,F)(190,F)(191,F)(192,F)(193,F)(194,F)(195,F)(196,F)(197,F)(198,F)(199,F)(200,F)(201,F)(202,F)(203,F)(204,F)(205,F)(206,F)(207,F)(208,F)(209,F)(210,F)(211,F)(212,F)(213,F)(214,F)(215,F)(216,F)(217,F)(218,F)(219,F)(220,F)(221,F)(222,F)(223,F)(224,F)(225,F)(226,F)(227,F)(228,F)(229,F)(230,F)(231,F)(232,F)(233,F)(234,F)(235,F)(236,F)(237,F)(238,F)(239,F)(240,F)(241,F)(242,F)(243,F)(244,F)(245,F)(246,F)(247,F)(248,F)(249,F)(250,F)(251,F)(252,F)(253,F)(254,F)(255,F)(256,F)(257,F)(258,F)(259,F)(260,F)(261,F)(262,F)(263,F)(264,F)(265,F)(266,F)(267,F)(268,F)(269,F)(270,F)(271,F)(272,F)(273,F)(274,F)(275,F)(276,F)(277,F)(278,F)(279,F)(280,F)(281,F)(282,F)(283,F)(284,F)(285,F)(286,F)(287,F)(288,F)(289,F)(290,F)(291,F)(292,F)(293,F)(294,F)(295,F)(296,F)(297,F)(298,F)(299,F)(300,F)(301,F)(302,F)(303,F)(304,F)(305,F)(306,F)(307,F)(308,F)(309,F)(310,F)(311,F)(312,F)(313,F)(314,F)(315,F)(316,F)(317,F)(318,F)(319,F)(320,F)(321,F)(322,F)(323,F)(324,F)(325,F)(326,F)(327,F)(328,F)(329,F)(330,F)(331,F)(332,F)(333,F)(334,F)(335,F)(336,F)(337,F)(338,F)(339,F)(340,F)(341,F)(342,F)(343,F)(344,F)(345,F)(346,F)(347,F)(348,F)(349,F)(350,F)(351,F)(352,F)(353,F)(354,F)(355,F)(356,F)(357,F)(358,F)(359,F)(360,F)(361,F)(362,F)(363,F)(364,F)(365,F)(366,F)(367,F)(368,F)(369,F)(370,F)(371,F)(372,F)(373,F)(374,F)(375,F)(376,F)(377,F)(378,F)(379,F)(380,F)(381,F)(382,F)(383,F)(384,F)(385,F)(386,F)(387,F)(388,F)(389,F)(390,F)(391,F)(392,F)(393,F)(394,F)(395,F)(396,F)(397,F)(398,F)(399,F)(400,F)(401,F)(402,F)(403,F)(404,F)(405,F)(406,F)(407,F)(408,F)(409,F)(410,F)(411,F)(412,F)(413,F)(414,F)(415,F)(416,F)(417,F)(418,F)(419,F)(420,F)(421,F)(422,F)(423,F)(424,F)(425,F)(426,F)(427,F)(428,F)(429,F)(430,F)(431,F)(432,F)(433,F)(434,F)(435,F)(436,F)(437,F)(438,F)(439,F)(440,F)(441,F)(442,F)(443,F)(444,F)(445,F)(446,F)(447,F)(448,F)(449,F)(450,F)(451,F)(452,F)(453,F)(454,F)(455,F)(456,F)(457,F)(458,F)(459,F)(460,F)(461,F)(462,F)(463,F)(464,F)(465,F)(466,F)(467,F)(468,F)(469,F)(470,F)(471,F)(472,F)(473,F)(474,F)(475,F)(476,F)(477,F)(478,F)(479,F)(480,F)(481,F)(482,F)(483,F)(484,F)(485,F)(486,F)(487,F)(488,F)(489,F)(490,F)(491,F)(492,F)(493,F)(494,F)(495,F)(496,F)(497,F)(498,F)(499,F)(500,F)(501,F)(502,F)(503,F)(504,F)(505,F)(506,F)(507,F)(508,F)(509,F)(510,F)(511,F)(512,F)(513,F)(514,F)(515,F)(516,F)(517,F)(518,F)(519,F)(520,F)(521,F)(522,F)(523,F)(524,F)(525,F)(526,F)(527,F)(528,F)(529,F)(530,F)(531,F)(532,F)(533,F)(534,F)(535,F)(536,F)(537,F)(538,F)(539,F)(540,F)(541,F)(542,F)(543,F)(544,F)(545,F)(546,F)(547,F)(548,F)(549,F)(550,F)(551,F)(552,F)(553,F)(554,F)(555,F)(556,F)(557,F)(558,F)(559,F)(560,F)(561,F)(562,F)(563,F)(564,F)(565,F)(566,F)(567,F)(568,F)(569,F)(570,F)(571,F)(572,F)(573,F)(574,F)(575,F)(576,F)(577,F)(578,F)(579,F)(580,F)(581,F)(582,F)(583,F)(584,F)(585,F)(586,F)(587,F)(588,F)(589,F)(590,F)(591,F)(592,F)(593,F)(594,F)(595,F)(596,F)(597,F)(598,F)(599,F)(600,F)(601,F)(602,F)(603,F)(604,F)(605,F)(606,F)(607,F)(608,F)(609,F)(610,F)(611,F)(612,F)(613,F)(614,F)(615,F)(616,F)(617,F)(618,F)(619,F)(620,F)(621,F)(622,T) Dump interface flags: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 40 [LEVEL 0] Implemented interfaces by class ClassB: [LEVEL 1] Implemented interfaces by class ClassA: [UIID 622] interface IDefault [000][UUID 622][SLOT 004][SIZE 002] interface .IDefault [LEVEL 2] Implemented interfaces by class Object: * Interfaces for class 'ClassB' done. Starting vtable (size 7): [O][000][INDEX 000] object:GetHashCode () [0x12701ac30] [O][001][INDEX 001] object:Equals (object) [0x12701ac08] [O][002][INDEX 002] object:ToString () [0x12701abe0] [O][003][INDEX 003] object:Finalize () [0x12701abb8] [O][004][INDEX 006] ClassA:Method1 () [0x1370678b8] [O][005][INDEX 001] IDefault:Method2 () [0x137067890] [O][006][INDEX 006] ClassA:Method1 () [0x1370678b8] Override map "AFTER OVERRIDING INTERFACE METHODS" EMPTY. *** Vtable for class 'ClassB' at "AFTER OVERRIDING INTERFACE METHODS" (size 7) [O][000][INDEX 000] object:GetHashCode () [0x12701ac30] [O][001][INDEX 001] object:Equals (object) [0x12701ac08] [O][002][INDEX 002] object:ToString () [0x12701abe0] [O][003][INDEX 003] object:Finalize () [0x12701abb8] [O][004][INDEX 006] ClassA:Method1 () [0x1370678b8] [O][005][INDEX 001] IDefault:Method2 () [0x137067890] [O][006][INDEX 006] ClassA:Method1 () [0x1370678b8] checking iface method IDefault:Method1 () For slot 4 (''.'IDefault':'Method1'), trying method ''.'ClassB':'Method2'... [EXPLICIT IMPLEMENTATION = 0][SLOT IS NULL = 0][RANK CHECK FAILED] checking iface method IDefault:Method2 () For slot 5 (''.'IDefault':'Method2'), trying method ''.'ClassB':'Method2'... [EXPLICIT IMPLEMENTATION = 0][SLOT IS NULL = 0][NOT EXPLICIT IMPLEMENTATION IN FULL SLOT REFUSED] [class is not abstract, checking slot 4 for interface ''.'IDefault', method Method1, slot check is 0] [class is not abstract, checking slot 5 for interface ''.'IDefault', method Method2, slot check is 0] *** Vtable for class 'ClassB' at "AFTER SETTING UP INTERFACE METHODS" (size 7) [O][000][INDEX 000] object:GetHashCode () [0x12701ac30] [O][001][INDEX 001] object:Equals (object) [0x12701ac08] [O][002][INDEX 002] object:ToString () [0x12701abe0] [O][003][INDEX 003] object:Finalize () [0x12701abb8] [O][004][INDEX 006] ClassA:Method1 () [0x1370678b8] [O][005][INDEX 001] IDefault:Method2 () [0x137067890] [O][006][INDEX 006] ClassA:Method1 () [0x1370678b8] *** Vtable for class 'ClassB' at "AFTER OVERRIDING NON-INTERFACE METHODS" (size 8) [O][000][INDEX 000] object:GetHashCode () [0x12701ac30] [O][001][INDEX 001] object:Equals (object) [0x12701ac08] [O][002][INDEX 002] object:ToString () [0x12701abe0] [O][003][INDEX 003] object:Finalize () [0x12701abb8] [O][004][INDEX 006] ClassA:Method1 () [0x1370678b8] [O][005][INDEX 001] IDefault:Method2 () [0x137067890] [O][006][INDEX 006] ClassA:Method1 () [0x1370678b8] [N][007][INDEX 007] ClassB:Method2 () [0x1370678e0] *** Vtable for class 'ClassB' at "FINALLY" (size 8) [O][000][INDEX 000] object:GetHashCode () [0x12701ac30] [O][001][INDEX 001] object:Equals (object) [0x12701ac08] [O][002][INDEX 002] object:ToString () [0x12701abe0] [O][003][INDEX 003] object:Finalize () [0x12701abb8] [O][004][INDEX 006] ClassA:Method1 () [0x1370678b8] [O][005][INDEX 001] IDefault:Method2 () [0x137067890] [O][006][INDEX 006] ClassA:Method1 () [0x1370678b8] [N][007][INDEX 007] ClassB:Method2 () [0x1370678e0]
The relevant bit is:
For slot 5 (''.'IDefault':'Method2'), trying method ''.'ClassB':'Method2'... [EXPLICIT IMPLEMENTATION = 0][SLOT IS NULL = 0][NOT EXPLICIT IMPLEMENTATION IN FULL SLOT REFUSED]
So we didn't like ClassB.Method2 because IDefault is inherited from ClassA, not explicitly implemented by ClassB.
ClassB.Method2 is always .method public hidebysig newslot virtual instance
. So when ClassA
is not abstract, or when DIMs are not in the picture at all, this makes sense to me... we have a newslot method that happens to have the same name as something that our parent already implemented. We can ignore it.
But I guess if the parent (ancestor?) is abstract then we do want to override the DIM? I think I need to read the ecma augments...
@janvorli - I don't think I've been fixing anything in this area, please note this issue deals with instance, not static virtual methods, I've only been making changes to the static path. One way or another, the reabstraction fix you reviewed about a week or two ago still hasn't been merged in because it fails in several Mono legs, I'm working with the Mono team on figuring out the fix.
FWIW, I'm somewhat surprised by the fact that the method overrides in ClassA
and ClassB
are marked as virtual
, not as override
as I'd expect, but perhaps that's just my incomplete knowledge of the C# syntax.
I think the issue is we only want to fill the vtable slot if the current class is not abstract. That is, classA's Method2 slot should be empty, and class B should fill it in with the DIM method as the last step.
PR shortly, after I validate locally that this doesn't break some other cases, to avoid public embarrassment.
Description
In net7 when using monoVM different method is called.
Reproduction Steps
This small example:
Expected behavior
the same methods to be called
Actual behavior
For CoreCLR outputs: ClassA Method 1 ClassB Method2
When using monoVM: ClassA Method 1 Interface Method2
Regression?
no
Known Workarounds
not to use default interface implementatinos
Configuration
Tested on:
net7/linux/armv6 (only supports monoVM so this is where I found it) net7/win/x64 when publishing app with
dotnet publish --self-contained true -p:UseMonoRuntime=true
net7-androidOther information
No response