From a55f298b9f6dd91b7381188e9da73f5fbb2435f6 Mon Sep 17 00:00:00 2001 From: AlekseyTs Date: Tue, 29 Oct 2024 06:36:34 -0700 Subject: [PATCH 1/4] VB: Recognize and check an `unmanaged` constraint --- .../Portable/Symbols/BaseTypeAnalysis.cs | 62 +- .../Core/Portable/Binding/UseSiteInfo.cs | 15 + .../Symbols/INamedTypeSymbolInternal.cs | 65 + .../BasicDeterministicKeyBuilderTests.cs | 6 +- .../Utilities/VisualBasic/BasicTestSource.vb | 9 +- .../VisualBasic/CompilationTestUtils.vb | 2 +- .../Test/Utilities/VisualBasic/Extensions.vb | 4 +- .../VisualBasic/ParserTestUtilities.vb | 2 +- .../Test/Utilities/VisualBasic/TestOptions.vb | 1 + .../VisualBasic/Portable/Binding/Binder.vb | 3 + .../Portable/Binding/Binder_Invocation.vb | 2 +- .../Portable/Binding/Binder_Lookup.vb | 2 +- .../Portable/Binding/Binder_Symbols.vb | 2 +- .../Portable/Binding/Binder_Utils.vb | 2 +- .../Portable/Binding/BindingLocation.vb | 2 + .../VisualBasicSymbolMatcher.vb | 1 + .../VisualBasic/Portable/Errors/ErrorFacts.vb | 1 + .../VisualBasic/Portable/Errors/Errors.vb | 4 +- .../VisualBasic/Portable/LanguageVersion.vb | 14 +- .../VisualBasic/Portable/Parser/Parser.vb | 12 +- .../Portable/Parser/ParserFeature.vb | 7 + .../Portable/PublicAPI.Unshipped.txt | 2 +- .../Portable/Semantics/Conversions.vb | 1 + .../Portable/Semantics/OverloadResolution.vb | 2 +- ...nymousTypeOrDelegateTypeParameterSymbol.vb | 6 + .../Portable/Symbols/ArrayTypeSymbol.vb | 4 + .../Portable/Symbols/ConstraintsHelper.vb | 53 +- .../Symbols/IndexedTypeParameterSymbol.vb | 6 + .../Symbols/InstanceErrorTypeSymbol.vb | 6 + .../Metadata/PE/PETypeParameterSymbol.vb | 66 +- .../Symbols/MethodSignatureComparer.vb | 1 + .../Portable/Symbols/MethodSymbol.vb | 10 +- .../Portable/Symbols/NamedTypeSymbol.vb | 117 +- .../Symbols/ReducedExtensionMethodSymbol.vb | 18 +- .../RetargetingTypeParameterSymbol.vb | 6 + .../Symbols/Source/CrefTypeParameterSymbol.vb | 6 + .../Symbols/Source/SourceEventSymbol.vb | 15 +- .../Symbols/Source/SourceFieldSymbol.vb | 21 +- .../Portable/Symbols/Source/SourceFile.vb | 4 +- .../Symbols/Source/SourceMemberFieldSymbol.vb | 13 + .../Symbols/Source/SourceMethodSymbol.vb | 8 +- .../Symbols/Source/SourceModuleSymbol.vb | 4 +- .../Symbols/Source/SourceNamedTypeSymbol.vb | 8 +- .../Source/SourcePropertyAccessorSymbol.vb | 8 +- .../Symbols/Source/SourcePropertySymbol.vb | 16 +- .../Source/SourceTypeParameterSymbol.vb | 10 +- .../Symbols/SubstitutedTypeParameterSymbol.vb | 6 + .../SynthesizedClonedTypeParameterSymbol.vb | 6 + .../Portable/Symbols/TypeParameterSymbol.vb | 10 +- .../Portable/Symbols/TypeSymbol.vb | 8 +- .../Portable/Symbols/TypeSymbolExtensions.vb | 11 + .../VisualBasic/Portable/VBResources.resx | 6 + .../Portable/xlf/VBResources.cs.xlf | 10 + .../Portable/xlf/VBResources.de.xlf | 10 + .../Portable/xlf/VBResources.es.xlf | 10 + .../Portable/xlf/VBResources.fr.xlf | 10 + .../Portable/xlf/VBResources.it.xlf | 10 + .../Portable/xlf/VBResources.ja.xlf | 10 + .../Portable/xlf/VBResources.ko.xlf | 10 + .../Portable/xlf/VBResources.pl.xlf | 10 + .../Portable/xlf/VBResources.pt-BR.xlf | 10 + .../Portable/xlf/VBResources.ru.xlf | 10 + .../Portable/xlf/VBResources.tr.xlf | 10 + .../Portable/xlf/VBResources.zh-Hans.xlf | 10 + .../Portable/xlf/VBResources.zh-Hant.xlf | 10 + .../Test/CommandLine/CommandLineTests.vb | 11 +- .../Test/Emit/CodeGen/CodeGenTuples.vb | 4 +- .../Compilation/CompilationAPITests.vb | 6 +- .../Compilation/SemanticModelAPITests.vb | 10 +- .../Semantic/Semantics/OverloadResolution.vb | 2 +- .../SymbolsTests/GenericConstraintTests.vb | 12 +- .../SymbolsTests/InstantiatingGenerics.vb | 2 +- .../Metadata/PE/LoadCustomModifiers.vb | 82 +- .../Symbol/SymbolsTests/SymbolErrorTests.vb | 2 +- .../UnmanagedTypeConstraintTests.vb | 1799 +++++++++++++++++ .../Symbols/EETypeParameterSymbol.vb | 6 + .../Symbols/SimpleTypeParameterSymbol.vb | 6 + 77 files changed, 2581 insertions(+), 167 deletions(-) create mode 100644 src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/UnmanagedTypeConstraintTests.vb diff --git a/src/Compilers/CSharp/Portable/Symbols/BaseTypeAnalysis.cs b/src/Compilers/CSharp/Portable/Symbols/BaseTypeAnalysis.cs index 8583f3cb714b9..7d5e29491e665 100644 --- a/src/Compilers/CSharp/Portable/Symbols/BaseTypeAnalysis.cs +++ b/src/Compilers/CSharp/Portable/Symbols/BaseTypeAnalysis.cs @@ -8,6 +8,7 @@ using System.Diagnostics; using Microsoft.CodeAnalysis.Collections; using Microsoft.CodeAnalysis.PooledObjects; +using Microsoft.CodeAnalysis.Symbols; using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.CSharp.Symbols @@ -122,7 +123,9 @@ private static void StructDependsClosure(NamedTypeSymbol type, HashSet p /// internal static ManagedKind GetManagedKind(NamedTypeSymbol type, ref CompoundUseSiteInfo useSiteInfo) { - var (isManaged, hasGenerics) = IsManagedTypeHelper(type); + // The code below should be kept in sync with NamedTypeSymbol.GetManagedKind in VB + + var (isManaged, hasGenerics) = INamedTypeSymbolInternal.Helpers.IsManagedTypeHelper(type); var definitelyManaged = isManaged == ThreeState.True; if (isManaged == ThreeState.Unknown) { @@ -201,7 +204,7 @@ internal static ManagedKind GetManagedKind(NamedTypeSymbol type, ref CompoundUse } else { - var result = IsManagedTypeHelper(fieldNamedType); + var result = INamedTypeSymbolInternal.Helpers.IsManagedTypeHelper(fieldNamedType); hasGenerics = hasGenerics || result.hasGenerics; // NOTE: don't use ManagedKind.get on a NamedTypeSymbol - that could lead // to infinite recursion. @@ -235,60 +238,5 @@ internal static ManagedKind GetManagedKind(NamedTypeSymbol type, ref CompoundUse internal static TypeSymbol NonPointerType(this FieldSymbol field) => field.HasPointerType ? null : field.Type; - - /// - /// Returns True or False if we can determine whether the type is managed - /// without looking at its fields and Unknown otherwise. - /// Also returns whether or not the given type is generic. - /// - private static (ThreeState isManaged, bool hasGenerics) IsManagedTypeHelper(NamedTypeSymbol type) - { - // To match dev10, we treat enums as their underlying types. - if (type.IsEnumType()) - { - type = type.GetEnumUnderlyingType(); - } - - // Short-circuit common cases. - switch (type.SpecialType) - { - case SpecialType.System_Void: - case SpecialType.System_Boolean: - case SpecialType.System_Char: - case SpecialType.System_SByte: - case SpecialType.System_Byte: - case SpecialType.System_Int16: - case SpecialType.System_UInt16: - case SpecialType.System_Int32: - case SpecialType.System_UInt32: - case SpecialType.System_Int64: - case SpecialType.System_UInt64: - case SpecialType.System_Decimal: - case SpecialType.System_Single: - case SpecialType.System_Double: - case SpecialType.System_IntPtr: - case SpecialType.System_UIntPtr: - case SpecialType.System_ArgIterator: - case SpecialType.System_RuntimeArgumentHandle: - return (ThreeState.False, false); - case SpecialType.System_TypedReference: - return (ThreeState.True, false); - case SpecialType.None: - default: - // CONSIDER: could provide cases for other common special types. - break; // Proceed with additional checks. - } - - bool hasGenerics = type.IsGenericType; - switch (type.TypeKind) - { - case TypeKind.Enum: - return (ThreeState.False, hasGenerics); - case TypeKind.Struct: - return (ThreeState.Unknown, hasGenerics); - default: - return (ThreeState.True, hasGenerics); - } - } } } diff --git a/src/Compilers/Core/Portable/Binding/UseSiteInfo.cs b/src/Compilers/Core/Portable/Binding/UseSiteInfo.cs index 5b4d4e0667415..7216e11b68097 100644 --- a/src/Compilers/Core/Portable/Binding/UseSiteInfo.cs +++ b/src/Compilers/Core/Portable/Binding/UseSiteInfo.cs @@ -320,6 +320,21 @@ public void AddDiagnostics(ImmutableArray diagnostics) } } + public void AddDiagnosticInfo(DiagnosticInfo diagnosticInfo) + { + if (!AccumulatesDiagnostics) + { + return; + } + + _diagnostics ??= new HashSet(); + + if (_diagnostics.Add(diagnosticInfo) && diagnosticInfo?.Severity == DiagnosticSeverity.Error) + { + RecordPresenceOfAnError(); + } + } + public void AddDependencies(UseSiteInfo info) { if (!_hasErrors && AccumulatesDependencies) diff --git a/src/Compilers/Core/Portable/Symbols/INamedTypeSymbolInternal.cs b/src/Compilers/Core/Portable/Symbols/INamedTypeSymbolInternal.cs index 9bbab4d281ebf..5cea8316655f0 100644 --- a/src/Compilers/Core/Portable/Symbols/INamedTypeSymbolInternal.cs +++ b/src/Compilers/Core/Portable/Symbols/INamedTypeSymbolInternal.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using System.Collections.Immutable; +using System.Diagnostics; namespace Microsoft.CodeAnalysis.Symbols { @@ -16,5 +17,69 @@ internal interface INamedTypeSymbolInternal : ITypeSymbolInternal ImmutableArray GetMembers(); ImmutableArray GetMembers(string name); + + /// + /// True if this type or some containing type has type parameters. + /// + public bool IsGenericType { get; } + + internal static class Helpers + { + /// + /// Returns True or False if we can determine whether the type is managed + /// without looking at its fields and Unknown otherwise. + /// Also returns whether or not the given type is generic. + /// + public static (ThreeState isManaged, bool hasGenerics) IsManagedTypeHelper(INamedTypeSymbolInternal type) + { + // To match dev10, we treat enums as their underlying types. + if (type.TypeKind == TypeKind.Enum) + { + Debug.Assert(type.EnumUnderlyingType is not null); + type = type.EnumUnderlyingType; + } + + // Short-circuit common cases. + switch (type.SpecialType) + { + case SpecialType.System_Void: + case SpecialType.System_Boolean: + case SpecialType.System_Char: + case SpecialType.System_SByte: + case SpecialType.System_Byte: + case SpecialType.System_Int16: + case SpecialType.System_UInt16: + case SpecialType.System_Int32: + case SpecialType.System_UInt32: + case SpecialType.System_Int64: + case SpecialType.System_UInt64: + case SpecialType.System_Decimal: + case SpecialType.System_Single: + case SpecialType.System_Double: + case SpecialType.System_IntPtr: + case SpecialType.System_UIntPtr: + case SpecialType.System_ArgIterator: + case SpecialType.System_RuntimeArgumentHandle: + return (ThreeState.False, false); + case SpecialType.System_TypedReference: + return (ThreeState.True, false); + case SpecialType.None: + default: + // CONSIDER: could provide cases for other common special types. + break; // Proceed with additional checks. + } + + bool hasGenerics = type.IsGenericType; + switch (type.TypeKind) + { + case TypeKind.Enum: + return (ThreeState.False, hasGenerics); + case TypeKind.Struct: + return (ThreeState.Unknown, hasGenerics); + default: + return (ThreeState.True, hasGenerics); + } + } + } } } diff --git a/src/Compilers/Core/RebuildTest/BasicDeterministicKeyBuilderTests.cs b/src/Compilers/Core/RebuildTest/BasicDeterministicKeyBuilderTests.cs index 24e0c4f6122c4..f6977a5e218fd 100644 --- a/src/Compilers/Core/RebuildTest/BasicDeterministicKeyBuilderTests.cs +++ b/src/Compilers/Core/RebuildTest/BasicDeterministicKeyBuilderTests.cs @@ -220,7 +220,7 @@ public void BasicPathMapWindows(string filePath, string workingDirectory, string ""specifiedLanguageVersion"": ""VisualBasic15"", ""preprocessorSymbols"": { ""TARGET"": ""exe"", - ""VBC_VER"": ""16.9"" + ""VBC_VER"": ""17.13"" } } } @@ -360,7 +360,7 @@ public void FeatureFlag() ""specifiedLanguageVersion"": ""Default"", ""preprocessorSymbols"": {{ ""TARGET"": ""library"", - ""VBC_VER"": ""16.9"", + ""VBC_VER"": ""17.13"", ""_MYTYPE"": ""Empty"" }} }} @@ -385,7 +385,7 @@ public void FeatureFlag() ""specifiedLanguageVersion"": ""Default"", ""preprocessorSymbols"": {{ ""TARGET"": ""library"", - ""VBC_VER"": ""16.9"", + ""VBC_VER"": ""17.13"", ""_MYTYPE"": ""Empty"" }} }} diff --git a/src/Compilers/Test/Utilities/VisualBasic/BasicTestSource.vb b/src/Compilers/Test/Utilities/VisualBasic/BasicTestSource.vb index dd88a392d4954..6fd897b5505f2 100644 --- a/src/Compilers/Test/Utilities/VisualBasic/BasicTestSource.vb +++ b/src/Compilers/Test/Utilities/VisualBasic/BasicTestSource.vb @@ -43,12 +43,17 @@ Public Structure BasicTestSource Dim source = TryCast(Value, String) If source IsNot Nothing Then - Return New SyntaxTree() {VisualBasicSyntaxTree.ParseText(SourceText.From(source, encoding:=Nothing, SourceHashAlgorithms.Default), parseOptions)} + Return New SyntaxTree() _ + { + VisualBasicSyntaxTree.ParseText( + SourceText.From(source, encoding:=Nothing, SourceHashAlgorithms.Default), + If(parseOptions, TestOptions.RegularLatest)) + } End If Dim sources = TryCast(Value, String()) If sources IsNot Nothing Then - Return sources.Select(Function(s) VisualBasicSyntaxTree.ParseText(SourceText.From(s, encoding:=Nothing, SourceHashAlgorithms.Default), parseOptions)).ToArray() + Return sources.Select(Function(s) VisualBasicSyntaxTree.ParseText(SourceText.From(s, encoding:=Nothing, SourceHashAlgorithms.Default), If(parseOptions, TestOptions.RegularLatest))).ToArray() End If Dim tree = TryCast(Value, SyntaxTree) diff --git a/src/Compilers/Test/Utilities/VisualBasic/CompilationTestUtils.vb b/src/Compilers/Test/Utilities/VisualBasic/CompilationTestUtils.vb index 92534ab7a301f..93f4e83be9b84 100644 --- a/src/Compilers/Test/Utilities/VisualBasic/CompilationTestUtils.vb +++ b/src/Compilers/Test/Utilities/VisualBasic/CompilationTestUtils.vb @@ -651,7 +651,7 @@ Friend Module CompilationUtils MarkupTestFile.GetSpans(codeWithMarker, codeWithoutMarker, spans) Dim text = SourceText.From(codeWithoutMarker, Encoding.UTF8) - Return (VisualBasicSyntaxTree.ParseText(text, parseOptions, If(programElement.@name, "")), spans) + Return (VisualBasicSyntaxTree.ParseText(text, If(parseOptions, TestOptions.RegularLatest), If(programElement.@name, "")), spans) End Function ' Find a node inside a tree. diff --git a/src/Compilers/Test/Utilities/VisualBasic/Extensions.vb b/src/Compilers/Test/Utilities/VisualBasic/Extensions.vb index 74017f93d7cc8..f8fb2e210426a 100644 --- a/src/Compilers/Test/Utilities/VisualBasic/Extensions.vb +++ b/src/Compilers/Test/Utilities/VisualBasic/Extensions.vb @@ -344,12 +344,12 @@ Friend Module Extensions Friend Function ReduceExtensionMethod(this As MethodSymbol, instanceType As TypeSymbol) As MethodSymbol - Return this.ReduceExtensionMethod(instanceType, CompoundUseSiteInfo(Of AssemblySymbol).Discarded) + Return this.ReduceExtensionMethod(instanceType, CompoundUseSiteInfo(Of AssemblySymbol).Discarded, LanguageVersion.Latest) End Function Friend Function ReduceExtensionMethod(this As MethodSymbol, instanceType As TypeSymbol, proximity As Integer) As MethodSymbol - Return this.ReduceExtensionMethod(instanceType, proximity, CompoundUseSiteInfo(Of AssemblySymbol).Discarded) + Return this.ReduceExtensionMethod(instanceType, proximity, CompoundUseSiteInfo(Of AssemblySymbol).Discarded, LanguageVersion.Latest) End Function diff --git a/src/Compilers/Test/Utilities/VisualBasic/ParserTestUtilities.vb b/src/Compilers/Test/Utilities/VisualBasic/ParserTestUtilities.vb index 005330a70f15c..1858d6987c0d7 100644 --- a/src/Compilers/Test/Utilities/VisualBasic/ParserTestUtilities.vb +++ b/src/Compilers/Test/Utilities/VisualBasic/ParserTestUtilities.vb @@ -110,7 +110,7 @@ Friend Module ParserTestUtilities encoding = Encoding.UTF8 End If - Dim tree = VisualBasicSyntaxTree.ParseText(SourceText.From(source, encoding), options:=If(options, VisualBasicParseOptions.Default), path:=fileName) + Dim tree = VisualBasicSyntaxTree.ParseText(SourceText.From(source, encoding), options:=If(options, TestOptions.RegularLatest), path:=fileName) Dim root = tree.GetRoot() ' Verify FullText Assert.Equal(source, root.ToFullString) diff --git a/src/Compilers/Test/Utilities/VisualBasic/TestOptions.vb b/src/Compilers/Test/Utilities/VisualBasic/TestOptions.vb index 84c370aa213f7..875f9fd5029a2 100644 --- a/src/Compilers/Test/Utilities/VisualBasic/TestOptions.vb +++ b/src/Compilers/Test/Utilities/VisualBasic/TestOptions.vb @@ -14,6 +14,7 @@ Public Class TestOptions Public Shared ReadOnly Regular15_5 As VisualBasicParseOptions = Regular.WithLanguageVersion(LanguageVersion.VisualBasic15_5) Public Shared ReadOnly Regular16 As VisualBasicParseOptions = Regular.WithLanguageVersion(LanguageVersion.VisualBasic16) Public Shared ReadOnly Regular16_9 As VisualBasicParseOptions = Regular.WithLanguageVersion(LanguageVersion.VisualBasic16_9) + Public Shared ReadOnly Regular17_13 As VisualBasicParseOptions = Regular.WithLanguageVersion(LanguageVersion.VisualBasic17_13) Public Shared ReadOnly RegularLatest As VisualBasicParseOptions = Regular.WithLanguageVersion(LanguageVersion.Latest) Public Shared ReadOnly RegularWithLegacyStrongName As VisualBasicParseOptions = Regular.WithFeature("UseLegacyStrongNameProvider") diff --git a/src/Compilers/VisualBasic/Portable/Binding/Binder.vb b/src/Compilers/VisualBasic/Portable/Binding/Binder.vb index f768e7f1ee1b8..a5d5bc1becfb0 100644 --- a/src/Compilers/VisualBasic/Portable/Binding/Binder.vb +++ b/src/Compilers/VisualBasic/Portable/Binding/Binder.vb @@ -1029,6 +1029,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic Select Case Me.BindingLocation Case BindingLocation.BaseTypes, BindingLocation.MethodSignature, + BindingLocation.FieldType, + BindingLocation.PropertyType, + BindingLocation.EventType, BindingLocation.GenericConstraintsClause, BindingLocation.ProjectImportsDeclaration, BindingLocation.SourceFileImportsDeclaration diff --git a/src/Compilers/VisualBasic/Portable/Binding/Binder_Invocation.vb b/src/Compilers/VisualBasic/Portable/Binding/Binder_Invocation.vb index 4b6fc722871a4..a1aa76da2ac0e 100644 --- a/src/Compilers/VisualBasic/Portable/Binding/Binder_Invocation.vb +++ b/src/Compilers/VisualBasic/Portable/Binding/Binder_Invocation.vb @@ -2274,7 +2274,7 @@ ProduceBoundNode: Dim method = DirectCast(candidate.UnderlyingSymbol, MethodSymbol) ' TODO: Dev10 uses the location of the type parameter or argument that ' violated the constraint, rather than the entire invocation expression. - Dim succeeded = method.CheckConstraints(diagnosticLocation, diagnostics, template:=GetNewCompoundUseSiteInfo(diagnostics)) + Dim succeeded = method.CheckConstraints(Compilation.LanguageVersion, diagnosticLocation, diagnostics, template:=GetNewCompoundUseSiteInfo(diagnostics)) Debug.Assert(Not succeeded) Return End If diff --git a/src/Compilers/VisualBasic/Portable/Binding/Binder_Lookup.vb b/src/Compilers/VisualBasic/Portable/Binding/Binder_Lookup.vb index 366b4ae2b1da4..cbeb2eb0d71ea 100644 --- a/src/Compilers/VisualBasic/Portable/Binding/Binder_Lookup.vb +++ b/src/Compilers/VisualBasic/Portable/Binding/Binder_Lookup.vb @@ -1217,7 +1217,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ' Process all methods from the same type together. Do ' Try to reduce this method and merge with the current result - Dim reduced As MethodSymbol = methods(i).ReduceExtensionMethod(container, proximity, useSiteInfo) + Dim reduced As MethodSymbol = methods(i).ReduceExtensionMethod(container, proximity, useSiteInfo, binder.Compilation.LanguageVersion) If reduced IsNot Nothing Then lookupResult.MergeOverloadedOrPrioritizedExtensionMethods(binder.CheckViability(reduced, arity, options, reduced.ContainingType, useSiteInfo)) diff --git a/src/Compilers/VisualBasic/Portable/Binding/Binder_Symbols.vb b/src/Compilers/VisualBasic/Portable/Binding/Binder_Symbols.vb index f6da9ae8a394e..b3e96eea9d9d0 100644 --- a/src/Compilers/VisualBasic/Portable/Binding/Binder_Symbols.vb +++ b/src/Compilers/VisualBasic/Portable/Binding/Binder_Symbols.vb @@ -175,7 +175,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ' Interface IA(Of T As C) : End Interface ' Interface IB(Of T As C) : Inherits IA(Of T) : End Interface If checkConstraints AndAlso ShouldCheckConstraints Then - constructedType.CheckConstraintsForNonTuple(syntaxArguments, diagnostics, template:=GetNewCompoundUseSiteInfo(diagnostics)) + constructedType.CheckConstraintsForNonTuple(Compilation.LanguageVersion, syntaxArguments, diagnostics, template:=GetNewCompoundUseSiteInfo(diagnostics)) End If constructedType = DirectCast(TupleTypeSymbol.TransformToTupleIfCompatible(constructedType), NamedTypeSymbol) diff --git a/src/Compilers/VisualBasic/Portable/Binding/Binder_Utils.vb b/src/Compilers/VisualBasic/Portable/Binding/Binder_Utils.vb index f674f21110d33..12e56274d263c 100644 --- a/src/Compilers/VisualBasic/Portable/Binding/Binder_Utils.vb +++ b/src/Compilers/VisualBasic/Portable/Binding/Binder_Utils.vb @@ -301,7 +301,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic If ShouldCheckConstraints Then Dim diagnosticsBuilder = ArrayBuilder(Of TypeParameterDiagnosticInfo).GetInstance() Dim useSiteDiagnosticsBuilder As ArrayBuilder(Of TypeParameterDiagnosticInfo) = Nothing - constructedType.CheckConstraints(diagnosticsBuilder, useSiteDiagnosticsBuilder, template:=GetNewCompoundUseSiteInfo(diagBag)) + constructedType.CheckConstraints(Compilation.LanguageVersion, diagnosticsBuilder, useSiteDiagnosticsBuilder, template:=GetNewCompoundUseSiteInfo(diagBag)) If useSiteDiagnosticsBuilder IsNot Nothing Then diagnosticsBuilder.AddRange(useSiteDiagnosticsBuilder) diff --git a/src/Compilers/VisualBasic/Portable/Binding/BindingLocation.vb b/src/Compilers/VisualBasic/Portable/Binding/BindingLocation.vb index 64627343e1664..ee21c0c6e4394 100644 --- a/src/Compilers/VisualBasic/Portable/Binding/BindingLocation.vb +++ b/src/Compilers/VisualBasic/Portable/Binding/BindingLocation.vb @@ -21,8 +21,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic EventSignature FieldType HandlesClause + PropertyType PropertySignature PropertyAccessorSignature + EventType EventAccessorSignature End Enum diff --git a/src/Compilers/VisualBasic/Portable/Emit/EditAndContinue/VisualBasicSymbolMatcher.vb b/src/Compilers/VisualBasic/Portable/Emit/EditAndContinue/VisualBasicSymbolMatcher.vb index f14fa7854ca66..db9448ac0f6a1 100644 --- a/src/Compilers/VisualBasic/Portable/Emit/EditAndContinue/VisualBasicSymbolMatcher.vb +++ b/src/Compilers/VisualBasic/Portable/Emit/EditAndContinue/VisualBasicSymbolMatcher.vb @@ -478,6 +478,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Emit Debug.Assert(type.AllowsRefLikeType = other.AllowsRefLikeType) Debug.Assert(type.HasReferenceTypeConstraint = other.HasReferenceTypeConstraint) Debug.Assert(type.ConstraintTypesNoUseSiteDiagnostics.Length = other.ConstraintTypesNoUseSiteDiagnostics.Length) + Debug.Assert(type.HasUnmanagedTypeConstraint = other.HasUnmanagedTypeConstraint) Return True End Function diff --git a/src/Compilers/VisualBasic/Portable/Errors/ErrorFacts.vb b/src/Compilers/VisualBasic/Portable/Errors/ErrorFacts.vb index 90324908c2390..48fe778a53989 100644 --- a/src/Compilers/VisualBasic/Portable/Errors/ErrorFacts.vb +++ b/src/Compilers/VisualBasic/Portable/Errors/ErrorFacts.vb @@ -1366,6 +1366,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ERRID.ERR_DoNotUseRequiredMember, ERRID.ERR_UnsupportedRefReturningCallInWithStatement, ERRID.ERR_TypeReserved, + ERRID.ERR_UnmanagedConstraintNotSatisfied, ERRID.ERR_NextAvailable, ERRID.WRN_UseOfObsoleteSymbol2, ERRID.WRN_InvalidOverrideDueToTupleNames2, diff --git a/src/Compilers/VisualBasic/Portable/Errors/Errors.vb b/src/Compilers/VisualBasic/Portable/Errors/Errors.vb index 337adb8b5246a..7a1f4efecbec3 100644 --- a/src/Compilers/VisualBasic/Portable/Errors/Errors.vb +++ b/src/Compilers/VisualBasic/Portable/Errors/Errors.vb @@ -1781,8 +1781,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ERR_LockTypeUnsupported = 37329 ERR_InvalidVersionFormatDeterministic = 37330 ERR_TypeReserved = 37331 + ERR_UnmanagedConstraintNotSatisfied = 37332 - ERR_NextAvailable = 37332 + ERR_NextAvailable = 37333 '// WARNINGS BEGIN HERE WRN_UseOfObsoleteSymbol2 = 40000 @@ -2081,5 +2082,6 @@ Namespace Microsoft.CodeAnalysis.VisualBasic FEATURE_CommentsAfterLineContinuation FEATURE_InitOnlySettersUsage FEATURE_CallerArgumentExpression + FEATURE_UnmanagedConstraint End Enum End Namespace diff --git a/src/Compilers/VisualBasic/Portable/LanguageVersion.vb b/src/Compilers/VisualBasic/Portable/LanguageVersion.vb index 2c416182c3ac8..1a6aac70c9f81 100644 --- a/src/Compilers/VisualBasic/Portable/LanguageVersion.vb +++ b/src/Compilers/VisualBasic/Portable/LanguageVersion.vb @@ -21,6 +21,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic VisualBasic15_5 = 1505 VisualBasic16 = 1600 VisualBasic16_9 = 1609 + VisualBasic17_13 = 1713 Latest = Integer.MaxValue End Enum @@ -39,7 +40,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic LanguageVersion.VisualBasic15_3, LanguageVersion.VisualBasic15_5, LanguageVersion.VisualBasic16, - LanguageVersion.VisualBasic16_9 + LanguageVersion.VisualBasic16_9, + LanguageVersion.VisualBasic17_13 Return True End Select @@ -71,6 +73,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic Return "16" Case LanguageVersion.VisualBasic16_9 Return "16.9" + Case LanguageVersion.VisualBasic17_13 + Return "17.13" Case Else Throw ExceptionUtilities.UnexpectedValue(value) End Select @@ -87,7 +91,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic Public Function MapSpecifiedToEffectiveVersion(version As LanguageVersion) As LanguageVersion Select Case version Case LanguageVersion.Latest - Return LanguageVersion.VisualBasic16_9 + Return LanguageVersion.VisualBasic17_13 Case LanguageVersion.Default Return LanguageVersion.VisualBasic16_9 Case Else @@ -97,7 +101,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic Friend ReadOnly Property CurrentVersion As LanguageVersion Get - Return LanguageVersion.VisualBasic16_9 + Return LanguageVersion.VisualBasic17_13 End Get End Property @@ -128,6 +132,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic Return "16" Case LanguageVersion.VisualBasic16_9 Return "16.9" + Case LanguageVersion.VisualBasic17_13 + Return "17.13" Case LanguageVersion.Default Return "default" Case LanguageVersion.Latest @@ -167,6 +173,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic result = LanguageVersion.VisualBasic16 Case "16.9" result = LanguageVersion.VisualBasic16_9 + Case "17.13" + result = LanguageVersion.VisualBasic17_13 Case "default" result = LanguageVersion.Default Case "latest" diff --git a/src/Compilers/VisualBasic/Portable/Parser/Parser.vb b/src/Compilers/VisualBasic/Portable/Parser/Parser.vb index b9423962bd48f..2b7dc24d71d1f 100644 --- a/src/Compilers/VisualBasic/Portable/Parser/Parser.vb +++ b/src/Compilers/VisualBasic/Portable/Parser/Parser.vb @@ -6131,9 +6131,7 @@ checkNullable: Friend Shared Function CheckFeatureAvailability(diagnosticsOpt As DiagnosticBag, location As Location, languageVersion As LanguageVersion, feature As Feature) As Boolean If Not CheckFeatureAvailability(languageVersion, feature) Then If diagnosticsOpt IsNot Nothing Then - Dim featureName = ErrorFactory.ErrorInfo(feature.GetResourceId()) - Dim requiredVersion = New VisualBasicRequiredLanguageVersion(feature.GetLanguageVersion()) - diagnosticsOpt.Add(ERRID.ERR_LanguageVersion, location, languageVersion.GetErrorName(), featureName, requiredVersion) + diagnosticsOpt.Add(GetFeatureAvailabilityError(feature, languageVersion), location) End If Return False @@ -6141,6 +6139,14 @@ checkNullable: Return True End Function + Friend Shared Function GetFeatureAvailabilityError(feature As Feature, languageVersion As LanguageVersion) As DiagnosticInfo + Return ErrorFactory.ErrorInfo( + ERRID.ERR_LanguageVersion, + languageVersion.GetErrorName(), + ErrorFactory.ErrorInfo(feature.GetResourceId()), + New VisualBasicRequiredLanguageVersion(feature.GetLanguageVersion())) + End Function + Friend Shared Function CheckFeatureAvailability(diagnostics As BindingDiagnosticBag, location As Location, languageVersion As LanguageVersion, feature As Feature) As Boolean Return CheckFeatureAvailability(diagnostics.DiagnosticBag, location, languageVersion, feature) End Function diff --git a/src/Compilers/VisualBasic/Portable/Parser/ParserFeature.vb b/src/Compilers/VisualBasic/Portable/Parser/ParserFeature.vb index 71a47e3f057fd..9235e57dd1710 100644 --- a/src/Compilers/VisualBasic/Portable/Parser/ParserFeature.vb +++ b/src/Compilers/VisualBasic/Portable/Parser/ParserFeature.vb @@ -41,6 +41,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Syntax.InternalSyntax UnconstrainedTypeParameterInConditional CommentsAfterLineContinuation InitOnlySettersUsage + UnmanagedConstraint End Enum Friend Module FeatureExtensions @@ -105,6 +106,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Syntax.InternalSyntax Case Feature.InitOnlySettersUsage Return LanguageVersion.VisualBasic16_9 + + Case Feature.UnmanagedConstraint + Return LanguageVersion.VisualBasic17_13 + Case Else Throw ExceptionUtilities.UnexpectedValue(feature) End Select @@ -178,6 +183,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Syntax.InternalSyntax Return ERRID.FEATURE_CommentsAfterLineContinuation Case Feature.InitOnlySettersUsage Return ERRID.FEATURE_InitOnlySettersUsage + Case Feature.UnmanagedConstraint + Return ERRID.FEATURE_UnmanagedConstraint Case Else Throw ExceptionUtilities.UnexpectedValue(feature) End Select diff --git a/src/Compilers/VisualBasic/Portable/PublicAPI.Unshipped.txt b/src/Compilers/VisualBasic/Portable/PublicAPI.Unshipped.txt index 8b137891791fe..360164d8fcc64 100644 --- a/src/Compilers/VisualBasic/Portable/PublicAPI.Unshipped.txt +++ b/src/Compilers/VisualBasic/Portable/PublicAPI.Unshipped.txt @@ -1 +1 @@ - +Microsoft.CodeAnalysis.VisualBasic.LanguageVersion.VisualBasic17_13 = 1713 -> Microsoft.CodeAnalysis.VisualBasic.LanguageVersion diff --git a/src/Compilers/VisualBasic/Portable/Semantics/Conversions.vb b/src/Compilers/VisualBasic/Portable/Semantics/Conversions.vb index 7dd98a025230b..ba8e9d9e0e956 100644 --- a/src/Compilers/VisualBasic/Portable/Semantics/Conversions.vb +++ b/src/Compilers/VisualBasic/Portable/Semantics/Conversions.vb @@ -2032,6 +2032,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic While candidate IsNot Nothing If ConstraintsHelper.CheckConstraints(constructedSymbol:=Nothing, + LanguageVersion.Latest, ' Classifying conversions from/to type parameters. This is meaningful only when they are and their constraints are declared in source substitution:=Nothing, typeParameter:=typeParam, typeArgument:=candidate, diff --git a/src/Compilers/VisualBasic/Portable/Semantics/OverloadResolution.vb b/src/Compilers/VisualBasic/Portable/Semantics/OverloadResolution.vb index ebc523567a7c2..6d69e5c4ce84c 100644 --- a/src/Compilers/VisualBasic/Portable/Semantics/OverloadResolution.vb +++ b/src/Compilers/VisualBasic/Portable/Semantics/OverloadResolution.vb @@ -2895,7 +2895,7 @@ Bailout: If method.IsGenericMethod Then Dim diagnosticsBuilder = ArrayBuilder(Of TypeParameterDiagnosticInfo).GetInstance() Dim useSiteDiagnosticsBuilder As ArrayBuilder(Of TypeParameterDiagnosticInfo) = Nothing - Dim satisfiedConstraints = method.CheckConstraints(diagnosticsBuilder, useSiteDiagnosticsBuilder, template:=useSiteInfo) + Dim satisfiedConstraints = method.CheckConstraints(binder.Compilation.LanguageVersion, diagnosticsBuilder, useSiteDiagnosticsBuilder, template:=useSiteInfo) diagnosticsBuilder.Free() If useSiteDiagnosticsBuilder IsNot Nothing AndAlso useSiteDiagnosticsBuilder.Count > 0 Then diff --git a/src/Compilers/VisualBasic/Portable/Symbols/AnonymousTypes/SynthesizedSymbols/AnonymousTypeOrDelegateTypeParameterSymbol.vb b/src/Compilers/VisualBasic/Portable/Symbols/AnonymousTypes/SynthesizedSymbols/AnonymousTypeOrDelegateTypeParameterSymbol.vb index f8571dbac4861..9d48c9b4c2517 100644 --- a/src/Compilers/VisualBasic/Portable/Symbols/AnonymousTypes/SynthesizedSymbols/AnonymousTypeOrDelegateTypeParameterSymbol.vb +++ b/src/Compilers/VisualBasic/Portable/Symbols/AnonymousTypes/SynthesizedSymbols/AnonymousTypeOrDelegateTypeParameterSymbol.vb @@ -42,6 +42,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols End Get End Property + Friend Overrides ReadOnly Property HasUnmanagedTypeConstraint 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/ArrayTypeSymbol.vb b/src/Compilers/VisualBasic/Portable/Symbols/ArrayTypeSymbol.vb index baffd44f6e146..e209b6032c0a8 100644 --- a/src/Compilers/VisualBasic/Portable/Symbols/ArrayTypeSymbol.vb +++ b/src/Compilers/VisualBasic/Portable/Symbols/ArrayTypeSymbol.vb @@ -364,6 +364,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols Friend MustOverride Function WithElementType(elementType As TypeSymbol) As ArrayTypeSymbol + Friend Overrides Function GetManagedKind(ByRef useSiteInfo As CompoundUseSiteInfo(Of AssemblySymbol)) As ManagedKind + Return ManagedKind.Managed + End Function + #Region "Use-Site Diagnostics" Friend Overrides Function GetUseSiteInfo() As UseSiteInfo(Of AssemblySymbol) diff --git a/src/Compilers/VisualBasic/Portable/Symbols/ConstraintsHelper.vb b/src/Compilers/VisualBasic/Portable/Symbols/ConstraintsHelper.vb index d7a8f078fc96a..129ee7d783771 100644 --- a/src/Compilers/VisualBasic/Portable/Symbols/ConstraintsHelper.vb +++ b/src/Compilers/VisualBasic/Portable/Symbols/ConstraintsHelper.vb @@ -383,12 +383,13 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols Public Sub CheckAllConstraints( type As TypeSymbol, + languageVersion As LanguageVersion, loc As Location, diagnostics As BindingDiagnosticBag, template As CompoundUseSiteInfo(Of AssemblySymbol)) Dim diagnosticsBuilder = ArrayBuilder(Of TypeParameterDiagnosticInfo).GetInstance() Dim useSiteDiagnosticsBuilder As ArrayBuilder(Of TypeParameterDiagnosticInfo) = Nothing - type.CheckAllConstraints(diagnosticsBuilder, useSiteDiagnosticsBuilder, template) + type.CheckAllConstraints(languageVersion, diagnosticsBuilder, useSiteDiagnosticsBuilder, template) If useSiteDiagnosticsBuilder IsNot Nothing Then diagnosticsBuilder.AddRange(useSiteDiagnosticsBuilder) @@ -409,6 +410,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols Public Sub CheckAllConstraints( type As TypeSymbol, + languageVersion As LanguageVersion, diagnosticsBuilder As ArrayBuilder(Of TypeParameterDiagnosticInfo), <[In], Out> ByRef useSiteDiagnosticsBuilder As ArrayBuilder(Of TypeParameterDiagnosticInfo), template As CompoundUseSiteInfo(Of AssemblySymbol)) @@ -416,6 +418,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols diagnostics.diagnosticsBuilder = diagnosticsBuilder diagnostics.useSiteDiagnosticsBuilder = useSiteDiagnosticsBuilder diagnostics.template = template + diagnostics.languageVersion = languageVersion type.VisitType(s_checkConstraintsSingleTypeFunc, diagnostics) @@ -426,13 +429,15 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols Public diagnosticsBuilder As ArrayBuilder(Of TypeParameterDiagnosticInfo) Public useSiteDiagnosticsBuilder As ArrayBuilder(Of TypeParameterDiagnosticInfo) Public template As CompoundUseSiteInfo(Of AssemblySymbol) + Public languageVersion As LanguageVersion End Class Private ReadOnly s_checkConstraintsSingleTypeFunc As Func(Of TypeSymbol, CheckConstraintsDiagnosticsBuilders, Boolean) = AddressOf CheckConstraintsSingleType Private Function CheckConstraintsSingleType(type As TypeSymbol, diagnostics As CheckConstraintsDiagnosticsBuilders) As Boolean If type.Kind = SymbolKind.NamedType Then - DirectCast(type, NamedTypeSymbol).CheckConstraints(diagnostics.diagnosticsBuilder, diagnostics.useSiteDiagnosticsBuilder, diagnostics.template) + DirectCast(type, NamedTypeSymbol).CheckConstraints( + diagnostics.languageVersion, diagnostics.diagnosticsBuilder, diagnostics.useSiteDiagnosticsBuilder, diagnostics.template) End If Return False ' continue walking types End Function @@ -460,7 +465,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols Dim offset As Integer = 0 For Each underlyingTuple In underlyingTupleTypeChain Dim useSiteDiagnosticsBuilder As ArrayBuilder(Of TypeParameterDiagnosticInfo) = Nothing - CheckTypeConstraints(underlyingTuple, diagnosticsBuilder, useSiteDiagnosticsBuilder, template) + CheckTypeConstraints(underlyingTuple, + DirectCast(syntaxNode.SyntaxTree.Options, VisualBasicParseOptions).LanguageVersion, + diagnosticsBuilder, useSiteDiagnosticsBuilder, template) If useSiteDiagnosticsBuilder IsNot Nothing Then diagnosticsBuilder.AddRange(useSiteDiagnosticsBuilder) @@ -487,6 +494,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols Public Function CheckConstraintsForNonTuple( type As NamedTypeSymbol, + languageVersion As LanguageVersion, typeArgumentsSyntax As SeparatedSyntaxList(Of TypeSyntax), diagnostics As BindingDiagnosticBag, template As CompoundUseSiteInfo(Of AssemblySymbol)) As Boolean @@ -498,7 +506,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols Dim diagnosticsBuilder = ArrayBuilder(Of TypeParameterDiagnosticInfo).GetInstance() Dim useSiteDiagnosticsBuilder As ArrayBuilder(Of TypeParameterDiagnosticInfo) = Nothing - Dim result = CheckTypeConstraints(type, diagnosticsBuilder, useSiteDiagnosticsBuilder, template) + Dim result = CheckTypeConstraints(type, languageVersion, diagnosticsBuilder, useSiteDiagnosticsBuilder, template) If useSiteDiagnosticsBuilder IsNot Nothing Then diagnosticsBuilder.AddRange(useSiteDiagnosticsBuilder) @@ -517,6 +525,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols Public Function CheckConstraints( type As NamedTypeSymbol, + languageVersion As LanguageVersion, diagnosticsBuilder As ArrayBuilder(Of TypeParameterDiagnosticInfo), <[In], Out> ByRef useSiteDiagnosticsBuilder As ArrayBuilder(Of TypeParameterDiagnosticInfo), template As CompoundUseSiteInfo(Of AssemblySymbol)) As Boolean @@ -529,12 +538,13 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols If Not RequiresChecking(type) Then Return True End If - Return CheckTypeConstraints(type, diagnosticsBuilder, useSiteDiagnosticsBuilder, template) + Return CheckTypeConstraints(type, languageVersion, diagnosticsBuilder, useSiteDiagnosticsBuilder, template) End Function Public Function CheckConstraints( method As MethodSymbol, + languageVersion As LanguageVersion, diagnosticLocation As Location, diagnostics As BindingDiagnosticBag, template As CompoundUseSiteInfo(Of AssemblySymbol)) As Boolean @@ -544,7 +554,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols Dim diagnosticsBuilder = ArrayBuilder(Of TypeParameterDiagnosticInfo).GetInstance() Dim useSiteDiagnosticsBuilder As ArrayBuilder(Of TypeParameterDiagnosticInfo) = Nothing - Dim result = CheckMethodConstraints(method, diagnosticsBuilder, useSiteDiagnosticsBuilder, template) + Dim result = CheckMethodConstraints(method, languageVersion, diagnosticsBuilder, useSiteDiagnosticsBuilder, template) If useSiteDiagnosticsBuilder IsNot Nothing Then diagnosticsBuilder.AddRange(useSiteDiagnosticsBuilder) @@ -561,31 +571,34 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols Public Function CheckConstraints( method As MethodSymbol, + languageVersion As LanguageVersion, diagnosticsBuilder As ArrayBuilder(Of TypeParameterDiagnosticInfo), <[In], Out> ByRef useSiteDiagnosticsBuilder As ArrayBuilder(Of TypeParameterDiagnosticInfo), template As CompoundUseSiteInfo(Of AssemblySymbol)) As Boolean If Not RequiresChecking(method) Then Return True End If - Return CheckMethodConstraints(method, diagnosticsBuilder, useSiteDiagnosticsBuilder, template) + Return CheckMethodConstraints(method, languageVersion, diagnosticsBuilder, useSiteDiagnosticsBuilder, template) End Function Private Function CheckTypeConstraints( type As NamedTypeSymbol, + languageVersion As LanguageVersion, diagnosticsBuilder As ArrayBuilder(Of TypeParameterDiagnosticInfo), <[In], Out> ByRef useSiteDiagnosticsBuilder As ArrayBuilder(Of TypeParameterDiagnosticInfo), template As CompoundUseSiteInfo(Of AssemblySymbol)) As Boolean Dim substitution = type.TypeSubstitution - Return CheckConstraints(type, substitution, type.OriginalDefinition.TypeParameters, type.TypeArgumentsNoUseSiteDiagnostics, diagnosticsBuilder, useSiteDiagnosticsBuilder, template) + Return CheckConstraints(type, languageVersion, substitution, type.OriginalDefinition.TypeParameters, type.TypeArgumentsNoUseSiteDiagnostics, diagnosticsBuilder, useSiteDiagnosticsBuilder, template) End Function Private Function CheckMethodConstraints( method As MethodSymbol, + languageVersion As LanguageVersion, diagnosticsBuilder As ArrayBuilder(Of TypeParameterDiagnosticInfo), <[In], Out> ByRef useSiteDiagnosticsBuilder As ArrayBuilder(Of TypeParameterDiagnosticInfo), template As CompoundUseSiteInfo(Of AssemblySymbol)) As Boolean Dim substitution = DirectCast(method, SubstitutedMethodSymbol).TypeSubstitution - Return CheckConstraints(method, substitution, method.OriginalDefinition.TypeParameters, method.TypeArguments, diagnosticsBuilder, useSiteDiagnosticsBuilder, template) + Return CheckConstraints(method, languageVersion, substitution, method.OriginalDefinition.TypeParameters, method.TypeArguments, diagnosticsBuilder, useSiteDiagnosticsBuilder, template) End Function ''' @@ -599,6 +612,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols Public Function CheckConstraints( constructedSymbol As Symbol, + languageVersion As LanguageVersion, substitution As TypeSubstitution, typeParameters As ImmutableArray(Of TypeParameterSymbol), typeArguments As ImmutableArray(Of TypeSymbol), @@ -614,7 +628,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols Dim typeArgument = typeArguments(i) Dim typeParameter = typeParameters(i) Dim useSiteInfo As New CompoundUseSiteInfo(Of AssemblySymbol)(template) - If Not CheckConstraints(constructedSymbol, substitution, typeParameter, typeArgument, diagnosticsBuilder, useSiteInfo) Then + If Not CheckConstraints(constructedSymbol, languageVersion, substitution, typeParameter, typeArgument, diagnosticsBuilder, useSiteInfo) Then succeeded = False End If @@ -628,6 +642,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols Public Function CheckConstraints( constructedSymbol As Symbol, + languageVersion As LanguageVersion, substitution As TypeSubstitution, typeParameter As TypeParameterSymbol, typeArgument As TypeSymbol, @@ -659,6 +674,24 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols succeeded = False End If + If typeParameter.HasUnmanagedTypeConstraint Then + + If Not InternalSyntax.Parser.CheckFeatureAvailability(languageVersion, InternalSyntax.Feature.UnmanagedConstraint) Then + useSiteInfo.AddDiagnosticInfo(InternalSyntax.Parser.GetFeatureAvailabilityError(InternalSyntax.Feature.UnmanagedConstraint, languageVersion)) + succeeded = False + End If + + Dim managedKind = typeArgument.GetManagedKind(useSiteInfo) + + If managedKind = ManagedKind.Managed Then + If diagnosticsBuilder IsNot Nothing Then + diagnosticsBuilder.Add(New TypeParameterDiagnosticInfo(typeParameter, ErrorFactory.ErrorInfo(ERRID.ERR_UnmanagedConstraintNotSatisfied, typeArgument, typeParameter))) + End If + + succeeded = False + End If + End If + If typeParameter.HasValueTypeConstraint AndAlso Not SatisfiesValueTypeConstraint(constructedSymbol, typeParameter, typeArgument, diagnosticsBuilder, useSiteInfo) Then succeeded = False End If diff --git a/src/Compilers/VisualBasic/Portable/Symbols/IndexedTypeParameterSymbol.vb b/src/Compilers/VisualBasic/Portable/Symbols/IndexedTypeParameterSymbol.vb index dca460d7f317d..d327dc3b1a378 100644 --- a/src/Compilers/VisualBasic/Portable/Symbols/IndexedTypeParameterSymbol.vb +++ b/src/Compilers/VisualBasic/Portable/Symbols/IndexedTypeParameterSymbol.vb @@ -140,6 +140,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols End Get End Property + Friend Overrides ReadOnly Property HasUnmanagedTypeConstraint As Boolean + Get + Return False + End Get + End Property + Public Overrides ReadOnly Property ContainingSymbol As Symbol Get Return Nothing diff --git a/src/Compilers/VisualBasic/Portable/Symbols/InstanceErrorTypeSymbol.vb b/src/Compilers/VisualBasic/Portable/Symbols/InstanceErrorTypeSymbol.vb index dd6486d1d2839..37297227743c9 100644 --- a/src/Compilers/VisualBasic/Portable/Symbols/InstanceErrorTypeSymbol.vb +++ b/src/Compilers/VisualBasic/Portable/Symbols/InstanceErrorTypeSymbol.vb @@ -205,6 +205,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols End Get End Property + Friend Overrides ReadOnly Property HasUnmanagedTypeConstraint As Boolean + Get + Return False + End Get + End Property + Friend Overrides Function GetConstraints() As ImmutableArray(Of TypeParameterConstraint) Return ImmutableArray(Of TypeParameterConstraint).Empty End Function diff --git a/src/Compilers/VisualBasic/Portable/Symbols/Metadata/PE/PETypeParameterSymbol.vb b/src/Compilers/VisualBasic/Portable/Symbols/Metadata/PE/PETypeParameterSymbol.vb index 6b033ecd2b07c..65bb824fcae7c 100644 --- a/src/Compilers/VisualBasic/Portable/Symbols/Metadata/PE/PETypeParameterSymbol.vb +++ b/src/Compilers/VisualBasic/Portable/Symbols/Metadata/PE/PETypeParameterSymbol.vb @@ -12,6 +12,7 @@ Imports Microsoft.CodeAnalysis.VisualBasic.Symbols Imports Microsoft.CodeAnalysis.VisualBasic.Syntax Imports System.Reflection Imports System.Reflection.Metadata.Ecma335 +Imports System.Runtime.InteropServices Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols.Metadata.PE @@ -34,6 +35,11 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols.Metadata.PE Private _lazyConstraintTypes As ImmutableArray(Of TypeSymbol) + ''' + ''' Actually stores + ''' + Private _lazyHasIsUnmanagedConstraint As Byte + ''' ''' First error calculating bounds. ''' @@ -149,9 +155,18 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols.Metadata.PE End Get End Property - Private Function GetDeclaredConstraints() As ImmutableArray(Of TypeParameterConstraint) + Friend Overrides ReadOnly Property HasUnmanagedTypeConstraint As Boolean + Get + EnsureAllConstraintsAreResolved() + Return CType(Volatile.Read(_lazyHasIsUnmanagedConstraint), ThreeState).Value() + End Get + End Property + + Private Function GetDeclaredConstraints( ByRef hasUnmanagedModreqPattern As Boolean) As ImmutableArray(Of TypeParameterConstraint) Dim constraintsBuilder = ArrayBuilder(Of TypeParameterConstraint).GetInstance() + hasUnmanagedModreqPattern = False + If HasConstructorConstraint Then constraintsBuilder.Add(New TypeParameterConstraint(TypeParameterConstraintKind.Constructor, Nothing)) End If @@ -194,9 +209,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols.Metadata.PE End If For Each constraintHandle In constraints - Dim constraint = metadataReader.GetGenericParameterConstraint(constraintHandle) - Dim constraintTypeHandle = constraint.Type - Dim typeSymbol As TypeSymbol = tokenDecoder.GetTypeOfToken(constraintTypeHandle) + Dim typeSymbol As TypeSymbol = GetConstraintType(metadataReader, tokenDecoder, constraintHandle, hasUnmanagedModreqPattern) ' Drop 'System.ValueType' constraint type if the 'valuetype' constraint was also specified. If ((_flags And GenericParameterAttributes.NotNullableValueTypeConstraint) <> 0) AndAlso @@ -212,9 +225,50 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols.Metadata.PE Next End If + ' - presence of unmanaged pattern has to be matched with `valuetype` + ' - IsUnmanagedAttribute is allowed iff there is an unmanaged pattern + If (hasUnmanagedModreqPattern AndAlso (_flags And GenericParameterAttributes.NotNullableValueTypeConstraint) = 0) OrElse + hasUnmanagedModreqPattern <> moduleSymbol.Module.HasIsUnmanagedAttribute(_handle) Then + ' we do not recognize these combinations as "unmanaged" + hasUnmanagedModreqPattern = False + _lazyCachedBoundsUseSiteInfo.InterlockedInitializeFromSentinel(primaryDependency:=Nothing, New UseSiteInfo(Of AssemblySymbol)(ErrorFactory.ErrorInfo(ERRID.ERR_UnsupportedType1, Me))) + End If + Return constraintsBuilder.ToImmutableAndFree() End Function + Private Shared Function GetConstraintType( + metadataReader As MetadataReader, + tokenDecoder As MetadataDecoder, + constraintHandle As GenericParameterConstraintHandle, + ByRef hasUnmanagedModreqPattern As Boolean + ) As TypeSymbol + + Dim constraint = metadataReader.GetGenericParameterConstraint(constraintHandle) + Dim modifiers As ImmutableArray(Of ModifierInfo(Of TypeSymbol)) = Nothing + Dim typeSymbol = tokenDecoder.DecodeGenericParameterConstraint(constraint.Type, modifiers) + + If Not modifiers.IsDefaultOrEmpty AndAlso modifiers.Length > 1 Then + typeSymbol = New UnsupportedMetadataTypeSymbol() + ElseIf typeSymbol.SpecialType = SpecialType.System_ValueType Then + ' recognize "(class [mscorlib]System.ValueType modreq([mscorlib]System.Runtime.InteropServices.UnmanagedType" pattern as "unmanaged" + If Not modifiers.IsDefaultOrEmpty Then + Dim m As ModifierInfo(Of TypeSymbol) = modifiers.Single() + If Not m.IsOptional AndAlso m.Modifier.IsWellKnownTypeUnmanagedType() Then + hasUnmanagedModreqPattern = True + Else + ' Any other modifiers, optional or not, are not allowed + typeSymbol = New UnsupportedMetadataTypeSymbol() + End If + End If + ElseIf Not modifiers.IsDefaultOrEmpty Then + ' Any other modifiers, optional or not, are not allowed + typeSymbol = New UnsupportedMetadataTypeSymbol() + End If + + Return typeSymbol + End Function + Public Overrides ReadOnly Property Locations As ImmutableArray(Of Location) Get Return _containingSymbol.Locations @@ -273,6 +327,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols.Metadata.PE If _lazyConstraintTypes.IsDefault Then Dim diagnosticsBuilder = ArrayBuilder(Of TypeParameterDiagnosticInfo).GetInstance() Dim inherited = (_containingSymbol.Kind = SymbolKind.Method) AndAlso DirectCast(_containingSymbol, MethodSymbol).IsOverrides + Dim hasUnmanagedModreqPattern As Boolean = False ' Check direct constraints on the type parameter to generate any use-site errors ' (for example, the cycle in ".class public A<(!T)T>"). It's necessary to check for such @@ -284,7 +339,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols.Metadata.PE ' which cannot be satisfied if A and B are from different hierarchies.) It also isn't ' necessary to report redundant constraints since redundant constraints are still ' valid. Redundant constraints are dropped silently. - Dim constraints = Me.RemoveDirectConstraintConflicts(GetDeclaredConstraints(), inProgress.Prepend(Me), DirectConstraintConflictKind.None, diagnosticsBuilder) + Dim constraints = Me.RemoveDirectConstraintConflicts(GetDeclaredConstraints(hasUnmanagedModreqPattern), inProgress.Prepend(Me), DirectConstraintConflictKind.None, diagnosticsBuilder) Dim primaryDependency As AssemblySymbol = Me.PrimaryDependency Dim useSiteInfo As New UseSiteInfo(Of AssemblySymbol)(primaryDependency) @@ -299,6 +354,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols.Metadata.PE diagnosticsBuilder.Free() _lazyCachedBoundsUseSiteInfo.InterlockedInitializeFromSentinel(primaryDependency, useSiteInfo) + _lazyHasIsUnmanagedConstraint = hasUnmanagedModreqPattern.ToThreeState() ImmutableInterlocked.InterlockedInitialize(_lazyConstraintTypes, GetConstraintTypesOnly(constraints)) End If diff --git a/src/Compilers/VisualBasic/Portable/Symbols/MethodSignatureComparer.vb b/src/Compilers/VisualBasic/Portable/Symbols/MethodSignatureComparer.vb index 39e5fbc32563e..c395012933648 100644 --- a/src/Compilers/VisualBasic/Portable/Symbols/MethodSignatureComparer.vb +++ b/src/Compilers/VisualBasic/Portable/Symbols/MethodSignatureComparer.vb @@ -864,6 +864,7 @@ Done: (typeParameter1.HasReferenceTypeConstraint <> typeParameter2.HasReferenceTypeConstraint) OrElse (typeParameter1.HasValueTypeConstraint <> typeParameter2.HasValueTypeConstraint) OrElse (typeParameter1.AllowsRefLikeType <> typeParameter2.AllowsRefLikeType) OrElse + (typeParameter1.HasUnmanagedTypeConstraint <> typeParameter2.HasUnmanagedTypeConstraint) OrElse (typeParameter1.Variance <> typeParameter2.Variance) Then Return False End If diff --git a/src/Compilers/VisualBasic/Portable/Symbols/MethodSymbol.vb b/src/Compilers/VisualBasic/Portable/Symbols/MethodSymbol.vb index 5e3893146718c..3101385966ebc 100644 --- a/src/Compilers/VisualBasic/Portable/Symbols/MethodSymbol.vb +++ b/src/Compilers/VisualBasic/Portable/Symbols/MethodSymbol.vb @@ -784,16 +784,16 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols ''' Name lookup should use this method in order to capture proximity, which affects ''' overload resolution. ''' - Friend Function ReduceExtensionMethod(instanceType As TypeSymbol, proximity As Integer, ByRef useSiteInfo As CompoundUseSiteInfo(Of AssemblySymbol)) As MethodSymbol - Return ReducedExtensionMethodSymbol.Create(instanceType, Me, proximity, useSiteInfo) + Friend Function ReduceExtensionMethod(instanceType As TypeSymbol, proximity As Integer, ByRef useSiteInfo As CompoundUseSiteInfo(Of AssemblySymbol), languageVersion As LanguageVersion) As MethodSymbol + Return ReducedExtensionMethodSymbol.Create(instanceType, Me, proximity, useSiteInfo, languageVersion) End Function ''' ''' If this is an extension method that can be applied to a instance of the given type, ''' returns the reduced method symbol thus formed. Otherwise, returns Nothing. ''' - Public Function ReduceExtensionMethod(instanceType As TypeSymbol, ByRef useSiteInfo As CompoundUseSiteInfo(Of AssemblySymbol)) As MethodSymbol - Return ReduceExtensionMethod(instanceType, proximity:=0, useSiteInfo) + Public Function ReduceExtensionMethod(instanceType As TypeSymbol, ByRef useSiteInfo As CompoundUseSiteInfo(Of AssemblySymbol), languageVersion As LanguageVersion) As MethodSymbol + Return ReduceExtensionMethod(instanceType, proximity:=0, useSiteInfo, languageVersion) End Function ''' @@ -965,7 +965,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols Throw New ArgumentNullException(NameOf(receiverType)) End If - Return Me.ReduceExtensionMethod(receiverType.EnsureVbSymbolOrNothing(Of TypeSymbol)(NameOf(receiverType)), CompoundUseSiteInfo(Of AssemblySymbol).Discarded) + Return Me.ReduceExtensionMethod(receiverType.EnsureVbSymbolOrNothing(Of TypeSymbol)(NameOf(receiverType)), CompoundUseSiteInfo(Of AssemblySymbol).Discarded, LanguageVersion.Latest) End Function Private ReadOnly Property IMethodSymbol_Parameters As ImmutableArray(Of IParameterSymbol) Implements IMethodSymbol.Parameters diff --git a/src/Compilers/VisualBasic/Portable/Symbols/NamedTypeSymbol.vb b/src/Compilers/VisualBasic/Portable/Symbols/NamedTypeSymbol.vb index 03f4062b917df..95a55ad1a04bf 100644 --- a/src/Compilers/VisualBasic/Portable/Symbols/NamedTypeSymbol.vb +++ b/src/Compilers/VisualBasic/Portable/Symbols/NamedTypeSymbol.vb @@ -936,7 +936,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols ''' ''' True if and only if this type or some containing type has type parameters. ''' - Public ReadOnly Property IsGenericType As Boolean Implements INamedTypeSymbol.IsGenericType + Public ReadOnly Property IsGenericType As Boolean Implements INamedTypeSymbol.IsGenericType, INamedTypeSymbolInternal.IsGenericType Get Dim p As NamedTypeSymbol = Me Do While p IsNot Nothing @@ -1195,6 +1195,121 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols Return True End Function + Friend Overrides Function GetManagedKind(ByRef useSiteInfo As CompoundUseSiteInfo(Of AssemblySymbol)) As ManagedKind + Return GetManagedKind(Me, useSiteInfo) + End Function + + ' + ' IsManagedType is simple for most named types: + ' enums are not managed; + ' non-enum, non-struct named types are managed; + ' type parameters are managed unless an 'unmanaged' constraint is present; + ' all special types have spec'd values (basically, (non-string) primitives) are not managed; + ' + ' Only structs are complicated, because the definition is recursive. A struct type is managed + ' if one of its instance fields is managed or a ref field. Unfortunately, this can result in infinite recursion. + ' If the closure is finite, and we don't find anything definitely managed, then we return true. + ' If the closure is infinite, we disregard all but a representative of any expanding cycle. + ' + ' Intuitively, this will only return true if there's a specific type we can point to that is would + ' be managed even if it had no fields. e.g. struct S { S s; } is not managed, but struct S { S s; object o; } + ' is because we can point to object. + ' + Private Overloads Shared Function GetManagedKind(type As NamedTypeSymbol, ByRef useSiteInfo As CompoundUseSiteInfo(Of AssemblySymbol)) As ManagedKind + type = DirectCast(type.GetTupleUnderlyingTypeOrSelf(), NamedTypeSymbol) + + ' The code below is a clone of BaseTypeAnalysis.GetManagedKind from C# it should be kept in sync going forward + Dim managedInfo = INamedTypeSymbolInternal.Helpers.IsManagedTypeHelper(type) + Dim definitelyManaged = (managedInfo.isManaged = ThreeState.True) + + If managedInfo.isManaged = ThreeState.Unknown Then + ' Otherwise, we have to build and inspect the closure of depended-upon types. + Dim hs = PooledHashSet(Of Symbol).GetInstance() + Dim result = DependsOnDefinitelyManagedType(type, hs, useSiteInfo) + definitelyManaged = result.definitelyManaged + managedInfo.hasGenerics = managedInfo.hasGenerics OrElse result.hasGenerics + hs.Free() + End If + + If definitelyManaged Then + Return ManagedKind.Managed + ElseIf managedInfo.hasGenerics Then + Return ManagedKind.UnmanagedWithGenerics + Else + Return ManagedKind.Unmanaged + End If + End Function + + Private Shared Function DependsOnDefinitelyManagedType( + type As NamedTypeSymbol, + partialClosure As HashSet(Of Symbol), + ByRef useSiteInfo As CompoundUseSiteInfo(Of AssemblySymbol) + ) As (definitelyManaged As Boolean, hasGenerics As Boolean) + + Debug.Assert(type IsNot Nothing) + + Dim hasGenerics = False + + If partialClosure.Add(type) Then + + For Each member In type.GetMembersUnordered() + + Dim field = TryCast(member, FieldSymbol) + + ' Only instance fields (including field-like events) affect the outcome. + If field Is Nothing OrElse field.IsShared Then + Continue For + End If + + useSiteInfo.Add(field.GetUseSiteInfo()) + Dim fieldType As TypeSymbol = field.Type.GetTupleUnderlyingTypeOrSelf() + + ' A ref struct which has a ref field is never considered unmanaged + ' but we cannot represent ref fields in VB + ' The previous line should collect an error about the fact + + Select Case fieldType.TypeKind + Case TypeKind.Pointer, TypeKind.FunctionPointer + ' pointers are unmanaged + ExceptionUtilities.UnexpectedValue(fieldType.TypeKind) + Continue For + End Select + + Dim fieldNamedType = TryCast(fieldType, NamedTypeSymbol) + If fieldNamedType Is Nothing Then + If fieldType.GetManagedKind(useSiteInfo) = ManagedKind.Managed Then + Return (True, hasGenerics) + End If + Else + Dim result = INamedTypeSymbolInternal.Helpers.IsManagedTypeHelper(fieldNamedType) + hasGenerics = hasGenerics OrElse result.hasGenerics + ' NOTE: don't use GetManagedKind on a NamedTypeSymbol - that could lead + ' to infinite recursion. + Select Case result.isManaged + Case ThreeState.True + Return (True, hasGenerics) + + Case ThreeState.False + Continue For + + Case ThreeState.Unknown + If Not fieldNamedType.OriginalDefinition.KnownCircularStruct Then + Dim dependsInfo = DependsOnDefinitelyManagedType(fieldNamedType, partialClosure, useSiteInfo) + hasGenerics = hasGenerics OrElse dependsInfo.hasGenerics + If dependsInfo.definitelyManaged Then + Return (True, hasGenerics) + End If + End If + + Continue For + End Select + End If + Next + End If + + Return (False, hasGenerics) + End Function + #Region "INamedTypeSymbol" Private ReadOnly Property INamedTypeSymbol_Arity As Integer Implements INamedTypeSymbol.Arity diff --git a/src/Compilers/VisualBasic/Portable/Symbols/ReducedExtensionMethodSymbol.vb b/src/Compilers/VisualBasic/Portable/Symbols/ReducedExtensionMethodSymbol.vb index 7cad34b2202d4..bc1475beaed91 100644 --- a/src/Compilers/VisualBasic/Portable/Symbols/ReducedExtensionMethodSymbol.vb +++ b/src/Compilers/VisualBasic/Portable/Symbols/ReducedExtensionMethodSymbol.vb @@ -32,7 +32,14 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols ''' If this is an extension method that can be applied to an instance of the given type, ''' returns the curried method symbol thus formed. Otherwise, returns Nothing. ''' - Public Shared Function Create(instanceType As TypeSymbol, possiblyExtensionMethod As MethodSymbol, proximity As Integer, ByRef useSiteInfo As CompoundUseSiteInfo(Of AssemblySymbol)) As MethodSymbol + Public Shared Function Create( + instanceType As TypeSymbol, + possiblyExtensionMethod As MethodSymbol, + proximity As Integer, + ByRef useSiteInfo As CompoundUseSiteInfo(Of AssemblySymbol), + languageVersion As LanguageVersion + ) As MethodSymbol + Debug.Assert(instanceType IsNot Nothing) Debug.Assert(possiblyExtensionMethod IsNot Nothing) Debug.Assert(proximity >= 0) @@ -140,7 +147,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols ' Check constraints. Dim diagnosticsBuilder = ArrayBuilder(Of TypeParameterDiagnosticInfo).GetInstance() Dim useSiteDiagnosticsBuilder As ArrayBuilder(Of TypeParameterDiagnosticInfo) = Nothing - success = possiblyExtensionMethod.CheckConstraints(partialSubstitution, + success = possiblyExtensionMethod.CheckConstraints(languageVersion, + partialSubstitution, typeParametersToFixArray, fixWithArray, diagnosticsBuilder, @@ -721,6 +729,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols End Get End Property + Friend Overrides ReadOnly Property HasUnmanagedTypeConstraint As Boolean + Get + Return _curriedFromTypeParameter.HasUnmanagedTypeConstraint + End Get + End Property + Public Overrides ReadOnly Property ContainingSymbol As Symbol Get Return _curriedMethod diff --git a/src/Compilers/VisualBasic/Portable/Symbols/Retargeting/RetargetingTypeParameterSymbol.vb b/src/Compilers/VisualBasic/Portable/Symbols/Retargeting/RetargetingTypeParameterSymbol.vb index b814ac65952a1..4084c4e823693 100644 --- a/src/Compilers/VisualBasic/Portable/Symbols/Retargeting/RetargetingTypeParameterSymbol.vb +++ b/src/Compilers/VisualBasic/Portable/Symbols/Retargeting/RetargetingTypeParameterSymbol.vb @@ -80,6 +80,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols.Retargeting End Get End Property + Friend Overrides ReadOnly Property HasUnmanagedTypeConstraint As Boolean + Get + Return _underlyingTypeParameter.HasUnmanagedTypeConstraint + End Get + End Property + Public Overrides ReadOnly Property HasConstructorConstraint As Boolean Get Return _underlyingTypeParameter.HasConstructorConstraint diff --git a/src/Compilers/VisualBasic/Portable/Symbols/Source/CrefTypeParameterSymbol.vb b/src/Compilers/VisualBasic/Portable/Symbols/Source/CrefTypeParameterSymbol.vb index dd14245f73a15..ba0c92ccaf095 100644 --- a/src/Compilers/VisualBasic/Portable/Symbols/Source/CrefTypeParameterSymbol.vb +++ b/src/Compilers/VisualBasic/Portable/Symbols/Source/CrefTypeParameterSymbol.vb @@ -79,6 +79,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols End Get End Property + Friend Overrides ReadOnly Property HasUnmanagedTypeConstraint As Boolean + Get + Return False + End Get + End Property + Friend Overrides Function GetConstraints() As ImmutableArray(Of TypeParameterConstraint) Return ImmutableArray(Of TypeParameterConstraint).Empty End Function diff --git a/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceEventSymbol.vb b/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceEventSymbol.vb index 5513ecf608895..8cf47f22d2330 100644 --- a/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceEventSymbol.vb +++ b/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceEventSymbol.vb @@ -40,6 +40,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols IsDelegateFromImplements = &H2 ' Bit value valid once m_lazyType is assigned. ReportedExplicitImplementationDiagnostics = &H4 SymbolDeclaredEvent = &H8 ' Bit value for generating SymbolDeclaredEvent + TypeConstraintsChecked = &H10 End Enum Private _lazyType As TypeSymbol @@ -150,7 +151,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols End Sub Private Function ComputeType(diagnostics As BindingDiagnosticBag, ByRef isTypeInferred As Boolean, ByRef isDelegateFromImplements As Boolean) As TypeSymbol - Dim binder = CreateBinderForTypeDeclaration() + Dim binder = BinderBuilder.CreateBinderForType(ContainingSourceModule, _syntaxRef.SyntaxTree, _containingType) + binder = New LocationSpecificBinder(BindingLocation.EventType, Me, binder) Dim syntax = DirectCast(_syntaxRef.GetSyntax(), EventStatementSyntax) isTypeInferred = False @@ -744,10 +746,19 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols Friend Overrides Sub GenerateDeclarationErrors(cancellationToken As CancellationToken) MyBase.GenerateDeclarationErrors(cancellationToken) - Dim unusedType = Me.Type + Dim type = Me.Type Dim unusedImplementations = Me.ExplicitInterfaceImplementations Me.CheckExplicitImplementationTypes() + If (_lazyState And StateFlags.TypeConstraintsChecked) = 0 Then + Dim sourceModule = DirectCast(Me.ContainingModule, SourceModuleSymbol) + Dim diagnostics = BindingDiagnosticBag.GetInstance() + type.CheckAllConstraints(DeclaringCompilation.LanguageVersion, + Locations(0), diagnostics, template:=New CompoundUseSiteInfo(Of AssemblySymbol)(diagnostics, sourceModule.ContainingAssembly)) + sourceModule.AtomicSetFlagAndStoreDiagnostics(_lazyState, StateFlags.TypeConstraintsChecked, 0, diagnostics) + diagnostics.Free() + End If + If DeclaringCompilation.EventQueue IsNot Nothing Then Me.ContainingSourceModule.AtomicSetFlagAndRaiseSymbolDeclaredEvent(_lazyState, StateFlags.SymbolDeclaredEvent, 0, Me) End If diff --git a/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceFieldSymbol.vb b/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceFieldSymbol.vb index 2556c6218da54..9e7528edde223 100644 --- a/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceFieldSymbol.vb +++ b/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceFieldSymbol.vb @@ -32,8 +32,17 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols Private _lazyExpandedDocComment As String Private _lazyCustomAttributesBag As CustomAttributesBag(Of VisualBasicAttributeData) - ' Set to 1 when the compilation event has been produced - Private _eventProduced As Integer + ''' + ''' See + ''' + Protected _lazyState As Integer + + + Protected Enum StateFlags As Integer + TypeConstraintsChecked = &H1 + + EventProduced = &H2 + End Enum Protected Sub New(container As SourceMemberContainerTypeSymbol, syntaxRef As SyntaxReference, @@ -51,15 +60,19 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols m_memberFlags = memberFlags End Sub - Friend Overrides Sub GenerateDeclarationErrors(cancellationToken As CancellationToken) + Protected Overridable Sub GenerateDeclarationErrorsImpl(cancellationToken As CancellationToken) MyBase.GenerateDeclarationErrors(cancellationToken) Dim unusedType = Me.Type GetConstantValue(ConstantFieldsInProgress.Empty) + End Sub + + Friend NotOverridable Overrides Sub GenerateDeclarationErrors(cancellationToken As CancellationToken) + GenerateDeclarationErrorsImpl(cancellationToken) ' We want declaration events to be last, after all compilation analysis is done, so we produce them here Dim sourceModule = DirectCast(Me.ContainingModule, SourceModuleSymbol) - If Interlocked.CompareExchange(_eventProduced, 1, 0) = 0 AndAlso Not Me.IsImplicitlyDeclared Then + If ThreadSafeFlagOperations.Set(_lazyState, StateFlags.EventProduced) AndAlso Not Me.IsImplicitlyDeclared Then sourceModule.DeclaringCompilation.SymbolDeclaredEvent(Me) End If End Sub diff --git a/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceFile.vb b/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceFile.vb index 98553d475e29f..d811f22c45274 100644 --- a/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceFile.vb +++ b/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceFile.vb @@ -360,7 +360,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols Dim type = TryCast(namespaceOrType, TypeSymbol) If type IsNot Nothing Then clauseDiagnostics.Clear() - type.CheckAllConstraints(location, clauseDiagnostics, template:=New CompoundUseSiteInfo(Of AssemblySymbol)(diagnostics, compilation.Assembly)) + type.CheckAllConstraints( + compilation.LanguageVersion, + location, clauseDiagnostics, template:=New CompoundUseSiteInfo(Of AssemblySymbol)(diagnostics, compilation.Assembly)) diagnostics.AddRange(clauseDiagnostics.DiagnosticBag) If VisualBasicCompilation.ReportUnusedImportsInTree(location.PossiblyEmbeddedOrMySourceTree) Then diff --git a/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceMemberFieldSymbol.vb b/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceMemberFieldSymbol.vb index 3a0251f8311d5..1e034909add1b 100644 --- a/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceMemberFieldSymbol.vb +++ b/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceMemberFieldSymbol.vb @@ -29,6 +29,19 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols MyBase.New(container, syntaxRef, name, memberFlags) End Sub + Protected Overrides Sub GenerateDeclarationErrorsImpl(cancellationToken As CancellationToken) + MyBase.GenerateDeclarationErrorsImpl(cancellationToken) + + If (_lazyState And StateFlags.TypeConstraintsChecked) = 0 Then + Dim sourceModule = DirectCast(Me.ContainingModule, SourceModuleSymbol) + Dim diagnostics = BindingDiagnosticBag.GetInstance() + Type.CheckAllConstraints(DeclaringCompilation.LanguageVersion, + Locations(0), diagnostics, template:=New CompoundUseSiteInfo(Of AssemblySymbol)(diagnostics, sourceModule.ContainingAssembly)) + sourceModule.AtomicSetFlagAndStoreDiagnostics(_lazyState, StateFlags.TypeConstraintsChecked, 0, diagnostics) + diagnostics.Free() + End If + End Sub + Friend NotOverridable Overrides ReadOnly Property DeclarationSyntax As VisualBasicSyntaxNode Get Return Syntax.Parent.Parent diff --git a/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceMethodSymbol.vb b/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceMethodSymbol.vb index 9d17716bffd83..bcf324bcc0325 100644 --- a/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceMethodSymbol.vb +++ b/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceMethodSymbol.vb @@ -2156,7 +2156,9 @@ lReportErrorOnTwoTokens: If param.Locations.Length > 0 Then ' Note: Errors are reported on the parameter name. Ideally, we should ' match Dev10 and report errors on the parameter type syntax instead. - param.Type.CheckAllConstraints(param.Locations(0), diagBag, template:=New CompoundUseSiteInfo(Of AssemblySymbol)(diagBag, sourceModule.ContainingAssembly)) + param.Type.CheckAllConstraints( + DeclaringCompilation.LanguageVersion, + param.Locations(0), diagBag, template:=New CompoundUseSiteInfo(Of AssemblySymbol)(diagBag, sourceModule.ContainingAssembly)) End If Next @@ -2164,7 +2166,9 @@ lReportErrorOnTwoTokens: Dim diagnosticsBuilder = ArrayBuilder(Of TypeParameterDiagnosticInfo).GetInstance() Dim useSiteDiagnosticsBuilder As ArrayBuilder(Of TypeParameterDiagnosticInfo) = Nothing - retType.CheckAllConstraints(diagnosticsBuilder, useSiteDiagnosticsBuilder, template:=New CompoundUseSiteInfo(Of AssemblySymbol)(diagBag, sourceModule.ContainingAssembly)) + retType.CheckAllConstraints( + DeclaringCompilation.LanguageVersion, + diagnosticsBuilder, useSiteDiagnosticsBuilder, template:=New CompoundUseSiteInfo(Of AssemblySymbol)(diagBag, sourceModule.ContainingAssembly)) If useSiteDiagnosticsBuilder IsNot Nothing Then diagnosticsBuilder.AddRange(useSiteDiagnosticsBuilder) diff --git a/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceModuleSymbol.vb b/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceModuleSymbol.vb index 5721db14a43f3..a30a836f3121b 100644 --- a/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceModuleSymbol.vb +++ b/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceModuleSymbol.vb @@ -529,7 +529,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols Private Sub ValidateImport(type As TypeSymbol, info As GlobalImportInfo, diagnostics As BindingDiagnosticBag) Dim diagnosticsBuilder = ArrayBuilder(Of TypeParameterDiagnosticInfo).GetInstance() Dim useSiteDiagnosticsBuilder As ArrayBuilder(Of TypeParameterDiagnosticInfo) = Nothing - type.CheckAllConstraints(diagnosticsBuilder, useSiteDiagnosticsBuilder, template:=New CompoundUseSiteInfo(Of AssemblySymbol)(diagnostics, ContainingAssembly)) + type.CheckAllConstraints( + DeclaringCompilation.LanguageVersion, + diagnosticsBuilder, useSiteDiagnosticsBuilder, template:=New CompoundUseSiteInfo(Of AssemblySymbol)(diagnostics, ContainingAssembly)) If useSiteDiagnosticsBuilder IsNot Nothing Then diagnosticsBuilder.AddRange(useSiteDiagnosticsBuilder) diff --git a/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceNamedTypeSymbol.vb b/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceNamedTypeSymbol.vb index f540c8c35744f..abd72dfff73ac 100644 --- a/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceNamedTypeSymbol.vb +++ b/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceNamedTypeSymbol.vb @@ -1626,7 +1626,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols Dim location = singleDeclaration.NameLocation diagnostics = BindingDiagnosticBag.GetInstance() - localBase.CheckAllConstraints(location, diagnostics, template:=New CompoundUseSiteInfo(Of AssemblySymbol)(diagnostics, m_containingModule.ContainingAssembly)) + localBase.CheckAllConstraints( + DeclaringCompilation.LanguageVersion, + location, diagnostics, template:=New CompoundUseSiteInfo(Of AssemblySymbol)(diagnostics, m_containingModule.ContainingAssembly)) If IsGenericType Then ' Check that generic type does not derive from System.Attribute. @@ -1678,7 +1680,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols Dim location = singleDeclaration.NameLocation diagnostics = BindingDiagnosticBag.GetInstance() For Each [interface] In localInterfaces - [interface].CheckAllConstraints(location, diagnostics, template:=New CompoundUseSiteInfo(Of AssemblySymbol)(diagnostics, m_containingModule.ContainingAssembly)) + [interface].CheckAllConstraints( + DeclaringCompilation.LanguageVersion, + location, diagnostics, template:=New CompoundUseSiteInfo(Of AssemblySymbol)(diagnostics, m_containingModule.ContainingAssembly)) Next End If End If diff --git a/src/Compilers/VisualBasic/Portable/Symbols/Source/SourcePropertyAccessorSymbol.vb b/src/Compilers/VisualBasic/Portable/Symbols/Source/SourcePropertyAccessorSymbol.vb index a34e887cd0f87..02addfd0ec070 100644 --- a/src/Compilers/VisualBasic/Portable/Symbols/Source/SourcePropertyAccessorSymbol.vb +++ b/src/Compilers/VisualBasic/Portable/Symbols/Source/SourcePropertyAccessorSymbol.vb @@ -191,7 +191,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols Dim diagnosticsBuilder = ArrayBuilder(Of TypeParameterDiagnosticInfo).GetInstance() Dim useSiteDiagnosticsBuilder As ArrayBuilder(Of TypeParameterDiagnosticInfo) = Nothing - retType.CheckAllConstraints(diagnosticsBuilder, useSiteDiagnosticsBuilder, template:=New CompoundUseSiteInfo(Of AssemblySymbol)(diagBag, sourceModule.ContainingAssembly)) + retType.CheckAllConstraints( + DeclaringCompilation.LanguageVersion, + diagnosticsBuilder, useSiteDiagnosticsBuilder, template:=New CompoundUseSiteInfo(Of AssemblySymbol)(diagBag, sourceModule.ContainingAssembly)) If useSiteDiagnosticsBuilder IsNot Nothing Then diagnosticsBuilder.AddRange(useSiteDiagnosticsBuilder) @@ -260,7 +262,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols If param.Locations.Length > 0 Then ' Note: Errors are reported on the parameter name. Ideally, we should ' match Dev10 and report errors on the parameter type syntax instead. - param.Type.CheckAllConstraints(param.Locations(0), diagBag, template:=New CompoundUseSiteInfo(Of AssemblySymbol)(diagBag, sourceModule.ContainingAssembly)) + param.Type.CheckAllConstraints( + DeclaringCompilation.LanguageVersion, + param.Locations(0), diagBag, template:=New CompoundUseSiteInfo(Of AssemblySymbol)(diagBag, sourceModule.ContainingAssembly)) End If Next diff --git a/src/Compilers/VisualBasic/Portable/Symbols/Source/SourcePropertySymbol.vb b/src/Compilers/VisualBasic/Portable/Symbols/Source/SourcePropertySymbol.vb index 4f67c023631da..661fbf78934c2 100644 --- a/src/Compilers/VisualBasic/Portable/Symbols/Source/SourcePropertySymbol.vb +++ b/src/Compilers/VisualBasic/Portable/Symbols/Source/SourcePropertySymbol.vb @@ -55,6 +55,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols Private Enum StateFlags As Integer SymbolDeclaredEvent = &H1 ' Bit value for generating SymbolDeclaredEvent + + TypeConstraintsChecked = &H2 End Enum Private Sub New(container As SourceMemberContainerTypeSymbol, @@ -335,7 +337,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols End Property Private Function ComputeType(diagnostics As BindingDiagnosticBag) As TypeSymbol - Dim binder = CreateBinderForTypeDeclaration() + Dim binder = BinderBuilder.CreateBinderForType(DirectCast(ContainingModule, SourceModuleSymbol), _syntaxRef.SyntaxTree, _containingType) + binder = New LocationSpecificBinder(BindingLocation.PropertyType, Me, binder) If IsWithEvents Then Dim syntax = DirectCast(_syntaxRef.GetSyntax(), ModifiedIdentifierSyntax) @@ -1190,11 +1193,20 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols MyBase.GenerateDeclarationErrors(cancellationToken) ' Ensure return type attributes are bound - Dim unusedType = Me.Type + Dim type = Me.Type Dim unusedParameters = Me.Parameters Me.GetReturnTypeAttributesBag() Dim unusedImplementations = Me.ExplicitInterfaceImplementations + If (_lazyState And StateFlags.TypeConstraintsChecked) = 0 Then + Dim sourceModule = DirectCast(Me.ContainingModule, SourceModuleSymbol) + Dim diagnostics = BindingDiagnosticBag.GetInstance() + type.CheckAllConstraints(DeclaringCompilation.LanguageVersion, + Locations(0), diagnostics, template:=New CompoundUseSiteInfo(Of AssemblySymbol)(diagnostics, sourceModule.ContainingAssembly)) + sourceModule.AtomicSetFlagAndStoreDiagnostics(_lazyState, StateFlags.TypeConstraintsChecked, 0, diagnostics) + diagnostics.Free() + End If + If DeclaringCompilation.EventQueue IsNot Nothing Then DirectCast(Me.ContainingModule, SourceModuleSymbol).AtomicSetFlagAndRaiseSymbolDeclaredEvent(_lazyState, StateFlags.SymbolDeclaredEvent, 0, Me) End If diff --git a/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceTypeParameterSymbol.vb b/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceTypeParameterSymbol.vb index 126b2ef5c1ab5..eb20fe448f87d 100644 --- a/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceTypeParameterSymbol.vb +++ b/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceTypeParameterSymbol.vb @@ -90,6 +90,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols End Get End Property + Friend Overrides ReadOnly Property HasUnmanagedTypeConstraint As Boolean + Get + Return False + End Get + End Property + Friend Overrides Function GetConstraints() As ImmutableArray(Of TypeParameterConstraint) EnsureAllConstraintsAreResolved() Return _lazyConstraints @@ -183,7 +189,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols constraintType.AddUseSiteInfo(useSiteInfo) If Not diagnostics.Add(location, useSiteInfo) Then - constraintType.CheckAllConstraints(location, diagnostics, template:=New CompoundUseSiteInfo(Of AssemblySymbol)(diagnostics, containingAssembly)) + constraintType.CheckAllConstraints( + DeclaringCompilation.LanguageVersion, + location, diagnostics, template:=New CompoundUseSiteInfo(Of AssemblySymbol)(diagnostics, containingAssembly)) End If End If Next diff --git a/src/Compilers/VisualBasic/Portable/Symbols/SubstitutedTypeParameterSymbol.vb b/src/Compilers/VisualBasic/Portable/Symbols/SubstitutedTypeParameterSymbol.vb index 475be49ff2a2c..461844dd4f76f 100644 --- a/src/Compilers/VisualBasic/Portable/Symbols/SubstitutedTypeParameterSymbol.vb +++ b/src/Compilers/VisualBasic/Portable/Symbols/SubstitutedTypeParameterSymbol.vb @@ -98,6 +98,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols End Get End Property + Friend Overrides ReadOnly Property HasUnmanagedTypeConstraint As Boolean + Get + Return _originalDefinition.HasUnmanagedTypeConstraint + End Get + End Property + Public Overrides ReadOnly Property ContainingSymbol As Symbol Get Return _containingSymbol diff --git a/src/Compilers/VisualBasic/Portable/Symbols/SynthesizedSymbols/SynthesizedClonedTypeParameterSymbol.vb b/src/Compilers/VisualBasic/Portable/Symbols/SynthesizedSymbols/SynthesizedClonedTypeParameterSymbol.vb index e6a1a352fbd6d..398264f9da09f 100644 --- a/src/Compilers/VisualBasic/Portable/Symbols/SynthesizedSymbols/SynthesizedClonedTypeParameterSymbol.vb +++ b/src/Compilers/VisualBasic/Portable/Symbols/SynthesizedSymbols/SynthesizedClonedTypeParameterSymbol.vb @@ -76,6 +76,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols End Get End Property + Friend Overrides ReadOnly Property HasUnmanagedTypeConstraint As Boolean + Get + Return _correspondingMethodTypeParameter.HasUnmanagedTypeConstraint + End Get + End Property + Public Overrides ReadOnly Property ContainingSymbol As Symbol Get Return _container diff --git a/src/Compilers/VisualBasic/Portable/Symbols/TypeParameterSymbol.vb b/src/Compilers/VisualBasic/Portable/Symbols/TypeParameterSymbol.vb index 184a1c7286655..603d4ca44ce2c 100644 --- a/src/Compilers/VisualBasic/Portable/Symbols/TypeParameterSymbol.vb +++ b/src/Compilers/VisualBasic/Portable/Symbols/TypeParameterSymbol.vb @@ -319,11 +319,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols Public MustOverride ReadOnly Property AllowsRefLikeType As Boolean Implements ITypeParameterSymbol.AllowsRefLikeType - Private ReadOnly Property HasUnmanagedTypeConstraint As Boolean Implements ITypeParameterSymbol.HasUnmanagedTypeConstraint - Get - Return False - End Get - End Property + Friend MustOverride ReadOnly Property HasUnmanagedTypeConstraint As Boolean Implements ITypeParameterSymbol.HasUnmanagedTypeConstraint Private ReadOnly Property HasNotNullConstraint As Boolean Implements ITypeParameterSymbol.HasNotNullConstraint Get @@ -333,6 +329,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols Public MustOverride ReadOnly Property Variance As VarianceKind Implements ITypeParameterSymbol.Variance + Friend Overrides Function GetManagedKind(ByRef useSiteInfo As CompoundUseSiteInfo(Of AssemblySymbol)) As ManagedKind + Return If(HasUnmanagedTypeConstraint, ManagedKind.Unmanaged, ManagedKind.Managed) + End Function + ''' ''' If this is a type parameter of a reduced extension method, gets the type parameter definition that ''' this type parameter was reduced from. Otherwise, returns Nothing. diff --git a/src/Compilers/VisualBasic/Portable/Symbols/TypeSymbol.vb b/src/Compilers/VisualBasic/Portable/Symbols/TypeSymbol.vb index 72f9437aa8837..c6f532857bfda 100644 --- a/src/Compilers/VisualBasic/Portable/Symbols/TypeSymbol.vb +++ b/src/Compilers/VisualBasic/Portable/Symbols/TypeSymbol.vb @@ -261,6 +261,11 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols End Get End Property + ' + ' Indicates whether a type is managed or not in C# terms (i.e. you can take a pointer to it). + ' + Friend MustOverride Function GetManagedKind(ByRef useSiteInfo As CompoundUseSiteInfo(Of AssemblySymbol)) As ManagedKind + ' Only the compiler can create TypeSymbols. Friend Sub New() End Sub @@ -588,8 +593,7 @@ Done: Private ReadOnly Property ITypeSymbol_IsUnmanagedType As Boolean Implements ITypeSymbol.IsUnmanagedType Get - ' VB has no concept of unmanaged types - Return False + Return GetManagedKind(CompoundUseSiteInfo(Of AssemblySymbol).Discarded) <> ManagedKind.Managed End Get End Property diff --git a/src/Compilers/VisualBasic/Portable/Symbols/TypeSymbolExtensions.vb b/src/Compilers/VisualBasic/Portable/Symbols/TypeSymbolExtensions.vb index 8dbdcb3e68379..80ccdad058a12 100644 --- a/src/Compilers/VisualBasic/Portable/Symbols/TypeSymbolExtensions.vb +++ b/src/Compilers/VisualBasic/Portable/Symbols/TypeSymbolExtensions.vb @@ -1308,6 +1308,17 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols namedTypeSymbol.IsContainedInNamespace(NameOf(System), NameOf(System.Threading)) End Function + ' Keep in sync with C# equivalent. + + Friend Function IsWellKnownTypeUnmanagedType(typeSymbol As TypeSymbol) As Boolean + Dim namedTypeSymbol = TryCast(typeSymbol, NamedTypeSymbol) + Return namedTypeSymbol IsNot Nothing AndAlso + namedTypeSymbol.Name = "UnmanagedType" AndAlso + namedTypeSymbol.Arity = 0 AndAlso + namedTypeSymbol.ContainingType Is Nothing AndAlso + IsContainedInNamespace(typeSymbol, "System", "Runtime", "InteropServices") + End Function + Private Function IsWellKnownCompilerServicesTopLevelType(typeSymbol As TypeSymbol, name As String) As Boolean If Not String.Equals(typeSymbol.Name, name) Then diff --git a/src/Compilers/VisualBasic/Portable/VBResources.resx b/src/Compilers/VisualBasic/Portable/VBResources.resx index 6e3a339790dbb..aa32f54bfc7c7 100644 --- a/src/Compilers/VisualBasic/Portable/VBResources.resx +++ b/src/Compilers/VisualBasic/Portable/VBResources.resx @@ -2784,6 +2784,9 @@ Type argument '{0}' does not satisfy the 'Structure' constraint for type parameter '{1}'. + + Type argument '{0}' must be a non-nullable value type, along with all fields at any level of nesting, in order to use it as type parameter '{1}'. + Type argument '{0}' does not satisfy the 'Class' constraint for type parameter '{1}'. @@ -5626,6 +5629,9 @@ assigning to or passing 'ByRef' properties with init-only setters + + recognizing 'unmanaged' constraint + Init-only property '{0}' can only be assigned by an object member initializer, or on 'Me', 'MyClass` or 'MyBase' in an instance constructor. diff --git a/src/Compilers/VisualBasic/Portable/xlf/VBResources.cs.xlf b/src/Compilers/VisualBasic/Portable/xlf/VBResources.cs.xlf index 58a67c5e5dee6..678da8c69cc85 100644 --- a/src/Compilers/VisualBasic/Portable/xlf/VBResources.cs.xlf +++ b/src/Compilers/VisualBasic/Portable/xlf/VBResources.cs.xlf @@ -132,6 +132,11 @@ Atribut UnmanagedCallersOnly se nepodporuje. + + Type argument '{0}' must be a non-nullable value type, along with all fields at any level of nesting, in order to use it as type parameter '{1}'. + Type argument '{0}' must be a non-nullable value type, along with all fields at any level of nesting, in order to use it as type parameter '{1}'. + + '{0}' requires compiler feature '{1}', which is not supported by this version of the Visual Basic compiler. {0} vyžaduje funkci kompilátoru {1}, což tato verze kompilátoru Visual Basic nepodporuje. @@ -162,6 +167,11 @@ parametry neomezeného typu v binárních podmíněných výrazech + + recognizing 'unmanaged' constraint + recognizing 'unmanaged' constraint + + Visual Basic Compiler Options diff --git a/src/Compilers/VisualBasic/Portable/xlf/VBResources.de.xlf b/src/Compilers/VisualBasic/Portable/xlf/VBResources.de.xlf index 9e9ed4cc30aa5..8ec7aec8c00c2 100644 --- a/src/Compilers/VisualBasic/Portable/xlf/VBResources.de.xlf +++ b/src/Compilers/VisualBasic/Portable/xlf/VBResources.de.xlf @@ -132,6 +132,11 @@ Das Attribut "UnmanagedCallersOnly" wird nicht unterstützt. + + Type argument '{0}' must be a non-nullable value type, along with all fields at any level of nesting, in order to use it as type parameter '{1}'. + Type argument '{0}' must be a non-nullable value type, along with all fields at any level of nesting, in order to use it as type parameter '{1}'. + + '{0}' requires compiler feature '{1}', which is not supported by this version of the Visual Basic compiler. "{0}" erfordert die Compilerfunktion "{1}", die von dieser Version des Visual Basic Compilers nicht unterstützt wird. @@ -162,6 +167,11 @@ Nicht eingeschränkte Typparameter in binären bedingten Ausdrücken + + recognizing 'unmanaged' constraint + recognizing 'unmanaged' constraint + + Visual Basic Compiler Options diff --git a/src/Compilers/VisualBasic/Portable/xlf/VBResources.es.xlf b/src/Compilers/VisualBasic/Portable/xlf/VBResources.es.xlf index edd7d212905a9..bf862f7cc8d8a 100644 --- a/src/Compilers/VisualBasic/Portable/xlf/VBResources.es.xlf +++ b/src/Compilers/VisualBasic/Portable/xlf/VBResources.es.xlf @@ -132,6 +132,11 @@ No se admite el atributo "UnmanagedCallersOnly". + + Type argument '{0}' must be a non-nullable value type, along with all fields at any level of nesting, in order to use it as type parameter '{1}'. + Type argument '{0}' must be a non-nullable value type, along with all fields at any level of nesting, in order to use it as type parameter '{1}'. + + '{0}' requires compiler feature '{1}', which is not supported by this version of the Visual Basic compiler. '{0}' requiere la característica del compilador '{1}', que no es compatible con esta versión del compilador de Visual Basic. @@ -162,6 +167,11 @@ parámetros de tipo sin restricciones en expresiones condicionales binarias + + recognizing 'unmanaged' constraint + recognizing 'unmanaged' constraint + + Visual Basic Compiler Options diff --git a/src/Compilers/VisualBasic/Portable/xlf/VBResources.fr.xlf b/src/Compilers/VisualBasic/Portable/xlf/VBResources.fr.xlf index e9940a1be752b..34598d12f1e3c 100644 --- a/src/Compilers/VisualBasic/Portable/xlf/VBResources.fr.xlf +++ b/src/Compilers/VisualBasic/Portable/xlf/VBResources.fr.xlf @@ -132,6 +132,11 @@ L'attribut 'UnmanagedCallersOnly' n'est pas pris en charge. + + Type argument '{0}' must be a non-nullable value type, along with all fields at any level of nesting, in order to use it as type parameter '{1}'. + Type argument '{0}' must be a non-nullable value type, along with all fields at any level of nesting, in order to use it as type parameter '{1}'. + + '{0}' requires compiler feature '{1}', which is not supported by this version of the Visual Basic compiler. '{0}' nécessite la fonctionnalité de compilateur '{1}', qui n’est pas prise en charge par cette version du compilateur Visual Basic. @@ -162,6 +167,11 @@ paramètres de type sans contrainte dans les expressions conditionnelles binaires + + recognizing 'unmanaged' constraint + recognizing 'unmanaged' constraint + + Visual Basic Compiler Options diff --git a/src/Compilers/VisualBasic/Portable/xlf/VBResources.it.xlf b/src/Compilers/VisualBasic/Portable/xlf/VBResources.it.xlf index 1115589772d4f..f29bdafb4d467 100644 --- a/src/Compilers/VisualBasic/Portable/xlf/VBResources.it.xlf +++ b/src/Compilers/VisualBasic/Portable/xlf/VBResources.it.xlf @@ -132,6 +132,11 @@ L'attributo 'UnmanagedCallersOnly' non è supportato. + + Type argument '{0}' must be a non-nullable value type, along with all fields at any level of nesting, in order to use it as type parameter '{1}'. + Type argument '{0}' must be a non-nullable value type, along with all fields at any level of nesting, in order to use it as type parameter '{1}'. + + '{0}' requires compiler feature '{1}', which is not supported by this version of the Visual Basic compiler. '{0}' richiede la funzionalità del compilatore '{1}', che non è supportata da questa versione del compilatore Visual Basic. @@ -162,6 +167,11 @@ parametri di tipo non senza vincoli in espressioni condizionali binarie + + recognizing 'unmanaged' constraint + recognizing 'unmanaged' constraint + + Visual Basic Compiler Options diff --git a/src/Compilers/VisualBasic/Portable/xlf/VBResources.ja.xlf b/src/Compilers/VisualBasic/Portable/xlf/VBResources.ja.xlf index dd1aeb31ff170..cee9b4d04c988 100644 --- a/src/Compilers/VisualBasic/Portable/xlf/VBResources.ja.xlf +++ b/src/Compilers/VisualBasic/Portable/xlf/VBResources.ja.xlf @@ -132,6 +132,11 @@ 'UnmanagedCallersOnly' 属性はサポートされていません。 + + Type argument '{0}' must be a non-nullable value type, along with all fields at any level of nesting, in order to use it as type parameter '{1}'. + Type argument '{0}' must be a non-nullable value type, along with all fields at any level of nesting, in order to use it as type parameter '{1}'. + + '{0}' requires compiler feature '{1}', which is not supported by this version of the Visual Basic compiler. '{0}' にはコンパイラ機能 '{1}' が必要ですが、このバージョンのVisual Basic コンパイラではサポートされていません。 @@ -162,6 +167,11 @@ バイナリ条件式での非制約型パラメーター + + recognizing 'unmanaged' constraint + recognizing 'unmanaged' constraint + + Visual Basic Compiler Options diff --git a/src/Compilers/VisualBasic/Portable/xlf/VBResources.ko.xlf b/src/Compilers/VisualBasic/Portable/xlf/VBResources.ko.xlf index 7810d8be04987..a7324e86a2bb4 100644 --- a/src/Compilers/VisualBasic/Portable/xlf/VBResources.ko.xlf +++ b/src/Compilers/VisualBasic/Portable/xlf/VBResources.ko.xlf @@ -132,6 +132,11 @@ 'UnmanagedCallersOnly' 특성은 지원되지 않습니다. + + Type argument '{0}' must be a non-nullable value type, along with all fields at any level of nesting, in order to use it as type parameter '{1}'. + Type argument '{0}' must be a non-nullable value type, along with all fields at any level of nesting, in order to use it as type parameter '{1}'. + + '{0}' requires compiler feature '{1}', which is not supported by this version of the Visual Basic compiler. '{0}'에는 이 버전의 Visual Basic 컴파일러에서 지원하지 않는 컴파일러 기능 '{1}'이(가) 필요합니다. @@ -162,6 +167,11 @@ 이진 조건식의 비제한 형식 매개 변수 + + recognizing 'unmanaged' constraint + recognizing 'unmanaged' constraint + + Visual Basic Compiler Options diff --git a/src/Compilers/VisualBasic/Portable/xlf/VBResources.pl.xlf b/src/Compilers/VisualBasic/Portable/xlf/VBResources.pl.xlf index 07f875f3c3812..350bd6716bc38 100644 --- a/src/Compilers/VisualBasic/Portable/xlf/VBResources.pl.xlf +++ b/src/Compilers/VisualBasic/Portable/xlf/VBResources.pl.xlf @@ -132,6 +132,11 @@ Atrybut „UnmanagedCallersOnly” jest nieobsługiwany. + + Type argument '{0}' must be a non-nullable value type, along with all fields at any level of nesting, in order to use it as type parameter '{1}'. + Type argument '{0}' must be a non-nullable value type, along with all fields at any level of nesting, in order to use it as type parameter '{1}'. + + '{0}' requires compiler feature '{1}', which is not supported by this version of the Visual Basic compiler. „{0}” wymaga funkcji kompilatora „{1}”, która nie jest obsługiwana przez tę wersję kompilatora języka Visual Basic. @@ -162,6 +167,11 @@ parametry typu bez ograniczeń w binarnych wyrażeniach warunkowych + + recognizing 'unmanaged' constraint + recognizing 'unmanaged' constraint + + Visual Basic Compiler Options diff --git a/src/Compilers/VisualBasic/Portable/xlf/VBResources.pt-BR.xlf b/src/Compilers/VisualBasic/Portable/xlf/VBResources.pt-BR.xlf index 80f5bd687e3e0..2da6bfec81618 100644 --- a/src/Compilers/VisualBasic/Portable/xlf/VBResources.pt-BR.xlf +++ b/src/Compilers/VisualBasic/Portable/xlf/VBResources.pt-BR.xlf @@ -132,6 +132,11 @@ Não há suporte para o atributo 'UnmanagedCallersOnly'. + + Type argument '{0}' must be a non-nullable value type, along with all fields at any level of nesting, in order to use it as type parameter '{1}'. + Type argument '{0}' must be a non-nullable value type, along with all fields at any level of nesting, in order to use it as type parameter '{1}'. + + '{0}' requires compiler feature '{1}', which is not supported by this version of the Visual Basic compiler. '{0}' requer o recurso de compilador '{1}', o que não é suportado por esta versão do compilador do Visual Basic. @@ -162,6 +167,11 @@ parâmetros de tipo irrestritos em expressões condicionais binárias + + recognizing 'unmanaged' constraint + recognizing 'unmanaged' constraint + + Visual Basic Compiler Options diff --git a/src/Compilers/VisualBasic/Portable/xlf/VBResources.ru.xlf b/src/Compilers/VisualBasic/Portable/xlf/VBResources.ru.xlf index 09bf20a178096..2c2b9facbe584 100644 --- a/src/Compilers/VisualBasic/Portable/xlf/VBResources.ru.xlf +++ b/src/Compilers/VisualBasic/Portable/xlf/VBResources.ru.xlf @@ -132,6 +132,11 @@ Атрибут "UnmanagedCallersOnly" не поддерживается. + + Type argument '{0}' must be a non-nullable value type, along with all fields at any level of nesting, in order to use it as type parameter '{1}'. + Type argument '{0}' must be a non-nullable value type, along with all fields at any level of nesting, in order to use it as type parameter '{1}'. + + '{0}' requires compiler feature '{1}', which is not supported by this version of the Visual Basic compiler. Для "{0}" требуется функция компилятора "{1}", которая не поддерживается в этой версии компилятора Visual Basic. @@ -162,6 +167,11 @@ параметры неограниченного типа в двоичных условных выражениях + + recognizing 'unmanaged' constraint + recognizing 'unmanaged' constraint + + Visual Basic Compiler Options diff --git a/src/Compilers/VisualBasic/Portable/xlf/VBResources.tr.xlf b/src/Compilers/VisualBasic/Portable/xlf/VBResources.tr.xlf index 68462011b0d12..f8ee6dd28cb27 100644 --- a/src/Compilers/VisualBasic/Portable/xlf/VBResources.tr.xlf +++ b/src/Compilers/VisualBasic/Portable/xlf/VBResources.tr.xlf @@ -132,6 +132,11 @@ 'UnmanagedCallersOnly' özniteliği desteklenmez. + + Type argument '{0}' must be a non-nullable value type, along with all fields at any level of nesting, in order to use it as type parameter '{1}'. + Type argument '{0}' must be a non-nullable value type, along with all fields at any level of nesting, in order to use it as type parameter '{1}'. + + '{0}' requires compiler feature '{1}', which is not supported by this version of the Visual Basic compiler. '{0}', Visual Basic derleyicisinin bu sürümü tarafından desteklenmeyen '{1}' derleyici özelliğini gerektirir. @@ -162,6 +167,11 @@ ikili koşullu ifadelerde kısıtlanmamış tür parametreleri + + recognizing 'unmanaged' constraint + recognizing 'unmanaged' constraint + + Visual Basic Compiler Options diff --git a/src/Compilers/VisualBasic/Portable/xlf/VBResources.zh-Hans.xlf b/src/Compilers/VisualBasic/Portable/xlf/VBResources.zh-Hans.xlf index 76bc9c7093c0c..78a655222e9b3 100644 --- a/src/Compilers/VisualBasic/Portable/xlf/VBResources.zh-Hans.xlf +++ b/src/Compilers/VisualBasic/Portable/xlf/VBResources.zh-Hans.xlf @@ -132,6 +132,11 @@ 不支持 "UnmanagedCallersOnly" 属性。 + + Type argument '{0}' must be a non-nullable value type, along with all fields at any level of nesting, in order to use it as type parameter '{1}'. + Type argument '{0}' must be a non-nullable value type, along with all fields at any level of nesting, in order to use it as type parameter '{1}'. + + '{0}' requires compiler feature '{1}', which is not supported by this version of the Visual Basic compiler. '{0}' 需要编译器功能 '{1}',此版本的 Visual Basic 编译器不支持此功能。 @@ -162,6 +167,11 @@ 二进制条件表达式中的无约束类型参数 + + recognizing 'unmanaged' constraint + recognizing 'unmanaged' constraint + + Visual Basic Compiler Options diff --git a/src/Compilers/VisualBasic/Portable/xlf/VBResources.zh-Hant.xlf b/src/Compilers/VisualBasic/Portable/xlf/VBResources.zh-Hant.xlf index de5cea83ecad1..f081ca6a94841 100644 --- a/src/Compilers/VisualBasic/Portable/xlf/VBResources.zh-Hant.xlf +++ b/src/Compilers/VisualBasic/Portable/xlf/VBResources.zh-Hant.xlf @@ -132,6 +132,11 @@ 不支援 'UnmanagedCallersOnly' 屬性。 + + Type argument '{0}' must be a non-nullable value type, along with all fields at any level of nesting, in order to use it as type parameter '{1}'. + Type argument '{0}' must be a non-nullable value type, along with all fields at any level of nesting, in order to use it as type parameter '{1}'. + + '{0}' requires compiler feature '{1}', which is not supported by this version of the Visual Basic compiler. '{0}' 需要編譯器功能 '{1}',此版本的 Visual Basic 編譯器不支援此功能。 @@ -162,6 +167,11 @@ 二進位條件運算式中的非限制式型別參數 + + recognizing 'unmanaged' constraint + recognizing 'unmanaged' constraint + + Visual Basic Compiler Options diff --git a/src/Compilers/VisualBasic/Test/CommandLine/CommandLineTests.vb b/src/Compilers/VisualBasic/Test/CommandLine/CommandLineTests.vb index 11eebfbc837bd..1663dd469c080 100644 --- a/src/Compilers/VisualBasic/Test/CommandLine/CommandLineTests.vb +++ b/src/Compilers/VisualBasic/Test/CommandLine/CommandLineTests.vb @@ -1530,6 +1530,10 @@ End Module").Path parsedArgs.Errors.Verify() Assert.Equal(LanguageVersion.VisualBasic16_9, parsedArgs.ParseOptions.LanguageVersion) + parsedArgs = DefaultParse({"/langVERSION:17.13", "a.vb"}, _baseDirectory) + parsedArgs.Errors.Verify() + Assert.Equal(LanguageVersion.VisualBasic17_13, parsedArgs.ParseOptions.LanguageVersion) + ' The canary check is a reminder that this test needs to be updated when a language version is added LanguageVersionAdded_Canary() @@ -2055,7 +2059,7 @@ End Module").Path ' - update the "UpgradeProject" codefixer (not yet supported in VB) ' - update all the tests that call this canary ' - update the command-line documentation (CommandLine.md) - AssertEx.SetEqual({"default", "9", "10", "11", "12", "14", "15", "15.3", "15.5", "16", "16.9", "latest"}, + AssertEx.SetEqual({"default", "9", "10", "11", "12", "14", "15", "15.3", "15.5", "16", "16.9", "17.13", "latest"}, System.Enum.GetValues(GetType(LanguageVersion)).Cast(Of LanguageVersion)().Select(Function(v) v.ToDisplayString())) ' For minor versions, the format should be "x.y", such as "15.3" End Sub @@ -2077,7 +2081,8 @@ End Module").Path "15.3", "15.5", "16", - "16.9" + "16.9", + "17.13" } AssertEx.SetEqual(versions, errorCodes) @@ -2098,6 +2103,7 @@ End Module").Path Assert.Equal(LanguageVersion.VisualBasic15_5, LanguageVersion.VisualBasic15_5.MapSpecifiedToEffectiveVersion()) Assert.Equal(LanguageVersion.VisualBasic16, LanguageVersion.VisualBasic16.MapSpecifiedToEffectiveVersion()) Assert.Equal(LanguageVersion.VisualBasic16_9, LanguageVersion.VisualBasic16_9.MapSpecifiedToEffectiveVersion()) + Assert.Equal(LanguageVersion.VisualBasic17_13, LanguageVersion.VisualBasic17_13.MapSpecifiedToEffectiveVersion()) ' The canary check is a reminder that this test needs to be updated when a language version is added LanguageVersionAdded_Canary() @@ -2121,6 +2127,7 @@ End Module").Path InlineData("16", True, LanguageVersion.VisualBasic16), InlineData("16.0", True, LanguageVersion.VisualBasic16), InlineData("16.9", True, LanguageVersion.VisualBasic16_9), + InlineData("17.13", True, LanguageVersion.VisualBasic17_13), InlineData("DEFAULT", True, LanguageVersion.Default), InlineData("default", True, LanguageVersion.Default), InlineData("LATEST", True, LanguageVersion.Latest), diff --git a/src/Compilers/VisualBasic/Test/Emit/CodeGen/CodeGenTuples.vb b/src/Compilers/VisualBasic/Test/Emit/CodeGen/CodeGenTuples.vb index d67a719f84de7..3a01a511788d1 100644 --- a/src/Compilers/VisualBasic/Test/Emit/CodeGen/CodeGenTuples.vb +++ b/src/Compilers/VisualBasic/Test/Emit/CodeGen/CodeGenTuples.vb @@ -14448,7 +14448,7 @@ End Class BC32106: Type argument 'T' does not satisfy the 'Class' constraint for type parameter 'T2'. Dim field As List(Of (T, T)) - ~ + ~~~~~ BC32106: Type argument 'U' does not satisfy the 'Class' constraint for type parameter 'T2'. Function M(Of U)(x As U) As (U, U) ~~~~~~ @@ -14516,7 +14516,7 @@ End Class BC32105: Type argument 'T' does not satisfy the 'Structure' constraint for type parameter 'T2'. Dim field As List(Of (T, T)) - ~ + ~~~~~ BC32105: Type argument 'U' does not satisfy the 'Structure' constraint for type parameter 'T2'. Function M(Of U As Class)(x As (U, U)) As (U, U) ~ diff --git a/src/Compilers/VisualBasic/Test/Semantic/Compilation/CompilationAPITests.vb b/src/Compilers/VisualBasic/Test/Semantic/Compilation/CompilationAPITests.vb index fa7e860d7c8c4..7a317369b781d 100644 --- a/src/Compilers/VisualBasic/Test/Semantic/Compilation/CompilationAPITests.vb +++ b/src/Compilers/VisualBasic/Test/Semantic/Compilation/CompilationAPITests.vb @@ -2324,10 +2324,10 @@ End Class Public Sub ReferenceManagerReuse_WithSyntaxTrees() Dim ta = Parse("Imports System") - Dim tb = Parse("Imports System", options:=TestOptions.Script) + Dim tb = Parse("Imports System", options:=TestOptions.Script.WithLanguageVersion(LanguageVersion.Latest)) Dim tc = Parse("#r ""bar"" ' error: #r in regular code") - Dim tr = Parse("#r ""goo""", options:=TestOptions.Script) - Dim ts = Parse("#r ""bar""", options:=TestOptions.Script) + Dim tr = Parse("#r ""goo""", options:=TestOptions.Script.WithLanguageVersion(LanguageVersion.Latest)) + Dim ts = Parse("#r ""bar""", options:=TestOptions.Script.WithLanguageVersion(LanguageVersion.Latest)) Dim a = VisualBasicCompilation.Create("c", syntaxTrees:={ta}) diff --git a/src/Compilers/VisualBasic/Test/Semantic/Compilation/SemanticModelAPITests.vb b/src/Compilers/VisualBasic/Test/Semantic/Compilation/SemanticModelAPITests.vb index b91a3444a2145..84df0803e7b17 100644 --- a/src/Compilers/VisualBasic/Test/Semantic/Compilation/SemanticModelAPITests.vb +++ b/src/Compilers/VisualBasic/Test/Semantic/Compilation/SemanticModelAPITests.vb @@ -2947,12 +2947,12 @@ End Class") Single(Function(n) n.Identifier.ValueText = name) Return CType(model.GetDeclaredSymbol(decl), ILocalSymbol).Type End Function - ' VB does not have a concept of a managed type - Assert.False(getLocalType("s1").IsUnmanagedType) - Assert.False(getLocalType("s2").IsUnmanagedType) + + Assert.True(getLocalType("s1").IsUnmanagedType) + Assert.True(getLocalType("s2").IsUnmanagedType) Assert.False(getLocalType("s3").IsUnmanagedType) - Assert.False(getLocalType("s4").IsUnmanagedType) - Assert.False(getLocalType("e1").IsUnmanagedType) + Assert.True(getLocalType("s4").IsUnmanagedType) + Assert.True(getLocalType("e1").IsUnmanagedType) End Sub diff --git a/src/Compilers/VisualBasic/Test/Semantic/Semantics/OverloadResolution.vb b/src/Compilers/VisualBasic/Test/Semantic/Semantics/OverloadResolution.vb index b3944b3117778..28420b328047d 100644 --- a/src/Compilers/VisualBasic/Test/Semantic/Semantics/OverloadResolution.vb +++ b/src/Compilers/VisualBasic/Test/Semantic/Semantics/OverloadResolution.vb @@ -3050,7 +3050,7 @@ Class OptionStrictOff End Class - Dim optionStrictOffTree = VisualBasicSyntaxTree.ParseText(optionStrictOff.Value) + Dim optionStrictOffTree = VisualBasicSyntaxTree.ParseText(optionStrictOff.Value, options:=TestOptions.RegularLatest) Dim c1 = VisualBasicCompilation.Create("Test1", syntaxTrees:={Parse(SemanticResourceUtil.OverloadResolutionTestSource), optionStrictOffTree}, diff --git a/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/GenericConstraintTests.vb b/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/GenericConstraintTests.vb index 0f6ea6c15d133..55c1d3224dc62 100644 --- a/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/GenericConstraintTests.vb +++ b/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/GenericConstraintTests.vb @@ -4686,7 +4686,7 @@ End Interface compilation.AssertTheseDiagnostics( BC32044: Type argument 'String' does not inherit from or implement the constraint type 'IStoreable'. Public ReadOnly Property Deleted As IEnumerable(Of UpdateResult(Of String)) - ~~~~~~ + ~~~~~~~ ) End Sub @@ -5014,10 +5014,10 @@ Delegate Sub D(Of T As New)() compilation.AssertTheseDiagnostics( BC32044: Type argument 'C3T2' does not inherit from or implement the constraint type 'Integer'. Dim x As C1(Of Integer, Integer).C2(Of C2T1, C2T2).C3(Of C3T1, C3T2) - ~~~~ + ~ ) Assert.Throws(Of InvalidOperationException)(Sub() c5.Construct(c1)) diff --git a/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/Metadata/PE/LoadCustomModifiers.vb b/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/Metadata/PE/LoadCustomModifiers.vb index b08336c56d925..58edd937fbfc4 100644 --- a/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/Metadata/PE/LoadCustomModifiers.vb +++ b/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/Metadata/PE/LoadCustomModifiers.vb @@ -110,7 +110,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.UnitTests.Symbols.Metadata.PE End Sub - Public Sub UnmanagedConstraint_RejectedSymbol_OnClass() + Public Sub UnmanagedConstraint_OnClass() Dim reference = CreateCSharpCompilation(" public class TestRef where T : unmanaged { @@ -122,6 +122,7 @@ public class TestRef where T : unmanaged Class Test Shared Sub Main() Dim x = New TestRef(Of String)() + Dim y = New TestRef(Of Integer)() End Sub End Class @@ -129,24 +130,63 @@ End Class Dim compilation = CreateCompilationWithMscorlib45AndVBRuntime(source, references:={reference}) - AssertTheseDiagnostics(compilation, -BC30649: '' is an unsupported type. + Dim errs As XElement = + +BC32105: Type argument 'String' does not satisfy the 'Structure' constraint for type parameter 'T'. Dim x = New TestRef(Of String)() ~~~~~~ -BC32044: Type argument 'String' does not inherit from or implement the constraint type '?'. +BC37332: Type argument 'String' must be a non-nullable value type, along with all fields at any level of nesting, in order to use it as type parameter 'T'. Dim x = New TestRef(Of String)() ~~~~~~ + + + AssertTheseDiagnostics(compilation, errs) + + Dim typeParameter = compilation.GetTypeByMetadataName("TestRef`1").TypeParameters.Single() + Assert.True(typeParameter.HasValueTypeConstraint) + Assert.True(typeParameter.HasUnmanagedTypeConstraint) + + typeParameter = compilation.GetTypeByMetadataName("System.Nullable`1").TypeParameters.Single() + Assert.True(typeParameter.HasValueTypeConstraint) + Assert.False(typeParameter.HasUnmanagedTypeConstraint) + + compilation = CreateCompilationWithMscorlib45AndVBRuntime(source, references:={reference}, parseOptions:=TestOptions.Regular17_13) + AssertTheseDiagnostics(compilation, errs) + + typeParameter = compilation.GetTypeByMetadataName("TestRef`1").TypeParameters.Single() + Assert.True(typeParameter.HasValueTypeConstraint) + Assert.True(typeParameter.HasUnmanagedTypeConstraint) + compilation = CreateCompilationWithMscorlib45AndVBRuntime(source, references:={reference}, parseOptions:=TestOptions.RegularLatest) + + AssertTheseDiagnostics(compilation, errs) + + typeParameter = compilation.GetTypeByMetadataName("TestRef`1").TypeParameters.Single() + Assert.True(typeParameter.HasValueTypeConstraint) + Assert.True(typeParameter.HasUnmanagedTypeConstraint) + + compilation = CreateCompilationWithMscorlib45AndVBRuntime(source, references:={reference}, parseOptions:=TestOptions.Regular16_9) + AssertTheseDiagnostics(compilation, BC32105: Type argument 'String' does not satisfy the 'Structure' constraint for type parameter 'T'. Dim x = New TestRef(Of String)() ~~~~~~ +BC36716: Visual Basic 16.9 does not support recognizing 'unmanaged' constraint. + Dim x = New TestRef(Of String)() + ~~~~~~ +BC37332: Type argument 'String' must be a non-nullable value type, along with all fields at any level of nesting, in order to use it as type parameter 'T'. + Dim x = New TestRef(Of String)() + ~~~~~~ +BC36716: Visual Basic 16.9 does not support recognizing 'unmanaged' constraint. + Dim y = New TestRef(Of Integer)() + ~~~~~~~ ) - Dim badTypeParameter = compilation.GetTypeByMetadataName("TestRef`1").TypeParameters.Single() - Assert.True(badTypeParameter.HasValueTypeConstraint) + typeParameter = compilation.GetTypeByMetadataName("TestRef`1").TypeParameters.Single() + Assert.True(typeParameter.HasValueTypeConstraint) + Assert.True(typeParameter.HasUnmanagedTypeConstraint) End Sub - Public Sub UnmanagedConstraint_RejectedSymbol_OnMethod() + Public Sub UnmanagedConstraint_OnMethod() Dim reference = CreateCSharpCompilation(" public class TestRef { @@ -170,17 +210,21 @@ End Class Dim compilation = CreateCompilationWithMscorlib45AndVBRuntime(source, references:={reference}) AssertTheseDiagnostics(compilation, -BC30649: '' is an unsupported type. +BC32105: Type argument 'String' does not satisfy the 'Structure' constraint for type parameter 'T'. + x.M(Of String)() + ~~~~~~~~~~~~ +BC37332: Type argument 'String' must be a non-nullable value type, along with all fields at any level of nesting, in order to use it as type parameter 'T'. x.M(Of String)() - ~~~~~~~~~~~~~~~~ + ~~~~~~~~~~~~ ) - Dim badTypeParameter = compilation.GetTypeByMetadataName("TestRef").GetMethod("M").TypeParameters.Single() - Assert.True(badTypeParameter.HasValueTypeConstraint) + Dim typeParameter = compilation.GetTypeByMetadataName("TestRef").GetMethod("M").TypeParameters.Single() + Assert.True(typeParameter.HasValueTypeConstraint) + Assert.True(typeParameter.HasUnmanagedTypeConstraint) End Sub - Public Sub UnmanagedConstraint_RejectedSymbol_OnDelegate() + Public Sub UnmanagedConstraint_OnDelegate() Dim reference = CreateCSharpCompilation(" public delegate T D() where T : unmanaged; ", parseOptions:=New CSharpParseOptions(CSharp.LanguageVersion.Latest)).EmitToImageReference() @@ -192,25 +236,23 @@ Class Test Shared Sub Main(del As D(Of String)) End Sub End Class - + Dim compilation = CreateCompilationWithMscorlib45AndVBRuntime(source, references:={reference}) AssertTheseDiagnostics(compilation, -BC30649: '' is an unsupported type. - Shared Sub Main(del As D(Of String)) - ~~~ -BC32044: Type argument 'String' does not inherit from or implement the constraint type '?'. +BC32105: Type argument 'String' does not satisfy the 'Structure' constraint for type parameter 'T'. Shared Sub Main(del As D(Of String)) ~~~ -BC32105: Type argument 'String' does not satisfy the 'Structure' constraint for type parameter 'T'. +BC37332: Type argument 'String' must be a non-nullable value type, along with all fields at any level of nesting, in order to use it as type parameter 'T'. Shared Sub Main(del As D(Of String)) ~~~ ) - Dim badTypeParameter = compilation.GetTypeByMetadataName("D`1").TypeParameters.Single() - Assert.True(badTypeParameter.HasValueTypeConstraint) + Dim typeParameter = compilation.GetTypeByMetadataName("D`1").TypeParameters.Single() + Assert.True(typeParameter.HasValueTypeConstraint) + Assert.True(typeParameter.HasUnmanagedTypeConstraint) End Sub End Class diff --git a/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/SymbolErrorTests.vb b/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/SymbolErrorTests.vb index 131c09d199002..e32077a0bb2bc 100644 --- a/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/SymbolErrorTests.vb +++ b/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/SymbolErrorTests.vb @@ -14655,7 +14655,7 @@ BC32081: 'New' constraint cannot be specified multiple times for the same type p Dim expectedErrors1 = CompilationUtils.AssertTheseDiagnostics(compilation1, expectedErrors1) End Sub diff --git a/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/UnmanagedTypeConstraintTests.vb b/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/UnmanagedTypeConstraintTests.vb new file mode 100644 index 0000000000000..c905d7ae28a0d --- /dev/null +++ b/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/UnmanagedTypeConstraintTests.vb @@ -0,0 +1,1799 @@ +' Licensed to the .NET Foundation under one or more agreements. +' The .NET Foundation licenses this file to you under the MIT license. +' See the LICENSE file in the project root for more information. + +Imports System.Runtime.InteropServices +Imports Microsoft.CodeAnalysis.CSharp +Imports Microsoft.CodeAnalysis.Test.Utilities +Imports Microsoft.CodeAnalysis.VisualBasic.Symbols +Imports Roslyn.Test.Utilities + +Namespace Microsoft.CodeAnalysis.VisualBasic.UnitTests + + Public Class UnmanagedTypeConstraintTests + Inherits BasicTestBase + + + Public Sub LoadingADifferentModifierTypeForUnmanagedConstraint() + + Dim ilSource = IsUnmanagedAttributeIL + " +.class public auto ansi beforefieldinit TestRef + extends [mscorlib]System.Object +{ + .method public hidebysig instance void + M1() cil managed + { + .param type T + .custom instance void System.Runtime.CompilerServices.IsUnmanagedAttribute::.ctor() = ( 01 00 00 00 ) + // Code size 2 (0x2) + .maxstack 8 + IL_0000: nop + IL_0001: ret + } // end of method TestRef::M1 + + .method public hidebysig instance void + M2() cil managed + { + .param type T + .custom instance void System.Runtime.CompilerServices.IsUnmanagedAttribute::.ctor() = ( 01 00 00 00 ) + // Code size 2 (0x2) + .maxstack 8 + IL_0000: nop + IL_0001: ret + } // end of method TestRef::M2 + + .method public hidebysig specialname rtspecialname + instance void .ctor() cil managed + { + // Code size 8 (0x8) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [mscorlib]System.Object::.ctor() + IL_0006: nop + IL_0007: ret + } // end of method TestRef::.ctor + +}" + + Dim reference = CompileIL(ilSource, prependDefaultHeader:=False) + + Dim code = " +public class Test + public shared sub Main() + dim obj = new TestRef() + + obj.M1(Of Integer)() ' valid + obj.M2(Of Integer)() ' invalid + End Sub +End Class +" + + CreateCompilation(code, references:={reference}). + AssertTheseDiagnostics( +BC30649: '' is an unsupported type. + obj.M2(Of Integer)() ' invalid + ~~~~~~~~~~~~~~~~~~~~ +BC30649: 'T' is an unsupported type. + obj.M2(Of Integer)() ' invalid + ~~~~~~~~~~~~~~~~~~~~ + ) + End Sub + + + Public Sub LoadingUnmanagedTypeModifier_OptionalIsError() + + Dim ilSource = IsUnmanagedAttributeIL + " +.class public auto ansi beforefieldinit TestRef + extends [mscorlib]System.Object +{ + .method public hidebysig instance void + M1() cil managed + { + .param type T + .custom instance void System.Runtime.CompilerServices.IsUnmanagedAttribute::.ctor() = ( 01 00 00 00 ) + // Code size 2 (0x2) + .maxstack 8 + IL_0000: nop + IL_0001: ret + } // end of method TestRef::M1 + + .method public hidebysig instance void + M2() cil managed + { + .param type T + .custom instance void System.Runtime.CompilerServices.IsUnmanagedAttribute::.ctor() = ( 01 00 00 00 ) + // Code size 2 (0x2) + .maxstack 8 + IL_0000: nop + IL_0001: ret + } // end of method TestRef::M2 + + .method public hidebysig specialname rtspecialname + instance void .ctor() cil managed + { + // Code size 8 (0x8) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [mscorlib]System.Object::.ctor() + IL_0006: nop + IL_0007: ret + } // end of method TestRef::.ctor + +}" + + Dim reference = CompileIL(ilSource, prependDefaultHeader:=False) + + Dim code = " +public class Test + public shared sub Main() + Dim obj = new TestRef() + + obj.M1(Of Integer)() ' valid + obj.M2(Of Integer)() ' invalid + end sub +end class +" + + CreateCompilation(code, references:={reference}). + AssertTheseDiagnostics( +BC30649: '' is an unsupported type. + obj.M2(Of Integer)() ' invalid + ~~~~~~~~~~~~~~~~~~~~ +BC30649: 'T' is an unsupported type. + obj.M2(Of Integer)() ' invalid + ~~~~~~~~~~~~~~~~~~~~ + ) + End Sub + + + Public Sub LoadingUnmanagedTypeModifier_MoreThanOneModifier() + + Dim ilSource = IsUnmanagedAttributeIL + " +.class public auto ansi beforefieldinit TestRef + extends [mscorlib]System.Object +{ + .method public hidebysig instance void + M1() cil managed + { + .param type T + .custom instance void System.Runtime.CompilerServices.IsUnmanagedAttribute::.ctor() = ( 01 00 00 00 ) + // Code size 2 (0x2) + .maxstack 8 + IL_0000: nop + IL_0001: ret + } // end of method TestRef::M1 + + .method public hidebysig instance void + M2() cil managed + { + .param type T + .custom instance void System.Runtime.CompilerServices.IsUnmanagedAttribute::.ctor() = ( 01 00 00 00 ) + // Code size 2 (0x2) + .maxstack 8 + IL_0000: nop + IL_0001: ret + } // end of method TestRef::M2 + + .method public hidebysig specialname rtspecialname + instance void .ctor() cil managed + { + // Code size 8 (0x8) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [mscorlib]System.Object::.ctor() + IL_0006: nop + IL_0007: ret + } // end of method TestRef::.ctor + +}" + + Dim reference = CompileIL(ilSource, prependDefaultHeader:=False) + + Dim code = " +public class Test + public shared sub Main() + Dim obj = new TestRef() + + obj.M1(Of Integer)() ' valid + obj.M2(Of Integer)() ' invalid + end sub +end class +" + + CreateCompilation(code, references:={reference}). + AssertTheseDiagnostics( +BC30649: '' is an unsupported type. + obj.M2(Of Integer)() ' invalid + ~~~~~~~~~~~~~~~~~~~~ +BC30649: 'T' is an unsupported type. + obj.M2(Of Integer)() ' invalid + ~~~~~~~~~~~~~~~~~~~~ + ) + End Sub + + + Public Sub LoadingUnmanagedTypeModifier_ModreqWithoutAttribute() + + Dim ilSource = IsUnmanagedAttributeIL + " +.class public auto ansi beforefieldinit TestRef + extends [mscorlib]System.Object +{ + .method public hidebysig instance void + M1() cil managed + { + .param type T + .custom instance void System.Runtime.CompilerServices.IsUnmanagedAttribute::.ctor() = ( 01 00 00 00 ) + // Code size 2 (0x2) + .maxstack 8 + IL_0000: nop + IL_0001: ret + } // end of method TestRef::M1 + + .method public hidebysig instance void + M2() cil managed + { + // Code size 2 (0x2) + .maxstack 8 + IL_0000: nop + IL_0001: ret + } // end of method TestRef::M2 + + .method public hidebysig specialname rtspecialname + instance void .ctor() cil managed + { + // Code size 8 (0x8) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [mscorlib]System.Object::.ctor() + IL_0006: nop + IL_0007: ret + } // end of method TestRef::.ctor + +}" + + Dim reference = CompileIL(ilSource, prependDefaultHeader:=False) + + Dim code = " +public class Test + public shared sub Main() + Dim obj = new TestRef() + + obj.M1(Of Integer)() ' valid + obj.M2(Of Integer)() ' invalid + end sub +end class +" + + CreateCompilation(code, references:={reference}). + AssertTheseDiagnostics( +BC30649: 'T' is an unsupported type. + obj.M2(Of Integer)() ' invalid + ~~~~~~~~~~~~~~~~~~~~ + ) + End Sub + + + Public Sub LoadingUnmanagedTypeModifier_AttributeWithoutModreq() + + Dim ilSource = IsUnmanagedAttributeIL + " +.class public auto ansi beforefieldinit TestRef + extends [mscorlib]System.Object +{ + .method public hidebysig instance void + M1() cil managed + { + .param type T + .custom instance void System.Runtime.CompilerServices.IsUnmanagedAttribute::.ctor() = ( 01 00 00 00 ) + // Code size 2 (0x2) + .maxstack 8 + IL_0000: nop + IL_0001: ret + } // end of method TestRef::M1 + + .method public hidebysig instance void + M2() cil managed + { + .param type T + .custom instance void System.Runtime.CompilerServices.IsUnmanagedAttribute::.ctor() = ( 01 00 00 00 ) + // Code size 2 (0x2) + .maxstack 8 + IL_0000: nop + IL_0001: ret + } // end of method TestRef::M2 + + .method public hidebysig specialname rtspecialname + instance void .ctor() cil managed + { + // Code size 8 (0x8) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [mscorlib]System.Object::.ctor() + IL_0006: nop + IL_0007: ret + } // end of method TestRef::.ctor + +}" + + Dim reference = CompileIL(ilSource, prependDefaultHeader:=False) + + Dim code = " +public class Test + public shared sub Main() + Dim obj = new TestRef() + + obj.M1(Of Integer)() ' valid + obj.M2(Of Integer)() ' invalid + end sub +end class +" + + CreateCompilation(code, references:={reference}). + AssertTheseDiagnostics( +BC30649: 'T' is an unsupported type. + obj.M2(Of Integer)() ' invalid + ~~~~~~~~~~~~~~~~~~~~ + ) + End Sub + + + Public Sub UnmanagedTypeModreqOnOverriddenMethod() + Dim reference = CreateCSharpCompilation(" +public class Parent +{ + public virtual string M() where T : unmanaged => ""Parent""; +} +", parseOptions:=New CSharpParseOptions(CSharp.LanguageVersion.Latest)).EmitToImageReference() + + Dim source = " +public class Child + Inherits Parent + + public overrides Function M(Of T as Structure)() As string + Return ""Child"" + End Function +End Class +" + + Dim compilation = CreateCompilation(source, references:={reference}) + + Dim typeParameter = compilation.GetTypeByMetadataName("Parent").GetMethod("M").TypeParameters.Single() + Assert.True(typeParameter.HasValueTypeConstraint) + Assert.True(typeParameter.HasUnmanagedTypeConstraint) + + typeParameter = compilation.GetTypeByMetadataName("Child").GetMethod("M").TypeParameters.Single() + Assert.True(typeParameter.HasValueTypeConstraint) + Assert.False(typeParameter.HasUnmanagedTypeConstraint) + + AssertTheseDiagnostics(compilation, +BC32077: 'Public Overrides Function M(Of T As Structure)() As String' cannot override 'Public Overridable Overloads Function M(Of T As Structure)() As String' because they differ by type parameter constraints. + public overrides Function M(Of T as Structure)() As string + ~ + ) + End Sub + + + Public Sub UnmanagedTypeModreqOnImplementedMethod() + Dim reference = CreateCSharpCompilation(" +public interface Parent +{ + string M() where T : unmanaged; +} +", parseOptions:=New CSharpParseOptions(CSharp.LanguageVersion.Latest)).EmitToImageReference() + + Dim source = " +public class Child + Implements Parent + + Function M(Of T as Structure)() As string Implements Parent.M + Return ""Child"" + End Function +End Class +" + + Dim compilation = CreateCompilation(source, references:={reference}) + + Dim typeParameter = compilation.GetTypeByMetadataName("Parent").GetMethod("M").TypeParameters.Single() + Assert.True(typeParameter.HasValueTypeConstraint) + Assert.True(typeParameter.HasUnmanagedTypeConstraint) + + typeParameter = compilation.GetTypeByMetadataName("Child").GetMethod("M").TypeParameters.Single() + Assert.True(typeParameter.HasValueTypeConstraint) + Assert.False(typeParameter.HasUnmanagedTypeConstraint) + + AssertTheseDiagnostics(compilation, +BC32078: 'Public Function M(Of T As Structure)() As String' cannot implement 'Parent.Function M(Of T As Structure)() As String' because they differ by type parameter constraints. + Function M(Of T as Structure)() As string Implements Parent.M + ~~~~~~~~ + ) + End Sub + + + Public Sub UnmanagedConstraintWithClassConstraint_IL() + + Dim ilSource = IsUnmanagedAttributeIL + " +.class public auto ansi beforefieldinit TestRef + extends [mscorlib]System.Object +{ + .method public hidebysig instance void + M() cil managed + { + .param type T + .custom instance void System.Runtime.CompilerServices.IsUnmanagedAttribute::.ctor() = ( 01 00 00 00 ) + // Code size 2 (0x2) + .maxstack 8 + IL_0000: nop + IL_0001: ret + } // end of method TestRef::M + + .method public hidebysig specialname rtspecialname + instance void .ctor() cil managed + { + // Code size 8 (0x8) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [mscorlib]System.Object::.ctor() + IL_0006: nop + IL_0007: ret + } // end of method TestRef::.ctor + +}" + + Dim reference = CompileIL(ilSource, prependDefaultHeader:=False) + + Dim code = " +public class Test + public shared sub Main() + Dim obj = new TestRef() + + obj.M(Of integer)() + obj.M(Of string)() + end sub +end class +" + + CreateCompilation(code, references:={reference}). + AssertTheseDiagnostics( +BC30649: 'T' is an unsupported type. + obj.M(Of integer)() + ~~~~~~~~~~~~~~~~~~~ +BC30649: 'T' is an unsupported type. + obj.M(Of string)() + ~~~~~~~~~~~~~~~~~~ + ) + End Sub + + + Public Sub UnmanagedConstraintWithConstructorConstraint_IL() + + Dim ilSource = IsUnmanagedAttributeIL + " +.class public auto ansi beforefieldinit TestRef + extends [mscorlib]System.Object +{ + .method public hidebysig instance void + M<.ctor (class [mscorlib]System.ValueType modreq([mscorlib]System.Runtime.InteropServices.UnmanagedType)) T>() cil managed + { + .param type T + .custom instance void System.Runtime.CompilerServices.IsUnmanagedAttribute::.ctor() = ( 01 00 00 00 ) + // Code size 2 (0x2) + .maxstack 8 + IL_0000: nop + IL_0001: ret + } // end of method TestRef::M + + .method public hidebysig specialname rtspecialname + instance void .ctor() cil managed + { + // Code size 8 (0x8) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [mscorlib]System.Object::.ctor() + IL_0006: nop + IL_0007: ret + } // end of method TestRef::.ctor + +}" + + Dim reference = CompileIL(ilSource, prependDefaultHeader:=False) + + Dim code = " +public class Test + public shared sub Main() + Dim obj = new TestRef() + + obj.M(Of integer)() + obj.M(Of string)() + end sub +end class +" + + CreateCompilation(code, references:={reference}). + AssertTheseDiagnostics( +BC30649: 'T' is an unsupported type. + obj.M(Of integer)() + ~~~~~~~~~~~~~~~~~~~ +BC30649: 'T' is an unsupported type. + obj.M(Of string)() + ~~~~~~~~~~~~~~~~~~ + ) + End Sub + + + Public Sub UnmanagedConstraintWithoutValueTypeConstraint_IL() + + Dim ilSource = IsUnmanagedAttributeIL + " +.class public auto ansi beforefieldinit TestRef + extends [mscorlib]System.Object +{ + .method public hidebysig instance void + M<(class [mscorlib]System.ValueType modreq([mscorlib]System.Runtime.InteropServices.UnmanagedType)) T>() cil managed + { + .param type T + .custom instance void System.Runtime.CompilerServices.IsUnmanagedAttribute::.ctor() = ( 01 00 00 00 ) + // Code size 2 (0x2) + .maxstack 8 + IL_0000: nop + IL_0001: ret + } // end of method TestRef::M + + .method public hidebysig specialname rtspecialname + instance void .ctor() cil managed + { + // Code size 8 (0x8) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [mscorlib]System.Object::.ctor() + IL_0006: nop + IL_0007: ret + } // end of method TestRef::.ctor + +}" + + Dim reference = CompileIL(ilSource, prependDefaultHeader:=False) + + Dim code = " +public class Test + public shared sub Main() + Dim obj = new TestRef() + + obj.M(Of integer)() + obj.M(Of string)() + end sub +end class +" + + CreateCompilation(code, references:={reference}). + AssertTheseDiagnostics( +BC30649: 'T' is an unsupported type. + obj.M(Of integer)() + ~~~~~~~~~~~~~~~~~~~ +BC30649: 'T' is an unsupported type. + obj.M(Of string)() + ~~~~~~~~~~~~~~~~~~ + ) + End Sub + + + Public Sub UnmanagedConstraintWithTypeConstraint_IL() + + Dim ilSource = IsUnmanagedAttributeIL + " +.class public auto ansi beforefieldinit TestRef + extends [mscorlib]System.Object +{ + .method public hidebysig instance void + M() cil managed + { + .param type T + .custom instance void System.Runtime.CompilerServices.IsUnmanagedAttribute::.ctor() = ( 01 00 00 00 ) + // Code size 2 (0x2) + .maxstack 8 + IL_0000: nop + IL_0001: ret + } // end of method TestRef::M + + .method public hidebysig specialname rtspecialname + instance void .ctor() cil managed + { + // Code size 8 (0x8) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [mscorlib]System.Object::.ctor() + IL_0006: nop + IL_0007: ret + } // end of method TestRef::.ctor + +}" + + Dim reference = CompileIL(ilSource, prependDefaultHeader:=False) + + Dim code = " +public class Test + public shared sub Main() + Dim obj = new TestRef() + + obj.M(Of integer)() + obj.M(Of string)() + obj.M(Of S1)() + end sub +end class + +Structure S1 +End Structure +" + + CreateCompilation(code, references:={reference}). + AssertTheseDiagnostics( +BC32105: Type argument 'String' does not satisfy the 'Structure' constraint for type parameter 'T'. + obj.M(Of string)() + ~~~~~~~~~~~~ +BC37332: Type argument 'String' must be a non-nullable value type, along with all fields at any level of nesting, in order to use it as type parameter 'T'. + obj.M(Of string)() + ~~~~~~~~~~~~ +BC32044: Type argument 'S1' does not inherit from or implement the constraint type 'IComparable'. + obj.M(Of S1)() + ~~~~~~~~ + ) + End Sub + + + Public Sub UnmanagedTypeModreqNotSet() + Dim reference = CreateCSharpCompilation(" +public interface Parent +{ + string M() where T : struct; +} +", parseOptions:=New CSharpParseOptions(CSharp.LanguageVersion.Latest)).EmitToImageReference() + + Dim source = " +public class Child + Implements Parent + + Function M(Of T as Structure)() As string Implements Parent.M + Return ""Child"" + End Function +End Class +" + + Dim compilation = CreateCompilation(source, references:={reference}) + + Dim typeParameter = compilation.GetTypeByMetadataName("Parent").GetMethod("M").TypeParameters.Single() + Assert.True(typeParameter.HasValueTypeConstraint) + Assert.False(typeParameter.HasUnmanagedTypeConstraint) + + typeParameter = compilation.GetTypeByMetadataName("Child").GetMethod("M").TypeParameters.Single() + Assert.True(typeParameter.HasValueTypeConstraint) + Assert.False(typeParameter.HasUnmanagedTypeConstraint) + + AssertNoDiagnostics(compilation) + End Sub + + + Public Sub UnmanagedCheck_Array() + Dim reference = CreateCSharpCompilation(" +public class Test where T : unmanaged +{ +} +", parseOptions:=New CSharpParseOptions(CSharp.LanguageVersion.Latest)).EmitToImageReference() + + Dim source = " +public class Program + Shared Sub Main + Dim o As Object + o = GetType(Test(Of Integer())) + o = GetType(Test(Of Integer()())) + o = GetType(Test(Of Integer(,))) + o = GetType(Test(Of Integer)) + End Sub +End Class +" + + Dim compilation = CreateCompilation(source, references:={reference}) + AssertTheseDiagnostics(compilation, +BC32105: Type argument 'Integer()' does not satisfy the 'Structure' constraint for type parameter 'T'. + o = GetType(Test(Of Integer())) + ~~~~~~~~~ +BC37332: Type argument 'Integer()' must be a non-nullable value type, along with all fields at any level of nesting, in order to use it as type parameter 'T'. + o = GetType(Test(Of Integer())) + ~~~~~~~~~ +BC32105: Type argument 'Integer()()' does not satisfy the 'Structure' constraint for type parameter 'T'. + o = GetType(Test(Of Integer()())) + ~~~~~~~~~~~ +BC37332: Type argument 'Integer()()' must be a non-nullable value type, along with all fields at any level of nesting, in order to use it as type parameter 'T'. + o = GetType(Test(Of Integer()())) + ~~~~~~~~~~~ +BC32105: Type argument 'Integer(*,*)' does not satisfy the 'Structure' constraint for type parameter 'T'. + o = GetType(Test(Of Integer(,))) + ~~~~~~~~~~ +BC37332: Type argument 'Integer(*,*)' must be a non-nullable value type, along with all fields at any level of nesting, in order to use it as type parameter 'T'. + o = GetType(Test(Of Integer(,))) + ~~~~~~~~~~ + ) + + compilation = CreateCompilation(source, references:={reference}, parseOptions:=TestOptions.Regular17_13) + AssertTheseDiagnostics(compilation, ) + + compilation = CreateCompilation(source, references:={reference}, parseOptions:=TestOptions.Regular16_9) + AssertTheseDiagnostics(compilation, ) + End Sub + + + Public Sub UnmanagedCheck_AnonymousType() + Dim reference = CreateCSharpCompilation(" +public class Test +{ + public void M(T x) where T : unmanaged {} +} +", parseOptions:=New CSharpParseOptions(CSharp.LanguageVersion.Latest)).EmitToImageReference() + + Dim source = " +public class Program + Shared Sub Main + Dim o As New Test + o.M(new with {.A = 1}) + End Sub +End Class +" + + Dim compilation = CreateCompilation(source, references:={reference}) + AssertTheseDiagnostics(compilation, ' does not satisfy the 'Structure' constraint for type parameter 'T'. + o.M(new with {.A = 1}) + ~ +BC37332: Type argument '' must be a non-nullable value type, along with all fields at any level of nesting, in order to use it as type parameter 'T'. + o.M(new with {.A = 1}) + ~ + ]]>) + End Sub + + + Public Sub UnmanagedCheck_TypedReference() + Dim reference = CreateCSharpCompilation(" +public class Test +{ + public void M(T x) where T : unmanaged {} +} +", parseOptions:=New CSharpParseOptions(CSharp.LanguageVersion.Latest)).EmitToImageReference() + + Dim source = " +public class Program + Shared Sub Main + Dim o As New Test + o.M(CType(Nothing, System.TypedReference)) + End Sub +End Class +" + + Dim compilation = CreateCompilation(source, references:={reference}) + AssertTheseDiagnostics(compilation, ) + End Sub + + + Public Sub UnmanagedCheck_RefStruct() + Dim reference = CreateCSharpCompilation(" +public class Test +{ + public void M(T x) where T : unmanaged, allows ref struct {} + + void Tst() + { + this.M((RefS)default); + } +} + +public ref struct RefS { } +public ref struct RefG { public T field; } +public ref struct Ref { ref int field; } +public ref struct StructWithIndirectRefField +{ + public Ref Field; +} +public ref struct StructWithIndirectRefField2 +{ + public StructWithRefField Field; +} +public ref struct StructWithRefField +{ + public ref T RefField; +} + +", parseOptions:=New CSharpParseOptions(CSharp.LanguageVersion.Latest), referencedAssemblies:=Basic.Reference.Assemblies.Net90.References.All).EmitToImageReference() + + Dim source = " +public class Program + + Shared Sub Main + Dim o As New Test + o.M(CType(Nothing, RefS)) + o.M(CType(Nothing, RefG(Of String))) + o.M(CType(Nothing, Ref)) + o.M(CType(Nothing, StructWithIndirectRefField)) + o.M(CType(Nothing, StructWithIndirectRefField2)) + End Sub +End Class +" + + Dim compilation = CreateCompilation(source, references:={reference}, targetFramework:=TargetFramework.Net90) + AssertTheseDiagnostics(compilation, ) + End Sub + + + Public Sub UnmanagedCheck_Class() + Dim reference = CreateCSharpCompilation(" +public class Test +{ + public void M(T x) where T : unmanaged {} +} +", parseOptions:=New CSharpParseOptions(CSharp.LanguageVersion.Latest)).EmitToImageReference() + + Dim source = " +public class Program + Shared Sub Main + Dim o As New Test + o.M(New Program()) + End Sub +End Class +" + + Dim compilation = CreateCompilation(source, references:={reference}) + AssertTheseDiagnostics(compilation, ) + End Sub + + + Public Sub UnmanagedCheck_StructWithManagedField() + Dim reference = CreateCSharpCompilation(" +public class Test +{ + public void M(T x) where T : unmanaged {} +} +", parseOptions:=New CSharpParseOptions(CSharp.LanguageVersion.Latest)).EmitToImageReference() + + Dim source = " +public class Program + Shared Sub Main + Dim o As New Test + o.M(New S1()) + o.M(New S2()) + o.M(New S3()) + o.M(New S4(Of Integer)()) + o.M(New S4(Of Program)()) + o.M(New S5(Of Program)()) + End Sub +End Class + +Structure S1 + Dim F as Program +End Structure + +Structure S2 + Dim F as Integer +End Structure + +Structure S3 + Shared F as Program +End Structure + +Structure S4(Of T) + Dim F as T +End Structure + +Structure S5(Of T) + Dim F as Integer +End Structure +" + + Dim compilation = CreateCompilation(source, references:={reference}) + AssertTheseDiagnostics(compilation, ) + + Dim s1 = compilation.GetTypeByMetadataName("S1") + Dim s2 = compilation.GetTypeByMetadataName("S2") + Dim s5 = compilation.GetTypeByMetadataName("S5`1") + Assert.Equal(ManagedKind.Managed, s1.GetManagedKind(Nothing)) + Assert.Equal(ManagedKind.Unmanaged, s2.GetManagedKind(Nothing)) + Assert.Equal(ManagedKind.UnmanagedWithGenerics, s5.GetManagedKind(Nothing)) + + Assert.False(DirectCast(s1, INamedTypeSymbol).IsUnmanagedType) + Assert.True(DirectCast(s2, INamedTypeSymbol).IsUnmanagedType) + Assert.True(DirectCast(s5, INamedTypeSymbol).IsUnmanagedType) + + Dim s5T = s5.TypeParameters(0) + Assert.Equal(ManagedKind.Managed, s5T.GetManagedKind(Nothing)) + Assert.False(DirectCast(s5T, ITypeSymbol).IsUnmanagedType) + Assert.False(s5T.HasUnmanagedTypeConstraint) + Assert.False(DirectCast(s5T, ITypeParameterSymbol).HasUnmanagedTypeConstraint) + + Dim mT = compilation.GetTypeByMetadataName("Test").GetMember(Of MethodSymbol)("M").TypeParameters(0) + Assert.Equal(ManagedKind.Unmanaged, mT.GetManagedKind(Nothing)) + Assert.True(DirectCast(mT, ITypeSymbol).IsUnmanagedType) + Assert.True(mT.HasUnmanagedTypeConstraint) + Assert.True(DirectCast(mT, ITypeParameterSymbol).HasUnmanagedTypeConstraint) + End Sub + + + Public Sub UnmanagedCheck_StructWithManagedProperty() + Dim reference = CreateCSharpCompilation(" +public class Test +{ + public void M(T x) where T : unmanaged {} +} +", parseOptions:=New CSharpParseOptions(CSharp.LanguageVersion.Latest)).EmitToImageReference() + + Dim source = " +public class Program + Shared Sub Main + Dim o As New Test + o.M(New S1()) + o.M(New S2()) + End Sub +End Class + +Structure S1 + Property F as Program +End Structure + +Structure S2 + Property F as Integer +End Structure +" + + Dim compilation = CreateCompilation(source, references:={reference}) + AssertTheseDiagnostics(compilation, ) + End Sub + + + Public Sub UnmanagedCheck_StructWithEvent() + Dim reference = CreateCSharpCompilation(" +public class Test +{ + public void M(T x) where T : unmanaged {} +} +", parseOptions:=New CSharpParseOptions(CSharp.LanguageVersion.Latest)).EmitToImageReference() + + Dim source = " +public class Program + Shared Sub Main + Dim o As New Test + o.M(New S1()) + End Sub +End Class + +Structure S1 + Event E as System.Action +End Structure +" + + Dim compilation = CreateCompilation(source, references:={reference}) + AssertTheseDiagnostics(compilation, ) + End Sub + + + Public Sub UnmanagedCheck_StructWithCycle() + Dim reference = CreateCSharpCompilation(" +public class Test +{ + public void M(T x) where T : unmanaged {} +} +", parseOptions:=New CSharpParseOptions(CSharp.LanguageVersion.Latest)).EmitToImageReference() + + Dim source = " +public class Program + Shared Sub Main + Dim o As New Test + o.M(New S1()) + o.M(New S2()) + End Sub +End Class + +Structure S1 + Dim F as S2 +End Structure + +Structure S2 + Dim F as S1 +End Structure +" + + Dim compilation = CreateCompilation(source, references:={reference}) + AssertTheseDiagnostics(compilation, ) + End Sub + + + Public Sub UnmanagedCheck_Tuple() + Dim reference = CreateCSharpCompilation(" +public class Test +{ + public void M(T x) where T : unmanaged {} +} +", parseOptions:=New CSharpParseOptions(CSharp.LanguageVersion.Latest)).EmitToImageReference() + + Dim source = " +public class Program + Shared Sub Main(Of T)(x As T) + Dim o As New Test + o.M((1, 1)) + o.M((1, x)) + o.M((1, ""s"")) + o.M((1, 2, 3, 4, 5, 6, 7, 8, ""s"")) + o.M(new S1()) + o.M(new S2()) + o.M(new S3()) + o.M(new S4(Of T)()) + End Sub +End Class + +Structure S1 + Dim F as (Integer, Integer) +End Structure + +Structure S2 + Dim F as (String, Integer) +End Structure + +Structure S3 + Dim F as (Integer, Integer, Integer, Integer, Integer, Integer, Integer, Integer, String) +End Structure + +Structure S4(Of T) + Dim F as (T, Integer) +End Structure +" + + Dim compilation = CreateCompilation(source, references:={reference}) + AssertTheseDiagnostics(compilation, ) + End Sub + + + Public Sub UnmanagedCheck_Enum() + Dim reference = CreateCSharpCompilation(" +public class Test +{ + public void M(T x) where T : unmanaged {} +} +", parseOptions:=New CSharpParseOptions(CSharp.LanguageVersion.Latest)).EmitToImageReference() + + Dim source = " +public class Program + Shared Sub Main() + Dim o As New Test + o.M(E1.Val) + o.M(new S1()) + End Sub +End Class + +Enum E1 + Val +End Enum + +Structure S1 + Dim F as E1 +End Structure +" + + Dim compilation = CreateCompilation(source, references:={reference}) + compilation.AssertNoDiagnostics() + End Sub + + + Public Sub UnmanagedCheck_Interface() + Dim reference = CreateCSharpCompilation(" +public class Test +{ + public void M(T x) where T : unmanaged {} +} +", parseOptions:=New CSharpParseOptions(CSharp.LanguageVersion.Latest)).EmitToImageReference() + + Dim source = " +public class Program + Shared Sub Main(x As I1) + Dim o As New Test + o.M(x) + o.M(New S2()) + End Sub +End Class + +Public Interface I1 +End Interface + +Structure S2 + Dim F as I1 +End Structure +" + + Dim compilation = CreateCompilation(source, references:={reference}) + AssertTheseDiagnostics(compilation, ) + End Sub + + + Public Sub UnmanagedCheck_Pointer() + Dim reference = CreateCSharpCompilation(" +public class Test +{ + public void M(T x) where T : unmanaged {} + + public static S1 GetS1() => default; + public static S2 GetS2() => default; +} + +unsafe public struct S1 +{ + int* P1; +} + +unsafe public struct S2 +{ + delegate* P1; +} +", + parseOptions:=New CSharpParseOptions(CSharp.LanguageVersion.Latest), + compilationOptions:=New CSharp.CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary).WithAllowUnsafe(True)).EmitToImageReference() + + Dim source = " +public class Program + Shared Sub Main() + Dim o As New Test + o.M(New S1()) + o.M(New S2()) + o.M(Test.GetS1()) + o.M(Test.GetS2()) + End Sub +End Class +" + + Dim compilation = CreateCompilation(source, references:={reference}) + AssertTheseDiagnostics(compilation, ) + End Sub + + + Public Sub UnmanagedCheck_ExpandingTypeArgument_01() + Dim reference = CreateCSharpCompilation(" +public struct YourStruct where T : unmanaged +{ + public T field; +} +", parseOptions:=New CSharpParseOptions(CSharp.LanguageVersion.Latest)).EmitToImageReference() + + Dim source = " +Structure MyStruct(Of T) + Dim field as YourStruct(Of MyStruct(Of MyStruct(Of T))) + Dim s as string +End Structure +" + + Dim compilation = CreateCompilation(source, references:={reference}) + AssertTheseDiagnostics(compilation, ) + End Sub + + + Public Sub UnmanagedCheck_ExpandingTypeArgument_02() + Dim reference = CreateCSharpCompilation(" +public struct YourStruct where T : unmanaged +{ + public T field; +} +", parseOptions:=New CSharpParseOptions(CSharp.LanguageVersion.Latest)).EmitToImageReference() + + Dim source = " +Structure MyStruct(Of T) + Dim s as string + Dim field as YourStruct(Of MyStruct(Of MyStruct(Of T))) +End Structure +" + + Dim compilation = CreateCompilation(source, references:={reference}) + AssertTheseDiagnostics(compilation, ) + End Sub + + + Public Sub UnmanagedCheck_ExpandingTypeArgument_03() + Dim reference = CreateCSharpCompilation(" +public struct YourStruct where T : unmanaged +{ + public T field; +} +", parseOptions:=New CSharpParseOptions(CSharp.LanguageVersion.Latest)).EmitToImageReference() + + Dim source = " +Structure MyStruct(Of T) + Property field as YourStruct(Of MyStruct(Of MyStruct(Of T))) + Dim s as string +End Structure +" + + Dim compilation = CreateCompilation(source, references:={reference}) + AssertTheseDiagnostics(compilation, ) + End Sub + + + Public Sub UnmanagedCheck_ExpandingTypeArgument_04() + Dim reference = CreateCSharpCompilation(" +public struct YourStruct where T : unmanaged +{ + public T field; +} +", parseOptions:=New CSharpParseOptions(CSharp.LanguageVersion.Latest)).EmitToImageReference() + + Dim source = " +Structure MyStruct(Of T) + Dim s as string + Property field as YourStruct(Of MyStruct(Of MyStruct(Of T))) +End Structure +" + + Dim compilation = CreateCompilation(source, references:={reference}) + AssertTheseDiagnostics(compilation, ) + End Sub + + + Public Sub UnmanagedCheck_ExpandingTypeArgument_05() + Dim reference = CreateCSharpCompilation(" +public struct YourStruct where T : unmanaged +{ + public T field; +} +", parseOptions:=New CSharpParseOptions(CSharp.LanguageVersion.Latest)).EmitToImageReference() + + Dim source = " +Structure MyStruct(Of T) + Event field as YourStruct(Of MyStruct(Of MyStruct(Of T))) + Dim s as string +End Structure +" + + Dim compilation = CreateCompilation(source, references:={reference}) + AssertTheseDiagnostics(compilation, ) + End Sub + + + Public Sub UnmanagedCheck_ExpandingTypeArgument_06() + Dim reference = CreateCSharpCompilation(" +public struct YourStruct where T : unmanaged +{ + public T field; +} +", parseOptions:=New CSharpParseOptions(CSharp.LanguageVersion.Latest)).EmitToImageReference() + + Dim source = " +Structure MyStruct(Of T) + Dim s as string + Event field as YourStruct(Of MyStruct(Of MyStruct(Of T))) +End Structure +" + + Dim compilation = CreateCompilation(source, references:={reference}) + AssertTheseDiagnostics(compilation, ) + End Sub + + + Public Sub UnmanagedCheck_ExpandingTypeArgument_07() + Dim reference = CreateCSharpCompilation(" +public struct YourStruct where T : unmanaged +{ + public T field; + string s; +} +", parseOptions:=New CSharpParseOptions(CSharp.LanguageVersion.Latest)).EmitToImageReference() + + Dim source = " +Structure MyStruct(Of T) + Dim field as YourStruct(Of MyStruct(Of MyStruct(Of T))) +End Structure +" + + Dim compilation = CreateCompilation(source, references:={reference}) + AssertTheseDiagnostics(compilation, ) + End Sub + + + Public Sub UnmanagedCheck_ExpandingTypeArgument_08() + Dim reference = CreateCSharpCompilation(" +public struct YourStruct where T : unmanaged +{ + string s; + public T field; +} +", parseOptions:=New CSharpParseOptions(CSharp.LanguageVersion.Latest)).EmitToImageReference() + + Dim source = " +Structure MyStruct(Of T) + Dim field as YourStruct(Of MyStruct(Of MyStruct(Of T))) +End Structure +" + + Dim compilation = CreateCompilation(source, references:={reference}) + AssertTheseDiagnostics(compilation, ) + End Sub + + + Public Sub UnmanagedCheck_ExpandingTypeArgument_09() + Dim reference = CreateCSharpCompilation(" +public struct YourStruct where T : unmanaged +{ + public T field; + string s; +} +", parseOptions:=New CSharpParseOptions(CSharp.LanguageVersion.Latest)).EmitToImageReference() + + Dim source = " +Structure MyStruct(Of T) + Property field as YourStruct(Of MyStruct(Of MyStruct(Of T))) +End Structure +" + + Dim compilation = CreateCompilation(source, references:={reference}) + AssertTheseDiagnostics(compilation, ) + End Sub + + + Public Sub UnmanagedCheck_ExpandingTypeArgument_10() + Dim reference = CreateCSharpCompilation(" +public struct YourStruct where T : unmanaged +{ + string s; + public T field; +} +", parseOptions:=New CSharpParseOptions(CSharp.LanguageVersion.Latest)).EmitToImageReference() + + Dim source = " +Structure MyStruct(Of T) + Property field as YourStruct(Of MyStruct(Of MyStruct(Of T))) +End Structure +" + + Dim compilation = CreateCompilation(source, references:={reference}) + AssertTheseDiagnostics(compilation, ) + End Sub + + + Public Sub UnmanagedCheck_ExpandingTypeArgument_11() + Dim reference = CreateCSharpCompilation(" +public struct YourStruct where T : unmanaged +{ + public T field; + string s; +} +", parseOptions:=New CSharpParseOptions(CSharp.LanguageVersion.Latest)).EmitToImageReference() + + Dim source = " +Structure MyStruct(Of T) + Event field as YourStruct(Of MyStruct(Of MyStruct(Of T))) +End Structure +" + + Dim compilation = CreateCompilation(source, references:={reference}) + AssertTheseDiagnostics(compilation, ) + End Sub + + + Public Sub UnmanagedCheck_ExpandingTypeArgument_12() + Dim reference = CreateCSharpCompilation(" +public struct YourStruct where T : unmanaged +{ + string s; + public T field; +} +", parseOptions:=New CSharpParseOptions(CSharp.LanguageVersion.Latest)).EmitToImageReference() + + Dim source = " +Structure MyStruct(Of T) + Event field as YourStruct(Of MyStruct(Of MyStruct(Of T))) +End Structure +" + + Dim compilation = CreateCompilation(source, references:={reference}) + AssertTheseDiagnostics(compilation, ) + End Sub + + + Public Sub UnmanagedCheck_TypeParameter() + Dim reference = CreateCSharpCompilation(" +public class Test +{ + public void M(T x) where T : unmanaged {} +} +", parseOptions:=New CSharpParseOptions(CSharp.LanguageVersion.Latest)).EmitToImageReference() + + Dim source = " +public class Program(Of T As Structure) + Shared Sub Main + Dim o As New Test + o.M(New T()) + End Sub +End Class +" + + Dim compilation = CreateCompilation(source, references:={reference}) + AssertTheseDiagnostics(compilation, ) + End Sub + + + Public Sub ConsumeAssertEqual() + Dim reference = CreateCSharpCompilation(" +using System; + +public class Assert +{ + public static void Equal( + T[] expected, + T[] actual) + where T : unmanaged, IEquatable + { + System.Console.Write(""T[]""); + } + + public static void Equal( + T expected, + T actual) + { + System.Console.Write(""T""); + } +} +", parseOptions:=New CSharpParseOptions(CSharp.LanguageVersion.Latest)).EmitToImageReference() + + Dim source = " +public class Program + Shared Sub Main + Assert.Equal(New Integer() {1, 2}, New Integer() {1, 2}) + Assert.Equal(New String() {1, 2}, New String() {1, 2}) + End Sub +End Class +" + + Dim compilation = CreateCompilation(source, references:={reference}, options:=TestOptions.DebugExe) + CompileAndVerify(compilation, expectedOutput:="T[]T").VerifyDiagnostics() + + compilation = CreateCompilation(source, references:={reference}, options:=TestOptions.DebugExe, parseOptions:=TestOptions.Regular17_13) + CompileAndVerify(compilation, expectedOutput:="T[]T").VerifyDiagnostics() + + compilation = CreateCompilation(source, references:={reference}, options:=TestOptions.DebugExe, parseOptions:=TestOptions.Regular16_9) + compilation.AssertTheseDiagnostics( +BC36716: Visual Basic 16.9 does not support recognizing 'unmanaged' constraint. + Assert.Equal(New Integer() {1, 2}, New Integer() {1, 2}) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +BC36716: Visual Basic 16.9 does not support recognizing 'unmanaged' constraint. + Assert.Equal(New String() {1, 2}, New String() {1, 2}) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ) + End Sub + + + Public Sub ConsumeExtensionMethod() + Dim reference = CreateCSharpCompilation(" +using System; + +public static class Assert +{ + public static void Equal( + this T[] expected, + T[] actual) + where T : unmanaged, IEquatable + { + System.Console.Write(""T[]""); + } + + public static void Equal( + this T expected, + T actual) + { + System.Console.Write(""T""); + } +} +", parseOptions:=New CSharpParseOptions(CSharp.LanguageVersion.Latest)).EmitToImageReference() + + Dim source = " +public class Program + Shared Sub Main + Call New Integer() {1, 2}.Equal(New Integer() {1, 2}) + Call New String() {1, 2}.Equal(New String() {1, 2}) + End Sub +End Class +" + + Dim compilation = CreateCompilation(source, references:={reference}, options:=TestOptions.DebugExe) + CompileAndVerify(compilation, expectedOutput:="T[]T").VerifyDiagnostics() + + compilation = CreateCompilation(source, references:={reference}, options:=TestOptions.DebugExe, parseOptions:=TestOptions.Regular17_13) + CompileAndVerify(compilation, expectedOutput:="T[]T").VerifyDiagnostics() + + compilation = CreateCompilation(source, references:={reference}, options:=TestOptions.DebugExe, parseOptions:=TestOptions.Regular16_9) + CompileAndVerify(compilation, expectedOutput:="TT").VerifyDiagnostics() + End Sub + + Private Const IsUnmanagedAttributeIL As String = " +.assembly extern mscorlib +{ + .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) + .ver 4:0:0:0 +} +.assembly Test +{ + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 ) + .custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78 63 65 70 74 69 6F 6E 54 68 72 6F 77 73 01 ) + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.module Test.dll +.imagebase 0x10000000 +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 +.corflags 0x00000001 + +.class private auto ansi sealed beforefieldinit System.Runtime.CompilerServices.IsUnmanagedAttribute + extends [mscorlib]System.Attribute +{ + .method public hidebysig specialname rtspecialname + instance void .ctor() cil managed + { + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [mscorlib]System.Attribute::.ctor() + IL_0006: nop + IL_0007: ret + } +} +" + + 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 55b4f53ca80d4..a2de7b87fbc9a 100644 --- a/src/ExpressionEvaluator/VisualBasic/Source/ExpressionCompiler/Symbols/EETypeParameterSymbol.vb +++ b/src/ExpressionEvaluator/VisualBasic/Source/ExpressionCompiler/Symbols/EETypeParameterSymbol.vb @@ -118,5 +118,11 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExpressionEvaluator Return InternalSubstituteTypeParametersDistinct(substitution, constraintTypes) End Get End Property + + Friend Overrides ReadOnly Property HasUnmanagedTypeConstraint As Boolean + Get + Return _sourceTypeParameterSymbol.HasUnmanagedTypeConstraint + End Get + End Property End Class End Namespace diff --git a/src/ExpressionEvaluator/VisualBasic/Source/ExpressionCompiler/Symbols/SimpleTypeParameterSymbol.vb b/src/ExpressionEvaluator/VisualBasic/Source/ExpressionCompiler/Symbols/SimpleTypeParameterSymbol.vb index 81adcbcdf74f0..c72350f30684f 100644 --- a/src/ExpressionEvaluator/VisualBasic/Source/ExpressionCompiler/Symbols/SimpleTypeParameterSymbol.vb +++ b/src/ExpressionEvaluator/VisualBasic/Source/ExpressionCompiler/Symbols/SimpleTypeParameterSymbol.vb @@ -88,6 +88,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExpressionEvaluator End Get End Property + Friend Overrides ReadOnly Property HasUnmanagedTypeConstraint As Boolean + Get + Return False + End Get + End Property + Public Overrides ReadOnly Property Locations As ImmutableArray(Of Location) Get Throw ExceptionUtilities.Unreachable From cbf6e395eaf9c61171c6c9e4c0049a31b5ca953a Mon Sep 17 00:00:00 2001 From: AlekseyTs Date: Thu, 31 Oct 2024 09:10:47 -0700 Subject: [PATCH 2/4] PR feedback --- .../Emit2/Emit/UnmanagedTypeModifierTests.cs | 64 +++++++++++++++++ .../Core/Portable/Binding/UseSiteInfo.cs | 30 ++++---- .../Symbols/INamedTypeSymbolInternal.cs | 2 +- .../Portable/Symbols/NamedTypeSymbol.vb | 32 ++++----- .../UnmanagedTypeConstraintTests.vb | 68 +++++++++++++++++++ 5 files changed, 163 insertions(+), 33 deletions(-) diff --git a/src/Compilers/CSharp/Test/Emit2/Emit/UnmanagedTypeModifierTests.cs b/src/Compilers/CSharp/Test/Emit2/Emit/UnmanagedTypeModifierTests.cs index 3436b9a10cb13..dfc1fbea048ae 100644 --- a/src/Compilers/CSharp/Test/Emit2/Emit/UnmanagedTypeModifierTests.cs +++ b/src/Compilers/CSharp/Test/Emit2/Emit/UnmanagedTypeModifierTests.cs @@ -282,6 +282,70 @@ public static void Main() ); } + [Fact] + [WorkItem("https://github.com/dotnet/roslyn/issues/75681")] + public void LoadingUnmanagedTypeModifier_ModreqGeneric() + { + var ilSource = IsUnmanagedAttributeIL + @" +.class public auto ansi beforefieldinit TestRef + extends [mscorlib]System.Object +{ + .method public hidebysig instance void + M1() cil managed + { + .param type T + .custom instance void System.Runtime.CompilerServices.IsUnmanagedAttribute::.ctor() = ( 01 00 00 00 ) + // Code size 2 (0x2) + .maxstack 8 + IL_0000: nop + IL_0001: ret + } // end of method TestRef::M1 + + .method public hidebysig specialname rtspecialname + instance void .ctor() cil managed + { + // Code size 8 (0x8) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [mscorlib]System.Object::.ctor() + IL_0006: nop + IL_0007: ret + } // end of method TestRef::.ctor +} + +.class public auto ansi beforefieldinit System.Runtime.InteropServices.UnmanagedType`1 + extends [mscorlib]System.Object +{ + .method public hidebysig specialname rtspecialname + instance void .ctor () cil managed + { + .maxstack 8 + + IL_0000: ldarg.0 + IL_0001: call instance void [mscorlib]System.Object::.ctor() + IL_0006: ret + } +} +"; + + var reference = CompileIL(ilSource, prependDefaultHeader: false); + + var code = @" +public class Test +{ + public static void Main() + { + var obj = new TestRef(); + + obj.M1(); + } +}"; + + CreateCompilation(code, references: new[] { reference }).VerifyDiagnostics( + // An error is expected here, see https://github.com/dotnet/roslyn/issues/75681 + ); + } + [Fact] public void LoadingUnmanagedTypeModifier_AttributeWithoutModreq() { diff --git a/src/Compilers/Core/Portable/Binding/UseSiteInfo.cs b/src/Compilers/Core/Portable/Binding/UseSiteInfo.cs index 7216e11b68097..23ff99760ba72 100644 --- a/src/Compilers/Core/Portable/Binding/UseSiteInfo.cs +++ b/src/Compilers/Core/Portable/Binding/UseSiteInfo.cs @@ -270,14 +270,21 @@ public void AddDiagnostics(ICollection? diagnostics) foreach (var diagnosticInfo in diagnostics) { - if (_diagnostics.Add(diagnosticInfo) && diagnosticInfo?.Severity == DiagnosticSeverity.Error) - { - RecordPresenceOfAnError(); - } + AccumulateDiagnosticInfoAndRecordPresenceOfAnError(diagnosticInfo); } } } + private void AccumulateDiagnosticInfoAndRecordPresenceOfAnError(DiagnosticInfo diagnosticInfo) + { + Debug.Assert(_diagnostics is not null); + + if (_diagnostics.Add(diagnosticInfo) && diagnosticInfo?.Severity == DiagnosticSeverity.Error) + { + RecordPresenceOfAnError(); + } + } + public void AddDiagnostics(IReadOnlyCollection? diagnostics) { if (!AccumulatesDiagnostics) @@ -291,10 +298,7 @@ public void AddDiagnostics(IReadOnlyCollection? diagnostics) foreach (var diagnosticInfo in diagnostics) { - if (_diagnostics.Add(diagnosticInfo) && diagnosticInfo?.Severity == DiagnosticSeverity.Error) - { - RecordPresenceOfAnError(); - } + AccumulateDiagnosticInfoAndRecordPresenceOfAnError(diagnosticInfo); } } } @@ -312,10 +316,7 @@ public void AddDiagnostics(ImmutableArray diagnostics) foreach (var diagnosticInfo in diagnostics) { - if (_diagnostics.Add(diagnosticInfo) && diagnosticInfo?.Severity == DiagnosticSeverity.Error) - { - RecordPresenceOfAnError(); - } + AccumulateDiagnosticInfoAndRecordPresenceOfAnError(diagnosticInfo); } } } @@ -329,10 +330,7 @@ public void AddDiagnosticInfo(DiagnosticInfo diagnosticInfo) _diagnostics ??= new HashSet(); - if (_diagnostics.Add(diagnosticInfo) && diagnosticInfo?.Severity == DiagnosticSeverity.Error) - { - RecordPresenceOfAnError(); - } + AccumulateDiagnosticInfoAndRecordPresenceOfAnError(diagnosticInfo); } public void AddDependencies(UseSiteInfo info) diff --git a/src/Compilers/Core/Portable/Symbols/INamedTypeSymbolInternal.cs b/src/Compilers/Core/Portable/Symbols/INamedTypeSymbolInternal.cs index 5cea8316655f0..31e9f10ee96d6 100644 --- a/src/Compilers/Core/Portable/Symbols/INamedTypeSymbolInternal.cs +++ b/src/Compilers/Core/Portable/Symbols/INamedTypeSymbolInternal.cs @@ -21,7 +21,7 @@ internal interface INamedTypeSymbolInternal : ITypeSymbolInternal /// /// True if this type or some containing type has type parameters. /// - public bool IsGenericType { get; } + bool IsGenericType { get; } internal static class Helpers { diff --git a/src/Compilers/VisualBasic/Portable/Symbols/NamedTypeSymbol.vb b/src/Compilers/VisualBasic/Portable/Symbols/NamedTypeSymbol.vb index 95a55ad1a04bf..a53d61af4aade 100644 --- a/src/Compilers/VisualBasic/Portable/Symbols/NamedTypeSymbol.vb +++ b/src/Compilers/VisualBasic/Portable/Symbols/NamedTypeSymbol.vb @@ -1199,22 +1199,22 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols Return GetManagedKind(Me, useSiteInfo) End Function - ' - ' IsManagedType is simple for most named types: - ' enums are not managed; - ' non-enum, non-struct named types are managed; - ' type parameters are managed unless an 'unmanaged' constraint is present; - ' all special types have spec'd values (basically, (non-string) primitives) are not managed; - ' - ' Only structs are complicated, because the definition is recursive. A struct type is managed - ' if one of its instance fields is managed or a ref field. Unfortunately, this can result in infinite recursion. - ' If the closure is finite, and we don't find anything definitely managed, then we return true. - ' If the closure is infinite, we disregard all but a representative of any expanding cycle. - ' - ' Intuitively, this will only return true if there's a specific type we can point to that is would - ' be managed even if it had no fields. e.g. struct S { S s; } is not managed, but struct S { S s; object o; } - ' is because we can point to object. - ' + ''' + ''' is simple for most named types: + ''' enums are not managed; + ''' non-enum, non-struct named types are managed; + ''' type parameters are managed unless an 'unmanaged' constraint is present; + ''' all special types have spec'd values (basically, (non-string) primitives) are not managed; + ''' + ''' Only structs are complicated, because the definition is recursive. A struct type is managed + ''' if one of its instance fields is managed or a ref field. Unfortunately, this can result in infinite recursion. + ''' If the closure is finite, and we don't find anything definitely managed, then we return true. + ''' If the closure is infinite, we disregard all but a representative of any expanding cycle. + ''' + ''' Intuitively, this will only return true if there's a specific type we can point to that is would + ''' be managed even if it had no fields. e.g. struct S { S s; } is not managed, but struct S { S s; object o; } + ''' is because we can point to object. + ''' Private Overloads Shared Function GetManagedKind(type As NamedTypeSymbol, ByRef useSiteInfo As CompoundUseSiteInfo(Of AssemblySymbol)) As ManagedKind type = DirectCast(type.GetTupleUnderlyingTypeOrSelf(), NamedTypeSymbol) diff --git a/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/UnmanagedTypeConstraintTests.vb b/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/UnmanagedTypeConstraintTests.vb index c905d7ae28a0d..ab86f7a1774df 100644 --- a/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/UnmanagedTypeConstraintTests.vb +++ b/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/UnmanagedTypeConstraintTests.vb @@ -272,6 +272,74 @@ BC30649: 'T' is an unsupported type. ) End Sub + + Public Sub LoadingUnmanagedTypeModifier_ModreqGeneric() + + Dim ilSource = IsUnmanagedAttributeIL + " +.class public auto ansi beforefieldinit TestRef + extends [mscorlib]System.Object +{ + .method public hidebysig instance void + M1() cil managed + { + .param type T + .custom instance void System.Runtime.CompilerServices.IsUnmanagedAttribute::.ctor() = ( 01 00 00 00 ) + // Code size 2 (0x2) + .maxstack 8 + IL_0000: nop + IL_0001: ret + } // end of method TestRef::M1 + + .method public hidebysig specialname rtspecialname + instance void .ctor() cil managed + { + // Code size 8 (0x8) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [mscorlib]System.Object::.ctor() + IL_0006: nop + IL_0007: ret + } // end of method TestRef::.ctor +} + +.class public auto ansi beforefieldinit System.Runtime.InteropServices.UnmanagedType`1 + extends [mscorlib]System.Object +{ + .method public hidebysig specialname rtspecialname + instance void .ctor () cil managed + { + .maxstack 8 + + IL_0000: ldarg.0 + IL_0001: call instance void [mscorlib]System.Object::.ctor() + IL_0006: ret + } +} +" + + Dim reference = CompileIL(ilSource, prependDefaultHeader:=False) + + Dim code = " +public class Test + public shared sub Main() + Dim obj = new TestRef() + + obj.M1(Of Integer)() + end sub +end class +" + + CreateCompilation(code, references:={reference}). + AssertTheseDiagnostics( +BC30649: '' is an unsupported type. + obj.M1(Of Integer)() + ~~~~~~~~~~~~~~~~~~~~ +BC30649: 'T' is an unsupported type. + obj.M1(Of Integer)() + ~~~~~~~~~~~~~~~~~~~~ + ) + End Sub + Public Sub LoadingUnmanagedTypeModifier_AttributeWithoutModreq() From c18e05901ae45b7474c6aeed3201b294db939f96 Mon Sep 17 00:00:00 2001 From: AlekseyTs Date: Thu, 31 Oct 2024 10:16:04 -0700 Subject: [PATCH 3/4] Adjust tests --- .../UnmanagedTypeConstraintTests.vb | 30 +++++++++++++++---- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/UnmanagedTypeConstraintTests.vb b/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/UnmanagedTypeConstraintTests.vb index ab86f7a1774df..8730118939182 100644 --- a/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/UnmanagedTypeConstraintTests.vb +++ b/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/UnmanagedTypeConstraintTests.vb @@ -1037,13 +1037,19 @@ BC37332: Type argument 'S4(Of Program)' must be a non-nullable value type, along Dim s1 = compilation.GetTypeByMetadataName("S1") Dim s2 = compilation.GetTypeByMetadataName("S2") + Dim s3 = compilation.GetTypeByMetadataName("S3") + Dim s4 = compilation.GetTypeByMetadataName("S4`1") Dim s5 = compilation.GetTypeByMetadataName("S5`1") Assert.Equal(ManagedKind.Managed, s1.GetManagedKind(Nothing)) Assert.Equal(ManagedKind.Unmanaged, s2.GetManagedKind(Nothing)) + Assert.Equal(ManagedKind.Unmanaged, s3.GetManagedKind(Nothing)) + Assert.Equal(ManagedKind.Managed, s4.GetManagedKind(Nothing)) Assert.Equal(ManagedKind.UnmanagedWithGenerics, s5.GetManagedKind(Nothing)) Assert.False(DirectCast(s1, INamedTypeSymbol).IsUnmanagedType) Assert.True(DirectCast(s2, INamedTypeSymbol).IsUnmanagedType) + Assert.True(DirectCast(s3, INamedTypeSymbol).IsUnmanagedType) + Assert.False(DirectCast(s4, INamedTypeSymbol).IsUnmanagedType) Assert.True(DirectCast(s5, INamedTypeSymbol).IsUnmanagedType) Dim s5T = s5.TypeParameters(0) @@ -1719,18 +1725,32 @@ public class Test ", parseOptions:=New CSharpParseOptions(CSharp.LanguageVersion.Latest)).EmitToImageReference() Dim source = " -public class Program(Of T As Structure) - Shared Sub Main +public class Program + Shared Sub Main(Of T1, T2 As Class, T3 As Structure)(x1 as T1, x2 As T2, x3 As T3) Dim o As New Test - o.M(New T()) + o.M(x1) + o.M(x2) + o.M(x3) End Sub End Class " Dim compilation = CreateCompilation(source, references:={reference}) AssertTheseDiagnostics(compilation, ) End Sub From 57147d9e280ea0d789f84096d58d3b09c2cb8976 Mon Sep 17 00:00:00 2001 From: AlekseyTs Date: Fri, 1 Nov 2024 14:30:54 -0700 Subject: [PATCH 4/4] PR feedback --- .../Portable/Symbols/Metadata/PE/PETypeParameterSymbol.cs | 2 +- src/Compilers/VisualBasic/Portable/Semantics/Conversions.vb | 2 +- .../Portable/Symbols/Metadata/PE/PETypeParameterSymbol.vb | 5 ++++- .../VisualBasic/Portable/Symbols/NamedTypeSymbol.vb | 2 +- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PETypeParameterSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PETypeParameterSymbol.cs index a584624035ce3..ae6accbadf890 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PETypeParameterSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PETypeParameterSymbol.cs @@ -230,7 +230,7 @@ private ImmutableArray GetDeclaredConstraintTypes(ConsList< } // - presence of unmanaged pattern has to be matched with `valuetype` - // - IsUnmanagedAttribute is allowed iff there is an unmanaged pattern + // - IsUnmanagedAttribute is allowed if there is an unmanaged pattern if (hasUnmanagedModreqPattern && (_flags & GenericParameterAttributes.NotNullableValueTypeConstraint) == 0 || hasUnmanagedModreqPattern != peModule.HasIsUnmanagedAttribute(_handle)) { diff --git a/src/Compilers/VisualBasic/Portable/Semantics/Conversions.vb b/src/Compilers/VisualBasic/Portable/Semantics/Conversions.vb index ba8e9d9e0e956..568685e8b4627 100644 --- a/src/Compilers/VisualBasic/Portable/Semantics/Conversions.vb +++ b/src/Compilers/VisualBasic/Portable/Semantics/Conversions.vb @@ -2032,7 +2032,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic While candidate IsNot Nothing If ConstraintsHelper.CheckConstraints(constructedSymbol:=Nothing, - LanguageVersion.Latest, ' Classifying conversions from/to type parameters. This is meaningful only when they are and their constraints are declared in source + LanguageVersion.Latest, ' Classifying conversions from/to type parameters. This is meaningful only when they and their constraints are declared in source substitution:=Nothing, typeParameter:=typeParam, typeArgument:=candidate, diff --git a/src/Compilers/VisualBasic/Portable/Symbols/Metadata/PE/PETypeParameterSymbol.vb b/src/Compilers/VisualBasic/Portable/Symbols/Metadata/PE/PETypeParameterSymbol.vb index 65bb824fcae7c..e1d387a2b4924 100644 --- a/src/Compilers/VisualBasic/Portable/Symbols/Metadata/PE/PETypeParameterSymbol.vb +++ b/src/Compilers/VisualBasic/Portable/Symbols/Metadata/PE/PETypeParameterSymbol.vb @@ -226,7 +226,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols.Metadata.PE End If ' - presence of unmanaged pattern has to be matched with `valuetype` - ' - IsUnmanagedAttribute is allowed iff there is an unmanaged pattern + ' - IsUnmanagedAttribute is allowed if there is an unmanaged pattern If (hasUnmanagedModreqPattern AndAlso (_flags And GenericParameterAttributes.NotNullableValueTypeConstraint) = 0) OrElse hasUnmanagedModreqPattern <> moduleSymbol.Module.HasIsUnmanagedAttribute(_handle) Then ' we do not recognize these combinations as "unmanaged" @@ -355,6 +355,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols.Metadata.PE _lazyCachedBoundsUseSiteInfo.InterlockedInitializeFromSentinel(primaryDependency, useSiteInfo) _lazyHasIsUnmanagedConstraint = hasUnmanagedModreqPattern.ToThreeState() + + ' Note, we are relying on the fact that _lazyConstraintTypes is initialized last, and + ' we depend on the memory barrier from this interlocked operation to prevent write reordering ImmutableInterlocked.InterlockedInitialize(_lazyConstraintTypes, GetConstraintTypesOnly(constraints)) End If diff --git a/src/Compilers/VisualBasic/Portable/Symbols/NamedTypeSymbol.vb b/src/Compilers/VisualBasic/Portable/Symbols/NamedTypeSymbol.vb index a53d61af4aade..b983ef0e1e1e1 100644 --- a/src/Compilers/VisualBasic/Portable/Symbols/NamedTypeSymbol.vb +++ b/src/Compilers/VisualBasic/Portable/Symbols/NamedTypeSymbol.vb @@ -1218,7 +1218,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols Private Overloads Shared Function GetManagedKind(type As NamedTypeSymbol, ByRef useSiteInfo As CompoundUseSiteInfo(Of AssemblySymbol)) As ManagedKind type = DirectCast(type.GetTupleUnderlyingTypeOrSelf(), NamedTypeSymbol) - ' The code below is a clone of BaseTypeAnalysis.GetManagedKind from C# it should be kept in sync going forward + ' The code below is a clone of BaseTypeAnalysis.GetManagedKind from C#. It should be kept in sync going forward Dim managedInfo = INamedTypeSymbolInternal.Helpers.IsManagedTypeHelper(type) Dim definitelyManaged = (managedInfo.isManaged = ThreeState.True)