/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/Compilers/VisualBasic/Portable/Symbols/ConstraintsHelper.vb
1 256 строк
69 KB
AlekseyTs
VB: Recognize and check an `unmanaged` constraint (#75665)
06 ноя 2024, 01:45
Не верифицирован
06 ноя 2024, 01:45
f97c50e
Код
Авторство
О чём код?
' 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.Collections.Immutable Imports System.Diagnostics Imports System.Runtime.CompilerServices Imports System.Runtime.InteropServices Imports Microsoft.CodeAnalysis.PooledObjects Imports Microsoft.CodeAnalysis.Text Imports Microsoft.CodeAnalysis.VisualBasic.Symbols Imports Microsoft.CodeAnalysis.VisualBasic.Syntax Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols ''' <summary> ''' A tuple of TypeParameterSymbol and DiagnosticInfo, created for errors ''' reported from ConstraintsHelper rather than creating Diagnostics directly. ''' This decouples constraints checking from syntax and Locations, and supports ''' callers that may want to create Location instances lazily or not at all. ''' </summary> Friend Structure TypeParameterDiagnosticInfo Public Sub New(typeParameter As TypeParameterSymbol, useSiteInfo As UseSiteInfo(Of AssemblySymbol)) Me.TypeParameter = typeParameter Me.UseSiteInfo = useSiteInfo End Sub Public Sub New(typeParameter As TypeParameterSymbol, diagnostic As DiagnosticInfo) Me.New(typeParameter, New UseSiteInfo(Of AssemblySymbol)(diagnostic)) End Sub Public Sub New(typeParameter As TypeParameterSymbol, constraint As TypeParameterConstraint, diagnostic As DiagnosticInfo) Me.New(typeParameter, diagnostic) Me.Constraint = constraint End Sub Public ReadOnly TypeParameter As TypeParameterSymbol Public ReadOnly Constraint As TypeParameterConstraint Public ReadOnly UseSiteInfo As UseSiteInfo(Of AssemblySymbol) End Structure <Flags()> Friend Enum DirectConstraintConflictKind None = 0 DuplicateTypeConstraint = 1 << 0 RedundantConstraint = 1 << 1 All = (1 << 2) - 1 End Enum ''' <summary> ''' Helper methods for generic type parameter constraints. There are two sets of methods: one ''' set for resolving constraint "bounds" (that is, determining the effective base type, interface set, ''' etc.), and another set for checking for constraint violations in type and method references. ''' ''' Bounds are resolved by calling one of the ResolveBounds overloads. Typically bounds are ''' resolved by each TypeParameterSymbol at, or before, one of the corresponding properties ''' (BaseType, Interfaces, etc.) is accessed. Resolving bounds may result in errors (cycles, ''' inconsistent constraints, etc.) and it is the responsibility of the caller to report any such ''' errors as declaration errors or use-site errors (depending on whether the type parameter ''' was from source or metadata) and to ensure bounds are resolved for source type parameters ''' even if the corresponding properties are never accessed directly. ''' ''' Constraints are checked by calling one of the CheckConstraints or CheckAllConstraints ''' overloads for any generic type or method reference from source. In some circumstances, ''' references are checked at the time the generic type or generic method is bound and constructed ''' by the Binder. In those case, it is sufficient to call one of the CheckConstraints overloads ''' since compound types (such as A(Of T).B(Of U) or A(Of B(Of T))) are checked incrementally ''' as each part is bound. In other cases however, constraint checking needs to be delayed to ''' prevent cycles where checking constraints requires binding the syntax that is currently ''' being bound (such as the constraint in Class C(Of T As C(Of T)). In those cases, the caller ''' must lazily check constraints, and since the types may be compound types, it is necessary ''' to call CheckAllConstraints. ''' </summary> Friend Module ConstraintsHelper ''' <summary> ''' Enum used internally by RemoveDirectConstraintConflicts to ''' track what type constraint has been seen, to report conflicts ''' between { 'Structure', 'Class', [explicit type] }. The 'New' ''' constraint does not need to be tracked for those conflicts. ''' </summary> Private Enum DirectTypeConstraintKind None ReferenceTypeConstraint ValueTypeConstraint ExplicitType End Enum ''' <summary> ''' Return the constraints for the type parameter with any cycles ''' or conflicting constraints reported as errors and removed. ''' </summary> <Extension()> Public Function RemoveDirectConstraintConflicts( typeParameter As TypeParameterSymbol, constraints As ImmutableArray(Of TypeParameterConstraint), inProgress As ConsList(Of TypeParameterSymbol), reportConflicts As DirectConstraintConflictKind, diagnosticsBuilder As ArrayBuilder(Of TypeParameterDiagnosticInfo)) As ImmutableArray(Of TypeParameterConstraint) If constraints.Length > 0 Then Dim constraintsBuilder = ArrayBuilder(Of TypeParameterConstraint).GetInstance() Dim containingSymbol = typeParameter.ContainingSymbol Dim explicitKind = DirectTypeConstraintKind.None Dim reportRedundantConstraints = (reportConflicts And DirectConstraintConflictKind.RedundantConstraint) <> 0 For Each constraint In constraints ' See Bindable::ValidateDirectConstraint. Select Case constraint.Kind Case TypeParameterConstraintKind.ReferenceType If reportRedundantConstraints Then If explicitKind = DirectTypeConstraintKind.None Then explicitKind = DirectTypeConstraintKind.ReferenceTypeConstraint Else ' Combinations of {Class, Structure} should have ' been caught and discarded during binding. Debug.Assert(explicitKind = DirectTypeConstraintKind.ExplicitType) ' "'Class' constraint and a specific class type constraint cannot be combined." diagnosticsBuilder.Add(New TypeParameterDiagnosticInfo(typeParameter, constraint, ErrorFactory.ErrorInfo(ERRID.ERR_RefAndClassTypeConstrCombined))) Continue For End If End If Case TypeParameterConstraintKind.ValueType If reportRedundantConstraints Then If explicitKind = DirectTypeConstraintKind.None Then explicitKind = DirectTypeConstraintKind.ValueTypeConstraint Else ' Combinations of {Class, Structure} should have ' been caught and discarded during binding. Debug.Assert(explicitKind = DirectTypeConstraintKind.ExplicitType) ' "'Structure' constraint and a specific class type constraint cannot be combined." diagnosticsBuilder.Add(New TypeParameterDiagnosticInfo(typeParameter, constraint, ErrorFactory.ErrorInfo(ERRID.ERR_ValueAndClassTypeConstrCombined))) Continue For End If End If Case TypeParameterConstraintKind.None Dim constraintType = constraint.TypeConstraint Dim duplicate As Boolean = ContainsTypeConstraint(constraintsBuilder, constraintType) ' Check for duplicate type constraints. If duplicate Then If (reportConflicts And DirectConstraintConflictKind.DuplicateTypeConstraint) <> 0 Then ' "Constraint type '{0}' already specified for this type parameter.' diagnosticsBuilder.Add(New TypeParameterDiagnosticInfo(typeParameter, constraint, ErrorFactory.ErrorInfo(ERRID.ERR_ConstraintAlreadyExists1, constraintType))) End If ' Continue with other checks for this constraint type, even ' though it's a duplicate, for consistency with Dev10. End If Select Case constraintType.TypeKind Case TypeKind.Class If reportRedundantConstraints Then Select Case explicitKind Case DirectTypeConstraintKind.None Dim classType = DirectCast(constraintType, NamedTypeSymbol) If classType.IsNotInheritable Then ' "Type constraint cannot be a 'NotInheritable' class." diagnosticsBuilder.Add(New TypeParameterDiagnosticInfo(typeParameter, constraint, ErrorFactory.ErrorInfo(ERRID.ERR_ClassConstraintNotInheritable1))) Else Select Case constraintType.SpecialType Case SpecialType.System_Object, SpecialType.System_ValueType, SpecialType.System_Enum, SpecialType.System_Delegate, SpecialType.System_MulticastDelegate, SpecialType.System_Array ' "'{0}' cannot be used as a type constraint." diagnosticsBuilder.Add(New TypeParameterDiagnosticInfo(typeParameter, constraint, ErrorFactory.ErrorInfo(ERRID.ERR_ConstraintIsRestrictedType1, constraintType))) End Select End If explicitKind = DirectTypeConstraintKind.ExplicitType Case DirectTypeConstraintKind.ReferenceTypeConstraint ' "'Class' constraint and a specific class type constraint cannot be combined." diagnosticsBuilder.Add(New TypeParameterDiagnosticInfo(typeParameter, constraint, ErrorFactory.ErrorInfo(ERRID.ERR_RefAndClassTypeConstrCombined))) Continue For Case DirectTypeConstraintKind.ValueTypeConstraint ' "'Structure' constraint and a specific class type constraint cannot be combined." diagnosticsBuilder.Add(New TypeParameterDiagnosticInfo(typeParameter, constraint, ErrorFactory.ErrorInfo(ERRID.ERR_ValueAndClassTypeConstrCombined))) Continue For Case DirectTypeConstraintKind.ExplicitType ' "Type parameter '{0}' can only have one constraint that is a class." diagnosticsBuilder.Add(New TypeParameterDiagnosticInfo(typeParameter, constraint, ErrorFactory.ErrorInfo(ERRID.ERR_MultipleClassConstraints1, typeParameter))) Continue For End Select End If Case TypeKind.Interface, TypeKind.Error Case TypeKind.Module ' No error reported for Module. If the type reference was in source, BC30371 ' ERR_ModuleAsType1 will have been reported binding the type reference. Case TypeKind.TypeParameter Dim constraintTypeParameter = DirectCast(constraintType, TypeParameterSymbol) If constraintTypeParameter.ContainingSymbol = containingSymbol Then ' The constraint type parameter is from the same containing type or method. If inProgress.ContainsReference(constraintTypeParameter) Then ' "Type parameter '{0}' cannot be constrained to itself: {1}" diagnosticsBuilder.Add(New TypeParameterDiagnosticInfo(constraintTypeParameter, constraint, ErrorFactory.ErrorInfo(ERRID.ERR_ConstraintCycle2, constraintTypeParameter, GetConstraintCycleInfo(inProgress)))) Continue For Else ' Traverse constraint type parameter constraints to detect cycles. constraintTypeParameter.ResolveConstraints(inProgress) End If End If If reportRedundantConstraints AndAlso constraintTypeParameter.HasValueTypeConstraint Then ' "Type parameter with a 'Structure' constraint cannot be used as a constraint." diagnosticsBuilder.Add(New TypeParameterDiagnosticInfo(constraintTypeParameter, constraint, ErrorFactory.ErrorInfo(ERRID.ERR_TypeParamWithStructConstAsConst))) Continue For End If Case TypeKind.Array, TypeKind.Delegate, TypeKind.Enum, TypeKind.Structure If reportRedundantConstraints Then ' "Type constraint '{0}' must be either a class, interface or type parameter." diagnosticsBuilder.Add(New TypeParameterDiagnosticInfo(typeParameter, constraint, ErrorFactory.ErrorInfo(ERRID.ERR_ConstNotClassInterfaceOrTypeParam1, constraintType))) End If Case Else Throw ExceptionUtilities.UnexpectedValue(constraintType.TypeKind) End Select If duplicate Then Continue For End If End Select constraintsBuilder.Add(constraint) Next If constraintsBuilder.Count <> constraints.Length Then constraints = constraintsBuilder.ToImmutable() End If constraintsBuilder.Free() End If Return constraints End Function ' Currently, this method should be called for SourceTypeParameterSymbols ' only, not PETypeParameterSymbols. If that changes, and this method is ' called for type parameters from metadata, we need to ensure a use-site ' error is generated if conflicts are found. Add a unit test if that's the case. ' See Bindable::ValidateIndirectConstraints. <Extension()> Public Sub ReportIndirectConstraintConflicts( typeParameter As SourceTypeParameterSymbol, diagnosticsBuilder As ArrayBuilder(Of TypeParameterDiagnosticInfo), <[In], Out> ByRef useSiteDiagnosticsBuilder As ArrayBuilder(Of TypeParameterDiagnosticInfo)) Dim constraints = ArrayBuilder(Of TypeParameterAndConstraint).GetInstance() typeParameter.GetAllConstraints(constraints, fromConstraintOpt:=Nothing) Dim n = constraints.Count For i = 0 To n - 1 Dim pair1 = constraints(i) If pair1.IsBad Then Continue For End If For j = i + 1 To n - 1 Dim pair2 = constraints(j) If pair2.IsBad Then Continue For End If Dim bad = False Dim useSiteInfo As New CompoundUseSiteInfo(Of AssemblySymbol)(typeParameter.ContainingAssembly) If (pair1.TypeParameter Is typeParameter) AndAlso (pair2.TypeParameter Is typeParameter) Then ' Check direct constraints to handle inherited constraints on overridden methods. If HasConflict(pair1.Constraint, pair2.Constraint, useSiteInfo) Then ' "Constraint '{0}' conflicts with the constraint '{1}' already specified for type parameter '{2}'." diagnosticsBuilder.Add(New TypeParameterDiagnosticInfo(typeParameter, pair2.Constraint, ErrorFactory.ErrorInfo( ERRID.ERR_ConflictingDirectConstraints3, pair2.Constraint.ToDisplayFormat(), pair1.Constraint.ToDisplayFormat(), typeParameter))) bad = True End If ElseIf (pair1.TypeParameter Is pair2.TypeParameter) Then ' Skip other cases where both constraints are from the same type ' parameter but not the current type parameter since those cases ' will be reported directly on the other type parameter. ElseIf HasConflict(pair1.Constraint, pair2.Constraint, useSiteInfo) Then If pair1.TypeParameter Is typeParameter Then ' "Constraint '{0}' conflicts with the indirect constraint '{1}' obtained from the type parameter constraint '{2}'." diagnosticsBuilder.Add(New TypeParameterDiagnosticInfo(typeParameter, pair1.Constraint, ErrorFactory.ErrorInfo( ERRID.ERR_ConstraintClashDirectIndirect3, pair1.Constraint.ToDisplayFormat(), pair2.Constraint.ToDisplayFormat(), pair2.TypeParameter))) bad = True ElseIf pair2.TypeParameter Is typeParameter Then ' "Indirect constraint '{0}' obtained from the type parameter constraint '{1}' conflicts with the constraint '{2}'." diagnosticsBuilder.Add(New TypeParameterDiagnosticInfo(typeParameter, pair1.Constraint, ErrorFactory.ErrorInfo( ERRID.ERR_ConstraintClashIndirectDirect3, pair1.Constraint.ToDisplayFormat(), pair1.TypeParameter, pair2.Constraint.ToDisplayFormat()))) bad = True Else ' "Indirect constraint '{0}' obtained from the type parameter constraint '{1}' conflicts with the indirect constraint '{2}' obtained from the type parameter constraint '{3}'." diagnosticsBuilder.Add(New TypeParameterDiagnosticInfo(typeParameter, pair2.Constraint, ErrorFactory.ErrorInfo( ERRID.ERR_ConstraintClashIndirectIndirect4, pair2.Constraint.ToDisplayFormat(), pair2.TypeParameter, pair1.Constraint.ToDisplayFormat(), pair1.TypeParameter))) bad = True End If End If If AppendUseSiteInfo(useSiteInfo, typeParameter, useSiteDiagnosticsBuilder) Then bad = True End If If bad Then constraints(j) = pair2.ToBad() End If Next Next constraints.Free() End Sub <Extension()> 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(languageVersion, diagnosticsBuilder, useSiteDiagnosticsBuilder, template) If useSiteDiagnosticsBuilder IsNot Nothing Then diagnosticsBuilder.AddRange(useSiteDiagnosticsBuilder) End If For Each diagnostic In diagnosticsBuilder diagnostics.Add(diagnostic.UseSiteInfo, loc) Next diagnosticsBuilder.Free() End Sub ''' <summary> ''' Check all generic constraints on the given type and any containing types ''' (such as A(Of T) in A(Of T).B(Of U)). This includes checking constraints ''' on generic types within the type (such as B(Of T) in A(Of B(Of T)())). ''' </summary> <Extension()> 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)) Dim diagnostics As New CheckConstraintsDiagnosticsBuilders() diagnostics.diagnosticsBuilder = diagnosticsBuilder diagnostics.useSiteDiagnosticsBuilder = useSiteDiagnosticsBuilder diagnostics.template = template diagnostics.languageVersion = languageVersion type.VisitType(s_checkConstraintsSingleTypeFunc, diagnostics) useSiteDiagnosticsBuilder = diagnostics.useSiteDiagnosticsBuilder End Sub Private Class CheckConstraintsDiagnosticsBuilders 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.languageVersion, diagnostics.diagnosticsBuilder, diagnostics.useSiteDiagnosticsBuilder, diagnostics.template) End If Return False ' continue walking types End Function <Extension()> Public Sub CheckConstraints( tuple As TupleTypeSymbol, syntaxNode As SyntaxNode, elementLocations As ImmutableArray(Of Location), diagnostics As BindingDiagnosticBag, template As CompoundUseSiteInfo(Of AssemblySymbol)) Dim type As NamedTypeSymbol = tuple.TupleUnderlyingType If Not RequiresChecking(type) Then Return End If If syntaxNode.HasErrors Then Return End If Dim diagnosticsBuilder = ArrayBuilder(Of TypeParameterDiagnosticInfo).GetInstance() Dim underlyingTupleTypeChain = ArrayBuilder(Of NamedTypeSymbol).GetInstance TupleTypeSymbol.GetUnderlyingTypeChain(type, underlyingTupleTypeChain) Dim offset As Integer = 0 For Each underlyingTuple In underlyingTupleTypeChain Dim useSiteDiagnosticsBuilder As ArrayBuilder(Of TypeParameterDiagnosticInfo) = Nothing CheckTypeConstraints(underlyingTuple, DirectCast(syntaxNode.SyntaxTree.Options, VisualBasicParseOptions).LanguageVersion, diagnosticsBuilder, useSiteDiagnosticsBuilder, template) If useSiteDiagnosticsBuilder IsNot Nothing Then diagnosticsBuilder.AddRange(useSiteDiagnosticsBuilder) End If For Each diagnostic In diagnosticsBuilder Dim ordinal = diagnostic.TypeParameter.Ordinal ' If this is the TRest type parameter, we report it on ' the entire type syntax as it does not map to any tuple element. Dim location = If(ordinal = TupleTypeSymbol.RestIndex, syntaxNode.Location, elementLocations(ordinal + offset)) diagnostics.Add(diagnostic.UseSiteInfo, location) Next diagnosticsBuilder.Clear() offset += TupleTypeSymbol.RestIndex Next underlyingTupleTypeChain.Free() diagnosticsBuilder.Free() End Sub <Extension()> Public Function CheckConstraintsForNonTuple( type As NamedTypeSymbol, languageVersion As LanguageVersion, typeArgumentsSyntax As SeparatedSyntaxList(Of TypeSyntax), diagnostics As BindingDiagnosticBag, template As CompoundUseSiteInfo(Of AssemblySymbol)) As Boolean Debug.Assert(Not type.IsTupleType) Debug.Assert(typeArgumentsSyntax.Count = type.Arity) If Not RequiresChecking(type) Then Return True End If Dim diagnosticsBuilder = ArrayBuilder(Of TypeParameterDiagnosticInfo).GetInstance() Dim useSiteDiagnosticsBuilder As ArrayBuilder(Of TypeParameterDiagnosticInfo) = Nothing Dim result = CheckTypeConstraints(type, languageVersion, diagnosticsBuilder, useSiteDiagnosticsBuilder, template) If useSiteDiagnosticsBuilder IsNot Nothing Then diagnosticsBuilder.AddRange(useSiteDiagnosticsBuilder) End If For Each diagnostic In diagnosticsBuilder Dim ordinal = diagnostic.TypeParameter.Ordinal Dim location = typeArgumentsSyntax(ordinal).GetLocation() diagnostics.Add(diagnostic.UseSiteInfo, location) Next diagnosticsBuilder.Free() Return result End Function <Extension()> 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 ' We do not report element locations in method parameters and return types ' so we will simply unwrap the type if it was a tuple. We are relying on ' TypeSymbolExtensions.VisitType to dig into the "Rest" tuple so that they ' will be recursively unwrapped as well. type = DirectCast(type.GetTupleUnderlyingTypeOrSelf(), NamedTypeSymbol) If Not RequiresChecking(type) Then Return True End If Return CheckTypeConstraints(type, languageVersion, diagnosticsBuilder, useSiteDiagnosticsBuilder, template) End Function <Extension()> Public Function CheckConstraints( method As MethodSymbol, languageVersion As LanguageVersion, diagnosticLocation As Location, diagnostics As BindingDiagnosticBag, template As CompoundUseSiteInfo(Of AssemblySymbol)) As Boolean If Not RequiresChecking(method) Then Return True End If Dim diagnosticsBuilder = ArrayBuilder(Of TypeParameterDiagnosticInfo).GetInstance() Dim useSiteDiagnosticsBuilder As ArrayBuilder(Of TypeParameterDiagnosticInfo) = Nothing Dim result = CheckMethodConstraints(method, languageVersion, diagnosticsBuilder, useSiteDiagnosticsBuilder, template) If useSiteDiagnosticsBuilder IsNot Nothing Then diagnosticsBuilder.AddRange(useSiteDiagnosticsBuilder) End If For Each diagnostic In diagnosticsBuilder diagnostics.Add(diagnostic.UseSiteInfo, diagnosticLocation) Next diagnosticsBuilder.Free() Return result End Function <Extension()> 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, 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, 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, languageVersion, substitution, method.OriginalDefinition.TypeParameters, method.TypeArguments, diagnosticsBuilder, useSiteDiagnosticsBuilder, template) End Function ''' <summary> ''' Check type parameters for the containing type or method symbol. ''' The type parameters are assumed to be the original definitions of type ''' parameters from the containing type or method, and the TypeSubstitution ''' instance is used for substituting type parameters within the constraints ''' of those type parameters, so the substitution should map from type ''' parameters to type arguments. ''' </summary> <Extension()> Public Function CheckConstraints( constructedSymbol As Symbol, languageVersion As LanguageVersion, substitution As TypeSubstitution, typeParameters As ImmutableArray(Of TypeParameterSymbol), typeArguments As ImmutableArray(Of TypeSymbol), diagnosticsBuilder As ArrayBuilder(Of TypeParameterDiagnosticInfo), <[In], Out> ByRef useSiteDiagnosticsBuilder As ArrayBuilder(Of TypeParameterDiagnosticInfo), template As CompoundUseSiteInfo(Of AssemblySymbol)) As Boolean Debug.Assert(typeParameters.Length = typeArguments.Length) Dim n = typeParameters.Length Dim succeeded = True For i = 0 To n - 1 Dim typeArgument = typeArguments(i) Dim typeParameter = typeParameters(i) Dim useSiteInfo As New CompoundUseSiteInfo(Of AssemblySymbol)(template) If Not CheckConstraints(constructedSymbol, languageVersion, substitution, typeParameter, typeArgument, diagnosticsBuilder, useSiteInfo) Then succeeded = False End If If AppendUseSiteInfo(useSiteInfo, typeParameter, useSiteDiagnosticsBuilder) Then succeeded = False End If Next Return succeeded End Function Public Function CheckConstraints( constructedSymbol As Symbol, languageVersion As LanguageVersion, substitution As TypeSubstitution, typeParameter As TypeParameterSymbol, typeArgument As TypeSymbol, diagnosticsBuilder As ArrayBuilder(Of TypeParameterDiagnosticInfo), <[In], Out> ByRef useSiteInfo As CompoundUseSiteInfo(Of AssemblySymbol)) As Boolean ' The type parameters must be original definitions of type parameters from the containing symbol. Debug.Assert(((constructedSymbol Is Nothing) AndAlso (substitution Is Nothing)) OrElse (typeParameter.ContainingSymbol Is constructedSymbol.OriginalDefinition)) If typeArgument.IsErrorType() Then Return True End If Dim succeeded = True If typeArgument.IsRestrictedType() Then If diagnosticsBuilder IsNot Nothing Then ' "'{0}' cannot be made nullable, and cannot be used as the data type of an array element, field, anonymous type member, type argument, 'ByRef' parameter, or return statement." diagnosticsBuilder.Add(New TypeParameterDiagnosticInfo(typeParameter, ErrorFactory.ErrorInfo(ERRID.ERR_RestrictedType1, typeArgument))) End If succeeded = False End If If typeParameter.HasConstructorConstraint AndAlso Not SatisfiesConstructorConstraint(typeParameter, typeArgument, diagnosticsBuilder) Then succeeded = False End If If typeParameter.HasReferenceTypeConstraint AndAlso Not SatisfiesReferenceTypeConstraint(typeParameter, typeArgument, diagnosticsBuilder) Then 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 ' The type parameters for a constructed type/method are the type parameters of the ConstructedFrom ' type/method, so the constraint types are not substituted. For instance with "Class C(Of T As U, U)", ' the type parameter for T in "C(Of Object, Integer)" has constraint "U", not "Integer". We need to ' substitute the type parameter constraints from the original definition of the type parameters ' using the TypeSubstitution from the constructed type/method. For Each t In typeParameter.ConstraintTypesWithDefinitionUseSiteDiagnostics(useSiteInfo) Dim constraintType = t.InternalSubstituteTypeParameters(substitution).Type If Not SatisfiesTypeConstraint(typeArgument, constraintType, useSiteInfo) Then If diagnosticsBuilder IsNot Nothing Then ' "Type argument '{0}' does not inherit from or implement the constraint type '{1}'." diagnosticsBuilder.Add(New TypeParameterDiagnosticInfo(typeParameter, ErrorFactory.ErrorInfo(ERRID.ERR_GenericConstraintNotSatisfied2, typeArgument, constraintType))) End If succeeded = False End If Next Return succeeded End Function Private Function AppendUseSiteInfo( useSiteInfo As CompoundUseSiteInfo(Of AssemblySymbol), typeParameter As TypeParameterSymbol, <[In], Out> ByRef useSiteDiagnosticsBuilder As ArrayBuilder(Of TypeParameterDiagnosticInfo) ) As Boolean Dim hasErrors As Boolean = useSiteInfo.AccumulatesDiagnostics AndAlso Not useSiteInfo.Diagnostics.IsNullOrEmpty If Not hasErrors AndAlso (Not useSiteInfo.AccumulatesDependencies OrElse useSiteInfo.Dependencies.IsNullOrEmpty) Then Return False End If If useSiteDiagnosticsBuilder Is Nothing Then useSiteDiagnosticsBuilder = New ArrayBuilder(Of TypeParameterDiagnosticInfo)() End If If Not hasErrors Then If useSiteInfo.AccumulatesDependencies AndAlso Not useSiteInfo.Dependencies.IsNullOrEmpty() Then useSiteDiagnosticsBuilder.Add(New TypeParameterDiagnosticInfo(typeParameter, If(useSiteInfo.Dependencies.Count = 1, New UseSiteInfo(Of AssemblySymbol)(useSiteInfo.Dependencies.Single()), New UseSiteInfo(Of AssemblySymbol)(useSiteInfo.Dependencies.ToImmutableHashSet())))) End If Return False End If For Each info In useSiteInfo.Diagnostics Debug.Assert(info.Severity = DiagnosticSeverity.Error) useSiteDiagnosticsBuilder.Add(New TypeParameterDiagnosticInfo(typeParameter, info)) Next Return True End Function ''' <summary> ''' Return the most derived type from the set of constraint types on this type ''' parameter and any type parameter it depends on. Returns Nothing if there ''' are no concrete constraint types. If there are multiple constraints, returns ''' the most derived, ignoring any subsequent constraints that are neither ''' more or less derived. This method assumes there are no constraint cycles. ''' </summary> <Extension()> Public Function GetNonInterfaceConstraint(typeParameter As TypeParameterSymbol, <[In], Out> ByRef useSiteInfo As CompoundUseSiteInfo(Of AssemblySymbol)) As TypeSymbol Dim result As TypeSymbol = Nothing For Each constraint In typeParameter.ConstraintTypesWithDefinitionUseSiteDiagnostics(useSiteInfo) Dim candidate As TypeSymbol = Nothing Select Case constraint.Kind Case SymbolKind.ErrorType Continue For Case SymbolKind.TypeParameter candidate = DirectCast(constraint, TypeParameterSymbol).GetNonInterfaceConstraint(useSiteInfo) Case Else If Not constraint.IsInterfaceType() Then candidate = constraint End If End Select If result Is Nothing Then result = candidate ElseIf candidate IsNot Nothing Then ' Pick the most derived type If result.IsClassType AndAlso Conversions.IsDerivedFrom(candidate, result, useSiteInfo) Then result = candidate End If End If Next Return result End Function <Extension()> Public Function HasInterfaceConstraint(typeParameter As TypeParameterSymbol) As Boolean Dim result As TypeSymbol = Nothing For Each constraint In typeParameter.ConstraintTypesNoUseSiteDiagnostics Select Case constraint.Kind Case SymbolKind.ErrorType Continue For Case SymbolKind.TypeParameter If DirectCast(constraint, TypeParameterSymbol).HasInterfaceConstraint() Then Return True End If Case Else If constraint.IsInterfaceType() Then Return True End If End Select Next Return False End Function ''' <summary> ''' Return the most derived class type from the set of constraint types on this type ''' parameter and any type parameter it depends on. Returns Nothing if there are ''' no concrete constraint types. If there are multiple constraints, returns the most ''' derived, ignoring any subsequent constraints that are neither more or less derived. ''' This method assumes there are no constraint cycles. Unlike GetBaseConstraintType, ''' this method will always return a NamedTypeSymbol representing a class: returning ''' System.ValueType for value types, System.Array for arrays, and System.Enum for enums. ''' </summary> <Extension()> Public Function GetClassConstraint(typeParameter As TypeParameterSymbol, <[In], Out> ByRef useSiteInfo As CompoundUseSiteInfo(Of AssemblySymbol)) As NamedTypeSymbol Dim baseType = typeParameter.GetNonInterfaceConstraint(useSiteInfo) If baseType Is Nothing Then Return Nothing End If Select Case baseType.TypeKind Case TypeKind.Array, TypeKind.Enum, TypeKind.Structure Return baseType.BaseTypeWithDefinitionUseSiteDiagnostics(useSiteInfo) Case Else Debug.Assert(Not baseType.IsInterfaceType()) Debug.Assert(baseType.TypeKind <> TypeKind.TypeParameter) Return DirectCast(baseType, NamedTypeSymbol) End Select End Function ''' <summary> ''' Populate the collection with all constraints for the type parameter, traversing ''' any constraints that are also type parameters. The result is a collection of type ''' and flag constraints, with no type parameter references. This method assumes ''' there are no constraint cycles. ''' </summary> <Extension()> Private Sub GetAllConstraints( typeParameter As TypeParameterSymbol, constraintsBuilder As ArrayBuilder(Of TypeParameterAndConstraint), fromConstraintOpt As TypeParameterConstraint?) Dim constraints = ArrayBuilder(Of TypeParameterConstraint).GetInstance() typeParameter.GetConstraints(constraints) For Each constraint In constraints Dim type = constraint.TypeConstraint If type IsNot Nothing Then Select Case type.TypeKind Case TypeKind.TypeParameter ' Add constraints from type parameter. DirectCast(type, TypeParameterSymbol).GetAllConstraints(constraintsBuilder, If(fromConstraintOpt.HasValue, fromConstraintOpt.Value, constraint)) Continue For Case TypeKind.Error ' Skip error types. Continue For End Select End If constraintsBuilder.Add( If(fromConstraintOpt.HasValue, New TypeParameterAndConstraint(DirectCast(fromConstraintOpt.Value.TypeConstraint, TypeParameterSymbol), constraint.AtLocation(fromConstraintOpt.Value.LocationOpt)), New TypeParameterAndConstraint(typeParameter, constraint))) Next constraints.Free() End Sub ''' <summary> ''' A tuple of type parameter and constraint type. ''' </summary> Private Structure TypeParameterAndConstraint Public Sub New(typeParameter As TypeParameterSymbol, constraint As TypeParameterConstraint, Optional isBad As Boolean = False) Me.TypeParameter = typeParameter Me.Constraint = constraint Me.IsBad = isBad End Sub Public ReadOnly TypeParameter As TypeParameterSymbol Public ReadOnly Constraint As TypeParameterConstraint Public ReadOnly IsBad As Boolean Public Function ToBad() As TypeParameterAndConstraint Debug.Assert(Not IsBad) Return New TypeParameterAndConstraint(TypeParameter, Constraint, True) End Function Public Overrides Function ToString() As String Dim result = String.Format("{0} : {1}", TypeParameter, Constraint) If IsBad Then result = result & " (bad)" End If Return result End Function End Structure Private Function SatisfiesTypeConstraint( typeArgument As TypeSymbol, constraintType As TypeSymbol, <[In], Out> ByRef useSiteInfo As CompoundUseSiteInfo(Of AssemblySymbol) ) As Boolean If constraintType.IsErrorType() Then constraintType.AddUseSiteInfo(useSiteInfo) Return False End If Return Conversions.HasWideningDirectCastConversionButNotEnumTypeConversion(typeArgument, constraintType, useSiteInfo) End Function ' See Bindable::ValidateNewConstraintForType. Private Function SatisfiesConstructorConstraint( typeParameter As TypeParameterSymbol, typeArgument As TypeSymbol, diagnosticsBuilder As ArrayBuilder(Of TypeParameterDiagnosticInfo)) As Boolean Debug.Assert(typeParameter.HasConstructorConstraint) Select Case typeArgument.TypeKind Case TypeKind.Enum Return True Case TypeKind.TypeParameter If DirectCast(typeArgument, TypeParameterSymbol).HasConstructorConstraint OrElse typeArgument.IsValueType Then Return True Else If diagnosticsBuilder IsNot Nothing Then ' "Type parameter '{0}' must have either a 'New' constraint or a 'Structure' constraint to satisfy the 'New' constraint for type parameter '{1}'." diagnosticsBuilder.Add(New TypeParameterDiagnosticInfo(typeParameter, ErrorFactory.ErrorInfo(ERRID.ERR_BadGenericParamForNewConstraint2, typeArgument, typeParameter))) End If Return False End If Case Else Dim isStructure As Boolean = typeArgument.TypeKind = TypeKind.Structure Dim constraintError = ConstructorConstraintError.NoPublicParameterlessConstructor If typeArgument.TypeKind = TypeKind.Class OrElse isStructure Then Dim namedType = DirectCast(typeArgument, NamedTypeSymbol) constraintError = HasPublicParameterlessConstructor(namedType) If constraintError = ConstructorConstraintError.None AndAlso namedType.IsMustInherit Then constraintError = ConstructorConstraintError.MustInheritType End If End If If diagnosticsBuilder IsNot Nothing Then Select Case constraintError Case ConstructorConstraintError.NoPublicParameterlessConstructor ' "Type argument '{0}' must have a public parameterless instance constructor to satisfy the 'New' constraint for type parameter '{1}'." diagnosticsBuilder.Add(New TypeParameterDiagnosticInfo(typeParameter, ErrorFactory.ErrorInfo(ERRID.ERR_NoSuitableNewForNewConstraint2, typeArgument, typeParameter))) Case ConstructorConstraintError.MustInheritType ' "Type argument '{0}' is declared 'MustInherit' and does not satisfy the 'New' constraint for type parameter '{1}'." diagnosticsBuilder.Add(New TypeParameterDiagnosticInfo(typeParameter, ErrorFactory.ErrorInfo(ERRID.ERR_MustInheritForNewConstraint2, typeArgument, typeParameter))) Case ConstructorConstraintError.HasRequiredMembers ' '{2}' cannot satisfy the 'New' constraint on parameter '{1}' in the generic type or or method '{0}' because '{2}' has required members. diagnosticsBuilder.Add(New TypeParameterDiagnosticInfo(typeParameter, ErrorFactory.ErrorInfo(ERRID.ERR_NewConstraintCannotHaveRequiredMembers, typeParameter.ContainingSymbol, typeParameter, typeArgument))) Case ConstructorConstraintError.None Case Else Throw ExceptionUtilities.UnexpectedValue(constraintError) End Select End If Return constraintError = ConstructorConstraintError.None End Select End Function ' See Bindable::ValidateReferenceConstraintForType. Private Function SatisfiesReferenceTypeConstraint( typeParameter As TypeParameterSymbol, typeArgument As TypeSymbol, diagnosticsBuilder As ArrayBuilder(Of TypeParameterDiagnosticInfo)) As Boolean Debug.Assert((typeParameter Is Nothing) OrElse typeParameter.HasReferenceTypeConstraint) If Not typeArgument.IsReferenceType Then If diagnosticsBuilder IsNot Nothing Then ' "Type argument '{0}' does not satisfy the 'Class' constraint for type parameter '{1}'." diagnosticsBuilder.Add(New TypeParameterDiagnosticInfo(typeParameter, ErrorFactory.ErrorInfo(ERRID.ERR_BadTypeArgForRefConstraint2, typeArgument, typeParameter))) End If Return False End If Return True End Function ' See Bindable::ValidateValueConstraintForType. Private Function SatisfiesValueTypeConstraint( constructedSymbol As Symbol, typeParameter As TypeParameterSymbol, typeArgument As TypeSymbol, diagnosticsBuilder As ArrayBuilder(Of TypeParameterDiagnosticInfo), <[In], Out> ByRef useSiteInfo As CompoundUseSiteInfo(Of AssemblySymbol)) As Boolean Debug.Assert((typeParameter Is Nothing) OrElse typeParameter.HasValueTypeConstraint) If Not typeArgument.IsValueType Then If diagnosticsBuilder IsNot Nothing Then Dim containingType = TryCast(constructedSymbol, TypeSymbol) If (containingType IsNot Nothing) AndAlso containingType.IsNullableType() Then ' "Type '{0}' must be a value type or a type argument constrained to 'Structure' in order to be used with 'Nullable' or nullable modifier '?'." diagnosticsBuilder.Add(New TypeParameterDiagnosticInfo(typeParameter, ErrorFactory.ErrorInfo(ERRID.ERR_BadTypeArgForStructConstraintNull, typeArgument))) Else ' "Type argument '{0}' does not satisfy the 'Structure' constraint for type parameter '{1}'." diagnosticsBuilder.Add(New TypeParameterDiagnosticInfo(typeParameter, ErrorFactory.ErrorInfo(ERRID.ERR_BadTypeArgForStructConstraint2, typeArgument, typeParameter))) End If End If Return False ElseIf IsNullableTypeOrTypeParameter(typeArgument, useSiteInfo) Then If diagnosticsBuilder IsNot Nothing Then ' "'System.Nullable' does not satisfy the 'Structure' constraint for type parameter '{0}'. Only non-nullable 'Structure' types are allowed." diagnosticsBuilder.Add(New TypeParameterDiagnosticInfo(typeParameter, ErrorFactory.ErrorInfo(ERRID.ERR_NullableDisallowedForStructConstr1, typeParameter))) End If Return False End If Return True End Function ' See Bindable::ConstraintsConflict. Private Function HasConflict(constraint1 As TypeParameterConstraint, constraint2 As TypeParameterConstraint, <[In], Out> ByRef useSiteInfo As CompoundUseSiteInfo(Of AssemblySymbol)) As Boolean Dim constraintType1 = constraint1.TypeConstraint Dim constraintType2 = constraint2.TypeConstraint If (constraintType1 IsNot Nothing) AndAlso (constraintType1.IsInterfaceType()) Then Return False End If If (constraintType2 IsNot Nothing) AndAlso (constraintType2.IsInterfaceType()) Then Return False End If If constraint1.IsValueTypeConstraint Then If HasValueTypeConstraintConflict(constraint2, useSiteInfo) Then Return True End If ElseIf constraint2.IsValueTypeConstraint Then If HasValueTypeConstraintConflict(constraint1, useSiteInfo) Then Return True End If End If If constraint1.IsReferenceTypeConstraint Then If HasReferenceTypeConstraintConflict(constraint2) Then Return True End If ElseIf constraint2.IsReferenceTypeConstraint Then If HasReferenceTypeConstraintConflict(constraint1) Then Return True End If End If If (constraintType1 IsNot Nothing) AndAlso (constraintType2 IsNot Nothing) AndAlso Not SatisfiesTypeConstraint(constraintType1, constraintType2, useSiteInfo) AndAlso Not SatisfiesTypeConstraint(constraintType2, constraintType1, useSiteInfo) Then Return True End If Return False End Function Private Function HasValueTypeConstraintConflict(constraint As TypeParameterConstraint, <[In], Out> ByRef useSiteInfo As CompoundUseSiteInfo(Of AssemblySymbol)) As Boolean Dim constraintType = constraint.TypeConstraint If constraintType Is Nothing Then Return False End If If SatisfiesValueTypeConstraint(constructedSymbol:=Nothing, typeParameter:=Nothing, typeArgument:=constraintType, diagnosticsBuilder:=Nothing, useSiteInfo:=useSiteInfo) Then Return False End If Select Case constraintType.SpecialType Case SpecialType.System_Object, SpecialType.System_ValueType Return False End Select Return True End Function Private Function HasReferenceTypeConstraintConflict(constraint As TypeParameterConstraint) As Boolean Dim constraintType = constraint.TypeConstraint If constraintType Is Nothing Then Return False End If If SatisfiesReferenceTypeConstraint(typeParameter:=Nothing, typeArgument:=constraintType, diagnosticsBuilder:=Nothing) Then Return False End If Return True End Function Private Function IsNullableTypeOrTypeParameter(type As TypeSymbol, <[In], Out> ByRef useSiteInfo As CompoundUseSiteInfo(Of AssemblySymbol)) As Boolean If type.TypeKind = TypeKind.TypeParameter Then Dim typeParameter = DirectCast(type, TypeParameterSymbol) Dim constraintTypes = typeParameter.ConstraintTypesWithDefinitionUseSiteDiagnostics(useSiteInfo) For Each constraintType In constraintTypes If IsNullableTypeOrTypeParameter(constraintType, useSiteInfo) Then Return True End If Next Return False Else Return type.IsNullableType() End If End Function Private Function GetConstraintCycleInfo(cycle As ConsList(Of TypeParameterSymbol)) As CompoundDiagnosticInfo Debug.Assert(cycle.Any()) Dim previous As TypeParameterSymbol = Nothing Dim builder = ArrayBuilder(Of DiagnosticInfo).GetInstance() builder.Add(Nothing) ' Placeholder for first entry added later. For Each typeParameter In cycle If previous IsNot Nothing Then builder.Add(ErrorFactory.ErrorInfo(ERRID.ERR_ConstraintCycleLink2, typeParameter, previous)) End If previous = typeParameter Next builder(0) = ErrorFactory.ErrorInfo(ERRID.ERR_ConstraintCycleLink2, cycle.Head, previous) Dim diagnostics = builder.ToArrayAndFree() Array.Reverse(diagnostics) Return New CompoundDiagnosticInfo(diagnostics) End Function Public Enum ConstructorConstraintError None NoPublicParameterlessConstructor MustInheritType HasRequiredMembers End Enum ''' <summary> ''' Return true if the class type has a public parameterless constructor. ''' </summary> Public Function HasPublicParameterlessConstructor(type As NamedTypeSymbol) As ConstructorConstraintError type = type.OriginalDefinition Debug.Assert(type.TypeKind = TypeKind.Class OrElse type.TypeKind = TypeKind.Structure) Dim sourceClass = If(type.TypeKind = TypeKind.Class, TryCast(type, SourceNamedTypeSymbol), Nothing) If sourceClass IsNot Nothing AndAlso Not sourceClass.MembersHaveBeenCreated Then ' When we are dealing with group classes and synthetic entry points, ' we can end up here while we are building the set of members for the type. ' Using InstanceConstructors property will send us into an infinite loop. If sourceClass.InferFromSyntaxIfClassWillHavePublicParameterlessConstructor() Then Return ConstructorConstraintError.None Else Return ConstructorConstraintError.NoPublicParameterlessConstructor End If End If Dim hasRequiredMembers = type.AllRequiredMembers.Count > 0 OrElse type.HasRequiredMembersError For Each constructor In type.InstanceConstructors If constructor.ParameterCount = 0 Then If constructor.DeclaredAccessibility <> Accessibility.Public Then Return ConstructorConstraintError.NoPublicParameterlessConstructor ElseIf hasRequiredMembers AndAlso Not constructor.HasSetsRequiredMembers Then Return ConstructorConstraintError.HasRequiredMembers Else Return ConstructorConstraintError.None End If End If Next If Not type.TypeKind = TypeKind.Structure Then Return ConstructorConstraintError.NoPublicParameterlessConstructor ElseIf hasRequiredMembers Then Return ConstructorConstraintError.HasRequiredMembers Else Return ConstructorConstraintError.None End If End Function ''' <summary> ''' Return true if the constraints collection contains the given type constraint. ''' </summary> Private Function ContainsTypeConstraint(constraints As ArrayBuilder(Of TypeParameterConstraint), constraintType As TypeSymbol) As Boolean Debug.Assert(constraintType IsNot Nothing) For Each constraint In constraints Dim type = constraint.TypeConstraint If (type IsNot Nothing) AndAlso constraintType.IsSameTypeIgnoringAll(type) Then Return True End If Next Return False End Function Private Function RequiresChecking(type As NamedTypeSymbol) As Boolean If type.Arity = 0 Then Return False End If ' If type is the original definition, there is no need ' to check constraints. In the following for instance: ' Class A(Of T As Structure) ' Dim F As New A(Of T)() ' End Class If type.OriginalDefinition Is type Then Return False End If Debug.Assert(Not TypeSymbol.Equals(type.ConstructedFrom, type, TypeCompareKind.ConsiderEverything)) Return True End Function Private Function RequiresChecking(method As MethodSymbol) As Boolean If Not method.IsGenericMethod Then Return False End If ' If method is the original definition, there is no need ' to check constraints. In the following for instance: ' Sub M(Of T As Class)() ' M(Of T)() ' End Function If method.OriginalDefinition Is method Then Return False End If Debug.Assert(method.ConstructedFrom <> method) Return True End Function End Module End Namespace