Skip to content

Commit 6910642

Browse files
committed
C#: Add implicit span conversion test case.
1 parent 119ecff commit 6910642

File tree

2 files changed

+63
-0
lines changed

2 files changed

+63
-0
lines changed
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
using System;
2+
using System.Collections.Generic;
3+
4+
public interface CovariantInterface<out T> { }
5+
6+
public interface InvariantInterface<T> { }
7+
8+
public interface Interface<out T1, T2> { }
9+
10+
public class Base { }
11+
12+
public class Derived : Base { }
13+
14+
public class C
15+
{
16+
public void M()
17+
{
18+
string[] stringArray = [];
19+
string[][] stringArrayArray;
20+
string[,] stringArray2D;
21+
22+
Span<string> stringSpan = stringArray; // string[] -> Span<string>;
23+
24+
// Covariant conversions to ReadOnlySpan
25+
// Assignments are included to illustrate that this compiles.
26+
// Only the use of the types matter in terms of test output.
27+
ReadOnlySpan<CovariantInterface<Base>> covariantInterfaceBaseReadOnlySpan;
28+
ReadOnlySpan<CovariantInterface<Derived>> covariantInterfaceDerivedReadOnlySpan = default;
29+
Span<CovariantInterface<Derived>> covariantInterfaceDerivedSpan = default;
30+
CovariantInterface<Derived>[] covariantInterfaceDerivedArray = [];
31+
covariantInterfaceBaseReadOnlySpan = covariantInterfaceDerivedReadOnlySpan; // ReadOnlySpan<CovariantInterface<Derived>> -> ReadOnlySpan<CovariantInterface<Base>>
32+
covariantInterfaceBaseReadOnlySpan = covariantInterfaceDerivedSpan; // Span<CovariantInterface<Derived>> -> ReadOnlySpan<CovariantInterface<Base>>
33+
covariantInterfaceBaseReadOnlySpan = covariantInterfaceDerivedArray; // CovariantInterface<Derived>[] -> ReadOnlySpan<CovariantInterface<Base>>
34+
35+
// Identify conversions to ReadOnlySpan
36+
ReadOnlySpan<string> stringReadOnlySpan;
37+
stringReadOnlySpan = stringSpan; // Span<string> -> ReadOnlySpan<string>;
38+
stringReadOnlySpan = stringArray; // string[] -> ReadOnlySpan<string>;
39+
40+
// Convert string to ReadOnlySpan<char>
41+
string s = "";
42+
ReadOnlySpan<char> charReadOnlySpan = s; // string -> ReadOnlySpan<char>
43+
44+
// Use the non-covariant interfaces to show that no conversion is possible.
45+
ReadOnlySpan<InvariantInterface<Base>> invariantInterfaceBaseReadOnlySpan;
46+
ReadOnlySpan<InvariantInterface<Derived>> invariantInterfaceDerivedReadOnlySpan;
47+
Span<InvariantInterface<Derived>> invariantInterfaceDerivedSpan;
48+
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;
53+
}
54+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import semmle.code.csharp.Conversion
2+
3+
private class InterestingType extends Type {
4+
InterestingType() { exists(LocalVariable lv | lv.getType() = this) }
5+
}
6+
7+
from InterestingType sub, InterestingType sup
8+
where convSpan(sub, sup) and sub != sup
9+
select sub.toStringWithTypes() as s1, sup.toStringWithTypes() as s2 order by s1, s2

0 commit comments

Comments
 (0)