From 6a0c1e794b01747db9880b36f56ef946814ffdfb Mon Sep 17 00:00:00 2001 From: Andy Gocke Date: Fri, 18 Apr 2025 15:19:38 -0700 Subject: [PATCH 1/2] Create error on LibraryImport of generic delegate Fixes #113590 --- .../gen/Common/Resources/Strings.resx | 57 ++++++++++--------- .../gen/Common/Resources/xlf/Strings.cs.xlf | 5 ++ .../gen/Common/Resources/xlf/Strings.de.xlf | 5 ++ .../gen/Common/Resources/xlf/Strings.es.xlf | 5 ++ .../gen/Common/Resources/xlf/Strings.fr.xlf | 5 ++ .../gen/Common/Resources/xlf/Strings.it.xlf | 5 ++ .../gen/Common/Resources/xlf/Strings.ja.xlf | 5 ++ .../gen/Common/Resources/xlf/Strings.ko.xlf | 5 ++ .../gen/Common/Resources/xlf/Strings.pl.xlf | 5 ++ .../Common/Resources/xlf/Strings.pt-BR.xlf | 5 ++ .../gen/Common/Resources/xlf/Strings.ru.xlf | 5 ++ .../gen/Common/Resources/xlf/Strings.tr.xlf | 5 ++ .../Common/Resources/xlf/Strings.zh-Hans.xlf | 5 ++ .../Common/Resources/xlf/Strings.zh-Hant.xlf | 5 ++ .../ManagedTypeInfo.cs | 4 +- .../MarshalAsMarshallingGeneratorResolver.cs | 6 +- .../CompileFails.cs | 25 ++++++++ 17 files changed, 127 insertions(+), 30 deletions(-) diff --git a/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/Strings.resx b/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/Strings.resx index 7253540e16a0df..a90b4dcc9f9124 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/Strings.resx +++ b/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/Strings.resx @@ -1,17 +1,17 @@  - @@ -916,4 +916,7 @@ Specifying 'GeneratedComInterfaceAttribute' on an interface that has a base interface defined in another assembly is not supported + + Marshalling a generic delegate is not supported. Consider using a function pointer instead. + \ No newline at end of file diff --git a/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.cs.xlf b/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.cs.xlf index ba1c9a3a785dba..c51ab19853fcf4 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.cs.xlf +++ b/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.cs.xlf @@ -432,6 +432,11 @@ Konfigurace „StringMarshalling“ a „StringMarshallingCustomType“ se musí shodovat se základním rozhraním COM. + + Marshalling a generic delegate is not supported. Consider using a function pointer instead. + Marshalling a generic delegate is not supported. Consider using a function pointer instead. + + The marshaller type must be a closed generic or have the same number of generic parameters as the managed type so the emitted code can use a specific instantiation. Zařazovací typ musí být uzavřený obecný typ nebo mít stejný počet obecných parametrů jako spravovaný typ, aby mohl vygenerovaný kód použít konkrétní vytvoření instance. diff --git a/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.de.xlf b/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.de.xlf index b8b529c7c12b71..b165430bf325a2 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.de.xlf +++ b/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.de.xlf @@ -432,6 +432,11 @@ Die Konfiguration von "StringMarshalling" und "StringMarshallingCustomType" muss mit der COM-Basisschnittstelle übereinstimmen. + + Marshalling a generic delegate is not supported. Consider using a function pointer instead. + Marshalling a generic delegate is not supported. Consider using a function pointer instead. + + The marshaller type must be a closed generic or have the same number of generic parameters as the managed type so the emitted code can use a specific instantiation. Der Marshaller-Typ muss ein geschlossener generischer Typ sein oder dieselbe Anzahl generischer Parameter wie der verwaltete Typ aufweisen, damit der ausgegebene Code eine bestimmte Instanziierung verwenden kann. diff --git a/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.es.xlf b/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.es.xlf index 89886b7f025883..1aca57d4f9ecce 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.es.xlf +++ b/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.es.xlf @@ -432,6 +432,11 @@ La configuración de "StringMarshalling" y "StringMarshallingCustomType" debe coincidir con la interfaz COM base. + + Marshalling a generic delegate is not supported. Consider using a function pointer instead. + Marshalling a generic delegate is not supported. Consider using a function pointer instead. + + The marshaller type must be a closed generic or have the same number of generic parameters as the managed type so the emitted code can use a specific instantiation. El tipo serializador debe ser un genérico cerrado o tener el mismo número de parámetros genéricos que el tipo administrado para que el código emitido pueda usar una creación de instancia específica. diff --git a/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.fr.xlf b/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.fr.xlf index 34309a0a8dc920..271b12e5ab8b6a 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.fr.xlf +++ b/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.fr.xlf @@ -432,6 +432,11 @@ La configuration de « StringMarshalling » et de « StringMarshallingCustomType » doit correspondre à l’interface COM de base. + + Marshalling a generic delegate is not supported. Consider using a function pointer instead. + Marshalling a generic delegate is not supported. Consider using a function pointer instead. + + The marshaller type must be a closed generic or have the same number of generic parameters as the managed type so the emitted code can use a specific instantiation. Le type marshaler doit être un générique fermé ou avoir le même nombre de paramètres génériques que le type managé pour que le code émis puisse utiliser une instanciation spécifique. diff --git a/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.it.xlf b/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.it.xlf index 598b0874ab7f25..e99df5eb1d76fe 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.it.xlf +++ b/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.it.xlf @@ -432,6 +432,11 @@ La configurazione di 'StringMarshalling' e 'StringMarshallingCustomType' deve corrispondere all'interfaccia COM di base. + + Marshalling a generic delegate is not supported. Consider using a function pointer instead. + Marshalling a generic delegate is not supported. Consider using a function pointer instead. + + The marshaller type must be a closed generic or have the same number of generic parameters as the managed type so the emitted code can use a specific instantiation. Il tipo di marshaller deve essere un generico chiuso o avere lo stesso numero di parametri generici del tipo gestito, in modo che il codice generato possa usare una creazione di istanza specifica. diff --git a/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.ja.xlf b/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.ja.xlf index e0c3c159f39952..85bf1e1932e365 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.ja.xlf +++ b/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.ja.xlf @@ -432,6 +432,11 @@ 'StringMarshalling' および 'StringMarshallingCustomType' の構成は、ベース COM インターフェイスと一致する必要があります。 + + Marshalling a generic delegate is not supported. Consider using a function pointer instead. + Marshalling a generic delegate is not supported. Consider using a function pointer instead. + + The marshaller type must be a closed generic or have the same number of generic parameters as the managed type so the emitted code can use a specific instantiation. マーシャラー型は、クローズ ジェネリックであるか、マネージド型と同じ数のジェネリック パラメーターを持つ必要があります。これにより、生成されたコードが特定のインスタンス化を使用できるようになります。 diff --git a/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.ko.xlf b/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.ko.xlf index 3544bea85669bd..1d8d61266fbb84 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.ko.xlf +++ b/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.ko.xlf @@ -432,6 +432,11 @@ 'StringMarshalling' 및 'StringMarshallingCustomType'의 구성은 기본 COM 인터페이스와 일치해야 합니다. + + Marshalling a generic delegate is not supported. Consider using a function pointer instead. + Marshalling a generic delegate is not supported. Consider using a function pointer instead. + + The marshaller type must be a closed generic or have the same number of generic parameters as the managed type so the emitted code can use a specific instantiation. 마샬러 형식은 닫힌 제네릭이거나 관리되는 형식과 동일한 수의 제네릭 매개 변수가 있어야 내보낸 코드에서 특정 인스턴스화를 사용할 수 있습니다. diff --git a/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.pl.xlf b/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.pl.xlf index 30bc2cef8ae4de..95d2c9fc215466 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.pl.xlf +++ b/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.pl.xlf @@ -432,6 +432,11 @@ Konfiguracja elementów „StringMarssourceing” i „StringMarsxtingCustomType” musi być zgodna z podstawowym interfejsem COM. + + Marshalling a generic delegate is not supported. Consider using a function pointer instead. + Marshalling a generic delegate is not supported. Consider using a function pointer instead. + + The marshaller type must be a closed generic or have the same number of generic parameters as the managed type so the emitted code can use a specific instantiation. Typ marshallera musi być zamkniętym typem ogólnym lub mieć taką samą liczbę parametrów ogólnych jak typ zarządzany, aby emitowany kod mógł używać określonego wystąpienia. diff --git a/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.pt-BR.xlf b/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.pt-BR.xlf index 3b825512d46ceb..f723b3cf6e3446 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.pt-BR.xlf +++ b/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.pt-BR.xlf @@ -432,6 +432,11 @@ A configuração de 'StringMarshalling' e 'StringMarshallingCustomType' deve corresponder à interface COM base. + + Marshalling a generic delegate is not supported. Consider using a function pointer instead. + Marshalling a generic delegate is not supported. Consider using a function pointer instead. + + The marshaller type must be a closed generic or have the same number of generic parameters as the managed type so the emitted code can use a specific instantiation. O tipo de empacotador deve ser um genérico fechado ou ter o mesmo número de parâmetros genéricos que o tipo gerenciado para que o código emitido possa usar uma instanciação específica. diff --git a/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.ru.xlf b/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.ru.xlf index 27d7f597d2202c..f52b8ace5b2ea0 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.ru.xlf +++ b/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.ru.xlf @@ -432,6 +432,11 @@ Конфигурация "StringMarshalling" и "StringMarshallingCustomType" должна соответствовать базовому COM-интерфейсу. + + Marshalling a generic delegate is not supported. Consider using a function pointer instead. + Marshalling a generic delegate is not supported. Consider using a function pointer instead. + + The marshaller type must be a closed generic or have the same number of generic parameters as the managed type so the emitted code can use a specific instantiation. Тип маршалера должен быть закрытым универсальным или иметь то же количество универсальных параметров, что и управляемый тип, чтобы создаваемый код мог использовать конкретный экземпляр. diff --git a/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.tr.xlf b/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.tr.xlf index 72813018d87503..9640cf17509152 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.tr.xlf +++ b/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.tr.xlf @@ -432,6 +432,11 @@ 'StringMarshalling' ve 'StringMarshallingCustomType' yapılandırması temel COM arabirimiyle eşleşmelidir. + + Marshalling a generic delegate is not supported. Consider using a function pointer instead. + Marshalling a generic delegate is not supported. Consider using a function pointer instead. + + The marshaller type must be a closed generic or have the same number of generic parameters as the managed type so the emitted code can use a specific instantiation. Hazırlayıcı türü kapalı bir genel tür olmalıdır veya gösterilen kodun belirli bir örnek oluşturma kullanabilmesi için yönetilen türle aynı sayıda genel parametreye sahip olmalıdır. diff --git a/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.zh-Hans.xlf b/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.zh-Hans.xlf index b9e21c430f3a76..5ea6c89e3c8af7 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.zh-Hans.xlf +++ b/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.zh-Hans.xlf @@ -432,6 +432,11 @@ "StringMarshalling" 和 "StringMarshallingCustomType" 的配置必须与基本 COM 接口匹配。 + + Marshalling a generic delegate is not supported. Consider using a function pointer instead. + Marshalling a generic delegate is not supported. Consider using a function pointer instead. + + The marshaller type must be a closed generic or have the same number of generic parameters as the managed type so the emitted code can use a specific instantiation. 封送处理程序类型必须是封闭泛型或具有与托管类型相同数目的泛型参数,以便发出的代码可以使用特定实例化。 diff --git a/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.zh-Hant.xlf b/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.zh-Hant.xlf index feb774294e8ea0..f1f937cfb8d218 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.zh-Hant.xlf +++ b/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.zh-Hant.xlf @@ -432,6 +432,11 @@ 'StringMarshalling' 和 'StringMarshallingCustomType' 的設定必須和基底 COM 介面相符。 + + Marshalling a generic delegate is not supported. Consider using a function pointer instead. + Marshalling a generic delegate is not supported. Consider using a function pointer instead. + + The marshaller type must be a closed generic or have the same number of generic parameters as the managed type so the emitted code can use a specific instantiation. 封送處理器類型必須是封閉式泛型或具有與受控類型相同的泛型參數數目,因此發出的程式碼可以使用特定的具現化。 diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/ManagedTypeInfo.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/ManagedTypeInfo.cs index e76e66981ed424..7b75729b1b06d1 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/ManagedTypeInfo.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/ManagedTypeInfo.cs @@ -63,7 +63,7 @@ public static ManagedTypeInfo CreateTypeInfoForTypeSymbol(ITypeSymbol type) } if (type.TypeKind == TypeKind.Delegate) { - return new DelegateTypeInfo(typeName, diagnosticFormattedName); + return new DelegateTypeInfo(typeName, diagnosticFormattedName, type is INamedTypeSymbol { IsGenericType: true }); } if (type.TypeKind == TypeKind.TypeParameter) { @@ -107,7 +107,7 @@ public sealed record PointerTypeInfo(string FullTypeName, string DiagnosticForma public sealed record SzArrayType(ManagedTypeInfo ElementTypeInfo) : ManagedTypeInfo($"{ElementTypeInfo.FullTypeName}[]", $"{ElementTypeInfo.DiagnosticFormattedName}[]"); - public sealed record DelegateTypeInfo(string FullTypeName, string DiagnosticFormattedName) : ManagedTypeInfo(FullTypeName, DiagnosticFormattedName); + public sealed record DelegateTypeInfo(string FullTypeName, string DiagnosticFormattedName, bool IsGeneric) : ManagedTypeInfo(FullTypeName, DiagnosticFormattedName); public sealed record TypeParameterTypeInfo(string FullTypeName, string DiagnosticFormattedName) : ManagedTypeInfo(FullTypeName, DiagnosticFormattedName); diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/MarshalAsMarshallingGeneratorResolver.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/MarshalAsMarshallingGeneratorResolver.cs index 6f4721b71fd5e5..e8b658db48743d 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/MarshalAsMarshallingGeneratorResolver.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/MarshalAsMarshallingGeneratorResolver.cs @@ -84,7 +84,11 @@ public ResolvedGenerator Create( return ResolvedGenerator.Resolved(s_variantBool.Bind(info, context)); // Delegate types - case { ManagedType: DelegateTypeInfo, MarshallingAttributeInfo: NoMarshallingInfo or MarshalAsInfo(UnmanagedType.FunctionPtr, _) }: + case { ManagedType: DelegateTypeInfo delegateTypeInfo, MarshallingAttributeInfo: NoMarshallingInfo or MarshalAsInfo(UnmanagedType.FunctionPtr, _) }: + if (delegateTypeInfo.IsGeneric) + { + return ResolvedGenerator.NotSupported(info, context, new(info) { NotSupportedDetails = SR.GenericDelegatesNotSupported }); + } return ResolvedGenerator.Resolved(s_delegate.Bind(info, context)); // void diff --git a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/CompileFails.cs b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/CompileFails.cs index ecbe1c3d19e02f..bf3b948b3d6a12 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/CompileFails.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/CompileFails.cs @@ -22,6 +22,31 @@ namespace LibraryImportGenerator.UnitTests { public class CompileFails { + [Fact] + public Task GenericDelegateParameterFails() + { + var src = """ + using System; + using System.Runtime.InteropServices; + + partial class Test + { + [LibraryImportAttribute("DoesNotExist")] + public static partial void Method1(Func {|#0:f|}); + } + """; + + + return VerifyCS.VerifySourceGeneratorAsync( + src, + new DiagnosticResult[] + { + VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails) + .WithLocation(0) + .WithArguments("Marshalling a generic delegate is not supported. Consider using a function pointer instead.", "f") + }); + } + private static string ID( [CallerLineNumber] int lineNumber = 0, [CallerFilePath] string? filePath = null) From dd97c9d5d7279d66258dee86f3be2eeb0166274a Mon Sep 17 00:00:00 2001 From: Andy Gocke Date: Wed, 23 Apr 2025 13:48:18 -0700 Subject: [PATCH 2/2] Respond to PR comments --- .../CompileFails.cs | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/CompileFails.cs b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/CompileFails.cs index bf3b948b3d6a12..605cd6b80386c5 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/CompileFails.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/CompileFails.cs @@ -25,25 +25,25 @@ public class CompileFails [Fact] public Task GenericDelegateParameterFails() { - var src = """ - using System; - using System.Runtime.InteropServices; - - partial class Test - { - [LibraryImportAttribute("DoesNotExist")] - public static partial void Method1(Func {|#0:f|}); - } - """; - - return VerifyCS.VerifySourceGeneratorAsync( - src, + CodeSnippets.BasicParametersAndModifiers("System.Func"), new DiagnosticResult[] { - VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails) + VerifyCS.Diagnostic(GeneratorDiagnostics.ReturnTypeNotSupportedWithDetails) .WithLocation(0) - .WithArguments("Marshalling a generic delegate is not supported. Consider using a function pointer instead.", "f") + .WithArguments("Marshalling a generic delegate is not supported. Consider using a function pointer instead.", "Method"), + VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails) + .WithLocation(1) + .WithArguments("Marshalling a generic delegate is not supported. Consider using a function pointer instead.", "p"), + VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails) + .WithLocation(2) + .WithArguments("Marshalling a generic delegate is not supported. Consider using a function pointer instead.", "pIn"), + VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails) + .WithLocation(3) + .WithArguments("Marshalling a generic delegate is not supported. Consider using a function pointer instead.", "pRef"), + VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails) + .WithLocation(4) + .WithArguments("Marshalling a generic delegate is not supported. Consider using a function pointer instead.", "pOut"), }); }