From d679d95a21da31f186a3c2bde733c6ff649be62a Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Fri, 27 Sep 2024 16:12:18 -0600 Subject: [PATCH] Avoid using `UnscopedRefAttribute` on downlevel *compilers* Fixes #1205 --- src/Microsoft.Windows.CsWin32/Generator.Features.cs | 1 + src/Microsoft.Windows.CsWin32/Generator.cs | 6 ++++++ .../templates/VariableLengthInlineArray`1.cs | 4 ++++ 3 files changed, 11 insertions(+) diff --git a/src/Microsoft.Windows.CsWin32/Generator.Features.cs b/src/Microsoft.Windows.CsWin32/Generator.Features.cs index b9061353..23950116 100644 --- a/src/Microsoft.Windows.CsWin32/Generator.Features.cs +++ b/src/Microsoft.Windows.CsWin32/Generator.Features.cs @@ -5,6 +5,7 @@ namespace Microsoft.Windows.CsWin32; public partial class Generator { + private readonly bool canUseUnscopedRef; private readonly bool canUseSpan; private readonly bool canCallCreateSpan; private readonly bool canUseUnsafeAsRef; diff --git a/src/Microsoft.Windows.CsWin32/Generator.cs b/src/Microsoft.Windows.CsWin32/Generator.cs index 37fcaed9..91f3aef0 100644 --- a/src/Microsoft.Windows.CsWin32/Generator.cs +++ b/src/Microsoft.Windows.CsWin32/Generator.cs @@ -85,6 +85,11 @@ public Generator(string metadataLibraryPath, Docs? docs, GeneratorOptions option this.parseOptions = parseOptions; this.volatileCode = new(this.committedCode); + // UnscopedRefAttribute may be emitted to work on downlevel *runtimes*, but we can't use it + // on downlevel *compilers*. Only .NET 8+ SDK compilers support it. Since we cannot detect + // compiler version, we use language version instead. + this.canUseUnscopedRef = this.parseOptions?.LanguageVersion >= (LanguageVersion)1100; // C# 11.0 + this.canUseSpan = this.compilation?.GetTypeByMetadataName(typeof(Span<>).FullName) is not null; this.canCallCreateSpan = this.compilation?.GetTypeByMetadataName(typeof(MemoryMarshal).FullName)?.GetMembers("CreateSpan").Any() is true; this.canUseUnsafeAsRef = this.compilation?.GetTypeByMetadataName(typeof(Unsafe).FullName)?.GetMembers("Add").Any() is true; @@ -117,6 +122,7 @@ public Generator(string metadataLibraryPath, Docs? docs, GeneratorOptions option AddSymbolIf(this.canUseUnsafeNullRef, "canUseUnsafeNullRef"); AddSymbolIf(compilation?.GetTypeByMetadataName("System.Drawing.Point") is not null, "canUseSystemDrawing"); AddSymbolIf(this.IsFeatureAvailable(Feature.InterfaceStaticMembers), "canUseInterfaceStaticMembers"); + AddSymbolIf(this.canUseUnscopedRef, "canUseUnscopedRef"); if (extraSymbols.Count > 0) { diff --git a/src/Microsoft.Windows.CsWin32/templates/VariableLengthInlineArray`1.cs b/src/Microsoft.Windows.CsWin32/templates/VariableLengthInlineArray`1.cs index d29ed33d..31c6935f 100644 --- a/src/Microsoft.Windows.CsWin32/templates/VariableLengthInlineArray`1.cs +++ b/src/Microsoft.Windows.CsWin32/templates/VariableLengthInlineArray`1.cs @@ -3,6 +3,8 @@ { internal T e0; +#if canUseUnscopedRef + #if canUseUnsafeAdd internal ref T this[int index] { @@ -30,4 +32,6 @@ internal Span AsSpan(int length) #endif } #endif + +#endif }