C#: Narrow the set of declarations where we make explicit interface implementations.

This commit is contained in:
Michael Nebel
2023-03-03 09:14:35 +01:00
parent d8acc7cd17
commit e797b5c226

View File

@@ -400,7 +400,7 @@ private string stubAccessibility(Member m) {
if
m.getDeclaringType() instanceof Interface
or
exists(getSingleSpecificImplementedInterface(m))
exists(useExplicitImplementedInterface(m))
or
m instanceof Constructor and m.isStatic()
then result = ""
@@ -713,13 +713,49 @@ private string stubEventAccessors(Event e) {
else result = ";"
}
private Interface getSingleSpecificImplementedInterface(Member c) {
result = unique(Interface i | i = c.(Virtualizable).getExplicitlyImplementedInterface())
/**
* Returns an interface that `c` explicitly implements, if either or the
* following holds.
* (1) `c` is not static.
* (2) `c` is static and an implementation of a generic with type constraints.
* (3) `c` is static and there is another member with the same name
* but different return types.
*
* We use these rules, as explicit interfaces are needed in some cases, eg.
* for compilation purposes (both to distinguish members but also to ensure
* type constraints are satisfied). We can't always use the explicit interface
* due to the generic math support, because then in some cases we will only be
* able to access a static via a type variable with type
* constraints (C# 11 language feature).
*/
private Interface useExplicitImplementedInterface(Virtualizable c) {
result = unique(Interface i | i = c.getExplicitlyImplementedInterface()) and
(
not c.isStatic()
or
c.isStatic() and
(
not c instanceof Method
or
c instanceof Method and
(
exists(TypeParameter t | t = c.getImplementee().(UnboundGeneric).getATypeParameter() |
exists(t.getConstraints().getATypeConstraint())
)
or
exists(Member m |
(not m.isStatic() or m.(Method).getReturnType() != c.(Method).getReturnType()) and
m.getName() = c.getName() and
m.getDeclaringType() = c.getDeclaringType()
)
)
)
)
}
private string stubExplicitImplementation(Member c) {
if exists(getSingleSpecificImplementedInterface(c))
then result = stubClassName(getSingleSpecificImplementedInterface(c)) + "."
if exists(useExplicitImplementedInterface(c))
then result = stubClassName(useExplicitImplementedInterface(c)) + "."
else result = ""
}