diff --git a/src/Compilers/CSharp/Portable/Emitter/Model/PEModuleBuilder.cs b/src/Compilers/CSharp/Portable/Emitter/Model/PEModuleBuilder.cs index 942f5d78b27f2a62286eacff305fc1064272889d..c959328def4c140abfdcdbb9a630d1de73aa0a91 100644 --- a/src/Compilers/CSharp/Portable/Emitter/Model/PEModuleBuilder.cs +++ b/src/Compilers/CSharp/Portable/Emitter/Model/PEModuleBuilder.cs @@ -898,7 +898,8 @@ private void CheckTupleUnderlying(NamedTypeSymbol namedTypeSymbol, SyntaxNode sy // but if it does happen we should make it a failure. // NOTE: declaredBase could be null for interfaces var declaredBase = namedTypeSymbol.BaseTypeNoUseSiteDiagnostics; - if (declaredBase?.SpecialType != SpecialType.System_ValueType && declaredBase?.IsErrorType() != true) + if (declaredBase == null || + (declaredBase.SpecialType != SpecialType.System_ValueType && !declaredBase.IsErrorType())) { // Try to decrease noise by not complaining about the same type over and over again. if (_reportedErrorTypesMap.Add(namedTypeSymbol)) diff --git a/src/Compilers/VisualBasic/Portable/Emit/SymbolTranslator.vb b/src/Compilers/VisualBasic/Portable/Emit/SymbolTranslator.vb index 9761f5718c12035b81cf754d0bab57978d92a95d..64bbf4c0003fdbb287e39d85b8413898981ffbe5 100644 --- a/src/Compilers/VisualBasic/Portable/Emit/SymbolTranslator.vb +++ b/src/Compilers/VisualBasic/Portable/Emit/SymbolTranslator.vb @@ -13,7 +13,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Emit ' TODO: Need to estimate amount of elements for this map and pass that value to the constructor. Protected ReadOnly m_AssemblyOrModuleSymbolToModuleRefMap As New ConcurrentDictionary(Of Symbol, Microsoft.Cci.IModuleReference)() Private ReadOnly _genericInstanceMap As New ConcurrentDictionary(Of Symbol, Object)() - Private ReadOnly _reportedErrorTypesMap As New ConcurrentSet(Of ErrorTypeSymbol)() + Private ReadOnly _reportedErrorTypesMap As New ConcurrentSet(Of TypeSymbol)() Private ReadOnly _embeddedTypesManagerOpt As NoPia.EmbeddedTypesManager Public Overrides ReadOnly Property EmbeddedTypesManagerOpt As NoPia.EmbeddedTypesManager @@ -119,6 +119,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Emit ElseIf namedTypeSymbol.IsTupleType Then Debug.Assert(Not needDeclaration) namedTypeSymbol = namedTypeSymbol.TupleUnderlyingType + + CheckTupleUnderlying(namedTypeSymbol, syntaxNodeOpt, diagnostics) End If ' Substitute error types with a special singleton object. @@ -201,6 +203,24 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Emit Return namedTypeSymbol End Function + Private Sub CheckTupleUnderlying(namedTypeSymbol As NamedTypeSymbol, syntaxNodeOpt As SyntaxNode, diagnostics As DiagnosticBag) + ' check that underlying type of a ValueTuple is indeed a value type (or error) + ' this should never happen, in theory, + ' but if it does happen we should make it a failure. + ' NOTE: declaredBase could be null for interfaces + Dim declaredBase = namedTypeSymbol.BaseTypeNoUseSiteDiagnostics + If declaredBase Is Nothing OrElse + (declaredBase.SpecialType <> SpecialType.System_ValueType AndAlso Not declaredBase.IsErrorType()) Then + ' Try to decrease noise by not complaining about the same type over and over again. + If (_reportedErrorTypesMap.Add(namedTypeSymbol)) Then + diagnostics.Add(New VBDiagnostic( + ErrorFactory.ErrorInfo(ERRID.ERR_PredefinedValueTupleTypeMustBeStruct, namedTypeSymbol.MetadataName), + If(syntaxNodeOpt Is Nothing, NoLocation.Singleton, syntaxNodeOpt.GetLocation()))) + + End If + End If + End Sub + Friend Overloads Function Translate([param] As TypeParameterSymbol) As Microsoft.Cci.IGenericParameterReference Debug.Assert(param Is param.OriginalDefinition) Return [param] diff --git a/src/Compilers/VisualBasic/Portable/Errors/Errors.vb b/src/Compilers/VisualBasic/Portable/Errors/Errors.vb index 68a5e217e8553b0662d80804e3f5b22fa6908228..3aa7f5306cc32d3db41d3a77ed82c821caeb0918 100644 --- a/src/Compilers/VisualBasic/Portable/Errors/Errors.vb +++ b/src/Compilers/VisualBasic/Portable/Errors/Errors.vb @@ -1707,6 +1707,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ERR_ExplicitTupleElementNamesAttribute = 37269 ERR_TupleLiteralDisallowsTypeChar = 37270 ERR_NewWithTupleTypeSyntax = 37271 + ERR_PredefinedValueTupleTypeMustBeStruct = 37272 ' Available 37270 ERR_DuplicateProcDefWithDifferentTupleNames2 = 37271 diff --git a/src/Compilers/VisualBasic/Portable/Symbols/Tuples/TupleTypeSymbol.vb b/src/Compilers/VisualBasic/Portable/Symbols/Tuples/TupleTypeSymbol.vb index 229e5d088aad871f9c6da0a29071559a0956a307..409e43cb7481cfe2a170e37ff1b52cdb05b2bcb4 100644 --- a/src/Compilers/VisualBasic/Portable/Symbols/Tuples/TupleTypeSymbol.vb +++ b/src/Compilers/VisualBasic/Portable/Symbols/Tuples/TupleTypeSymbol.vb @@ -68,18 +68,6 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols End Get End Property - Public Overrides ReadOnly Property IsReferenceType As Boolean - Get - Return Not Me._underlyingType.IsErrorType() AndAlso Me._underlyingType.IsReferenceType - End Get - End Property - - Public Overrides ReadOnly Property IsValueType As Boolean - Get - Return Me._underlyingType.IsErrorType() OrElse Me._underlyingType.IsValueType - End Get - End Property - Public Overrides ReadOnly Property IsImplicitlyDeclared As Boolean Get Return False @@ -122,7 +110,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols Public Overrides ReadOnly Property TypeKind As TypeKind Get - Return If(Me._underlyingType.TypeKind = TypeKind.Class, TypeKind.Class, TypeKind.Struct) + ' From the language perspective tuple is a value type + ' composed of its underlying elements + Return TypeKind.Struct End Get End Property diff --git a/src/Compilers/VisualBasic/Portable/VBResources.Designer.vb b/src/Compilers/VisualBasic/Portable/VBResources.Designer.vb index d0a885c657ac76d44da6dd7a4840ee87c5282052..46bb30f4fe6058532f3e874bf2bdc913e019c190 100644 --- a/src/Compilers/VisualBasic/Portable/VBResources.Designer.vb +++ b/src/Compilers/VisualBasic/Portable/VBResources.Designer.vb @@ -9117,6 +9117,15 @@ Namespace Microsoft.CodeAnalysis.VisualBasic End Get End Property + ''' + ''' Looks up a localized string similar to Predefined type '{0}' must be a structure.. + ''' + Friend ReadOnly Property ERR_PredefinedValueTupleTypeMustBeStruct() As String + Get + Return ResourceManager.GetString("ERR_PredefinedValueTupleTypeMustBeStruct", resourceCulture) + End Get + End Property + ''' ''' Looks up a localized string similar to SecurityAction value '{0}' is invalid for PrincipalPermission attribute.. ''' diff --git a/src/Compilers/VisualBasic/Portable/VBResources.resx b/src/Compilers/VisualBasic/Portable/VBResources.resx index b12095e6c74af28032a1696d55fa68bc4ba43f76..5e5d6d3b4d20f0fdec87c9e3101b3d7767053359 100644 --- a/src/Compilers/VisualBasic/Portable/VBResources.resx +++ b/src/Compilers/VisualBasic/Portable/VBResources.resx @@ -3169,6 +3169,9 @@ 'New' cannot be used with tuple type. Use a tuple literal expression instead. + + Predefined type '{0}' must be a structure. + Extension method '{0}' has type constraints that can never be satisfied. diff --git a/src/Compilers/VisualBasic/Test/Emit/CodeGen/CodeGenTuples.vb b/src/Compilers/VisualBasic/Test/Emit/CodeGen/CodeGenTuples.vb index 9892e93db78753fedbaad6811c7e3017df017336..914c5590ea0d2a7453db082e6467088908984a37 100644 --- a/src/Compilers/VisualBasic/Test/Emit/CodeGen/CodeGenTuples.vb +++ b/src/Compilers/VisualBasic/Test/Emit/CodeGen/CodeGenTuples.vb @@ -51,6 +51,19 @@ namespace System.Runtime.CompilerServices End Namespace " + + ReadOnly s_tupleattributes As String = " +namespace System.Runtime.CompilerServices + + public class TupleElementNamesAttribute : Inherits Attribute + public Sub New(transformNames As String()) + End Sub + End Class +End Namespace + +" + + ReadOnly s_trivial3uple As String = " Namespace System Public Structure ValueTuple(Of T1, T2, T3) @@ -1089,7 +1102,7 @@ False IL_0035: ldfld "System.ValueTuple(Of Integer, Integer, Integer, Integer, Integer, Integer, Integer, (Integer, Integer, Integer, Integer)).Item5 As Integer" IL_003a: call "Sub System.Console.WriteLine(Integer)" IL_003f: call "Sub C.TestArray()" - IL_0044: call "Sub C.Testullable()" + IL_0044: call "Sub C.TestNullable()" IL_0049: ret } ]]>) @@ -15549,6 +15562,117 @@ BC30402: 'evtTest3' cannot implement event 'evtTest2' on interface 'I1' because ) End Sub + + + Public Sub ValueTupleNotStruct0() + + Dim comp = CreateCompilationWithMscorlibAndVBRuntime( + + +class C + Shared Sub Main() + Dim x as (a As Integer, b As String) + x.Item1 = 1 + x.b = "2" + + ' by the language rules tuple x is definitely assigned + ' since all its elements are definitely assigned + System.Console.WriteLine(x) + end sub +end class + +namespace System + public class ValueTuple(Of T1, T2) + public Item1 as T1 + public Item2 as T2 + + public Sub New(item1 as T1 , item2 as T2 ) + Me.Item1 = item1 + Me.Item2 = item2 + end sub + End class +end Namespace + + <%= s_tupleattributes %> + +, +options:=TestOptions.DebugExe) + + comp.AssertTheseEmitDiagnostics( + +BC37272: Predefined type 'ValueTuple`2' must be a structure. + Dim x as (a As Integer, b As String) + ~ +) + + End Sub + + + + Public Sub ValueTupleNotStruct1() + + Dim comp = CreateCompilationWithMscorlibAndVBRuntime( + + +class C + Shared Sub Main() + Dim x = (1,2,3,4,5,6,7,8,9) + + System.Console.WriteLine(x) + end sub +end class + +namespace System + public class ValueTuple(Of T1, T2) + public Item1 as T1 + public Item2 as T2 + + public Sub New(item1 as T1 , item2 as T2 ) + Me.Item1 = item1 + Me.Item2 = item2 + end sub + End class + + public class ValueTuple(Of T1, T2, T3, T4, T5, T6, T7, TRest) + public Item1 As T1 + public Item2 As T2 + public Item3 As T3 + public Item4 As T4 + public Item5 As T5 + public Item6 As T6 + public Item7 As T7 + public Rest As TRest + + public Sub New(item1 As T1, item2 As T2, item3 As T3, item4 As T4, item5 As T5, item6 As T6, item7 As T7, rest As TRest) + Item1 = item1 + Item2 = item2 + Item3 = item3 + Item4 = item4 + Item5 = item5 + Item6 = item6 + Item7 = item7 + Rest = rest + end Sub + + End Class +end Namespace + + <%= s_tupleattributes %> + + , + options:=TestOptions.DebugExe) + + comp.AssertTheseEmitDiagnostics( + +BC37272: Predefined type 'ValueTuple`2' must be a structure. + Dim x = (1,2,3,4,5,6,7,8,9) + ~ +BC37272: Predefined type 'ValueTuple`8' must be a structure. + Dim x = (1,2,3,4,5,6,7,8,9) + ~ +) + End Sub + Public Sub ConversionToBase() Dim compilation1 = CompilationUtils.CreateCompilationWithMscorlib( @@ -15582,6 +15706,163 @@ BC33030: Conversion operators cannot convert from a base type. ) End Sub + + + Public Sub ValueTupleNotStruct2() + + Dim comp = CreateCompilationWithMscorlibAndVBRuntime( + + +class C + Shared Sub Main() + end sub + + Shared Sub Test2(arg as (a As Integer, b As Integer)) + End Sub +end class + +namespace System + public class ValueTuple(Of T1, T2) + public Item1 as T1 + public Item2 as T2 + + public Sub New(item1 as T1 , item2 as T2 ) + Me.Item1 = item1 + Me.Item2 = item2 + end sub + End class +end Namespace + + <%= s_tupleattributes %> + +, +options:=TestOptions.DebugExe) + + comp.AssertTheseEmitDiagnostics( + +BC37272: Predefined type 'ValueTuple`2' must be a structure. +) + + End Sub + + + + Public Sub ValueTupleNotStruct2i() + + Dim comp = CreateCompilationWithMscorlibAndVBRuntime( + + +class C + Shared Sub Main() + end sub + + Shared Sub Test2(arg as (a As Integer, b As Integer)) + End Sub +end class + +namespace System + public interface ValueTuple(Of T1, T2) + End Interface +end Namespace + + <%= s_tupleattributes %> + +, +options:=TestOptions.DebugExe) + + comp.AssertTheseEmitDiagnostics( + +BC37272: Predefined type 'ValueTuple`2' must be a structure. +) + + End Sub + + + + + Public Sub ValueTupleNotStruct3() + + Dim comp = CreateCompilationWithMscorlibAndVBRuntime( + + +class C + Shared Sub Main() + Dim x as (a As Integer, b As String)() = Nothing + + ' by the language rules tuple x is definitely assigned + ' since all its elements are definitely assigned + System.Console.WriteLine(x) + end sub +end class + +namespace System + public class ValueTuple(Of T1, T2) + public Item1 as T1 + public Item2 as T2 + + public Sub New(item1 as T1 , item2 as T2 ) + Me.Item1 = item1 + Me.Item2 = item2 + end sub + End class +end Namespace + + <%= s_tupleattributes %> + +, +options:=TestOptions.DebugExe) + + comp.AssertTheseEmitDiagnostics( + +BC37272: Predefined type 'ValueTuple`2' must be a structure. + Dim x as (a As Integer, b As String)() = Nothing + ~ +) + + End Sub + + + + Public Sub ValueTupleNotStruct4() + + Dim comp = CreateCompilationWithMscorlibAndVBRuntime( + + +class C + Shared Sub Main() + + end sub + + Shared Function Test2()as (a As Integer, b As Integer) + End Function +end class + +namespace System + public class ValueTuple(Of T1, T2) + public Item1 as T1 + public Item2 as T2 + + public Sub New(item1 as T1 , item2 as T2 ) + Me.Item1 = item1 + Me.Item2 = item2 + end sub + End class +end Namespace + + <%= s_tupleattributes %> + +, +options:=TestOptions.DebugExe) + + comp.AssertTheseEmitDiagnostics( + +BC37272: Predefined type 'ValueTuple`2' must be a structure. + Shared Function Test2()as (a As Integer, b As Integer) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +) + + End Sub + Public Sub IsBaseOf_WithoutCustomModifiers() ' The IL is from this code, but with modifiers