diff --git a/.gitattributes b/.gitattributes
index a6227fffc..1d3ed1d12 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -2,6 +2,7 @@
*.cs text eol=crlf diff=csharp
*.sln text eol=crlf
*.csproj text eol=crlf
+*.resx text eol=crlf
# Consumed verbatim by Linux tools (shell-executed rpm spec, dpkg control, desktop entry);
# CRLF breaks them, so keep them LF even in Windows working trees.
*.spec text eol=lf
diff --git a/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj b/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj
index 1b4339f43..cba53f058 100644
--- a/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj
+++ b/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj
@@ -212,6 +212,8 @@
+
+
diff --git a/ICSharpCode.Decompiler.Tests/ILPrettyTestRunner.cs b/ICSharpCode.Decompiler.Tests/ILPrettyTestRunner.cs
index 2026ad906..7e9f8df94 100644
--- a/ICSharpCode.Decompiler.Tests/ILPrettyTestRunner.cs
+++ b/ICSharpCode.Decompiler.Tests/ILPrettyTestRunner.cs
@@ -303,6 +303,12 @@ namespace ICSharpCode.Decompiler.Tests
await Run();
}
+ [Test]
+ public async Task SpanConversionOperatorMismatch()
+ {
+ await Run(settings: new DecompilerSettings { FileScopedNamespaces = false, FirstClassSpanTypes = true });
+ }
+
[Test]
public async Task ConstantBlobs()
{
diff --git a/ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs b/ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs
index 634aaa5cf..3a16f4270 100644
--- a/ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs
+++ b/ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs
@@ -800,6 +800,18 @@ namespace ICSharpCode.Decompiler.Tests
await RunForLibrary(cscOptions: cscOptions);
}
+ [Test]
+ public async Task FirstClassSpanTypes([ValueSource(nameof(roslyn5OrNewerOptions))] CompilerOptions cscOptions)
+ {
+ await RunForLibrary(cscOptions: cscOptions);
+ }
+
+ [Test]
+ public async Task FirstClassSpanConversions([ValueSource(nameof(roslyn5OrNewerOptions))] CompilerOptions cscOptions)
+ {
+ await RunForLibrary(cscOptions: cscOptions);
+ }
+
[Test]
public async Task ExpandParamsArgumentsDisabled([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
{
diff --git a/ICSharpCode.Decompiler.Tests/Semantics/ConversionTests.cs b/ICSharpCode.Decompiler.Tests/Semantics/ConversionTests.cs
index 3d5308925..ab1bf9af9 100644
--- a/ICSharpCode.Decompiler.Tests/Semantics/ConversionTests.cs
+++ b/ICSharpCode.Decompiler.Tests/Semantics/ConversionTests.cs
@@ -1787,5 +1787,74 @@ namespace ICSharpCode.Decompiler.Tests.Semantics
return conversions.ImplicitConversion(bodyReturnType, returnType);
}
}
+
+ #region First-class span conversions
+ Conversion SpanConversion(Type from, Type to)
+ {
+ var c = RefAssemblyCompilation.Instance;
+ return CSharpConversions.Get(c).ImplicitConversion(c.FindType(from), c.FindType(to));
+ }
+
+ [Test]
+ public void ImplicitSpanConversions()
+ {
+ Assert.That(SpanConversion(typeof(string), typeof(ReadOnlySpan)), Is.EqualTo(C.ImplicitSpanConversion),
+ "the span conversion must win over String's own op_Implicit: user-defined conversions are not considered between span-convertible types");
+ Assert.That(SpanConversion(typeof(string[]), typeof(Span)), Is.EqualTo(C.ImplicitSpanConversion));
+ Assert.That(SpanConversion(typeof(string[]), typeof(ReadOnlySpan