From 482528fcf4dd69c1958406c9644e3ea0704504f4 Mon Sep 17 00:00:00 2001 From: AlekseyTs Date: Fri, 10 May 2024 12:37:52 -0700 Subject: [PATCH 1/2] Recognize 'allows ref struct' constraint in VB compiler --- .../SymbolDisplayVisitor.Types.cs | 20 +- .../Test/Emit3/RefStructInterfacesTests.cs | 66 ++++++ .../VisualBasicSymbolMatcher.vb | 1 + .../Emit/NoPia/EmbeddedTypeParameter.vb | 2 +- .../Emit/TypeParameterSymbolAdapter.vb | 2 +- ...nymousTypeOrDelegateTypeParameterSymbol.vb | 6 + .../Symbols/IndexedTypeParameterSymbol.vb | 6 + .../Symbols/InstanceErrorTypeSymbol.vb | 6 + .../Metadata/PE/PETypeParameterSymbol.vb | 6 + .../Symbols/MethodSignatureComparer.vb | 1 + .../Symbols/ReducedExtensionMethodSymbol.vb | 6 + .../RetargetingTypeParameterSymbol.vb | 6 + .../Symbols/Source/CrefTypeParameterSymbol.vb | 6 + .../Source/SourceTypeParameterSymbol.vb | 6 + .../Symbols/SubstitutedTypeParameterSymbol.vb | 6 + .../SynthesizedClonedTypeParameterSymbol.vb | 6 + .../Portable/Symbols/TypeParameterSymbol.vb | 6 +- .../Wrapped/WrappedTypeParameterSymbol.vb | 6 + .../SymbolsTests/RefStructInterfacesTests.vb | 194 ++++++++++++++++++ .../Symbols/EETypeParameterSymbol.vb | 6 + .../Symbols/SimpleTypeParameterSymbol.vb | 6 + 21 files changed, 361 insertions(+), 9 deletions(-) diff --git a/src/Compilers/CSharp/Portable/SymbolDisplay/SymbolDisplayVisitor.Types.cs b/src/Compilers/CSharp/Portable/SymbolDisplay/SymbolDisplayVisitor.Types.cs index 396fcdd7f80b4..5961e96a5cc71 100644 --- a/src/Compilers/CSharp/Portable/SymbolDisplay/SymbolDisplayVisitor.Types.cs +++ b/src/Compilers/CSharp/Portable/SymbolDisplay/SymbolDisplayVisitor.Types.cs @@ -837,7 +837,7 @@ private static bool TypeParameterHasConstraints(ITypeParameterSymbol typeParam) { return !typeParam.ConstraintTypes.IsEmpty || typeParam.HasConstructorConstraint || typeParam.HasReferenceTypeConstraint || typeParam.HasValueTypeConstraint || - typeParam.HasNotNullConstraint; + typeParam.HasNotNullConstraint || typeParam.AllowsByRefLike; } private void AddTypeParameterConstraints(ImmutableArray typeArguments) @@ -917,7 +917,7 @@ private void AddTypeParameterConstraints(ImmutableArray typeArgumen needComma = true; } - //ctor constraint must be last + //ctor constraint must be last before 'allows ref struct' if (typeParam.HasConstructorConstraint) { if (needComma) @@ -929,6 +929,22 @@ private void AddTypeParameterConstraints(ImmutableArray typeArgumen AddKeyword(SyntaxKind.NewKeyword); AddPunctuation(SyntaxKind.OpenParenToken); AddPunctuation(SyntaxKind.CloseParenToken); + needComma = true; + } + + if (typeParam.AllowsByRefLike) + { + if (needComma) + { + AddPunctuation(SyntaxKind.CommaToken); + AddSpace(); + } + + AddKeyword(SyntaxKind.AllowsKeyword); + AddSpace(); + AddKeyword(SyntaxKind.RefKeyword); + AddSpace(); + AddKeyword(SyntaxKind.StructKeyword); } } } diff --git a/src/Compilers/CSharp/Test/Emit3/RefStructInterfacesTests.cs b/src/Compilers/CSharp/Test/Emit3/RefStructInterfacesTests.cs index 901a93d4d426f..5b8b68abbd7b0 100644 --- a/src/Compilers/CSharp/Test/Emit3/RefStructInterfacesTests.cs +++ b/src/Compilers/CSharp/Test/Emit3/RefStructInterfacesTests.cs @@ -4377,6 +4377,7 @@ void verify(ModuleSymbol m) Assert.False(t.HasNotNullConstraint); Assert.True(t.AllowsByRefLike); Assert.True(t.GetPublicSymbol().AllowsByRefLike); + AssertEx.Equal("C where T : allows ref struct", t.ContainingSymbol.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); } comp = CreateCompilation(src, targetFramework: s_targetFrameworkSupportingByRefLikeGenerics, parseOptions: TestOptions.RegularNext).VerifyDiagnostics(); @@ -5085,6 +5086,7 @@ public class C Assert.False(t.HasNotNullConstraint); Assert.True(t.HasConstructorConstraint); Assert.True(t.AllowsByRefLike); + AssertEx.Equal("C where T : new(), allows ref struct", t.ContainingSymbol.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); } [Fact] @@ -5108,6 +5110,7 @@ public class C Assert.False(t.HasNotNullConstraint); Assert.True(t.HasConstructorConstraint); Assert.True(t.AllowsByRefLike); + AssertEx.Equal("C where T : new(), allows ref struct", t.ContainingSymbol.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); } [Fact] @@ -5754,6 +5757,7 @@ void verify(ModuleSymbol m) Assert.False(t.HasNotNullConstraint); Assert.False(t.AllowsByRefLike); Assert.False(t.GetPublicSymbol().AllowsByRefLike); + AssertEx.Equal("C", t.ContainingSymbol.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); } } @@ -23918,5 +23922,67 @@ public class Activator expectedOutput: ExecutionConditionUtil.IsMonoOrCoreClr ? "123 246" : null, verify: ExecutionConditionUtil.IsMonoOrCoreClr ? Verification.Passes : Verification.Skipped).VerifyDiagnostics(); } + + [Fact] + public void NoPiaEmbedding() + { + string pia = @" +using System; +using System.Runtime.InteropServices; + +[assembly: ImportedFromTypeLib(""GeneralPIA.dll"")] +[assembly: Guid(""f9c2d51d-4f44-45f0-9eda-c9d599b58257"")] + +[ComImport()] +[Guid(""f9c2d51d-4f44-45f0-9eda-c9d599b58278"")] +public interface ITest29 +{ + void M21() where T1 : allows ref struct; +} +"; + + var piaCompilation = CreateCompilation(pia, options: TestOptions.ReleaseDll, assemblyName: "Pia", targetFramework: s_targetFrameworkSupportingByRefLikeGenerics); + + string consumer = @" +class UsePia +{ + public static void Main() + { + } +} + +interface UsePia5 : ITest29 +{ +} +"; + + var compilation1 = CreateCompilation(consumer, options: TestOptions.ReleaseExe, + references: [piaCompilation.ToMetadataReference(embedInteropTypes: true)], + targetFramework: s_targetFrameworkSupportingByRefLikeGenerics); + + var compilation2 = CreateCompilation(consumer, options: TestOptions.ReleaseExe, + references: [piaCompilation.EmitToImageReference(embedInteropTypes: true)], + targetFramework: s_targetFrameworkSupportingByRefLikeGenerics); + + System.Action metadataValidator = + delegate (ModuleSymbol module) + { + ((PEModuleSymbol)module).Module.PretendThereArentNoPiaLocalTypes(); + + var itest29 = (PENamedTypeSymbol)module.GlobalNamespace.GetTypeMembers("ITest29").Single(); + Assert.Equal(TypeKind.Interface, itest29.TypeKind); + + var m21 = (PEMethodSymbol)itest29.GetMembers("M21").Single(); + + var t1 = m21.TypeParameters[0]; + Assert.Equal("T1", t1.Name); + Assert.True(t1.AllowsByRefLike); + AssertEx.Equal("void ITest29.M21() where T1 : allows ref struct", m21.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); + }; + + CompileAndVerify(compilation1, symbolValidator: metadataValidator, verify: Verification.Skipped).VerifyDiagnostics(); + + CompileAndVerify(compilation2, symbolValidator: metadataValidator, verify: Verification.Skipped).VerifyDiagnostics(); + } } } diff --git a/src/Compilers/VisualBasic/Portable/Emit/EditAndContinue/VisualBasicSymbolMatcher.vb b/src/Compilers/VisualBasic/Portable/Emit/EditAndContinue/VisualBasicSymbolMatcher.vb index 92bf462abb3cc..03e37be8af79e 100644 --- a/src/Compilers/VisualBasic/Portable/Emit/EditAndContinue/VisualBasicSymbolMatcher.vb +++ b/src/Compilers/VisualBasic/Portable/Emit/EditAndContinue/VisualBasicSymbolMatcher.vb @@ -475,6 +475,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Emit ' edit. Furthermore, comparing constraint types might lead to a cycle. Debug.Assert(type.HasConstructorConstraint = other.HasConstructorConstraint) Debug.Assert(type.HasValueTypeConstraint = other.HasValueTypeConstraint) + Debug.Assert(type.AllowsByRefLike = other.AllowsByRefLike) Debug.Assert(type.HasReferenceTypeConstraint = other.HasReferenceTypeConstraint) Debug.Assert(type.ConstraintTypesNoUseSiteDiagnostics.Length = other.ConstraintTypesNoUseSiteDiagnostics.Length) Return True diff --git a/src/Compilers/VisualBasic/Portable/Emit/NoPia/EmbeddedTypeParameter.vb b/src/Compilers/VisualBasic/Portable/Emit/NoPia/EmbeddedTypeParameter.vb index 26ce57982b259..8b8aba1f86ec2 100644 --- a/src/Compilers/VisualBasic/Portable/Emit/NoPia/EmbeddedTypeParameter.vb +++ b/src/Compilers/VisualBasic/Portable/Emit/NoPia/EmbeddedTypeParameter.vb @@ -37,7 +37,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Emit.NoPia Protected Overrides ReadOnly Property AllowByRefLike As Boolean Get - Return False ' PROTOTYPE(RefStructInterfaces): Implement for real + Return UnderlyingTypeParameter.AdaptedTypeParameterSymbol.AllowsByRefLike End Get End Property diff --git a/src/Compilers/VisualBasic/Portable/Emit/TypeParameterSymbolAdapter.vb b/src/Compilers/VisualBasic/Portable/Emit/TypeParameterSymbolAdapter.vb index fe138b5ef2e2a..e6d469c9b479b 100644 --- a/src/Compilers/VisualBasic/Portable/Emit/TypeParameterSymbolAdapter.vb +++ b/src/Compilers/VisualBasic/Portable/Emit/TypeParameterSymbolAdapter.vb @@ -235,7 +235,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols Private ReadOnly Property IGenericParameterAllowByRefLike As Boolean Implements IGenericParameter.AllowByRefLike Get - Return False ' PROTOTYPE(RefStructInterfaces): Implement for real + Return AdaptedTypeParameterSymbol.AllowsByRefLike End Get End Property diff --git a/src/Compilers/VisualBasic/Portable/Symbols/AnonymousTypes/SynthesizedSymbols/AnonymousTypeOrDelegateTypeParameterSymbol.vb b/src/Compilers/VisualBasic/Portable/Symbols/AnonymousTypes/SynthesizedSymbols/AnonymousTypeOrDelegateTypeParameterSymbol.vb index 2c64a421fd8e0..dd6c79e7ac02c 100644 --- a/src/Compilers/VisualBasic/Portable/Symbols/AnonymousTypes/SynthesizedSymbols/AnonymousTypeOrDelegateTypeParameterSymbol.vb +++ b/src/Compilers/VisualBasic/Portable/Symbols/AnonymousTypes/SynthesizedSymbols/AnonymousTypeOrDelegateTypeParameterSymbol.vb @@ -93,6 +93,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols End Get End Property + Public Overrides ReadOnly Property AllowsByRefLike As Boolean + Get + Return False + End Get + End Property + Public Overrides ReadOnly Property Variance As VarianceKind Get Return VarianceKind.None diff --git a/src/Compilers/VisualBasic/Portable/Symbols/IndexedTypeParameterSymbol.vb b/src/Compilers/VisualBasic/Portable/Symbols/IndexedTypeParameterSymbol.vb index 18b403c6252a0..7a85a3bc31358 100644 --- a/src/Compilers/VisualBasic/Portable/Symbols/IndexedTypeParameterSymbol.vb +++ b/src/Compilers/VisualBasic/Portable/Symbols/IndexedTypeParameterSymbol.vb @@ -116,6 +116,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols End Get End Property + Public Overrides ReadOnly Property AllowsByRefLike As Boolean + Get + Return False + End Get + End Property + Public Overrides ReadOnly Property HasReferenceTypeConstraint As Boolean Get Return False diff --git a/src/Compilers/VisualBasic/Portable/Symbols/InstanceErrorTypeSymbol.vb b/src/Compilers/VisualBasic/Portable/Symbols/InstanceErrorTypeSymbol.vb index 985579c078721..52e595fb59348 100644 --- a/src/Compilers/VisualBasic/Portable/Symbols/InstanceErrorTypeSymbol.vb +++ b/src/Compilers/VisualBasic/Portable/Symbols/InstanceErrorTypeSymbol.vb @@ -233,6 +233,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols End Get End Property + Public Overrides ReadOnly Property AllowsByRefLike As Boolean + Get + Return False + End Get + End Property + Public Overrides ReadOnly Property Locations As ImmutableArray(Of Location) Get Return ImmutableArray(Of Location).Empty diff --git a/src/Compilers/VisualBasic/Portable/Symbols/Metadata/PE/PETypeParameterSymbol.vb b/src/Compilers/VisualBasic/Portable/Symbols/Metadata/PE/PETypeParameterSymbol.vb index 1ecc93c7051df..a2832b32810f4 100644 --- a/src/Compilers/VisualBasic/Portable/Symbols/Metadata/PE/PETypeParameterSymbol.vb +++ b/src/Compilers/VisualBasic/Portable/Symbols/Metadata/PE/PETypeParameterSymbol.vb @@ -245,6 +245,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols.Metadata.PE End Get End Property + Public Overrides ReadOnly Property AllowsByRefLike As Boolean + Get + Return (_flags And MetadataHelpers.GenericParameterAttributesAllowByRefLike) <> 0 + End Get + End Property + Public Overrides ReadOnly Property Variance As VarianceKind Get Return CType((_flags And GenericParameterAttributes.VarianceMask), VarianceKind) diff --git a/src/Compilers/VisualBasic/Portable/Symbols/MethodSignatureComparer.vb b/src/Compilers/VisualBasic/Portable/Symbols/MethodSignatureComparer.vb index 449d48c014410..cb09eeb807870 100644 --- a/src/Compilers/VisualBasic/Portable/Symbols/MethodSignatureComparer.vb +++ b/src/Compilers/VisualBasic/Portable/Symbols/MethodSignatureComparer.vb @@ -863,6 +863,7 @@ Done: If (typeParameter1.HasConstructorConstraint <> typeParameter2.HasConstructorConstraint) OrElse (typeParameter1.HasReferenceTypeConstraint <> typeParameter2.HasReferenceTypeConstraint) OrElse (typeParameter1.HasValueTypeConstraint <> typeParameter2.HasValueTypeConstraint) OrElse + (typeParameter1.AllowsByRefLike <> typeParameter2.AllowsByRefLike) OrElse (typeParameter1.Variance <> typeParameter2.Variance) Then Return False End If diff --git a/src/Compilers/VisualBasic/Portable/Symbols/ReducedExtensionMethodSymbol.vb b/src/Compilers/VisualBasic/Portable/Symbols/ReducedExtensionMethodSymbol.vb index 8dfaf13e7f301..f6b46f03cca62 100644 --- a/src/Compilers/VisualBasic/Portable/Symbols/ReducedExtensionMethodSymbol.vb +++ b/src/Compilers/VisualBasic/Portable/Symbols/ReducedExtensionMethodSymbol.vb @@ -749,6 +749,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols End Get End Property + Public Overrides ReadOnly Property AllowsByRefLike As Boolean + Get + Return _curriedFromTypeParameter.AllowsByRefLike + End Get + End Property + Public Overrides ReadOnly Property Locations As ImmutableArray(Of Location) Get Return _curriedFromTypeParameter.Locations diff --git a/src/Compilers/VisualBasic/Portable/Symbols/Retargeting/RetargetingTypeParameterSymbol.vb b/src/Compilers/VisualBasic/Portable/Symbols/Retargeting/RetargetingTypeParameterSymbol.vb index 18a5c44aafd78..4b3e2465ef3d1 100644 --- a/src/Compilers/VisualBasic/Portable/Symbols/Retargeting/RetargetingTypeParameterSymbol.vb +++ b/src/Compilers/VisualBasic/Portable/Symbols/Retargeting/RetargetingTypeParameterSymbol.vb @@ -98,6 +98,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols.Retargeting End Get End Property + Public Overrides ReadOnly Property AllowsByRefLike As Boolean + Get + Return _underlyingTypeParameter.AllowsByRefLike + End Get + End Property + Public Overrides ReadOnly Property Variance As VarianceKind Get Return _underlyingTypeParameter.Variance diff --git a/src/Compilers/VisualBasic/Portable/Symbols/Source/CrefTypeParameterSymbol.vb b/src/Compilers/VisualBasic/Portable/Symbols/Source/CrefTypeParameterSymbol.vb index 902b992e69b1d..b57bf55596dd5 100644 --- a/src/Compilers/VisualBasic/Portable/Symbols/Source/CrefTypeParameterSymbol.vb +++ b/src/Compilers/VisualBasic/Portable/Symbols/Source/CrefTypeParameterSymbol.vb @@ -67,6 +67,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols End Get End Property + Public Overrides ReadOnly Property AllowsByRefLike As Boolean + Get + Return False + End Get + End Property + Friend Overrides ReadOnly Property ConstraintTypesNoUseSiteDiagnostics As ImmutableArray(Of TypeSymbol) Get Return ImmutableArray(Of TypeSymbol).Empty diff --git a/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceTypeParameterSymbol.vb b/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceTypeParameterSymbol.vb index 2ca688c612858..b9c9b9d2f6311 100644 --- a/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceTypeParameterSymbol.vb +++ b/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceTypeParameterSymbol.vb @@ -77,6 +77,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols End Get End Property + Public Overrides ReadOnly Property AllowsByRefLike As Boolean + Get + Return False + End Get + End Property + Friend Overrides ReadOnly Property ConstraintTypesNoUseSiteDiagnostics As ImmutableArray(Of TypeSymbol) Get EnsureAllConstraintsAreResolved() diff --git a/src/Compilers/VisualBasic/Portable/Symbols/SubstitutedTypeParameterSymbol.vb b/src/Compilers/VisualBasic/Portable/Symbols/SubstitutedTypeParameterSymbol.vb index e511e0cebe764..7bdb2c63b95d6 100644 --- a/src/Compilers/VisualBasic/Portable/Symbols/SubstitutedTypeParameterSymbol.vb +++ b/src/Compilers/VisualBasic/Portable/Symbols/SubstitutedTypeParameterSymbol.vb @@ -126,6 +126,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols End Get End Property + Public Overrides ReadOnly Property AllowsByRefLike As Boolean + Get + Return _originalDefinition.AllowsByRefLike + End Get + End Property + Public Overrides ReadOnly Property IsImplicitlyDeclared As Boolean Get Return _originalDefinition.IsImplicitlyDeclared diff --git a/src/Compilers/VisualBasic/Portable/Symbols/SynthesizedSymbols/SynthesizedClonedTypeParameterSymbol.vb b/src/Compilers/VisualBasic/Portable/Symbols/SynthesizedSymbols/SynthesizedClonedTypeParameterSymbol.vb index d7a9a545059da..e7f8968add0ae 100644 --- a/src/Compilers/VisualBasic/Portable/Symbols/SynthesizedSymbols/SynthesizedClonedTypeParameterSymbol.vb +++ b/src/Compilers/VisualBasic/Portable/Symbols/SynthesizedSymbols/SynthesizedClonedTypeParameterSymbol.vb @@ -100,6 +100,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols End Get End Property + Public Overrides ReadOnly Property AllowsByRefLike As Boolean + Get + Return _correspondingMethodTypeParameter.AllowsByRefLike + End Get + End Property + Public Overrides ReadOnly Property Locations As ImmutableArray(Of Location) Get Return _correspondingMethodTypeParameter.Locations diff --git a/src/Compilers/VisualBasic/Portable/Symbols/TypeParameterSymbol.vb b/src/Compilers/VisualBasic/Portable/Symbols/TypeParameterSymbol.vb index a0e9968ac2f62..5f0cc8e579c95 100644 --- a/src/Compilers/VisualBasic/Portable/Symbols/TypeParameterSymbol.vb +++ b/src/Compilers/VisualBasic/Portable/Symbols/TypeParameterSymbol.vb @@ -317,11 +317,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols Public MustOverride ReadOnly Property HasValueTypeConstraint As Boolean Implements ITypeParameterSymbol.HasValueTypeConstraint - Public ReadOnly Property AllowsByRefLike As Boolean Implements ITypeParameterSymbol.AllowsByRefLike - Get - Return False ' PROTOTYPE(RefStructInterfaces): Implement for real - End Get - End Property + Public MustOverride ReadOnly Property AllowsByRefLike As Boolean Implements ITypeParameterSymbol.AllowsByRefLike Private ReadOnly Property HasUnmanagedTypeConstraint As Boolean Implements ITypeParameterSymbol.HasUnmanagedTypeConstraint Get diff --git a/src/Compilers/VisualBasic/Portable/Symbols/Wrapped/WrappedTypeParameterSymbol.vb b/src/Compilers/VisualBasic/Portable/Symbols/Wrapped/WrappedTypeParameterSymbol.vb index a98e82937f542..ae062ce77683b 100644 --- a/src/Compilers/VisualBasic/Portable/Symbols/Wrapped/WrappedTypeParameterSymbol.vb +++ b/src/Compilers/VisualBasic/Portable/Symbols/Wrapped/WrappedTypeParameterSymbol.vb @@ -61,6 +61,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols End Get End Property + Public Overrides ReadOnly Property AllowsByRefLike As Boolean + Get + Return Me._underlyingTypeParameter.AllowsByRefLike + End Get + End Property + Public Overrides ReadOnly Property Variance As VarianceKind Get Return Me._underlyingTypeParameter.Variance diff --git a/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/RefStructInterfacesTests.vb b/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/RefStructInterfacesTests.vb index e3a04faf75c60..793df33034fd5 100644 --- a/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/RefStructInterfacesTests.vb +++ b/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/RefStructInterfacesTests.vb @@ -4,6 +4,7 @@ Imports Microsoft.CodeAnalysis.Test.Utilities Imports Microsoft.CodeAnalysis.VisualBasic.Symbols +Imports Microsoft.CodeAnalysis.VisualBasic.Symbols.Metadata.PE Imports Roslyn.Test.Utilities Namespace Microsoft.CodeAnalysis.VisualBasic.UnitTests @@ -23,6 +24,199 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.UnitTests comp = CreateCompilation("", targetFramework:=TargetFramework.DesktopLatestExtended) Assert.False(comp.SupportsRuntimeCapability(RuntimeCapability.ByRefLikeGenerics)) End Sub + + + Public Sub AllowsConstraint_01() + + Dim csSource = +" +public class A; + +public class C + where T : allows ref struct +{ +} +" + + Dim csCompilation = CreateCSharpCompilation(csSource, + parseOptions:=CSharp.CSharpParseOptions.Default.WithLanguageVersion(CSharp.LanguageVersion.Preview), + referencedAssemblies:=TargetFrameworkUtil.GetReferences(s_targetFrameworkSupportingByRefLikeGenerics)).EmitToImageReference() + + Dim source1 = + + + + + Dim comp1 = CreateCompilation(source1, targetFramework:=s_targetFrameworkSupportingByRefLikeGenerics, references:={csCompilation}, options:=TestOptions.DebugExe) + + Dim a = comp1.GetTypeByMetadataName("A`1") + AssertEx.Equal("A(Of T)", a.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)) + Assert.False(a.TypeParameters.Single().AllowsByRefLike) + + Dim b = comp1.GetTypeByMetadataName("B`1") + AssertEx.Equal("B(Of S)", b.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)) + Assert.False(b.TypeParameters.Single().AllowsByRefLike) + + Dim c = comp1.GetTypeByMetadataName("C`1") + AssertEx.Equal("C(Of T)", c.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)) + Assert.True(c.TypeParameters.Single().AllowsByRefLike) + + c = b.BaseTypeNoUseSiteDiagnostics + AssertEx.Equal("C(Of S)", c.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)) + Assert.True(c.TypeParameters.Single().AllowsByRefLike) + + CompileAndVerify( + comp1, + verify:=If(ExecutionConditionUtil.IsMonoOrCoreClr, Verification.Passes, Verification.Skipped), + expectedOutput:=If(ExecutionConditionUtil.IsMonoOrCoreClr, "Done", Nothing)).VerifyDiagnostics() + End Sub + + + Public Sub AllowsConstraint_02() + + Dim csSource = +" +public class C +{ + public virtual void M() + where T : allows ref struct + { + } +} +" + + Dim csCompilation = CreateCSharpCompilation(csSource, + parseOptions:=CSharp.CSharpParseOptions.Default.WithLanguageVersion(CSharp.LanguageVersion.Preview), + referencedAssemblies:=TargetFrameworkUtil.GetReferences(s_targetFrameworkSupportingByRefLikeGenerics)).EmitToImageReference() + + Dim source1 = + + + + + Dim comp1 = CreateCompilation(source1, targetFramework:=s_targetFrameworkSupportingByRefLikeGenerics, references:={csCompilation}) + + Dim m = comp1.GetMember(Of MethodSymbol)("B.M") + Assert.False(m.TypeParameters.Single().AllowsByRefLike) + + comp1.AssertTheseDiagnostics( + +BC32077: 'Public Overrides Sub M(Of T)()' cannot override 'Public Overridable Overloads Sub M(Of T)()' because they differ by type parameter constraints. + Public Overrides Sub M(Of T) + ~ +) + End Sub + + + Public Sub AllowsConstraint_03() + + Dim csSource = +" +public interface IC +{ + public abstract void M() + where T : allows ref struct; +} +" + + Dim csCompilation = CreateCSharpCompilation(csSource, + parseOptions:=CSharp.CSharpParseOptions.Default.WithLanguageVersion(CSharp.LanguageVersion.Preview), + referencedAssemblies:=TargetFrameworkUtil.GetReferences(s_targetFrameworkSupportingByRefLikeGenerics)).EmitToImageReference() + + Dim source1 = + + + + + Dim comp1 = CreateCompilation(source1, targetFramework:=s_targetFrameworkSupportingByRefLikeGenerics, references:={csCompilation}) + comp1.AssertTheseDiagnostics( + +BC32078: 'Public Sub M(Of T)()' cannot implement 'IC.Sub M(Of T)()' because they differ by type parameter constraints. + Sub M(Of T) Implements IC.M + ~~~~ +) + + Dim m = comp1.GetMember(Of MethodSymbol)("B.M") + Assert.False(m.TypeParameters.Single().AllowsByRefLike) + End Sub + + + Public Sub NoPiaEmbedding() + Dim csSource = +" +using System; +using System.Runtime.InteropServices; +using System.Runtime.CompilerServices; + +[assembly: ImportedFromTypeLib(""GeneralPIA.dll"")] +[assembly: Guid(""f9c2d51d-4f44-45f0-9eda-c9d599b58257"")] + +[ComImport()] +[Guid(""f9c2d51d-4f44-45f0-9eda-c9d599b58278"")] +public interface ITest29 +{ + void M21() where T1 : allows ref struct; +} +" + + Dim csCompilation = CreateCSharpCompilation(csSource, + parseOptions:=CSharp.CSharpParseOptions.Default.WithLanguageVersion(CSharp.LanguageVersion.Preview), + assemblyName:="Pia", + referencedAssemblies:=TargetFrameworkUtil.GetReferences(s_targetFrameworkSupportingByRefLikeGenerics)).EmitToImageReference(embedInteropTypes:=True) + + Dim sources1 = + + + + Dim validator As Action(Of ModuleSymbol) = Sub([module]) + DirectCast([module], PEModuleSymbol).Module.PretendThereArentNoPiaLocalTypes() + + Dim type2 = [module].GlobalNamespace.GetMember(Of PENamedTypeSymbol)("ITest29") + Assert.Equal(TypeKind.Interface, type2.TypeKind) + Dim method = type2.GetMember(Of PEMethodSymbol)("M21") + Dim tp = method.TypeParameters + Dim t1 = tp(0) + Assert.Equal("T1", t1.Name) + Assert.True(t1.AllowsByRefLike) + End Sub + + Dim compilation1 = CreateCompilation( + sources1, + targetFramework:=s_targetFrameworkSupportingByRefLikeGenerics, + options:=TestOptions.DebugDll, + references:={csCompilation}) + + CompileAndVerify(compilation1, symbolValidator:=validator, verify:=Verification.Skipped).VerifyDiagnostics() + End Sub End Class End Namespace diff --git a/src/ExpressionEvaluator/VisualBasic/Source/ExpressionCompiler/Symbols/EETypeParameterSymbol.vb b/src/ExpressionEvaluator/VisualBasic/Source/ExpressionCompiler/Symbols/EETypeParameterSymbol.vb index eaf75fc239ea9..bc9b76779314b 100644 --- a/src/ExpressionEvaluator/VisualBasic/Source/ExpressionCompiler/Symbols/EETypeParameterSymbol.vb +++ b/src/ExpressionEvaluator/VisualBasic/Source/ExpressionCompiler/Symbols/EETypeParameterSymbol.vb @@ -64,6 +64,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExpressionEvaluator End Get End Property + Public Overrides ReadOnly Property AllowsByRefLike As Boolean + Get + Return _sourceTypeParameterSymbol.AllowsByRefLike + End Get + End Property + Public Overrides ReadOnly Property Locations As ImmutableArray(Of Location) Get Throw ExceptionUtilities.Unreachable diff --git a/src/ExpressionEvaluator/VisualBasic/Source/ExpressionCompiler/Symbols/SimpleTypeParameterSymbol.vb b/src/ExpressionEvaluator/VisualBasic/Source/ExpressionCompiler/Symbols/SimpleTypeParameterSymbol.vb index 19b822a4c7a74..3a2554ec6b033 100644 --- a/src/ExpressionEvaluator/VisualBasic/Source/ExpressionCompiler/Symbols/SimpleTypeParameterSymbol.vb +++ b/src/ExpressionEvaluator/VisualBasic/Source/ExpressionCompiler/Symbols/SimpleTypeParameterSymbol.vb @@ -64,6 +64,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExpressionEvaluator End Get End Property + Public Overrides ReadOnly Property AllowsByRefLike As Boolean + Get + Return False + End Get + End Property + Public Overrides ReadOnly Property Variance As VarianceKind Get Return VarianceKind.None From 906f0f32d85eecadfc0bdc408ed3a35e03c3febc Mon Sep 17 00:00:00 2001 From: AlekseyTs Date: Mon, 13 May 2024 20:24:46 -0700 Subject: [PATCH 2/2] Adjust tests --- .../Test/Symbol/SymbolsTests/RefStructInterfacesTests.vb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/RefStructInterfacesTests.vb b/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/RefStructInterfacesTests.vb index 793df33034fd5..f15fb04aa9130 100644 --- a/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/RefStructInterfacesTests.vb +++ b/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/RefStructInterfacesTests.vb @@ -116,6 +116,7 @@ End Class Dim m = comp1.GetMember(Of MethodSymbol)("B.M") Assert.False(m.TypeParameters.Single().AllowsByRefLike) + Assert.True(m.OverriddenMethod.TypeParameters.Single().AllowsByRefLike) comp1.AssertTheseDiagnostics( @@ -163,6 +164,7 @@ BC32078: 'Public Sub M(Of T)()' cannot implement 'IC.Sub M(Of T)()' because they Dim m = comp1.GetMember(Of MethodSymbol)("B.M") Assert.False(m.TypeParameters.Single().AllowsByRefLike) + Assert.True(m.ExplicitInterfaceImplementations.Single().TypeParameters.Single().AllowsByRefLike) End Sub