Bug 60545

Summary: Multiple argument generic with contravariant interface as an argument causes MissingMethodException.
Product: [Mono] Runtime Reporter: Timofey Pokhilenko <zhakataka>
Component: GeneralAssignee: Aleksey Kliger <aleksey>
Status: RESOLVED FIXED    
Severity: normal CC: aleksey, ludovic, mono-bugs+mono, mono-bugs+runtime
Priority: Normal    
Version: 5.8 (2017-10)   
Target Milestone: Future Cycle (TBD)   
Hardware: PC   
OS: All   
Tags: bugpool-archive Is this bug a regression?: ---
Last known good build:
Attachments: Minimal code reproducing this bug. See the readme file.

Description Timofey Pokhilenko 2017-11-07 05:04:27 UTC
Created attachment 25575 [details]
Minimal code reproducing this bug. See the readme file.

Somehow a contravariant interface used as an argument for a generic with more than two arguments causes contravariance failure with MissingMethodException under certain conditions.
See the attached solution with the minimal code. (Readme file with some suggestions is included).

Bug reproduces on:
Mono (both Windows and Linux)
Unity3D (.NET 4.6 runtime, tested on Windows)
Xamarin (tested via x86 Android emulator)
Comment 1 Ludovic Henry 2017-11-08 18:08:06 UTC
I can reproduce with Mono 5.8.0.40 (2017-10/ce494e3d152)
Comment 2 Aleksey Kliger 2017-11-14 16:30:18 UTC
Interestingly, if you AOT the .exe (and mscorlib.dll) and then run with fullaot, the test passes.


     $ mono --full-aot BrokenContravariance.exe 
     Testing...
     Action performed on String
     Passed!
Comment 3 Aleksey Kliger 2017-11-16 22:36:38 UTC
loader.c:get_constrained_method() is doing complicated things for `constrained.callvirt` calls, to find the method that implements an interface in the constraining class (and gets it wrong in the case of variant interfaces).

But vtable and interface setup already do all the hard work for us. To computer the constrained MonoMethod*:
   if constraining a virtual method of a class consult the corresponding vtable entry of the constraining class and return that MonoMethod*.
   if constraining an interface method, find the base interface offset of the interface on the constraining class, bump it the interface slot of the method, and look in the corresponding vtable entry for the MonoMethod*.
Comment 4 Ludovic Henry 2017-11-21 20:30:31 UTC
https://github.com/mono/mono/pull/6037
Comment 5 Ludovic Henry 2017-11-21 20:31:16 UTC
https://github.com/mono/mono/pull/6067 is a fix for the interpreter which was broken by PR from https://bugzilla.xamarin.com/show_bug.cgi?id=60545#c4
Comment 6 Aleksey Kliger 2017-11-22 21:52:05 UTC
Fixed on mono master after https://github.com/mono/mono/commit/9d6f4309948ef9a967accb6d15ab92cfe3d98e63
(this is a follow-on commit; the original partly incorrect fix was https://github.com/mono/mono/commit/3259e04ace67552fc8d63a8f1ddbb830e526f05f)

Fixed on mono 2017-10 https://github.com/mono/mono/commit/ef5b3b466368252f532d89cf97f10f8b785eca01
(This has the corrected fix).