Skip to content

Commit b686890

Browse files
committed
C#: Address review comments.
1 parent 1817f9c commit b686890

File tree

3 files changed

+43
-31
lines changed

3 files changed

+43
-31
lines changed

csharp/ql/lib/semmle/code/csharp/Conversion.qll

Lines changed: 5 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -535,7 +535,7 @@ predicate convSpan(Type fromType, Type toType) {
535535
|
536536
convIdentity(fromElementType, toElementType)
537537
or
538-
convCovariance(fromElementType, toElementType)
538+
convVariance(fromElementType, toElementType)
539539
)
540540
or
541541
fromType instanceof SystemStringClass and
@@ -835,8 +835,8 @@ predicate convConversionOperator(Type fromType, Type toType) {
835835
)
836836
}
837837

838-
pragma[nomagic]
839-
private predicate convVarianceAux(UnboundGenericType ugt, GenericType fromType, GenericType toType) {
838+
/** 13.1.3.2: Variance conversion. */
839+
private predicate convVariance(GenericType fromType, GenericType toType) {
840840
// Semantically equivalent with
841841
// ```ql
842842
// ugt = fromType.getUnboundGeneric()
@@ -856,23 +856,10 @@ private predicate convVarianceAux(UnboundGenericType ugt, GenericType fromType,
856856
// ```
857857
// but performance is improved by explicitly evaluating the `i`th argument
858858
// only when all preceding arguments are convertible.
859-
Variance::convVarianceSingle(ugt, fromType, toType)
859+
Variance::convVarianceSingle(_, fromType, toType)
860860
or
861-
Variance::convVarianceMultiple(ugt, fromType, toType, ugt.getNumberOfTypeParameters() - 1)
862-
}
863-
864-
/** 13.1.3.2: Variance conversion. */
865-
private predicate convVariance(GenericType fromType, GenericType toType) {
866-
convVarianceAux(_, fromType, toType)
867-
}
868-
869-
/**
870-
* Holds, if `fromType` is covariance convertible to `toType`.
871-
*/
872-
private predicate convCovariance(GenericType fromType, GenericType toType) {
873861
exists(UnboundGenericType ugt |
874-
convVarianceAux(ugt, fromType, toType) and
875-
forall(TypeParameter tp | tp = ugt.getATypeParameter() | tp.isOut())
862+
Variance::convVarianceMultiple(ugt, fromType, toType, ugt.getNumberOfTypeParameters() - 1)
876863
)
877864
}
878865

csharp/ql/test/library-tests/conversion/span/Span.cs

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,11 @@
33

44
public interface CovariantInterface<out T> { }
55

6+
public interface ContravariantInterface<in T> { }
7+
68
public interface InvariantInterface<T> { }
79

8-
public interface Interface<out T1, T2> { }
10+
public interface MixedInterface<out T1, in T2> { }
911

1012
public class Base { }
1113

@@ -16,14 +18,14 @@ public class C
1618
public void M()
1719
{
1820
string[] stringArray = [];
19-
string[][] stringArrayArray;
20-
string[,] stringArray2D;
21+
string[][] stringArrayArray = [];
22+
string[,] stringArray2D = new string[0, 0];
2123

2224
Span<string> stringSpan = stringArray; // string[] -> Span<string>;
2325

24-
// Covariant conversions to ReadOnlySpan
25-
// Assignments are included to illustrate that this compiles.
26+
// Assignments are included to illustrate that it compiles.
2627
// Only the use of the types matter in terms of test output.
28+
// Covariant conversions to ReadOnlySpan
2729
ReadOnlySpan<CovariantInterface<Base>> covariantInterfaceBaseReadOnlySpan;
2830
ReadOnlySpan<CovariantInterface<Derived>> covariantInterfaceDerivedReadOnlySpan = default;
2931
Span<CovariantInterface<Derived>> covariantInterfaceDerivedSpan = default;
@@ -37,18 +39,32 @@ public void M()
3739
stringReadOnlySpan = stringSpan; // Span<string> -> ReadOnlySpan<string>;
3840
stringReadOnlySpan = stringArray; // string[] -> ReadOnlySpan<string>;
3941

42+
// Contravariant conversions to ReadOnlySpan
43+
ReadOnlySpan<ContravariantInterface<Derived>> contravariantInterfaceDerivedReadOnlySpan;
44+
ReadOnlySpan<ContravariantInterface<Base>> contravariantInterfaceBaseReadOnlySpan = default;
45+
Span<ContravariantInterface<Base>> contravariantInterfaceBaseSpan = default;
46+
ContravariantInterface<Base>[] contravariantInterfaceBaseArray = [];
47+
contravariantInterfaceDerivedReadOnlySpan = contravariantInterfaceBaseReadOnlySpan; // ReadOnlySpan<ContravariantInterface<Base>> -> ReadOnlySpan<ContravariantInterface<Derived>>
48+
contravariantInterfaceDerivedReadOnlySpan = contravariantInterfaceBaseSpan; // Span<ContravariantInterface<Base>> -> ReadOnlySpan<ContravariantInterface<Derived>>
49+
contravariantInterfaceDerivedReadOnlySpan = contravariantInterfaceBaseArray; // ContravariantInterface<Base>[] -> ReadOnlySpan<ContravariantInterface<Derived>>
50+
51+
// Mixed variance conversions to ReadOnlySpan
52+
ReadOnlySpan<MixedInterface<Base, Derived>> mixedInterfaceBaseReadOnlySpan;
53+
ReadOnlySpan<MixedInterface<Derived, Base>> mixedInterfaceDerivedReadOnlySpan = default;
54+
Span<MixedInterface<Derived, Base>> mixedInterfaceDerivedSpan = default;
55+
MixedInterface<Derived, Base>[] mixedInterfaceDerivedArray = [];
56+
mixedInterfaceBaseReadOnlySpan = mixedInterfaceDerivedReadOnlySpan; // ReadOnlySpan<MixedInterface<Derived, Base>> -> ReadOnlySpan<MixedInterface<Base, Derived>>
57+
mixedInterfaceBaseReadOnlySpan = mixedInterfaceDerivedSpan; // Span<MixedInterface<Derived, Base>> -> ReadOnlySpan<MixedInterface<Base, Derived>>
58+
mixedInterfaceBaseReadOnlySpan = mixedInterfaceDerivedArray; // MixedInterface<Derived, Base>[] -> ReadOnlySpan<MixedInterface<Base, Derived>>
59+
4060
// Convert string to ReadOnlySpan<char>
4161
string s = "";
4262
ReadOnlySpan<char> charReadOnlySpan = s; // string -> ReadOnlySpan<char>
4363

44-
// Use the non-covariant interfaces to show that no conversion is possible.
64+
// No conversion possible except for identity.
4565
ReadOnlySpan<InvariantInterface<Base>> invariantInterfaceBaseReadOnlySpan;
4666
ReadOnlySpan<InvariantInterface<Derived>> invariantInterfaceDerivedReadOnlySpan;
4767
Span<InvariantInterface<Derived>> invariantInterfaceDerivedSpan;
4868
InvariantInterface<Derived>[] invariantInterfaceDerivedArray;
49-
ReadOnlySpan<Interface<Base, string>> interfaceBaseReadOnlySpan;
50-
ReadOnlySpan<Interface<Derived, string>> interfaceDerivedReadOnlySpan;
51-
Span<Interface<Derived, string>> interfaceDerivedSpan;
52-
Interface<Derived, string>[] interfaceDerivedArray;
5369
}
5470
}

csharp/ql/test/library-tests/conversion/span/span.expected

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,24 @@
1+
| ContravariantInterface<Base>[] | ReadOnlySpan<ContravariantInterface<Base>> |
2+
| ContravariantInterface<Base>[] | ReadOnlySpan<ContravariantInterface<Derived>> |
3+
| ContravariantInterface<Base>[] | Span<ContravariantInterface<Base>> |
14
| CovariantInterface<Derived>[] | ReadOnlySpan<CovariantInterface<Base>> |
25
| CovariantInterface<Derived>[] | ReadOnlySpan<CovariantInterface<Derived>> |
36
| CovariantInterface<Derived>[] | Span<CovariantInterface<Derived>> |
4-
| Interface<Derived,String>[] | ReadOnlySpan<Interface<Derived, string>> |
5-
| Interface<Derived,String>[] | Span<Interface<Derived, string>> |
67
| InvariantInterface<Derived>[] | ReadOnlySpan<InvariantInterface<Derived>> |
78
| InvariantInterface<Derived>[] | Span<InvariantInterface<Derived>> |
9+
| MixedInterface<Derived,Base>[] | ReadOnlySpan<MixedInterface<Base, Derived>> |
10+
| MixedInterface<Derived,Base>[] | ReadOnlySpan<MixedInterface<Derived, Base>> |
11+
| MixedInterface<Derived,Base>[] | Span<MixedInterface<Derived, Base>> |
12+
| ReadOnlySpan<ContravariantInterface<Base>> | ReadOnlySpan<ContravariantInterface<Derived>> |
813
| ReadOnlySpan<CovariantInterface<Derived>> | ReadOnlySpan<CovariantInterface<Base>> |
14+
| ReadOnlySpan<MixedInterface<Derived, Base>> | ReadOnlySpan<MixedInterface<Base, Derived>> |
15+
| Span<ContravariantInterface<Base>> | ReadOnlySpan<ContravariantInterface<Base>> |
16+
| Span<ContravariantInterface<Base>> | ReadOnlySpan<ContravariantInterface<Derived>> |
917
| Span<CovariantInterface<Derived>> | ReadOnlySpan<CovariantInterface<Base>> |
1018
| Span<CovariantInterface<Derived>> | ReadOnlySpan<CovariantInterface<Derived>> |
11-
| Span<Interface<Derived, string>> | ReadOnlySpan<Interface<Derived, string>> |
1219
| Span<InvariantInterface<Derived>> | ReadOnlySpan<InvariantInterface<Derived>> |
20+
| Span<MixedInterface<Derived, Base>> | ReadOnlySpan<MixedInterface<Base, Derived>> |
21+
| Span<MixedInterface<Derived, Base>> | ReadOnlySpan<MixedInterface<Derived, Base>> |
1322
| Span<string> | ReadOnlySpan<string> |
1423
| String[] | ReadOnlySpan<string> |
1524
| String[] | Span<string> |

0 commit comments

Comments
 (0)