Skip to content

Commit

Permalink
Recognize 'allows ref struct' constraint in VB compiler (#73429)
Browse files Browse the repository at this point in the history
  • Loading branch information
AlekseyTs authored May 14, 2024
1 parent 7467dda commit 844663d
Show file tree
Hide file tree
Showing 21 changed files with 363 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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<ITypeSymbol> typeArguments)
Expand Down Expand Up @@ -917,7 +917,7 @@ private void AddTypeParameterConstraints(ImmutableArray<ITypeSymbol> typeArgumen
needComma = true;
}

//ctor constraint must be last
//ctor constraint must be last before 'allows ref struct'
if (typeParam.HasConstructorConstraint)
{
if (needComma)
Expand All @@ -929,6 +929,22 @@ private void AddTypeParameterConstraints(ImmutableArray<ITypeSymbol> 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);
}
}
}
Expand Down
66 changes: 66 additions & 0 deletions src/Compilers/CSharp/Test/Emit3/RefStructInterfacesTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4377,6 +4377,7 @@ void verify(ModuleSymbol m)
Assert.False(t.HasNotNullConstraint);
Assert.True(t.AllowsByRefLike);
Assert.True(t.GetPublicSymbol().AllowsByRefLike);
AssertEx.Equal("C<T> where T : allows ref struct", t.ContainingSymbol.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints));
}

comp = CreateCompilation(src, targetFramework: s_targetFrameworkSupportingByRefLikeGenerics, parseOptions: TestOptions.RegularNext).VerifyDiagnostics();
Expand Down Expand Up @@ -5085,6 +5086,7 @@ public class C<T>
Assert.False(t.HasNotNullConstraint);
Assert.True(t.HasConstructorConstraint);
Assert.True(t.AllowsByRefLike);
AssertEx.Equal("C<T> where T : new(), allows ref struct", t.ContainingSymbol.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints));
}

[Fact]
Expand All @@ -5108,6 +5110,7 @@ public class C<T>
Assert.False(t.HasNotNullConstraint);
Assert.True(t.HasConstructorConstraint);
Assert.True(t.AllowsByRefLike);
AssertEx.Equal("C<T> where T : new(), allows ref struct", t.ContainingSymbol.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints));
}

[Fact]
Expand Down Expand Up @@ -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>", t.ContainingSymbol.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints));
}
}

Expand Down Expand Up @@ -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<T1>() 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<ModuleSymbol> 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<T1>() 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();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading

0 comments on commit 844663d

Please sign in to comment.