diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/SymbolType.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/SymbolType.cs index b154dac0d48b1d..ea9ddeafe80b30 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/SymbolType.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/SymbolType.cs @@ -259,6 +259,8 @@ internal void SetFormat(string format, int curIndex, int length) public override bool IsTypeDefinition => false; + public override bool IsByRefLike => false; + public override bool IsSZArray => _rank <= 1 && _isSzArray; public override Type? GetNullableUnderlyingType() => null; diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/TypeBuilderInstantiation.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/TypeBuilderInstantiation.cs index b7167fde85e323..86aac33074dd5b 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/TypeBuilderInstantiation.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/TypeBuilderInstantiation.cs @@ -217,6 +217,7 @@ public override Type? BaseType protected override TypeAttributes GetAttributeFlagsImpl() { return _genericType.Attributes; } public override bool IsTypeDefinition => false; + public override bool IsByRefLike => _genericType.IsByRefLike; public override bool IsSZArray => false; protected override bool IsArrayImpl() { return false; } diff --git a/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/GenericTypeParameterBuilderImpl.cs b/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/GenericTypeParameterBuilderImpl.cs index 916288b3f80918..378a31018dc39c 100644 --- a/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/GenericTypeParameterBuilderImpl.cs +++ b/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/GenericTypeParameterBuilderImpl.cs @@ -83,6 +83,7 @@ public override Type[] GetGenericParameterConstraints() => public override bool IsGenericType => false; public override bool IsGenericParameter => true; public override bool IsConstructedGenericType => false; + public override bool IsByRefLike => false; public override bool ContainsGenericParameters => false; public override MethodBase? DeclaringMethod => _type.DeclaringMethod; public override Type? BaseType => _parent; diff --git a/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/TypeBuilderImpl.cs b/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/TypeBuilderImpl.cs index 5f54a4c10de474..27ffad936b4bef 100644 --- a/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/TypeBuilderImpl.cs +++ b/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/TypeBuilderImpl.cs @@ -622,6 +622,7 @@ public override Type GetEnumUnderlyingType() throw new ArgumentException(SR.Argument_MustBeEnum); } } + public override bool IsByRefLike => false; public override bool IsSZArray => false; public override Guid GUID => throw new NotSupportedException(); public override Type? BaseType => _typeParent; diff --git a/src/libraries/System.Reflection.Emit/tests/PersistedAssemblyBuilder/AssemblySaveTypeBuilderAPIsTests.cs b/src/libraries/System.Reflection.Emit/tests/PersistedAssemblyBuilder/AssemblySaveTypeBuilderAPIsTests.cs index 8063964e4473b7..42398fd3096308 100644 --- a/src/libraries/System.Reflection.Emit/tests/PersistedAssemblyBuilder/AssemblySaveTypeBuilderAPIsTests.cs +++ b/src/libraries/System.Reflection.Emit/tests/PersistedAssemblyBuilder/AssemblySaveTypeBuilderAPIsTests.cs @@ -1010,5 +1010,38 @@ public void TestContainsGenericParametersOnMethodCtorOfConstructedGenericType() Assert.False(TypeBuilder.GetConstructor(instantiatedTypeBuilder2, constructorBuilder).ContainsGenericParameters); Assert.False(TypeBuilder.GetMethod(instantiatedTypeBuilder2, methodBuilder).ContainsGenericParameters); } + + [Fact] + public void IsByRefLike_TypeBuilderAndConstructedTypes_ReturnsFalse() + { + AssemblySaveTools.PopulateAssemblyBuilderAndTypeBuilder(out TypeBuilder type); + GenericTypeParameterBuilder[] typeParams = type.DefineGenericParameters("T"); + + Type[] types = + [ + type, + typeParams[0], + type.MakeGenericType(typeof(int)), + type.MakeArrayType(), + type.MakeArrayType(2), + type.MakePointerType(), + type.MakeByRefType(), + typeParams[0].MakeArrayType(), + typeParams[0].MakePointerType(), + typeParams[0].MakeByRefType(), + ]; + + Assert.All(types, t => Assert.False(t.IsByRefLike)); + } + + [Theory] + [InlineData(typeof(Span<>), true)] + [InlineData(typeof(ReadOnlySpan<>), true)] + [InlineData(typeof(List<>), false)] + public void IsByRefLike_RuntimeGenericTypeInstantiatedOverTypeBuilder_MatchesGenericTypeDefinition(Type genericTypeDefinition, bool expected) + { + AssemblySaveTools.PopulateAssemblyBuilderAndTypeBuilder(out TypeBuilder type); + Assert.Equal(expected, genericTypeDefinition.MakeGenericType(type).IsByRefLike); + } } } diff --git a/src/libraries/System.Reflection.Emit/tests/TypeBuilder/TypeBuilderIsByRefLike.cs b/src/libraries/System.Reflection.Emit/tests/TypeBuilder/TypeBuilderIsByRefLike.cs index 3f03d268ca4702..c05576b13afac6 100644 --- a/src/libraries/System.Reflection.Emit/tests/TypeBuilder/TypeBuilderIsByRefLike.cs +++ b/src/libraries/System.Reflection.Emit/tests/TypeBuilder/TypeBuilderIsByRefLike.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Collections.Generic; using Xunit; namespace System.Reflection.Emit.Tests @@ -13,5 +14,36 @@ public void IsByRefLikeReturnsFalse() TypeBuilder type = Helpers.DynamicType(TypeAttributes.Public); Assert.False(type.IsByRefLike); } + + [Fact] + public void IsByRefLike_TypesConstructedFromTypeBuilder_ReturnsFalse() + { + TypeBuilder type = Helpers.DynamicType(TypeAttributes.Public); + GenericTypeParameterBuilder[] typeParams = type.DefineGenericParameters("T"); + + Type[] constructedTypes = + [ + type.MakeGenericType(typeof(int)), + type.MakeArrayType(), + type.MakeArrayType(2), + type.MakePointerType(), + type.MakeByRefType(), + typeParams[0].MakeArrayType(), + typeParams[0].MakePointerType(), + typeParams[0].MakeByRefType(), + ]; + + Assert.All(constructedTypes, t => Assert.False(t.IsByRefLike)); + } + + [Theory] + [InlineData(typeof(Span<>), true)] + [InlineData(typeof(ReadOnlySpan<>), true)] + [InlineData(typeof(List<>), false)] + public void IsByRefLike_RuntimeGenericTypeInstantiatedOverTypeBuilder_MatchesGenericTypeDefinition(Type genericTypeDefinition, bool expected) + { + TypeBuilder type = Helpers.DynamicType(TypeAttributes.Public); + Assert.Equal(expected, genericTypeDefinition.MakeGenericType(type).IsByRefLike); + } } }