@@ -3324,6 +3324,16 @@ mono_generic_context_is_sharable (MonoGenericContext *context, gboolean allow_ty
33243324 return mono_generic_context_is_sharable_full (context , allow_type_vars , partial_sharing_supported ());
33253325}
33263326
3327+ static gboolean
3328+ is_primitive_inst (MonoGenericInst * inst )
3329+ {
3330+ for (int i = 0 ; i < inst -> type_argc ; ++ i ) {
3331+ if (!MONO_TYPE_IS_PRIMITIVE (inst -> type_argv [i ]))
3332+ return FALSE;
3333+ }
3334+ return TRUE;
3335+ }
3336+
33273337/*
33283338 * mono_method_is_generic_impl:
33293339 * @method: a method
@@ -3350,18 +3360,45 @@ mono_method_is_generic_impl (MonoMethod *method)
33503360static gboolean
33513361has_constraints (MonoGenericContainer * container )
33523362{
3353- // int i;
3363+ int i ;
33543364
3355- return FALSE;
3356- /*
33573365 g_assert (container -> type_argc > 0 );
33583366 g_assert (container -> type_params );
33593367
33603368 for (i = 0 ; i < container -> type_argc ; ++ i )
3361- if (container->type_params [i].constraints)
3369+ if (container -> type_params [i ].info . constraints )
33623370 return TRUE;
33633371 return FALSE;
3364- */
3372+ }
3373+
3374+ /*
3375+ * Return whenever GPARAM can be instantiated with an enum.
3376+ */
3377+ static gboolean
3378+ gparam_can_be_enum (MonoGenericParam * gparam )
3379+ {
3380+ if (!gparam -> info .constraints )
3381+ return TRUE;
3382+ /*
3383+ * If a constraint is an interface which is not implemented by Enum, then the gparam can't be
3384+ * instantiated with an enum.
3385+ */
3386+ for (int cindex = 0 ; gparam -> info .constraints [cindex ]; cindex ++ ) {
3387+ MonoClass * k = gparam -> info .constraints [cindex ];
3388+ if (MONO_CLASS_IS_INTERFACE_INTERNAL (k )) {
3389+ MonoClass * * enum_ifaces = m_class_get_interfaces (mono_defaults .enum_class );
3390+ gboolean is_enum_iface = FALSE;
3391+ for (int i = 0 ; i < m_class_get_interface_count (mono_defaults .enum_class ); i ++ ) {
3392+ if (k == enum_ifaces [i ]) {
3393+ is_enum_iface = TRUE;
3394+ break ;
3395+ }
3396+ }
3397+ if (!is_enum_iface )
3398+ return FALSE;
3399+ }
3400+ }
3401+ return TRUE;
33653402}
33663403
33673404static gboolean
@@ -3488,21 +3525,39 @@ mono_method_is_generic_sharable_full (MonoMethod *method, gboolean allow_type_va
34883525
34893526 g_assert (inflated -> declaring );
34903527
3528+ #if FALSE
34913529 if (inflated -> declaring -> is_generic ) {
3492- if (has_constraints (mono_method_get_generic_container (inflated -> declaring )))
3493- return FALSE;
3530+ if (has_constraints (mono_method_get_generic_container (inflated -> declaring ))) {
3531+ }
34943532 }
3533+ #endif
34953534 }
34963535
34973536 if (mono_class_is_ginst (method -> klass )) {
3498- if (!mono_generic_context_is_sharable_full (& mono_class_get_generic_class (method -> klass )-> context , allow_type_vars , allow_partial ))
3537+ MonoGenericContext * ctx = & mono_class_get_generic_class (method -> klass )-> context ;
3538+ if (!mono_generic_context_is_sharable_full (ctx , allow_type_vars , allow_partial ))
34993539 return FALSE;
35003540
35013541 g_assert (mono_class_get_generic_class (method -> klass )-> container_class &&
35023542 mono_class_is_gtd (mono_class_get_generic_class (method -> klass )-> container_class ));
35033543
3504- if (has_constraints (mono_class_get_generic_container (mono_class_get_generic_class (method -> klass )-> container_class )))
3505- return FALSE;
3544+ /*
3545+ * If all the parameters are primitive types and constraints prevent
3546+ * them from being instantiated with enums, then only the primitive
3547+ * type instantiation is possible, thus sharing is not useful.
3548+ * Happens with generic math interfaces.
3549+ */
3550+ if ((!ctx -> class_inst || is_primitive_inst (ctx -> class_inst )) &&
3551+ (!ctx -> method_inst || is_primitive_inst (ctx -> method_inst ))) {
3552+ MonoGenericContainer * container = mono_class_get_generic_container (mono_class_get_generic_class (method -> klass )-> container_class );
3553+ if (has_constraints (container )) {
3554+ g_assert (ctx -> class_inst -> type_argc == container -> type_argc );
3555+ for (int i = 0 ; i < container -> type_argc ; ++ i ) {
3556+ if (!gparam_can_be_enum (& container -> type_params [i ]))
3557+ return FALSE;
3558+ }
3559+ }
3560+ }
35063561 }
35073562
35083563 if (mono_class_is_gtd (method -> klass ) && !allow_type_vars )
0 commit comments