/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/Compilers/CSharp/Test/Emit3/Attributes/AttributeTests_Tuples.cs
1 053 строки
63 KB
Tomáš Matoušek
Move some emit tests from Emit2 to Emit3 to avoid hitting UserString heap limit (#75091)
13 сен 2024, 12:01
Не верифицирован
13 сен 2024, 12:01
814c61c
Код
Авторство
О чём код?
// 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. #nullable disable using System; using System.Collections.Immutable; using System.Linq; using System.Reflection.Metadata; using Microsoft.CodeAnalysis.CSharp.Symbols; using Microsoft.CodeAnalysis.CSharp.Test.Utilities; using Microsoft.CodeAnalysis.PooledObjects; using Microsoft.CodeAnalysis.Test.Utilities; using Roslyn.Test.Utilities; using Xunit; namespace Microsoft.CodeAnalysis.CSharp.UnitTests { public class AttributeTests_Tuples : WellKnownAttributesTestBase { private static readonly string s_tuplesTestSource = @" using System; public class Base0 { } public class Base1<T> { } public class Base2<T, U> { } public class Outer<T> : Base1<(int key, int val)> { public class Inner<U, V> : Base2<(int key2, int val2), V> { public class InnerInner<W> : Base1<(int key3, int val3)> { } } } public class Derived<T> : Outer<(int e1, (int e2, int e3) e4)>.Inner< Outer<(int e5, int e6)>.Inner<(int e7, int e8)[], (int e9, int e10)>.InnerInner<int>[], ((int e11, int e12) e13, int e14)> .InnerInner<((int e15, int e16) e17, (int e18, Base1<(int e19, int e20)> e21) e22)> { public static (int e1, int e2) Field1; public static (int e1, int e2) Field2; public static Base1<(int e1, (int e2, int e3) e4)> Field3; public static ValueTuple<Base1<(int e1, (int, (dynamic, dynamic)) e2)>, int> Field4; public static Outer<(object e1, dynamic e2)> .Inner<(dynamic e3, object e4), ValueTuple<dynamic, dynamic>> Field5; // No names public static Base1<(int, ValueTuple<int, ValueTuple>)> Field6; public static ValueTuple Field7; // Long tuples public static (int e1, int e2, int e3, int e4, int e5, int e6, int e7, int e8, int e9) Field8; public static Base1<(int e1, int e2, int e3, int e4, int e5, int e6, int e7, int e8, int e9)> Field9; public static (int e1, int e2) Method1() => (0, 0); public static void Method2((int e1, int e2) x) { } public static (int e1, int e2) Method3((int e3, int e4) x) => (0, 0); public static (int e1, int e2) Method4(ref (int e3, int e4) x) => x; public static ((int, (object, (dynamic, object)), object, int), ValueTuple) Method5(ref (object,dynamic) x) => ((0, (null, (null, null)), null, 0), default(ValueTuple)); public static (int e1, int e2, int e3, int e4, int e5, int e6, int e7, int e8, int e9) Method6() => (0, 0, 0, 0, 0, 0, 0, 0, 0); public static (int e1, int e2) Prop1 => (0, 0); public static (int e1, int e2) Prop2 { get; set; } public (int e1, int e2) this[(int e3, int e4) param] { get { return param; } set {} } public delegate void Delegate1<V>(object sender, ValueTuple<V, ((dynamic e1, dynamic e2, object e3) e4, dynamic e5), (dynamic, object)> args); public static event Delegate1<(dynamic e1, ValueTuple<(dynamic e2, dynamic e3)> e4)> Event1 { add { } remove { } } }"; private static readonly MetadataReference[] s_attributeRefs = { ValueTupleRef, SystemRuntimeFacadeRef, SystemCoreRef, CSharpRef }; [Fact] public void TestCompile() { CompileAndVerifyWithMscorlib40(s_tuplesTestSource, options: TestOptions.ReleaseDll, references: s_attributeRefs); } [Fact] public void TestTupleAttributes() { var comp = CreateCompilationWithMscorlib40(s_tuplesTestSource, options: TestOptions.UnsafeReleaseDll, references: s_attributeRefs); CompileAndVerify(comp, verify: Verification.Passes, symbolValidator: module => { TupleAttributeValidator.ValidateTupleAttributes(module); }); } [Fact] public void TupleAttributeWithOnlyOneConstructor() { var comp = CreateCompilationWithMscorlib40( s_tuplesTestSource + TestResources.NetFX.ValueTuple.tuplelib_cs + @" namespace System.Runtime.CompilerServices { /// <summary> /// Indicates that the use of <see cref=""System.ValueTuple""/> on a member is meant to be treated as a tuple with element names. /// </summary> [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.ReturnValue | AttributeTargets.Class | AttributeTargets.Struct )] public sealed class TupleElementNamesAttribute : Attribute { public TupleElementNamesAttribute(string[] transformNames) { } } }", references: new[] { SystemCoreRef }, options: TestOptions.ReleaseDll); comp.VerifyDiagnostics(); CompileAndVerify(comp, symbolValidator: module => { TupleAttributeValidator.ValidateTupleAttributes(module); }); } [Fact] public void TupleLambdaParametersMissingString() { var source0 = @"namespace System { public class Object { } public class ValueType { } public struct Void { } public struct IntPtr { } public struct Int32 { } public class MulticastDelegate { } }"; var source1 = @"delegate void D<T>(T t); class C { static void Main() { D<(int x, int y)> d = o => { }; d((0, 0)); } }"; var parseOptions = TestOptions.Regular.WithNoRefSafetyRulesAttribute(); var comp = CreateEmptyCompilation(source0, parseOptions: parseOptions); comp.VerifyDiagnostics(); var ref0 = comp.EmitToImageReference(); comp = CreateEmptyCompilation(source1, parseOptions: parseOptions, references: s_attributeRefs.Concat(new[] { ref0 })); comp.VerifyDiagnostics( // (6,11): error CS0518: Predefined type 'System.String' is not defined or imported // D<(int x, int y)> d = o => { }; Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "(int x, int y)").WithArguments("System.String").WithLocation(6, 11), // (6,11): error CS0012: The type 'ValueType' is defined in an assembly that is not referenced. You must add a reference to assembly 'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'. // D<(int x, int y)> d = o => { }; Diagnostic(ErrorCode.ERR_NoTypeDef, "(int x, int y)").WithArguments("System.ValueType", "mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089").WithLocation(6, 11), // (7,11): error CS0012: The type 'ValueType' is defined in an assembly that is not referenced. You must add a reference to assembly 'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'. // d((0, 0)); Diagnostic(ErrorCode.ERR_NoTypeDef, "(0, 0)").WithArguments("System.ValueType", "mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089").WithLocation(7, 11) ); } [Fact] public void TupleInDeclarationFailureWithoutString() { var source0 = @"namespace System { public class Object { } public class ValueType { } public struct Void { } public struct IntPtr { } public struct Int32 { } }"; var source1 = @" class C { static (int x, int y) M() => (0, 0); }"; var parseOptions = TestOptions.Regular.WithNoRefSafetyRulesAttribute(); var comp = CreateEmptyCompilation(source0, parseOptions: parseOptions); comp.VerifyDiagnostics(); var ref0 = comp.EmitToImageReference(); comp = CreateEmptyCompilation(source1, parseOptions: parseOptions, references: new[] { ref0, ValueTupleRef }); comp.VerifyDiagnostics( // (4,12): error CS0518: Predefined type 'System.String' is not defined or imported // static (int x, int y) M() => (0, 0); Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "(int x, int y)").WithArguments("System.String").WithLocation(4, 12), // (4,12): error CS0012: The type 'ValueType' is defined in an assembly that is not referenced. You must add a reference to assembly 'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'. // static (int x, int y) M() => (0, 0); Diagnostic(ErrorCode.ERR_NoTypeDef, "(int x, int y)").WithArguments("System.ValueType", "mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089").WithLocation(4, 12), // (4,34): error CS0012: The type 'ValueType' is defined in an assembly that is not referenced. You must add a reference to assembly 'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'. // static (int x, int y) M() => (0, 0); Diagnostic(ErrorCode.ERR_NoTypeDef, "(0, 0)").WithArguments("System.ValueType", "mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089").WithLocation(4, 34) ); } [Fact] public void RoundTrip() { ModuleSymbol sourceModule = null; ModuleSymbol peModule = null; CompileAndVerifyWithMscorlib40(s_tuplesTestSource, options: TestOptions.UnsafeReleaseDll, references: s_attributeRefs, verify: Verification.Passes, sourceSymbolValidator: m => sourceModule = m, symbolValidator: m => peModule = m); var srcTypes = sourceModule.GlobalNamespace.GetTypeMembers(); var peTypes = peModule.GlobalNamespace.GetTypeMembers() .WhereAsArray(t => t.Name != "<Module>"); Assert.Equal(srcTypes.Length, peTypes.Length); for (int i = 0; i < srcTypes.Length; i++) { var srcType = srcTypes[i]; var peType = peTypes[i]; Assert.Equal(ToTestString(srcType.BaseType()), ToTestString(peType.BaseType())); var srcMembers = srcType.GetMembers() .Where(m => !m.Name.Contains("k__BackingField")) .Select(ToTestString) .ToList(); var peMembers = peType.GetMembers() .Select(ToTestString) .ToList(); srcMembers.Sort(); peMembers.Sort(); AssertEx.Equal(srcMembers, peMembers); } } private static string ToTestString(Symbol symbol) { var typeSymbols = ArrayBuilder<TypeSymbol>.GetInstance(); switch (symbol.Kind) { case SymbolKind.Method: var methodSymbol = (MethodSymbol)symbol; typeSymbols.Add(methodSymbol.ReturnType); foreach (var parameterType in methodSymbol.ParameterTypesWithAnnotations) { typeSymbols.Add(parameterType.Type); } break; case SymbolKind.NamedType: var namedType = (NamedTypeSymbol)symbol; typeSymbols.Add(namedType.BaseType() ?? namedType); break; case SymbolKind.Field: typeSymbols.Add(((FieldSymbol)symbol).Type); break; case SymbolKind.Property: typeSymbols.Add(((PropertySymbol)symbol).Type); break; case SymbolKind.Event: typeSymbols.Add(((EventSymbol)symbol).Type); break; } var symbolString = string.Join(" | ", typeSymbols .Select(s => s.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat))); typeSymbols.Free(); return $"{symbol.Name}: {symbolString}"; } private readonly struct TupleAttributeValidator { private readonly NamedTypeSymbol _base0Class, _base1Class, _base2Class, _outerClass, _derivedClass; private TupleAttributeValidator(ModuleSymbol module) { var globalNs = module.GlobalNamespace; _base0Class = globalNs.GetTypeMember("Base0"); _base1Class = globalNs.GetTypeMember("Base1"); _base2Class = globalNs.GetTypeMember("Base2"); _outerClass = globalNs.GetTypeMember("Outer"); _derivedClass = globalNs.GetTypeMember("Derived"); } internal static void ValidateTupleAttributes(ModuleSymbol module) { var validator = new TupleAttributeValidator(module); validator.ValidateAttributesOnNamedTypes(); validator.ValidateAttributesOnFields(); validator.ValidateAttributesOnMethods(); validator.ValidateAttributesOnProperties(); validator.ValidateAttributesOnEvents(); validator.ValidateAttributesOnDelegates(); } private void ValidateAttributesOnDelegates() { // public delegate void Delegate1<T>(object sender, // ValueTuple<T, // ((dynamic e1, dynamic e2, object e3) e4, dynamic e5), // (dynamic, object)> args); var delegate1 = _derivedClass.GetMember<NamedTypeSymbol>("Delegate1"); Assert.NotNull(delegate1); Assert.True(delegate1.IsDelegateType()); var invokeMethod = delegate1.DelegateInvokeMethod; Assert.NotNull(invokeMethod); ValidateTupleNameAttribute(invokeMethod.GetAttributes(), expectedTupleNamesAttribute: false); Assert.Equal(2, invokeMethod.ParameterCount); var sender = invokeMethod.Parameters[0]; Assert.Equal("sender", sender.Name); Assert.Equal(SpecialType.System_Object, sender.Type.SpecialType); ValidateTupleNameAttribute(sender.GetAttributes(), expectedTupleNamesAttribute: false); var args = invokeMethod.Parameters[1]; Assert.Equal("args", args.Name); var expectedElementNames = new[] { null, null, null, "e4", "e5", "e1", "e2", "e3", null, null }; ValidateTupleNameAttribute(args.GetAttributes(), expectedTupleNamesAttribute: true, expectedElementNames: expectedElementNames); AttributeTests_Dynamic.DynamicAttributeValidator.ValidateDynamicAttribute( args.GetAttributes(), expectedDynamicAttribute: true, expectedTransformFlags: new[] { false, false, false, false, true, true, false, true, false, true, false }); } private void ValidateAttributesOnEvents() { // public static event Delegate1<(dynamic e1, // ValueTuple<(dynamic e2, dynamic e3)> e4)> Event1; var event1 = _derivedClass.GetMember<EventSymbol>("Event1"); Assert.NotNull(event1); ValidateTupleNameAttribute(event1.GetAttributes(), expectedTupleNamesAttribute: true, expectedElementNames: new[] { "e1", "e4", null, "e2", "e3" }); AttributeTests_Dynamic.DynamicAttributeValidator.ValidateDynamicAttribute( event1.GetAttributes(), expectedDynamicAttribute: true, expectedTransformFlags: new[] { false, false, false, true, false, false, true, true }); } private void ValidateAttributesOnNamedTypes() { // public class Base0 { } ValidateTupleNameAttribute(_base0Class.GetAttributes(), expectedTupleNamesAttribute: false); // public class Base1<T> { } ValidateTupleNameAttribute(_base1Class.GetAttributes(), expectedTupleNamesAttribute: false); // public class Base2<T, U> { } ValidateTupleNameAttribute(_base2Class.GetAttributes(), expectedTupleNamesAttribute: false); // public class Outer<T> : Base1<(int key, int val)> Assert.True(_outerClass.BaseType().ContainsTuple()); var expectedElementNames = new[] { "key", "val" }; ValidateTupleNameAttribute(_outerClass.GetAttributes(), expectedTupleNamesAttribute: true, expectedElementNames: expectedElementNames); // public class Derived<T> : Outer<(int e1, (int e2, int e3) e4)>.Inner< // Outer<(int e5, int e6)>.Inner<(int e7, int e8)[], (int e9, int e10)>.InnerInner<int>[], // ((int e11, int e12) e13, int e14)> // .InnerInner<((int e15, int e16) e17, (int e18, Base1<(int e19, int e20)> e21) e22)> expectedElementNames = new[] { "e1", "e4", "e2", "e3", "e5", "e6", "e7", "e8", "e9", "e10", "e13", "e14", "e11", "e12", "e17", "e22", "e15", "e16", "e18", "e21", "e19", "e20" }; ValidateTupleNameAttribute(_derivedClass.GetAttributes(), expectedTupleNamesAttribute: true, expectedElementNames: expectedElementNames); } private void ValidateAttributesOnFields() { // public static (int e1, int e2) Field1; var field1 = _derivedClass.GetMember<FieldSymbol>("Field1"); var expectedElementNames = new[] { "e1", "e2" }; ValidateTupleNameAttribute(field1.GetAttributes(), expectedTupleNamesAttribute: true, expectedElementNames: expectedElementNames); // public static (int e1, int e2) Field2; var field2 = _derivedClass.GetMember<FieldSymbol>("Field2"); expectedElementNames = new[] { "e1", "e2" }; ValidateTupleNameAttribute(field2.GetAttributes(), expectedTupleNamesAttribute: true, expectedElementNames: expectedElementNames); // public static Base1<(int e1, (int e2, int e3) e4)> Field3; var field3 = _derivedClass.GetMember<FieldSymbol>("Field3"); expectedElementNames = new[] { "e1", "e4", "e2", "e3" }; ValidateTupleNameAttribute(field3.GetAttributes(), expectedTupleNamesAttribute: true, expectedElementNames: expectedElementNames); // public static ValueTuple<Base1<(int e1, (int, (dynamic, dynamic)) e2)>, int> Field4; var field4 = _derivedClass.GetMember<FieldSymbol>("Field4"); expectedElementNames = new[] { null, null, "e1", "e2", null, null, null, null }; ValidateTupleNameAttribute(field4.GetAttributes(), expectedTupleNamesAttribute: true, expectedElementNames: expectedElementNames); AttributeTests_Dynamic.DynamicAttributeValidator.ValidateDynamicAttribute( field4.GetAttributes(), expectedDynamicAttribute: true, expectedTransformFlags: new[] { false, false, false, false, false, false, false, true, true, false }); // public static Outer<(object e1, dynamic e2)> // .Inner<(dynamic e3, object e4), // ValueTuple<dynamic, dynamic>> Field5; var field5 = _derivedClass.GetMember<FieldSymbol>("Field5"); expectedElementNames = new[] { "e1", "e2", "e3", "e4", null, null }; ValidateTupleNameAttribute(field5.GetAttributes(), expectedTupleNamesAttribute: true, expectedElementNames: expectedElementNames); AttributeTests_Dynamic.DynamicAttributeValidator.ValidateDynamicAttribute( field5.GetAttributes(), expectedDynamicAttribute: true, expectedTransformFlags: new[] { false, false, false, true, false, true, false, false, true, true }); // public static Base1<(int, ValueTuple<int, ValueTuple>)> Field6; var field6 = _derivedClass.GetMember<FieldSymbol>("Field6"); ValidateTupleNameAttribute(field6.GetAttributes(), expectedTupleNamesAttribute: false); var field6Type = Assert.IsType<ConstructedNamedTypeSymbol>(field6.Type); Assert.Equal("Base1", field6Type.Name); Assert.Equal(1, field6Type.TypeParameters.Length); var firstTuple = field6Type.TypeArguments().Single(); Assert.True(firstTuple.IsTupleType); Assert.True(firstTuple.TupleElementNames.IsDefault); Assert.Equal(2, firstTuple.TupleElementTypesWithAnnotations.Length); var secondTuple = firstTuple.TupleElementTypesWithAnnotations[1].Type; Assert.True(secondTuple.IsTupleType); Assert.True(secondTuple.TupleElementNames.IsDefault); Assert.Equal(2, secondTuple.TupleElementTypesWithAnnotations.Length); // public static ValueTuple Field7; var field7 = _derivedClass.GetMember<FieldSymbol>("Field7"); ValidateTupleNameAttribute(field7.GetAttributes(), expectedTupleNamesAttribute: false); 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"); expectedElementNames = new[] { "e1", "e2", "e3", "e4", "e5", "e6", "e7", "e8", "e9", null, null }; ValidateTupleNameAttribute(field8.GetAttributes(), expectedTupleNamesAttribute: true, expectedElementNames: expectedElementNames); // public static Base<(int e1, int e2, int e3, int e4, int e5, int e6, int e7, int e8, int e9)> Field9; var field9 = _derivedClass.GetMember<FieldSymbol>("Field9"); expectedElementNames = new[] { "e1", "e2", "e3", "e4", "e5", "e6", "e7", "e8", "e9", null, null }; ValidateTupleNameAttribute(field9.GetAttributes(), expectedTupleNamesAttribute: true, expectedElementNames: expectedElementNames); } private void ValidateAttributesOnMethods() { // public static (int e1, int e2) Method1() => (0, 0); var method1 = _derivedClass.GetMember<MethodSymbol>("Method1"); var expectedElementNames = new[] { "e1", "e2" }; ValidateTupleNameAttribute(method1.GetReturnTypeAttributes(), expectedTupleNamesAttribute: true, expectedElementNames: expectedElementNames); // public static void Method2((int e1, int e2) x) { } var method2 = _derivedClass.GetMember<MethodSymbol>("Method2"); expectedElementNames = new[] { "e1", "e2" }; ValidateTupleNameAttribute(method2.Parameters.Single().GetAttributes(), expectedTupleNamesAttribute: true, expectedElementNames: expectedElementNames); // public static (int e1, int e2) Method3((int e3, int e4) x) => (0, 0); var method3 = _derivedClass.GetMember<MethodSymbol>("Method3"); expectedElementNames = new[] { "e1", "e2" }; ValidateTupleNameAttribute(method3.GetReturnTypeAttributes(), expectedTupleNamesAttribute: true, expectedElementNames: expectedElementNames); expectedElementNames = new[] { "e3", "e4" }; ValidateTupleNameAttribute(method3.Parameters.Single().GetAttributes(), expectedTupleNamesAttribute: true, expectedElementNames: expectedElementNames); // public static (int e1, int e2) Method4(ref (int e3, int e4) x) => x; var method4 = _derivedClass.GetMember<MethodSymbol>("Method4"); expectedElementNames = new[] { "e1", "e2" }; ValidateTupleNameAttribute(method4.GetReturnTypeAttributes(), expectedTupleNamesAttribute: true, expectedElementNames: expectedElementNames); expectedElementNames = new[] { "e3", "e4" }; ValidateTupleNameAttribute(method4.Parameters.Single().GetAttributes(), expectedTupleNamesAttribute: true, expectedElementNames: expectedElementNames); // public static ((int, // (object, (dynamic, object)), // object, // int), // ValueTuple) Method5(ref (object,dynamic) x) => // ((0, (null, (null, null)), null, 0), default(ValueTuple)); var method5 = _derivedClass.GetMember<MethodSymbol>("Method5"); ValidateTupleNameAttribute(method5.GetReturnTypeAttributes(), expectedTupleNamesAttribute: false); ValidateTupleNameAttribute(method5.Parameters.Single().GetAttributes(), expectedTupleNamesAttribute: false); // public static (int e1, int e2, int e3, int e4, int e5, // int e6, int e7, int e8, int e9) Method6() => (0, 0, 0, 0, // 0, 0, 0, 0, 0); var method6 = _derivedClass.GetMember<MethodSymbol>("Method6"); expectedElementNames = new[] { "e1", "e2", "e3", "e4", "e5", "e6", "e7", "e8", "e9", null, null }; ValidateTupleNameAttribute(method6.GetReturnTypeAttributes(), expectedTupleNamesAttribute: true, expectedElementNames: expectedElementNames); } private void ValidateAttributesOnProperties() { // public static (int e1, int e2) Prop1 => (0, 0); var prop1 = _derivedClass.GetMember("Prop1"); var expectedTupleNames = new[] { "e1", "e2" }; ValidateTupleNameAttribute(prop1.GetAttributes(), expectedTupleNamesAttribute: true, expectedElementNames: expectedTupleNames); // public static (int e1, int e2) Prop2 { get; set; } var prop2 = _derivedClass.GetMember("Prop2"); expectedTupleNames = new[] { "e1", "e2" }; ValidateTupleNameAttribute(prop2.GetAttributes(), expectedTupleNamesAttribute: true, expectedElementNames: expectedTupleNames); // public (int e1, int e2) this[(int e3, int e4) param] var indexer = (PropertySymbol)_derivedClass.GetMember("this[]"); expectedTupleNames = new[] { "e1", "e2" }; ValidateTupleNameAttribute(indexer.GetAttributes(), expectedTupleNamesAttribute: true, expectedElementNames: expectedTupleNames); expectedTupleNames = new[] { "e3", "e4" }; ValidateTupleNameAttribute(indexer.Parameters.Single().GetAttributes(), expectedTupleNamesAttribute: true, expectedElementNames: expectedTupleNames); } private void ValidateTupleNameAttribute( ImmutableArray<CSharpAttributeData> attributes, bool expectedTupleNamesAttribute, string[] expectedElementNames = null) { var synthesizedTupleElementNamesAttr = attributes.Where(attr => string.Equals(attr.AttributeClass.Name, "TupleElementNamesAttribute", StringComparison.Ordinal)); if (!expectedTupleNamesAttribute) { Assert.Empty(synthesizedTupleElementNamesAttr); Assert.Null(expectedElementNames); } else { var tupleAttr = synthesizedTupleElementNamesAttr.Single(); Assert.Equal("System.Runtime.CompilerServices.TupleElementNamesAttribute", tupleAttr.AttributeClass.ToTestDisplayString()); Assert.Equal("System.String[]", tupleAttr.AttributeConstructor.Parameters.Single().TypeWithAnnotations.ToTestDisplayString()); if (expectedElementNames == null) { Assert.True(tupleAttr.CommonConstructorArguments.IsEmpty); } else { var arg = tupleAttr.CommonConstructorArguments.Single(); Assert.Equal(TypedConstantKind.Array, arg.Kind); var actualElementNames = arg.Values.SelectAsArray(TypedConstantString); AssertEx.Equal(expectedElementNames, actualElementNames); } } } private static string TypedConstantString(TypedConstant constant) { Assert.True(constant.Type.SpecialType == SpecialType.System_String); return (string)constant.Value; } } [Fact] public void TupleAttributeMissing() { var comp = CreateCompilationWithMscorlib40( s_tuplesTestSource + TestResources.NetFX.ValueTuple.tuplelib_cs, references: new[] { SystemCoreRef }, options: TestOptions.ReleaseDll); comp.VerifyDiagnostics( // (8,31): error CS8137: Cannot define a class or member that utilizes tuples because the compiler required type 'System.Runtime.CompilerServices.TupleElementNamesAttribute' cannot be found. Are you missing a reference? // public class Outer<T> : Base1<(int key, int val)> Diagnostic(ErrorCode.ERR_TupleElementNamesAttributeMissing, "(int key, int val)").WithArguments("System.Runtime.CompilerServices.TupleElementNamesAttribute").WithLocation(8, 31), // (16,42): error CS8137: Cannot define a class or member that utilizes tuples because the compiler required type 'System.Runtime.CompilerServices.TupleElementNamesAttribute' cannot be found. Are you missing a reference? // public class Derived<T> : Outer<(int e1, (int e2, int e3) e4)>.Inner< Diagnostic(ErrorCode.ERR_TupleElementNamesAttributeMissing, "(int e2, int e3)").WithArguments("System.Runtime.CompilerServices.TupleElementNamesAttribute").WithLocation(16, 42), // (16,33): error CS8137: Cannot define a class or member that utilizes tuples because the compiler required type 'System.Runtime.CompilerServices.TupleElementNamesAttribute' cannot be found. Are you missing a reference? // public class Derived<T> : Outer<(int e1, (int e2, int e3) e4)>.Inner< Diagnostic(ErrorCode.ERR_TupleElementNamesAttributeMissing, "(int e1, (int e2, int e3) e4)").WithArguments("System.Runtime.CompilerServices.TupleElementNamesAttribute").WithLocation(16, 33), // (17,11): error CS8137: Cannot define a class or member that utilizes tuples because the compiler required type 'System.Runtime.CompilerServices.TupleElementNamesAttribute' cannot be found. Are you missing a reference? // Outer<(int e5, int e6)>.Inner<(int e7, int e8)[], (int e9, int e10)>.InnerInner<int>[], Diagnostic(ErrorCode.ERR_TupleElementNamesAttributeMissing, "(int e5, int e6)").WithArguments("System.Runtime.CompilerServices.TupleElementNamesAttribute").WithLocation(17, 11), // (17,35): error CS8137: Cannot define a class or member that utilizes tuples because the compiler required type 'System.Runtime.CompilerServices.TupleElementNamesAttribute' cannot be found. Are you missing a reference? // Outer<(int e5, int e6)>.Inner<(int e7, int e8)[], (int e9, int e10)>.InnerInner<int>[], Diagnostic(ErrorCode.ERR_TupleElementNamesAttributeMissing, "(int e7, int e8)").WithArguments("System.Runtime.CompilerServices.TupleElementNamesAttribute").WithLocation(17, 35), // (17,55): error CS8137: Cannot define a class or member that utilizes tuples because the compiler required type 'System.Runtime.CompilerServices.TupleElementNamesAttribute' cannot be found. Are you missing a reference? // Outer<(int e5, int e6)>.Inner<(int e7, int e8)[], (int e9, int e10)>.InnerInner<int>[], Diagnostic(ErrorCode.ERR_TupleElementNamesAttributeMissing, "(int e9, int e10)").WithArguments("System.Runtime.CompilerServices.TupleElementNamesAttribute").WithLocation(17, 55), // (18,6): error CS8137: Cannot define a class or member that utilizes tuples because the compiler required type 'System.Runtime.CompilerServices.TupleElementNamesAttribute' cannot be found. Are you missing a reference? // ((int e11, int e12) e13, int e14)> Diagnostic(ErrorCode.ERR_TupleElementNamesAttributeMissing, "(int e11, int e12)").WithArguments("System.Runtime.CompilerServices.TupleElementNamesAttribute").WithLocation(18, 6), // (18,5): error CS8137: Cannot define a class or member that utilizes tuples because the compiler required type 'System.Runtime.CompilerServices.TupleElementNamesAttribute' cannot be found. Are you missing a reference? // ((int e11, int e12) e13, int e14)> Diagnostic(ErrorCode.ERR_TupleElementNamesAttributeMissing, "((int e11, int e12) e13, int e14)").WithArguments("System.Runtime.CompilerServices.TupleElementNamesAttribute").WithLocation(18, 5), // (19,18): error CS8137: Cannot define a class or member that utilizes tuples because the compiler required type 'System.Runtime.CompilerServices.TupleElementNamesAttribute' cannot be found. Are you missing a reference? // .InnerInner<((int e15, int e16) e17, (int e18, Base1<(int e19, int e20)> e21) e22)> Diagnostic(ErrorCode.ERR_TupleElementNamesAttributeMissing, "(int e15, int e16)").WithArguments("System.Runtime.CompilerServices.TupleElementNamesAttribute").WithLocation(19, 18), // (19,58): error CS8137: Cannot define a class or member that utilizes tuples because the compiler required type 'System.Runtime.CompilerServices.TupleElementNamesAttribute' cannot be found. Are you missing a reference? // .InnerInner<((int e15, int e16) e17, (int e18, Base1<(int e19, int e20)> e21) e22)> Diagnostic(ErrorCode.ERR_TupleElementNamesAttributeMissing, "(int e19, int e20)").WithArguments("System.Runtime.CompilerServices.TupleElementNamesAttribute").WithLocation(19, 58), // (19,42): error CS8137: Cannot define a class or member that utilizes tuples because the compiler required type 'System.Runtime.CompilerServices.TupleElementNamesAttribute' cannot be found. Are you missing a reference? // .InnerInner<((int e15, int e16) e17, (int e18, Base1<(int e19, int e20)> e21) e22)> Diagnostic(ErrorCode.ERR_TupleElementNamesAttributeMissing, "(int e18, Base1<(int e19, int e20)> e21)").WithArguments("System.Runtime.CompilerServices.TupleElementNamesAttribute").WithLocation(19, 42), // (19,17): error CS8137: Cannot define a class or member that utilizes tuples because the compiler required type 'System.Runtime.CompilerServices.TupleElementNamesAttribute' cannot be found. Are you missing a reference? // .InnerInner<((int e15, int e16) e17, (int e18, Base1<(int e19, int e20)> e21) e22)> Diagnostic(ErrorCode.ERR_TupleElementNamesAttributeMissing, "((int e15, int e16) e17, (int e18, Base1<(int e19, int e20)> e21) e22)").WithArguments("System.Runtime.CompilerServices.TupleElementNamesAttribute").WithLocation(19, 17), // (10,38): error CS8137: Cannot define a class or member that utilizes tuples because the compiler required type 'System.Runtime.CompilerServices.TupleElementNamesAttribute' cannot be found. Are you missing a reference? // public class Inner<U, V> : Base2<(int key2, int val2), V> Diagnostic(ErrorCode.ERR_TupleElementNamesAttributeMissing, "(int key2, int val2)").WithArguments("System.Runtime.CompilerServices.TupleElementNamesAttribute").WithLocation(10, 38), // (12,44): error CS8137: Cannot define a class or member that utilizes tuples because the compiler required type 'System.Runtime.CompilerServices.TupleElementNamesAttribute' cannot be found. Are you missing a reference? // public class InnerInner<W> : Base1<(int key3, int val3)> { } Diagnostic(ErrorCode.ERR_TupleElementNamesAttributeMissing, "(int key3, int val3)").WithArguments("System.Runtime.CompilerServices.TupleElementNamesAttribute").WithLocation(12, 44), // (72,47): error CS8137: Cannot define a class or member that utilizes tuples because the compiler required type 'System.Runtime.CompilerServices.TupleElementNamesAttribute' cannot be found. Are you missing a reference? // ValueTuple<(dynamic e2, dynamic e3)> e4)> Event1 Diagnostic(ErrorCode.ERR_TupleElementNamesAttributeMissing, "(dynamic e2, dynamic e3)").WithArguments("System.Runtime.CompilerServices.TupleElementNamesAttribute").WithLocation(72, 47), // (71,35): error CS8137: Cannot define a class or member that utilizes tuples because the compiler required type 'System.Runtime.CompilerServices.TupleElementNamesAttribute' cannot be found. Are you missing a reference? // public static event Delegate1<(dynamic e1, Diagnostic(ErrorCode.ERR_TupleElementNamesAttributeMissing, @"(dynamic e1, ValueTuple<(dynamic e2, dynamic e3)> e4)").WithArguments("System.Runtime.CompilerServices.TupleElementNamesAttribute").WithLocation(71, 35), // (41,19): error CS8137: Cannot define a class or member that utilizes tuples because the compiler required type 'System.Runtime.CompilerServices.TupleElementNamesAttribute' cannot be found. Are you missing a reference? // public static (int e1, int e2) Method1() => (0, 0); Diagnostic(ErrorCode.ERR_TupleElementNamesAttributeMissing, "(int e1, int e2)").WithArguments("System.Runtime.CompilerServices.TupleElementNamesAttribute").WithLocation(41, 19), // (42,32): error CS8137: Cannot define a class or member that utilizes tuples because the compiler required type 'System.Runtime.CompilerServices.TupleElementNamesAttribute' cannot be found. Are you missing a reference? // public static void Method2((int e1, int e2) x) { } Diagnostic(ErrorCode.ERR_TupleElementNamesAttributeMissing, "(int e1, int e2)").WithArguments("System.Runtime.CompilerServices.TupleElementNamesAttribute").WithLocation(42, 32), // (43,44): error CS8137: Cannot define a class or member that utilizes tuples because the compiler required type 'System.Runtime.CompilerServices.TupleElementNamesAttribute' cannot be found. Are you missing a reference? // public static (int e1, int e2) Method3((int e3, int e4) x) => (0, 0); Diagnostic(ErrorCode.ERR_TupleElementNamesAttributeMissing, "(int e3, int e4)").WithArguments("System.Runtime.CompilerServices.TupleElementNamesAttribute").WithLocation(43, 44), // (43,19): error CS8137: Cannot define a class or member that utilizes tuples because the compiler required type 'System.Runtime.CompilerServices.TupleElementNamesAttribute' cannot be found. Are you missing a reference? // public static (int e1, int e2) Method3((int e3, int e4) x) => (0, 0); Diagnostic(ErrorCode.ERR_TupleElementNamesAttributeMissing, "(int e1, int e2)").WithArguments("System.Runtime.CompilerServices.TupleElementNamesAttribute").WithLocation(43, 19), // (44,48): error CS8137: Cannot define a class or member that utilizes tuples because the compiler required type 'System.Runtime.CompilerServices.TupleElementNamesAttribute' cannot be found. Are you missing a reference? // public static (int e1, int e2) Method4(ref (int e3, int e4) x) => x; Diagnostic(ErrorCode.ERR_TupleElementNamesAttributeMissing, "(int e3, int e4)").WithArguments("System.Runtime.CompilerServices.TupleElementNamesAttribute").WithLocation(44, 48), // (44,19): error CS8137: Cannot define a class or member that utilizes tuples because the compiler required type 'System.Runtime.CompilerServices.TupleElementNamesAttribute' cannot be found. Are you missing a reference? // public static (int e1, int e2) Method4(ref (int e3, int e4) x) => x; Diagnostic(ErrorCode.ERR_TupleElementNamesAttributeMissing, "(int e1, int e2)").WithArguments("System.Runtime.CompilerServices.TupleElementNamesAttribute").WithLocation(44, 19), // (53,19): error CS8137: Cannot define a class or member that utilizes tuples because the compiler required type 'System.Runtime.CompilerServices.TupleElementNamesAttribute' cannot be found. Are you missing a reference? // public static (int e1, int e2, int e3, int e4, int e5, Diagnostic(ErrorCode.ERR_TupleElementNamesAttributeMissing, @"(int e1, int e2, int e3, int e4, int e5, int e6, int e7, int e8, int e9)").WithArguments("System.Runtime.CompilerServices.TupleElementNamesAttribute").WithLocation(53, 19), // (57,19): error CS8137: Cannot define a class or member that utilizes tuples because the compiler required type 'System.Runtime.CompilerServices.TupleElementNamesAttribute' cannot be found. Are you missing a reference? // public static (int e1, int e2) Prop1 => (0, 0); Diagnostic(ErrorCode.ERR_TupleElementNamesAttributeMissing, "(int e1, int e2)").WithArguments("System.Runtime.CompilerServices.TupleElementNamesAttribute").WithLocation(57, 19), // (58,19): error CS8137: Cannot define a class or member that utilizes tuples because the compiler required type 'System.Runtime.CompilerServices.TupleElementNamesAttribute' cannot be found. Are you missing a reference? // public static (int e1, int e2) Prop2 { get; set; } Diagnostic(ErrorCode.ERR_TupleElementNamesAttributeMissing, "(int e1, int e2)").WithArguments("System.Runtime.CompilerServices.TupleElementNamesAttribute").WithLocation(58, 19), // (60,34): error CS8137: Cannot define a class or member that utilizes tuples because the compiler required type 'System.Runtime.CompilerServices.TupleElementNamesAttribute' cannot be found. Are you missing a reference? // public (int e1, int e2) this[(int e3, int e4) param] Diagnostic(ErrorCode.ERR_TupleElementNamesAttributeMissing, "(int e3, int e4)").WithArguments("System.Runtime.CompilerServices.TupleElementNamesAttribute").WithLocation(60, 34), // (60,12): error CS8137: Cannot define a class or member that utilizes tuples because the compiler required type 'System.Runtime.CompilerServices.TupleElementNamesAttribute' cannot be found. Are you missing a reference? // public (int e1, int e2) this[(int e3, int e4) param] Diagnostic(ErrorCode.ERR_TupleElementNamesAttributeMissing, "(int e1, int e2)").WithArguments("System.Runtime.CompilerServices.TupleElementNamesAttribute").WithLocation(60, 12), // (68,14): error CS8137: Cannot define a class or member that utilizes tuples because the compiler required type 'System.Runtime.CompilerServices.TupleElementNamesAttribute' cannot be found. Are you missing a reference? // ((dynamic e1, dynamic e2, object e3) e4, dynamic e5), Diagnostic(ErrorCode.ERR_TupleElementNamesAttributeMissing, "(dynamic e1, dynamic e2, object e3)").WithArguments("System.Runtime.CompilerServices.TupleElementNamesAttribute").WithLocation(68, 14), // (68,13): error CS8137: Cannot define a class or member that utilizes tuples because the compiler required type 'System.Runtime.CompilerServices.TupleElementNamesAttribute' cannot be found. Are you missing a reference? // ((dynamic e1, dynamic e2, object e3) e4, dynamic e5), Diagnostic(ErrorCode.ERR_TupleElementNamesAttributeMissing, "((dynamic e1, dynamic e2, object e3) e4, dynamic e5)").WithArguments("System.Runtime.CompilerServices.TupleElementNamesAttribute").WithLocation(68, 13), // (22,19): error CS8137: Cannot define a class or member that utilizes tuples because the compiler required type 'System.Runtime.CompilerServices.TupleElementNamesAttribute' cannot be found. Are you missing a reference? // public static (int e1, int e2) Field2; Diagnostic(ErrorCode.ERR_TupleElementNamesAttributeMissing, "(int e1, int e2)").WithArguments("System.Runtime.CompilerServices.TupleElementNamesAttribute").WithLocation(22, 19), // (23,34): error CS8137: Cannot define a class or member that utilizes tuples because the compiler required type 'System.Runtime.CompilerServices.TupleElementNamesAttribute' cannot be found. Are you missing a reference? // public static Base1<(int e1, (int e2, int e3) e4)> Field3; Diagnostic(ErrorCode.ERR_TupleElementNamesAttributeMissing, "(int e2, int e3)").WithArguments("System.Runtime.CompilerServices.TupleElementNamesAttribute").WithLocation(23, 34), // (23,25): error CS8137: Cannot define a class or member that utilizes tuples because the compiler required type 'System.Runtime.CompilerServices.TupleElementNamesAttribute' cannot be found. Are you missing a reference? // public static Base1<(int e1, (int e2, int e3) e4)> Field3; Diagnostic(ErrorCode.ERR_TupleElementNamesAttributeMissing, "(int e1, (int e2, int e3) e4)").WithArguments("System.Runtime.CompilerServices.TupleElementNamesAttribute").WithLocation(23, 25), // (25,36): error CS8137: Cannot define a class or member that utilizes tuples because the compiler required type 'System.Runtime.CompilerServices.TupleElementNamesAttribute' cannot be found. Are you missing a reference? // public static ValueTuple<Base1<(int e1, (int, (dynamic, dynamic)) e2)>, int> Field4; Diagnostic(ErrorCode.ERR_TupleElementNamesAttributeMissing, "(int e1, (int, (dynamic, dynamic)) e2)").WithArguments("System.Runtime.CompilerServices.TupleElementNamesAttribute").WithLocation(25, 36), // (27,25): error CS8137: Cannot define a class or member that utilizes tuples because the compiler required type 'System.Runtime.CompilerServices.TupleElementNamesAttribute' cannot be found. Are you missing a reference? // public static Outer<(object e1, dynamic e2)> Diagnostic(ErrorCode.ERR_TupleElementNamesAttributeMissing, "(object e1, dynamic e2)").WithArguments("System.Runtime.CompilerServices.TupleElementNamesAttribute").WithLocation(27, 25), // (28,16): error CS8137: Cannot define a class or member that utilizes tuples because the compiler required type 'System.Runtime.CompilerServices.TupleElementNamesAttribute' cannot be found. Are you missing a reference? // .Inner<(dynamic e3, object e4), Diagnostic(ErrorCode.ERR_TupleElementNamesAttributeMissing, "(dynamic e3, object e4)").WithArguments("System.Runtime.CompilerServices.TupleElementNamesAttribute").WithLocation(28, 16), // (36,19): error CS8137: Cannot define a class or member that utilizes tuples because the compiler required type 'System.Runtime.CompilerServices.TupleElementNamesAttribute' cannot be found. Are you missing a reference? // public static (int e1, int e2, int e3, int e4, int e5, Diagnostic(ErrorCode.ERR_TupleElementNamesAttributeMissing, @"(int e1, int e2, int e3, int e4, int e5, int e6, int e7, int e8, int e9)").WithArguments("System.Runtime.CompilerServices.TupleElementNamesAttribute").WithLocation(36, 19), // (38,25): error CS8137: Cannot define a class or member that utilizes tuples because the compiler required type 'System.Runtime.CompilerServices.TupleElementNamesAttribute' cannot be found. Are you missing a reference? // public static Base1<(int e1, int e2, int e3, int e4, int e5, Diagnostic(ErrorCode.ERR_TupleElementNamesAttributeMissing, @"(int e1, int e2, int e3, int e4, int e5, int e6, int e7, int e8, int e9)").WithArguments("System.Runtime.CompilerServices.TupleElementNamesAttribute").WithLocation(38, 25), // (21,19): error CS8137: Cannot define a class or member that utilizes tuples because the compiler required type 'System.Runtime.CompilerServices.TupleElementNamesAttribute' cannot be found. Are you missing a reference? // public static (int e1, int e2) Field1; Diagnostic(ErrorCode.ERR_TupleElementNamesAttributeMissing, "(int e1, int e2)").WithArguments("System.Runtime.CompilerServices.TupleElementNamesAttribute").WithLocation(21, 19)); } [Fact] public void ExplicitTupleNamesAttribute() { var text = @" using System; using System.Runtime.CompilerServices; [TupleElementNames(new[] { ""a"", ""b"" })] public class C { [TupleElementNames(new string[] { null, null })] public ValueTuple<int, int> Field1; [TupleElementNames(new[] { ""x"", ""y"" })] public ValueTuple<int, int> Prop1; [return: TupleElementNames(new string[] { null, null })] public ValueTuple<int, int> M([TupleElementNames(new string[] { null})] ValueTuple x) => (0, 0); public delegate void Delegate1<T>(object sender, [TupleElementNames(new[] { ""x"" })]ValueTuple<T> args); [TupleElementNames(new[] { ""y"" })] public event Delegate1<ValueTuple<int>> Event1 { add { } remove { } } [TupleElementNames(new[] { ""a"", ""b"" })] public (int x, int y) this[[TupleElementNames](int a, int b) t] => t; } [TupleElementNames(new[] { ""a"", ""b"" })] public struct S { }"; var comp = CreateCompilationWithMscorlib40(text, references: s_attributeRefs); comp.VerifyDiagnostics( // (5,2): error CS8138: Cannot reference 'System.Runtime.CompilerServices.TupleElementNamesAttribute' explicitly. Use the tuple syntax to define tuple names. // [TupleElementNames(new[] { "a", "b" })] Diagnostic(ErrorCode.ERR_ExplicitTupleElementNamesAttribute, @"TupleElementNames(new[] { ""a"", ""b"" })").WithLocation(5, 2), // (31,2): error CS8138: Cannot reference 'System.Runtime.CompilerServices.TupleElementNamesAttribute' explicitly. Use the tuple syntax to define tuple names. // [TupleElementNames(new[] { "a", "b" })] Diagnostic(ErrorCode.ERR_ExplicitTupleElementNamesAttribute, @"TupleElementNames(new[] { ""a"", ""b"" })").WithLocation(31, 2), // (18,10): error CS8138: Cannot reference 'System.Runtime.CompilerServices.TupleElementNamesAttribute' explicitly. Use the tuple syntax to define tuple names. // [TupleElementNames(new[] { "x" })]ValueTuple<T> args); Diagnostic(ErrorCode.ERR_ExplicitTupleElementNamesAttribute, @"TupleElementNames(new[] { ""x"" })").WithLocation(18, 10), // (11,6): error CS8138: Cannot reference 'System.Runtime.CompilerServices.TupleElementNamesAttribute' explicitly. Use the tuple syntax to define tuple names. // [TupleElementNames(new[] { "x", "y" })] Diagnostic(ErrorCode.ERR_ExplicitTupleElementNamesAttribute, @"TupleElementNames(new[] { ""x"", ""y"" })").WithLocation(11, 6), // (14,14): error CS8138: Cannot reference 'System.Runtime.CompilerServices.TupleElementNamesAttribute' explicitly. Use the tuple syntax to define tuple names. // [return: TupleElementNames(new string[] { null, null })] Diagnostic(ErrorCode.ERR_ExplicitTupleElementNamesAttribute, "TupleElementNames(new string[] { null, null })").WithLocation(14, 14), // (15,36): error CS8138: Cannot reference 'System.Runtime.CompilerServices.TupleElementNamesAttribute' explicitly. Use the tuple syntax to define tuple names. // public ValueTuple<int, int> M([TupleElementNames(new string[] { null})] ValueTuple x) => (0, 0); Diagnostic(ErrorCode.ERR_ExplicitTupleElementNamesAttribute, "TupleElementNames(new string[] { null})").WithLocation(15, 36), // (20,6): error CS8138: Cannot reference 'System.Runtime.CompilerServices.TupleElementNamesAttribute' explicitly. Use the tuple syntax to define tuple names. // [TupleElementNames(new[] { "y" })] Diagnostic(ErrorCode.ERR_ExplicitTupleElementNamesAttribute, @"TupleElementNames(new[] { ""y"" })").WithLocation(20, 6), // (27,6): error CS8138: Cannot reference 'System.Runtime.CompilerServices.TupleElementNamesAttribute' explicitly. Use the tuple syntax to define tuple names. // [TupleElementNames(new[] { "a", "b" })] Diagnostic(ErrorCode.ERR_ExplicitTupleElementNamesAttribute, @"TupleElementNames(new[] { ""a"", ""b"" })").WithLocation(27, 6), // (28,33): error CS7036: There is no argument given that corresponds to the required parameter 'transformNames' of 'TupleElementNamesAttribute.TupleElementNamesAttribute(string[])' // public (int x, int y) this[[TupleElementNames](int a, int b) t] => t; Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "TupleElementNames").WithArguments("transformNames", "System.Runtime.CompilerServices.TupleElementNamesAttribute.TupleElementNamesAttribute(string[])").WithLocation(28, 33), // (8,6): error CS8138: Cannot reference 'System.Runtime.CompilerServices.TupleElementNamesAttribute' explicitly. Use the tuple syntax to define tuple names. // [TupleElementNames(new string[] { null, null })] Diagnostic(ErrorCode.ERR_ExplicitTupleElementNamesAttribute, "TupleElementNames(new string[] { null, null })").WithLocation(8, 6)); } [Fact] [WorkItem(14844, "https://github.com/dotnet/roslyn/issues/14844")] public void AttributesOnTypeConstraints() { var src = @" public interface I1<T> {} public interface I2<T> where T : I1<(int a, int b)> {} public interface I3<T> where T : I1<(int c, int d)> {}"; Action<PEAssembly> validator = assembly => { var reader = assembly.GetMetadataReader(); Action<TypeDefinition, string[]> verifyTupleConstraint = (def, tupleNames) => { var typeParams = def.GetGenericParameters(); Assert.Equal(1, typeParams.Count); var typeParam = reader.GetGenericParameter(typeParams[0]); var constraintHandles = typeParam.GetConstraints(); Assert.Equal(1, constraintHandles.Count); var constraint = reader.GetGenericParameterConstraint(constraintHandles[0]); var attributes = constraint.GetCustomAttributes(); Assert.Equal(1, attributes.Count); var attr = reader.GetCustomAttribute(attributes.Single()); // Verify that the attribute contains an array of matching tuple names var argsReader = reader.GetBlobReader(attr.Value); // Prolog Assert.Equal(1, argsReader.ReadUInt16()); // Array size Assert.Equal(tupleNames.Length, argsReader.ReadInt32()); foreach (var name in tupleNames) { Assert.Equal(name, argsReader.ReadSerializedString()); } }; foreach (var typeHandle in reader.TypeDefinitions) { var def = reader.GetTypeDefinition(typeHandle); var name = reader.GetString(def.Name); switch (name) { case "I1`1": case "<Module>": continue; case "I2`1": verifyTupleConstraint(def, new[] { "a", "b" }); break; case "I3`1": verifyTupleConstraint(def, new[] { "c", "d" }); break; default: throw TestExceptionUtilities.UnexpectedValue(name); } } }; void symbolValidator(ModuleSymbol m) { foreach (var t in m.GlobalNamespace.GetTypeMembers()) { switch (t.Name) { case "I1": case "<Module>": continue; case "I2": verifyTupleImpls(t, new[] { "a", "b" }); break; case "I3": verifyTupleImpls(t, new[] { "c", "d" }); break; } } void verifyTupleImpls(NamedTypeSymbol t, string[] tupleNames) { var typeParam = t.TypeParameters.Single(); var constraint = (NamedTypeSymbol)typeParam.ConstraintTypes().Single(); var typeArg = constraint.TypeArguments().Single(); Assert.True(typeArg.IsTupleType); Assert.Equal(tupleNames, typeArg.TupleElementNames); } } CompileAndVerifyWithMscorlib40(src, references: new[] { ValueTupleRef, SystemRuntimeFacadeRef }, parseOptions: TestOptions.Regular.WithNoRefSafetyRulesAttribute(), assemblyValidator: validator, symbolValidator: symbolValidator); } [Fact] [WorkItem(14844, "https://github.com/dotnet/roslyn/issues/14844")] public void AttributesOnInterfaceImplementations() { var src = @" public interface I1<T> {} public interface I2 : I1<(int a, int b)> {} public interface I3 : I1<(int c, int d)> {}"; Action<PEAssembly> validator = (assembly) => { var reader = assembly.GetMetadataReader(); Action<TypeDefinition, string[]> verifyTupleImpls = (def, tupleNames) => { var interfaceImpls = def.GetInterfaceImplementations(); Assert.Equal(1, interfaceImpls.Count); var interfaceImpl = reader.GetInterfaceImplementation(interfaceImpls.Single()); var attributes = interfaceImpl.GetCustomAttributes(); Assert.Equal(1, attributes.Count); var attr = reader.GetCustomAttribute(attributes.Single()); // Verify that the attribute contains an array of matching tuple names var argsReader = reader.GetBlobReader(attr.Value); // Prolog Assert.Equal(1, argsReader.ReadUInt16()); // Array size Assert.Equal(tupleNames.Length, argsReader.ReadInt32()); foreach (var name in tupleNames) { Assert.Equal(name, argsReader.ReadSerializedString()); } }; foreach (var typeHandle in reader.TypeDefinitions) { var def = reader.GetTypeDefinition(typeHandle); var name = reader.GetString(def.Name); switch (name) { case "I1`1": case "<Module>": continue; case "I2": verifyTupleImpls(def, new[] { "a", "b" }); break; case "I3": verifyTupleImpls(def, new[] { "c", "d" }); break; default: throw TestExceptionUtilities.UnexpectedValue(name); } } }; void symbolValidator(ModuleSymbol m) { foreach (var t in m.GlobalNamespace.GetTypeMembers()) { switch (t.Name) { case "I1": case "<Module>": continue; case "I2": VerifyTupleImpls(t, new[] { "a", "b" }); break; case "I3": VerifyTupleImpls(t, new[] { "c", "d" }); break; default: throw TestExceptionUtilities.UnexpectedValue(t.Name); } } void VerifyTupleImpls(NamedTypeSymbol t, string[] tupleNames) { var interfaceImpl = t.Interfaces().Single(); var typeArg = interfaceImpl.TypeArguments().Single(); Assert.True(typeArg.IsTupleType); Assert.Equal(tupleNames, typeArg.TupleElementNames); } } CompileAndVerifyWithMscorlib40(src, references: new[] { ValueTupleRef, SystemRuntimeFacadeRef }, parseOptions: TestOptions.Regular.WithNoRefSafetyRulesAttribute(), assemblyValidator: validator, symbolValidator: symbolValidator); } } }