Bug 60545 - Multiple argument generic with contravariant interface as an argument causes MissingMethodException.
Summary: Multiple argument generic with contravariant interface as an argument causes ...
Alias: None
Product: Runtime
Classification: Mono
Component: General (show other bugs)
Version: 5.8 (2017-10)
Hardware: PC All
: Normal normal
Target Milestone: Future Cycle (TBD)
Assignee: Aleksey Kliger
Depends on:
Reported: 2017-11-07 05:04 UTC by Timofey Pokhilenko
Modified: 2018-01-05 13:27 UTC (History)
4 users (show)

See Also:
Tags: bugpool-archive
Is this bug a regression?: ---
Last known good build:

Minimal code reproducing this bug. See the readme file. (2.85 KB, application/gzip)
2017-11-07 05:04 UTC, Timofey Pokhilenko

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 (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 
     Action performed on String
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
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).

Note You need to log in before you can comment on or make changes to this bug.