Skip to content

Commit 8c5f347

Browse files
committed
Skip exact interface matches when an interface has variance
Search for interface matches starting from the end instead of the beginning of the list
1 parent 39c4905 commit 8c5f347

File tree

1 file changed

+37
-10
lines changed

1 file changed

+37
-10
lines changed

src/mono/mono/metadata/class.c

Lines changed: 37 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1946,32 +1946,52 @@ mono_class_interface_offset (MonoClass *klass, MonoClass *itf)
19461946
int
19471947
mono_class_interface_offset_with_variance (MonoClass *klass, MonoClass *itf, gboolean *non_exact_match)
19481948
{
1949-
int i = mono_class_interface_offset (klass, itf);
1949+
// const char *iname = mono_type_get_name_full (m_class_get_byval_arg (itf), MONO_TYPE_NAME_FORMAT_FULL_NAME);
1950+
gboolean has_variance = mono_class_has_variant_generic_params (itf);
1951+
int exact_match = mono_class_interface_offset (klass, itf), i = -1;
19501952
*non_exact_match = FALSE;
1951-
if (i >= 0)
1952-
return i;
1953+
1954+
if (exact_match >= 0) {
1955+
// g_print ("exact match for %s on %s\n", iname, m_class_get_name (klass));
1956+
if (!has_variance)
1957+
return exact_match;
1958+
}
19531959

19541960
int klass_interface_offsets_count = m_class_get_interface_offsets_count (klass);
19551961

19561962
if (m_class_is_array_special_interface (itf) && m_class_get_rank (klass) < 2) {
19571963
MonoClass *gtd = mono_class_get_generic_type_definition (itf);
19581964
int found = -1;
19591965

1960-
for (i = 0; i < klass_interface_offsets_count; i++) {
1966+
for (i = klass_interface_offsets_count - 1; i >= 0; i--) {
19611967
if (mono_class_is_variant_compatible (itf, m_class_get_interfaces_packed (klass) [i], FALSE)) {
1968+
/*
1969+
g_print (
1970+
"is_variant_compatible (%s, %s, FALSE) == true\n",
1971+
iname,
1972+
mono_type_get_name_full (m_class_get_byval_arg (m_class_get_interfaces_packed (klass) [i]), MONO_TYPE_NAME_FORMAT_FULL_NAME)
1973+
);
1974+
*/
19621975
found = i;
1963-
*non_exact_match = TRUE;
1976+
*non_exact_match = (i != exact_match);
19641977
break;
19651978
}
19661979

19671980
}
19681981
if (found != -1)
19691982
return m_class_get_interface_offsets_packed (klass) [found];
19701983

1971-
for (i = 0; i < klass_interface_offsets_count; i++) {
1984+
for (i = klass_interface_offsets_count - 1; i >= 0; i--) {
19721985
if (mono_class_get_generic_type_definition (m_class_get_interfaces_packed (klass) [i]) == gtd) {
1986+
/*
1987+
g_print (
1988+
"gtd_of (%s) == gtd_of (%s)\n",
1989+
mono_type_get_name_full (m_class_get_byval_arg (m_class_get_interfaces_packed (klass) [i]), MONO_TYPE_NAME_FORMAT_FULL_NAME),
1990+
iname
1991+
);
1992+
*/
19731993
found = i;
1974-
*non_exact_match = TRUE;
1994+
*non_exact_match = (i != exact_match);
19751995
break;
19761996
}
19771997
}
@@ -1982,12 +2002,19 @@ mono_class_interface_offset_with_variance (MonoClass *klass, MonoClass *itf, gbo
19822002
return m_class_get_interface_offsets_packed (klass) [found];
19832003
}
19842004

1985-
if (!mono_class_has_variant_generic_params (itf))
2005+
if (!has_variance)
19862006
return -1;
19872007

1988-
for (i = 0; i < klass_interface_offsets_count; i++) {
2008+
for (i = klass_interface_offsets_count - 1; i >= 0; i--) {
19892009
if (mono_class_is_variant_compatible (itf, m_class_get_interfaces_packed (klass) [i], FALSE)) {
1990-
*non_exact_match = TRUE;
2010+
/*
2011+
g_print (
2012+
"is_variant_compatible (%s, %s, FALSE) == true\n",
2013+
iname,
2014+
mono_type_get_name_full (m_class_get_byval_arg (m_class_get_interfaces_packed (klass) [i]), MONO_TYPE_NAME_FORMAT_FULL_NAME)
2015+
);
2016+
*/
2017+
*non_exact_match = (i != exact_match);
19912018
return m_class_get_interface_offsets_packed (klass) [i];
19922019
}
19932020
}

0 commit comments

Comments
 (0)