diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs index 0b2532999cd0bd176217d0732432dc63c5a9d6a4..dbd919a527f11ce691025de03517b934bf50c7c5 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs @@ -648,9 +648,18 @@ private BoundExpression BindTupleExpression(TupleExpressionSyntax node, Diagnost if (arguments.Count < 2) { // this should be a parse error already. - return BadExpression(node); + var args = arguments.Count == 1 ? + new BoundExpression[] { BindValue(arguments[0].Expression, diagnostics, BindValueKind.RValue) } : + new BoundExpression[0]; + + return BadExpression(node, args); } + bool hasErrors = false; + + // set of names already used + HashSet uniqueFieldNames = new HashSet(); + var boundArguments = ArrayBuilder.GetInstance(arguments.Count); var elementTypes = ArrayBuilder.GetInstance(arguments.Count); ArrayBuilder elementNames = null; @@ -658,8 +667,22 @@ private BoundExpression BindTupleExpression(TupleExpressionSyntax node, Diagnost for (int i = 0, l = arguments.Count; i < l; i++) { var argumentSyntax = arguments[i]; - var name = argumentSyntax.NameColon?.Name.Identifier.ValueText; + var name = argumentSyntax.NameColon?.Name?.Identifier.ValueText; + + // validate name if we have one + if (name != null) + { + // PROTOTYPE: check for a case "ItemX" where X is not i + if (!uniqueFieldNames.Add(name)) + { + hasErrors = true; + // PROTOTYPE: need specific duplicate name error for tuples + Error(diagnostics, ErrorCode.ERR_AnonymousTypeDuplicatePropertyName, argumentSyntax.NameColon.Name); + } + } + + // add the name to the list // names would typically all be there or none at all // but in case we need to handle this in error cases if (elementNames != null) @@ -679,15 +702,18 @@ private BoundExpression BindTupleExpression(TupleExpressionSyntax node, Diagnost } } - var boundArgument = BindExpression(argumentSyntax.Expression, diagnostics); + var boundArgument = BindValue(argumentSyntax.Expression, diagnostics, BindValueKind.RValue); boundArguments.Add(boundArgument); - elementTypes.Add(boundArgument.Type); + + // PROTOTYPE: need to report distinc errors for tuples + var elementType = GetAnonymousTypeFieldType(boundArgument, argumentSyntax, diagnostics, ref hasErrors); + elementTypes.Add(elementType); } var type = new TupleTypeSymbol( elementTypes.ToImmutableAndFree(), elementNames == null ? - ImmutableArray.Empty : + default(ImmutableArray) : elementNames.ToImmutableAndFree(), node, this, @@ -696,7 +722,7 @@ private BoundExpression BindTupleExpression(TupleExpressionSyntax node, Diagnost //PROTOTYPE: should be a wellknown member? var ctor = type.UnderlyingTupleType?.InstanceConstructors.FirstOrDefault(); - return new BoundTupleCreationExpression(node, ctor, boundArguments.ToImmutableAndFree(), type); + return new BoundTupleCreationExpression(node, ctor, boundArguments.ToImmutableAndFree(), type, hasErrors); } private BoundExpression BindRefValue(RefValueExpressionSyntax node, DiagnosticBag diagnostics) diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Lookup.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Lookup.cs index 645360eb57327b0a490d44dd8aae73af5aee7ebe..2d56921e7535e43ce4f951e1528bb3d8d78babc9 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Lookup.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Lookup.cs @@ -187,10 +187,6 @@ protected void LookupMembersInType(LookupResult result, TypeSymbol type, string this.LookupMembersInClass(result, type, name, arity, basesBeingResolved, options, originalBinder, diagnose, ref useSiteDiagnostics); break; - case TypeKind.Tuple: - useSiteDiagnostics = LookupMembersInTuple(result, type, name, arity, basesBeingResolved, options, originalBinder, diagnose, useSiteDiagnostics); - break; - case TypeKind.Submission: this.LookupMembersInSubmissions(result, type, name, arity, basesBeingResolved, options, originalBinder, diagnose, ref useSiteDiagnostics); break; @@ -212,12 +208,6 @@ protected void LookupMembersInType(LookupResult result, TypeSymbol type, string // done in the caller? } - private HashSet LookupMembersInTuple(LookupResult result, TypeSymbol type, string name, int arity, ConsList basesBeingResolved, LookupOptions options, Binder originalBinder, bool diagnose, HashSet useSiteDiagnostics) - { - this.LookupMembersInClass(result, type, name, arity, basesBeingResolved, options, originalBinder, diagnose, ref useSiteDiagnostics); - return useSiteDiagnostics; - } - private void LookupMembersInErrorType(LookupResult result, ErrorTypeSymbol errorType, string name, int arity, ConsList basesBeingResolved, LookupOptions options, Binder originalBinder, bool diagnose, ref HashSet useSiteDiagnostics) { if (!errorType.CandidateSymbols.IsDefault && errorType.CandidateSymbols.Length == 1) @@ -728,7 +718,7 @@ internal virtual bool SupportsExtensionMethods // PROTOTYPE consider taking this out of the loop. tuples are always at the end of hierarchy // PROTOTYPE match this in other lookups var tuple = currentType as TupleTypeSymbol; - if (tuple != null) + if ((object)tuple != null) { currentType = tuple.UnderlyingTupleType; continue; @@ -1542,6 +1532,8 @@ private void AddMemberLookupSymbolsInfoInType(LookupSymbolsInfo result, TypeSymb this.AddMemberLookupSymbolsInfoInClass(result, type, options, originalBinder, type); break; + //PROTOTYPE: add special handling for tuple types - we need to collect both tuple members and from the underlying. + case TypeKind.Submission: this.AddMemberLookupSymbolsInfoInSubmissions(result, type, options, originalBinder); break; diff --git a/src/Compilers/CSharp/Portable/Binder/Semantics/AccessCheck.cs b/src/Compilers/CSharp/Portable/Binder/Semantics/AccessCheck.cs index cf44e9e50525156da7888c9600b46897847fced2..d62138ca66fd5d1637db20e5548a07fae9570938 100644 --- a/src/Compilers/CSharp/Portable/Binder/Semantics/AccessCheck.cs +++ b/src/Compilers/CSharp/Portable/Binder/Semantics/AccessCheck.cs @@ -99,9 +99,6 @@ internal static class AccessCheck case SymbolKind.NamedType: return IsNamedTypeAccessible((NamedTypeSymbol)symbol, within, ref useSiteDiagnostics, basesBeingResolved); - case SymbolKind.TupleType: - return IsNamedTypeAccessible(((TupleTypeSymbol)symbol).UnderlyingTupleType, within, ref useSiteDiagnostics, basesBeingResolved); - case SymbolKind.ErrorType: // Always assume that error types are accessible. return true; @@ -224,11 +221,6 @@ private static bool IsNamedTypeAccessible(NamedTypeSymbol type, Symbol within, r failedThroughTypeCheck = false; - // for tuples consider the underlying type as a true container for visibility puroposes. - containingType = - (containingType as TupleTypeSymbol)?.UnderlyingTupleType ?? - containingType; - // easy case - members of containing type are accessible. if ((object)containingType == (object)within) { diff --git a/src/Compilers/CSharp/Portable/BoundTree/BoundNodes.xml b/src/Compilers/CSharp/Portable/BoundTree/BoundNodes.xml index a4d67682aaf6f9a8dc5cf463eda42c3e9fb15864..cd4fc802cb839f11f4236e5a0a176c51bf18e7b9 100644 --- a/src/Compilers/CSharp/Portable/BoundTree/BoundNodes.xml +++ b/src/Compilers/CSharp/Portable/BoundTree/BoundNodes.xml @@ -1145,6 +1145,7 @@ + diff --git a/src/Compilers/CSharp/Portable/Emitter/Model/PEModuleBuilder.cs b/src/Compilers/CSharp/Portable/Emitter/Model/PEModuleBuilder.cs index 3a7cc83b3e90b61a5d3db9148006beebb42b77fb..ab318f219615b89ce7849b0d3286d5037314c121 100644 --- a/src/Compilers/CSharp/Portable/Emitter/Model/PEModuleBuilder.cs +++ b/src/Compilers/CSharp/Portable/Emitter/Model/PEModuleBuilder.cs @@ -768,6 +768,10 @@ protected virtual Cci.IModuleReference TranslateModule(ModuleSymbol module, Diag { namedTypeSymbol = AnonymousTypeManager.TranslateAnonymousTypeSymbol(namedTypeSymbol); } + else if (namedTypeSymbol.IsTupleType) + { + namedTypeSymbol = ((TupleTypeSymbol)namedTypeSymbol).UnderlyingTupleType; + } // Substitute error types with a special singleton object. // Unreported bad types can come through NoPia embedding, for example. @@ -914,9 +918,6 @@ internal static Cci.IGenericParameterReference Translate(TypeParameterSymbol par case SymbolKind.TypeParameter: return Translate((TypeParameterSymbol)typeSymbol); - - case SymbolKind.TupleType: - return Translate(((TupleTypeSymbol)typeSymbol).UnderlyingTupleType, syntaxNodeOpt, diagnostics); } throw ExceptionUtilities.UnexpectedValue(typeSymbol.Kind); @@ -1090,6 +1091,10 @@ internal override Cci.IMethodReference Translate(MethodSymbol symbol, Diagnostic { methodSymbol = AnonymousTypeManager.TranslateAnonymousTypeMethodSymbol(methodSymbol); } + else if (container.IsTupleType) + { + container = ((TupleTypeSymbol)container).UnderlyingTupleType; + } if (!methodSymbol.IsDefinition) { diff --git a/src/Compilers/CSharp/Portable/SymbolDisplay/SymbolDisplayVisitor.Types.cs b/src/Compilers/CSharp/Portable/SymbolDisplay/SymbolDisplayVisitor.Types.cs index 0714dcee25a665c52842c0dc90f37a365a8e6486..0bf605d91fbbec30b7edbc6927af375d67238d7f 100644 --- a/src/Compilers/CSharp/Portable/SymbolDisplay/SymbolDisplayVisitor.Types.cs +++ b/src/Compilers/CSharp/Portable/SymbolDisplay/SymbolDisplayVisitor.Types.cs @@ -165,7 +165,9 @@ public override void VisitNamedType(INamedTypeSymbol symbol) } } - if (this.IsMinimizing) + // PROTOTYPE : we need to settle on final tuple symbol visualization. + // it feels like tuples would not need any qualification + if (this.IsMinimizing || symbol.IsTupleType) { MinimallyQualify(symbol); return; @@ -238,6 +240,11 @@ private void AddNameAndTypeArgumentsOrParameters(INamedTypeSymbol symbol) AddAnonymousTypeName(symbol); return; } + else if (symbol.IsTupleType) + { + AddTupleTypeName(symbol); + return; + } string symbolName = null; @@ -378,11 +385,32 @@ private void AddAnonymousTypeName(INamedTypeSymbol symbol) } } + private void AddTupleTypeName(INamedTypeSymbol symbol) + { + // TODO: revise to generate user-friendly name + var members = string.Join(", ", symbol.GetMembers().OfType().Select(CreateTupleTypeMember)); + + if (members.Length == 0) + { + builder.Add(new SymbolDisplayPart(SymbolDisplayPartKind.ClassName, symbol, "")); + } + else + { + var name = $""; + builder.Add(new SymbolDisplayPart(SymbolDisplayPartKind.ClassName, symbol, name)); + } + } + private string CreateAnonymousTypeMember(IPropertySymbol property) { return property.Type.ToDisplayString(format) + " " + property.Name; } + private string CreateTupleTypeMember(IFieldSymbol field) + { + return field.Type.ToDisplayString(format) + " " + field.Name; + } + private bool CanShowDelegateSignature(INamedTypeSymbol symbol) { return @@ -479,6 +507,11 @@ private void AddTypeKind(INamedTypeSymbol symbol) builder.Add(new SymbolDisplayPart(SymbolDisplayPartKind.AnonymousTypeIndicator, null, "AnonymousType")); AddSpace(); } + else if (symbol.IsTupleType) + { + builder.Add(new SymbolDisplayPart(SymbolDisplayPartKind.AnonymousTypeIndicator, null, "Tuple")); + AddSpace(); + } else { var kindKeyword = GetKindKeyword(symbol.TypeKind); diff --git a/src/Compilers/CSharp/Portable/SymbolDisplay/SymbolDisplayVisitor_Minimal.cs b/src/Compilers/CSharp/Portable/SymbolDisplay/SymbolDisplayVisitor_Minimal.cs index a8f937c1b4dcfc4ce5cfbf0dd465d58535c68dca..62fdaa4ffa3d90cea4635b58e43e5bff3abfa9cd 100644 --- a/src/Compilers/CSharp/Portable/SymbolDisplay/SymbolDisplayVisitor_Minimal.cs +++ b/src/Compilers/CSharp/Portable/SymbolDisplay/SymbolDisplayVisitor_Minimal.cs @@ -118,7 +118,7 @@ private void MinimallyQualify(INamedTypeSymbol symbol) // TODO(cyrusn): This code needs to see if type is an attribute and if it can be shown // in simplified form here. - if (!symbol.IsAnonymousType) + if (!(symbol.IsAnonymousType || symbol.IsTupleType)) { if (!NameBoundSuccessfullyToSameSymbol(symbol)) { diff --git a/src/Compilers/CSharp/Portable/Symbols/NamedTypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/NamedTypeSymbol.cs index 9c68baf0c1f1992af5c13387537a97c0fbbf9cd0..b06fc4ec2761b836be1074680401d80dfdecee4d 100644 --- a/src/Compilers/CSharp/Portable/Symbols/NamedTypeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/NamedTypeSymbol.cs @@ -639,7 +639,7 @@ public override int GetHashCode() /// internal override bool Equals(TypeSymbol t2, bool ignoreCustomModifiersAndArraySizesAndLowerBounds = false, bool ignoreDynamic = false) { - if ((object)t2 == this) return true; + if ((object)t2 == this) return true; if ((object)t2 == null) return false; if (ignoreDynamic) @@ -655,18 +655,13 @@ internal override bool Equals(TypeSymbol t2, bool ignoreCustomModifiersAndArrayS //PROTOTYPE: rename ignoreDynamic or introduce another "ignoreTuple" flag // if ignoring dynamic, compare underlying tuple types - var tupleType = t2 as TupleTypeSymbol; - if (tupleType != null) + if (t2.IsTupleType) { - t2 = tupleType.UnderlyingTupleType; + t2 = ((TupleTypeSymbol)t2).UnderlyingTupleType; if ((object)t2 == this) return true; } - tupleType = this as TupleTypeSymbol; - if (tupleType != null) - { - return tupleType.UnderlyingTupleType.Equals(t2, ignoreCustomModifiersAndArraySizesAndLowerBounds, ignoreDynamic); - } + Debug.Assert(!this.IsTupleType); } NamedTypeSymbol other = t2 as NamedTypeSymbol; diff --git a/src/Compilers/CSharp/Portable/Symbols/TupleTypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/TupleTypeSymbol.cs index a1c30decac1292bc6c3bf3e42e484f11b7b17a3e..13086c6c807385a2983056c8325c20e4f8e8d54f 100644 --- a/src/Compilers/CSharp/Portable/Symbols/TupleTypeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/TupleTypeSymbol.cs @@ -65,11 +65,11 @@ internal sealed class TupleTypeSymbol : NamedTypeSymbol, ITupleTypeSymbol var underlyingField2 = (FieldSymbol) Binder.GetWellKnownTypeMember(binder.Compilation, WellKnownMember.System_Runtime_CompilerServices_ValueTuple_T1_T2__Item2, diagnostics, syntax: syntax); fields = ImmutableArray.Create( - new TupleFieldSymbol(elementNames.IsEmpty ? "Item1" : elementNames[0], + new TupleFieldSymbol(elementNames.IsDefault ? "Item1" : elementNames[0], this, elementTypes[0], underlyingField1?.AsMember(underlyingType)), - new TupleFieldSymbol(elementNames.IsEmpty ? "Item2" : elementNames[1], + new TupleFieldSymbol(elementNames.IsDefault ? "Item2" : elementNames[1], this, elementTypes[1], underlyingField2?.AsMember(underlyingType)) @@ -136,6 +136,14 @@ internal sealed override bool IsManagedType } } + public override bool IsTupleType + { + get + { + return true; + } + } + internal sealed override ObsoleteAttributeData ObsoleteAttributeData { get { return _underlyingType.ObsoleteAttributeData; } @@ -148,7 +156,7 @@ public override ImmutableArray GetMembers() public override ImmutableArray GetMembers(string name) { - //TODO: PERF do we need to have a dictionary here? + //PROTOTYPE: PERF do we need to have a dictionary here? // tuples will be typically small 2 or 3 elements only return ImmutableArray.CastUp(_fields).WhereAsArray(field => field.Name == name); } @@ -172,7 +180,7 @@ public override SymbolKind Kind { get { - return SymbolKind.TupleType; + return _underlyingType.Kind; } } @@ -180,7 +188,7 @@ public override TypeKind TypeKind { get { - return TypeKind.Tuple; + return _underlyingType.TypeKind; } } @@ -188,7 +196,7 @@ public override Symbol ContainingSymbol { get { - return null; + return _underlyingType.ContainingSymbol; } } @@ -229,6 +237,10 @@ internal override bool Equals(TypeSymbol t2, bool ignoreCustomModifiers, bool ig { //PROTOTYPE: rename ignoreDynamic or introduce another "ignoreTuple" flag // if ignoring dynamic, compare underlying tuple types + if (t2.IsTupleType) + { + t2 = (t2 as TupleTypeSymbol).UnderlyingTupleType; + } return _underlyingType.Equals(t2, ignoreCustomModifiers, ignoreDynamic); } @@ -280,7 +292,7 @@ public override Accessibility DeclaredAccessibility { get { - return Accessibility.NotApplicable; + return _underlyingType.DeclaredAccessibility; } } @@ -312,7 +324,7 @@ public override int Arity { get { - return _underlyingType.Arity; + return 0; } } @@ -320,7 +332,7 @@ public override ImmutableArray TypeParameters { get { - return _underlyingType.TypeParameters; + return ImmutableArray.Empty; } } @@ -328,7 +340,7 @@ internal override ImmutableArray> TypeArgumentsCu { get { - return _underlyingType.TypeArgumentsCustomModifiers; + return ImmutableArray>.Empty; } } @@ -336,7 +348,7 @@ internal override bool HasTypeArgumentsCustomModifiers { get { - return _underlyingType.HasTypeArgumentsCustomModifiers; + return false; } } @@ -344,7 +356,7 @@ internal override ImmutableArray TypeArgumentsNoUseSiteDiagnostics { get { - return _underlyingType.TypeArgumentsNoUseSiteDiagnostics; + return ImmutableArray.Empty; } } @@ -352,7 +364,7 @@ public override NamedTypeSymbol ConstructedFrom { get { - return _underlyingType.ConstructedFrom; + return this; } } @@ -376,7 +388,7 @@ internal override bool MangleName { get { - return _underlyingType.MangleName; + return false; } } @@ -392,7 +404,7 @@ internal override bool HasSpecialName { get { - return _underlyingType.HasSpecialName; + return false; } } @@ -400,7 +412,7 @@ internal override bool IsComImport { get { - return _underlyingType.IsComImport; + return false; } } @@ -408,7 +420,7 @@ internal override bool IsWindowsRuntimeImport { get { - return _underlyingType.IsWindowsRuntimeImport; + return false; } } @@ -416,7 +428,7 @@ internal override bool ShouldAddWinRTMembers { get { - return _underlyingType.ShouldAddWinRTMembers; + return false; } } @@ -456,7 +468,7 @@ internal override bool IsInterface { get { - return _underlyingType.IsInterface; + return false; } } @@ -488,59 +500,49 @@ internal override bool GetUnificationUseSiteDiagnosticRecursive(ref DiagnosticIn #region ISymbol Members - public override void Accept(SymbolVisitor visitor) - { - visitor.VisitTupleType(this); - } - - public override TResult Accept(SymbolVisitor visitor) - { - return visitor.VisitTupleType(this); - } - internal override AttributeUsageInfo GetAttributeUsageInfo() { - throw new NotImplementedException(); + return AttributeUsageInfo.Null; } internal override ImmutableArray GetEarlyAttributeDecodingMembers() { - throw new NotImplementedException(); + return this.GetMembers(); } internal override ImmutableArray GetEarlyAttributeDecodingMembers(string name) { - throw new NotImplementedException(); + return this.GetMembers(name); } internal override NamedTypeSymbol GetDeclaredBaseType(ConsList basesBeingResolved) { - throw new NotImplementedException(); + return _underlyingType.GetDeclaredBaseType(basesBeingResolved); } internal override ImmutableArray GetDeclaredInterfaces(ConsList basesBeingResolved) { - throw new NotImplementedException(); + return _underlyingType.GetDeclaredInterfaces(basesBeingResolved); } internal override IEnumerable GetSecurityInformation() { - throw new NotImplementedException(); + throw ExceptionUtilities.Unreachable; } internal override ImmutableArray GetAppliedConditionalSymbols() { - throw new NotImplementedException(); + return ImmutableArray.Empty; } internal override IEnumerable GetFieldsToEmit() { - throw new NotImplementedException(); + throw ExceptionUtilities.Unreachable; } internal override ImmutableArray GetInterfacesToEmit() { - throw new NotImplementedException(); + throw ExceptionUtilities.Unreachable; } #endregion diff --git a/src/Compilers/CSharp/Portable/Symbols/TypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/TypeSymbol.cs index 1486a7e0848dc06d753c9bb64116a6a34ffb6189..0be1dde03402daed85c7c4dce6eeaea055d7a826 100644 --- a/src/Compilers/CSharp/Portable/Symbols/TypeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/TypeSymbol.cs @@ -553,6 +553,17 @@ public virtual bool IsAnonymousType } } + /// + /// Is this a symbol for a Tuple + /// + public virtual bool IsTupleType + { + get + { + return false; + } + } + /// /// Is this type a managed type (false for everything but enum, pointer, and /// some struct types). diff --git a/src/Compilers/CSharp/Portable/Symbols/TypeSymbolExtensions.cs b/src/Compilers/CSharp/Portable/Symbols/TypeSymbolExtensions.cs index f9fb27a5617fa0c7efab7ad9499742b3086a07c5..026abe523d7893c3531ad9f31a5424551bd9ff40 100644 --- a/src/Compilers/CSharp/Portable/Symbols/TypeSymbolExtensions.cs +++ b/src/Compilers/CSharp/Portable/Symbols/TypeSymbolExtensions.cs @@ -509,7 +509,6 @@ public static TypeSymbol VisitType(this TypeSymbol type, Func V_0, //x - System.Runtime.CompilerServices.ValueTuple V_1) + System.Runtime.CompilerServices.ValueTuple> V_1) IL_0000: ldloca.s V_0 IL_0002: ldc.i4.1 IL_0003: ldc.i4.2 IL_0004: ldc.i4.3 IL_0005: ldc.i4.4 IL_0006: newobj ""System.Runtime.CompilerServices.ValueTuple..ctor(int, int)"" - IL_000b: newobj ""System.Runtime.CompilerServices.ValueTuple..ctor(int, )"" + IL_000b: newobj ""System.Runtime.CompilerServices.ValueTuple>..ctor(int, )"" IL_0010: stloc.1 IL_0011: ldloca.s V_1 - IL_0013: constrained. ""System.Runtime.CompilerServices.ValueTuple"" + IL_0013: constrained. ""System.Runtime.CompilerServices.ValueTuple>"" IL_0019: callvirt ""string object.ToString()"" IL_001e: call ""System.Runtime.CompilerServices.ValueTuple..ctor(int, string)"" IL_0023: ldloca.s V_0 @@ -277,30 +275,30 @@ static void Main() { // Code size 87 (0x57) .maxstack 4 - .locals init (System.Runtime.CompilerServices.ValueTuple V_0) //x + .locals init (System.Runtime.CompilerServices.ValueTuple> V_0) //x IL_0000: ldloca.s V_0 IL_0002: ldc.i4.1 IL_0003: ldc.i4.2 IL_0004: ldc.i4.3 IL_0005: newobj ""System.Runtime.CompilerServices.ValueTuple..ctor(int, int)"" - IL_000a: call ""System.Runtime.CompilerServices.ValueTuple..ctor(int, )"" + IL_000a: call ""System.Runtime.CompilerServices.ValueTuple>..ctor(int, )"" IL_000f: ldloca.s V_0 - IL_0011: ldflda "" System.Runtime.CompilerServices.ValueTuple.Item2"" + IL_0011: ldflda "" System.Runtime.CompilerServices.ValueTuple>.Item2"" IL_0016: ldflda ""int System.Runtime.CompilerServices.ValueTuple.Item1"" IL_001b: call ""string int.ToString()"" IL_0020: call ""void System.Console.WriteLine(string)"" IL_0025: ldloca.s V_0 - IL_0027: ldflda "" System.Runtime.CompilerServices.ValueTuple.Item2"" + IL_0027: ldflda "" System.Runtime.CompilerServices.ValueTuple>.Item2"" IL_002c: ldc.i4.s 39 IL_002e: stfld ""int System.Runtime.CompilerServices.ValueTuple.Item2"" IL_0033: ldloc.0 - IL_0034: ldfld ""int System.Runtime.CompilerServices.ValueTuple.Item1"" + IL_0034: ldfld ""int System.Runtime.CompilerServices.ValueTuple>.Item1"" IL_0039: ldloc.0 - IL_003a: ldfld "" System.Runtime.CompilerServices.ValueTuple.Item2"" + IL_003a: ldfld "" System.Runtime.CompilerServices.ValueTuple>.Item2"" IL_003f: ldfld ""int System.Runtime.CompilerServices.ValueTuple.Item1"" IL_0044: add IL_0045: ldloc.0 - IL_0046: ldfld "" System.Runtime.CompilerServices.ValueTuple.Item2"" + IL_0046: ldfld "" System.Runtime.CompilerServices.ValueTuple>.Item2"" IL_004b: ldfld ""int System.Runtime.CompilerServices.ValueTuple.Item2"" IL_0050: add IL_0051: call ""void System.Console.WriteLine(int)"" diff --git a/src/Compilers/Core/Portable/Symbols/ITypeSymbol.cs b/src/Compilers/Core/Portable/Symbols/ITypeSymbol.cs index e6f96210c916589641445178c0a704dae417e2b6..af5a301b41bced46d2cd9ec212f92fbe39a2ab63 100644 --- a/src/Compilers/Core/Portable/Symbols/ITypeSymbol.cs +++ b/src/Compilers/Core/Portable/Symbols/ITypeSymbol.cs @@ -64,6 +64,11 @@ public interface ITypeSymbol : INamespaceOrTypeSymbol /// bool IsAnonymousType { get; } + /// + /// Is this a symbol for a tuple . + /// + bool IsTupleType { get; } + /// /// The original definition of this symbol. If this symbol is constructed from another /// symbol by type substitution then gets the original symbol as it was defined in diff --git a/src/Compilers/Core/Portable/Symbols/SymbolKind.cs b/src/Compilers/Core/Portable/Symbols/SymbolKind.cs index b575bfa1b1936af3241b45a111def965a98df64b..51d5c05be3e188d42c305799e4b1f06e5fc5f284 100644 --- a/src/Compilers/Core/Portable/Symbols/SymbolKind.cs +++ b/src/Compilers/Core/Portable/Symbols/SymbolKind.cs @@ -101,10 +101,5 @@ public enum SymbolKind /// Symbol is a preprocessing/conditional compilation constant. /// Preprocessing = 18, - - /// - /// Symbol is a tuple type. - /// - TupleType = 19, } } diff --git a/src/Compilers/Core/Portable/Symbols/SymbolVisitor.cs b/src/Compilers/Core/Portable/Symbols/SymbolVisitor.cs index 033765b079d329063f307b1390ba7399b95c2210..e75255454298834207223a49966e24ccebf9dfd3 100644 --- a/src/Compilers/Core/Portable/Symbols/SymbolVisitor.cs +++ b/src/Compilers/Core/Portable/Symbols/SymbolVisitor.cs @@ -23,11 +23,6 @@ public virtual void VisitArrayType(IArrayTypeSymbol symbol) DefaultVisit(symbol); } - public virtual void VisitTupleType(ITupleTypeSymbol symbol) - { - DefaultVisit(symbol); - } - public virtual void VisitAssembly(IAssemblySymbol symbol) { DefaultVisit(symbol); diff --git a/src/Compilers/Core/Portable/Symbols/SymbolVisitor`1.cs b/src/Compilers/Core/Portable/Symbols/SymbolVisitor`1.cs index 002538faab0666b1da3093bb7e7db097636042d0..8c0e8d2deab44278813ec4494c9fd0e11b698bf7 100644 --- a/src/Compilers/Core/Portable/Symbols/SymbolVisitor`1.cs +++ b/src/Compilers/Core/Portable/Symbols/SymbolVisitor`1.cs @@ -26,11 +26,6 @@ public virtual TResult VisitArrayType(IArrayTypeSymbol symbol) return DefaultVisit(symbol); } - public virtual TResult VisitTupleType(ITupleTypeSymbol symbol) - { - return DefaultVisit(symbol); - } - public virtual TResult VisitAssembly(IAssemblySymbol symbol) { return DefaultVisit(symbol); diff --git a/src/Compilers/Core/Portable/Symbols/TypeKind.cs b/src/Compilers/Core/Portable/Symbols/TypeKind.cs index 6b894cd1a1d29ea4baa049b06ee738615b05894e..8ce52d1afb05c62c7fa76e2c2da7022c72b5dfbc 100644 --- a/src/Compilers/Core/Portable/Symbols/TypeKind.cs +++ b/src/Compilers/Core/Portable/Symbols/TypeKind.cs @@ -79,10 +79,5 @@ public enum TypeKind : byte /// Type is an interactive submission. /// Submission = 12, - - /// - /// Type is a tuple. - /// - Tuple = 13, } } diff --git a/src/Compilers/VisualBasic/Portable/Symbols/TypeSymbol.vb b/src/Compilers/VisualBasic/Portable/Symbols/TypeSymbol.vb index 304c59fea170a4cb1aaa9e44a85400740ae784b0..70e0036c8055b8988c024767c2137639cef87b5c 100644 --- a/src/Compilers/VisualBasic/Portable/Symbols/TypeSymbol.vb +++ b/src/Compilers/VisualBasic/Portable/Symbols/TypeSymbol.vb @@ -452,6 +452,13 @@ Done: End Get End Property + Private ReadOnly Property ITypeSymbol_IsTupleSymbol As Boolean Implements ITypeSymbol.IsTupleType + Get + ' PROTOTYPE: VB does not yet support tuples. + Return False + End Get + End Property + Private ReadOnly Property ITypeSymbol_TypeKind As TypeKind Implements ITypeSymbol.TypeKind Get Return Me.TypeKind.ToCommon() diff --git a/src/Features/Core/Portable/MetadataAsSource/AbstractMetadataAsSourceService.WrappedNamedTypeSymbol.cs b/src/Features/Core/Portable/MetadataAsSource/AbstractMetadataAsSourceService.WrappedNamedTypeSymbol.cs index 6cc81f6d173cf49e639b9fa1cdc4d4c1c4521797..5f43e2f7d6ddf4b3ec830e5c39bd30b82c968155 100644 --- a/src/Features/Core/Portable/MetadataAsSource/AbstractMetadataAsSourceService.WrappedNamedTypeSymbol.cs +++ b/src/Features/Core/Portable/MetadataAsSource/AbstractMetadataAsSourceService.WrappedNamedTypeSymbol.cs @@ -243,6 +243,14 @@ public bool IsAnonymousType } } + public bool IsTupleType + { + get + { + return _symbol.IsTupleType; + } + } + ITypeSymbol ITypeSymbol.OriginalDefinition { get diff --git a/src/Workspaces/Core/Portable/CodeGeneration/Symbols/CodeGenerationTypeSymbol.cs b/src/Workspaces/Core/Portable/CodeGeneration/Symbols/CodeGenerationTypeSymbol.cs index 54d0331b15faf8eab36ef3af3a4b43a0f6661abc..3fec5eddccd16be9be99fa4608515b2f3900fb5b 100644 --- a/src/Workspaces/Core/Portable/CodeGeneration/Symbols/CodeGenerationTypeSymbol.cs +++ b/src/Workspaces/Core/Portable/CodeGeneration/Symbols/CodeGenerationTypeSymbol.cs @@ -74,6 +74,14 @@ public bool IsAnonymousType } } + public bool IsTupleType + { + get + { + return false; + } + } + public new ITypeSymbol OriginalDefinition { get