diff --git a/src/libraries/System.Runtime.InteropServices/gen/DllImportGenerator/Marshalling/MarshallingGenerator.cs b/src/libraries/System.Runtime.InteropServices/gen/DllImportGenerator/Marshalling/MarshallingGenerator.cs
index e9d81561b75a3..c8f13da707c3f 100644
--- a/src/libraries/System.Runtime.InteropServices/gen/DllImportGenerator/Marshalling/MarshallingGenerator.cs
+++ b/src/libraries/System.Runtime.InteropServices/gen/DllImportGenerator/Marshalling/MarshallingGenerator.cs
@@ -237,6 +237,13 @@ private static IMarshallingGenerator CreateCore(
{
throw new MarshallingNotSupportedException(info, context);
}
+ if (info.IsByRef && info.ManagedType.IsAbstract)
+ {
+ throw new MarshallingNotSupportedException(info, context)
+ {
+ NotSupportedDetails = Resources.SafeHandleByRefMustBeConcrete
+ };
+ }
return new SafeHandleMarshaller(options);
// Marshalling in new model.
diff --git a/src/libraries/System.Runtime.InteropServices/gen/DllImportGenerator/Resources.Designer.cs b/src/libraries/System.Runtime.InteropServices/gen/DllImportGenerator/Resources.Designer.cs
index e86940b256c65..87fac1a3e0ffa 100644
--- a/src/libraries/System.Runtime.InteropServices/gen/DllImportGenerator/Resources.Designer.cs
+++ b/src/libraries/System.Runtime.InteropServices/gen/DllImportGenerator/Resources.Designer.cs
@@ -483,6 +483,15 @@ internal static string RefValuePropertyUnsupportedMessage {
}
}
+ ///
+ /// Looks up a localized string similar to An abstract type derived from 'SafeHandle' cannot be marshalled by reference. The provided type must be concrete..
+ ///
+ internal static string SafeHandleByRefMustBeConcrete {
+ get {
+ return ResourceManager.GetString("SafeHandleByRefMustBeConcrete", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to When constructor taking a Span<byte> is specified on the native type, the type must also have a public integer constant named StackBufferSize to provide the size of the stack-allocated buffer..
///
diff --git a/src/libraries/System.Runtime.InteropServices/gen/DllImportGenerator/Resources.resx b/src/libraries/System.Runtime.InteropServices/gen/DllImportGenerator/Resources.resx
index c6a5491493395..f66d2945ad7a8 100644
--- a/src/libraries/System.Runtime.InteropServices/gen/DllImportGenerator/Resources.resx
+++ b/src/libraries/System.Runtime.InteropServices/gen/DllImportGenerator/Resources.resx
@@ -259,6 +259,9 @@
The 'Value' property on the native type '{0}' must not be a 'ref' or 'readonly ref' property.
+
+ An abstract type derived from 'SafeHandle' cannot be marshalled by reference. The provided type must be concrete.
+
When constructor taking a Span<byte> is specified on the native type, the type must also have a public integer constant named StackBufferSize to provide the size of the stack-allocated buffer.
diff --git a/src/libraries/System.Runtime.InteropServices/gen/DllImportGenerator/TypePositionInfo.cs b/src/libraries/System.Runtime.InteropServices/gen/DllImportGenerator/TypePositionInfo.cs
index 9cb216590cc03..0a5d4c921b22d 100644
--- a/src/libraries/System.Runtime.InteropServices/gen/DllImportGenerator/TypePositionInfo.cs
+++ b/src/libraries/System.Runtime.InteropServices/gen/DllImportGenerator/TypePositionInfo.cs
@@ -312,11 +312,10 @@ static bool TryCreateTypeBasedMarshallingInfo(ITypeSymbol type, DefaultMarshalli
var conversion = compilation.ClassifyCommonConversion(type, compilation.GetTypeByMetadataName(TypeNames.System_Runtime_InteropServices_SafeHandle)!);
if (conversion.Exists
&& conversion.IsImplicit
- && conversion.IsReference
- && !type.IsAbstract)
+ && (conversion.IsReference || conversion.IsIdentity))
{
bool hasAccessibleDefaultConstructor = false;
- if (type is INamedTypeSymbol named && named.InstanceConstructors.Length > 0)
+ if (type is INamedTypeSymbol named && !named.IsAbstract && named.InstanceConstructors.Length > 0)
{
foreach (var ctor in named.InstanceConstructors)
{
diff --git a/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.UnitTests/CodeSnippets.cs b/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.UnitTests/CodeSnippets.cs
index 8d630f9c2b62f..eb4cc83858fee 100644
--- a/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.UnitTests/CodeSnippets.cs
+++ b/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.UnitTests/CodeSnippets.cs
@@ -843,6 +843,15 @@ public static partial void Method(
{byRefKind} {typeName} p);
}}";
+ public static string BasicParameterByValue(string typeName) => @$"
+using System.Runtime.InteropServices;
+partial class Test
+{{
+ [GeneratedDllImport(""DoesNotExist"")]
+ public static partial void Method(
+ {typeName} p);
+}}";
+
public static string BasicReturnType(string typeName) => @$"
using System.Runtime.InteropServices;
partial class Test
diff --git a/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.UnitTests/CompileFails.cs b/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.UnitTests/CompileFails.cs
index 61f98f45fff8d..89622d1cdf233 100644
--- a/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.UnitTests/CompileFails.cs
+++ b/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.UnitTests/CompileFails.cs
@@ -92,6 +92,9 @@ public static IEnumerable