-
Notifications
You must be signed in to change notification settings - Fork 4.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Different behaviour of default interface impelmentation in monoVM vs CoreCLR #81882
Comments
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 debug log*** 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:
So we didn't like ClassB.Method2 because IDefault is inherited from ClassA, not explicitly implemented by ClassB. ClassB.Method2 is always 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 |
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. runtime/src/mono/mono/metadata/class-setup-vtable.c Lines 1920 to 1924 in d067431
PR shortly, after I validate locally that this doesn't break some other cases, to avoid public embarrassment. |
leave the slot NULL and allow leaf classes to fill it in. Related to dotnet#81882
) * [class] treat slot as empty if it's filled in with a DIM Classes may override an interface method slot if it was filled in with a DIM, just as if it was empty. Related to #81882
Fixed in #82556 |
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-android
Other information
No response
The text was updated successfully, but these errors were encountered: