未验证 提交 f2c528f6 编写于 作者: J Julien Couvreur 提交者: GitHub

Treat 0- and 1-tuple symbols as tuples (#40459)

上级 94d1d143
......@@ -454,7 +454,7 @@ private bool CanUseTupleSyntax(INamedTypeSymbol tupleSymbol)
return false;
}
if (currentUnderlying.Arity == 1)
if (currentUnderlying.Arity <= 1)
{
return false;
}
......
......@@ -236,11 +236,14 @@ private NamedTypeSymbol DecodeNamedType(NamedTypeSymbol type)
if (decodedType.IsTupleType)
{
int tupleCardinality = decodedType.TupleElementTypesWithAnnotations.Length;
var elementNames = EatElementNamesIfAvailable(tupleCardinality);
if (tupleCardinality > 0)
{
var elementNames = EatElementNamesIfAvailable(tupleCardinality);
Debug.Assert(elementNames.IsDefault || elementNames.Length == tupleCardinality);
Debug.Assert(elementNames.IsDefault || elementNames.Length == tupleCardinality);
decodedType = NamedTypeSymbol.CreateTuple(decodedType, elementNames);
decodedType = NamedTypeSymbol.CreateTuple(decodedType, elementNames);
}
}
return decodedType;
......
......@@ -1485,7 +1485,7 @@ internal bool IsTupleTypeOfCardinality(out int tupleCardinality)
{
int arity = Arity;
if (arity > 0 && arity < ValueTupleRestPosition)
if (arity >= 0 && arity < ValueTupleRestPosition)
{
tupleCardinality = arity;
return true;
......
......@@ -586,7 +586,7 @@ private static bool IsNonGenericValueType(TypeSymbol type)
{
return type.IsNullableType();
}
return type.IsValueType && !type.IsTupleType;
return type.IsValueType;
}
public void AddNullableTransforms(ArrayBuilder<byte> transforms)
......
......@@ -489,7 +489,8 @@ private void ValidateAttributesOnFields()
// public static ValueTuple Field7;
var field7 = _derivedClass.GetMember<FieldSymbol>("Field7");
ValidateTupleNameAttribute(field7.GetAttributes(), expectedTupleNamesAttribute: false);
Assert.False(field7.Type.IsTupleType);
Assert.True(field7.Type.IsTupleType);
Assert.Empty(field7.Type.TupleElementTypesWithAnnotations);
// public static (int e1, int e2, int e3, int e4, int e5, int e6, int e7, int e8, int e9) Field8;
var field8 = _derivedClass.GetMember<FieldSymbol>("Field8");
......
......@@ -5799,6 +5799,65 @@ public void CreateTupleTypeSymbol_BadArguments()
Assert.Contains(CodeAnalysisResources.TupleElementLocationCountMismatch, e.Message);
}
[Fact, WorkItem(36676, "https://github.com/dotnet/roslyn/issues/36676")]
public void CreateTupleTypeSymbol_WithValueTuple_TupleZero()
{
var tupleComp = CreateCompilationWithMscorlib40(@"
namespace System
{
public struct ValueTuple
{
}
}");
var comp = CSharpCompilation.Create("test", references: new[] { MscorlibRef, tupleComp.ToMetadataReference() });
var vt0 = comp.GetWellKnownType(WellKnownType.System_ValueTuple);
var tupleWithoutNames = comp.CreateTupleTypeSymbol(vt0, ImmutableArray<string>.Empty);
Assert.True(tupleWithoutNames.IsTupleType);
Assert.Equal(SymbolKind.NamedType, tupleWithoutNames.TupleUnderlyingType.Kind);
Assert.Equal("System.ValueTuple", tupleWithoutNames.ToTestDisplayString());
Assert.True(GetTupleElementNames(tupleWithoutNames).IsDefault);
Assert.Empty(ElementTypeNames(tupleWithoutNames));
Assert.Equal(SymbolKind.NamedType, tupleWithoutNames.Kind);
TypeSymbol intType = comp.GetSpecialType(SpecialType.System_Int32);
TypeSymbol stringType = comp.GetSpecialType(SpecialType.System_String);
var vt8 = comp.GetWellKnownType(WellKnownType.System_ValueTuple_TRest)
.Construct(intType, stringType, intType, stringType, intType, stringType, intType, vt0);
Assert.False(vt8.IsTupleType);
Assert.Throws<ArgumentException>(() => comp.CreateTupleTypeSymbol(vt8, default));
}
[Fact, WorkItem(36676, "https://github.com/dotnet/roslyn/issues/36676")]
public void CreateTupleTypeSymbol_WithValueTuple_TupleOne()
{
var tupleComp = CreateCompilationWithMscorlib40(@"
namespace System
{
public struct ValueTuple<T1>
{
public T1 Item1;
public ValueTuple(T1 item1)
{
Item1 = item1;
}
}
}");
var comp = CSharpCompilation.Create("test", references: new[] { MscorlibRef, tupleComp.ToMetadataReference() });
TypeSymbol intType = comp.GetSpecialType(SpecialType.System_Int32);
var vt1 = comp.GetWellKnownType(WellKnownType.System_ValueTuple_T1).Construct(intType);
var tupleWithoutNames = comp.CreateTupleTypeSymbol(vt1, ImmutableArray.Create(new[] { (string)null }));
Assert.Same(vt1, ((Symbols.PublicModel.NonErrorNamedTypeSymbol)tupleWithoutNames).UnderlyingNamedTypeSymbol);
Assert.True(tupleWithoutNames.IsTupleType);
Assert.Equal("System.ValueTuple<System.Int32>", tupleWithoutNames.ToTestDisplayString());
Assert.True(GetTupleElementNames(tupleWithoutNames).IsDefault);
Assert.Equal(new[] { "System.Int32" }, ElementTypeNames(tupleWithoutNames));
}
[Fact]
public void CreateTupleTypeSymbol_WithValueTuple()
{
......@@ -612,6 +612,7 @@ public void AllWellKnownTypes()
switch (wkt)
{
case WellKnownType.System_ValueTuple:
case WellKnownType.System_ValueTuple_T1:
case WellKnownType.System_ValueTuple_T2:
case WellKnownType.System_ValueTuple_T3:
......
......@@ -2631,31 +2631,31 @@ static WellKnownMembers()
// System_ValueTuple_T5__Item1
(byte)MemberFlags.Field, // Flags
(byte)WellKnownType.System_ValueTuple_T5, // DeclaringTypeId
(byte)WellKnownType.ExtSentinel, (byte)(WellKnownType.System_ValueTuple_T5 - WellKnownType.ExtSentinel), // DeclaringTypeId
0, // Arity
(byte)SignatureTypeCode.GenericTypeParameter, 0, // Field Signature
// System_ValueTuple_T5__Item2
(byte)MemberFlags.Field, // Flags
(byte)WellKnownType.System_ValueTuple_T5, // DeclaringTypeId
(byte)WellKnownType.ExtSentinel, (byte)(WellKnownType.System_ValueTuple_T5 - WellKnownType.ExtSentinel), // DeclaringTypeId
0, // Arity
(byte)SignatureTypeCode.GenericTypeParameter, 1, // Field Signature
// System_ValueTuple_T5__Item3
(byte)MemberFlags.Field, // Flags
(byte)WellKnownType.System_ValueTuple_T5, // DeclaringTypeId
(byte)WellKnownType.ExtSentinel, (byte)(WellKnownType.System_ValueTuple_T5 - WellKnownType.ExtSentinel), // DeclaringTypeId
0, // Arity
(byte)SignatureTypeCode.GenericTypeParameter, 2, // Field Signature
// System_ValueTuple_T5__Item4
(byte)MemberFlags.Field, // Flags
(byte)WellKnownType.System_ValueTuple_T5, // DeclaringTypeId
(byte)WellKnownType.ExtSentinel, (byte)(WellKnownType.System_ValueTuple_T5 - WellKnownType.ExtSentinel), // DeclaringTypeId
0, // Arity
(byte)SignatureTypeCode.GenericTypeParameter, 3, // Field Signature
// System_ValueTuple_T5__Item5
(byte)MemberFlags.Field, // Flags
(byte)WellKnownType.System_ValueTuple_T5, // DeclaringTypeId
(byte)WellKnownType.ExtSentinel, (byte)(WellKnownType.System_ValueTuple_T5 - WellKnownType.ExtSentinel), // DeclaringTypeId
0, // Arity
(byte)SignatureTypeCode.GenericTypeParameter, 4, // Field Signature
......@@ -2825,7 +2825,7 @@ static WellKnownMembers()
// System_ValueTuple_T_T2_T3_T4_T5__ctor
(byte)MemberFlags.Constructor, // Flags
(byte)WellKnownType.System_ValueTuple_T5, // DeclaringTypeId
(byte)WellKnownType.ExtSentinel, (byte)(WellKnownType.System_ValueTuple_T5 - WellKnownType.ExtSentinel), // DeclaringTypeId
0, // Arity
5, // Method Signature
(byte)SignatureTypeCode.TypeHandle, (byte)SpecialType.System_Void, // Return Type
......
......@@ -250,14 +250,15 @@ internal enum WellKnownType
CSharp7Sentinel = System_IFormatProvider, // all types that were known before CSharp7 should remain above this sentinel
System_ValueTuple,
System_ValueTuple_T1,
System_ValueTuple_T2,
System_ValueTuple_T3,
System_ValueTuple_T4,
System_ValueTuple_T5,
ExtSentinel, // Not a real type, just a marker for types above 255 and strictly below 512
System_ValueTuple_T5,
System_ValueTuple_T6,
System_ValueTuple_T7,
System_ValueTuple_TRest,
......@@ -550,14 +551,15 @@ internal static class WellKnownTypes
"System.IFormatProvider",
"System.ValueTuple",
"System.ValueTuple`1",
"System.ValueTuple`2",
"System.ValueTuple`3",
"System.ValueTuple`4",
"System.ValueTuple`5",
"", // extension marker
"System.ValueTuple`5",
"System.ValueTuple`6",
"System.ValueTuple`7",
"System.ValueTuple`8",
......@@ -675,7 +677,7 @@ public static bool IsWellKnownType(this WellKnownType typeId)
public static bool IsValueTupleType(this WellKnownType typeId)
{
Debug.Assert(typeId != WellKnownType.ExtSentinel);
return typeId >= WellKnownType.System_ValueTuple_T1 && typeId <= WellKnownType.System_ValueTuple_TRest;
return typeId >= WellKnownType.System_ValueTuple && typeId <= WellKnownType.System_ValueTuple_TRest;
}
public static bool IsValid(this WellKnownType typeId)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册