Skip to content

Commit e797b5c

Browse files
committed
C#: Narrow the set of declarations where we make explicit interface implementations.
1 parent d8acc7c commit e797b5c

File tree

1 file changed

+41
-5
lines changed

1 file changed

+41
-5
lines changed

csharp/ql/src/Stubs/Stubs.qll

Lines changed: 41 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -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

720756
private 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

Comments
 (0)