@@ -400,7 +400,7 @@ private string stubAccessibility(Member m) {
400400 if
401401 m .getDeclaringType ( ) instanceof Interface
402402 or
403- exists ( getSingleSpecificImplementedInterface ( m ) )
403+ exists ( useExplicitImplementedInterface ( m ) )
404404 or
405405 m instanceof Constructor and m .isStatic ( )
406406 then result = ""
@@ -713,13 +713,49 @@ private string stubEventAccessors(Event e) {
713713 else result = ";"
714714}
715715
716- private Interface getSingleSpecificImplementedInterface ( Member c ) {
717- result = unique( Interface i | i = c .( Virtualizable ) .getExplicitlyImplementedInterface ( ) )
716+ /**
717+ * Returns an interface that `c` explicitly implements, if either or the
718+ * following holds.
719+ * (1) `c` is not static.
720+ * (2) `c` is static and an implementation of a generic with type constraints.
721+ * (3) `c` is static and there is another member with the same name
722+ * but different return types.
723+ *
724+ * We use these rules, as explicit interfaces are needed in some cases, eg.
725+ * for compilation purposes (both to distinguish members but also to ensure
726+ * type constraints are satisfied). We can't always use the explicit interface
727+ * due to the generic math support, because then in some cases we will only be
728+ * able to access a static via a type variable with type
729+ * constraints (C# 11 language feature).
730+ */
731+ private Interface useExplicitImplementedInterface ( Virtualizable c ) {
732+ result = unique( Interface i | i = c .getExplicitlyImplementedInterface ( ) ) and
733+ (
734+ not c .isStatic ( )
735+ or
736+ c .isStatic ( ) and
737+ (
738+ not c instanceof Method
739+ or
740+ c instanceof Method and
741+ (
742+ exists ( TypeParameter t | t = c .getImplementee ( ) .( UnboundGeneric ) .getATypeParameter ( ) |
743+ exists ( t .getConstraints ( ) .getATypeConstraint ( ) )
744+ )
745+ or
746+ exists ( Member m |
747+ ( not m .isStatic ( ) or m .( Method ) .getReturnType ( ) != c .( Method ) .getReturnType ( ) ) and
748+ m .getName ( ) = c .getName ( ) and
749+ m .getDeclaringType ( ) = c .getDeclaringType ( )
750+ )
751+ )
752+ )
753+ )
718754}
719755
720756private string stubExplicitImplementation ( Member c ) {
721- if exists ( getSingleSpecificImplementedInterface ( c ) )
722- then result = stubClassName ( getSingleSpecificImplementedInterface ( c ) ) + "."
757+ if exists ( useExplicitImplementedInterface ( c ) )
758+ then result = stubClassName ( useExplicitImplementedInterface ( c ) ) + "."
723759 else result = ""
724760}
725761
0 commit comments